summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuco van Amstel <duco.vanamstel@gmail.com>2018-10-07 22:17:46 +0100
committerWim <wim@42.be>2018-10-07 23:17:46 +0200
commit917040b044e349eadc886f9685ada30d164687eb (patch)
treeea063d87a415f89060b376f29a844e4d1ed86363
parent69646a160d8597944c307334901f0acfd32582c5 (diff)
downloadmatterbridge-msglm-917040b044e349eadc886f9685ada30d164687eb.tar.gz
matterbridge-msglm-917040b044e349eadc886f9685ada30d164687eb.tar.bz2
matterbridge-msglm-917040b044e349eadc886f9685ada30d164687eb.zip
Update of nlopes/slack dependency (#511)
-rw-r--r--go.mod4
-rw-r--r--go.sum12
-rw-r--r--vendor/github.com/labstack/echo/Gopkg.toml87
-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
-rw-r--r--vendor/github.com/pelletier/go-toml/benchmark.toml244
-rw-r--r--vendor/github.com/pelletier/go-toml/example-crlf.toml29
-rw-r--r--vendor/github.com/pelletier/go-toml/example.toml29
-rw-r--r--vendor/github.com/pelletier/go-toml/marshal_test.toml38
-rw-r--r--vendor/modules.txt3
23 files changed, 992 insertions, 92 deletions
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
@@ -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"`
+}
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