From be898b44c3c057c7b70efb83f66b7bbbdd5e9276 Mon Sep 17 00:00:00 2001 From: Wim Date: Mon, 8 Jan 2018 22:41:38 +0100 Subject: [PATCH] Update vendor (slack) --- .../matterbridge/slack/websocket_utils.go | 20 --- .../{matterbridge => nlopes}/slack/LICENSE | 0 .../{matterbridge => nlopes}/slack/admin.go | 0 .../slack/attachments.go | 4 + .../{matterbridge => nlopes}/slack/backoff.go | 0 .../{matterbridge => nlopes}/slack/bots.go | 0 .../slack/channels.go | 162 ++++++++++-------- .../{matterbridge => nlopes}/slack/chat.go | 62 ++++++- .../{matterbridge => nlopes}/slack/comment.go | 0 .../slack/conversation.go | 0 .../{matterbridge => nlopes}/slack/dnd.go | 0 .../{matterbridge => nlopes}/slack/emoji.go | 0 .../slack/examples/channels/channels.go | 21 +++ .../nlopes/slack/examples/files/files.go | 30 ++++ .../nlopes/slack/examples/groups/groups.go | 22 +++ .../nlopes/slack/examples/ims/ims.go | 21 +++ .../slack/examples/messages/messages.go | 32 ++++ .../nlopes/slack/examples/pins/pins.go | 123 +++++++++++++ .../slack/examples/reactions/reactions.go | 126 ++++++++++++++ .../nlopes/slack/examples/stars/stars.go | 46 +++++ .../nlopes/slack/examples/team/team.go | 25 +++ .../nlopes/slack/examples/users/users.go | 17 ++ .../slack/examples/websocket/websocket.go | 54 ++++++ .../{matterbridge => nlopes}/slack/files.go | 5 +- .../{matterbridge => nlopes}/slack/groups.go | 15 +- .../{matterbridge => nlopes}/slack/history.go | 0 .../{matterbridge => nlopes}/slack/im.go | 0 .../{matterbridge => nlopes}/slack/info.go | 0 .../{matterbridge => nlopes}/slack/item.go | 0 .../slack/messageID.go | 0 .../slack/messages.go | 9 +- .../{matterbridge => nlopes}/slack/misc.go | 36 +++- .../{matterbridge => nlopes}/slack/oauth.go | 0 .../slack/pagination.go | 0 .../{matterbridge => nlopes}/slack/pins.go | 0 .../slack/reactions.go | 0 .../{matterbridge => nlopes}/slack/rtm.go | 23 +-- .../{matterbridge => nlopes}/slack/search.go | 0 .../{matterbridge => nlopes}/slack/slack.go | 28 ++- .../{matterbridge => nlopes}/slack/stars.go | 0 .../{matterbridge => nlopes}/slack/team.go | 0 .../slack/usergroups.go | 0 .../{matterbridge => nlopes}/slack/users.go | 9 +- .../slack/websocket.go | 6 + .../slack/websocket_channels.go | 0 .../slack/websocket_dm.go | 0 .../slack/websocket_dnd.go | 0 .../slack/websocket_files.go | 0 .../slack/websocket_groups.go | 0 .../slack/websocket_internals.go | 0 .../slack/websocket_managed_conn.go | 17 +- .../slack/websocket_misc.go | 0 .../slack/websocket_pins.go | 0 .../slack/websocket_proxy.go | 3 +- .../slack/websocket_reactions.go | 0 .../slack/websocket_stars.go | 0 .../slack/websocket_teams.go | 0 vendor/manifest | 20 +-- 58 files changed, 769 insertions(+), 167 deletions(-) delete mode 100644 vendor/github.com/matterbridge/slack/websocket_utils.go rename vendor/github.com/{matterbridge => nlopes}/slack/LICENSE (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/admin.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/attachments.go (96%) rename vendor/github.com/{matterbridge => nlopes}/slack/backoff.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/bots.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/channels.go (69%) rename vendor/github.com/{matterbridge => nlopes}/slack/chat.go (84%) rename vendor/github.com/{matterbridge => nlopes}/slack/comment.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/conversation.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/dnd.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/emoji.go (100%) create mode 100644 vendor/github.com/nlopes/slack/examples/channels/channels.go create mode 100644 vendor/github.com/nlopes/slack/examples/files/files.go create mode 100644 vendor/github.com/nlopes/slack/examples/groups/groups.go create mode 100644 vendor/github.com/nlopes/slack/examples/ims/ims.go create mode 100644 vendor/github.com/nlopes/slack/examples/messages/messages.go create mode 100644 vendor/github.com/nlopes/slack/examples/pins/pins.go create mode 100644 vendor/github.com/nlopes/slack/examples/reactions/reactions.go create mode 100644 vendor/github.com/nlopes/slack/examples/stars/stars.go create mode 100644 vendor/github.com/nlopes/slack/examples/team/team.go create mode 100644 vendor/github.com/nlopes/slack/examples/users/users.go create mode 100644 vendor/github.com/nlopes/slack/examples/websocket/websocket.go rename vendor/github.com/{matterbridge => nlopes}/slack/files.go (99%) rename vendor/github.com/{matterbridge => nlopes}/slack/groups.go (98%) rename vendor/github.com/{matterbridge => nlopes}/slack/history.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/im.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/info.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/item.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/messageID.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/messages.go (95%) rename vendor/github.com/{matterbridge => nlopes}/slack/misc.go (85%) rename vendor/github.com/{matterbridge => nlopes}/slack/oauth.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/pagination.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/pins.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/reactions.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/rtm.go (78%) rename vendor/github.com/{matterbridge => nlopes}/slack/search.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/slack.go (77%) rename vendor/github.com/{matterbridge => nlopes}/slack/stars.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/team.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/usergroups.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/users.go (98%) rename vendor/github.com/{matterbridge => nlopes}/slack/websocket.go (90%) rename vendor/github.com/{matterbridge => nlopes}/slack/websocket_channels.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/websocket_dm.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/websocket_dnd.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/websocket_files.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/websocket_groups.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/websocket_internals.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/websocket_managed_conn.go (96%) rename vendor/github.com/{matterbridge => nlopes}/slack/websocket_misc.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/websocket_pins.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/websocket_proxy.go (95%) rename vendor/github.com/{matterbridge => nlopes}/slack/websocket_reactions.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/websocket_stars.go (100%) rename vendor/github.com/{matterbridge => nlopes}/slack/websocket_teams.go (100%) diff --git a/vendor/github.com/matterbridge/slack/websocket_utils.go b/vendor/github.com/matterbridge/slack/websocket_utils.go deleted file mode 100644 index b3d0ec89..00000000 --- a/vendor/github.com/matterbridge/slack/websocket_utils.go +++ /dev/null @@ -1,20 +0,0 @@ -package slack - -import ( - "net" - "net/url" -) - -var portMapping = map[string]string{"ws": "80", "wss": "443"} - -func websocketizeURLPort(orig string) (string, error) { - urlObj, err := url.ParseRequestURI(orig) - if err != nil { - return "", err - } - _, _, err = net.SplitHostPort(urlObj.Host) - if err != nil { - return urlObj.Scheme + "://" + urlObj.Host + ":" + portMapping[urlObj.Scheme] + urlObj.Path, nil - } - return orig, nil -} diff --git a/vendor/github.com/matterbridge/slack/LICENSE b/vendor/github.com/nlopes/slack/LICENSE similarity index 100% rename from vendor/github.com/matterbridge/slack/LICENSE rename to vendor/github.com/nlopes/slack/LICENSE diff --git a/vendor/github.com/matterbridge/slack/admin.go b/vendor/github.com/nlopes/slack/admin.go similarity index 100% rename from vendor/github.com/matterbridge/slack/admin.go rename to vendor/github.com/nlopes/slack/admin.go diff --git a/vendor/github.com/matterbridge/slack/attachments.go b/vendor/github.com/nlopes/slack/attachments.go similarity index 96% rename from vendor/github.com/matterbridge/slack/attachments.go rename to vendor/github.com/nlopes/slack/attachments.go index c5a66d96..abc94e73 100644 --- a/vendor/github.com/matterbridge/slack/attachments.go +++ b/vendor/github.com/nlopes/slack/attachments.go @@ -25,6 +25,7 @@ type AttachmentAction struct { SelectedOptions []AttachmentActionOption `json:"selected_options,omitempty"` // Optional. The first element of this array will be set as the pre-selected option for this menu. OptionGroups []AttachmentActionOptionGroup `json:"option_groups,omitempty"` // Optional. Confirm *ConfirmationField `json:"confirm,omitempty"` // Optional. + URL string `json:"url,omitempty"` // Optional. } // AttachmentActionOption the individual option to appear in action menu. @@ -48,6 +49,9 @@ type AttachmentActionCallback struct { Channel Channel `json:"channel"` User User `json:"user"` + Name string `json:"name"` + Value string `json:"value"` + OriginalMessage Message `json:"original_message"` ActionTs string `json:"action_ts"` diff --git a/vendor/github.com/matterbridge/slack/backoff.go b/vendor/github.com/nlopes/slack/backoff.go similarity index 100% rename from vendor/github.com/matterbridge/slack/backoff.go rename to vendor/github.com/nlopes/slack/backoff.go diff --git a/vendor/github.com/matterbridge/slack/bots.go b/vendor/github.com/nlopes/slack/bots.go similarity index 100% rename from vendor/github.com/matterbridge/slack/bots.go rename to vendor/github.com/nlopes/slack/bots.go diff --git a/vendor/github.com/matterbridge/slack/channels.go b/vendor/github.com/nlopes/slack/channels.go similarity index 69% rename from vendor/github.com/matterbridge/slack/channels.go rename to vendor/github.com/nlopes/slack/channels.go index 4a67b2fb..9490bc70 100644 --- a/vendor/github.com/matterbridge/slack/channels.go +++ b/vendor/github.com/nlopes/slack/channels.go @@ -38,51 +38,51 @@ func channelRequest(ctx context.Context, path string, values url.Values, debug b } // ArchiveChannel archives the given channel -func (api *Client) ArchiveChannel(channel string) error { - return api.ArchiveChannelContext(context.Background(), channel) +// see https://api.slack.com/methods/channels.archive +func (api *Client) ArchiveChannel(channelID string) error { + return api.ArchiveChannelContext(context.Background(), channelID) } // ArchiveChannelContext archives the given channel with a custom context -func (api *Client) ArchiveChannelContext(ctx context.Context, channel string) error { +// see https://api.slack.com/methods/channels.archive +func (api *Client) ArchiveChannelContext(ctx context.Context, channelID string) error { values := url.Values{ "token": {api.config.token}, - "channel": {channel}, + "channel": {channelID}, } _, err := channelRequest(ctx, "channels.archive", values, api.debug) - if err != nil { - return err - } - return nil + return err } // UnarchiveChannel unarchives the given channel -func (api *Client) UnarchiveChannel(channel string) error { - return api.UnarchiveChannelContext(context.Background(), channel) +// see https://api.slack.com/methods/channels.unarchive +func (api *Client) UnarchiveChannel(channelID string) error { + return api.UnarchiveChannelContext(context.Background(), channelID) } // UnarchiveChannelContext unarchives the given channel with a custom context -func (api *Client) UnarchiveChannelContext(ctx context.Context, channel string) error { +// see https://api.slack.com/methods/channels.unarchive +func (api *Client) UnarchiveChannelContext(ctx context.Context, channelID string) error { values := url.Values{ "token": {api.config.token}, - "channel": {channel}, + "channel": {channelID}, } _, err := channelRequest(ctx, "channels.unarchive", values, api.debug) - if err != nil { - return err - } - return nil + return err } // CreateChannel creates a channel with the given name and returns a *Channel -func (api *Client) CreateChannel(channel string) (*Channel, error) { - return api.CreateChannelContext(context.Background(), channel) +// see https://api.slack.com/methods/channels.create +func (api *Client) CreateChannel(channelName string) (*Channel, error) { + return api.CreateChannelContext(context.Background(), channelName) } // CreateChannelContext creates a channel with the given name and returns a *Channel with a custom context -func (api *Client) CreateChannelContext(ctx context.Context, channel string) (*Channel, error) { +// see https://api.slack.com/methods/channels.create +func (api *Client) CreateChannelContext(ctx context.Context, channelName string) (*Channel, error) { values := url.Values{ "token": {api.config.token}, - "name": {channel}, + "name": {channelName}, } response, err := channelRequest(ctx, "channels.create", values, api.debug) if err != nil { @@ -92,15 +92,17 @@ func (api *Client) CreateChannelContext(ctx context.Context, channel string) (*C } // GetChannelHistory retrieves the channel history -func (api *Client) GetChannelHistory(channel string, params HistoryParameters) (*History, error) { - return api.GetChannelHistoryContext(context.Background(), channel, params) +// see https://api.slack.com/methods/channels.history +func (api *Client) GetChannelHistory(channelID string, params HistoryParameters) (*History, error) { + return api.GetChannelHistoryContext(context.Background(), channelID, params) } // GetChannelHistoryContext retrieves the channel history with a custom context -func (api *Client) GetChannelHistoryContext(ctx context.Context, channel string, params HistoryParameters) (*History, error) { +// see https://api.slack.com/methods/channels.history +func (api *Client) GetChannelHistoryContext(ctx context.Context, channelID string, params HistoryParameters) (*History, error) { values := url.Values{ "token": {api.config.token}, - "channel": {channel}, + "channel": {channelID}, } if params.Latest != DEFAULT_HISTORY_LATEST { values.Add("latest", params.Latest) @@ -133,15 +135,17 @@ func (api *Client) GetChannelHistoryContext(ctx context.Context, channel string, } // GetChannelInfo retrieves the given channel -func (api *Client) GetChannelInfo(channel string) (*Channel, error) { - return api.GetChannelInfoContext(context.Background(), channel) +// see https://api.slack.com/methods/channels.info +func (api *Client) GetChannelInfo(channelID string) (*Channel, error) { + return api.GetChannelInfoContext(context.Background(), channelID) } // GetChannelInfoContext retrieves the given channel with a custom context -func (api *Client) GetChannelInfoContext(ctx context.Context, channel string) (*Channel, error) { +// see https://api.slack.com/methods/channels.info +func (api *Client) GetChannelInfoContext(ctx context.Context, channelID string) (*Channel, error) { values := url.Values{ "token": {api.config.token}, - "channel": {channel}, + "channel": {channelID}, } response, err := channelRequest(ctx, "channels.info", values, api.debug) if err != nil { @@ -151,15 +155,17 @@ func (api *Client) GetChannelInfoContext(ctx context.Context, channel string) (* } // InviteUserToChannel invites a user to a given channel and returns a *Channel -func (api *Client) InviteUserToChannel(channel, user string) (*Channel, error) { - return api.InviteUserToChannelContext(context.Background(), channel, user) +// see https://api.slack.com/methods/channels.invite +func (api *Client) InviteUserToChannel(channelID, user string) (*Channel, error) { + return api.InviteUserToChannelContext(context.Background(), channelID, user) } // InviteUserToChannelCustom invites a user to a given channel and returns a *Channel with a custom context -func (api *Client) InviteUserToChannelContext(ctx context.Context, channel, user string) (*Channel, error) { +// see https://api.slack.com/methods/channels.invite +func (api *Client) InviteUserToChannelContext(ctx context.Context, channelID, user string) (*Channel, error) { values := url.Values{ "token": {api.config.token}, - "channel": {channel}, + "channel": {channelID}, "user": {user}, } response, err := channelRequest(ctx, "channels.invite", values, api.debug) @@ -170,15 +176,17 @@ func (api *Client) InviteUserToChannelContext(ctx context.Context, channel, user } // JoinChannel joins the currently authenticated user to a channel -func (api *Client) JoinChannel(channel string) (*Channel, error) { - return api.JoinChannelContext(context.Background(), channel) +// see https://api.slack.com/methods/channels.join +func (api *Client) JoinChannel(channelName string) (*Channel, error) { + return api.JoinChannelContext(context.Background(), channelName) } // JoinChannelContext joins the currently authenticated user to a channel with a custom context -func (api *Client) JoinChannelContext(ctx context.Context, channel string) (*Channel, error) { +// see https://api.slack.com/methods/channels.join +func (api *Client) JoinChannelContext(ctx context.Context, channelName string) (*Channel, error) { values := url.Values{ "token": {api.config.token}, - "name": {channel}, + "name": {channelName}, } response, err := channelRequest(ctx, "channels.join", values, api.debug) if err != nil { @@ -188,15 +196,17 @@ func (api *Client) JoinChannelContext(ctx context.Context, channel string) (*Cha } // LeaveChannel makes the authenticated user leave the given channel -func (api *Client) LeaveChannel(channel string) (bool, error) { - return api.LeaveChannelContext(context.Background(), channel) +// see https://api.slack.com/methods/channels.leave +func (api *Client) LeaveChannel(channelID string) (bool, error) { + return api.LeaveChannelContext(context.Background(), channelID) } // LeaveChannelContext makes the authenticated user leave the given channel with a custom context -func (api *Client) LeaveChannelContext(ctx context.Context, channel string) (bool, error) { +// see https://api.slack.com/methods/channels.leave +func (api *Client) LeaveChannelContext(ctx context.Context, channelID string) (bool, error) { values := url.Values{ "token": {api.config.token}, - "channel": {channel}, + "channel": {channelID}, } response, err := channelRequest(ctx, "channels.leave", values, api.debug) if err != nil { @@ -209,30 +219,31 @@ func (api *Client) LeaveChannelContext(ctx context.Context, channel string) (boo } // KickUserFromChannel kicks a user from a given channel -func (api *Client) KickUserFromChannel(channel, user string) error { - return api.KickUserFromChannelContext(context.Background(), channel, user) +// see https://api.slack.com/methods/channels.kick +func (api *Client) KickUserFromChannel(channelID, user string) error { + return api.KickUserFromChannelContext(context.Background(), channelID, user) } // KickUserFromChannelContext kicks a user from a given channel with a custom context -func (api *Client) KickUserFromChannelContext(ctx context.Context, channel, user string) error { +// see https://api.slack.com/methods/channels.kick +func (api *Client) KickUserFromChannelContext(ctx context.Context, channelID, user string) error { values := url.Values{ "token": {api.config.token}, - "channel": {channel}, + "channel": {channelID}, "user": {user}, } _, err := channelRequest(ctx, "channels.kick", values, api.debug) - if err != nil { - return err - } - return nil + return err } // GetChannels retrieves all the channels +// see https://api.slack.com/methods/channels.list func (api *Client) GetChannels(excludeArchived bool) ([]Channel, error) { return api.GetChannelsContext(context.Background(), excludeArchived) } // GetChannelsContext retrieves all the channels with a custom context +// see https://api.slack.com/methods/channels.list func (api *Client) GetChannelsContext(ctx context.Context, excludeArchived bool) ([]Channel, error) { values := url.Values{ "token": {api.config.token}, @@ -252,35 +263,36 @@ func (api *Client) GetChannelsContext(ctx context.Context, excludeArchived bool) // 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 *Client) SetChannelReadMark(channel, ts string) error { - return api.SetChannelReadMarkContext(context.Background(), channel, ts) +// see https://api.slack.com/methods/channels.mark +func (api *Client) SetChannelReadMark(channelID, ts string) error { + return api.SetChannelReadMarkContext(context.Background(), channelID, ts) } // SetChannelReadMarkContext sets the read mark of a given channel to a specific point with a custom context // For more details see SetChannelReadMark documentation -func (api *Client) SetChannelReadMarkContext(ctx context.Context, channel, ts string) error { +// see https://api.slack.com/methods/channels.mark +func (api *Client) SetChannelReadMarkContext(ctx context.Context, channelID, ts string) error { values := url.Values{ "token": {api.config.token}, - "channel": {channel}, + "channel": {channelID}, "ts": {ts}, } _, err := channelRequest(ctx, "channels.mark", values, api.debug) - if err != nil { - return err - } - return nil + return err } // RenameChannel renames a given channel -func (api *Client) RenameChannel(channel, name string) (*Channel, error) { - return api.RenameChannelContext(context.Background(), channel, name) +// see https://api.slack.com/methods/channels.rename +func (api *Client) RenameChannel(channelID, name string) (*Channel, error) { + return api.RenameChannelContext(context.Background(), channelID, name) } // RenameChannelContext renames a given channel with a custom context -func (api *Client) RenameChannelContext(ctx context.Context, channel, name string) (*Channel, error) { +// see https://api.slack.com/methods/channels.rename +func (api *Client) RenameChannelContext(ctx context.Context, channelID, name string) (*Channel, error) { values := url.Values{ "token": {api.config.token}, - "channel": {channel}, + "channel": {channelID}, "name": {name}, } // XXX: the created entry in this call returns a string instead of a number @@ -293,15 +305,17 @@ func (api *Client) RenameChannelContext(ctx context.Context, channel, name strin } // SetChannelPurpose sets the channel purpose and returns the purpose that was successfully set -func (api *Client) SetChannelPurpose(channel, purpose string) (string, error) { - return api.SetChannelPurposeContext(context.Background(), channel, purpose) +// see https://api.slack.com/methods/channels.setPurpose +func (api *Client) SetChannelPurpose(channelID, purpose string) (string, error) { + return api.SetChannelPurposeContext(context.Background(), channelID, purpose) } // SetChannelPurposeContext sets the channel purpose and returns the purpose that was successfully set with a custom context -func (api *Client) SetChannelPurposeContext(ctx context.Context, channel, purpose string) (string, error) { +// see https://api.slack.com/methods/channels.setPurpose +func (api *Client) SetChannelPurposeContext(ctx context.Context, channelID, purpose string) (string, error) { values := url.Values{ "token": {api.config.token}, - "channel": {channel}, + "channel": {channelID}, "purpose": {purpose}, } response, err := channelRequest(ctx, "channels.setPurpose", values, api.debug) @@ -312,15 +326,17 @@ func (api *Client) SetChannelPurposeContext(ctx context.Context, channel, purpos } // SetChannelTopic sets the channel topic and returns the topic that was successfully set -func (api *Client) SetChannelTopic(channel, topic string) (string, error) { - return api.SetChannelTopicContext(context.Background(), channel, topic) +// see https://api.slack.com/methods/channels.setTopic +func (api *Client) SetChannelTopic(channelID, topic string) (string, error) { + return api.SetChannelTopicContext(context.Background(), channelID, topic) } // SetChannelTopicContext sets the channel topic and returns the topic that was successfully set with a custom context -func (api *Client) SetChannelTopicContext(ctx context.Context, channel, topic string) (string, error) { +// see https://api.slack.com/methods/channels.setTopic +func (api *Client) SetChannelTopicContext(ctx context.Context, channelID, topic string) (string, error) { values := url.Values{ "token": {api.config.token}, - "channel": {channel}, + "channel": {channelID}, "topic": {topic}, } response, err := channelRequest(ctx, "channels.setTopic", values, api.debug) @@ -331,15 +347,17 @@ func (api *Client) SetChannelTopicContext(ctx context.Context, channel, topic st } // GetChannelReplies gets an entire thread (a message plus all the messages in reply to it). -func (api *Client) GetChannelReplies(channel, thread_ts string) ([]Message, error) { - return api.GetChannelRepliesContext(context.Background(), channel, thread_ts) +// see https://api.slack.com/methods/channels.replies +func (api *Client) GetChannelReplies(channelID, thread_ts string) ([]Message, error) { + return api.GetChannelRepliesContext(context.Background(), channelID, thread_ts) } // GetChannelRepliesContext gets an entire thread (a message plus all the messages in reply to it) with a custom context -func (api *Client) GetChannelRepliesContext(ctx context.Context, channel, thread_ts string) ([]Message, error) { +// see https://api.slack.com/methods/channels.replies +func (api *Client) GetChannelRepliesContext(ctx context.Context, channelID, thread_ts string) ([]Message, error) { values := url.Values{ "token": {api.config.token}, - "channel": {channel}, + "channel": {channelID}, "thread_ts": {thread_ts}, } response, err := channelRequest(ctx, "channels.replies", values, api.debug) diff --git a/vendor/github.com/matterbridge/slack/chat.go b/vendor/github.com/nlopes/slack/chat.go similarity index 84% rename from vendor/github.com/matterbridge/slack/chat.go rename to vendor/github.com/nlopes/slack/chat.go index 9a2c4453..0eb042df 100644 --- a/vendor/github.com/matterbridge/slack/chat.go +++ b/vendor/github.com/nlopes/slack/chat.go @@ -11,6 +11,7 @@ import ( const ( DEFAULT_MESSAGE_USERNAME = "" DEFAULT_MESSAGE_THREAD_TIMESTAMP = "" + DEFAULT_MESSAGE_REPLY_BROADCAST = false DEFAULT_MESSAGE_ASUSER = false DEFAULT_MESSAGE_PARSE = "" DEFAULT_MESSAGE_LINK_NAMES = 0 @@ -36,6 +37,7 @@ type PostMessageParameters struct { AsUser bool `json:"as_user"` Parse string `json:"parse"` ThreadTimestamp string `json:"thread_ts"` + ReplyBroadcast bool `json:"reply_broadcast"` LinkNames int `json:"link_names"` Attachments []Attachment `json:"attachments"` UnfurlLinks bool `json:"unfurl_links"` @@ -44,12 +46,17 @@ type PostMessageParameters struct { IconEmoji string `json:"icon_emoji"` Markdown bool `json:"mrkdwn,omitempty"` EscapeText bool `json:"escape_text"` + + // chat.postEphemeral support + Channel string `json:"channel"` + User string `json:"user"` } // NewPostMessageParameters provides an instance of PostMessageParameters with all the sane default values set func NewPostMessageParameters() PostMessageParameters { return PostMessageParameters{ Username: DEFAULT_MESSAGE_USERNAME, + User: DEFAULT_MESSAGE_USERNAME, AsUser: DEFAULT_MESSAGE_ASUSER, Parse: DEFAULT_MESSAGE_PARSE, LinkNames: DEFAULT_MESSAGE_LINK_NAMES, @@ -102,6 +109,37 @@ func (api *Client) PostMessageContext(ctx context.Context, channel, text string, return respChannel, respTimestamp, err } +// PostEphemeral sends an ephemeral message to a user in a channel. +// Message is escaped by default according to https://api.slack.com/docs/formatting +// Use http://davestevens.github.io/slack-message-builder/ to help crafting your message. +func (api *Client) PostEphemeral(channel, userID string, options ...MsgOption) (string, error) { + options = append(options, MsgOptionPostEphemeral()) + return api.PostEphemeralContext( + context.Background(), + channel, + userID, + options..., + ) +} + +// PostEphemeralContext sends an ephemeal message to a user in a channel with a custom context +// For more details, see PostEphemeral documentation +func (api *Client) PostEphemeralContext(ctx context.Context, channel, userID string, options ...MsgOption) (string, error) { + path, values, err := ApplyMsgOptions(api.config.token, channel, options...) + if err != nil { + return "", err + } + + values.Add("user", userID) + + response, err := chatRequest(ctx, path, values, api.debug) + if err != nil { + return "", err + } + + return response.Timestamp, nil +} + // UpdateMessage updates a message in a channel func (api *Client) UpdateMessage(channel, timestamp, text string) (string, string, string, error) { return api.UpdateMessageContext(context.Background(), channel, timestamp, text) @@ -171,9 +209,10 @@ func chatRequest(ctx context.Context, path string, values url.Values, debug bool type sendMode string const ( - chatUpdate sendMode = "chat.update" - chatPostMessage sendMode = "chat.postMessage" - chatDelete sendMode = "chat.delete" + chatUpdate sendMode = "chat.update" + chatPostMessage sendMode = "chat.postMessage" + chatDelete sendMode = "chat.delete" + chatPostEphemeral sendMode = "chat.postEphemeral" ) type sendConfig struct { @@ -193,6 +232,15 @@ func MsgOptionPost() MsgOption { } } +// MsgOptionPostEphemeral posts an ephemeral message +func MsgOptionPostEphemeral() MsgOption { + return func(config *sendConfig) error { + config.mode = chatPostEphemeral + config.values.Del("ts") + return nil + } +} + // MsgOptionUpdate updates a message based on the timestamp. func MsgOptionUpdate(timestamp string) MsgOption { return func(config *sendConfig) error { @@ -279,6 +327,11 @@ func MsgOptionPostMessageParameters(params PostMessageParameters) MsgOption { config.values.Set("username", string(params.Username)) } + // chat.postEphemeral support + if params.User != DEFAULT_MESSAGE_USERNAME { + config.values.Set("user", params.User) + } + // never generates an error. MsgOptionAsUser(params.AsUser)(config) @@ -314,6 +367,9 @@ func MsgOptionPostMessageParameters(params PostMessageParameters) MsgOption { if params.ThreadTimestamp != DEFAULT_MESSAGE_THREAD_TIMESTAMP { config.values.Set("thread_ts", params.ThreadTimestamp) } + if params.ReplyBroadcast != DEFAULT_MESSAGE_REPLY_BROADCAST { + config.values.Set("reply_broadcast", "true") + } return nil } diff --git a/vendor/github.com/matterbridge/slack/comment.go b/vendor/github.com/nlopes/slack/comment.go similarity index 100% rename from vendor/github.com/matterbridge/slack/comment.go rename to vendor/github.com/nlopes/slack/comment.go diff --git a/vendor/github.com/matterbridge/slack/conversation.go b/vendor/github.com/nlopes/slack/conversation.go similarity index 100% rename from vendor/github.com/matterbridge/slack/conversation.go rename to vendor/github.com/nlopes/slack/conversation.go diff --git a/vendor/github.com/matterbridge/slack/dnd.go b/vendor/github.com/nlopes/slack/dnd.go similarity index 100% rename from vendor/github.com/matterbridge/slack/dnd.go rename to vendor/github.com/nlopes/slack/dnd.go diff --git a/vendor/github.com/matterbridge/slack/emoji.go b/vendor/github.com/nlopes/slack/emoji.go similarity index 100% rename from vendor/github.com/matterbridge/slack/emoji.go rename to vendor/github.com/nlopes/slack/emoji.go diff --git a/vendor/github.com/nlopes/slack/examples/channels/channels.go b/vendor/github.com/nlopes/slack/examples/channels/channels.go new file mode 100644 index 00000000..37d5f741 --- /dev/null +++ b/vendor/github.com/nlopes/slack/examples/channels/channels.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + + "github.com/nlopes/slack" +) + +func main() { + api := slack.New("YOUR_TOKEN_HERE") + channels, err := api.GetChannels(false) + if err != nil { + fmt.Printf("%s\n", err) + return + } + for _, channel := range channels { + fmt.Println(channel.Name) + // channel is of type conversation & groupConversation + // see all available methods in `conversation.go` + } +} diff --git a/vendor/github.com/nlopes/slack/examples/files/files.go b/vendor/github.com/nlopes/slack/examples/files/files.go new file mode 100644 index 00000000..bb7b4e50 --- /dev/null +++ b/vendor/github.com/nlopes/slack/examples/files/files.go @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + + "github.com/nlopes/slack" +) + +func main() { + api := slack.New("YOUR_TOKEN_HERE") + params := slack.FileUploadParameters{ + Title: "Batman Example", + //Filetype: "txt", + File: "example.txt", + //Content: "Nan Nan Nan Nan Nan Nan Nan Nan Batman", + } + file, err := api.UploadFile(params) + if err != nil { + fmt.Printf("%s\n", err) + return + } + fmt.Printf("Name: %s, URL: %s\n", file.Name, file.URL) + + err = api.DeleteFile(file.ID) + if err != nil { + fmt.Printf("%s\n", err) + return + } + fmt.Printf("File %s deleted successfully.\n", file.Name) +} diff --git a/vendor/github.com/nlopes/slack/examples/groups/groups.go b/vendor/github.com/nlopes/slack/examples/groups/groups.go new file mode 100644 index 00000000..2af215d1 --- /dev/null +++ b/vendor/github.com/nlopes/slack/examples/groups/groups.go @@ -0,0 +1,22 @@ +package main + +import ( + "fmt" + + "github.com/nlopes/slack" +) + +func main() { + api := slack.New("YOUR_TOKEN_HERE") + // If you set debugging, it will log all requests to the console + // Useful when encountering issues + // api.SetDebug(true) + groups, err := api.GetGroups(false) + if err != nil { + fmt.Printf("%s\n", err) + return + } + for _, group := range groups { + fmt.Printf("ID: %s, Name: %s\n", group.ID, group.Name) + } +} diff --git a/vendor/github.com/nlopes/slack/examples/ims/ims.go b/vendor/github.com/nlopes/slack/examples/ims/ims.go new file mode 100644 index 00000000..80d73c0a --- /dev/null +++ b/vendor/github.com/nlopes/slack/examples/ims/ims.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + + "github.com/nlopes/slack" +) + +func main() { + api := slack.New("YOUR_TOKEN_HERE") + + userID := "USER_ID" + + _, _, channelID, err := api.OpenIMChannel(userID) + + if err != nil { + fmt.Printf("%s\n", err) + } + + api.PostMessage(channelID, "Hello World!", slack.PostMessageParameters{}) +} diff --git a/vendor/github.com/nlopes/slack/examples/messages/messages.go b/vendor/github.com/nlopes/slack/examples/messages/messages.go new file mode 100644 index 00000000..b3ea87f3 --- /dev/null +++ b/vendor/github.com/nlopes/slack/examples/messages/messages.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + + "github.com/nlopes/slack" +) + +func main() { + api := slack.New("YOUR_TOKEN_HERE") + params := slack.PostMessageParameters{} + attachment := slack.Attachment{ + Pretext: "some pretext", + Text: "some text", + // Uncomment the following part to send a field too + /* + Fields: []slack.AttachmentField{ + slack.AttachmentField{ + Title: "a", + Value: "no", + }, + }, + */ + } + params.Attachments = []slack.Attachment{attachment} + channelID, timestamp, err := api.PostMessage("CHANNEL_ID", "Some text", params) + if err != nil { + fmt.Printf("%s\n", err) + return + } + fmt.Printf("Message successfully sent to channel %s at %s", channelID, timestamp) +} diff --git a/vendor/github.com/nlopes/slack/examples/pins/pins.go b/vendor/github.com/nlopes/slack/examples/pins/pins.go new file mode 100644 index 00000000..d225184c --- /dev/null +++ b/vendor/github.com/nlopes/slack/examples/pins/pins.go @@ -0,0 +1,123 @@ +package main + +import ( + "flag" + "fmt" + + "github.com/nlopes/slack" +) + +/* + WARNING: This example is destructive in the sense that it create a channel called testpinning +*/ +func main() { + var ( + apiToken string + debug bool + ) + + flag.StringVar(&apiToken, "token", "YOUR_TOKEN_HERE", "Your Slack API Token") + flag.BoolVar(&debug, "debug", false, "Show JSON output") + flag.Parse() + + api := slack.New(apiToken) + if debug { + api.SetDebug(true) + } + + var ( + postAsUserName string + postAsUserID string + postToChannelID string + ) + + // Find the user to post as. + authTest, err := api.AuthTest() + if err != nil { + fmt.Printf("Error getting channels: %s\n", err) + return + } + + channelName := "testpinning" + + // Post as the authenticated user. + postAsUserName = authTest.User + postAsUserID = authTest.UserID + + // Create a temporary channel + channel, err := api.CreateChannel(channelName) + + if err != nil { + // If the channel exists, that means we just need to unarchive it + if err.Error() == "name_taken" { + err = nil + channels, err := api.GetChannels(false) + if err != nil { + fmt.Println("Could not retrieve channels") + return + } + for _, archivedChannel := range channels { + if archivedChannel.Name == channelName { + if archivedChannel.IsArchived { + err = api.UnarchiveChannel(archivedChannel.ID) + if err != nil { + fmt.Printf("Could not unarchive %s: %s\n", archivedChannel.ID, err) + return + } + } + channel = &archivedChannel + break + } + } + } + if err != nil { + fmt.Printf("Error setting test channel for pinning: %s\n", err) + return + } + } + postToChannelID = channel.ID + + fmt.Printf("Posting as %s (%s) in channel %s\n", postAsUserName, postAsUserID, postToChannelID) + + // Post a message. + postParams := slack.PostMessageParameters{} + channelID, timestamp, err := api.PostMessage(postToChannelID, "Is this any good?", postParams) + if err != nil { + fmt.Printf("Error posting message: %s\n", err) + return + } + + // Grab a reference to the message. + msgRef := slack.NewRefToMessage(channelID, timestamp) + + // Add message pin to channel + if err := api.AddPin(channelID, msgRef); err != nil { + fmt.Printf("Error adding pin: %s\n", err) + return + } + + // List all of the users pins. + listPins, _, err := api.ListPins(channelID) + if err != nil { + fmt.Printf("Error listing pins: %s\n", err) + return + } + fmt.Printf("\n") + fmt.Printf("All pins by %s...\n", authTest.User) + for _, item := range listPins { + fmt.Printf(" > Item type: %s\n", item.Type) + } + + // Remove the pin. + err = api.RemovePin(channelID, msgRef) + if err != nil { + fmt.Printf("Error remove pin: %s\n", err) + return + } + + if err = api.ArchiveChannel(channelID); err != nil { + fmt.Printf("Error archiving channel: %s\n", err) + return + } + +} diff --git a/vendor/github.com/nlopes/slack/examples/reactions/reactions.go b/vendor/github.com/nlopes/slack/examples/reactions/reactions.go new file mode 100644 index 00000000..753f0d25 --- /dev/null +++ b/vendor/github.com/nlopes/slack/examples/reactions/reactions.go @@ -0,0 +1,126 @@ +package main + +import ( + "flag" + "fmt" + + "github.com/nlopes/slack" +) + +func main() { + var ( + apiToken string + debug bool + ) + + flag.StringVar(&apiToken, "token", "YOUR_TOKEN_HERE", "Your Slack API Token") + flag.BoolVar(&debug, "debug", false, "Show JSON output") + flag.Parse() + + api := slack.New(apiToken) + if debug { + api.SetDebug(true) + } + + var ( + postAsUserName string + postAsUserID string + postToUserName string + postToUserID string + postToChannelID string + ) + + // Find the user to post as. + authTest, err := api.AuthTest() + if err != nil { + fmt.Printf("Error getting channels: %s\n", err) + return + } + + // Post as the authenticated user. + postAsUserName = authTest.User + postAsUserID = authTest.UserID + + // Posting to DM with self causes a conversation with slackbot. + postToUserName = authTest.User + postToUserID = authTest.UserID + + // Find the channel. + _, _, chanID, err := api.OpenIMChannel(postToUserID) + if err != nil { + fmt.Printf("Error opening IM: %s\n", err) + return + } + postToChannelID = chanID + + fmt.Printf("Posting as %s (%s) in DM with %s (%s), channel %s\n", postAsUserName, postAsUserID, postToUserName, postToUserID, postToChannelID) + + // Post a message. + postParams := slack.PostMessageParameters{} + channelID, timestamp, err := api.PostMessage(postToChannelID, "Is this any good?", postParams) + if err != nil { + fmt.Printf("Error posting message: %s\n", err) + return + } + + // Grab a reference to the message. + msgRef := slack.NewRefToMessage(channelID, timestamp) + + // React with :+1: + if err := api.AddReaction("+1", msgRef); err != nil { + fmt.Printf("Error adding reaction: %s\n", err) + return + } + + // React with :-1: + if err := api.AddReaction("cry", msgRef); err != nil { + fmt.Printf("Error adding reaction: %s\n", err) + return + } + + // Get all reactions on the message. + msgReactions, err := api.GetReactions(msgRef, slack.NewGetReactionsParameters()) + if err != nil { + fmt.Printf("Error getting reactions: %s\n", err) + return + } + fmt.Printf("\n") + fmt.Printf("%d reactions to message...\n", len(msgReactions)) + for _, r := range msgReactions { + fmt.Printf(" %d users say %s\n", r.Count, r.Name) + } + + // List all of the users reactions. + listReactions, _, err := api.ListReactions(slack.NewListReactionsParameters()) + if err != nil { + fmt.Printf("Error listing reactions: %s\n", err) + return + } + fmt.Printf("\n") + fmt.Printf("All reactions by %s...\n", authTest.User) + for _, item := range listReactions { + fmt.Printf("%d on a %s...\n", len(item.Reactions), item.Type) + for _, r := range item.Reactions { + fmt.Printf(" %s (along with %d others)\n", r.Name, r.Count-1) + } + } + + // Remove the :cry: reaction. + err = api.RemoveReaction("cry", msgRef) + if err != nil { + fmt.Printf("Error remove reaction: %s\n", err) + return + } + + // Get all reactions on the message. + msgReactions, err = api.GetReactions(msgRef, slack.NewGetReactionsParameters()) + if err != nil { + fmt.Printf("Error getting reactions: %s\n", err) + return + } + fmt.Printf("\n") + fmt.Printf("%d reactions to message after removing cry...\n", len(msgReactions)) + for _, r := range msgReactions { + fmt.Printf(" %d users say %s\n", r.Count, r.Name) + } +} diff --git a/vendor/github.com/nlopes/slack/examples/stars/stars.go b/vendor/github.com/nlopes/slack/examples/stars/stars.go new file mode 100644 index 00000000..d20c3dcf --- /dev/null +++ b/vendor/github.com/nlopes/slack/examples/stars/stars.go @@ -0,0 +1,46 @@ +package main + +import ( + "flag" + "fmt" + + "github.com/nlopes/slack" +) + +func main() { + var ( + apiToken string + debug bool + ) + + flag.StringVar(&apiToken, "token", "YOUR_TOKEN_HERE", "Your Slack API Token") + flag.BoolVar(&debug, "debug", false, "Show JSON output") + flag.Parse() + + api := slack.New(apiToken) + if debug { + api.SetDebug(true) + } + + // Get all stars for the usr. + params := slack.NewStarsParameters() + starredItems, _, err := api.GetStarred(params) + if err != nil { + fmt.Printf("Error getting stars: %s\n", err) + return + } + for _, s := range starredItems { + var desc string + switch s.Type { + case slack.TYPE_MESSAGE: + desc = s.Message.Text + case slack.TYPE_FILE: + desc = s.File.Name + case slack.TYPE_FILE_COMMENT: + desc = s.File.Name + " - " + s.Comment.Comment + case slack.TYPE_CHANNEL, slack.TYPE_IM, slack.TYPE_GROUP: + desc = s.Channel + } + fmt.Printf("Starred %s: %s\n", s.Type, desc) + } +} diff --git a/vendor/github.com/nlopes/slack/examples/team/team.go b/vendor/github.com/nlopes/slack/examples/team/team.go new file mode 100644 index 00000000..caaf79f6 --- /dev/null +++ b/vendor/github.com/nlopes/slack/examples/team/team.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + + "github.com/nlopes/slack" +) + +func main() { + api := slack.New("YOUR_TOKEN_HERE") + //Example for single user + billingActive, err := api.GetBillableInfo("U023BECGF") + if err != nil { + fmt.Printf("%s\n", err) + return + } + fmt.Printf("ID: U023BECGF, BillingActive: %v\n\n\n", billingActive["U023BECGF"]) + + //Example for team + billingActiveForTeam, _ := api.GetBillableInfoForTeam() + for id, value := range billingActiveForTeam { + fmt.Printf("ID: %v, BillingActive: %v\n", id, value) + } + +} diff --git a/vendor/github.com/nlopes/slack/examples/users/users.go b/vendor/github.com/nlopes/slack/examples/users/users.go new file mode 100644 index 00000000..9a6e1f6f --- /dev/null +++ b/vendor/github.com/nlopes/slack/examples/users/users.go @@ -0,0 +1,17 @@ +package main + +import ( + "fmt" + + "github.com/nlopes/slack" +) + +func main() { + api := slack.New("YOUR_TOKEN_HERE") + user, err := api.GetUserInfo("U023BECGF") + if err != nil { + fmt.Printf("%s\n", err) + return + } + fmt.Printf("ID: %s, Fullname: %s, Email: %s\n", user.ID, user.Profile.RealName, user.Profile.Email) +} diff --git a/vendor/github.com/nlopes/slack/examples/websocket/websocket.go b/vendor/github.com/nlopes/slack/examples/websocket/websocket.go new file mode 100644 index 00000000..c232951a --- /dev/null +++ b/vendor/github.com/nlopes/slack/examples/websocket/websocket.go @@ -0,0 +1,54 @@ +package main + +import ( + "fmt" + "log" + "os" + + "github.com/nlopes/slack" +) + +func main() { + api := slack.New("YOUR TOKEN HERE") + logger := log.New(os.Stdout, "slack-bot: ", log.Lshortfile|log.LstdFlags) + slack.SetLogger(logger) + api.SetDebug(true) + + rtm := api.NewRTM() + go rtm.ManageConnection() + + for msg := range rtm.IncomingEvents { + fmt.Print("Event Received: ") + switch ev := msg.Data.(type) { + case *slack.HelloEvent: + // Ignore hello + + case *slack.ConnectedEvent: + fmt.Println("Infos:", ev.Info) + fmt.Println("Connection counter:", ev.ConnectionCount) + // Replace C2147483705 with your Channel ID + rtm.SendMessage(rtm.NewOutgoingMessage("Hello world", "C2147483705")) + + case *slack.MessageEvent: + fmt.Printf("Message: %v\n", ev) + + case *slack.PresenceChangeEvent: + fmt.Printf("Presence Change: %v\n", ev) + + case *slack.LatencyReport: + fmt.Printf("Current latency: %v\n", ev.Value) + + case *slack.RTMError: + fmt.Printf("Error: %s\n", ev.Error()) + + case *slack.InvalidAuthEvent: + fmt.Printf("Invalid credentials") + return + + default: + + // Ignore other events.. + // fmt.Printf("Unexpected: %v\n", msg.Data) + } + } +} diff --git a/vendor/github.com/matterbridge/slack/files.go b/vendor/github.com/nlopes/slack/files.go similarity index 99% rename from vendor/github.com/matterbridge/slack/files.go rename to vendor/github.com/nlopes/slack/files.go index fc4b7e23..68941422 100644 --- a/vendor/github.com/matterbridge/slack/files.go +++ b/vendor/github.com/nlopes/slack/files.go @@ -267,10 +267,7 @@ func (api *Client) DeleteFileContext(ctx context.Context, fileID string) error { "file": {fileID}, } _, err := fileRequest(ctx, "files.delete", values, api.debug) - if err != nil { - return err - } - return nil + return err } diff --git a/vendor/github.com/matterbridge/slack/groups.go b/vendor/github.com/nlopes/slack/groups.go similarity index 98% rename from vendor/github.com/matterbridge/slack/groups.go rename to vendor/github.com/nlopes/slack/groups.go index 444666dd..d7f39144 100644 --- a/vendor/github.com/matterbridge/slack/groups.go +++ b/vendor/github.com/nlopes/slack/groups.go @@ -208,10 +208,7 @@ func (api *Client) LeaveGroupContext(ctx context.Context, group string) error { "channel": {group}, } _, err := groupRequest(ctx, "groups.leave", values, api.debug) - if err != nil { - return err - } - return nil + return err } // KickUserFromGroup kicks a user from a group @@ -227,10 +224,7 @@ func (api *Client) KickUserFromGroupContext(ctx context.Context, group, user str "user": {user}, } _, err := groupRequest(ctx, "groups.kick", values, api.debug) - if err != nil { - return err - } - return nil + return err } // GetGroups retrieves all groups @@ -289,10 +283,7 @@ func (api *Client) SetGroupReadMarkContext(ctx context.Context, group, ts string "ts": {ts}, } _, err := groupRequest(ctx, "groups.mark", values, api.debug) - if err != nil { - return err - } - return nil + return err } // OpenGroup opens a private group diff --git a/vendor/github.com/matterbridge/slack/history.go b/vendor/github.com/nlopes/slack/history.go similarity index 100% rename from vendor/github.com/matterbridge/slack/history.go rename to vendor/github.com/nlopes/slack/history.go diff --git a/vendor/github.com/matterbridge/slack/im.go b/vendor/github.com/nlopes/slack/im.go similarity index 100% rename from vendor/github.com/matterbridge/slack/im.go rename to vendor/github.com/nlopes/slack/im.go diff --git a/vendor/github.com/matterbridge/slack/info.go b/vendor/github.com/nlopes/slack/info.go similarity index 100% rename from vendor/github.com/matterbridge/slack/info.go rename to vendor/github.com/nlopes/slack/info.go diff --git a/vendor/github.com/matterbridge/slack/item.go b/vendor/github.com/nlopes/slack/item.go similarity index 100% rename from vendor/github.com/matterbridge/slack/item.go rename to vendor/github.com/nlopes/slack/item.go diff --git a/vendor/github.com/matterbridge/slack/messageID.go b/vendor/github.com/nlopes/slack/messageID.go similarity index 100% rename from vendor/github.com/matterbridge/slack/messageID.go rename to vendor/github.com/nlopes/slack/messageID.go diff --git a/vendor/github.com/matterbridge/slack/messages.go b/vendor/github.com/nlopes/slack/messages.go similarity index 95% rename from vendor/github.com/matterbridge/slack/messages.go rename to vendor/github.com/nlopes/slack/messages.go index 39f0d6b1..cdb13098 100644 --- a/vendor/github.com/matterbridge/slack/messages.go +++ b/vendor/github.com/nlopes/slack/messages.go @@ -3,6 +3,7 @@ package slack // OutgoingMessage is used for the realtime API, and seems incomplete. type OutgoingMessage struct { ID int `json:"id"` + // channel ID Channel string `json:"channel,omitempty"` Text string `json:"text,omitempty"` Type string `json:"type,omitempty"` @@ -121,12 +122,12 @@ type Pong struct { // NewOutgoingMessage prepares an OutgoingMessage that the user can // use to send a message. Use this function to properly set the // messageID. -func (rtm *RTM) NewOutgoingMessage(text string, channel string) *OutgoingMessage { +func (rtm *RTM) NewOutgoingMessage(text string, channelID string) *OutgoingMessage { id := rtm.idGen.Next() return &OutgoingMessage{ ID: id, Type: "message", - Channel: channel, + Channel: channelID, Text: text, } } @@ -134,11 +135,11 @@ func (rtm *RTM) NewOutgoingMessage(text string, channel string) *OutgoingMessage // NewTypingMessage prepares an OutgoingMessage that the user can // use to send as a typing indicator. Use this function to properly set the // messageID. -func (rtm *RTM) NewTypingMessage(channel string) *OutgoingMessage { +func (rtm *RTM) NewTypingMessage(channelID string) *OutgoingMessage { id := rtm.idGen.Next() return &OutgoingMessage{ ID: id, Type: "typing", - Channel: channel, + Channel: channelID, } } diff --git a/vendor/github.com/matterbridge/slack/misc.go b/vendor/github.com/nlopes/slack/misc.go similarity index 85% rename from vendor/github.com/matterbridge/slack/misc.go rename to vendor/github.com/nlopes/slack/misc.go index 3a9ed2d6..e890aa8f 100644 --- a/vendor/github.com/matterbridge/slack/misc.go +++ b/vendor/github.com/nlopes/slack/misc.go @@ -13,6 +13,7 @@ import ( "net/url" "os" "path/filepath" + "strconv" "strings" "time" ) @@ -42,6 +43,14 @@ func (s WebError) Error() string { return string(s) } +type RateLimitedError struct { + RetryAfter time.Duration +} + +func (e *RateLimitedError) Error() string { + return fmt.Sprintf("Slack rate limit exceeded, retry after %s", e.RetryAfter) +} + func fileUploadReq(ctx context.Context, path, fieldname, filename string, values url.Values, r io.Reader) (*http.Request, error) { body := &bytes.Buffer{} wr := multipart.NewWriter(body) @@ -79,12 +88,7 @@ func parseResponseBody(body io.ReadCloser, intf *interface{}, debug bool) error logger.Printf("parseResponseBody: %s\n", string(response)) } - err = json.Unmarshal(response, &intf) - if err != nil { - return err - } - - return nil + return json.Unmarshal(response, &intf) } func postLocalWithMultipartResponse(ctx context.Context, path, fpath, fieldname string, values url.Values, intf interface{}, debug bool) error { @@ -112,8 +116,16 @@ func postWithMultipartResponse(ctx context.Context, path, name, fieldname string } defer resp.Body.Close() + if resp.StatusCode == http.StatusTooManyRequests { + retry, err := strconv.ParseInt(resp.Header.Get("Retry-After"), 10, 64) + if err != nil { + return err + } + return &RateLimitedError{time.Duration(retry) * time.Second} + } + // Slack seems to send an HTML body along with 5xx error codes. Don't parse it. - if resp.StatusCode != 200 { + if resp.StatusCode != http.StatusOK { logResponse(resp, debug) return fmt.Errorf("Slack server error: %s.", resp.Status) } @@ -136,8 +148,16 @@ func postForm(ctx context.Context, endpoint string, values url.Values, intf inte } defer resp.Body.Close() + if resp.StatusCode == http.StatusTooManyRequests { + retry, err := strconv.ParseInt(resp.Header.Get("Retry-After"), 10, 64) + if err != nil { + return err + } + return &RateLimitedError{time.Duration(retry) * time.Second} + } + // Slack seems to send an HTML body along with 5xx error codes. Don't parse it. - if resp.StatusCode != 200 { + if resp.StatusCode != http.StatusOK { logResponse(resp, debug) return fmt.Errorf("Slack server error: %s.", resp.Status) } diff --git a/vendor/github.com/matterbridge/slack/oauth.go b/vendor/github.com/nlopes/slack/oauth.go similarity index 100% rename from vendor/github.com/matterbridge/slack/oauth.go rename to vendor/github.com/nlopes/slack/oauth.go diff --git a/vendor/github.com/matterbridge/slack/pagination.go b/vendor/github.com/nlopes/slack/pagination.go similarity index 100% rename from vendor/github.com/matterbridge/slack/pagination.go rename to vendor/github.com/nlopes/slack/pagination.go diff --git a/vendor/github.com/matterbridge/slack/pins.go b/vendor/github.com/nlopes/slack/pins.go similarity index 100% rename from vendor/github.com/matterbridge/slack/pins.go rename to vendor/github.com/nlopes/slack/pins.go diff --git a/vendor/github.com/matterbridge/slack/reactions.go b/vendor/github.com/nlopes/slack/reactions.go similarity index 100% rename from vendor/github.com/matterbridge/slack/reactions.go rename to vendor/github.com/nlopes/slack/reactions.go diff --git a/vendor/github.com/matterbridge/slack/rtm.go b/vendor/github.com/nlopes/slack/rtm.go similarity index 78% rename from vendor/github.com/matterbridge/slack/rtm.go rename to vendor/github.com/nlopes/slack/rtm.go index fd5d2002..bb3cde1b 100644 --- a/vendor/github.com/matterbridge/slack/rtm.go +++ b/vendor/github.com/nlopes/slack/rtm.go @@ -27,17 +27,8 @@ func (api *Client) StartRTMContext(ctx context.Context) (info *Info, websocketUR if !response.Ok { return nil, "", response.Error } - - // websocket.Dial does not accept url without the port (yet) - // Fixed by: https://github.com/golang/net/commit/5058c78c3627b31e484a81463acd51c7cecc06f3 - // but slack returns the address with no port, so we have to fix it api.Debugln("Using URL:", response.Info.URL) - websocketURL, err = websocketizeURLPort(response.Info.URL) - if err != nil { - return nil, "", fmt.Errorf("parsing response URL: %s", err) - } - - return &response.Info, websocketURL, nil + return &response.Info, response.Info.URL, nil } // ConnectRTM calls the "rtm.connect" endpoint and returns the provided URL and the compact Info block. @@ -59,17 +50,8 @@ func (api *Client) ConnectRTMContext(ctx context.Context) (info *Info, websocket if !response.Ok { return nil, "", response.Error } - - // websocket.Dial does not accept url without the port (yet) - // Fixed by: https://github.com/golang/net/commit/5058c78c3627b31e484a81463acd51c7cecc06f3 - // but slack returns the address with no port, so we have to fix it api.Debugln("Using URL:", response.Info.URL) - websocketURL, err = websocketizeURLPort(response.Info.URL) - if err != nil { - return nil, "", fmt.Errorf("parsing response URL: %s", err) - } - - return &response.Info, websocketURL, nil + return &response.Info, response.Info.URL, nil } // NewRTM returns a RTM, which provides a fully managed connection to @@ -90,6 +72,7 @@ func (api *Client) NewRTMWithOptions(options *RTMOptions) *RTM { isConnected: false, wasIntentional: true, killChannel: make(chan bool), + disconnected: make(chan struct{}), forcePing: make(chan bool), rawEvents: make(chan json.RawMessage), idGen: NewSafeID(1), diff --git a/vendor/github.com/matterbridge/slack/search.go b/vendor/github.com/nlopes/slack/search.go similarity index 100% rename from vendor/github.com/matterbridge/slack/search.go rename to vendor/github.com/nlopes/slack/search.go diff --git a/vendor/github.com/matterbridge/slack/slack.go b/vendor/github.com/nlopes/slack/slack.go similarity index 77% rename from vendor/github.com/matterbridge/slack/slack.go rename to vendor/github.com/nlopes/slack/slack.go index a13bed31..754117c1 100644 --- a/vendor/github.com/matterbridge/slack/slack.go +++ b/vendor/github.com/nlopes/slack/slack.go @@ -3,12 +3,13 @@ package slack import ( "context" "errors" + "fmt" "log" "net/url" "os" ) -var logger *log.Logger // A logger that can be set by consumers +var logger stdLogger // A logger that can be set by consumers /* Added as a var so that we can change this for testing purposes */ @@ -41,12 +42,31 @@ type Client struct { debug bool } +// stdLogger is a logger interface compatible with both stdlib and some +// 3rd party loggers such as logrus. +type stdLogger interface { + Print(...interface{}) + Printf(string, ...interface{}) + Println(...interface{}) + + Fatal(...interface{}) + Fatalf(string, ...interface{}) + Fatalln(...interface{}) + + Panic(...interface{}) + Panicf(string, ...interface{}) + Panicln(...interface{}) + + Output(int, string) error +} + // SetLogger let's library users supply a logger, so that api debugging // can be logged along with the application's debugging info. -func SetLogger(l *log.Logger) { +func SetLogger(l stdLogger) { logger = l } +// New creates new Client. func New(token string) *Client { s := &Client{} s.config.token = token @@ -83,12 +103,12 @@ func (api *Client) SetDebug(debug bool) { func (api *Client) Debugf(format string, v ...interface{}) { if api.debug { - logger.Printf(format, v...) + logger.Output(2, fmt.Sprintf(format, v...)) } } func (api *Client) Debugln(v ...interface{}) { if api.debug { - logger.Println(v...) + logger.Output(2, fmt.Sprintln(v...)) } } diff --git a/vendor/github.com/matterbridge/slack/stars.go b/vendor/github.com/nlopes/slack/stars.go similarity index 100% rename from vendor/github.com/matterbridge/slack/stars.go rename to vendor/github.com/nlopes/slack/stars.go diff --git a/vendor/github.com/matterbridge/slack/team.go b/vendor/github.com/nlopes/slack/team.go similarity index 100% rename from vendor/github.com/matterbridge/slack/team.go rename to vendor/github.com/nlopes/slack/team.go diff --git a/vendor/github.com/matterbridge/slack/usergroups.go b/vendor/github.com/nlopes/slack/usergroups.go similarity index 100% rename from vendor/github.com/matterbridge/slack/usergroups.go rename to vendor/github.com/nlopes/slack/usergroups.go diff --git a/vendor/github.com/matterbridge/slack/users.go b/vendor/github.com/nlopes/slack/users.go similarity index 98% rename from vendor/github.com/matterbridge/slack/users.go rename to vendor/github.com/nlopes/slack/users.go index 82798c93..f7fbd0d2 100644 --- a/vendor/github.com/matterbridge/slack/users.go +++ b/vendor/github.com/nlopes/slack/users.go @@ -200,10 +200,7 @@ func (api *Client) SetUserAsActiveContext(ctx context.Context) error { "token": {api.config.token}, } _, err := userRequest(ctx, "users.setActive", values, api.debug) - if err != nil { - return err - } - return nil + return err } // SetUserPresence changes the currently authenticated user presence @@ -247,8 +244,8 @@ func (api *Client) GetUserIdentityContext(ctx context.Context) (*UserIdentityRes } // SetUserPhoto changes the currently authenticated user's profile image -func (api *Client) SetUserPhoto(ctx context.Context, image string, params UserSetPhotoParams) error { - return api.SetUserPhoto(context.Background(), image, params) +func (api *Client) SetUserPhoto(image string, params UserSetPhotoParams) error { + return api.SetUserPhotoContext(context.Background(), image, params) } // SetUserPhotoContext changes the currently authenticated user's profile image using a custom context diff --git a/vendor/github.com/matterbridge/slack/websocket.go b/vendor/github.com/nlopes/slack/websocket.go similarity index 90% rename from vendor/github.com/matterbridge/slack/websocket.go rename to vendor/github.com/nlopes/slack/websocket.go index f3c9cbd8..77906e07 100644 --- a/vendor/github.com/matterbridge/slack/websocket.go +++ b/vendor/github.com/nlopes/slack/websocket.go @@ -27,6 +27,7 @@ type RTM struct { IncomingEvents chan RTMEvent outgoingMessages chan OutgoingMessage killChannel chan bool + disconnected chan struct{} // disconnected is closed when Disconnect is invoked, regardless of connection state. Allows for ManagedConnection to not leak. forcePing chan bool rawEvents chan json.RawMessage wasIntentional bool @@ -59,9 +60,14 @@ type RTMOptions struct { // Disconnect and wait, blocking until a successful disconnection. func (rtm *RTM) Disconnect() error { + // this channel is always closed on disconnect. lets the ManagedConnection() function + // properly clean up. + close(rtm.disconnected) + if !rtm.isConnected { return errors.New("Invalid call to Disconnect - Slack API is already disconnected") } + rtm.killChannel <- true return nil } diff --git a/vendor/github.com/matterbridge/slack/websocket_channels.go b/vendor/github.com/nlopes/slack/websocket_channels.go similarity index 100% rename from vendor/github.com/matterbridge/slack/websocket_channels.go rename to vendor/github.com/nlopes/slack/websocket_channels.go diff --git a/vendor/github.com/matterbridge/slack/websocket_dm.go b/vendor/github.com/nlopes/slack/websocket_dm.go similarity index 100% rename from vendor/github.com/matterbridge/slack/websocket_dm.go rename to vendor/github.com/nlopes/slack/websocket_dm.go diff --git a/vendor/github.com/matterbridge/slack/websocket_dnd.go b/vendor/github.com/nlopes/slack/websocket_dnd.go similarity index 100% rename from vendor/github.com/matterbridge/slack/websocket_dnd.go rename to vendor/github.com/nlopes/slack/websocket_dnd.go diff --git a/vendor/github.com/matterbridge/slack/websocket_files.go b/vendor/github.com/nlopes/slack/websocket_files.go similarity index 100% rename from vendor/github.com/matterbridge/slack/websocket_files.go rename to vendor/github.com/nlopes/slack/websocket_files.go diff --git a/vendor/github.com/matterbridge/slack/websocket_groups.go b/vendor/github.com/nlopes/slack/websocket_groups.go similarity index 100% rename from vendor/github.com/matterbridge/slack/websocket_groups.go rename to vendor/github.com/nlopes/slack/websocket_groups.go diff --git a/vendor/github.com/matterbridge/slack/websocket_internals.go b/vendor/github.com/nlopes/slack/websocket_internals.go similarity index 100% rename from vendor/github.com/matterbridge/slack/websocket_internals.go rename to vendor/github.com/nlopes/slack/websocket_internals.go diff --git a/vendor/github.com/matterbridge/slack/websocket_managed_conn.go b/vendor/github.com/nlopes/slack/websocket_managed_conn.go similarity index 96% rename from vendor/github.com/matterbridge/slack/websocket_managed_conn.go rename to vendor/github.com/nlopes/slack/websocket_managed_conn.go index 9c48852a..fec07fd7 100644 --- a/vendor/github.com/matterbridge/slack/websocket_managed_conn.go +++ b/vendor/github.com/nlopes/slack/websocket_managed_conn.go @@ -99,6 +99,15 @@ func (rtm *RTM) connect(connectionCount int, useRTMStart bool) (*Info, *websocke Attempt: boff.attempts, ErrorObj: err, }} + + // check if Disconnect() has been invoked. + select { + case _ = <-rtm.disconnected: + rtm.IncomingEvents <- RTMEvent{"disconnected", &DisconnectedEvent{Intentional: true}} + return nil, nil, fmt.Errorf("disconnect received while trying to connect") + default: + } + // get time we should wait before attempting to connect again dur := boff.Duration() rtm.Debugf("reconnection %d failed: %s", boff.attempts+1, err) @@ -124,7 +133,8 @@ func (rtm *RTM) startRTMAndDial(useRTMStart bool) (*Info, *websocket.Conn, error return nil, nil, err } - conn, err := websocketProxyDial(url, "http://api.slack.com") + // Only use HTTPS for connections to prevent MITM attacks on the connection. + conn, err := websocketProxyDial(url, "https://api.slack.com") if err != nil { return nil, nil, err } @@ -317,10 +327,13 @@ func (rtm *RTM) handleAck(event json.RawMessage) { rtm.Debugln(" -> Erroneous 'ack' event:", string(event)) return } + if ack.Ok { rtm.IncomingEvents <- RTMEvent{"ack", ack} - } else { + } else if ack.RTMResponse.Error != nil { rtm.IncomingEvents <- RTMEvent{"ack_error", &AckErrorEvent{ack.Error}} + } else { + rtm.IncomingEvents <- RTMEvent{"ack_error", &AckErrorEvent{fmt.Errorf("ack decode failure")}} } } diff --git a/vendor/github.com/matterbridge/slack/websocket_misc.go b/vendor/github.com/nlopes/slack/websocket_misc.go similarity index 100% rename from vendor/github.com/matterbridge/slack/websocket_misc.go rename to vendor/github.com/nlopes/slack/websocket_misc.go diff --git a/vendor/github.com/matterbridge/slack/websocket_pins.go b/vendor/github.com/nlopes/slack/websocket_pins.go similarity index 100% rename from vendor/github.com/matterbridge/slack/websocket_pins.go rename to vendor/github.com/nlopes/slack/websocket_pins.go diff --git a/vendor/github.com/matterbridge/slack/websocket_proxy.go b/vendor/github.com/nlopes/slack/websocket_proxy.go similarity index 95% rename from vendor/github.com/matterbridge/slack/websocket_proxy.go rename to vendor/github.com/nlopes/slack/websocket_proxy.go index 440015d6..27f1cf99 100644 --- a/vendor/github.com/matterbridge/slack/websocket_proxy.go +++ b/vendor/github.com/nlopes/slack/websocket_proxy.go @@ -32,8 +32,7 @@ func websocketHTTPConnect(proxy, urlString string) (net.Conn, error) { } cc := httputil.NewProxyClientConn(p, nil) - cc.Do(&req) - if err != nil && err != httputil.ErrPersistEOF { + if _, err := cc.Do(&req); err != nil { return nil, err } diff --git a/vendor/github.com/matterbridge/slack/websocket_reactions.go b/vendor/github.com/nlopes/slack/websocket_reactions.go similarity index 100% rename from vendor/github.com/matterbridge/slack/websocket_reactions.go rename to vendor/github.com/nlopes/slack/websocket_reactions.go diff --git a/vendor/github.com/matterbridge/slack/websocket_stars.go b/vendor/github.com/nlopes/slack/websocket_stars.go similarity index 100% rename from vendor/github.com/matterbridge/slack/websocket_stars.go rename to vendor/github.com/nlopes/slack/websocket_stars.go diff --git a/vendor/github.com/matterbridge/slack/websocket_teams.go b/vendor/github.com/nlopes/slack/websocket_teams.go similarity index 100% rename from vendor/github.com/matterbridge/slack/websocket_teams.go rename to vendor/github.com/nlopes/slack/websocket_teams.go diff --git a/vendor/manifest b/vendor/manifest index 78bc2b9a..684e435c 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -294,14 +294,6 @@ "branch": "master", "notests": true }, - { - "importpath": "github.com/matterbridge/slack", - "repository": "https://github.com/matterbridge/slack", - "vcs": "git", - "revision": "1c6e6305bf9c07fc603c9cf28f09ab0517a03120", - "branch": "matterbridge", - "notests": true - }, { "importpath": "github.com/mattermost/platform/einterfaces", "repository": "https://github.com/mattermost/platform", @@ -441,6 +433,14 @@ "path": "/i18n", "notests": true }, + { + "importpath": "github.com/nlopes/slack", + "repository": "https://github.com/nlopes/slack", + "vcs": "git", + "revision": "107290b5bbaf3e634833346bb4ff389b1c782bc7", + "branch": "master", + "notests": true + }, { "importpath": "github.com/paulrosania/go-charset", "repository": "https://github.com/paulrosania/go-charset", @@ -712,7 +712,7 @@ "importpath": "golang.org/x/net/websocket", "repository": "https://go.googlesource.com/net", "vcs": "git", - "revision": "6c23252515492caf9b228a9d5cabcdbde29f7f82", + "revision": "434ec0c7fe3742c984919a691b2018a6e9694425", "branch": "master", "path": "/websocket", "notests": true @@ -760,4 +760,4 @@ "notests": true } ] -} \ No newline at end of file +}