diff --git a/admin.go b/admin.go index a2aa7e5cb..db44aa380 100644 --- a/admin.go +++ b/admin.go @@ -12,9 +12,9 @@ type adminResponse struct { Error string `json:"error"` } -func adminRequest(ctx context.Context, client HTTPRequester, method string, teamName string, values url.Values, debug bool) (*adminResponse, error) { +func adminRequest(ctx context.Context, client httpClient, method string, teamName string, values url.Values, d debug) (*adminResponse, error) { adminResponse := &adminResponse{} - err := parseAdminResponse(ctx, client, method, teamName, values, adminResponse, debug) + err := parseAdminResponse(ctx, client, method, teamName, values, adminResponse, d) if err != nil { return nil, err } @@ -40,7 +40,7 @@ func (api *Client) DisableUserContext(ctx context.Context, teamName string, uid "_attempts": {"1"}, } - _, err := adminRequest(ctx, api.httpclient, "setInactive", teamName, values, api.debug) + _, err := adminRequest(ctx, api.httpclient, "setInactive", teamName, values, api) if err != nil { return fmt.Errorf("Failed to disable user with id '%s': %s", uid, err) } @@ -67,7 +67,7 @@ func (api *Client) InviteGuestContext(ctx context.Context, teamName, channel, fi "_attempts": {"1"}, } - _, err := adminRequest(ctx, api.httpclient, "invite", teamName, values, api.debug) + _, err := adminRequest(ctx, api.httpclient, "invite", teamName, values, api) if err != nil { return fmt.Errorf("Failed to invite single-channel guest: %s", err) } @@ -94,7 +94,7 @@ func (api *Client) InviteRestrictedContext(ctx context.Context, teamName, channe "_attempts": {"1"}, } - _, err := adminRequest(ctx, api.httpclient, "invite", teamName, values, api.debug) + _, err := adminRequest(ctx, api.httpclient, "invite", teamName, values, api) if err != nil { return fmt.Errorf("Failed to restricted account: %s", err) } @@ -118,7 +118,7 @@ func (api *Client) InviteToTeamContext(ctx context.Context, teamName, firstName, "_attempts": {"1"}, } - _, err := adminRequest(ctx, api.httpclient, "invite", teamName, values, api.debug) + _, err := adminRequest(ctx, api.httpclient, "invite", teamName, values, api) if err != nil { return fmt.Errorf("Failed to invite to team: %s", err) } @@ -140,7 +140,7 @@ func (api *Client) SetRegularContext(ctx context.Context, teamName, user string) "_attempts": {"1"}, } - _, err := adminRequest(ctx, api.httpclient, "setRegular", teamName, values, api.debug) + _, err := adminRequest(ctx, api.httpclient, "setRegular", teamName, values, api) if err != nil { return fmt.Errorf("Failed to change the user (%s) to a regular user: %s", user, err) } @@ -162,7 +162,7 @@ func (api *Client) SendSSOBindingEmailContext(ctx context.Context, teamName, use "_attempts": {"1"}, } - _, err := adminRequest(ctx, api.httpclient, "sendSSOBind", teamName, values, api.debug) + _, err := adminRequest(ctx, api.httpclient, "sendSSOBind", teamName, values, api) if err != nil { return fmt.Errorf("Failed to send SSO binding email for user (%s): %s", user, err) } @@ -185,7 +185,7 @@ func (api *Client) SetUltraRestrictedContext(ctx context.Context, teamName, uid, "_attempts": {"1"}, } - _, err := adminRequest(ctx, api.httpclient, "setUltraRestricted", teamName, values, api.debug) + _, err := adminRequest(ctx, api.httpclient, "setUltraRestricted", teamName, values, api) if err != nil { return fmt.Errorf("Failed to ultra-restrict account: %s", err) } @@ -207,7 +207,7 @@ func (api *Client) SetRestrictedContext(ctx context.Context, teamName, uid strin "_attempts": {"1"}, } - _, err := adminRequest(ctx, api.httpclient, "setRestricted", teamName, values, api.debug) + _, err := adminRequest(ctx, api.httpclient, "setRestricted", teamName, values, api) if err != nil { return fmt.Errorf("Failed to restrict account: %s", err) } diff --git a/bots.go b/bots.go index 92570a049..e27e76ab6 100644 --- a/bots.go +++ b/bots.go @@ -19,9 +19,9 @@ type botResponseFull struct { SlackResponse } -func botRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*botResponseFull, error) { +func botRequest(ctx context.Context, client httpClient, path string, values url.Values, d debug) (*botResponseFull, error) { response := &botResponseFull{} - err := postSlackMethod(ctx, client, path, values, response, debug) + err := postSlackMethod(ctx, client, path, values, response, d) if err != nil { return nil, err } @@ -43,7 +43,7 @@ func (api *Client) GetBotInfoContext(ctx context.Context, bot string) (*Bot, err "bot": {bot}, } - response, err := botRequest(ctx, api.httpclient, "bots.info", values, api.debug) + response, err := botRequest(ctx, api.httpclient, "bots.info", values, api) if err != nil { return nil, err } diff --git a/bots_test.go b/bots_test.go index 7066e78fc..3eab4e274 100644 --- a/bots_test.go +++ b/bots_test.go @@ -24,7 +24,7 @@ func TestGetBotInfo(t *testing.T) { http.HandleFunc("/bots.info", getBotInfo) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") bot, err := api.GetBotInfo("B02875YLA") diff --git a/channels.go b/channels.go index 6204315a9..007985bc1 100644 --- a/channels.go +++ b/channels.go @@ -26,9 +26,9 @@ type Channel struct { Locale string `json:"locale"` } -func channelRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*channelResponseFull, error) { +func channelRequest(ctx context.Context, client httpClient, path string, values url.Values, d debug) (*channelResponseFull, error) { response := &channelResponseFull{} - err := postForm(ctx, client, SLACK_API+path, values, response, debug) + err := postForm(ctx, client, APIURL+path, values, response, d) if err != nil { return nil, err } @@ -52,7 +52,7 @@ func (api *Client) ArchiveChannelContext(ctx context.Context, channelID string) "channel": {channelID}, } - _, err = channelRequest(ctx, api.httpclient, "channels.archive", values, api.debug) + _, err = channelRequest(ctx, api.httpclient, "channels.archive", values, api) return err } @@ -70,7 +70,7 @@ func (api *Client) UnarchiveChannelContext(ctx context.Context, channelID string "channel": {channelID}, } - _, err = channelRequest(ctx, api.httpclient, "channels.unarchive", values, api.debug) + _, err = channelRequest(ctx, api.httpclient, "channels.unarchive", values, api) return err } @@ -88,7 +88,7 @@ func (api *Client) CreateChannelContext(ctx context.Context, channelName string) "name": {channelName}, } - response, err := channelRequest(ctx, api.httpclient, "channels.create", values, api.debug) + response, err := channelRequest(ctx, api.httpclient, "channels.create", values, api) if err != nil { return nil, err } @@ -133,7 +133,7 @@ func (api *Client) GetChannelHistoryContext(ctx context.Context, channelID strin } } - response, err := channelRequest(ctx, api.httpclient, "channels.history", values, api.debug) + response, err := channelRequest(ctx, api.httpclient, "channels.history", values, api) if err != nil { return nil, err } @@ -154,7 +154,7 @@ func (api *Client) GetChannelInfoContext(ctx context.Context, channelID string) "channel": {channelID}, } - response, err := channelRequest(ctx, api.httpclient, "channels.info", values, api.debug) + response, err := channelRequest(ctx, api.httpclient, "channels.info", values, api) if err != nil { return nil, err } @@ -167,7 +167,7 @@ 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 +// InviteUserToChannelContext invites a user to a given channel and returns a *Channel with a custom context // see https://api.slack.com/methods/channels.invite func (api *Client) InviteUserToChannelContext(ctx context.Context, channelID, user string) (*Channel, error) { values := url.Values{ @@ -176,7 +176,7 @@ func (api *Client) InviteUserToChannelContext(ctx context.Context, channelID, us "user": {user}, } - response, err := channelRequest(ctx, api.httpclient, "channels.invite", values, api.debug) + response, err := channelRequest(ctx, api.httpclient, "channels.invite", values, api) if err != nil { return nil, err } @@ -197,7 +197,7 @@ func (api *Client) JoinChannelContext(ctx context.Context, channelName string) ( "name": {channelName}, } - response, err := channelRequest(ctx, api.httpclient, "channels.join", values, api.debug) + response, err := channelRequest(ctx, api.httpclient, "channels.join", values, api) if err != nil { return nil, err } @@ -218,7 +218,7 @@ func (api *Client) LeaveChannelContext(ctx context.Context, channelID string) (b "channel": {channelID}, } - response, err := channelRequest(ctx, api.httpclient, "channels.leave", values, api.debug) + response, err := channelRequest(ctx, api.httpclient, "channels.leave", values, api) if err != nil { return false, err } @@ -241,7 +241,7 @@ func (api *Client) KickUserFromChannelContext(ctx context.Context, channelID, us "user": {user}, } - _, err = channelRequest(ctx, api.httpclient, "channels.kick", values, api.debug) + _, err = channelRequest(ctx, api.httpclient, "channels.kick", values, api) return err } @@ -261,7 +261,7 @@ func (api *Client) GetChannelsContext(ctx context.Context, excludeArchived bool) values.Add("exclude_archived", "1") } - response, err := channelRequest(ctx, api.httpclient, "channels.list", values, api.debug) + response, err := channelRequest(ctx, api.httpclient, "channels.list", values, api) if err != nil { return nil, err } @@ -288,7 +288,7 @@ func (api *Client) SetChannelReadMarkContext(ctx context.Context, channelID, ts "ts": {ts}, } - _, err = channelRequest(ctx, api.httpclient, "channels.mark", values, api.debug) + _, err = channelRequest(ctx, api.httpclient, "channels.mark", values, api) return err } @@ -309,7 +309,7 @@ func (api *Client) RenameChannelContext(ctx context.Context, channelID, name str // 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(ctx, api.httpclient, "channels.rename", values, api.debug) + response, err := channelRequest(ctx, api.httpclient, "channels.rename", values, api) if err != nil { return nil, err } @@ -331,7 +331,7 @@ func (api *Client) SetChannelPurposeContext(ctx context.Context, channelID, purp "purpose": {purpose}, } - response, err := channelRequest(ctx, api.httpclient, "channels.setPurpose", values, api.debug) + response, err := channelRequest(ctx, api.httpclient, "channels.setPurpose", values, api) if err != nil { return "", err } @@ -353,7 +353,7 @@ func (api *Client) SetChannelTopicContext(ctx context.Context, channelID, topic "topic": {topic}, } - response, err := channelRequest(ctx, api.httpclient, "channels.setTopic", values, api.debug) + response, err := channelRequest(ctx, api.httpclient, "channels.setTopic", values, api) if err != nil { return "", err } @@ -374,7 +374,7 @@ func (api *Client) GetChannelRepliesContext(ctx context.Context, channelID, thre "channel": {channelID}, "thread_ts": {thread_ts}, } - response, err := channelRequest(ctx, api.httpclient, "channels.replies", values, api.debug) + response, err := channelRequest(ctx, api.httpclient, "channels.replies", values, api) if err != nil { return nil, err } diff --git a/chat.go b/chat.go index 8cc6bdefd..ece17292f 100644 --- a/chat.go +++ b/chat.go @@ -96,26 +96,24 @@ func (api *Client) DeleteMessageContext(ctx context.Context, channel, messageTim // PostMessage sends a message to 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) PostMessage(channel, text string, params PostMessageParameters) (string, string, error) { +func (api *Client) PostMessage(channelID string, options ...MsgOption) (string, string, error) { respChannel, respTimestamp, _, err := api.SendMessageContext( context.Background(), - channel, - MsgOptionText(text, params.EscapeText), - MsgOptionAttachments(params.Attachments...), - MsgOptionPostMessageParameters(params), + channelID, + MsgOptionPost(), + MsgOptionCompose(options...), ) return respChannel, respTimestamp, err } // PostMessageContext sends a message to a channel with a custom context -// For more details, see PostMessage documentation -func (api *Client) PostMessageContext(ctx context.Context, channel, text string, params PostMessageParameters) (string, string, error) { +// For more details, see PostMessage documentation. +func (api *Client) PostMessageContext(ctx context.Context, channelID string, options ...MsgOption) (string, string, error) { respChannel, respTimestamp, _, err := api.SendMessageContext( ctx, - channel, - MsgOptionText(text, params.EscapeText), - MsgOptionAttachments(params.Attachments...), - MsgOptionPostMessageParameters(params), + channelID, + MsgOptionPost(), + MsgOptionCompose(options...), ) return respChannel, respTimestamp, err } @@ -135,18 +133,18 @@ func (api *Client) PostEphemeral(channelID, userID string, options ...MsgOption) // 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, channelID, userID string, options ...MsgOption) (timestamp string, err error) { - _, timestamp, _, err = api.SendMessageContext(ctx, channelID, append(options, MsgOptionPostEphemeral2(userID))...) + _, timestamp, _, err = api.SendMessageContext(ctx, channelID, MsgOptionPostEphemeral(userID), MsgOptionCompose(options...)) return timestamp, err } // UpdateMessage updates a message in a channel -func (api *Client) UpdateMessage(channelID, timestamp, text string) (string, string, string, error) { - return api.UpdateMessageContext(context.Background(), channelID, timestamp, text) +func (api *Client) UpdateMessage(channelID, timestamp string, options ...MsgOption) (string, string, string, error) { + return api.SendMessageContext(context.Background(), channelID, MsgOptionUpdate(timestamp), MsgOptionCompose(options...)) } // UpdateMessageContext updates a message in a channel -func (api *Client) UpdateMessageContext(ctx context.Context, channelID, timestamp, text string) (string, string, string, error) { - return api.SendMessageContext(ctx, channelID, MsgOptionUpdate(timestamp), MsgOptionText(text, true)) +func (api *Client) UpdateMessageContext(ctx context.Context, channelID, timestamp string, options ...MsgOption) (string, string, string, error) { + return api.SendMessageContext(ctx, channelID, MsgOptionUpdate(timestamp), MsgOptionCompose(options...)) } // SendMessage more flexible method for configuring messages. @@ -165,7 +163,7 @@ func (api *Client) SendMessageContext(ctx context.Context, channelID string, opt return "", "", "", err } - if err = postForm(ctx, api.httpclient, config.endpoint, config.values, &response, api.debug); err != nil { + if err = postForm(ctx, api.httpclient, config.endpoint, config.values, &response, api); err != nil { return "", "", "", err } @@ -182,7 +180,7 @@ func UnsafeApplyMsgOptions(token, channel string, options ...MsgOption) (string, func applyMsgOptions(token, channel string, options ...MsgOption) (sendConfig, error) { config := sendConfig{ - endpoint: SLACK_API + string(chatPostMessage), + endpoint: APIURL + string(chatPostMessage), values: url.Values{ "token": {token}, "channel": {channel}, @@ -219,26 +217,16 @@ type MsgOption func(*sendConfig) error // MsgOptionPost posts a messages, this is the default. func MsgOptionPost() MsgOption { return func(config *sendConfig) error { - config.endpoint = SLACK_API + string(chatPostMessage) - config.values.Del("ts") - return nil - } -} - -// MsgOptionPostEphemeral - DEPRECATED: use MsgOptionPostEphemeral2 -// posts an ephemeral message. -func MsgOptionPostEphemeral() MsgOption { - return func(config *sendConfig) error { - config.endpoint = SLACK_API + string(chatPostEphemeral) + config.endpoint = APIURL + string(chatPostMessage) config.values.Del("ts") return nil } } -// MsgOptionPostEphemeral2 - posts an ephemeral message to the provided user. -func MsgOptionPostEphemeral2(userID string) MsgOption { +// MsgOptionPostEphemeral - posts an ephemeral message to the provided user. +func MsgOptionPostEphemeral(userID string) MsgOption { return func(config *sendConfig) error { - config.endpoint = SLACK_API + string(chatPostEphemeral) + config.endpoint = APIURL + string(chatPostEphemeral) MsgOptionUser(userID)(config) config.values.Del("ts") @@ -249,7 +237,7 @@ func MsgOptionPostEphemeral2(userID string) MsgOption { // MsgOptionMeMessage posts a "me message" type from the calling user func MsgOptionMeMessage() MsgOption { return func(config *sendConfig) error { - config.endpoint = SLACK_API + string(chatMeMessage) + config.endpoint = APIURL + string(chatMeMessage) return nil } } @@ -257,7 +245,7 @@ func MsgOptionMeMessage() MsgOption { // MsgOptionUpdate updates a message based on the timestamp. func MsgOptionUpdate(timestamp string) MsgOption { return func(config *sendConfig) error { - config.endpoint = SLACK_API + string(chatUpdate) + config.endpoint = APIURL + string(chatUpdate) config.values.Add("ts", timestamp) return nil } @@ -266,7 +254,7 @@ func MsgOptionUpdate(timestamp string) MsgOption { // MsgOptionDelete deletes a message based on the timestamp. func MsgOptionDelete(timestamp string) MsgOption { return func(config *sendConfig) error { - config.endpoint = SLACK_API + string(chatDelete) + config.endpoint = APIURL + string(chatDelete) config.values.Add("ts", timestamp) return nil } @@ -365,7 +353,7 @@ func MsgOptionBroadcast() MsgOption { } } -// this function combines multiple options into a single option. +// MsgOptionCompose combines multiple options into a single option. func MsgOptionCompose(options ...MsgOption) MsgOption { return func(c *sendConfig) error { for _, opt := range options { @@ -377,6 +365,7 @@ func MsgOptionCompose(options ...MsgOption) MsgOption { } } +// MsgOptionParse set parse option. func MsgOptionParse(b bool) MsgOption { return func(c *sendConfig) error { var v string diff --git a/chat_test.go b/chat_test.go index fa7627659..90d391ba5 100644 --- a/chat_test.go +++ b/chat_test.go @@ -17,16 +17,16 @@ func postMessageInvalidChannelHandler(rw http.ResponseWriter, r *http.Request) { func TestPostMessageInvalidChannel(t *testing.T) { http.HandleFunc("/chat.postMessage", postMessageInvalidChannelHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") - _, _, err := api.PostMessage("CXXXXXXXX", "hello", PostMessageParameters{}) + _, _, err := api.PostMessage("CXXXXXXXX", MsgOptionText("hello", false)) if err == nil { - t.Errorf("Expected error: %s; instead succeeded", "channel_not_found") + t.Errorf("Expected error: channel_not_found; instead succeeded") return } if err.Error() != "channel_not_found" { - t.Errorf("Expected error: %s; received: %s", "channel_not_found", err) + t.Errorf("Expected error: channel_not_found; received: %s", err) return } } diff --git a/conversation.go b/conversation.go index 1c64116ef..940907a20 100644 --- a/conversation.go +++ b/conversation.go @@ -99,7 +99,7 @@ func (api *Client) GetUsersInConversationContext(ctx context.Context, params *Ge ResponseMetaData responseMetaData `json:"response_metadata"` SlackResponse }{} - err := postSlackMethod(ctx, api.httpclient, "conversations.members", values, &response, api.debug) + err := postSlackMethod(ctx, api.httpclient, "conversations.members", values, &response, api) if err != nil { return nil, "", err } @@ -134,14 +134,12 @@ func (api *Client) GetConversationsForUserContext(ctx context.Context, params *G ResponseMetaData responseMetaData `json:"response_metadata"` SlackResponse }{} - err = postSlackMethod(ctx, api.httpclient, "users.conversations", values, &response, api.debug) + err = postSlackMethod(ctx, api.httpclient, "users.conversations", values, &response, api) if err != nil { return nil, "", err } - if !response.Ok { - return nil, "", errors.New(response.Error) - } - return response.Channels, response.ResponseMetaData.NextCursor, nil + + return response.Channels, response.ResponseMetaData.NextCursor, response.Err() } // ArchiveConversation archives a conversation @@ -156,7 +154,7 @@ func (api *Client) ArchiveConversationContext(ctx context.Context, channelID str "channel": {channelID}, } response := SlackResponse{} - err := postSlackMethod(ctx, api.httpclient, "conversations.archive", values, &response, api.debug) + err := postSlackMethod(ctx, api.httpclient, "conversations.archive", values, &response, api) if err != nil { return err } @@ -176,7 +174,7 @@ func (api *Client) UnArchiveConversationContext(ctx context.Context, channelID s "channel": {channelID}, } response := SlackResponse{} - err := postSlackMethod(ctx, api.httpclient, "conversations.unarchive", values, &response, api.debug) + err := postSlackMethod(ctx, api.httpclient, "conversations.unarchive", values, &response, api) if err != nil { return err } @@ -200,7 +198,7 @@ func (api *Client) SetTopicOfConversationContext(ctx context.Context, channelID, SlackResponse Channel *Channel `json:"channel"` }{} - err := postSlackMethod(ctx, api.httpclient, "conversations.setTopic", values, &response, api.debug) + err := postSlackMethod(ctx, api.httpclient, "conversations.setTopic", values, &response, api) if err != nil { return nil, err } @@ -224,7 +222,7 @@ func (api *Client) SetPurposeOfConversationContext(ctx context.Context, channelI SlackResponse Channel *Channel `json:"channel"` }{} - err := postSlackMethod(ctx, api.httpclient, "conversations.setPurpose", values, &response, api.debug) + err := postSlackMethod(ctx, api.httpclient, "conversations.setPurpose", values, &response, api) if err != nil { return nil, err } @@ -248,7 +246,7 @@ func (api *Client) RenameConversationContext(ctx context.Context, channelID, cha SlackResponse Channel *Channel `json:"channel"` }{} - err := postSlackMethod(ctx, api.httpclient, "conversations.rename", values, &response, api.debug) + err := postSlackMethod(ctx, api.httpclient, "conversations.rename", values, &response, api) if err != nil { return nil, err } @@ -272,7 +270,7 @@ func (api *Client) InviteUsersToConversationContext(ctx context.Context, channel SlackResponse Channel *Channel `json:"channel"` }{} - err := postSlackMethod(ctx, api.httpclient, "conversations.invite", values, &response, api.debug) + err := postSlackMethod(ctx, api.httpclient, "conversations.invite", values, &response, api) if err != nil { return nil, err } @@ -293,7 +291,7 @@ func (api *Client) KickUserFromConversationContext(ctx context.Context, channelI "user": {user}, } response := SlackResponse{} - err := postSlackMethod(ctx, api.httpclient, "conversations.kick", values, &response, api.debug) + err := postSlackMethod(ctx, api.httpclient, "conversations.kick", values, &response, api) if err != nil { return err } @@ -318,7 +316,7 @@ func (api *Client) CloseConversationContext(ctx context.Context, channelID strin AlreadyClosed bool `json:"already_closed"` }{} - err = postSlackMethod(ctx, api.httpclient, "conversations.close", values, &response, api.debug) + err = postSlackMethod(ctx, api.httpclient, "conversations.close", values, &response, api) if err != nil { return false, false, err } @@ -339,7 +337,7 @@ func (api *Client) CreateConversationContext(ctx context.Context, channelName st "is_private": {strconv.FormatBool(isPrivate)}, } response, err := channelRequest( - ctx, api.httpclient, "conversations.create", values, api.debug) + ctx, api.httpclient, "conversations.create", values, api) if err != nil { return nil, err } @@ -360,7 +358,7 @@ func (api *Client) GetConversationInfoContext(ctx context.Context, channelID str "include_locale": {strconv.FormatBool(includeLocale)}, } response, err := channelRequest( - ctx, api.httpclient, "conversations.info", values, api.debug) + ctx, api.httpclient, "conversations.info", values, api) if err != nil { return nil, err } @@ -380,7 +378,7 @@ func (api *Client) LeaveConversationContext(ctx context.Context, channelID strin "channel": {channelID}, } - response, err := channelRequest(ctx, api.httpclient, "conversations.leave", values, api.debug) + response, err := channelRequest(ctx, api.httpclient, "conversations.leave", values, api) if err != nil { return false, err } @@ -436,7 +434,7 @@ func (api *Client) GetConversationRepliesContext(ctx context.Context, params *Ge Messages []Message `json:"messages"` }{} - err = postSlackMethod(ctx, api.httpclient, "conversations.replies", values, &response, api.debug) + err = postSlackMethod(ctx, api.httpclient, "conversations.replies", values, &response, api) if err != nil { return nil, false, "", err } @@ -476,7 +474,7 @@ func (api *Client) GetConversationsContext(ctx context.Context, params *GetConve ResponseMetaData responseMetaData `json:"response_metadata"` SlackResponse }{} - err = postSlackMethod(ctx, api.httpclient, "conversations.list", values, &response, api.debug) + err = postSlackMethod(ctx, api.httpclient, "conversations.list", values, &response, api) if err != nil { return nil, "", err } @@ -513,7 +511,7 @@ func (api *Client) OpenConversationContext(ctx context.Context, params *OpenConv AlreadyOpen bool `json:"already_open"` SlackResponse }{} - err := postSlackMethod(ctx, api.httpclient, "conversations.open", values, &response, api.debug) + err := postSlackMethod(ctx, api.httpclient, "conversations.open", values, &response, api) if err != nil { return nil, false, false, err } @@ -537,7 +535,7 @@ func (api *Client) JoinConversationContext(ctx context.Context, channelID string } `json:"response_metadata"` SlackResponse }{} - err := postSlackMethod(ctx, api.httpclient, "conversations.join", values, &response, api.debug) + err := postSlackMethod(ctx, api.httpclient, "conversations.join", values, &response, api) if err != nil { return nil, "", nil, err } @@ -599,12 +597,10 @@ func (api *Client) GetConversationHistoryContext(ctx context.Context, params *Ge response := GetConversationHistoryResponse{} - err := postSlackMethod(ctx, api.httpclient, "conversations.history", values, &response, api.debug) + err := postSlackMethod(ctx, api.httpclient, "conversations.history", values, &response, api) if err != nil { return nil, err } - if !response.Ok { - return nil, errors.New(response.Error) - } - return &response, nil + + return &response, response.Err() } diff --git a/conversation_test.go b/conversation_test.go index fe46ca767..109fec0ce 100644 --- a/conversation_test.go +++ b/conversation_test.go @@ -222,7 +222,7 @@ func getUsersInConversation(rw http.ResponseWriter, r *http.Request) { func TestGetUsersInConversation(t *testing.T) { http.HandleFunc("/conversations.members", getUsersInConversation) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") params := GetUsersInConversationParameters{ ChannelID: "CXXXXXXXX", @@ -243,7 +243,7 @@ func TestGetUsersInConversation(t *testing.T) { func TestArchiveConversation(t *testing.T) { http.HandleFunc("/conversations.archive", okJSONHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") err := api.ArchiveConversation("CXXXXXXXX") if err != nil { @@ -255,7 +255,7 @@ func TestArchiveConversation(t *testing.T) { func TestUnArchiveConversation(t *testing.T) { http.HandleFunc("/conversations.unarchive", okJSONHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") err := api.UnArchiveConversation("CXXXXXXXX") if err != nil { @@ -291,7 +291,7 @@ func okChannelJsonHandler(rw http.ResponseWriter, r *http.Request) { func TestSetTopicOfConversation(t *testing.T) { http.HandleFunc("/conversations.setTopic", okChannelJsonHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") inputChannel := getTestChannel() channel, err := api.SetTopicOfConversation("CXXXXXXXX", inputChannel.Topic.Value) @@ -307,7 +307,7 @@ func TestSetTopicOfConversation(t *testing.T) { func TestSetPurposeOfConversation(t *testing.T) { http.HandleFunc("/conversations.setPurpose", okChannelJsonHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") inputChannel := getTestChannel() channel, err := api.SetPurposeOfConversation("CXXXXXXXX", inputChannel.Purpose.Value) @@ -323,7 +323,7 @@ func TestSetPurposeOfConversation(t *testing.T) { func TestRenameConversation(t *testing.T) { http.HandleFunc("/conversations.rename", okChannelJsonHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") inputChannel := getTestChannel() channel, err := api.RenameConversation("CXXXXXXXX", inputChannel.Name) @@ -339,7 +339,7 @@ func TestRenameConversation(t *testing.T) { func TestInviteUsersToConversation(t *testing.T) { http.HandleFunc("/conversations.invite", okChannelJsonHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") users := []string{"UXXXXXXX1", "UXXXXXXX2"} channel, err := api.InviteUsersToConversation("CXXXXXXXX", users...) @@ -356,7 +356,7 @@ func TestInviteUsersToConversation(t *testing.T) { func TestKickUserFromConversation(t *testing.T) { http.HandleFunc("/conversations.kick", okJSONHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") err := api.KickUserFromConversation("CXXXXXXXX", "UXXXXXXXX") if err != nil { @@ -379,7 +379,7 @@ func closeConversationHandler(rw http.ResponseWriter, r *http.Request) { func TestCloseConversation(t *testing.T) { http.HandleFunc("/conversations.close", closeConversationHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") _, _, err := api.CloseConversation("CXXXXXXXX") if err != nil { @@ -391,7 +391,7 @@ func TestCloseConversation(t *testing.T) { func TestCreateConversation(t *testing.T) { http.HandleFunc("/conversations.create", okChannelJsonHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") channel, err := api.CreateConversation("CXXXXXXXX", false) if err != nil { @@ -407,7 +407,7 @@ func TestCreateConversation(t *testing.T) { func TestGetConversationInfo(t *testing.T) { http.HandleFunc("/conversations.info", okChannelJsonHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") channel, err := api.GetConversationInfo("CXXXXXXXX", false) if err != nil { @@ -433,7 +433,7 @@ func leaveConversationHandler(rw http.ResponseWriter, r *http.Request) { func TestLeaveConversation(t *testing.T) { http.HandleFunc("/conversations.leave", leaveConversationHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") _, err := api.LeaveConversation("CXXXXXXXX") if err != nil { @@ -460,7 +460,7 @@ func getConversationRepliesHander(rw http.ResponseWriter, r *http.Request) { func TestGetConversationReplies(t *testing.T) { http.HandleFunc("/conversations.replies", getConversationRepliesHander) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") params := GetConversationRepliesParameters{ ChannelID: "CXXXXXXXX", @@ -490,7 +490,7 @@ func getConversationsHander(rw http.ResponseWriter, r *http.Request) { func TestGetConversations(t *testing.T) { http.HandleFunc("/conversations.list", getConversationsHander) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") params := GetConversationsParameters{} _, _, err := api.GetConversations(¶ms) @@ -515,7 +515,7 @@ func openConversationHandler(rw http.ResponseWriter, r *http.Request) { func TestOpenConversation(t *testing.T) { http.HandleFunc("/conversations.open", openConversationHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") params := OpenConversationParameters{ChannelID: "CXXXXXXXX"} _, _, _, err := api.OpenConversation(¶ms) @@ -542,7 +542,7 @@ func joinConversationHandler(rw http.ResponseWriter, r *http.Request) { func TestJoinConversation(t *testing.T) { http.HandleFunc("/conversations.join", joinConversationHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") _, _, _, err := api.JoinConversation("CXXXXXXXX") if err != nil { @@ -561,7 +561,7 @@ func getConversationHistoryHandler(rw http.ResponseWriter, r *http.Request) { func TestGetConversationHistory(t *testing.T) { http.HandleFunc("/conversations.history", getConversationHistoryHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") params := GetConversationHistoryParameters{ChannelID: "CXXXXXXXX"} _, err := api.GetConversationHistory(¶ms) diff --git a/dialog.go b/dialog.go index d1435d54c..914e01bee 100644 --- a/dialog.go +++ b/dialog.go @@ -108,8 +108,8 @@ func (api *Client) OpenDialogContext(ctx context.Context, triggerID string, dial } response := &DialogOpenResponse{} - endpoint := SLACK_API + "dialog.open" - if err := postJSON(ctx, api.httpclient, endpoint, api.token, encoded, response, api.debug); err != nil { + endpoint := APIURL + "dialog.open" + if err := postJSON(ctx, api.httpclient, endpoint, api.token, encoded, response, api); err != nil { return err } diff --git a/dialog_test.go b/dialog_test.go index 5367d8bb7..1c7538c36 100644 --- a/dialog_test.go +++ b/dialog_test.go @@ -286,7 +286,7 @@ func openDialogHandler(rw http.ResponseWriter, r *http.Request) { func TestOpenDialog(t *testing.T) { http.HandleFunc("/dialog.open", openDialogHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") dialog, err := unmarshalDialog() if err != nil { diff --git a/dnd.go b/dnd.go index 26d36d6ae..da6e4a16d 100644 --- a/dnd.go +++ b/dnd.go @@ -36,9 +36,9 @@ type dndTeamInfoResponse struct { SlackResponse } -func dndRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*dndResponseFull, error) { +func dndRequest(ctx context.Context, client httpClient, path string, values url.Values, d debug) (*dndResponseFull, error) { response := &dndResponseFull{} - err := postSlackMethod(ctx, client, path, values, response, debug) + err := postSlackMethod(ctx, client, path, values, response, d) if err != nil { return nil, err } @@ -61,7 +61,7 @@ func (api *Client) EndDNDContext(ctx context.Context) error { response := &SlackResponse{} - if err := postSlackMethod(ctx, api.httpclient, "dnd.endDnd", values, response, api.debug); err != nil { + if err := postSlackMethod(ctx, api.httpclient, "dnd.endDnd", values, response, api); err != nil { return err } @@ -79,7 +79,7 @@ func (api *Client) EndSnoozeContext(ctx context.Context) (*DNDStatus, error) { "token": {api.token}, } - response, err := dndRequest(ctx, api.httpclient, "dnd.endSnooze", values, api.debug) + response, err := dndRequest(ctx, api.httpclient, "dnd.endSnooze", values, api) if err != nil { return nil, err } @@ -100,7 +100,7 @@ func (api *Client) GetDNDInfoContext(ctx context.Context, user *string) (*DNDSta values.Set("user", *user) } - response, err := dndRequest(ctx, api.httpclient, "dnd.info", values, api.debug) + response, err := dndRequest(ctx, api.httpclient, "dnd.info", values, api) if err != nil { return nil, err } @@ -120,11 +120,12 @@ func (api *Client) GetDNDTeamInfoContext(ctx context.Context, users []string) (m } response := &dndTeamInfoResponse{} - if err := postSlackMethod(ctx, api.httpclient, "dnd.teamInfo", values, response, api.debug); err != nil { + if err := postSlackMethod(ctx, api.httpclient, "dnd.teamInfo", values, response, api); err != nil { return nil, err } - if !response.Ok { - return nil, errors.New(response.Error) + + if response.Err() != nil { + return nil, response.Err() } return response.Users, nil } @@ -144,7 +145,7 @@ func (api *Client) SetSnoozeContext(ctx context.Context, minutes int) (*DNDStatu "num_minutes": {strconv.Itoa(minutes)}, } - response, err := dndRequest(ctx, api.httpclient, "dnd.setSnooze", values, api.debug) + response, err := dndRequest(ctx, api.httpclient, "dnd.setSnooze", values, api) if err != nil { return nil, err } diff --git a/dnd_test.go b/dnd_test.go index ddcce8fb3..74ec94f42 100644 --- a/dnd_test.go +++ b/dnd_test.go @@ -12,7 +12,7 @@ func TestSlack_EndDND(t *testing.T) { w.Write([]byte(`{ "ok": true }`)) }) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") err := api.EndDND() if err != nil { @@ -36,7 +36,7 @@ func TestSlack_EndSnooze(t *testing.T) { SnoozeInfo: SnoozeInfo{SnoozeEnabled: false}, } once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") snoozeState, err := api.EndSnooze() if err != nil { @@ -72,7 +72,7 @@ func TestSlack_GetDNDInfo(t *testing.T) { }, } once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") userDNDInfoResponse, err := api.GetDNDInfo(nil) if err != nil { @@ -116,7 +116,7 @@ func TestSlack_GetDNDTeamInfo(t *testing.T) { }, } once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") usersDNDInfoResponse, err := api.GetDNDTeamInfo(nil) if err != nil { @@ -146,7 +146,7 @@ func TestSlack_SetSnooze(t *testing.T) { }, } once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") snoozeResponse, err := api.SetSnooze(60) if err != nil { diff --git a/emoji.go b/emoji.go index fe2945c49..aed2129fd 100644 --- a/emoji.go +++ b/emoji.go @@ -23,7 +23,7 @@ func (api *Client) GetEmojiContext(ctx context.Context) (map[string]string, erro } response := &emojiResponseFull{} - err := postSlackMethod(ctx, api.httpclient, "emoji.list", values, response, api.debug) + err := postSlackMethod(ctx, api.httpclient, "emoji.list", values, response, api) if err != nil { return nil, err } diff --git a/emoji_test.go b/emoji_test.go index 1aa086da1..f3924a73a 100644 --- a/emoji_test.go +++ b/emoji_test.go @@ -20,7 +20,7 @@ func TestGetEmoji(t *testing.T) { http.HandleFunc("/emoji.list", getEmojiHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") emojisResponse := map[string]string{ "bowtie": "https://my.slack.com/emoji/bowtie/46ec6f2bb0.png", diff --git a/examples/eventsapi/events.go b/examples/eventsapi/events.go index a96edfda4..aac8d2c4d 100644 --- a/examples/eventsapi/events.go +++ b/examples/eventsapi/events.go @@ -18,7 +18,7 @@ func main() { buf := new(bytes.Buffer) buf.ReadFrom(r.Body) body := buf.String() - eventsAPIEvent, e := slackevents.ParseEvent(json.RawMessage(body), slackevents.OptionVerifyToken(&slackevents.TokenComparator{"TOKEN"})) + eventsAPIEvent, e := slackevents.ParseEvent(json.RawMessage(body), slackevents.OptionVerifyToken(&slackevents.TokenComparator{VerificationToken: "TOKEN"})) if e != nil { w.WriteHeader(http.StatusInternalServerError) } @@ -33,11 +33,10 @@ func main() { w.Write([]byte(r.Challenge)) } if eventsAPIEvent.Type == slackevents.CallbackEvent { - postParams := slack.PostMessageParameters{} innerEvent := eventsAPIEvent.InnerEvent switch ev := innerEvent.Data.(type) { case *slackevents.AppMentionEvent: - api.PostMessage(ev.Channel, "Yes, hello.", postParams) + api.PostMessage(ev.Channel, slack.MsgOptionText("Yes, hello.", false)) } } }) diff --git a/examples/ims/ims.go b/examples/ims/ims.go index 80d73c0a6..f8ee814d1 100644 --- a/examples/ims/ims.go +++ b/examples/ims/ims.go @@ -17,5 +17,5 @@ func main() { fmt.Printf("%s\n", err) } - api.PostMessage(channelID, "Hello World!", slack.PostMessageParameters{}) + api.PostMessage(channelID, slack.MsgOptionText("Hello World!", false)) } diff --git a/examples/messages/messages.go b/examples/messages/messages.go index b3ea87f30..f97474298 100644 --- a/examples/messages/messages.go +++ b/examples/messages/messages.go @@ -8,7 +8,6 @@ import ( func main() { api := slack.New("YOUR_TOKEN_HERE") - params := slack.PostMessageParameters{} attachment := slack.Attachment{ Pretext: "some pretext", Text: "some text", @@ -22,8 +21,8 @@ func main() { }, */ } - params.Attachments = []slack.Attachment{attachment} - channelID, timestamp, err := api.PostMessage("CHANNEL_ID", "Some text", params) + + channelID, timestamp, err := api.PostMessage("CHANNEL_ID", slack.MsgOptionText("Some text", false), slack.MsgOptionAttachments(attachment)) if err != nil { fmt.Printf("%s\n", err) return diff --git a/examples/pins/pins.go b/examples/pins/pins.go index d225184c8..74876f953 100644 --- a/examples/pins/pins.go +++ b/examples/pins/pins.go @@ -20,15 +20,13 @@ func main() { flag.BoolVar(&debug, "debug", false, "Show JSON output") flag.Parse() - api := slack.New(apiToken) - if debug { - api.SetDebug(true) - } + api := slack.New(apiToken, slack.OptionDebug(debug)) var ( postAsUserName string postAsUserID string postToChannelID string + channels []slack.Channel ) // Find the user to post as. @@ -51,8 +49,7 @@ func main() { // 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 { + if channels, err = api.GetChannels(false); err != nil { fmt.Println("Could not retrieve channels") return } @@ -80,8 +77,7 @@ func main() { 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) + channelID, timestamp, err := api.PostMessage(postToChannelID, slack.MsgOptionText("Is this any good?", false)) if err != nil { fmt.Printf("Error posting message: %s\n", err) return @@ -91,7 +87,7 @@ func main() { msgRef := slack.NewRefToMessage(channelID, timestamp) // Add message pin to channel - if err := api.AddPin(channelID, msgRef); err != nil { + if err = api.AddPin(channelID, msgRef); err != nil { fmt.Printf("Error adding pin: %s\n", err) return } diff --git a/examples/reactions/reactions.go b/examples/reactions/reactions.go index 753f0d258..47808ff3a 100644 --- a/examples/reactions/reactions.go +++ b/examples/reactions/reactions.go @@ -17,10 +17,7 @@ func main() { flag.BoolVar(&debug, "debug", false, "Show JSON output") flag.Parse() - api := slack.New(apiToken) - if debug { - api.SetDebug(true) - } + api := slack.New(apiToken, slack.OptionDebug(debug)) var ( postAsUserName string @@ -56,8 +53,7 @@ func main() { 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) + channelID, timestamp, err := api.PostMessage(postToChannelID, slack.MsgOptionText("Is this any good?", false)) if err != nil { fmt.Printf("Error posting message: %s\n", err) return @@ -67,13 +63,13 @@ func main() { msgRef := slack.NewRefToMessage(channelID, timestamp) // React with :+1: - if err := api.AddReaction("+1", msgRef); err != nil { + 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 { + if err = api.AddReaction("cry", msgRef); err != nil { fmt.Printf("Error adding reaction: %s\n", err) return } diff --git a/examples/stars/stars.go b/examples/stars/stars.go index d20c3dcfa..c22fa0853 100644 --- a/examples/stars/stars.go +++ b/examples/stars/stars.go @@ -17,10 +17,7 @@ func main() { flag.BoolVar(&debug, "debug", false, "Show JSON output") flag.Parse() - api := slack.New(apiToken) - if debug { - api.SetDebug(true) - } + api := slack.New(apiToken, slack.OptionDebug(debug)) // Get all stars for the usr. params := slack.NewStarsParameters() diff --git a/examples/websocket/websocket.go b/examples/websocket/websocket.go index c232951a4..9dafefd5d 100644 --- a/examples/websocket/websocket.go +++ b/examples/websocket/websocket.go @@ -9,10 +9,11 @@ import ( ) 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) + api := slack.New( + "YOUR TOKEN HERE", + slack.OptionDebug(true), + slack.OptionLog(log.New(os.Stdout, "slack-bot: ", log.Lshortfile|log.LstdFlags)), + ) rtm := api.NewRTM() go rtm.ManageConnection() diff --git a/files.go b/files.go index 0550c9fb5..13158582d 100644 --- a/files.go +++ b/files.go @@ -137,16 +137,14 @@ func NewGetFilesParameters() GetFilesParameters { } } -func fileRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*fileResponseFull, error) { +func fileRequest(ctx context.Context, client httpClient, path string, values url.Values, d debug) (*fileResponseFull, error) { response := &fileResponseFull{} - err := postForm(ctx, client, SLACK_API+path, values, response, debug) + err := postForm(ctx, client, APIURL+path, values, response, d) if err != nil { return nil, err } - if !response.Ok { - return nil, errors.New(response.Error) - } - return response, nil + + return response, response.Err() } // GetFileInfo retrieves a file and related comments @@ -163,7 +161,7 @@ func (api *Client) GetFileInfoContext(ctx context.Context, fileID string, count, "page": {strconv.Itoa(page)}, } - response, err := fileRequest(ctx, api.httpclient, "files.info", values, api.debug) + response, err := fileRequest(ctx, api.httpclient, "files.info", values, api) if err != nil { return nil, nil, nil, err } @@ -202,7 +200,7 @@ func (api *Client) GetFilesContext(ctx context.Context, params GetFilesParameter values.Add("page", strconv.Itoa(params.Page)) } - response, err := fileRequest(ctx, api.httpclient, "files.list", values, api.debug) + response, err := fileRequest(ctx, api.httpclient, "files.list", values, api) if err != nil { return nil, nil, err } @@ -246,19 +244,17 @@ func (api *Client) UploadFileContext(ctx context.Context, params FileUploadParam } if params.Content != "" { values.Add("content", params.Content) - err = postForm(ctx, api.httpclient, SLACK_API+"files.upload", values, response, api.debug) + err = postForm(ctx, api.httpclient, APIURL+"files.upload", values, response, api) } else if params.File != "" { - err = postLocalWithMultipartResponse(ctx, api.httpclient, "files.upload", params.File, "file", values, response, api.debug) + err = postLocalWithMultipartResponse(ctx, api.httpclient, "files.upload", params.File, "file", values, response, api) } else if params.Reader != nil { - err = postWithMultipartResponse(ctx, api.httpclient, "files.upload", params.Filename, "file", values, params.Reader, response, api.debug) + err = postWithMultipartResponse(ctx, api.httpclient, "files.upload", params.Filename, "file", values, params.Reader, response, api) } if err != nil { return nil, err } - if !response.Ok { - return nil, errors.New(response.Error) - } - return &response.File, nil + + return &response.File, response.Err() } // DeleteFileComment deletes a file's comment @@ -277,7 +273,7 @@ func (api *Client) DeleteFileCommentContext(ctx context.Context, fileID, comment "file": {fileID}, "id": {commentID}, } - _, err = fileRequest(ctx, api.httpclient, "files.comments.delete", values, api.debug) + _, err = fileRequest(ctx, api.httpclient, "files.comments.delete", values, api) return err } @@ -293,7 +289,7 @@ func (api *Client) DeleteFileContext(ctx context.Context, fileID string) (err er "file": {fileID}, } - _, err = fileRequest(ctx, api.httpclient, "files.delete", values, api.debug) + _, err = fileRequest(ctx, api.httpclient, "files.delete", values, api) return err } @@ -309,7 +305,7 @@ func (api *Client) RevokeFilePublicURLContext(ctx context.Context, fileID string "file": {fileID}, } - response, err := fileRequest(ctx, api.httpclient, "files.revokePublicURL", values, api.debug) + response, err := fileRequest(ctx, api.httpclient, "files.revokePublicURL", values, api) if err != nil { return nil, err } @@ -328,7 +324,7 @@ func (api *Client) ShareFilePublicURLContext(ctx context.Context, fileID string) "file": {fileID}, } - response, err := fileRequest(ctx, api.httpclient, "files.sharedPublicURL", values, api.debug) + response, err := fileRequest(ctx, api.httpclient, "files.sharedPublicURL", values, api) if err != nil { return nil, nil, nil, err } diff --git a/files_test.go b/files_test.go index 91d6e8e1f..975e39b86 100644 --- a/files_test.go +++ b/files_test.go @@ -41,7 +41,7 @@ func (h *fileCommentHandler) handler(w http.ResponseWriter, r *http.Request) { func TestSlack_DeleteFileComment(t *testing.T) { once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") tests := []struct { title string @@ -125,7 +125,7 @@ func TestUploadFile(t *testing.T) { http.HandleFunc("/auth.test", authTestHandler) http.HandleFunc("/files.upload", uploadFileHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") params := FileUploadParameters{ Filename: "test.txt", Content: "test content", diff --git a/groups.go b/groups.go index 67e78e993..a248f6fd9 100644 --- a/groups.go +++ b/groups.go @@ -2,7 +2,6 @@ package slack import ( "context" - "errors" "net/url" "strconv" ) @@ -28,16 +27,14 @@ type groupResponseFull struct { SlackResponse } -func groupRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*groupResponseFull, error) { +func groupRequest(ctx context.Context, client httpClient, path string, values url.Values, d debug) (*groupResponseFull, error) { response := &groupResponseFull{} - err := postForm(ctx, client, SLACK_API+path, values, response, debug) + err := postForm(ctx, client, APIURL+path, values, response, d) if err != nil { return nil, err } - if !response.Ok { - return nil, errors.New(response.Error) - } - return response, nil + + return response, response.Err() } // ArchiveGroup archives a private group @@ -52,7 +49,7 @@ func (api *Client) ArchiveGroupContext(ctx context.Context, group string) error "channel": {group}, } - _, err := groupRequest(ctx, api.httpclient, "groups.archive", values, api.debug) + _, err := groupRequest(ctx, api.httpclient, "groups.archive", values, api) return err } @@ -68,7 +65,7 @@ func (api *Client) UnarchiveGroupContext(ctx context.Context, group string) erro "channel": {group}, } - _, err := groupRequest(ctx, api.httpclient, "groups.unarchive", values, api.debug) + _, err := groupRequest(ctx, api.httpclient, "groups.unarchive", values, api) return err } @@ -84,7 +81,7 @@ func (api *Client) CreateGroupContext(ctx context.Context, group string) (*Group "name": {group}, } - response, err := groupRequest(ctx, api.httpclient, "groups.create", values, api.debug) + response, err := groupRequest(ctx, api.httpclient, "groups.create", values, api) if err != nil { return nil, err } @@ -109,7 +106,7 @@ func (api *Client) CreateChildGroupContext(ctx context.Context, group string) (* "channel": {group}, } - response, err := groupRequest(ctx, api.httpclient, "groups.createChild", values, api.debug) + response, err := groupRequest(ctx, api.httpclient, "groups.createChild", values, api) if err != nil { return nil, err } @@ -128,7 +125,7 @@ func (api *Client) CloseGroupContext(ctx context.Context, group string) (bool, b "channel": {group}, } - response, err := imRequest(ctx, api.httpclient, "groups.close", values, api.debug) + response, err := imRequest(ctx, api.httpclient, "groups.close", values, api) if err != nil { return false, false, err } @@ -170,7 +167,7 @@ func (api *Client) GetGroupHistoryContext(ctx context.Context, group string, par } } - response, err := groupRequest(ctx, api.httpclient, "groups.history", values, api.debug) + response, err := groupRequest(ctx, api.httpclient, "groups.history", values, api) if err != nil { return nil, err } @@ -190,7 +187,7 @@ func (api *Client) InviteUserToGroupContext(ctx context.Context, group, user str "user": {user}, } - response, err := groupRequest(ctx, api.httpclient, "groups.invite", values, api.debug) + response, err := groupRequest(ctx, api.httpclient, "groups.invite", values, api) if err != nil { return nil, false, err } @@ -209,7 +206,7 @@ func (api *Client) LeaveGroupContext(ctx context.Context, group string) (err err "channel": {group}, } - _, err = groupRequest(ctx, api.httpclient, "groups.leave", values, api.debug) + _, err = groupRequest(ctx, api.httpclient, "groups.leave", values, api) return err } @@ -226,7 +223,7 @@ func (api *Client) KickUserFromGroupContext(ctx context.Context, group, user str "user": {user}, } - _, err = groupRequest(ctx, api.httpclient, "groups.kick", values, api.debug) + _, err = groupRequest(ctx, api.httpclient, "groups.kick", values, api) return err } @@ -244,7 +241,7 @@ func (api *Client) GetGroupsContext(ctx context.Context, excludeArchived bool) ( values.Add("exclude_archived", "1") } - response, err := groupRequest(ctx, api.httpclient, "groups.list", values, api.debug) + response, err := groupRequest(ctx, api.httpclient, "groups.list", values, api) if err != nil { return nil, err } @@ -263,7 +260,7 @@ func (api *Client) GetGroupInfoContext(ctx context.Context, group string) (*Grou "channel": {group}, } - response, err := groupRequest(ctx, api.httpclient, "groups.info", values, api.debug) + response, err := groupRequest(ctx, api.httpclient, "groups.info", values, api) if err != nil { return nil, err } @@ -288,7 +285,7 @@ func (api *Client) SetGroupReadMarkContext(ctx context.Context, group, ts string "ts": {ts}, } - _, err = groupRequest(ctx, api.httpclient, "groups.mark", values, api.debug) + _, err = groupRequest(ctx, api.httpclient, "groups.mark", values, api) return err } @@ -304,7 +301,7 @@ func (api *Client) OpenGroupContext(ctx context.Context, group string) (bool, bo "channel": {group}, } - response, err := groupRequest(ctx, api.httpclient, "groups.open", values, api.debug) + response, err := groupRequest(ctx, api.httpclient, "groups.open", values, api) if err != nil { return false, false, err } @@ -328,7 +325,7 @@ func (api *Client) RenameGroupContext(ctx context.Context, group, name string) ( // 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 := groupRequest(ctx, api.httpclient, "groups.rename", values, api.debug) + response, err := groupRequest(ctx, api.httpclient, "groups.rename", values, api) if err != nil { return nil, err } @@ -348,7 +345,7 @@ func (api *Client) SetGroupPurposeContext(ctx context.Context, group, purpose st "purpose": {purpose}, } - response, err := groupRequest(ctx, api.httpclient, "groups.setPurpose", values, api.debug) + response, err := groupRequest(ctx, api.httpclient, "groups.setPurpose", values, api) if err != nil { return "", err } @@ -368,7 +365,7 @@ func (api *Client) SetGroupTopicContext(ctx context.Context, group, topic string "topic": {topic}, } - response, err := groupRequest(ctx, api.httpclient, "groups.setTopic", values, api.debug) + response, err := groupRequest(ctx, api.httpclient, "groups.setTopic", values, api) if err != nil { return "", err } diff --git a/im.go b/im.go index fa8b09593..10563d91c 100644 --- a/im.go +++ b/im.go @@ -2,7 +2,6 @@ package slack import ( "context" - "errors" "net/url" "strconv" ) @@ -29,16 +28,14 @@ type IM struct { IsUserDeleted bool `json:"is_user_deleted"` } -func imRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*imResponseFull, error) { +func imRequest(ctx context.Context, client httpClient, path string, values url.Values, d debug) (*imResponseFull, error) { response := &imResponseFull{} - err := postSlackMethod(ctx, client, path, values, response, debug) + err := postSlackMethod(ctx, client, path, values, response, d) if err != nil { return nil, err } - if !response.Ok { - return nil, errors.New(response.Error) - } - return response, nil + + return response, response.Err() } // CloseIMChannel closes the direct message channel @@ -53,7 +50,7 @@ func (api *Client) CloseIMChannelContext(ctx context.Context, channel string) (b "channel": {channel}, } - response, err := imRequest(ctx, api.httpclient, "im.close", values, api.debug) + response, err := imRequest(ctx, api.httpclient, "im.close", values, api) if err != nil { return false, false, err } @@ -74,7 +71,7 @@ func (api *Client) OpenIMChannelContext(ctx context.Context, user string) (bool, "user": {user}, } - response, err := imRequest(ctx, api.httpclient, "im.open", values, api.debug) + response, err := imRequest(ctx, api.httpclient, "im.open", values, api) if err != nil { return false, false, "", err } @@ -94,7 +91,7 @@ func (api *Client) MarkIMChannelContext(ctx context.Context, channel, ts string) "ts": {ts}, } - _, err := imRequest(ctx, api.httpclient, "im.mark", values, api.debug) + _, err := imRequest(ctx, api.httpclient, "im.mark", values, api) return err } @@ -133,7 +130,7 @@ func (api *Client) GetIMHistoryContext(ctx context.Context, channel string, para } } - response, err := imRequest(ctx, api.httpclient, "im.history", values, api.debug) + response, err := imRequest(ctx, api.httpclient, "im.history", values, api) if err != nil { return nil, err } @@ -151,7 +148,7 @@ func (api *Client) GetIMChannelsContext(ctx context.Context) ([]IM, error) { "token": {api.token}, } - response, err := imRequest(ctx, api.httpclient, "im.list", values, api.debug) + response, err := imRequest(ctx, api.httpclient, "im.list", values, api) if err != nil { return nil, err } diff --git a/logger.go b/logger.go index 501d1672d..e494a98f6 100644 --- a/logger.go +++ b/logger.go @@ -2,20 +2,6 @@ package slack import ( "fmt" - "sync" -) - -// 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 logProvider) { - loggerMutex.Lock() - logger = ilogger{logProvider: l} - loggerMutex.Unlock() -} - -var ( - loggerMutex = new(sync.Mutex) - logger logInternal // A logger that can be set by consumers ) // logProvider is a logger interface compatible with both stdlib and some @@ -32,6 +18,15 @@ type logInternal interface { Output(int, string) error } +type debug interface { + Debug() bool + + // Debugf print a formatted debug line. + Debugf(format string, v ...interface{}) + // Debugln print a debug line. + Debugln(v ...interface{}) +} + // ilogger implements the additional methods used by our internal logging. type ilogger struct { logProvider @@ -51,3 +46,15 @@ func (t ilogger) Printf(format string, v ...interface{}) { func (t ilogger) Print(v ...interface{}) { t.Output(2, fmt.Sprint(v...)) } + +type discard struct{} + +func (t discard) Debug() bool { + return false +} + +// Debugf print a formatted debug line. +func (t discard) Debugf(format string, v ...interface{}) {} + +// Debugln print a debug line. +func (t discard) Debugln(v ...interface{}) {} diff --git a/misc.go b/misc.go index 691033849..cf89ecb25 100644 --- a/misc.go +++ b/misc.go @@ -90,21 +90,20 @@ func fileUploadReq(ctx context.Context, path, fieldname, filename string, values return req, nil } -func parseResponseBody(body io.ReadCloser, intf interface{}, debug bool) error { +func parseResponseBody(body io.ReadCloser, intf interface{}, d debug) error { response, err := ioutil.ReadAll(body) if err != nil { return err } - // FIXME: will be api.Debugf - if debug { - logger.Printf("parseResponseBody: %s\n", string(response)) + if d.Debug() { + d.Debugln("parseResponseBody", string(response)) } return json.Unmarshal(response, intf) } -func postLocalWithMultipartResponse(ctx context.Context, client HTTPRequester, path, fpath, fieldname string, values url.Values, intf interface{}, debug bool) error { +func postLocalWithMultipartResponse(ctx context.Context, client httpClient, path, fpath, fieldname string, values url.Values, intf interface{}, d debug) error { fullpath, err := filepath.Abs(fpath) if err != nil { return err @@ -114,11 +113,11 @@ func postLocalWithMultipartResponse(ctx context.Context, client HTTPRequester, p return err } defer file.Close() - return postWithMultipartResponse(ctx, client, path, filepath.Base(fpath), fieldname, values, file, intf, debug) + return postWithMultipartResponse(ctx, client, path, filepath.Base(fpath), fieldname, values, file, intf, d) } -func postWithMultipartResponse(ctx context.Context, client HTTPRequester, path, name, fieldname string, values url.Values, r io.Reader, intf interface{}, debug bool) error { - req, err := fileUploadReq(ctx, SLACK_API+path, fieldname, name, values, r) +func postWithMultipartResponse(ctx context.Context, client httpClient, path, name, fieldname string, values url.Values, r io.Reader, intf interface{}, d debug) error { + req, err := fileUploadReq(ctx, APIURL+path, fieldname, name, values, r) if err != nil { return err } @@ -139,14 +138,14 @@ func postWithMultipartResponse(ctx context.Context, client HTTPRequester, path, // Slack seems to send an HTML body along with 5xx error codes. Don't parse it. if resp.StatusCode != http.StatusOK { - logResponse(resp, debug) + logResponse(resp, d) return statusCodeError{Code: resp.StatusCode, Status: resp.Status} } - return parseResponseBody(resp.Body, intf, debug) + return parseResponseBody(resp.Body, intf, d) } -func doPost(ctx context.Context, client HTTPRequester, req *http.Request, intf interface{}, debug bool) error { +func doPost(ctx context.Context, client httpClient, req *http.Request, intf interface{}, d debug) error { req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { @@ -164,15 +163,15 @@ func doPost(ctx context.Context, client HTTPRequester, req *http.Request, intf i // Slack seems to send an HTML body along with 5xx error codes. Don't parse it. if resp.StatusCode != http.StatusOK { - logResponse(resp, debug) + logResponse(resp, d) return statusCodeError{Code: resp.StatusCode, Status: resp.Status} } - return parseResponseBody(resp.Body, intf, debug) + return parseResponseBody(resp.Body, intf, d) } // post JSON. -func postJSON(ctx context.Context, client HTTPRequester, endpoint, token string, json []byte, intf interface{}, debug bool) error { +func postJSON(ctx context.Context, client httpClient, endpoint, token string, json []byte, intf interface{}, d debug) error { reqBody := bytes.NewBuffer(json) req, err := http.NewRequest("POST", endpoint, reqBody) if err != nil { @@ -180,38 +179,37 @@ func postJSON(ctx context.Context, client HTTPRequester, endpoint, token string, } req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token)) - return doPost(ctx, client, req, intf, debug) + return doPost(ctx, client, req, intf, d) } // post a url encoded form. -func postForm(ctx context.Context, client HTTPRequester, endpoint string, values url.Values, intf interface{}, debug bool) error { +func postForm(ctx context.Context, client httpClient, endpoint string, values url.Values, intf interface{}, d debug) error { reqBody := strings.NewReader(values.Encode()) req, err := http.NewRequest("POST", endpoint, reqBody) if err != nil { return err } req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - return doPost(ctx, client, req, intf, debug) + return doPost(ctx, client, req, intf, d) } // post to a slack web method. -func postSlackMethod(ctx context.Context, client HTTPRequester, path string, values url.Values, intf interface{}, debug bool) error { - return postForm(ctx, client, SLACK_API+path, values, intf, debug) +func postSlackMethod(ctx context.Context, client httpClient, path string, values url.Values, intf interface{}, d debug) error { + return postForm(ctx, client, APIURL+path, values, intf, d) } -func parseAdminResponse(ctx context.Context, client HTTPRequester, method string, teamName string, values url.Values, intf interface{}, debug bool) error { - endpoint := fmt.Sprintf(SLACK_WEB_API_FORMAT, teamName, method, time.Now().Unix()) - return postForm(ctx, client, endpoint, values, intf, debug) +func parseAdminResponse(ctx context.Context, client httpClient, method string, teamName string, values url.Values, intf interface{}, d debug) error { + endpoint := fmt.Sprintf(WEBAPIURLFormat, teamName, method, time.Now().Unix()) + return postForm(ctx, client, endpoint, values, intf, d) } -func logResponse(resp *http.Response, debug bool) error { - if debug { +func logResponse(resp *http.Response, d debug) error { + if d.Debug() { text, err := httputil.DumpResponse(resp, true) if err != nil { return err } - - logger.Print(string(text)) + d.Debugln(string(text)) } return nil diff --git a/misc_test.go b/misc_test.go index 68ddf6c8a..d0ea4d2ca 100644 --- a/misc_test.go +++ b/misc_test.go @@ -36,12 +36,12 @@ func setParseResponseHandler() { func TestParseResponse(t *testing.T) { parseResponseOnce.Do(setParseResponseHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" values := url.Values{ "token": {validToken}, } responsePartial := &SlackResponse{} - err := postSlackMethod(context.Background(), http.DefaultClient, "parseResponse", values, responsePartial, false) + err := postSlackMethod(context.Background(), http.DefaultClient, "parseResponse", values, responsePartial, discard{}) if err != nil { t.Errorf("Unexpected error: %s", err) } @@ -50,10 +50,10 @@ func TestParseResponse(t *testing.T) { func TestParseResponseNoToken(t *testing.T) { parseResponseOnce.Do(setParseResponseHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" values := url.Values{} responsePartial := &SlackResponse{} - err := postSlackMethod(context.Background(), http.DefaultClient, "parseResponse", values, responsePartial, false) + err := postSlackMethod(context.Background(), http.DefaultClient, "parseResponse", values, responsePartial, discard{}) if err != nil { t.Errorf("Unexpected error: %s", err) return @@ -68,12 +68,12 @@ func TestParseResponseNoToken(t *testing.T) { func TestParseResponseInvalidToken(t *testing.T) { parseResponseOnce.Do(setParseResponseHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" values := url.Values{ "token": {"whatever"}, } responsePartial := &SlackResponse{} - err := postSlackMethod(context.Background(), http.DefaultClient, "parseResponse", values, responsePartial, false) + err := postSlackMethod(context.Background(), http.DefaultClient, "parseResponse", values, responsePartial, discard{}) if err != nil { t.Errorf("Unexpected error: %s", err) return diff --git a/oauth.go b/oauth.go index 378af4a54..904012188 100644 --- a/oauth.go +++ b/oauth.go @@ -6,6 +6,7 @@ import ( "net/url" ) +// OAuthResponseIncomingWebhook ... type OAuthResponseIncomingWebhook struct { URL string `json:"url"` Channel string `json:"channel"` @@ -13,11 +14,13 @@ type OAuthResponseIncomingWebhook struct { ConfigurationURL string `json:"configuration_url"` } +// OAuthResponseBot ... type OAuthResponseBot struct { BotUserID string `json:"bot_user_id"` BotAccessToken string `json:"bot_access_token"` } +// OAuthResponse ... type OAuthResponse struct { AccessToken string `json:"access_token"` Scope string `json:"scope"` @@ -30,24 +33,24 @@ type OAuthResponse struct { } // GetOAuthToken retrieves an AccessToken -func GetOAuthToken(clientID, clientSecret, code, redirectURI string, debug bool) (accessToken string, scope string, err error) { - return GetOAuthTokenContext(context.Background(), clientID, clientSecret, code, redirectURI, debug) +func GetOAuthToken(client httpClient, clientID, clientSecret, code, redirectURI string, d debug) (accessToken string, scope string, err error) { + return GetOAuthTokenContext(context.Background(), client, clientID, clientSecret, code, redirectURI, d) } // GetOAuthTokenContext retrieves an AccessToken with a custom context -func GetOAuthTokenContext(ctx context.Context, clientID, clientSecret, code, redirectURI string, debug bool) (accessToken string, scope string, err error) { - response, err := GetOAuthResponseContext(ctx, clientID, clientSecret, code, redirectURI, debug) +func GetOAuthTokenContext(ctx context.Context, client httpClient, clientID, clientSecret, code, redirectURI string, d debug) (accessToken string, scope string, err error) { + response, err := GetOAuthResponseContext(ctx, client, clientID, clientSecret, code, redirectURI, d) if err != nil { return "", "", err } return response.AccessToken, response.Scope, nil } -func GetOAuthResponse(clientID, clientSecret, code, redirectURI string, debug bool) (resp *OAuthResponse, err error) { - return GetOAuthResponseContext(context.Background(), clientID, clientSecret, code, redirectURI, debug) +func GetOAuthResponse(client httpClient, clientID, clientSecret, code, redirectURI string, d debug) (resp *OAuthResponse, err error) { + return GetOAuthResponseContext(context.Background(), client, clientID, clientSecret, code, redirectURI, d) } -func GetOAuthResponseContext(ctx context.Context, clientID, clientSecret, code, redirectURI string, debug bool) (resp *OAuthResponse, err error) { +func GetOAuthResponseContext(ctx context.Context, client httpClient, clientID, clientSecret, code, redirectURI string, d debug) (resp *OAuthResponse, err error) { values := url.Values{ "client_id": {clientID}, "client_secret": {clientSecret}, @@ -55,7 +58,7 @@ func GetOAuthResponseContext(ctx context.Context, clientID, clientSecret, code, "redirect_uri": {redirectURI}, } response := &OAuthResponse{} - err = postSlackMethod(ctx, customHTTPClient, "oauth.access", values, response, debug) + err = postSlackMethod(ctx, client, "oauth.access", values, response, d) if err != nil { return nil, err } diff --git a/pins.go b/pins.go index 34863f17b..c1d525df2 100644 --- a/pins.go +++ b/pins.go @@ -34,7 +34,7 @@ func (api *Client) AddPinContext(ctx context.Context, channel string, item ItemR } response := &SlackResponse{} - if err := postSlackMethod(ctx, api.httpclient, "pins.add", values, response, api.debug); err != nil { + if err := postSlackMethod(ctx, api.httpclient, "pins.add", values, response, api); err != nil { return err } @@ -63,7 +63,7 @@ func (api *Client) RemovePinContext(ctx context.Context, channel string, item It } response := &SlackResponse{} - if err := postSlackMethod(ctx, api.httpclient, "pins.remove", values, response, api.debug); err != nil { + if err := postSlackMethod(ctx, api.httpclient, "pins.remove", values, response, api); err != nil { return err } @@ -83,7 +83,7 @@ func (api *Client) ListPinsContext(ctx context.Context, channel string) ([]Item, } response := &listPinsResponseFull{} - err := postSlackMethod(ctx, api.httpclient, "pins.list", values, response, api.debug) + err := postSlackMethod(ctx, api.httpclient, "pins.list", values, response, api) if err != nil { return nil, nil, err } diff --git a/pins_test.go b/pins_test.go index 80f25b01b..a64eafb84 100644 --- a/pins_test.go +++ b/pins_test.go @@ -38,7 +38,7 @@ func (rh *pinsHandler) handler(w http.ResponseWriter, r *http.Request) { func TestSlack_AddPin(t *testing.T) { once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") tests := []struct { channel string @@ -86,7 +86,7 @@ func TestSlack_AddPin(t *testing.T) { func TestSlack_RemovePin(t *testing.T) { once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") tests := []struct { channel string @@ -134,7 +134,7 @@ func TestSlack_RemovePin(t *testing.T) { func TestSlack_ListPins(t *testing.T) { once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") rh := newPinsHandler() http.HandleFunc("/pins.list", func(w http.ResponseWriter, r *http.Request) { rh.handler(w, r) }) diff --git a/reactions.go b/reactions.go index 5eabde637..abe1e72ad 100644 --- a/reactions.go +++ b/reactions.go @@ -155,7 +155,7 @@ func (api *Client) AddReactionContext(ctx context.Context, name string, item Ite } response := &SlackResponse{} - if err := postSlackMethod(ctx, api.httpclient, "reactions.add", values, response, api.debug); err != nil { + if err := postSlackMethod(ctx, api.httpclient, "reactions.add", values, response, api); err != nil { return err } @@ -189,7 +189,7 @@ func (api *Client) RemoveReactionContext(ctx context.Context, name string, item } response := &SlackResponse{} - if err := postSlackMethod(ctx, api.httpclient, "reactions.remove", values, response, api.debug); err != nil { + if err := postSlackMethod(ctx, api.httpclient, "reactions.remove", values, response, api); err != nil { return err } @@ -223,7 +223,7 @@ func (api *Client) GetReactionsContext(ctx context.Context, item ItemRef, params } response := &getReactionsResponseFull{} - if err := postSlackMethod(ctx, api.httpclient, "reactions.get", values, response, api.debug); err != nil { + if err := postSlackMethod(ctx, api.httpclient, "reactions.get", values, response, api); err != nil { return nil, err } if !response.Ok { @@ -256,7 +256,7 @@ func (api *Client) ListReactionsContext(ctx context.Context, params ListReaction } response := &listReactionsResponseFull{} - err := postSlackMethod(ctx, api.httpclient, "reactions.list", values, response, api.debug) + err := postSlackMethod(ctx, api.httpclient, "reactions.list", values, response, api) if err != nil { return nil, nil, err } diff --git a/reactions_test.go b/reactions_test.go index f032696cd..0a4a54373 100644 --- a/reactions_test.go +++ b/reactions_test.go @@ -41,7 +41,7 @@ func (rh *reactionsHandler) handler(w http.ResponseWriter, r *http.Request) { func TestSlack_AddReaction(t *testing.T) { once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") tests := []struct { name string @@ -90,7 +90,7 @@ func TestSlack_AddReaction(t *testing.T) { func TestSlack_RemoveReaction(t *testing.T) { once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") tests := []struct { name string @@ -139,7 +139,7 @@ func TestSlack_RemoveReaction(t *testing.T) { func TestSlack_GetReactions(t *testing.T) { once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") tests := []struct { ref ItemRef @@ -254,7 +254,7 @@ func TestSlack_GetReactions(t *testing.T) { func TestSlack_ListReactions(t *testing.T) { once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") rh := newReactionsHandler() http.HandleFunc("/reactions.list", func(w http.ResponseWriter, r *http.Request) { rh.handler(w, r) }) diff --git a/rtm.go b/rtm.go index 41a136ebb..2aea30f7e 100644 --- a/rtm.go +++ b/rtm.go @@ -38,7 +38,7 @@ func (api *Client) StartRTM() (info *Info, websocketURL string, err error) { // To have a fully managed Websocket connection, use `NewRTM`, and call `ManageConnection()` on it. func (api *Client) StartRTMContext(ctx context.Context) (info *Info, websocketURL string, err error) { response := &infoResponseFull{} - err = postSlackMethod(ctx, api.httpclient, "rtm.start", url.Values{"token": {api.token}}, response, api.debug) + err = postSlackMethod(ctx, api.httpclient, "rtm.start", url.Values{"token": {api.token}}, response, api) if err != nil { return nil, "", err } @@ -63,7 +63,7 @@ func (api *Client) ConnectRTM() (info *Info, websocketURL string, err error) { // To have a fully managed Websocket connection, use `NewRTM`, and call `ManageConnection()` on it. func (api *Client) ConnectRTMContext(ctx context.Context) (info *Info, websocketURL string, err error) { response := &infoResponseFull{} - err = postSlackMethod(ctx, api.httpclient, "rtm.connect", url.Values{"token": {api.token}}, response, api.debug) + err = postSlackMethod(ctx, api.httpclient, "rtm.connect", url.Values{"token": {api.token}}, response, api) if err != nil { api.Debugf("Failed to connect to RTM: %s", err) return nil, "", err @@ -105,12 +105,12 @@ func RTMOptionPingInterval(d time.Duration) RTMOption { func (api *Client) NewRTM(options ...RTMOption) *RTM { result := &RTM{ Client: *api, + wasIntentional: true, + isConnected: false, IncomingEvents: make(chan RTMEvent, 50), outgoingMessages: make(chan OutgoingMessage, 20), pingInterval: defaultPingInterval, pingDeadman: time.NewTimer(deadmanDuration(defaultPingInterval)), - isConnected: false, - wasIntentional: true, killChannel: make(chan bool), disconnected: make(chan struct{}, 1), forcePing: make(chan bool), @@ -125,14 +125,3 @@ func (api *Client) NewRTM(options ...RTMOption) *RTM { return result } - -// NewRTMWithOptions Deprecated just use NewRTM(RTMOptionsUseStart(true)) -// returns a RTM, which provides a fully managed connection to -// Slack's websocket-based Real-Time Messaging protocol. -// This also allows to configure various options available for RTM API. -func (api *Client) NewRTMWithOptions(options *RTMOptions) *RTM { - if options != nil { - return api.NewRTM(RTMOptionUseStart(options.UseRTMStart)) - } - return api.NewRTM() -} diff --git a/search.go b/search.go index e858952f4..2d018fcc6 100644 --- a/search.go +++ b/search.go @@ -2,7 +2,6 @@ package slack import ( "context" - "errors" "net/url" "strconv" ) @@ -104,14 +103,12 @@ func (api *Client) _search(ctx context.Context, path, query string, params Searc } response = &searchResponseFull{} - err := postSlackMethod(ctx, api.httpclient, path, values, response, api.debug) + err := postSlackMethod(ctx, api.httpclient, path, values, response, api) if err != nil { return nil, err } - if !response.Ok { - return nil, errors.New(response.Error) - } - return response, nil + + return response, response.Err() } diff --git a/slack.go b/slack.go index 6d1e7de9c..f80bf1572 100644 --- a/slack.go +++ b/slack.go @@ -2,7 +2,6 @@ package slack import ( "context" - "errors" "fmt" "log" "net/http" @@ -10,31 +9,17 @@ import ( "os" ) -// Added as a var so that we can change this for testing purposes -var SLACK_API string = "https://slack.com/api/" -var SLACK_WEB_API_FORMAT string = "https://%s.slack.com/api/users.admin.%s?t=%s" +// APIURL a dded as a var so that we can change this for testing purposes +var APIURL = "https://slack.com/api/" -// HTTPClient sets a custom http.Client -// deprecated: in favor of SetHTTPClient() -var HTTPClient = &http.Client{} +// WEBAPIURLFormat ... +var WEBAPIURLFormat = "https://%s.slack.com/api/users.admin.%s?t=%s" -var customHTTPClient HTTPRequester = HTTPClient - -// HTTPRequester defines the minimal interface needed for an http.Client to be implemented. -// -// Use it in conjunction with the SetHTTPClient function to allow for other capabilities -// like a tracing http.Client -type HTTPRequester interface { +// httpClient defines the minimal interface needed for an http.Client to be implemented. +type httpClient interface { Do(*http.Request) (*http.Response, error) } -// SetHTTPClient allows you to specify a custom http.Client -// Use this instead of the package level HTTPClient variable if you want to use a custom client like the -// Stackdriver Trace HTTPClient https://godoc.org/cloud.google.com/go/trace#HTTPClient -func SetHTTPClient(client HTTPRequester) { - customHTTPClient = client -} - // ResponseMetadata holds pagination metadata type ResponseMetadata struct { Cursor string `json:"next_cursor"` @@ -48,6 +33,7 @@ func (t *ResponseMetadata) initialize() *ResponseMetadata { return &ResponseMetadata{} } +// AuthTestResponse ... type AuthTestResponse struct { URL string `json:"url"` Team string `json:"team"` @@ -61,20 +47,36 @@ type authTestResponseFull struct { AuthTestResponse } +// Client for the slack api. type Client struct { token string info Info debug bool - httpclient HTTPRequester + log logInternal + httpclient httpClient } // Option defines an option for a Client type Option func(*Client) // OptionHTTPClient - provide a custom http client to the slack client. -func OptionHTTPClient(c HTTPRequester) func(*Client) { - return func(s *Client) { - s.httpclient = c +func OptionHTTPClient(client httpClient) func(*Client) { + return func(c *Client) { + c.httpclient = client + } +} + +// OptionDebug enable debugging for the client +func OptionDebug(b bool) func(*Client) { + return func(c *Client) { + c.debug = b + } +} + +// OptionLog set logging for client. +func OptionLog(l logProvider) func(*Client) { + return func(c *Client) { + c.log = ilogger{logProvider: l} } } @@ -82,7 +84,8 @@ func OptionHTTPClient(c HTTPRequester) func(*Client) { func New(token string, options ...Option) *Client { s := &Client{ token: token, - httpclient: customHTTPClient, + httpclient: &http.Client{}, + log: log.New(os.Stdout, "nlopes/slack", log.LstdFlags|log.Lshortfile), } for _, opt := range options { @@ -98,43 +101,32 @@ func (api *Client) AuthTest() (response *AuthTestResponse, error error) { } // AuthTestContext tests if the user is able to do authenticated requests or not with a custom context -func (api *Client) AuthTestContext(ctx context.Context) (response *AuthTestResponse, error error) { +func (api *Client) AuthTestContext(ctx context.Context) (response *AuthTestResponse, err error) { api.Debugf("Challenging auth...") responseFull := &authTestResponseFull{} - err := postSlackMethod(ctx, api.httpclient, "auth.test", url.Values{"token": {api.token}}, responseFull, api.debug) + err = postSlackMethod(ctx, api.httpclient, "auth.test", url.Values{"token": {api.token}}, responseFull, api) if err != nil { - api.Debugf("failed to test for auth: %s", err) return nil, err } - if !responseFull.Ok { - api.Debugf("auth response was not Ok: %s", responseFull.Error) - return nil, errors.New(responseFull.Error) - } - api.Debugf("Auth challenge was successful with response %+v", responseFull.AuthTestResponse) - return &responseFull.AuthTestResponse, nil -} - -// SetDebug switches the api into debug mode -// When in debug mode, it logs various info about what its doing -// If you ever use this in production, don't call SetDebug(true) -func (api *Client) SetDebug(debug bool) { - api.debug = debug - if debug && logger == nil { - SetLogger(log.New(os.Stdout, "nlopes/slack", log.LstdFlags|log.Lshortfile)) - } + return &responseFull.AuthTestResponse, responseFull.Err() } // Debugf print a formatted debug line. func (api *Client) Debugf(format string, v ...interface{}) { if api.debug { - logger.Output(2, fmt.Sprintf(format, v...)) + api.log.Output(2, fmt.Sprintf(format, v...)) } } // Debugln print a debug line. func (api *Client) Debugln(v ...interface{}) { if api.debug { - logger.Output(2, fmt.Sprintln(v...)) + api.log.Output(2, fmt.Sprintln(v...)) } } + +// Debug returns if debug is enabled. +func (api *Client) Debug() bool { + return api.debug +} diff --git a/stars.go b/stars.go index c1e2f6cb7..7e1e621d1 100644 --- a/stars.go +++ b/stars.go @@ -58,7 +58,7 @@ func (api *Client) AddStarContext(ctx context.Context, channel string, item Item } response := &SlackResponse{} - if err := postSlackMethod(ctx, api.httpclient, "stars.add", values, response, api.debug); err != nil { + if err := postSlackMethod(ctx, api.httpclient, "stars.add", values, response, api); err != nil { return err } @@ -87,7 +87,7 @@ func (api *Client) RemoveStarContext(ctx context.Context, channel string, item I } response := &SlackResponse{} - if err := postSlackMethod(ctx, api.httpclient, "stars.remove", values, response, api.debug); err != nil { + if err := postSlackMethod(ctx, api.httpclient, "stars.remove", values, response, api); err != nil { return err } @@ -115,7 +115,7 @@ func (api *Client) ListStarsContext(ctx context.Context, params StarsParameters) } response := &listResponseFull{} - err := postSlackMethod(ctx, api.httpclient, "stars.list", values, response, api.debug) + err := postSlackMethod(ctx, api.httpclient, "stars.list", values, response, api) if err != nil { return nil, nil, err } diff --git a/stars_test.go b/stars_test.go index 65696b9ae..a4803850d 100644 --- a/stars_test.go +++ b/stars_test.go @@ -39,7 +39,7 @@ func (sh *starsHandler) handler(w http.ResponseWriter, r *http.Request) { func TestSlack_AddStar(t *testing.T) { once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") tests := []struct { channel string @@ -87,7 +87,7 @@ func TestSlack_AddStar(t *testing.T) { func TestSlack_RemoveStar(t *testing.T) { once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") tests := []struct { channel string @@ -135,7 +135,7 @@ func TestSlack_RemoveStar(t *testing.T) { func TestSlack_ListStars(t *testing.T) { once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") rh := newStarsHandler() http.HandleFunc("/stars.list", func(w http.ResponseWriter, r *http.Request) { rh.handler(w, r) }) diff --git a/team.go b/team.go index b6e341ebf..1892cf5f8 100644 --- a/team.go +++ b/team.go @@ -2,7 +2,6 @@ package slack import ( "context" - "errors" "net/url" "strconv" ) @@ -67,44 +66,33 @@ func NewAccessLogParameters() AccessLogParameters { } } -func teamRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*TeamResponse, error) { +func teamRequest(ctx context.Context, client httpClient, path string, values url.Values, d debug) (*TeamResponse, error) { response := &TeamResponse{} - err := postSlackMethod(ctx, client, path, values, response, debug) + err := postSlackMethod(ctx, client, path, values, response, d) if err != nil { return nil, err } - if !response.Ok { - return nil, errors.New(response.Error) - } - - return response, nil + return response, response.Err() } -func billableInfoRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (map[string]BillingActive, error) { +func billableInfoRequest(ctx context.Context, client httpClient, path string, values url.Values, d debug) (map[string]BillingActive, error) { response := &BillableInfoResponse{} - err := postSlackMethod(ctx, client, path, values, response, debug) + err := postSlackMethod(ctx, client, path, values, response, d) if err != nil { return nil, err } - if !response.Ok { - return nil, errors.New(response.Error) - } - - return response.BillableInfo, nil + return response.BillableInfo, response.Err() } -func accessLogsRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*LoginResponse, error) { +func accessLogsRequest(ctx context.Context, client httpClient, path string, values url.Values, d debug) (*LoginResponse, error) { response := &LoginResponse{} - err := postSlackMethod(ctx, client, path, values, response, debug) + err := postSlackMethod(ctx, client, path, values, response, d) if err != nil { return nil, err } - if !response.Ok { - return nil, errors.New(response.Error) - } - return response, nil + return response, response.Err() } // GetTeamInfo gets the Team Information of the user @@ -118,7 +106,7 @@ func (api *Client) GetTeamInfoContext(ctx context.Context) (*TeamInfo, error) { "token": {api.token}, } - response, err := teamRequest(ctx, api.httpclient, "team.info", values, api.debug) + response, err := teamRequest(ctx, api.httpclient, "team.info", values, api) if err != nil { return nil, err } @@ -142,7 +130,7 @@ func (api *Client) GetAccessLogsContext(ctx context.Context, params AccessLogPar values.Add("page", strconv.Itoa(params.Page)) } - response, err := accessLogsRequest(ctx, api.httpclient, "team.accessLogs", values, api.debug) + response, err := accessLogsRequest(ctx, api.httpclient, "team.accessLogs", values, api) if err != nil { return nil, nil, err } @@ -159,7 +147,7 @@ func (api *Client) GetBillableInfoContext(ctx context.Context, user string) (map "user": {user}, } - return billableInfoRequest(ctx, api.httpclient, "team.billableInfo", values, api.debug) + return billableInfoRequest(ctx, api.httpclient, "team.billableInfo", values, api) } // GetBillableInfoForTeam returns the billing_active status of all users on the team. @@ -173,5 +161,5 @@ func (api *Client) GetBillableInfoForTeamContext(ctx context.Context) (map[strin "token": {api.token}, } - return billableInfoRequest(ctx, api.httpclient, "team.billableInfo", values, api.debug) + return billableInfoRequest(ctx, api.httpclient, "team.billableInfo", values, api) } diff --git a/team_test.go b/team_test.go index 94ea10bc9..3497c383c 100644 --- a/team_test.go +++ b/team_test.go @@ -31,7 +31,7 @@ func TestGetTeamInfo(t *testing.T) { http.HandleFunc("/team.info", getTeamInfo) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") teamInfo, err := api.GetTeamInfo() @@ -95,7 +95,7 @@ func TestGetAccessLogs(t *testing.T) { http.HandleFunc("/team.accessLogs", getTeamAccessLogs) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") logins, paging, err := api.GetAccessLogs(NewAccessLogParameters()) diff --git a/usergroups.go b/usergroups.go index cc9bc4ca7..9e1452725 100644 --- a/usergroups.go +++ b/usergroups.go @@ -2,7 +2,6 @@ package slack import ( "context" - "errors" "net/url" "strings" ) @@ -41,16 +40,14 @@ type userGroupResponseFull struct { SlackResponse } -func userGroupRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*userGroupResponseFull, error) { +func userGroupRequest(ctx context.Context, client httpClient, path string, values url.Values, d debug) (*userGroupResponseFull, error) { response := &userGroupResponseFull{} - err := postSlackMethod(ctx, client, path, values, response, debug) + err := postSlackMethod(ctx, client, path, values, response, d) if err != nil { return nil, err } - if !response.Ok { - return nil, errors.New(response.Error) - } - return response, nil + + return response, response.Err() } // CreateUserGroup creates a new user group @@ -77,7 +74,7 @@ func (api *Client) CreateUserGroupContext(ctx context.Context, userGroup UserGro values["channels"] = []string{strings.Join(userGroup.Prefs.Channels, ",")} } - response, err := userGroupRequest(ctx, api.httpclient, "usergroups.create", values, api.debug) + response, err := userGroupRequest(ctx, api.httpclient, "usergroups.create", values, api) if err != nil { return UserGroup{}, err } @@ -96,7 +93,7 @@ func (api *Client) DisableUserGroupContext(ctx context.Context, userGroup string "usergroup": {userGroup}, } - response, err := userGroupRequest(ctx, api.httpclient, "usergroups.disable", values, api.debug) + response, err := userGroupRequest(ctx, api.httpclient, "usergroups.disable", values, api) if err != nil { return UserGroup{}, err } @@ -115,7 +112,7 @@ func (api *Client) EnableUserGroupContext(ctx context.Context, userGroup string) "usergroup": {userGroup}, } - response, err := userGroupRequest(ctx, api.httpclient, "usergroups.enable", values, api.debug) + response, err := userGroupRequest(ctx, api.httpclient, "usergroups.enable", values, api) if err != nil { return UserGroup{}, err } @@ -179,7 +176,7 @@ func (api *Client) GetUserGroupsContext(ctx context.Context, options ...GetUserG values.Add("include_users", "true") } - response, err := userGroupRequest(ctx, api.httpclient, "usergroups.list", values, api.debug) + response, err := userGroupRequest(ctx, api.httpclient, "usergroups.list", values, api) if err != nil { return nil, err } @@ -210,7 +207,7 @@ func (api *Client) UpdateUserGroupContext(ctx context.Context, userGroup UserGro values["description"] = []string{userGroup.Description} } - response, err := userGroupRequest(ctx, api.httpclient, "usergroups.update", values, api.debug) + response, err := userGroupRequest(ctx, api.httpclient, "usergroups.update", values, api) if err != nil { return UserGroup{}, err } @@ -229,7 +226,7 @@ func (api *Client) GetUserGroupMembersContext(ctx context.Context, userGroup str "usergroup": {userGroup}, } - response, err := userGroupRequest(ctx, api.httpclient, "usergroups.users.list", values, api.debug) + response, err := userGroupRequest(ctx, api.httpclient, "usergroups.users.list", values, api) if err != nil { return []string{}, err } @@ -249,7 +246,7 @@ func (api *Client) UpdateUserGroupMembersContext(ctx context.Context, userGroup "users": {members}, } - response, err := userGroupRequest(ctx, api.httpclient, "usergroups.users.update", values, api.debug) + response, err := userGroupRequest(ctx, api.httpclient, "usergroups.users.update", values, api) if err != nil { return UserGroup{}, err } diff --git a/usergroups_test.go b/usergroups_test.go index ba3b97f18..7f3ab6bf8 100644 --- a/usergroups_test.go +++ b/usergroups_test.go @@ -61,7 +61,7 @@ func (ugh *userGroupsHandler) handler(w http.ResponseWriter, r *http.Request) { func TestCreateUserGroup(t *testing.T) { once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") tests := []struct { @@ -142,7 +142,7 @@ func TestGetUserGroups(t *testing.T) { http.HandleFunc("/usergroups.list", getUserGroups) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") userGroups, err := api.GetUserGroups(GetUserGroupsOptionIncludeUsers(true)) diff --git a/users.go b/users.go index 0dd20db57..aa941a740 100644 --- a/users.go +++ b/users.go @@ -189,16 +189,14 @@ func NewUserSetPhotoParams() UserSetPhotoParams { } } -func userRequest(ctx context.Context, client HTTPRequester, path string, values url.Values, debug bool) (*userResponseFull, error) { +func userRequest(ctx context.Context, client httpClient, path string, values url.Values, d debug) (*userResponseFull, error) { response := &userResponseFull{} - err := postForm(ctx, client, SLACK_API+path, values, response, debug) + err := postForm(ctx, client, APIURL+path, values, response, d) if err != nil { return nil, err } - if !response.Ok { - return nil, errors.New(response.Error) - } - return response, nil + + return response, response.Err() } // GetUserPresence will retrieve the current presence status of given user. @@ -213,7 +211,7 @@ func (api *Client) GetUserPresenceContext(ctx context.Context, user string) (*Us "user": {user}, } - response, err := userRequest(ctx, api.httpclient, "users.getPresence", values, api.debug) + response, err := userRequest(ctx, api.httpclient, "users.getPresence", values, api) if err != nil { return nil, err } @@ -232,7 +230,7 @@ func (api *Client) GetUserInfoContext(ctx context.Context, user string) (*User, "user": {user}, } - response, err := userRequest(ctx, api.httpclient, "users.info", values, api.debug) + response, err := userRequest(ctx, api.httpclient, "users.info", values, api) if err != nil { return nil, err } @@ -310,7 +308,7 @@ func (t UserPagination) Next(ctx context.Context) (_ UserPagination, err error) "cursor": {t.previousResp.Cursor}, } - if resp, err = userRequest(ctx, t.c.httpclient, "users.list", values, t.c.debug); err != nil { + if resp, err = userRequest(ctx, t.c.httpclient, "users.list", values, t.c); err != nil { return t, err } @@ -355,7 +353,7 @@ func (api *Client) GetUserByEmailContext(ctx context.Context, email string) (*Us "token": {api.token}, "email": {email}, } - response, err := userRequest(ctx, api.httpclient, "users.lookupByEmail", values, api.debug) + response, err := userRequest(ctx, api.httpclient, "users.lookupByEmail", values, api) if err != nil { return nil, err } @@ -373,7 +371,7 @@ func (api *Client) SetUserAsActiveContext(ctx context.Context) (err error) { "token": {api.token}, } - _, err = userRequest(ctx, api.httpclient, "users.setActive", values, api.debug) + _, err = userRequest(ctx, api.httpclient, "users.setActive", values, api) return err } @@ -389,7 +387,7 @@ func (api *Client) SetUserPresenceContext(ctx context.Context, presence string) "presence": {presence}, } - _, err := userRequest(ctx, api.httpclient, "users.setPresence", values, api.debug) + _, err := userRequest(ctx, api.httpclient, "users.setPresence", values, api) return err } @@ -405,7 +403,7 @@ func (api *Client) GetUserIdentityContext(ctx context.Context) (*UserIdentityRes } response := &UserIdentityResponse{} - err := postForm(ctx, api.httpclient, SLACK_API+"users.identity", values, response, api.debug) + err := postForm(ctx, api.httpclient, APIURL+"users.identity", values, response, api) if err != nil { return nil, err } @@ -436,7 +434,7 @@ func (api *Client) SetUserPhotoContext(ctx context.Context, image string, params values.Add("crop_w", strconv.Itoa(params.CropW)) } - err := postLocalWithMultipartResponse(ctx, api.httpclient, "users.setPhoto", image, "image", values, response, api.debug) + err := postLocalWithMultipartResponse(ctx, api.httpclient, "users.setPhoto", image, "image", values, response, api) if err != nil { return err } @@ -456,7 +454,7 @@ func (api *Client) DeleteUserPhotoContext(ctx context.Context) error { "token": {api.token}, } - err := postForm(ctx, api.httpclient, SLACK_API+"users.deletePhoto", values, response, api.debug) + err := postForm(ctx, api.httpclient, APIURL+"users.deletePhoto", values, response, api) if err != nil { return err } @@ -506,7 +504,7 @@ func (api *Client) SetUserCustomStatusContext(ctx context.Context, statusText, s } response := &userResponseFull{} - if err = postForm(ctx, api.httpclient, SLACK_API+"users.profile.set", values, response, api.debug); err != nil { + if err = postForm(ctx, api.httpclient, APIURL+"users.profile.set", values, response, api); err != nil { return err } @@ -547,7 +545,7 @@ func (api *Client) GetUserProfileContext(ctx context.Context, userID string, inc } resp := &getUserProfileResponse{} - err := postSlackMethod(ctx, api.httpclient, "users.profile.get", values, &resp, api.debug) + err := postSlackMethod(ctx, api.httpclient, "users.profile.get", values, &resp, api) if err != nil { return nil, err } diff --git a/users_test.go b/users_test.go index 50dbdc679..701614061 100644 --- a/users_test.go +++ b/users_test.go @@ -170,7 +170,7 @@ func TestGetUserIdentity(t *testing.T) { http.HandleFunc("/users.identity", getUserIdentity) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") identity, err := api.GetUserIdentity() @@ -211,7 +211,7 @@ func TestGetUserByEmail(t *testing.T) { expectedUser := getTestUser() once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") user, err := api.GetUserByEmail("test@test.com") @@ -232,7 +232,7 @@ func TestUserCustomStatus(t *testing.T) { http.HandleFunc("/users.profile.set", setUserProfile) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") testSetUserCustomStatus(api, up, t) @@ -277,7 +277,7 @@ func TestGetUsers(t *testing.T) { expectedUser := getTestUser() once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") users, err := api.GetUsers() @@ -329,7 +329,7 @@ func TestSetUserPhoto(t *testing.T) { http.HandleFunc("/users.setPhoto", setUserPhotoHandler(fileContent, params)) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New(validToken) err := api.SetUserPhoto(file.Name(), params) @@ -436,7 +436,7 @@ func getUserProfileHandler(rw http.ResponseWriter, r *http.Request) { func TestGetUserProfile(t *testing.T) { http.HandleFunc("/users.profile.get", getUserProfileHandler) once.Do(startServer) - SLACK_API = "http://" + serverAddr + "/" + APIURL = "http://" + serverAddr + "/" api := New("testing-token") profile, err := api.GetUserProfile("UXXXXXXXX", false) if err != nil { diff --git a/websocket.go b/websocket.go index 242acf40e..b5c2b09fa 100644 --- a/websocket.go +++ b/websocket.go @@ -20,6 +20,9 @@ const ( // // Create this element with Client's NewRTM() or NewRTMWithOptions(*RTMOptions) type RTM struct { + // Client is the main API, embedded + Client + idGen IDGenerator pingInterval time.Duration pingDeadman *time.Timer @@ -35,8 +38,6 @@ type RTM struct { wasIntentional bool isConnected bool - // Client is the main API, embedded - Client websocketURL string // UserDetails upon connection @@ -55,18 +56,6 @@ type RTM struct { mu *sync.Mutex } -// RTMOptions allows configuration of various options available for RTM messaging -// -// This structure will evolve in time so please make sure you are always using the -// named keys for every entry available as per Go 1 compatibility promise adding fields -// to this structure should not be considered a breaking change. -type RTMOptions struct { - // UseRTMStart set to true in order to use rtm.start or false to use rtm.connect - // As of 11th July 2017 you should prefer setting this to false, see: - // https://api.slack.com/changelog/2017-04-start-using-rtm-connect-and-stop-using-rtm-start - UseRTMStart bool -} - // Disconnect and wait, blocking until a successful disconnection. func (rtm *RTM) Disconnect() error { // avoid RTM disconnect race conditions diff --git a/websocket_managed_conn.go b/websocket_managed_conn.go index e8ab65a1e..9e71956b3 100644 --- a/websocket_managed_conn.go +++ b/websocket_managed_conn.go @@ -405,8 +405,7 @@ func (rtm *RTM) handlePong(event json.RawMessage) { rtm.resetDeadman() if err := json.Unmarshal(event, &p); err != nil { - logger.Println("RTM Error unmarshalling 'pong' event:", err) - rtm.Debugln(" -> Erroneous 'ping' event:", string(event)) + rtm.Client.log.Println("RTM Error unmarshalling 'pong' event:", err) return } @@ -423,8 +422,8 @@ func (rtm *RTM) handlePong(event json.RawMessage) { func (rtm *RTM) handleEvent(typeStr string, event json.RawMessage) { v, exists := EventMapping[typeStr] if !exists { - rtm.Debugf("RTM Error, received unmapped event %q: %s\n", typeStr, string(event)) - err := fmt.Errorf("RTM Error: Received unmapped event %q: %s\n", typeStr, string(event)) + rtm.Debugf("RTM Error - received unmapped event %q: %s\n", typeStr, string(event)) + err := fmt.Errorf("RTM Error: Received unmapped event %q: %s", typeStr, string(event)) rtm.IncomingEvents <- RTMEvent{"unmarshalling_error", &UnmarshallingErrorEvent{err}} return } @@ -433,7 +432,7 @@ func (rtm *RTM) handleEvent(typeStr string, event json.RawMessage) { err := json.Unmarshal(event, recvEvent) if err != nil { rtm.Debugf("RTM Error, could not unmarshall event %q: %s\n", typeStr, string(event)) - err := fmt.Errorf("RTM Error: Could not unmarshall event %q: %s\n", typeStr, string(event)) + err := fmt.Errorf("RTM Error: Could not unmarshall event %q: %s", typeStr, string(event)) rtm.IncomingEvents <- RTMEvent{"unmarshalling_error", &UnmarshallingErrorEvent{err}} return } diff --git a/websocket_managed_conn_test.go b/websocket_managed_conn_test.go index 83e40dade..31fbedd45 100644 --- a/websocket_managed_conn_test.go +++ b/websocket_managed_conn_test.go @@ -19,7 +19,7 @@ func TestRTMSingleConnect(t *testing.T) { go testServer.Start() // Setup and start the RTM. - slack.SLACK_API = testServer.GetAPIURL() + slack.APIURL = testServer.GetAPIURL() api := slack.New(testToken) rtm := api.NewRTM(slack.RTMOptionUseStart(true)) go rtm.ManageConnection()