diff options
Diffstat (limited to 'vendor/github.com/nlopes/slack/chat.go')
-rw-r--r-- | vendor/github.com/nlopes/slack/chat.go | 301 |
1 files changed, 225 insertions, 76 deletions
diff --git a/vendor/github.com/nlopes/slack/chat.go b/vendor/github.com/nlopes/slack/chat.go index fc909a86..9a2c4453 100644 --- a/vendor/github.com/nlopes/slack/chat.go +++ b/vendor/github.com/nlopes/slack/chat.go @@ -1,6 +1,7 @@ package slack import ( + "context" "encoding/json" "errors" "net/url" @@ -62,30 +63,92 @@ func NewPostMessageParameters() PostMessageParameters { } } -func chatRequest(path string, values url.Values, debug bool) (*chatResponseFull, error) { - response := &chatResponseFull{} - err := post(path, values, response, debug) +// DeleteMessage deletes a message in a channel +func (api *Client) DeleteMessage(channel, messageTimestamp string) (string, string, error) { + respChannel, respTimestamp, _, err := api.SendMessageContext(context.Background(), channel, MsgOptionDelete(messageTimestamp)) + return respChannel, respTimestamp, err +} + +// DeleteMessageContext deletes a message in a channel with a custom context +func (api *Client) DeleteMessageContext(ctx context.Context, channel, messageTimestamp string) (string, string, error) { + respChannel, respTimestamp, _, err := api.SendMessageContext(ctx, channel, MsgOptionDelete(messageTimestamp)) + return respChannel, respTimestamp, err +} + +// 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) { + respChannel, respTimestamp, _, err := api.SendMessageContext( + context.Background(), + channel, + MsgOptionText(text, params.EscapeText), + MsgOptionAttachments(params.Attachments...), + MsgOptionPostMessageParameters(params), + ) + 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) { + respChannel, respTimestamp, _, err := api.SendMessageContext( + ctx, + channel, + MsgOptionText(text, params.EscapeText), + MsgOptionAttachments(params.Attachments...), + MsgOptionPostMessageParameters(params), + ) + return respChannel, respTimestamp, err +} + +// UpdateMessage updates a message in a channel +func (api *Client) UpdateMessage(channel, timestamp, text string) (string, string, string, error) { + return api.UpdateMessageContext(context.Background(), channel, timestamp, text) +} + +// UpdateMessage updates a message in a channel +func (api *Client) UpdateMessageContext(ctx context.Context, channel, timestamp, text string) (string, string, string, error) { + return api.SendMessageContext(ctx, channel, MsgOptionUpdate(timestamp), MsgOptionText(text, true)) +} + +// SendMessage more flexible method for configuring messages. +func (api *Client) SendMessage(channel string, options ...MsgOption) (string, string, string, error) { + return api.SendMessageContext(context.Background(), channel, options...) +} + +// SendMessageContext more flexible method for configuring messages with a custom context. +func (api *Client) SendMessageContext(ctx context.Context, channel string, options ...MsgOption) (string, string, string, error) { + channel, values, err := ApplyMsgOptions(api.config.token, channel, options...) if err != nil { - return nil, err + return "", "", "", err } - if !response.Ok { - return nil, errors.New(response.Error) + + response, err := chatRequest(ctx, channel, values, api.debug) + if err != nil { + return "", "", "", err } - return response, nil + + return response.Channel, response.Timestamp, response.Text, nil } -// DeleteMessage deletes a message in a channel -func (api *Client) DeleteMessage(channel, messageTimestamp string) (string, string, error) { - values := url.Values{ - "token": {api.config.token}, - "channel": {channel}, - "ts": {messageTimestamp}, +// ApplyMsgOptions utility function for debugging/testing chat requests. +func ApplyMsgOptions(token, channel string, options ...MsgOption) (string, url.Values, error) { + config := sendConfig{ + mode: chatPostMessage, + values: url.Values{ + "token": {token}, + "channel": {channel}, + }, } - response, err := chatRequest("chat.delete", values, api.debug) - if err != nil { - return "", "", err + + for _, opt := range options { + if err := opt(&config); err != nil { + return string(config.mode), config.values, err + } } - return response.Channel, response.Timestamp, nil + + return string(config.mode), config.values, nil } func escapeMessage(message string) string { @@ -93,79 +156,165 @@ func escapeMessage(message string) string { return replacer.Replace(message) } -// 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) { - if params.EscapeText { - text = escapeMessage(text) - } - values := url.Values{ - "token": {api.config.token}, - "channel": {channel}, - "text": {text}, +func chatRequest(ctx context.Context, path string, values url.Values, debug bool) (*chatResponseFull, error) { + response := &chatResponseFull{} + err := post(ctx, path, values, response, debug) + if err != nil { + return nil, err } - if params.Username != DEFAULT_MESSAGE_USERNAME { - values.Set("username", string(params.Username)) + if !response.Ok { + return nil, errors.New(response.Error) } - if params.AsUser != DEFAULT_MESSAGE_ASUSER { - values.Set("as_user", "true") + return response, nil +} + +type sendMode string + +const ( + chatUpdate sendMode = "chat.update" + chatPostMessage sendMode = "chat.postMessage" + chatDelete sendMode = "chat.delete" +) + +type sendConfig struct { + mode sendMode + values url.Values +} + +// MsgOption option provided when sending a message. +type MsgOption func(*sendConfig) error + +// MsgOptionPost posts a messages, this is the default. +func MsgOptionPost() MsgOption { + return func(config *sendConfig) error { + config.mode = chatPostMessage + config.values.Del("ts") + return nil } - if params.Parse != DEFAULT_MESSAGE_PARSE { - values.Set("parse", string(params.Parse)) +} + +// MsgOptionUpdate updates a message based on the timestamp. +func MsgOptionUpdate(timestamp string) MsgOption { + return func(config *sendConfig) error { + config.mode = chatUpdate + config.values.Add("ts", timestamp) + return nil } - if params.LinkNames != DEFAULT_MESSAGE_LINK_NAMES { - values.Set("link_names", "1") +} + +// MsgOptionDelete deletes a message based on the timestamp. +func MsgOptionDelete(timestamp string) MsgOption { + return func(config *sendConfig) error { + config.mode = chatDelete + config.values.Add("ts", timestamp) + return nil } - if params.Attachments != nil { - attachments, err := json.Marshal(params.Attachments) - if err != nil { - return "", "", err +} + +// MsgOptionAsUser whether or not to send the message as the user. +func MsgOptionAsUser(b bool) MsgOption { + return func(config *sendConfig) error { + if b != DEFAULT_MESSAGE_ASUSER { + config.values.Set("as_user", "true") } - values.Set("attachments", string(attachments)) + return nil } - if params.UnfurlLinks != DEFAULT_MESSAGE_UNFURL_LINKS { - values.Set("unfurl_links", "true") - } - // I want to send a message with explicit `as_user` `true` and `unfurl_links` `false` in request. - // Because setting `as_user` to `true` will change the default value for `unfurl_links` to `true` on Slack API side. - if params.AsUser != DEFAULT_MESSAGE_ASUSER && params.UnfurlLinks == DEFAULT_MESSAGE_UNFURL_LINKS { - values.Set("unfurl_links", "false") - } - if params.UnfurlMedia != DEFAULT_MESSAGE_UNFURL_MEDIA { - values.Set("unfurl_media", "false") - } - if params.IconURL != DEFAULT_MESSAGE_ICON_URL { - values.Set("icon_url", params.IconURL) - } - if params.IconEmoji != DEFAULT_MESSAGE_ICON_EMOJI { - values.Set("icon_emoji", params.IconEmoji) +} + +// MsgOptionText provide the text for the message, optionally escape the provided +// text. +func MsgOptionText(text string, escape bool) MsgOption { + return func(config *sendConfig) error { + if escape { + text = escapeMessage(text) + } + config.values.Add("text", text) + return nil } - if params.Markdown != DEFAULT_MESSAGE_MARKDOWN { - values.Set("mrkdwn", "false") +} + +// MsgOptionAttachments provide attachments for the message. +func MsgOptionAttachments(attachments ...Attachment) MsgOption { + return func(config *sendConfig) error { + if attachments == nil { + return nil + } + + attachments, err := json.Marshal(attachments) + if err == nil { + config.values.Set("attachments", string(attachments)) + } + return err } - if params.ThreadTimestamp != DEFAULT_MESSAGE_THREAD_TIMESTAMP { - values.Set("thread_ts", params.ThreadTimestamp) +} + +// MsgOptionEnableLinkUnfurl enables link unfurling +func MsgOptionEnableLinkUnfurl() MsgOption { + return func(config *sendConfig) error { + config.values.Set("unfurl_links", "true") + return nil } +} - response, err := chatRequest("chat.postMessage", values, api.debug) - if err != nil { - return "", "", err +// MsgOptionDisableMediaUnfurl disables media unfurling. +func MsgOptionDisableMediaUnfurl() MsgOption { + return func(config *sendConfig) error { + config.values.Set("unfurl_media", "false") + return nil } - return response.Channel, response.Timestamp, nil } -// UpdateMessage updates a message in a channel -func (api *Client) UpdateMessage(channel, timestamp, text string) (string, string, string, error) { - values := url.Values{ - "token": {api.config.token}, - "channel": {channel}, - "text": {escapeMessage(text)}, - "ts": {timestamp}, +// MsgOptionDisableMarkdown disables markdown. +func MsgOptionDisableMarkdown() MsgOption { + return func(config *sendConfig) error { + config.values.Set("mrkdwn", "false") + return nil } - response, err := chatRequest("chat.update", values, api.debug) - if err != nil { - return "", "", "", err +} + +// MsgOptionPostMessageParameters maintain backwards compatibility. +func MsgOptionPostMessageParameters(params PostMessageParameters) MsgOption { + return func(config *sendConfig) error { + if params.Username != DEFAULT_MESSAGE_USERNAME { + config.values.Set("username", string(params.Username)) + } + + // never generates an error. + MsgOptionAsUser(params.AsUser)(config) + + if params.Parse != DEFAULT_MESSAGE_PARSE { + config.values.Set("parse", string(params.Parse)) + } + if params.LinkNames != DEFAULT_MESSAGE_LINK_NAMES { + config.values.Set("link_names", "1") + } + + if params.UnfurlLinks != DEFAULT_MESSAGE_UNFURL_LINKS { + config.values.Set("unfurl_links", "true") + } + + // I want to send a message with explicit `as_user` `true` and `unfurl_links` `false` in request. + // Because setting `as_user` to `true` will change the default value for `unfurl_links` to `true` on Slack API side. + if params.AsUser != DEFAULT_MESSAGE_ASUSER && params.UnfurlLinks == DEFAULT_MESSAGE_UNFURL_LINKS { + config.values.Set("unfurl_links", "false") + } + if params.UnfurlMedia != DEFAULT_MESSAGE_UNFURL_MEDIA { + config.values.Set("unfurl_media", "false") + } + if params.IconURL != DEFAULT_MESSAGE_ICON_URL { + config.values.Set("icon_url", params.IconURL) + } + if params.IconEmoji != DEFAULT_MESSAGE_ICON_EMOJI { + config.values.Set("icon_emoji", params.IconEmoji) + } + if params.Markdown != DEFAULT_MESSAGE_MARKDOWN { + config.values.Set("mrkdwn", "false") + } + + if params.ThreadTimestamp != DEFAULT_MESSAGE_THREAD_TIMESTAMP { + config.values.Set("thread_ts", params.ThreadTimestamp) + } + + return nil } - return response.Channel, response.Timestamp, response.Text, nil } |