summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/nlopes/slack
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/nlopes/slack')
-rw-r--r--vendor/github.com/nlopes/slack/CHANGELOG.md12
-rw-r--r--vendor/github.com/nlopes/slack/Gopkg.lock8
-rw-r--r--vendor/github.com/nlopes/slack/Gopkg.toml17
-rw-r--r--vendor/github.com/nlopes/slack/chat.go50
-rw-r--r--vendor/github.com/nlopes/slack/conversation.go44
-rw-r--r--vendor/github.com/nlopes/slack/dialog.go104
-rw-r--r--vendor/github.com/nlopes/slack/dialog_select.go125
-rw-r--r--vendor/github.com/nlopes/slack/dialog_text.go50
-rw-r--r--vendor/github.com/nlopes/slack/files.go20
-rw-r--r--vendor/github.com/nlopes/slack/security.go47
-rw-r--r--vendor/github.com/nlopes/slack/slackutilsx/slackutilsx.go57
-rw-r--r--vendor/github.com/nlopes/slack/usergroups.go53
-rw-r--r--vendor/github.com/nlopes/slack/webhooks.go11
-rw-r--r--vendor/github.com/nlopes/slack/websocket_managed_conn.go5
-rw-r--r--vendor/github.com/nlopes/slack/websocket_subteam.go35
15 files changed, 554 insertions, 84 deletions
diff --git a/vendor/github.com/nlopes/slack/CHANGELOG.md b/vendor/github.com/nlopes/slack/CHANGELOG.md
index a79ea50c..cf0fc2cc 100644
--- a/vendor/github.com/nlopes/slack/CHANGELOG.md
+++ b/vendor/github.com/nlopes/slack/CHANGELOG.md
@@ -1,3 +1,15 @@
+### v0.4.0 - October 06, 2018
+full differences can be viewed using `git log --oneline --decorate --color v0.3.0..v0.4.0`
+- Breaking Change: renamed ApplyMessageOption, to mark it as unsafe,
+this means it may break without warning in the future.
+- Breaking: Msg structure files field changed to an array.
+- General: implementation for new security headers.
+- RTM: deadlock fix between connect/disconnect.
+- Events: various new fields added.
+- Web: various fixes, new fields exposed, new methods added.
+- Interactions: minor additions expect breaking changes in next release for dialogs/button clicks.
+- Utils: new methods added.
+
### v0.3.0 - July 30, 2018
full differences can be viewed using `git log --oneline --decorate --color v0.2.0..v0.3.0`
- slack events initial support added. (still considered experimental and undergoing changes, stability not promised)
diff --git a/vendor/github.com/nlopes/slack/Gopkg.lock b/vendor/github.com/nlopes/slack/Gopkg.lock
index 5cc0520e..9c33d0dc 100644
--- a/vendor/github.com/nlopes/slack/Gopkg.lock
+++ b/vendor/github.com/nlopes/slack/Gopkg.lock
@@ -14,6 +14,12 @@
version = "v1.2.0"
[[projects]]
+ name = "github.com/pkg/errors"
+ packages = ["."]
+ revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
+ version = "v0.8.0"
+
+[[projects]]
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
@@ -28,6 +34,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
- inputs-digest = "888307bf47ee004aaaa4c45e6139929b4984f2253e48e382246bfb8c66f3cd65"
+ inputs-digest = "596fa546322c2a1e9708a10c9f39aca2e04792b477fab86fb2899fbaab776070"
solver-name = "gps-cdcl"
solver-version = 1
diff --git a/vendor/github.com/nlopes/slack/Gopkg.toml b/vendor/github.com/nlopes/slack/Gopkg.toml
new file mode 100644
index 00000000..257870d6
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/Gopkg.toml
@@ -0,0 +1,17 @@
+ignored = ["github.com/lusis/slack-test"]
+
+[[constraint]]
+ name = "github.com/gorilla/websocket"
+ version = "1.2.0"
+
+[[constraint]]
+ name = "github.com/stretchr/testify"
+ version = "1.2.1"
+
+[[constraint]]
+ name = "github.com/pkg/errors"
+ version = "0.8.0"
+
+[prune]
+ go-tests = true
+ unused-packages = true
diff --git a/vendor/github.com/nlopes/slack/chat.go b/vendor/github.com/nlopes/slack/chat.go
index 2b89a44c..8cc6bdef 100644
--- a/vendor/github.com/nlopes/slack/chat.go
+++ b/vendor/github.com/nlopes/slack/chat.go
@@ -4,7 +4,8 @@ import (
"context"
"encoding/json"
"net/url"
- "strings"
+
+ "github.com/nlopes/slack/slackutilsx"
)
const (
@@ -164,22 +165,24 @@ func (api *Client) SendMessageContext(ctx context.Context, channelID string, opt
return "", "", "", err
}
- if err = postSlackMethod(ctx, api.httpclient, string(config.mode), config.values, &response, api.debug); err != nil {
+ if err = postForm(ctx, api.httpclient, config.endpoint, config.values, &response, api.debug); err != nil {
return "", "", "", err
}
return response.Channel, response.getMessageTimestamp(), response.Text, response.Err()
}
-// ApplyMsgOptions utility function for debugging/testing chat requests.
-func ApplyMsgOptions(token, channel string, options ...MsgOption) (string, url.Values, error) {
+// UnsafeApplyMsgOptions utility function for debugging/testing chat requests.
+// NOTE: USE AT YOUR OWN RISK: No issues relating to the use of this function
+// will be supported by the library.
+func UnsafeApplyMsgOptions(token, channel string, options ...MsgOption) (string, url.Values, error) {
config, err := applyMsgOptions(token, channel, options...)
- return string(config.mode), config.values, err
+ return config.endpoint, config.values, err
}
func applyMsgOptions(token, channel string, options ...MsgOption) (sendConfig, error) {
config := sendConfig{
- mode: chatPostMessage,
+ endpoint: SLACK_API + string(chatPostMessage),
values: url.Values{
"token": {token},
"channel": {channel},
@@ -195,11 +198,6 @@ func applyMsgOptions(token, channel string, options ...MsgOption) (sendConfig, e
return config, nil
}
-func escapeMessage(message string) string {
- replacer := strings.NewReplacer("&", "&amp;", "<", "&lt;", ">", "&gt;")
- return replacer.Replace(message)
-}
-
type sendMode string
const (
@@ -211,8 +209,8 @@ const (
)
type sendConfig struct {
- mode sendMode
- values url.Values
+ endpoint string
+ values url.Values
}
// MsgOption option provided when sending a message.
@@ -221,7 +219,7 @@ 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.endpoint = SLACK_API + string(chatPostMessage)
config.values.Del("ts")
return nil
}
@@ -231,7 +229,7 @@ func MsgOptionPost() MsgOption {
// posts an ephemeral message.
func MsgOptionPostEphemeral() MsgOption {
return func(config *sendConfig) error {
- config.mode = chatPostEphemeral
+ config.endpoint = SLACK_API + string(chatPostEphemeral)
config.values.Del("ts")
return nil
}
@@ -240,7 +238,7 @@ func MsgOptionPostEphemeral() MsgOption {
// MsgOptionPostEphemeral2 - posts an ephemeral message to the provided user.
func MsgOptionPostEphemeral2(userID string) MsgOption {
return func(config *sendConfig) error {
- config.mode = chatPostEphemeral
+ config.endpoint = SLACK_API + string(chatPostEphemeral)
MsgOptionUser(userID)(config)
config.values.Del("ts")
@@ -251,7 +249,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.mode = chatMeMessage
+ config.endpoint = SLACK_API + string(chatMeMessage)
return nil
}
}
@@ -259,7 +257,7 @@ func MsgOptionMeMessage() MsgOption {
// MsgOptionUpdate updates a message based on the timestamp.
func MsgOptionUpdate(timestamp string) MsgOption {
return func(config *sendConfig) error {
- config.mode = chatUpdate
+ config.endpoint = SLACK_API + string(chatUpdate)
config.values.Add("ts", timestamp)
return nil
}
@@ -268,7 +266,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.mode = chatDelete
+ config.endpoint = SLACK_API + string(chatDelete)
config.values.Add("ts", timestamp)
return nil
}
@@ -297,7 +295,7 @@ func MsgOptionUser(userID string) MsgOption {
func MsgOptionText(text string, escape bool) MsgOption {
return func(config *sendConfig) error {
if escape {
- text = escapeMessage(text)
+ text = slackutilsx.EscapeMessage(text)
}
config.values.Add("text", text)
return nil
@@ -392,6 +390,18 @@ func MsgOptionParse(b bool) MsgOption {
}
}
+// UnsafeMsgOptionEndpoint deliver the message to the specified endpoint.
+// NOTE: USE AT YOUR OWN RISK: No issues relating to the use of this Option
+// will be supported by the library, it is subject to change without notice that
+// may result in compilation errors or runtime behaviour changes.
+func UnsafeMsgOptionEndpoint(endpoint string, update func(url.Values)) MsgOption {
+ return func(config *sendConfig) error {
+ config.endpoint = endpoint
+ update(config.values)
+ return nil
+ }
+}
+
// MsgOptionPostMessageParameters maintain backwards compatibility.
func MsgOptionPostMessageParameters(params PostMessageParameters) MsgOption {
return func(config *sendConfig) error {
diff --git a/vendor/github.com/nlopes/slack/conversation.go b/vendor/github.com/nlopes/slack/conversation.go
index edde87a2..1c64116e 100644
--- a/vendor/github.com/nlopes/slack/conversation.go
+++ b/vendor/github.com/nlopes/slack/conversation.go
@@ -29,6 +29,8 @@ type conversation struct {
NameNormalized string `json:"name_normalized"`
NumMembers int `json:"num_members"`
Priority float64 `json:"priority"`
+ User string `json:"user"`
+
// TODO support pending_shared
// TODO support previous_names
}
@@ -64,6 +66,13 @@ type GetUsersInConversationParameters struct {
Limit int
}
+type GetConversationsForUserParameters struct {
+ UserID string
+ Cursor string
+ Types []string
+ Limit int
+}
+
type responseMetaData struct {
NextCursor string `json:"next_cursor"`
}
@@ -100,6 +109,41 @@ func (api *Client) GetUsersInConversationContext(ctx context.Context, params *Ge
return response.Members, response.ResponseMetaData.NextCursor, nil
}
+// GetConversationsForUser returns the list conversations for a given user
+func (api *Client) GetConversationsForUser(params *GetConversationsForUserParameters) (channels []Channel, nextCursor string, err error) {
+ return api.GetConversationsForUserContext(context.Background(), params)
+}
+
+// GetConversationsForUserContext returns the list conversations for a given user with a custom context
+func (api *Client) GetConversationsForUserContext(ctx context.Context, params *GetConversationsForUserParameters) (channels []Channel, nextCursor string, err error) {
+ values := url.Values{
+ "token": {api.token},
+ "user": {params.UserID},
+ }
+ if params.Cursor != "" {
+ values.Add("cursor", params.Cursor)
+ }
+ if params.Limit != 0 {
+ values.Add("limit", strconv.Itoa(params.Limit))
+ }
+ if params.Types != nil {
+ values.Add("types", strings.Join(params.Types, ","))
+ }
+ response := struct {
+ Channels []Channel `json:"channels"`
+ ResponseMetaData responseMetaData `json:"response_metadata"`
+ SlackResponse
+ }{}
+ err = postSlackMethod(ctx, api.httpclient, "users.conversations", values, &response, api.debug)
+ if err != nil {
+ return nil, "", err
+ }
+ if !response.Ok {
+ return nil, "", errors.New(response.Error)
+ }
+ return response.Channels, response.ResponseMetaData.NextCursor, nil
+}
+
// ArchiveConversation archives a conversation
func (api *Client) ArchiveConversation(channelID string) error {
return api.ArchiveConversationContext(context.Background(), channelID)
diff --git a/vendor/github.com/nlopes/slack/dialog.go b/vendor/github.com/nlopes/slack/dialog.go
index a13e53da..d1435d54 100644
--- a/vendor/github.com/nlopes/slack/dialog.go
+++ b/vendor/github.com/nlopes/slack/dialog.go
@@ -6,52 +6,47 @@ import (
"errors"
)
+// InputType is the type of the dialog input type
+type InputType string
+
+const (
+ // InputTypeText textfield input
+ InputTypeText InputType = "text"
+ // InputTypeTextArea textarea input
+ InputTypeTextArea InputType = "textarea"
+ // InputTypeSelect textfield input
+ InputTypeSelect InputType = "select"
+)
+
+// DialogInput for dialogs input type text or menu
+type DialogInput struct {
+ Type InputType `json:"type"`
+ Label string `json:"label"`
+ Name string `json:"name"`
+ Placeholder string `json:"placeholder"`
+ Optional bool `json:"optional"`
+}
+
+// DialogTrigger ...
type DialogTrigger struct {
- TriggerId string `json:"trigger_id"` //Required. Must respond within 3 seconds.
+ TriggerID string `json:"trigger_id"` //Required. Must respond within 3 seconds.
Dialog Dialog `json:"dialog"` //Required.
}
+// Dialog as in Slack dialogs
+// https://api.slack.com/dialogs#option_element_attributes#top-level_dialog_attributes
type Dialog struct {
- CallbackId string `json:"callback_id"` //Required.
- Title string `json:"title"` //Required.
- SubmitLabel string `json:"submit_label,omitempty"` //Optional. Default value is 'Submit'
- NotifyOnCancel bool `json:"notify_on_cancel,omitempty"` //Optional. Default value is false
- Elements []DialogElement `json:"elements"` //Required.
+ TriggerID string `json:"trigger_id"` //Required
+ CallbackID string `json:"callback_id"` //Required
+ Title string `json:"title"`
+ SubmitLabel string `json:"submit_label,omitempty"`
+ NotifyOnCancel bool `json:"notify_on_cancel"`
+ Elements []DialogElement `json:"elements"`
}
+// DialogElement abstract type for dialogs.
type DialogElement interface{}
-type DialogTextElement struct {
- Label string `json:"label"` //Required.
- Name string `json:"name"` //Required.
- Type string `json:"type"` //Required. Allowed values: "text", "textarea", "select".
- Placeholder string `json:"placeholder,omitempty"` //Optional.
- Optional bool `json:"optional,omitempty"` //Optional. Default value is false
- Value string `json:"value,omitempty"` //Optional.
- MaxLength int `json:"max_length,omitempty"` //Optional.
- MinLength int `json:"min_length,omitempty"` //Optional,. Default value is 0
- Hint string `json:"hint,omitempty"` //Optional.
- Subtype string `json:"subtype,omitempty"` //Optional. Allowed values: "email", "number", "tel", "url".
-}
-
-type DialogSelectElement struct {
- Label string `json:"label"` //Required.
- Name string `json:"name"` //Required.
- Type string `json:"type"` //Required. Allowed values: "text", "textarea", "select".
- Placeholder string `json:"placeholder,omitempty"` //Optional.
- Optional bool `json:"optional,omitempty"` //Optional. Default value is false
- Value string `json:"value,omitempty"` //Optional.
- DataSource string `json:"data_source,omitempty"` //Optional. Allowed values: "users", "channels", "conversations", "external".
- SelectedOptions string `json:"selected_options,omitempty"` //Optional. Default value for "external" only
- Options []DialogElementOption `json:"options,omitempty"` //One of options or option_groups is required.
- OptionGroups []DialogElementOption `json:"option_groups,omitempty"` //Provide up to 100 options.
-}
-
-type DialogElementOption struct {
- Label string `json:"label"` //Required.
- Value string `json:"value"` //Required.
-}
-
// DialogCallback is sent from Slack when a user submits a form from within a dialog
type DialogCallback struct {
Type string `json:"type"`
@@ -78,28 +73,43 @@ type DialogSuggestionCallback struct {
CallbackID string `json:"callback_id"`
}
-// OpenDialog opens a dialog window where the triggerId originated from
-func (api *Client) OpenDialog(triggerId string, dialog Dialog) (err error) {
- return api.OpenDialogContext(context.Background(), triggerId, dialog)
+// DialogOpenResponse response from `dialog.open`
+type DialogOpenResponse struct {
+ SlackResponse
+ DialogResponseMetadata DialogResponseMetadata `json:"response_metadata"`
+}
+
+// DialogResponseMetadata lists the error messages
+type DialogResponseMetadata struct {
+ Messages []string `json:"messages"`
+}
+
+// OpenDialog opens a dialog window where the triggerID originated from.
+// EXPERIMENTAL: dialog functionality is currently experimental, api is not considered stable.
+func (api *Client) OpenDialog(triggerID string, dialog Dialog) (err error) {
+ return api.OpenDialogContext(context.Background(), triggerID, dialog)
}
// OpenDialogContext opens a dialog window where the triggerId originated from with a custom context
-func (api *Client) OpenDialogContext(ctx context.Context, triggerId string, dialog Dialog) (err error) {
- if triggerId == "" {
+// EXPERIMENTAL: dialog functionality is currently experimental, api is not considered stable.
+func (api *Client) OpenDialogContext(ctx context.Context, triggerID string, dialog Dialog) (err error) {
+ if triggerID == "" {
return errors.New("received empty parameters")
}
- resp := DialogTrigger{
- TriggerId: triggerId,
+ req := DialogTrigger{
+ TriggerID: triggerID,
Dialog: dialog,
}
- jsonResp, err := json.Marshal(resp)
+
+ encoded, err := json.Marshal(req)
if err != nil {
return err
}
- response := &SlackResponse{}
+
+ response := &DialogOpenResponse{}
endpoint := SLACK_API + "dialog.open"
- if err := postJSON(ctx, api.httpclient, endpoint, api.token, jsonResp, response, api.debug); err != nil {
+ if err := postJSON(ctx, api.httpclient, endpoint, api.token, encoded, response, api.debug); err != nil {
return err
}
diff --git a/vendor/github.com/nlopes/slack/dialog_select.go b/vendor/github.com/nlopes/slack/dialog_select.go
new file mode 100644
index 00000000..cff35479
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/dialog_select.go
@@ -0,0 +1,125 @@
+package slack
+
+// SelectDataSource types of select datasource
+type SelectDataSource string
+
+const (
+ // DialogDataSourceStatic menu with static Options/OptionGroups
+ DialogDataSourceStatic SelectDataSource = "static"
+ // DialogDataSourceExternal dynamic datasource
+ DialogDataSourceExternal SelectDataSource = "external"
+ // DialogDataSourceConversations provides a list of conversations
+ DialogDataSourceConversations SelectDataSource = "conversations"
+ // DialogDataSourceChannels provides a list of channels
+ DialogDataSourceChannels SelectDataSource = "channels"
+ // DialogDataSourceUsers provides a list of users
+ DialogDataSourceUsers SelectDataSource = "users"
+)
+
+// DialogInputSelect dialog support for select boxes.
+type DialogInputSelect struct {
+ DialogInput
+ Value string `json:"value,omitempty"` //Optional.
+ DataSource SelectDataSource `json:"data_source,omitempty"` //Optional. Allowed values: "users", "channels", "conversations", "external".
+ SelectedOptions string `json:"selected_options,omitempty"` //Optional. Default value for "external" only
+ Options []DialogSelectOption `json:"options,omitempty"` //One of options or option_groups is required.
+ OptionGroups []DialogOptionGroup `json:"option_groups,omitempty"` //Provide up to 100 options.
+}
+
+// DialogSelectOption is an option for the user to select from the menu
+type DialogSelectOption struct {
+ Label string `json:"label"`
+ Value string `json:"value"`
+}
+
+// DialogOptionGroup is a collection of options for creating a segmented table
+type DialogOptionGroup struct {
+ Label string `json:"label"`
+ Options []DialogSelectOption `json:"options"`
+}
+
+// NewStaticSelectDialogInput constructor for a `static` datasource menu input
+func NewStaticSelectDialogInput(name, label string, options []DialogSelectOption) *DialogInputSelect {
+ return &DialogInputSelect{
+ DialogInput: DialogInput{
+ Type: InputTypeSelect,
+ Name: name,
+ Label: label,
+ Optional: true,
+ },
+ DataSource: DialogDataSourceStatic,
+ Options: options,
+ }
+}
+
+// NewGroupedSelectDialogInput creates grouped options select input for Dialogs.
+func NewGroupedSelectDialogInput(name, label string, groups map[string]map[string]string) *DialogInputSelect {
+ optionGroups := []DialogOptionGroup{}
+ for groupName, options := range groups {
+ optionGroups = append(optionGroups, DialogOptionGroup{
+ Label: groupName,
+ Options: optionsFromMap(options),
+ })
+ }
+ return &DialogInputSelect{
+ DialogInput: DialogInput{
+ Type: InputTypeSelect,
+ Name: name,
+ Label: label,
+ },
+ DataSource: DialogDataSourceStatic,
+ OptionGroups: optionGroups,
+ }
+}
+
+func optionsFromArray(options []string) []DialogSelectOption {
+ selectOptions := make([]DialogSelectOption, len(options))
+ for idx, value := range options {
+ selectOptions[idx] = DialogSelectOption{
+ Label: value,
+ Value: value,
+ }
+ }
+ return selectOptions
+}
+
+func optionsFromMap(options map[string]string) []DialogSelectOption {
+ selectOptions := make([]DialogSelectOption, len(options))
+ idx := 0
+ var option DialogSelectOption
+ for key, value := range options {
+ option = DialogSelectOption{
+ Label: key,
+ Value: value,
+ }
+ selectOptions[idx] = option
+ idx++
+ }
+ return selectOptions
+}
+
+// NewConversationsSelect returns a `Conversations` select
+func NewConversationsSelect(name, label string) *DialogInputSelect {
+ return newPresetSelect(name, label, DialogDataSourceConversations)
+}
+
+// NewChannelsSelect returns a `Channels` select
+func NewChannelsSelect(name, label string) *DialogInputSelect {
+ return newPresetSelect(name, label, DialogDataSourceChannels)
+}
+
+// NewUsersSelect returns a `Users` select
+func NewUsersSelect(name, label string) *DialogInputSelect {
+ return newPresetSelect(name, label, DialogDataSourceUsers)
+}
+
+func newPresetSelect(name, label string, dataSourceType SelectDataSource) *DialogInputSelect {
+ return &DialogInputSelect{
+ DialogInput: DialogInput{
+ Type: InputTypeSelect,
+ Label: label,
+ Name: name,
+ },
+ DataSource: dataSourceType,
+ }
+}
diff --git a/vendor/github.com/nlopes/slack/dialog_text.go b/vendor/github.com/nlopes/slack/dialog_text.go
new file mode 100644
index 00000000..bf9602cc
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/dialog_text.go
@@ -0,0 +1,50 @@
+package slack
+
+// TextInputSubtype Accepts email, number, tel, or url. In some form factors, optimized input is provided for this subtype.
+type TextInputSubtype string
+
+const (
+ // InputSubtypeEmail email keyboard
+ InputSubtypeEmail TextInputSubtype = "email"
+ // InputSubtypeNumber numeric keyboard
+ InputSubtypeNumber TextInputSubtype = "number"
+ // InputSubtypeTel Phone keyboard
+ InputSubtypeTel TextInputSubtype = "tel"
+ // InputSubtypeURL Phone keyboard
+ InputSubtypeURL TextInputSubtype = "url"
+)
+
+// TextInputElement subtype of DialogInput
+// https://api.slack.com/dialogs#option_element_attributes#text_element_attributes
+type TextInputElement struct {
+ DialogInput
+ MaxLength int `json:"max_length,omitempty"`
+ MinLength int `json:"min_length,omitempty"`
+ Hint string `json:"hint,omitempty"`
+ Subtype TextInputSubtype `json:"subtype"`
+ Value string `json:"value"`
+}
+
+// NewTextInput constructor for a `text` input
+func NewTextInput(name, label, text string) *TextInputElement {
+ return &TextInputElement{
+ DialogInput: DialogInput{
+ Type: InputTypeText,
+ Name: name,
+ Label: label,
+ },
+ Value: text,
+ }
+}
+
+// NewTextAreaInput constructor for a `textarea` input
+func NewTextAreaInput(name, label, text string) *TextInputElement {
+ return &TextInputElement{
+ DialogInput: DialogInput{
+ Type: InputTypeTextArea,
+ Name: name,
+ Label: label,
+ },
+ Value: text,
+ }
+}
diff --git a/vendor/github.com/nlopes/slack/files.go b/vendor/github.com/nlopes/slack/files.go
index 2381ec3c..0550c9fb 100644
--- a/vendor/github.com/nlopes/slack/files.go
+++ b/vendor/github.com/nlopes/slack/files.go
@@ -93,14 +93,15 @@ type File struct {
// There are three ways to upload a file. You can either set Content if file is small, set Reader if file is large,
// or provide a local file path in File to upload it from your filesystem.
type FileUploadParameters struct {
- File string
- Content string
- Reader io.Reader
- Filetype string
- Filename string
- Title string
- InitialComment string
- Channels []string
+ File string
+ Content string
+ Reader io.Reader
+ Filetype string
+ Filename string
+ Title string
+ InitialComment string
+ Channels []string
+ ThreadTimestamp string
}
// GetFilesParameters contains all the parameters necessary (including the optional ones) for a GetFiles() request
@@ -237,6 +238,9 @@ func (api *Client) UploadFileContext(ctx context.Context, params FileUploadParam
if params.InitialComment != "" {
values.Add("initial_comment", params.InitialComment)
}
+ if params.ThreadTimestamp != "" {
+ values.Add("thread_ts", params.ThreadTimestamp)
+ }
if len(params.Channels) != 0 {
values.Add("channels", strings.Join(params.Channels, ","))
}
diff --git a/vendor/github.com/nlopes/slack/security.go b/vendor/github.com/nlopes/slack/security.go
new file mode 100644
index 00000000..50201d99
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/security.go
@@ -0,0 +1,47 @@
+package slack
+
+import (
+ "crypto/hmac"
+ "crypto/sha256"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "hash"
+ "net/http"
+)
+
+// SecretsVerifier contains the information needed to verify that the request comes from Slack
+type SecretsVerifier struct {
+ slackSig string
+ timeStamp string
+ hmac hash.Hash
+}
+
+// NewSecretsVerifier returns a SecretsVerifier object in exchange for an http.Header object and signing secret
+func NewSecretsVerifier(header http.Header, signingSecret string) (SecretsVerifier, error) {
+ if header["X-Slack-Signature"][0] == "" || header["X-Slack-Request-Timestamp"][0] == "" {
+ return SecretsVerifier{}, errors.New("Headers are empty, cannot create SecretsVerifier")
+ }
+
+ hash := hmac.New(sha256.New, []byte(signingSecret))
+ hash.Write([]byte(fmt.Sprintf("v0:%s:", header["X-Slack-Request-Timestamp"][0])))
+ return SecretsVerifier{
+ slackSig: header["X-Slack-Signature"][0],
+ timeStamp: header["X-Slack-Request-Timestamp"][0],
+ hmac: hash,
+ }, nil
+}
+
+func (v *SecretsVerifier) Write(body []byte) (n int, err error) {
+ return v.hmac.Write(body)
+}
+
+// Ensure compares the signature sent from Slack with the actual computed hash to judge validity
+func (v SecretsVerifier) Ensure() error {
+ computed := "v0=" + string(hex.EncodeToString(v.hmac.Sum(nil)))
+ if computed == v.slackSig {
+ return nil
+ }
+
+ return fmt.Errorf("Expected signing signature: %s, but computed: %s", v.slackSig, computed)
+}
diff --git a/vendor/github.com/nlopes/slack/slackutilsx/slackutilsx.go b/vendor/github.com/nlopes/slack/slackutilsx/slackutilsx.go
new file mode 100644
index 00000000..ccf5372b
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/slackutilsx/slackutilsx.go
@@ -0,0 +1,57 @@
+// Package slackutilsx is a utility package that doesn't promise API stability.
+// its for experimental functionality and utilities.
+package slackutilsx
+
+import (
+ "strings"
+ "unicode/utf8"
+)
+
+// ChannelType the type of channel based on the channelID
+type ChannelType int
+
+func (t ChannelType) String() string {
+ switch t {
+ case CTypeDM:
+ return "Direct"
+ case CTypeGroup:
+ return "Group"
+ case CTypeChannel:
+ return "Channel"
+ default:
+ return "Unknown"
+ }
+}
+
+const (
+ // CTypeUnknown represents channels we cannot properly detect.
+ CTypeUnknown ChannelType = iota
+ // CTypeDM is a private channel between two slack users.
+ CTypeDM
+ // CTypeGroup is a group channel.
+ CTypeGroup
+ // CTypeChannel is a public channel.
+ CTypeChannel
+)
+
+// DetectChannelType converts a channelID to a ChannelType.
+// channelID must not be empty. However, if it is empty, the channel type will default to Unknown.
+func DetectChannelType(channelID string) ChannelType {
+ // intentionally ignore the error and just default to CTypeUnknown
+ switch r, _ := utf8.DecodeRuneInString(channelID); r {
+ case 'C':
+ return CTypeChannel
+ case 'G':
+ return CTypeGroup
+ case 'D':
+ return CTypeDM
+ default:
+ return CTypeUnknown
+ }
+}
+
+// EscapeMessage text
+func EscapeMessage(message string) string {
+ replacer := strings.NewReplacer("&", "&amp;", "<", "&lt;", ">", "&gt;")
+ return replacer.Replace(message)
+}
diff --git a/vendor/github.com/nlopes/slack/usergroups.go b/vendor/github.com/nlopes/slack/usergroups.go
index 1e2b6442..cc9bc4ca 100644
--- a/vendor/github.com/nlopes/slack/usergroups.go
+++ b/vendor/github.com/nlopes/slack/usergroups.go
@@ -25,6 +25,7 @@ type UserGroup struct {
DeletedBy string `json:"deleted_by"`
Prefs UserGroupPrefs `json:"prefs"`
UserCount int `json:"user_count"`
+ Users []string `json:"users"`
}
// UserGroupPrefs contains default channels and groups (private channels)
@@ -121,16 +122,62 @@ func (api *Client) EnableUserGroupContext(ctx context.Context, userGroup string)
return response.UserGroup, nil
}
+// GetUserGroupsOption options for the GetUserGroups method call.
+type GetUserGroupsOption func(*GetUserGroupsParams)
+
+// GetUserGroupsOptionIncludeCount include the number of users in each User Group (default: false)
+func GetUserGroupsOptionIncludeCount(b bool) GetUserGroupsOption {
+ return func(params *GetUserGroupsParams) {
+ params.IncludeCount = b
+ }
+}
+
+// GetUserGroupsOptionIncludeDisabled include disabled User Groups (default: false)
+func GetUserGroupsOptionIncludeDisabled(b bool) GetUserGroupsOption {
+ return func(params *GetUserGroupsParams) {
+ params.IncludeDisabled = b
+ }
+}
+
+// GetUserGroupsOptionIncludeUsers include the list of users for each User Group (default: false)
+func GetUserGroupsOptionIncludeUsers(b bool) GetUserGroupsOption {
+ return func(params *GetUserGroupsParams) {
+ params.IncludeUsers = b
+ }
+}
+
+// GetUserGroupsParams contains arguments for GetUserGroups method call
+type GetUserGroupsParams struct {
+ IncludeCount bool
+ IncludeDisabled bool
+ IncludeUsers bool
+}
+
// GetUserGroups returns a list of user groups for the team
-func (api *Client) GetUserGroups() ([]UserGroup, error) {
- return api.GetUserGroupsContext(context.Background())
+func (api *Client) GetUserGroups(options ...GetUserGroupsOption) ([]UserGroup, error) {
+ return api.GetUserGroupsContext(context.Background(), options...)
}
// GetUserGroupsContext returns a list of user groups for the team with a custom context
-func (api *Client) GetUserGroupsContext(ctx context.Context) ([]UserGroup, error) {
+func (api *Client) GetUserGroupsContext(ctx context.Context, options ...GetUserGroupsOption) ([]UserGroup, error) {
+ params := GetUserGroupsParams{}
+
+ for _, opt := range options {
+ opt(&params)
+ }
+
values := url.Values{
"token": {api.token},
}
+ if params.IncludeCount {
+ values.Add("include_count", "true")
+ }
+ if params.IncludeDisabled {
+ values.Add("include_disabled", "true")
+ }
+ if params.IncludeUsers {
+ values.Add("include_users", "true")
+ }
response, err := userGroupRequest(ctx, api.httpclient, "usergroups.list", values, api.debug)
if err != nil {
diff --git a/vendor/github.com/nlopes/slack/webhooks.go b/vendor/github.com/nlopes/slack/webhooks.go
index 870a8d8b..3ea69ffe 100644
--- a/vendor/github.com/nlopes/slack/webhooks.go
+++ b/vendor/github.com/nlopes/slack/webhooks.go
@@ -1,15 +1,16 @@
package slack
import (
- "github.com/pkg/errors"
- "net/http"
"bytes"
"encoding/json"
+ "net/http"
+
+ "github.com/pkg/errors"
)
type WebhookMessage struct {
- Text string `json:"text,omitempty"`
- Attachments []Attachment `json:"attachments,omitempty"`
+ Text string `json:"text,omitempty"`
+ Attachments []Attachment `json:"attachments,omitempty"`
}
func PostWebhook(url string, msg *WebhookMessage) error {
@@ -19,7 +20,7 @@ func PostWebhook(url string, msg *WebhookMessage) error {
return errors.Wrap(err, "marshal failed")
}
- response, err := http.Post(url, "application/json", bytes.NewReader(raw));
+ response, err := http.Post(url, "application/json", bytes.NewReader(raw))
if err != nil {
return errors.Wrap(err, "failed to post webhook")
diff --git a/vendor/github.com/nlopes/slack/websocket_managed_conn.go b/vendor/github.com/nlopes/slack/websocket_managed_conn.go
index b6d1bfc8..e8ab65a1 100644
--- a/vendor/github.com/nlopes/slack/websocket_managed_conn.go
+++ b/vendor/github.com/nlopes/slack/websocket_managed_conn.go
@@ -524,4 +524,9 @@ var EventMapping = map[string]interface{}{
"member_joined_channel": MemberJoinedChannelEvent{},
"member_left_channel": MemberLeftChannelEvent{},
+
+ "subteam_created": SubteamCreatedEvent{},
+ "subteam_self_added": SubteamSelfAddedEvent{},
+ "subteam_self_removed": SubteamSelfRemovedEvent{},
+ "subteam_updated": SubteamUpdatedEvent{},
}
diff --git a/vendor/github.com/nlopes/slack/websocket_subteam.go b/vendor/github.com/nlopes/slack/websocket_subteam.go
new file mode 100644
index 00000000..a23b274c
--- /dev/null
+++ b/vendor/github.com/nlopes/slack/websocket_subteam.go
@@ -0,0 +1,35 @@
+package slack
+
+// SubteamCreatedEvent represents the Subteam created event
+type SubteamCreatedEvent struct {
+ Type string `json:"type"`
+ Subteam UserGroup `json:"subteam"`
+}
+
+// SubteamCreatedEvent represents the membership of an existing User Group has changed event
+type SubteamMembersChangedEvent struct {
+ Type string `json:"type"`
+ SubteamID string `json:"subteam_id"`
+ TeamID string `json:"team_id"`
+ DatePreviousUpdate JSONTime `json:"date_previous_update"`
+ DateUpdate JSONTime `json:"date_update"`
+ AddedUsers []string `json:"added_users"`
+ AddedUsersCount string `json:"added_users_count"`
+ RemovedUsers []string `json:"removed_users"`
+ RemovedUsersCount string `json:"removed_users_count"`
+}
+
+// SubteamSelfAddedEvent represents an event of you have been added to a User Group
+type SubteamSelfAddedEvent struct {
+ Type string `json:"type"`
+ SubteamID string `json:"subteam_id"`
+}
+
+// SubteamSelfRemovedEvent represents an event of you have been removed from a User Group
+type SubteamSelfRemovedEvent SubteamSelfAddedEvent
+
+// SubteamUpdatedEvent represents an event of an existing User Group has been updated or its members changed
+type SubteamUpdatedEvent struct {
+ Type string `json:"type"`
+ Subteam UserGroup `json:"subteam"`
+}