Skip to content

Commit

Permalink
Implement most of the API and a couple of tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nlopes committed Jan 24, 2015
1 parent 8258160 commit 1b96f65
Show file tree
Hide file tree
Showing 27 changed files with 1,990 additions and 233 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.test
23 changes: 23 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Copyright (c) 2015, Norberto Lopes
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Slack API in Go

## Why?
I am currently learning Go and this seemed like a good idea.

## Stability
As with any other piece of software expect bugs. Also, the design isn't finalized yet because I am not happy with how I laid out some things. Especially the websocket stuff. It is functional but very incomplete and buggy.

## Help
Anyone is welcome to contribute. Either open a PR or create an issue.

## License
BSD 2 Clause license
7 changes: 7 additions & 0 deletions TODO.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
- Add more tests!!!
- Add timeouts
- Add examples
- Fix the Websocket mess
- Implement Upload File
- Add support to have markdown hints
- See section Message Formatting at https://api.slack.com/docs/formatting
61 changes: 0 additions & 61 deletions channel.go

This file was deleted.

256 changes: 256 additions & 0 deletions channels.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
package slack

import (
"errors"
"net/url"
"strconv"
)

type channelResponseFull struct {
Channel Channel `json:"channel"`
Channels []Channel `json:"channels"`
Purpose string `json:"purpose"`
Topic string `json:"topic"`
NotInChannel bool `json:"not_in_channel"`
History
SlackResponse
}

type ChannelTopic struct {
Value string `json:"value"`
Creator string `json:"creator"`
LastSet JSONTime `json:"last_set"`
}

type ChannelPurpose struct {
Value string `json:"value"`
Creator string `json:"creator"`
LastSet JSONTime `json:"last_set"`
}

type Channel struct {
Id string `json:"id"`
Name string `json:"name"`
IsChannel bool `json:"is_channel"`
Created JSONTime `json:"created"`
Creator string `json:"creator"`
IsArchived bool `json:"is_archived"`
IsGeneral bool `json:"is_general"`
IsGroup bool `json:"is_group"`
Members []string `json:"members"`
Topic ChannelTopic `json:"topic"`
Purpose ChannelPurpose `json:"purpose"`
IsMember bool `json:"is_member"`
LastRead string `json:"last_read,omitempty"`
Latest Message `json:"latest,omitempty"`
UnreadCount int `json:"unread_count,omitempty"`
NumMembers int `json:"num_members,omitempty"`
}

func channelRequest(path string, values url.Values, debug bool) (*channelResponseFull, error) {
response := &channelResponseFull{}
err := ParseResponse(path, values, response, debug)
if err != nil {
return nil, err
}
if !response.Ok {
return nil, errors.New(response.Error)
}
return response, nil
}

func (api *Slack) ArchiveChannel(channelId string) error {
values := url.Values{
"token": {api.config.token},
"channel": {channelId},
}
_, err := channelRequest("channels.archive", values, api.debug)
if err != nil {
return err
}
return nil
}

func (api *Slack) UnarchiveChannel(channelId string) error {
values := url.Values{
"token": {api.config.token},
"channel": {channelId},
}
_, err := channelRequest("channels.unarchive", values, api.debug)
if err != nil {
return err
}
return nil
}

func (api *Slack) CreateChannel(channel string) (*Channel, error) {
values := url.Values{
"token": {api.config.token},
"name": {channel},
}
response, err := channelRequest("channels.create", values, api.debug)
if err != nil {
return nil, err
}
return &response.Channel, nil
}

func (api *Slack) GetChannelHistory(channelId string, params HistoryParameters) (*History, error) {
values := url.Values{
"token": {api.config.token},
"channel": {channelId},
}
if params.Latest != DEFAULT_HISTORY_LATEST {
values.Add("latest", params.Latest)
}
if params.Oldest != DEFAULT_HISTORY_OLDEST {
values.Add("oldest", params.Oldest)
}
if params.Count != DEFAULT_HISTORY_COUNT {
values.Add("count", strconv.Itoa(params.Count))
}
response, err := channelRequest("channels.history", values, api.debug)
if err != nil {
return nil, err
}
channelHistory := response.History
return &channelHistory, nil
}

func (api *Slack) GetChannelInfo(channelId string) (*Channel, error) {
values := url.Values{
"token": {api.config.token},
"channel": {channelId},
}
response, err := channelRequest("channels.info", values, api.debug)
if err != nil {
return nil, err
}
return &response.Channel, nil
}

func (api *Slack) InviteUserToChannel(channelId, userId string) (*Channel, error) {
values := url.Values{
"token": {api.config.token},
"channel": {channelId},
"user": {userId},
}
response, err := channelRequest("channels.invite", values, api.debug)
if err != nil {
return nil, err
}
return &response.Channel, nil
}

func (api *Slack) JoinChannel(channel string) (*Channel, error) {
values := url.Values{
"token": {api.config.token},
"name": {channel},
}
response, err := channelRequest("channels.join", values, api.debug)
if err != nil {
return nil, err
}
return &response.Channel, nil
}

func (api *Slack) LeaveChannel(channelId string) (bool, error) {
values := url.Values{
"token": {api.config.token},
"channel": {channelId},
}
response, err := channelRequest("channels.leave", values, api.debug)
if err != nil {
return false, err
}
if response.NotInChannel {
return response.NotInChannel, nil
}
return false, nil
}

func (api *Slack) KickUserFromChannel(channelId, userId string) error {
values := url.Values{
"token": {api.config.token},
"channel": {channelId},
"user": {userId},
}
_, err := channelRequest("channels.kick", values, api.debug)
if err != nil {
return err
}
return nil
}

func (api *Slack) GetChannels(excludeArchived bool) ([]Channel, error) {
values := url.Values{
"token": {api.config.token},
}
if excludeArchived {
values.Add("exclude_archived", "1")
}
response, err := channelRequest("channels.list", values, api.debug)
if err != nil {
return nil, err
}
return response.Channels, nil
}

/* Clients should try to avoid making this call too often. When needing to mark a read position, a client should set a
timer before making the call. In this way, any further updates needed during the timeout will not generate extra calls
(just one per channel). This is useful for when reading scroll-back history, or following a busy live channel. A
timeout of 5 seconds is a good starting point. Be sure to flush these calls on shutdown/logout. */
func (api *Slack) SetChannelReadMark(channelId, ts string) error {
values := url.Values{
"token": {api.config.token},
"channel": {channelId},
"ts": {ts},
}
_, err := channelRequest("channels.mark", values, api.debug)
if err != nil {
return err
}
return nil
}

func (api *Slack) RenameChannel(channelId, name string) (*Channel, error) {
values := url.Values{
"token": {api.config.token},
"channel": {channelId},
"name": {name},
}
// XXX: the created entry in this call returns a string instead of a number
// so I may have to do some workaround to solve it.
response, err := channelRequest("channels.rename", values, api.debug)
if err != nil {
return nil, err
}
return &response.Channel, nil

}

func (api *Slack) SetChannelPurpose(channelId, purpose string) (string, error) {
values := url.Values{
"token": {api.config.token},
"channel": {channelId},
"purpose": {purpose},
}
response, err := channelRequest("channels.setPurpose", values, api.debug)
if err != nil {
return "", err
}
return response.Purpose, nil
}

func (api *Slack) SetChannelTopic(channelId, topic string) (string, error) {
values := url.Values{
"token": {api.config.token},
"channel": {channelId},
"topic": {topic},
}
response, err := channelRequest("channels.setTopic", values, api.debug)
if err != nil {
return "", err
}
return response.Topic, nil
}
Loading

0 comments on commit 1b96f65

Please sign in to comment.