diff options
Diffstat (limited to 'vendor/github.com/slack-go')
-rw-r--r-- | vendor/github.com/slack-go/slack/auth.go | 34 | ||||
-rw-r--r-- | vendor/github.com/slack-go/slack/block_conv.go | 12 | ||||
-rw-r--r-- | vendor/github.com/slack-go/slack/block_element.go | 92 | ||||
-rw-r--r-- | vendor/github.com/slack-go/slack/block_rich_text.go | 6 | ||||
-rw-r--r-- | vendor/github.com/slack-go/slack/conversation.go | 73 | ||||
-rw-r--r-- | vendor/github.com/slack-go/slack/files.go | 179 | ||||
-rw-r--r-- | vendor/github.com/slack-go/slack/misc.go | 3 | ||||
-rw-r--r-- | vendor/github.com/slack-go/slack/team.go | 69 | ||||
-rw-r--r-- | vendor/github.com/slack-go/slack/users.go | 105 | ||||
-rw-r--r-- | vendor/github.com/slack-go/slack/webhooks.go | 4 | ||||
-rw-r--r-- | vendor/github.com/slack-go/slack/websocket_reactions.go | 12 | ||||
-rw-r--r-- | vendor/github.com/slack-go/slack/workflow_step_execute.go | 6 |
12 files changed, 539 insertions, 56 deletions
diff --git a/vendor/github.com/slack-go/slack/auth.go b/vendor/github.com/slack-go/slack/auth.go index f4f7f003..bf6e80d3 100644 --- a/vendor/github.com/slack-go/slack/auth.go +++ b/vendor/github.com/slack-go/slack/auth.go @@ -38,3 +38,37 @@ func (api *Client) SendAuthRevokeContext(ctx context.Context, token string) (*Au return api.authRequest(ctx, "auth.revoke", values) } + +type listTeamsResponse struct { + Teams []Team `json:"teams"` + SlackResponse +} + +type ListTeamsParameters struct { + Limit int + Cursor string +} + +// ListTeams returns all workspaces a token can access. +// More info: https://api.slack.com/methods/admin.teams.list +func (api *Client) ListTeams(params ListTeamsParameters) ([]Team, string, error) { + return api.ListTeamsContext(context.Background(), params) +} + +// ListTeams returns all workspaces a token can access with a custom context. +func (api *Client) ListTeamsContext(ctx context.Context, params ListTeamsParameters) ([]Team, string, error) { + values := url.Values{ + "token": {api.token}, + } + if params.Cursor != "" { + values.Add("cursor", params.Cursor) + } + + response := &listTeamsResponse{} + err := api.postMethod(ctx, "auth.teams.list", values, response) + if err != nil { + return nil, "", err + } + + return response.Teams, response.ResponseMetadata.Cursor, response.Err() +} diff --git a/vendor/github.com/slack-go/slack/block_conv.go b/vendor/github.com/slack-go/slack/block_conv.go index 1a2c57e9..555e4811 100644 --- a/vendor/github.com/slack-go/slack/block_conv.go +++ b/vendor/github.com/slack-go/slack/block_conv.go @@ -112,6 +112,10 @@ func (b *InputBlock) UnmarshalJSON(data []byte) error { e = &TimePickerBlockElement{} case "plain_text_input": e = &PlainTextInputBlockElement{} + case "email_text_input": + e = &EmailTextInputBlockElement{} + case "url_text_input": + e = &URLTextInputBlockElement{} case "static_select", "external_select", "users_select", "conversations_select", "channels_select": e = &SelectBlockElement{} case "multi_static_select", "multi_external_select", "multi_users_select", "multi_conversations_select", "multi_channels_select": @@ -122,6 +126,8 @@ func (b *InputBlock) UnmarshalJSON(data []byte) error { e = &OverflowBlockElement{} case "radio_buttons": e = &RadioButtonsBlockElement{} + case "number_input": + e = &NumberInputBlockElement{} default: return errors.New("unsupported block element type") } @@ -186,12 +192,18 @@ func (b *BlockElements) UnmarshalJSON(data []byte) error { blockElement = &TimePickerBlockElement{} case "plain_text_input": blockElement = &PlainTextInputBlockElement{} + case "email_text_input": + blockElement = &EmailTextInputBlockElement{} + case "url_text_input": + blockElement = &URLTextInputBlockElement{} case "checkboxes": blockElement = &CheckboxGroupsBlockElement{} case "radio_buttons": blockElement = &RadioButtonsBlockElement{} case "static_select", "external_select", "users_select", "conversations_select", "channels_select": blockElement = &SelectBlockElement{} + case "number_input": + blockElement = &NumberInputBlockElement{} default: return fmt.Errorf("unsupported block element type %v", blockElementType) } diff --git a/vendor/github.com/slack-go/slack/block_element.go b/vendor/github.com/slack-go/slack/block_element.go index 643529ff..aba29c6b 100644 --- a/vendor/github.com/slack-go/slack/block_element.go +++ b/vendor/github.com/slack-go/slack/block_element.go @@ -11,6 +11,9 @@ const ( METTimepicker MessageElementType = "timepicker" METPlainTextInput MessageElementType = "plain_text_input" METRadioButtons MessageElementType = "radio_buttons" + METEmailTextInput MessageElementType = "email_text_input" + METURLTextInput MessageElementType = "url_text_input" + METNumber MessageElementType = "number_input" MixedElementImage MixedElementType = "mixed_image" MixedElementText MixedElementType = "mixed_text" @@ -389,6 +392,64 @@ func NewTimePickerBlockElement(actionID string) *TimePickerBlockElement { } } +// EmailTextInputBlockElement creates a field where a user can enter email +// data. +// email-text-input elements are currently only available in modals. +// +// More Information: https://api.slack.com/reference/block-kit/block-elements#email +type EmailTextInputBlockElement struct { + Type MessageElementType `json:"type"` + ActionID string `json:"action_id,omitempty"` + Placeholder *TextBlockObject `json:"placeholder,omitempty"` + InitialValue string `json:"initial_value,omitempty"` + DispatchActionConfig *DispatchActionConfig `json:"dispatch_action_config,omitempty"` + FocusOnLoad bool `json:"focus_on_load,omitempty"` +} + +// ElementType returns the type of the Element +func (s EmailTextInputBlockElement) ElementType() MessageElementType { + return s.Type +} + +// NewEmailTextInputBlockElement returns an instance of a plain-text input +// element +func NewEmailTextInputBlockElement(placeholder *TextBlockObject, actionID string) *EmailTextInputBlockElement { + return &EmailTextInputBlockElement{ + Type: METEmailTextInput, + ActionID: actionID, + Placeholder: placeholder, + } +} + +// URLTextInputBlockElement creates a field where a user can enter url data. +// +// url-text-input elements are currently only available in modals. +// +// More Information: https://api.slack.com/reference/block-kit/block-elements#url +type URLTextInputBlockElement struct { + Type MessageElementType `json:"type"` + ActionID string `json:"action_id,omitempty"` + Placeholder *TextBlockObject `json:"placeholder,omitempty"` + InitialValue string `json:"initial_value,omitempty"` + DispatchActionConfig *DispatchActionConfig `json:"dispatch_action_config,omitempty"` + FocusOnLoad bool `json:"focus_on_load,omitempty"` +} + +// ElementType returns the type of the Element +func (s URLTextInputBlockElement) ElementType() MessageElementType { + return s.Type +} + +// NewURLTextInputBlockElement returns an instance of a plain-text input +// element +func NewURLTextInputBlockElement(placeholder *TextBlockObject, actionID string) *URLTextInputBlockElement { + return &URLTextInputBlockElement{ + Type: METURLTextInput, + ActionID: actionID, + Placeholder: placeholder, + } +} + // PlainTextInputBlockElement creates a field where a user can enter freeform // data. // Plain-text input elements are currently only available in modals. @@ -475,3 +536,34 @@ func NewRadioButtonsBlockElement(actionID string, options ...*OptionBlockObject) Options: options, } } + +// NumberInputBlockElement creates a field where a user can enter number +// data. +// Number input elements are currently only available in modals. +// +// More Information: https://api.slack.com/reference/block-kit/block-elements#number +type NumberInputBlockElement struct { + Type MessageElementType `json:"type"` + IsDecimalAllowed bool `json:"is_decimal_allowed"` + ActionID string `json:"action_id,omitempty"` + Placeholder *TextBlockObject `json:"placeholder,omitempty"` + InitialValue string `json:"initial_value,omitempty"` + MinValue string `json:"min_value,omitempty"` + MaxValue string `json:"max_value,omitempty"` + DispatchActionConfig *DispatchActionConfig `json:"dispatch_action_config,omitempty"` +} + +// ElementType returns the type of the Element +func (s NumberInputBlockElement) ElementType() MessageElementType { + return s.Type +} + +// NewNumberInputBlockElement returns an instance of a number input element +func NewNumberInputBlockElement(placeholder *TextBlockObject, actionID string, isDecimalAllowed bool) *NumberInputBlockElement { + return &NumberInputBlockElement{ + Type: METNumber, + ActionID: actionID, + Placeholder: placeholder, + IsDecimalAllowed: isDecimalAllowed, + } +} diff --git a/vendor/github.com/slack-go/slack/block_rich_text.go b/vendor/github.com/slack-go/slack/block_rich_text.go index 281db213..555a6198 100644 --- a/vendor/github.com/slack-go/slack/block_rich_text.go +++ b/vendor/github.com/slack-go/slack/block_rich_text.go @@ -327,17 +327,17 @@ func NewRichTextSectionUserGroupElement(usergroupID string) *RichTextSectionUser type RichTextSectionDateElement struct { Type RichTextSectionElementType `json:"type"` - Timestamp string `json:"timestamp"` + Timestamp JSONTime `json:"timestamp"` } func (r RichTextSectionDateElement) RichTextSectionElementType() RichTextSectionElementType { return r.Type } -func NewRichTextSectionDateElement(timestamp string) *RichTextSectionDateElement { +func NewRichTextSectionDateElement(timestamp int64) *RichTextSectionDateElement { return &RichTextSectionDateElement{ Type: RTSEDate, - Timestamp: timestamp, + Timestamp: JSONTime(timestamp), } } diff --git a/vendor/github.com/slack-go/slack/conversation.go b/vendor/github.com/slack-go/slack/conversation.go index e523716c..44f06ea9 100644 --- a/vendor/github.com/slack-go/slack/conversation.go +++ b/vendor/github.com/slack-go/slack/conversation.go @@ -2,6 +2,7 @@ package slack import ( "context" + "errors" "net/url" "strconv" "strings" @@ -71,6 +72,7 @@ type GetConversationsForUserParameters struct { Types []string Limit int ExcludeArchived bool + TeamID string } type responseMetaData struct { @@ -137,6 +139,10 @@ func (api *Client) GetConversationsForUserContext(ctx context.Context, params *G if params.ExcludeArchived { values.Add("exclude_archived", "true") } + if params.TeamID != "" { + values.Add("team_id", params.TeamID) + } + response := struct { Channels []Channel `json:"channels"` ResponseMetaData responseMetaData `json:"response_metadata"` @@ -337,17 +343,26 @@ func (api *Client) CloseConversationContext(ctx context.Context, channelID strin return response.NoOp, response.AlreadyClosed, response.Err() } +type CreateConversationParams struct { + ChannelName string + IsPrivate bool + TeamID string +} + // CreateConversation initiates a public or private channel-based conversation -func (api *Client) CreateConversation(channelName string, isPrivate bool) (*Channel, error) { - return api.CreateConversationContext(context.Background(), channelName, isPrivate) +func (api *Client) CreateConversation(params CreateConversationParams) (*Channel, error) { + return api.CreateConversationContext(context.Background(), params) } // CreateConversationContext initiates a public or private channel-based conversation with a custom context -func (api *Client) CreateConversationContext(ctx context.Context, channelName string, isPrivate bool) (*Channel, error) { +func (api *Client) CreateConversationContext(ctx context.Context, params CreateConversationParams) (*Channel, error) { values := url.Values{ "token": {api.token}, - "name": {channelName}, - "is_private": {strconv.FormatBool(isPrivate)}, + "name": {params.ChannelName}, + "is_private": {strconv.FormatBool(params.IsPrivate)}, + } + if params.TeamID != "" { + values.Set("team_id", params.TeamID) } response, err := api.channelRequest(ctx, "conversations.create", values) if err != nil { @@ -357,17 +372,33 @@ func (api *Client) CreateConversationContext(ctx context.Context, channelName st return &response.Channel, nil } +// GetConversationInfoInput Defines the parameters of a GetConversationInfo and GetConversationInfoContext function +type GetConversationInfoInput struct { + ChannelID string + IncludeLocale bool + IncludeNumMembers bool +} + // GetConversationInfo retrieves information about a conversation -func (api *Client) GetConversationInfo(channelID string, includeLocale bool) (*Channel, error) { - return api.GetConversationInfoContext(context.Background(), channelID, includeLocale) +func (api *Client) GetConversationInfo(input *GetConversationInfoInput) (*Channel, error) { + return api.GetConversationInfoContext(context.Background(), input) } // GetConversationInfoContext retrieves information about a conversation with a custom context -func (api *Client) GetConversationInfoContext(ctx context.Context, channelID string, includeLocale bool) (*Channel, error) { +func (api *Client) GetConversationInfoContext(ctx context.Context, input *GetConversationInfoInput) (*Channel, error) { + if input == nil { + return nil, errors.New("GetConversationInfoInput must not be nil") + } + + if input.ChannelID == "" { + return nil, errors.New("ChannelID must be defined") + } + values := url.Values{ - "token": {api.token}, - "channel": {channelID}, - "include_locale": {strconv.FormatBool(includeLocale)}, + "token": {api.token}, + "channel": {input.ChannelID}, + "include_locale": {strconv.FormatBool(input.IncludeLocale)}, + "include_num_members": {strconv.FormatBool(input.IncludeNumMembers)}, } response, err := api.channelRequest(ctx, "conversations.info", values) if err != nil { @@ -398,13 +429,14 @@ func (api *Client) LeaveConversationContext(ctx context.Context, channelID strin } type GetConversationRepliesParameters struct { - ChannelID string - Timestamp string - Cursor string - Inclusive bool - Latest string - Limit int - Oldest string + ChannelID string + Timestamp string + Cursor string + Inclusive bool + Latest string + Limit int + Oldest string + IncludeAllMetadata bool } // GetConversationReplies retrieves a thread of messages posted to a conversation @@ -436,6 +468,11 @@ func (api *Client) GetConversationRepliesContext(ctx context.Context, params *Ge } else { values.Add("inclusive", "0") } + if params.IncludeAllMetadata { + values.Add("include_all_metadata", "1") + } else { + values.Add("include_all_metadata", "0") + } response := struct { SlackResponse HasMore bool `json:"has_more"` diff --git a/vendor/github.com/slack-go/slack/files.go b/vendor/github.com/slack-go/slack/files.go index e7cfe1fe..35628442 100644 --- a/vendor/github.com/slack-go/slack/files.go +++ b/vendor/github.com/slack-go/slack/files.go @@ -2,6 +2,7 @@ package slack import ( "context" + "encoding/json" "fmt" "io" "net/url" @@ -145,6 +146,58 @@ type ListFilesParameters struct { Cursor string } +type UploadFileV2Parameters struct { + File string + FileSize int + Content string + Reader io.Reader + Filename string + Title string + InitialComment string + Channel string + ThreadTimestamp string + AltTxt string + SnippetText string +} + +type getUploadURLExternalParameters struct { + altText string + fileSize int + fileName string + snippetText string +} + +type getUploadURLExternalResponse struct { + UploadURL string `json:"upload_url"` + FileID string `json:"file_id"` + SlackResponse +} + +type uploadToURLParameters struct { + UploadURL string + Reader io.Reader + File string + Content string + Filename string +} + +type FileSummary struct { + ID string `json:"id"` + Title string `json:"title"` +} + +type completeUploadExternalParameters struct { + title string + channel string + initialComment string + threadTimestamp string +} + +type completeUploadExternalResponse struct { + SlackResponse + Files []FileSummary `json:"files"` +} + type fileResponseFull struct { File `json:"file"` Paging `json:"paging"` @@ -416,3 +469,129 @@ func (api *Client) ShareFilePublicURLContext(ctx context.Context, fileID string) } return &response.File, response.Comments, &response.Paging, nil } + +// getUploadURLExternal gets a URL and fileID from slack which can later be used to upload a file +func (api *Client) getUploadURLExternal(ctx context.Context, params getUploadURLExternalParameters) (*getUploadURLExternalResponse, error) { + values := url.Values{ + "token": {api.token}, + "filename": {params.fileName}, + "length": {strconv.Itoa(params.fileSize)}, + } + if params.altText != "" { + values.Add("initial_comment", params.altText) + } + if params.snippetText != "" { + values.Add("thread_ts", params.snippetText) + } + response := &getUploadURLExternalResponse{} + err := api.postMethod(ctx, "files.getUploadURLExternal", values, response) + if err != nil { + return nil, err + } + + return response, response.Err() +} + +// uploadToURL uploads the file to the provided URL using post method +func (api *Client) uploadToURL(ctx context.Context, params uploadToURLParameters) (err error) { + values := url.Values{} + if params.Content != "" { + values.Add("content", params.Content) + values.Add("token", api.token) + err = postForm(ctx, api.httpclient, params.UploadURL, values, nil, api) + } else if params.File != "" { + err = postLocalWithMultipartResponse(ctx, api.httpclient, params.UploadURL, params.File, "file", api.token, values, nil, api) + } else if params.Reader != nil { + err = postWithMultipartResponse(ctx, api.httpclient, params.UploadURL, params.Filename, "file", api.token, values, params.Reader, nil, api) + } + return err +} + +// completeUploadExternal once files are uploaded, this completes the upload and shares it to the specified channel +func (api *Client) completeUploadExternal(ctx context.Context, fileID string, params completeUploadExternalParameters) (file *completeUploadExternalResponse, err error) { + request := []FileSummary{{ID: fileID, Title: params.title}} + requestBytes, err := json.Marshal(request) + if err != nil { + return nil, err + } + values := url.Values{ + "token": {api.token}, + "files": {string(requestBytes)}, + "channel_id": {params.channel}, + } + + if params.initialComment != "" { + values.Add("initial_comment", params.initialComment) + } + if params.threadTimestamp != "" { + values.Add("thread_ts", params.threadTimestamp) + } + response := &completeUploadExternalResponse{} + err = api.postMethod(ctx, "files.completeUploadExternal", values, response) + if err != nil { + return nil, err + } + if response.Err() != nil { + return nil, response.Err() + } + return response, nil +} + +// UploadFileV2 uploads file to a given slack channel using 3 steps - +// 1. Get an upload URL using files.getUploadURLExternal API +// 2. Send the file as a post to the URL provided by slack +// 3. Complete the upload and share it to the specified channel using files.completeUploadExternal +func (api *Client) UploadFileV2(params UploadFileV2Parameters) (*FileSummary, error) { + return api.UploadFileV2Context(context.Background(), params) +} + +// UploadFileV2 uploads file to a given slack channel using 3 steps with a custom context - +// 1. Get an upload URL using files.getUploadURLExternal API +// 2. Send the file as a post to the URL provided by slack +// 3. Complete the upload and share it to the specified channel using files.completeUploadExternal +func (api *Client) UploadFileV2Context(ctx context.Context, params UploadFileV2Parameters) (file *FileSummary, err error) { + if params.Filename == "" { + return nil, fmt.Errorf("file.upload.v2: filename cannot be empty") + } + if params.FileSize == 0 { + return nil, fmt.Errorf("file.upload.v2: file size cannot be 0") + } + if params.Channel == "" { + return nil, fmt.Errorf("file.upload.v2: channel cannot be empty") + } + u, err := api.getUploadURLExternal(ctx, getUploadURLExternalParameters{ + altText: params.AltTxt, + fileName: params.Filename, + fileSize: params.FileSize, + snippetText: params.SnippetText, + }) + if err != nil { + return nil, err + } + + err = api.uploadToURL(ctx, uploadToURLParameters{ + UploadURL: u.UploadURL, + Reader: params.Reader, + File: params.File, + Content: params.Content, + Filename: params.Filename, + }) + if err != nil { + return nil, err + } + + c, err := api.completeUploadExternal(ctx, u.FileID, completeUploadExternalParameters{ + title: params.Title, + channel: params.Channel, + initialComment: params.InitialComment, + threadTimestamp: params.ThreadTimestamp, + }) + if err != nil { + return nil, err + } + if len(c.Files) != 1 { + return nil, fmt.Errorf("file.upload.v2: something went wrong; received %d files instead of 1", len(c.Files)) + } + + return &c.Files[0], nil +} diff --git a/vendor/github.com/slack-go/slack/misc.go b/vendor/github.com/slack-go/slack/misc.go index 9180116a..7e5a8d54 100644 --- a/vendor/github.com/slack-go/slack/misc.go +++ b/vendor/github.com/slack-go/slack/misc.go @@ -307,6 +307,9 @@ type responseParser func(*http.Response) error func newJSONParser(dst interface{}) responseParser { return func(resp *http.Response) error { + if dst == nil { + return nil + } return json.NewDecoder(resp.Body).Decode(dst) } } diff --git a/vendor/github.com/slack-go/slack/team.go b/vendor/github.com/slack-go/slack/team.go index 029e2b5b..d21a1b64 100644 --- a/vendor/github.com/slack-go/slack/team.go +++ b/vendor/github.com/slack-go/slack/team.go @@ -24,6 +24,26 @@ type TeamInfo struct { Icon map[string]interface{} `json:"icon"` } +type TeamProfileResponse struct { + Profile TeamProfile `json:"profile"` + SlackResponse +} + +type TeamProfile struct { + Fields []TeamProfileField `json:"fields"` +} + +type TeamProfileField struct { + ID string `json:"id"` + Ordering int `json:"ordering"` + Label string `json:"label"` + Hint string `json:"hint"` + Type string `json:"type"` + PossibleValues []string `json:"possible_values"` + IsHidden bool `json:"is_hidden"` + Options map[string]bool `json:"options"` +} + type LoginResponse struct { Logins []Login `json:"logins"` Paging `json:"paging"` @@ -95,11 +115,41 @@ func (api *Client) accessLogsRequest(ctx context.Context, path string, values ur return response, response.Err() } +func (api *Client) teamProfileRequest(ctx context.Context, client httpClient, path string, values url.Values) (*TeamProfileResponse, error) { + response := &TeamProfileResponse{} + err := api.postMethod(ctx, path, values, response) + if err != nil { + return nil, err + } + return response, response.Err() +} + // GetTeamInfo gets the Team Information of the user func (api *Client) GetTeamInfo() (*TeamInfo, error) { return api.GetTeamInfoContext(context.Background()) } +// GetOtherTeamInfoContext gets Team information for any team with a custom context +func (api *Client) GetOtherTeamInfoContext(ctx context.Context, team string) (*TeamInfo, error) { + if team == "" { + return api.GetTeamInfoContext(ctx) + } + values := url.Values{ + "token": {api.token}, + } + values.Add("team", team) + response, err := api.teamRequest(ctx, "team.info", values) + if err != nil { + return nil, err + } + return &response.Team, nil +} + +// GetOtherTeamInfo gets Team information for any team +func (api *Client) GetOtherTeamInfo(team string) (*TeamInfo, error) { + return api.GetOtherTeamInfoContext(context.Background(), team) +} + // GetTeamInfoContext gets the Team Information of the user with a custom context func (api *Client) GetTeamInfoContext(ctx context.Context) (*TeamInfo, error) { values := url.Values{ @@ -113,6 +163,25 @@ func (api *Client) GetTeamInfoContext(ctx context.Context) (*TeamInfo, error) { return &response.Team, nil } +// GetTeamProfile gets the Team Profile settings of the user +func (api *Client) GetTeamProfile() (*TeamProfile, error) { + return api.GetTeamProfileContext(context.Background()) +} + +// GetTeamProfileContext gets the Team Profile settings of the user with a custom context +func (api *Client) GetTeamProfileContext(ctx context.Context) (*TeamProfile, error) { + values := url.Values{ + "token": {api.token}, + } + + response, err := api.teamProfileRequest(ctx, api.httpclient, "team.profile.get", values) + if err != nil { + return nil, err + } + return &response.Profile, nil + +} + // GetAccessLogs retrieves a page of logins according to the parameters given func (api *Client) GetAccessLogs(params AccessLogParameters) ([]Login, *Paging, error) { return api.GetAccessLogsContext(context.Background(), params) diff --git a/vendor/github.com/slack-go/slack/users.go b/vendor/github.com/slack-go/slack/users.go index d22b44f8..55f42118 100644 --- a/vendor/github.com/slack-go/slack/users.go +++ b/vendor/github.com/slack-go/slack/users.go @@ -17,30 +17,38 @@ const ( // UserProfile contains all the information details of a given user type UserProfile struct { - FirstName string `json:"first_name"` - LastName string `json:"last_name"` - RealName string `json:"real_name"` - RealNameNormalized string `json:"real_name_normalized"` - DisplayName string `json:"display_name"` - DisplayNameNormalized string `json:"display_name_normalized"` - Email string `json:"email"` - Skype string `json:"skype"` - Phone string `json:"phone"` - Image24 string `json:"image_24"` - Image32 string `json:"image_32"` - Image48 string `json:"image_48"` - Image72 string `json:"image_72"` - Image192 string `json:"image_192"` - Image512 string `json:"image_512"` - ImageOriginal string `json:"image_original"` - Title string `json:"title"` - BotID string `json:"bot_id,omitempty"` - ApiAppID string `json:"api_app_id,omitempty"` - StatusText string `json:"status_text,omitempty"` - StatusEmoji string `json:"status_emoji,omitempty"` - StatusExpiration int `json:"status_expiration"` - Team string `json:"team"` - Fields UserProfileCustomFields `json:"fields"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + RealName string `json:"real_name"` + RealNameNormalized string `json:"real_name_normalized"` + DisplayName string `json:"display_name"` + DisplayNameNormalized string `json:"display_name_normalized"` + Email string `json:"email"` + Skype string `json:"skype"` + Phone string `json:"phone"` + Image24 string `json:"image_24"` + Image32 string `json:"image_32"` + Image48 string `json:"image_48"` + Image72 string `json:"image_72"` + Image192 string `json:"image_192"` + Image512 string `json:"image_512"` + ImageOriginal string `json:"image_original"` + Title string `json:"title"` + BotID string `json:"bot_id,omitempty"` + ApiAppID string `json:"api_app_id,omitempty"` + StatusText string `json:"status_text,omitempty"` + StatusEmoji string `json:"status_emoji,omitempty"` + StatusEmojiDisplayInfo []UserProfileStatusEmojiDisplayInfo `json:"status_emoji_display_info,omitempty"` + StatusExpiration int `json:"status_expiration"` + Team string `json:"team"` + Fields UserProfileCustomFields `json:"fields"` +} + +type UserProfileStatusEmojiDisplayInfo struct { + EmojiName string `json:"emoji_name"` + DisplayAlias string `json:"display_alias,omitempty"` + DisplayURL string `json:"display_url,omitempty"` + Unicode string `json:"unicode,omitempty"` } // UserProfileCustomFields represents user profile's custom fields. @@ -556,6 +564,55 @@ func (api *Client) SetUserRealNameContextWithUser(ctx context.Context, user, rea return response.Err() } +// SetUserCustomFields sets Custom Profile fields on the provided users account. Due to the non-repeating elements +// within the request, a map fields is required. The key in the map signifies the field that will be updated. +// +// Note: You may need to change the way the custom field is populated within the Profile section of the Admin Console from +// SCIM or User Entered to API. +// +// See GetTeamProfile for information to retrieve possible fields for your account. +func (api *Client) SetUserCustomFields(userID string, customFields map[string]UserProfileCustomField) error { + return api.SetUserCustomFieldsContext(context.Background(), userID, customFields) +} + +// SetUserCustomFieldsContext will set a users custom profile field with context. +// +// For more information see SetUserCustomFields +func (api *Client) SetUserCustomFieldsContext(ctx context.Context, userID string, customFields map[string]UserProfileCustomField) error { + + // Convert data to data type with custom marshall / unmarshall + // For more information, see UserProfileCustomFields definition. + updateFields := UserProfileCustomFields{} + updateFields.SetMap(customFields) + + // This anonymous struct is needed to set the fields level of the request data. The base struct for + // UserProfileCustomFields has an unexported variable named fields that does not contain a struct tag, + // which has resulted in this configuration. + profile, err := json.Marshal(&struct { + Fields UserProfileCustomFields `json:"fields"` + }{ + Fields: updateFields, + }) + + if err != nil { + return err + } + + values := url.Values{ + "token": {api.token}, + "user": {userID}, + "profile": {string(profile)}, + } + + response := &userResponseFull{} + if err := postForm(ctx, api.httpclient, APIURL+"users.profile.set", values, response, api); err != nil { + return err + } + + return response.Err() + +} + // SetUserCustomStatus will set a custom status and emoji for the currently // authenticated user. If statusEmoji is "" and statusText is not, the Slack API // will automatically set it to ":speech_balloon:". Otherwise, if both are "" diff --git a/vendor/github.com/slack-go/slack/webhooks.go b/vendor/github.com/slack-go/slack/webhooks.go index 2f8fb47f..e3233536 100644 --- a/vendor/github.com/slack-go/slack/webhooks.go +++ b/vendor/github.com/slack-go/slack/webhooks.go @@ -21,8 +21,8 @@ type WebhookMessage struct { Parse string `json:"parse,omitempty"` Blocks *Blocks `json:"blocks,omitempty"` ResponseType string `json:"response_type,omitempty"` - ReplaceOriginal bool `json:"replace_original,omitempty"` - DeleteOriginal bool `json:"delete_original,omitempty"` + ReplaceOriginal bool `json:"replace_original"` + DeleteOriginal bool `json:"delete_original"` ReplyBroadcast bool `json:"reply_broadcast,omitempty"` } diff --git a/vendor/github.com/slack-go/slack/websocket_reactions.go b/vendor/github.com/slack-go/slack/websocket_reactions.go index e4973878..6098a6ca 100644 --- a/vendor/github.com/slack-go/slack/websocket_reactions.go +++ b/vendor/github.com/slack-go/slack/websocket_reactions.go @@ -1,7 +1,7 @@ package slack -// reactionItem is a lighter-weight item than is returned by the reactions list. -type reactionItem struct { +// ReactionItem is a lighter-weight item than is returned by the reactions list. +type ReactionItem struct { Type string `json:"type"` Channel string `json:"channel,omitempty"` File string `json:"file,omitempty"` @@ -9,17 +9,17 @@ type reactionItem struct { Timestamp string `json:"ts,omitempty"` } -type reactionEvent struct { +type ReactionEvent struct { Type string `json:"type"` User string `json:"user"` ItemUser string `json:"item_user"` - Item reactionItem `json:"item"` + Item ReactionItem `json:"item"` Reaction string `json:"reaction"` EventTimestamp string `json:"event_ts"` } // ReactionAddedEvent represents the Reaction added event -type ReactionAddedEvent reactionEvent +type ReactionAddedEvent ReactionEvent // ReactionRemovedEvent represents the Reaction removed event -type ReactionRemovedEvent reactionEvent +type ReactionRemovedEvent ReactionEvent diff --git a/vendor/github.com/slack-go/slack/workflow_step_execute.go b/vendor/github.com/slack-go/slack/workflow_step_execute.go index 18516f23..32db9ba0 100644 --- a/vendor/github.com/slack-go/slack/workflow_step_execute.go +++ b/vendor/github.com/slack-go/slack/workflow_step_execute.go @@ -19,10 +19,10 @@ type ( } ) -type WorkflowStepCompletedRequestOption func(opt WorkflowStepCompletedRequest) error +type WorkflowStepCompletedRequestOption func(opt *WorkflowStepCompletedRequest) error func WorkflowStepCompletedRequestOptionOutput(outputs map[string]string) WorkflowStepCompletedRequestOption { - return func(opt WorkflowStepCompletedRequest) error { + return func(opt *WorkflowStepCompletedRequest) error { if len(outputs) > 0 { opt.Outputs = outputs } @@ -33,7 +33,7 @@ func WorkflowStepCompletedRequestOptionOutput(outputs map[string]string) Workflo // WorkflowStepCompleted indicates step is completed func (api *Client) WorkflowStepCompleted(workflowStepExecuteID string, options ...WorkflowStepCompletedRequestOption) error { // More information: https://api.slack.com/methods/workflows.stepCompleted - r := WorkflowStepCompletedRequest{ + r := &WorkflowStepCompletedRequest{ WorkflowStepExecuteID: workflowStepExecuteID, } for _, option := range options { |