diff --git a/go.mod b/go.mod index 844d8dc6..b5b18874 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,8 @@ require ( github.com/labstack/echo v0.0.0-20180219162101-7eec915044a1 github.com/labstack/gommon v0.2.1 // indirect github.com/lrstanley/girc v0.0.0-20180913221000-0fb5b684054e + github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5 // indirect + github.com/lusis/slack-test v0.0.0-20180109053238-3c758769bfa6 // indirect github.com/magiconair/properties v0.0.0-20180217134545-2c9e95027885 // indirect github.com/matterbridge/discordgo v0.0.0-20180806170629-ef40ff5ba64f github.com/matterbridge/go-xmpp v0.0.0-20180529212104-cd19799fba91 @@ -41,7 +43,7 @@ require ( github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474 // indirect github.com/mrexodia/wray v0.0.0-20160318003008-78a2c1f284ff // indirect github.com/nicksnyder/go-i18n v1.4.0 // indirect - github.com/nlopes/slack v0.3.1-0.20180805133408-21749ab136a8 + github.com/nlopes/slack v0.4.0 github.com/onsi/ginkgo v1.6.0 // indirect github.com/onsi/gomega v1.4.1 // indirect github.com/paulrosania/go-charset v0.0.0-20151028000031-621bb39fcc83 diff --git a/go.sum b/go.sum index aa2f2f05..832c279e 100644 --- a/go.sum +++ b/go.sum @@ -51,10 +51,12 @@ github.com/labstack/echo v0.0.0-20180219162101-7eec915044a1 h1:cOIt0LZKdfeirAfTP github.com/labstack/echo v0.0.0-20180219162101-7eec915044a1/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= github.com/labstack/gommon v0.2.1 h1:C+I4NYknueQncqKYZQ34kHsLZJVeB5KwPUhnO0nmbpU= github.com/labstack/gommon v0.2.1/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4= -github.com/lrstanley/girc v0.0.0-20180427160007-102f17f86306 h1:IqN61cmi7LM/IaYaP9a/KXFtHRS2a3+WHu8GhAXJT7c= -github.com/lrstanley/girc v0.0.0-20180427160007-102f17f86306/go.mod h1:7cRs1SIBfKQ7e3Tam6GKTILSNHzR862JD0JpINaZoJk= github.com/lrstanley/girc v0.0.0-20180913221000-0fb5b684054e h1:RpktB2igr6nS1EN7bCvjldAEfngrM5GyAbmOa4/cafU= github.com/lrstanley/girc v0.0.0-20180913221000-0fb5b684054e/go.mod h1:7cRs1SIBfKQ7e3Tam6GKTILSNHzR862JD0JpINaZoJk= +github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5 h1:AsEBgzv3DhuYHI/GiQh2HxvTP71HCCE9E/tzGUzGdtU= +github.com/lusis/go-slackbot v0.0.0-20180109053408-401027ccfef5/go.mod h1:c2mYKRyMb1BPkO5St0c/ps62L4S0W2NAkaTXj9qEI+0= +github.com/lusis/slack-test v0.0.0-20180109053238-3c758769bfa6 h1:iOAVXzZyXtW408TMYejlUPo6BIn92HmOacWtIfNyYns= +github.com/lusis/slack-test v0.0.0-20180109053238-3c758769bfa6/go.mod h1:sFlOUpQL1YcjhFVXhg1CG8ZASEs/Mf1oVb6H75JL/zg= github.com/magiconair/properties v0.0.0-20180217134545-2c9e95027885 h1:HWxJJvF+QceKcql4r9PC93NtMEgEBfBxlQrZPvbcQvs= github.com/magiconair/properties v0.0.0-20180217134545-2c9e95027885/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/matterbridge/discordgo v0.0.0-20180806170629-ef40ff5ba64f h1:9IIOO9Aznn8zJx3nokZ4U6nfuzWw5xAlygPvuRZMisQ= @@ -83,10 +85,8 @@ github.com/mrexodia/wray v0.0.0-20160318003008-78a2c1f284ff h1:HLGD5/9UxxfEuO9Dt github.com/mrexodia/wray v0.0.0-20160318003008-78a2c1f284ff/go.mod h1:B8jLfIIPn2sKyWr0D7cL2v7tnrDD5z291s2Zypdu89E= github.com/nicksnyder/go-i18n v1.4.0 h1:AgLl+Yq7kg5OYlzCgu9cKTZOyI4tD/NgukKqLqC8E+I= github.com/nicksnyder/go-i18n v1.4.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q= -github.com/nlopes/slack v0.0.0-20180101221843-107290b5bbaf h1:M+xGhDxie/MqC+tzs+3ZHBSY4Wsv+fEkrpIMCKy8PTg= -github.com/nlopes/slack v0.0.0-20180101221843-107290b5bbaf/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM= -github.com/nlopes/slack v0.3.1-0.20180805133408-21749ab136a8 h1:PSy8NkmkyldLmPPnNNw7mwfQFOHDqOI6bINpJ+/KV7Y= -github.com/nlopes/slack v0.3.1-0.20180805133408-21749ab136a8/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM= +github.com/nlopes/slack v0.4.0 h1:OVnHm7lv5gGT5gkcHsZAyw++oHVFihbjWbL3UceUpiA= +github.com/nlopes/slack v0.4.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM= github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.1 h1:PZSj/UFNaVp3KxrzHOcS7oyuWA7LoOY/77yCTEFu21U= diff --git a/vendor/github.com/labstack/echo/Gopkg.toml b/vendor/github.com/labstack/echo/Gopkg.toml new file mode 100644 index 00000000..a24f61b9 --- /dev/null +++ b/vendor/github.com/labstack/echo/Gopkg.toml @@ -0,0 +1,87 @@ + +## Gopkg.toml example (these lines may be deleted) + +## "metadata" defines metadata about the project that could be used by other independent +## systems. The metadata defined here will be ignored by dep. +# [metadata] +# key1 = "value that convey data to other systems" +# system1-data = "value that is used by a system" +# system2-data = "value that is used by another system" + +## "required" lists a set of packages (not projects) that must be included in +## Gopkg.lock. This list is merged with the set of packages imported by the current +## project. Use it when your project needs a package it doesn't explicitly import - +## including "main" packages. +# required = ["github.com/user/thing/cmd/thing"] + +## "ignored" lists a set of packages (not projects) that are ignored when +## dep statically analyzes source code. Ignored packages can be in this project, +## or in a dependency. +# ignored = ["github.com/user/project/badpkg"] + +## Constraints are rules for how directly imported projects +## may be incorporated into the depgraph. They are respected by +## dep whether coming from the Gopkg.toml of the current project or a dependency. +# [[constraint]] +## Required: the root import path of the project being constrained. +# name = "github.com/user/project" +# +## Recommended: the version constraint to enforce for the project. +## Only one of "branch", "version" or "revision" can be specified. +# version = "1.0.0" +# branch = "master" +# revision = "abc123" +# +## Optional: an alternate location (URL or import path) for the project's source. +# source = "https://github.com/myfork/package.git" +# +## "metadata" defines metadata about the dependency or override that could be used +## by other independent systems. The metadata defined here will be ignored by dep. +# [metadata] +# key1 = "value that convey data to other systems" +# system1-data = "value that is used by a system" +# system2-data = "value that is used by another system" + +## Overrides have the same structure as [[constraint]], but supersede all +## [[constraint]] declarations from all projects. Only [[override]] from +## the current project's are applied. +## +## Overrides are a sledgehammer. Use them only as a last resort. +# [[override]] +## Required: the root import path of the project being constrained. +# name = "github.com/user/project" +# +## Optional: specifying a version constraint override will cause all other +## constraints on this project to be ignored; only the overridden constraint +## need be satisfied. +## Again, only one of "branch", "version" or "revision" can be specified. +# version = "1.0.0" +# branch = "master" +# revision = "abc123" +# +## Optional: specifying an alternate source location as an override will +## enforce that the alternate location is used for that project, regardless of +## what source location any dependent projects specify. +# source = "https://github.com/myfork/package.git" + + + +[[constraint]] + name = "github.com/dgrijalva/jwt-go" + version = "3.0.0" + +[[constraint]] + name = "github.com/labstack/gommon" + version = "0.2.1" + +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.1.4" + +[[constraint]] + branch = "master" + name = "github.com/valyala/fasttemplate" + +[[constraint]] + branch = "master" + name = "golang.org/x/crypto" 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 @@ -13,6 +13,12 @@ revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b" 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"] @@ -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("&", "&", "<", "<", ">", ">") - 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("&", "&", "<", "<", ">", ">") + 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(¶ms) + } + 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"` +} diff --git a/vendor/github.com/pelletier/go-toml/benchmark.toml b/vendor/github.com/pelletier/go-toml/benchmark.toml new file mode 100644 index 00000000..dfd77e09 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/benchmark.toml @@ -0,0 +1,244 @@ +################################################################################ +## Comment + +# Speak your mind with the hash symbol. They go from the symbol to the end of +# the line. + + +################################################################################ +## Table + +# Tables (also known as hash tables or dictionaries) are collections of +# key/value pairs. They appear in square brackets on a line by themselves. + +[table] + +key = "value" # Yeah, you can do this. + +# Nested tables are denoted by table names with dots in them. Name your tables +# whatever crap you please, just don't use #, ., [ or ]. + +[table.subtable] + +key = "another value" + +# You don't need to specify all the super-tables if you don't want to. TOML +# knows how to do it for you. + +# [x] you +# [x.y] don't +# [x.y.z] need these +[x.y.z.w] # for this to work + + +################################################################################ +## Inline Table + +# Inline tables provide a more compact syntax for expressing tables. They are +# especially useful for grouped data that can otherwise quickly become verbose. +# Inline tables are enclosed in curly braces `{` and `}`. No newlines are +# allowed between the curly braces unless they are valid within a value. + +[table.inline] + +name = { first = "Tom", last = "Preston-Werner" } +point = { x = 1, y = 2 } + + +################################################################################ +## String + +# There are four ways to express strings: basic, multi-line basic, literal, and +# multi-line literal. All strings must contain only valid UTF-8 characters. + +[string.basic] + +basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF." + +[string.multiline] + +# The following strings are byte-for-byte equivalent: +key1 = "One\nTwo" +key2 = """One\nTwo""" +key3 = """ +One +Two""" + +[string.multiline.continued] + +# The following strings are byte-for-byte equivalent: +key1 = "The quick brown fox jumps over the lazy dog." + +key2 = """ +The quick brown \ + + + fox jumps over \ + the lazy dog.""" + +key3 = """\ + The quick brown \ + fox jumps over \ + the lazy dog.\ + """ + +[string.literal] + +# What you see is what you get. +winpath = 'C:\Users\nodejs\templates' +winpath2 = '\\ServerX\admin$\system32\' +quoted = 'Tom "Dubs" Preston-Werner' +regex = '<\i\c*\s*>' + + +[string.literal.multiline] + +regex2 = '''I [dw]on't need \d{2} apples''' +lines = ''' +The first newline is +trimmed in raw strings. + All other whitespace + is preserved. +''' + + +################################################################################ +## Integer + +# Integers are whole numbers. Positive numbers may be prefixed with a plus sign. +# Negative numbers are prefixed with a minus sign. + +[integer] + +key1 = +99 +key2 = 42 +key3 = 0 +key4 = -17 + +[integer.underscores] + +# For large numbers, you may use underscores to enhance readability. Each +# underscore must be surrounded by at least one digit. +key1 = 1_000 +key2 = 5_349_221 +key3 = 1_2_3_4_5 # valid but inadvisable + + +################################################################################ +## Float + +# A float consists of an integer part (which may be prefixed with a plus or +# minus sign) followed by a fractional part and/or an exponent part. + +[float.fractional] + +key1 = +1.0 +key2 = 3.1415 +key3 = -0.01 + +[float.exponent] + +key1 = 5e+22 +key2 = 1e6 +key3 = -2E-2 + +[float.both] + +key = 6.626e-34 + +[float.underscores] + +key1 = 9_224_617.445_991_228_313 +key2 = 1e1_00 + + +################################################################################ +## Boolean + +# Booleans are just the tokens you're used to. Always lowercase. + +[boolean] + +True = true +False = false + + +################################################################################ +## Datetime + +# Datetimes are RFC 3339 dates. + +[datetime] + +key1 = 1979-05-27T07:32:00Z +key2 = 1979-05-27T00:32:00-07:00 +key3 = 1979-05-27T00:32:00.999999-07:00 + + +################################################################################ +## Array + +# Arrays are square brackets with other primitives inside. Whitespace is +# ignored. Elements are separated by commas. Data types may not be mixed. + +[array] + +key1 = [ 1, 2, 3 ] +key2 = [ "red", "yellow", "green" ] +key3 = [ [ 1, 2 ], [3, 4, 5] ] +#key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok + +# Arrays can also be multiline. So in addition to ignoring whitespace, arrays +# also ignore newlines between the brackets. Terminating commas are ok before +# the closing bracket. + +key5 = [ + 1, 2, 3 +] +key6 = [ + 1, + 2, # this is ok +] + + +################################################################################ +## Array of Tables + +# These can be expressed by using a table name in double brackets. Each table +# with the same double bracketed name will be an element in the array. The +# tables are inserted in the order encountered. + +[[products]] + +name = "Hammer" +sku = 738594937 + +[[products]] + +[[products]] + +name = "Nail" +sku = 284758393 +color = "gray" + + +# You can create nested arrays of tables as well. + +[[fruit]] + name = "apple" + + [fruit.physical] + color = "red" + shape = "round" + + [[fruit.variety]] + name = "red delicious" + + [[fruit.variety]] + name = "granny smith" + +[[fruit]] + name = "banana" + + [[fruit.variety]] + name = "plantain" diff --git a/vendor/github.com/pelletier/go-toml/example-crlf.toml b/vendor/github.com/pelletier/go-toml/example-crlf.toml new file mode 100644 index 00000000..12950a16 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/example-crlf.toml @@ -0,0 +1,29 @@ +# This is a TOML document. Boom. + +title = "TOML Example" + +[owner] +name = "Tom Preston-Werner" +organization = "GitHub" +bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." +dob = 1979-05-27T07:32:00Z # First class dates? Why not? + +[database] +server = "192.168.1.1" +ports = [ 8001, 8001, 8002 ] +connection_max = 5000 +enabled = true + +[servers] + + # You can indent as you please. Tabs or spaces. TOML don't care. + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + +[clients] +data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it diff --git a/vendor/github.com/pelletier/go-toml/example.toml b/vendor/github.com/pelletier/go-toml/example.toml new file mode 100644 index 00000000..3d902f28 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/example.toml @@ -0,0 +1,29 @@ +# This is a TOML document. Boom. + +title = "TOML Example" + +[owner] +name = "Tom Preston-Werner" +organization = "GitHub" +bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." +dob = 1979-05-27T07:32:00Z # First class dates? Why not? + +[database] +server = "192.168.1.1" +ports = [ 8001, 8001, 8002 ] +connection_max = 5000 +enabled = true + +[servers] + + # You can indent as you please. Tabs or spaces. TOML don't care. + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + +[clients] +data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it diff --git a/vendor/github.com/pelletier/go-toml/marshal_test.toml b/vendor/github.com/pelletier/go-toml/marshal_test.toml new file mode 100644 index 00000000..1c5f98e7 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/marshal_test.toml @@ -0,0 +1,38 @@ +title = "TOML Marshal Testing" + +[basic] + bool = true + date = 1979-05-27T07:32:00Z + float = 123.4 + int = 5000 + string = "Bite me" + uint = 5001 + +[basic_lists] + bools = [true,false,true] + dates = [1979-05-27T07:32:00Z,1980-05-27T07:32:00Z] + floats = [12.3,45.6,78.9] + ints = [8001,8001,8002] + strings = ["One","Two","Three"] + uints = [5002,5003] + +[basic_map] + one = "one" + two = "two" + +[subdoc] + + [subdoc.first] + name = "First" + + [subdoc.second] + name = "Second" + +[[subdoclist]] + name = "List.First" + +[[subdoclist]] + name = "List.Second" + +[[subdocptrs]] + name = "Second" diff --git a/vendor/modules.txt b/vendor/modules.txt index c95b593e..9a59b2ce 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -95,8 +95,9 @@ github.com/nicksnyder/go-i18n/i18n github.com/nicksnyder/go-i18n/i18n/bundle github.com/nicksnyder/go-i18n/i18n/language github.com/nicksnyder/go-i18n/i18n/translation -# github.com/nlopes/slack v0.3.1-0.20180805133408-21749ab136a8 +# github.com/nlopes/slack v0.4.0 github.com/nlopes/slack +github.com/nlopes/slack/slackutilsx # github.com/paulrosania/go-charset v0.0.0-20151028000031-621bb39fcc83 github.com/paulrosania/go-charset/charset github.com/paulrosania/go-charset/data