Update nlopes/slack to slack-go/slack

Fixes #236
This commit is contained in:
erroneousboat 2020-03-28 08:46:26 +01:00
parent 2ee21247ad
commit d63dd6006e
104 changed files with 1737 additions and 381 deletions

6
go.mod
View File

@ -6,15 +6,15 @@ require (
github.com/0xAX/notificator v0.0.0-20171022182052-88d57ee9043b
github.com/OpenPeeDeeP/xdg v0.2.0
github.com/erroneousboat/termui v0.0.0-20170923115141-80f245cdfa04
github.com/gorilla/websocket v1.4.1 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/lithammer/fuzzysearch v1.1.0
github.com/maruel/panicparse v1.1.1 // indirect
github.com/mattn/go-runewidth v0.0.7
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
github.com/nlopes/slack v0.6.1-0.20191106133607-d06c2a2b3249
github.com/nsf/termbox-go v0.0.0-20191229070316-58d4fcbce2a7
github.com/pkg/errors v0.8.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/slack-go/slack v0.6.3
github.com/stretchr/testify v1.4.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v2 v2.2.4 // indirect

16
go.sum
View File

@ -7,9 +7,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/erroneousboat/termui v0.0.0-20170923115141-80f245cdfa04 h1:DaFwoQC0Neeb2y2CVFxDPrS1BeyWAkKc4VVBDTZ0N98=
github.com/erroneousboat/termui v0.0.0-20170923115141-80f245cdfa04/go.mod h1:UPpsbgDrqmUayOFOkCGD7+xrBIml/1dA0dsqTRnZqac=
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@ -23,15 +25,17 @@ github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+tw
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/nlopes/slack v0.6.1-0.20191106133607-d06c2a2b3249 h1:Pr5gZa2VcmktVwq0lyC39MsN5tz356vC/pQHKvq+QBo=
github.com/nlopes/slack v0.6.1-0.20191106133607-d06c2a2b3249/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk=
github.com/nlopes/slack v0.6.0 h1:jt0jxVQGhssx1Ib7naAOZEZcGdtIhTzkP0nopK0AsRA=
github.com/nlopes/slack v0.6.0/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk=
github.com/nsf/termbox-go v0.0.0-20191229070316-58d4fcbce2a7 h1:OkWEy7aQeQTbgdrcGi9bifx+Y6bMM7ae7y42hDFaBvA=
github.com/nsf/termbox-go v0.0.0-20191229070316-58d4fcbce2a7/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/slack-go/slack v0.6.3 h1:qU037g8gQ71EuH6S9zYKnvYrEUj0fLFH4HFekFqBoRU=
github.com/slack-go/slack v0.6.3/go.mod h1:HE4RwNe7YpOg/F0vqo5PwXH3Hki31TplTvKRW9dGGaw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

View File

@ -11,8 +11,8 @@ import (
"github.com/0xAX/notificator"
"github.com/erroneousboat/termui"
"github.com/nlopes/slack"
termbox "github.com/nsf/termbox-go"
"github.com/slack-go/slack"
"github.com/erroneousboat/slack-term/components"
"github.com/erroneousboat/slack-term/config"

View File

@ -13,7 +13,7 @@ import (
"sync"
"time"
"github.com/nlopes/slack"
"github.com/slack-go/slack"
"github.com/erroneousboat/slack-term/components"
"github.com/erroneousboat/slack-term/config"

View File

@ -8,7 +8,7 @@ Gorilla WebSocket is a [Go](http://golang.org/) implementation of the
### Documentation
* [API Reference](http://godoc.org/github.com/gorilla/websocket)
* [API Reference](https://pkg.go.dev/github.com/gorilla/websocket?tab=doc)
* [Chat example](https://github.com/gorilla/websocket/tree/master/examples/chat)
* [Command example](https://github.com/gorilla/websocket/tree/master/examples/command)
* [Client and server example](https://github.com/gorilla/websocket/tree/master/examples/echo)

View File

@ -244,8 +244,8 @@ type Conn struct {
subprotocol string
// Write fields
mu chan bool // used as mutex to protect write to conn
writeBuf []byte // frame is constructed in this buffer.
mu chan struct{} // used as mutex to protect write to conn
writeBuf []byte // frame is constructed in this buffer.
writePool BufferPool
writeBufSize int
writeDeadline time.Time
@ -302,8 +302,8 @@ func newConn(conn net.Conn, isServer bool, readBufferSize, writeBufferSize int,
writeBuf = make([]byte, writeBufferSize)
}
mu := make(chan bool, 1)
mu <- true
mu := make(chan struct{}, 1)
mu <- struct{}{}
c := &Conn{
isServer: isServer,
br: br,
@ -377,7 +377,7 @@ func (c *Conn) read(n int) ([]byte, error) {
func (c *Conn) write(frameType int, deadline time.Time, buf0, buf1 []byte) error {
<-c.mu
defer func() { c.mu <- true }()
defer func() { c.mu <- struct{}{} }()
c.writeErrMu.Lock()
err := c.writeErr
@ -429,7 +429,7 @@ func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) er
maskBytes(key, 0, buf[6:])
}
d := time.Hour * 1000
d := 1000 * time.Hour
if !deadline.IsZero() {
d = deadline.Sub(time.Now())
if d < 0 {
@ -444,7 +444,7 @@ func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) er
case <-timer.C:
return errWriteTimeout
}
defer func() { c.mu <- true }()
defer func() { c.mu <- struct{}{} }()
c.writeErrMu.Lock()
err := c.writeErr

View File

@ -187,9 +187,9 @@
// than the largest message do not provide any benefit.
//
// Depending on the distribution of message sizes, setting the buffer size to
// to a value less than the maximum expected message size can greatly reduce
// memory use with a small impact on performance. Here's an example: If 99% of
// the messages are smaller than 256 bytes and the maximum message size is 512
// a value less than the maximum expected message size can greatly reduce memory
// use with a small impact on performance. Here's an example: If 99% of the
// messages are smaller than 256 bytes and the maximum message size is 512
// bytes, then a buffer size of 256 bytes will result in 1.01 more system calls
// than a buffer size of 512 bytes. The memory savings is 50%.
//

View File

@ -1,2 +0,0 @@
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=

View File

@ -73,8 +73,8 @@ func (pm *PreparedMessage) frame(key prepareKey) (int, []byte, error) {
// Prepare a frame using a 'fake' connection.
// TODO: Refactor code in conn.go to allow more direct construction of
// the frame.
mu := make(chan bool, 1)
mu <- true
mu := make(chan struct{}, 1)
mu <- struct{}{}
var nc prepareConn
c := &Conn{
conn: &nc,

View File

@ -1,9 +0,0 @@
module github.com/nlopes/slack
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gorilla/websocket v1.2.0
github.com/pkg/errors v0.8.0
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.2.2
)

View File

@ -1,22 +0,0 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/nlopes/slack v0.1.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM=
github.com/nlopes/slack v0.5.0 h1:NbIae8Kd0NpqaEI3iUrsuS0KbcEDhzhc939jLW5fNm0=
github.com/nlopes/slack v0.5.0/go.mod h1:jVI4BBK3lSktibKahxBF74txcK2vyvkza1z/+rRnVAM=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/victorcoder/slack-test v0.0.0-20190131110821-6f9a569c10af h1:JFxr+No3ZWgCtxnnTWCybnB/z0Iy3qLmdj3u2NV5o48=
github.com/victorcoder/slack-test v0.0.0-20190131110821-6f9a569c10af/go.mod h1:dStM4ShMus8J3hiq66ExbbzGLkwyZ+RQJePwFhWCCvQ=
github.com/victorcoder/slack-test v0.0.0-20190131113129-a43b3bb77f43 h1:wtFekkaAAQibpy3iE4Hhx2Gi9pZAbITOSfVP7GXk5eM=
github.com/victorcoder/slack-test v0.0.0-20190131113129-a43b3bb77f43/go.mod h1:dStM4ShMus8J3hiq66ExbbzGLkwyZ+RQJePwFhWCCvQ=
golang.org/x/net v0.0.0-20180108090419-434ec0c7fe37 h1:BkNcmLtAVeWe9h5k0jt24CQgaG5vb4x/doFbAiEC/Ho=
golang.org/x/net v0.0.0-20180108090419-434ec0c7fe37/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=

View File

@ -1,195 +0,0 @@
package slack
import (
"bytes"
"fmt"
"strconv"
"time"
)
// UserPrefs needs to be implemented
type UserPrefs struct {
// "highlight_words":"",
// "user_colors":"",
// "color_names_in_list":true,
// "growls_enabled":true,
// "tz":"Europe\/London",
// "push_dm_alert":true,
// "push_mention_alert":true,
// "push_everything":true,
// "push_idle_wait":2,
// "push_sound":"b2.mp3",
// "push_loud_channels":"",
// "push_mention_channels":"",
// "push_loud_channels_set":"",
// "email_alerts":"instant",
// "email_alerts_sleep_until":0,
// "email_misc":false,
// "email_weekly":true,
// "welcome_message_hidden":false,
// "all_channels_loud":true,
// "loud_channels":"",
// "never_channels":"",
// "loud_channels_set":"",
// "show_member_presence":true,
// "search_sort":"timestamp",
// "expand_inline_imgs":true,
// "expand_internal_inline_imgs":true,
// "expand_snippets":false,
// "posts_formatting_guide":true,
// "seen_welcome_2":true,
// "seen_ssb_prompt":false,
// "search_only_my_channels":false,
// "emoji_mode":"default",
// "has_invited":true,
// "has_uploaded":false,
// "has_created_channel":true,
// "search_exclude_channels":"",
// "messages_theme":"default",
// "webapp_spellcheck":true,
// "no_joined_overlays":false,
// "no_created_overlays":true,
// "dropbox_enabled":false,
// "seen_user_menu_tip_card":true,
// "seen_team_menu_tip_card":true,
// "seen_channel_menu_tip_card":true,
// "seen_message_input_tip_card":true,
// "seen_channels_tip_card":true,
// "seen_domain_invite_reminder":false,
// "seen_member_invite_reminder":false,
// "seen_flexpane_tip_card":true,
// "seen_search_input_tip_card":true,
// "mute_sounds":false,
// "arrow_history":false,
// "tab_ui_return_selects":true,
// "obey_inline_img_limit":true,
// "new_msg_snd":"knock_brush.mp3",
// "collapsible":false,
// "collapsible_by_click":true,
// "require_at":false,
// "mac_ssb_bounce":"",
// "mac_ssb_bullet":true,
// "win_ssb_bullet":true,
// "expand_non_media_attachments":true,
// "show_typing":true,
// "pagekeys_handled":true,
// "last_snippet_type":"",
// "display_real_names_override":0,
// "time24":false,
// "enter_is_special_in_tbt":false,
// "graphic_emoticons":false,
// "convert_emoticons":true,
// "autoplay_chat_sounds":true,
// "ss_emojis":true,
// "sidebar_behavior":"",
// "mark_msgs_read_immediately":true,
// "start_scroll_at_oldest":true,
// "snippet_editor_wrap_long_lines":false,
// "ls_disabled":false,
// "sidebar_theme":"default",
// "sidebar_theme_custom_values":"",
// "f_key_search":false,
// "k_key_omnibox":true,
// "speak_growls":false,
// "mac_speak_voice":"com.apple.speech.synthesis.voice.Alex",
// "mac_speak_speed":250,
// "comma_key_prefs":false,
// "at_channel_suppressed_channels":"",
// "push_at_channel_suppressed_channels":"",
// "prompted_for_email_disabling":false,
// "full_text_extracts":false,
// "no_text_in_notifications":false,
// "muted_channels":"",
// "no_macssb1_banner":false,
// "privacy_policy_seen":true,
// "search_exclude_bots":false,
// "fuzzy_matching":false
}
// UserDetails contains user details coming in the initial response from StartRTM
type UserDetails struct {
ID string `json:"id"`
Name string `json:"name"`
Created JSONTime `json:"created"`
ManualPresence string `json:"manual_presence"`
Prefs UserPrefs `json:"prefs"`
}
// JSONTime exists so that we can have a String method converting the date
type JSONTime int64
// String converts the unix timestamp into a string
func (t JSONTime) String() string {
tm := t.Time()
return fmt.Sprintf("\"%s\"", tm.Format("Mon Jan _2"))
}
// Time returns a `time.Time` representation of this value.
func (t JSONTime) Time() time.Time {
return time.Unix(int64(t), 0)
}
// UnmarshalJSON will unmarshal both string and int JSON values
func (t *JSONTime) UnmarshalJSON(buf []byte) error {
s := bytes.Trim(buf, `"`)
v, err := strconv.Atoi(string(s))
if err != nil {
return err
}
*t = JSONTime(int64(v))
return nil
}
// Team contains details about a team
type Team struct {
ID string `json:"id"`
Name string `json:"name"`
Domain string `json:"domain"`
}
// Icons XXX: needs further investigation
type Icons struct {
Image36 string `json:"image_36,omitempty"`
Image48 string `json:"image_48,omitempty"`
Image72 string `json:"image_72,omitempty"`
}
// Info contains various details about the authenticated user and team.
// It is returned by StartRTM or included in the "ConnectedEvent" RTM event.
type Info struct {
URL string `json:"url,omitempty"`
User *UserDetails `json:"self,omitempty"`
Team *Team `json:"team,omitempty"`
}
type infoResponseFull struct {
Info
SlackResponse
}
// GetBotByID is deprecated and returns nil
func (info Info) GetBotByID(botID string) *Bot {
return nil
}
// GetUserByID is deprecated and returns nil
func (info Info) GetUserByID(userID string) *User {
return nil
}
// GetChannelByID is deprecated and returns nil
func (info Info) GetChannelByID(channelID string) *Channel {
return nil
}
// GetGroupByID is deprecated and returns nil
func (info Info) GetGroupByID(groupID string) *Group {
return nil
}
// GetIMByID is deprecated and returns nil
func (info Info) GetIMByID(imID string) *IM {
return nil
}

View File

@ -1,15 +1,10 @@
language: go
go_import_path: github.com/pkg/errors
go:
- 1.4.x
- 1.5.x
- 1.6.x
- 1.7.x
- 1.8.x
- 1.9.x
- 1.10.x
- 1.11.x
- 1.12.x
- 1.13.x
- tip
script:
- go test -v ./...
- make check

44
vendor/github.com/pkg/errors/Makefile generated vendored Normal file
View File

@ -0,0 +1,44 @@
PKGS := github.com/pkg/errors
SRCDIRS := $(shell go list -f '{{.Dir}}' $(PKGS))
GO := go
check: test vet gofmt misspell unconvert staticcheck ineffassign unparam
test:
$(GO) test $(PKGS)
vet: | test
$(GO) vet $(PKGS)
staticcheck:
$(GO) get honnef.co/go/tools/cmd/staticcheck
staticcheck -checks all $(PKGS)
misspell:
$(GO) get github.com/client9/misspell/cmd/misspell
misspell \
-locale GB \
-error \
*.md *.go
unconvert:
$(GO) get github.com/mdempsky/unconvert
unconvert -v $(PKGS)
ineffassign:
$(GO) get github.com/gordonklaus/ineffassign
find $(SRCDIRS) -name '*.go' | xargs ineffassign
pedantic: check errcheck
unparam:
$(GO) get mvdan.cc/unparam
unparam ./...
errcheck:
$(GO) get github.com/kisielk/errcheck
errcheck $(PKGS)
gofmt:
@echo Checking code is gofmted
@test -z "$(shell gofmt -s -l -d -e $(SRCDIRS) | tee /dev/stderr)"

View File

@ -41,11 +41,18 @@ default:
[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors).
## Roadmap
With the upcoming [Go2 error proposals](https://go.googlesource.com/proposal/+/master/design/go2draft.md) this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows:
- 0.9. Remove pre Go 1.9 and Go 1.10 support, address outstanding pull requests (if possible)
- 1.0. Final release.
## Contributing
We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high.
Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports.
Before proposing a change, please discuss your change by raising an issue.
Before sending a PR, please discuss your change by raising an issue.
## License

View File

@ -82,7 +82,7 @@
//
// if err, ok := err.(stackTracer); ok {
// for _, f := range err.StackTrace() {
// fmt.Printf("%+s:%d", f)
// fmt.Printf("%+s:%d\n", f, f)
// }
// }
//
@ -159,6 +159,9 @@ type withStack struct {
func (w *withStack) Cause() error { return w.error }
// Unwrap provides compatibility for Go 1.13 error chains.
func (w *withStack) Unwrap() error { return w.error }
func (w *withStack) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
@ -241,6 +244,9 @@ type withMessage struct {
func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
func (w *withMessage) Cause() error { return w.cause }
// Unwrap provides compatibility for Go 1.13 error chains.
func (w *withMessage) Unwrap() error { return w.cause }
func (w *withMessage) Format(s fmt.State, verb rune) {
switch verb {
case 'v':

38
vendor/github.com/pkg/errors/go113.go generated vendored Normal file
View File

@ -0,0 +1,38 @@
// +build go1.13
package errors
import (
stderrors "errors"
)
// Is reports whether any error in err's chain matches target.
//
// The chain consists of err itself followed by the sequence of errors obtained by
// repeatedly calling Unwrap.
//
// An error is considered to match a target if it is equal to that target or if
// it implements a method Is(error) bool such that Is(target) returns true.
func Is(err, target error) bool { return stderrors.Is(err, target) }
// As finds the first error in err's chain that matches target, and if so, sets
// target to that error value and returns true.
//
// The chain consists of err itself followed by the sequence of errors obtained by
// repeatedly calling Unwrap.
//
// An error matches target if the error's concrete value is assignable to the value
// pointed to by target, or if the error has a method As(interface{}) bool such that
// As(target) returns true. In the latter case, the As method is responsible for
// setting target.
//
// As will panic if target is not a non-nil pointer to either a type that implements
// error, or to any interface type. As returns false if err is nil.
func As(err error, target interface{}) bool { return stderrors.As(err, target) }
// Unwrap returns the result of calling the Unwrap method on err, if err's
// type contains an Unwrap method returning error.
// Otherwise, Unwrap returns nil.
func Unwrap(err error) error {
return stderrors.Unwrap(err)
}

View File

@ -5,10 +5,13 @@ import (
"io"
"path"
"runtime"
"strconv"
"strings"
)
// Frame represents a program counter inside a stack frame.
// For historical reasons if Frame is interpreted as a uintptr
// its value represents the program counter + 1.
type Frame uintptr
// pc returns the program counter for this frame;
@ -37,6 +40,15 @@ func (f Frame) line() int {
return line
}
// name returns the name of this function, if known.
func (f Frame) name() string {
fn := runtime.FuncForPC(f.pc())
if fn == nil {
return "unknown"
}
return fn.Name()
}
// Format formats the frame according to the fmt.Formatter interface.
//
// %s source file
@ -54,22 +66,16 @@ func (f Frame) Format(s fmt.State, verb rune) {
case 's':
switch {
case s.Flag('+'):
pc := f.pc()
fn := runtime.FuncForPC(pc)
if fn == nil {
io.WriteString(s, "unknown")
} else {
file, _ := fn.FileLine(pc)
fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file)
}
io.WriteString(s, f.name())
io.WriteString(s, "\n\t")
io.WriteString(s, f.file())
default:
io.WriteString(s, path.Base(f.file()))
}
case 'd':
fmt.Fprintf(s, "%d", f.line())
io.WriteString(s, strconv.Itoa(f.line()))
case 'n':
name := runtime.FuncForPC(f.pc()).Name()
io.WriteString(s, funcname(name))
io.WriteString(s, funcname(f.name()))
case 'v':
f.Format(s, 's')
io.WriteString(s, ":")
@ -77,6 +83,16 @@ func (f Frame) Format(s fmt.State, verb rune) {
}
}
// MarshalText formats a stacktrace Frame as a text string. The output is the
// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs.
func (f Frame) MarshalText() ([]byte, error) {
name := f.name()
if name == "unknown" {
return []byte(name), nil
}
return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil
}
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
type StackTrace []Frame
@ -94,18 +110,32 @@ func (st StackTrace) Format(s fmt.State, verb rune) {
switch {
case s.Flag('+'):
for _, f := range st {
fmt.Fprintf(s, "\n%+v", f)
io.WriteString(s, "\n")
f.Format(s, verb)
}
case s.Flag('#'):
fmt.Fprintf(s, "%#v", []Frame(st))
default:
fmt.Fprintf(s, "%v", []Frame(st))
st.formatSlice(s, verb)
}
case 's':
fmt.Fprintf(s, "%s", []Frame(st))
st.formatSlice(s, verb)
}
}
// formatSlice will format this StackTrace into the given buffer as a slice of
// Frame, only valid when called with '%s' or '%v'.
func (st StackTrace) formatSlice(s fmt.State, verb rune) {
io.WriteString(s, "[")
for i, f := range st {
if i > 0 {
io.WriteString(s, " ")
}
f.Format(s, verb)
}
io.WriteString(s, "]")
}
// stack represents a stack of program counters.
type stack []uintptr

36
vendor/github.com/slack-go/slack/Makefile generated vendored Normal file
View File

@ -0,0 +1,36 @@
.PHONY: help deps fmt lint test test-race test-integration
help:
@echo ""
@echo "Welcome to slack-go/slack make."
@echo "The following commands are available:"
@echo ""
@echo " make deps : Fetch all dependencies"
@echo " make fmt : Run go fmt to fix any formatting issues"
@echo " make lint : Use go vet to check for linting issues"
@echo " make test : Run all short tests"
@echo " make test-race : Run all tests with race condition checking"
@echo " make test-integration : Run all tests without limiting to short"
@echo ""
@echo " make pr-prep : Run this before making a PR to run fmt, lint and tests"
@echo ""
deps:
@go mod tidy
fmt:
@go fmt .
lint:
@go vet .
test:
@go test -v -count=1 -timeout 300s -short ./...
test-race:
@go test -v -count=1 -timeout 300s -short -race ./...
test-integration:
@go test -v -count=1 -timeout 600s ./...
pr-prep: fmt lint test-race test-integration

View File

@ -1,5 +1,6 @@
Slack API in Go [![GoDoc](https://godoc.org/github.com/nlopes/slack?status.svg)](https://godoc.org/github.com/nlopes/slack) [![Build Status](https://travis-ci.org/nlopes/slack.svg)](https://travis-ci.org/nlopes/slack)
Slack API in Go [![GoDoc](https://godoc.org/github.com/slack-go/slack?status.svg)](https://godoc.org/github.com/slack-go/slack) [![Build Status](https://travis-ci.org/slack-go/slack.svg)](https://travis-ci.org/slack-go/slack)
===============
This is the original Slack library for Go created by Norberto Lopez, transferred to a Github organization.
[![Join the chat at https://gitter.im/go-slack/Lobby](https://badges.gitter.im/go-slack/Lobby.svg)](https://gitter.im/go-slack/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@ -12,13 +13,13 @@ a fully managed way.
## Changelog
[CHANGELOG.md](https://github.com/nlopes/slack/blob/master/CHANGELOG.md) is available. Please visit it for updates.
[CHANGELOG.md](https://github.com/slack-go/slack/blob/master/CHANGELOG.md) is available. Please visit it for updates.
## Installing
### *go get*
$ go get -u github.com/nlopes/slack
$ go get -u github.com/slack-go/slack
## Example
@ -28,7 +29,7 @@ a fully managed way.
import (
"fmt"
"github.com/nlopes/slack"
"github.com/slack-go/slack"
)
func main() {
@ -53,7 +54,7 @@ func main() {
import (
"fmt"
"github.com/nlopes/slack"
"github.com/slack-go/slack"
)
func main() {
@ -69,12 +70,12 @@ func main() {
## Minimal RTM usage:
See https://github.com/nlopes/slack/blob/master/examples/websocket/websocket.go
See https://github.com/slack-go/slack/blob/master/examples/websocket/websocket.go
## Minimal EventsAPI usage:
See https://github.com/nlopes/slack/blob/master/examples/eventsapi/events.go
See https://github.com/slack-go/slack/blob/master/examples/eventsapi/events.go
## Contributing
@ -82,6 +83,14 @@ See https://github.com/nlopes/slack/blob/master/examples/eventsapi/events.go
You are more than welcome to contribute to this project. Fork and
make a Pull Request, or create an Issue if you see any problem.
Before making any Pull Request please run the following:
```
make pr-prep
```
This will check/update code formatting, linting and then run all tests
## License
BSD 2 Clause license

View File

@ -84,7 +84,7 @@ type Attachment struct {
Actions []AttachmentAction `json:"actions,omitempty"`
MarkdownIn []string `json:"mrkdwn_in,omitempty"`
Blocks []Block `json:"blocks,omitempty"`
Blocks Blocks `json:"blocks,omitempty"`
Footer string `json:"footer,omitempty"`
FooterIcon string `json:"footer_icon,omitempty"`

View File

@ -27,7 +27,7 @@ func (api *Client) SendAuthRevoke(token string) (*AuthRevokeResponse, error) {
return api.SendAuthRevokeContext(context.Background(), token)
}
// SendAuthRevokeContext will retrieve the satus from api.test
// SendAuthRevokeContext will send a revocation request for our token to api.revoke with context
func (api *Client) SendAuthRevokeContext(ctx context.Context, token string) (*AuthRevokeResponse, error) {
if token == "" {
token = api.token

View File

@ -14,6 +14,8 @@ const (
MBTImage MessageBlockType = "image"
MBTAction MessageBlockType = "actions"
MBTContext MessageBlockType = "context"
MBTFile MessageBlockType = "file"
MBTInput MessageBlockType = "input"
)
// Block defines an interface all block types should implement

View File

@ -56,15 +56,16 @@ func (b *Blocks) UnmarshalJSON(data []byte) error {
block = &ContextBlock{}
case "divider":
block = &DividerBlock{}
case "file":
block = &FileBlock{}
case "image":
block = &ImageBlock{}
case "input":
block = &InputBlock{}
case "section":
block = &SectionBlock{}
case "rich_text":
// for now ignore the (complex) content of rich_text blocks until we can fully support it
continue
default:
return errors.New("unsupported block type")
block = &UnknownBlock{}
}
err = json.Unmarshal(r, block)
@ -79,6 +80,46 @@ func (b *Blocks) UnmarshalJSON(data []byte) error {
return nil
}
// UnmarshalJSON implements the Unmarshaller interface for InputBlock, so that any JSON
// unmarshalling is delegated and proper type determination can be made before unmarshal
func (b *InputBlock) UnmarshalJSON(data []byte) error {
type alias InputBlock
a := struct {
Element json.RawMessage `json:"element"`
*alias
}{
alias: (*alias)(b),
}
if err := json.Unmarshal(data, &a); err != nil {
return err
}
s := sumtype{}
if err := json.Unmarshal(a.Element, &s); err != nil {
return nil
}
var e BlockElement
switch s.TypeVal {
case "datepicker":
e = &DatePickerBlockElement{}
case "plain_text_input":
e = &PlainTextInputBlockElement{}
case "static_select", "external_select", "users_select", "conversations_select", "channels_select":
e = &SelectBlockElement{}
default:
return errors.New("unsupported block element type")
}
if err := json.Unmarshal(a.Element, e); err != nil {
return err
}
b.Element = e
return nil
}
// MarshalJSON implements the Marshaller interface for BlockElements so that any JSON
// marshalling is delegated and proper type determination can be made before marshal
func (b *BlockElements) MarshalJSON() ([]byte, error) {
@ -127,6 +168,8 @@ func (b *BlockElements) UnmarshalJSON(data []byte) error {
blockElement = &OverflowBlockElement{}
case "datepicker":
blockElement = &DatePickerBlockElement{}
case "plain_text_input":
blockElement = &PlainTextInputBlockElement{}
case "static_select", "external_select", "users_select", "conversations_select", "channels_select":
blockElement = &SelectBlockElement{}
default:
@ -206,12 +249,36 @@ func (a *Accessory) UnmarshalJSON(data []byte) error {
return err
}
a.DatePickerElement = element.(*DatePickerBlockElement)
case "static_select":
case "plain_text_input":
element, err := unmarshalBlockElement(r, &PlainTextInputBlockElement{})
if err != nil {
return err
}
a.PlainTextInputElement = element.(*PlainTextInputBlockElement)
case "radio_buttons":
element, err := unmarshalBlockElement(r, &RadioButtonsBlockElement{})
if err != nil {
return err
}
a.RadioButtonsElement = element.(*RadioButtonsBlockElement)
case "static_select", "external_select", "users_select", "conversations_select", "channels_select":
element, err := unmarshalBlockElement(r, &SelectBlockElement{})
if err != nil {
return err
}
a.SelectElement = element.(*SelectBlockElement)
case "multi_static_select", "multi_external_select", "multi_users_select", "multi_conversations_select", "multi_channels_select":
element, err := unmarshalBlockElement(r, &MultiSelectBlockElement{})
if err != nil {
return err
}
a.MultiSelectElement = element.(*MultiSelectBlockElement)
default:
element, err := unmarshalBlockElement(r, &UnknownBlockElement{})
if err != nil {
return err
}
a.UnknownElement = element.(*UnknownBlockElement)
}
return nil
@ -238,9 +305,18 @@ func toBlockElement(element *Accessory) BlockElement {
if element.DatePickerElement != nil {
return element.DatePickerElement
}
if element.PlainTextInputElement != nil {
return element.PlainTextInputElement
}
if element.RadioButtonsElement != nil {
return element.RadioButtonsElement
}
if element.SelectElement != nil {
return element.SelectElement
}
if element.MultiSelectElement != nil {
return element.MultiSelectElement
}
return nil
}

View File

@ -3,10 +3,12 @@ package slack
// https://api.slack.com/reference/messaging/block-elements
const (
METImage MessageElementType = "image"
METButton MessageElementType = "button"
METOverflow MessageElementType = "overflow"
METDatepicker MessageElementType = "datepicker"
METImage MessageElementType = "image"
METButton MessageElementType = "button"
METOverflow MessageElementType = "overflow"
METDatepicker MessageElementType = "datepicker"
METPlainTextInput MessageElementType = "plain_text_input"
METRadioButtons MessageElementType = "radio_buttons"
MixedElementImage MixedElementType = "mixed_image"
MixedElementText MixedElementType = "mixed_text"
@ -16,6 +18,12 @@ const (
OptTypeUser string = "users_select"
OptTypeConversations string = "conversations_select"
OptTypeChannels string = "channels_select"
MultiOptTypeStatic string = "multi_static_select"
MultiOptTypeExternal string = "multi_external_select"
MultiOptTypeUser string = "multi_users_select"
MultiOptTypeConversations string = "multi_conversations_select"
MultiOptTypeChannels string = "multi_channels_select"
)
type MessageElementType string
@ -31,11 +39,15 @@ type MixedElement interface {
}
type Accessory struct {
ImageElement *ImageBlockElement
ButtonElement *ButtonBlockElement
OverflowElement *OverflowBlockElement
DatePickerElement *DatePickerBlockElement
SelectElement *SelectBlockElement
ImageElement *ImageBlockElement
ButtonElement *ButtonBlockElement
OverflowElement *OverflowBlockElement
DatePickerElement *DatePickerBlockElement
PlainTextInputElement *PlainTextInputBlockElement
RadioButtonsElement *RadioButtonsBlockElement
SelectElement *SelectBlockElement
MultiSelectElement *MultiSelectBlockElement
UnknownElement *UnknownBlockElement
}
// NewAccessory returns a new Accessory for a given block element
@ -49,11 +61,17 @@ func NewAccessory(element BlockElement) *Accessory {
return &Accessory{OverflowElement: element.(*OverflowBlockElement)}
case *DatePickerBlockElement:
return &Accessory{DatePickerElement: element.(*DatePickerBlockElement)}
case *PlainTextInputBlockElement:
return &Accessory{PlainTextInputElement: element.(*PlainTextInputBlockElement)}
case *RadioButtonsBlockElement:
return &Accessory{RadioButtonsElement: element.(*RadioButtonsBlockElement)}
case *SelectBlockElement:
return &Accessory{SelectElement: element.(*SelectBlockElement)}
case *MultiSelectBlockElement:
return &Accessory{MultiSelectElement: element.(*MultiSelectBlockElement)}
default:
return &Accessory{UnknownElement: element.(*UnknownBlockElement)}
}
return nil
}
// BlockElements is a convenience struct defined to allow dynamic unmarshalling of
@ -62,6 +80,20 @@ type BlockElements struct {
ElementSet []BlockElement `json:"elements,omitempty"`
}
// UnknownBlockElement any block element that this library does not directly support.
// See the "Rich Elements" section at the following URL:
// https://api.slack.com/changelog/2019-09-what-they-see-is-what-you-get-and-more-and-less
// New block element types may be introduced by Slack at any time; this is a catch-all for any such block elements.
type UnknownBlockElement struct {
Type MessageElementType `json:"type"`
Elements BlockElements
}
// ElementType returns the type of the Element
func (s UnknownBlockElement) ElementType() MessageElementType {
return s.Type
}
// ImageBlockElement An element to insert an image - this element can be used
// in section and context blocks only. If you want a block with only an image
// in it, you're looking for the image block.
@ -134,6 +166,20 @@ func NewButtonBlockElement(actionID, value string, text *TextBlockObject) *Butto
}
}
// OptionsResponse defines the response used for select block typahead.
//
// More Information: https://api.slack.com/reference/block-kit/block-elements#external_multi_select
type OptionsResponse struct {
Options []*OptionBlockObject `json:"options,omitempty"`
}
// OptionGroupsResponse defines the response used for select block typahead.
//
// More Information: https://api.slack.com/reference/block-kit/block-elements#external_multi_select
type OptionGroupsResponse struct {
OptionGroups []*OptionGroupBlockObject `json:"option_groups,omitempty"`
}
// SelectBlockElement defines the simplest form of select menu, with a static list
// of options passed in when defining the element.
//
@ -148,7 +194,7 @@ type SelectBlockElement struct {
InitialUser string `json:"initial_user,omitempty"`
InitialConversation string `json:"initial_conversation,omitempty"`
InitialChannel string `json:"initial_channel,omitempty"`
MinQueryLength int `json:"min_query_length,omitempty"`
MinQueryLength *int `json:"min_query_length,omitempty"`
Confirm *ConfirmationBlockObject `json:"confirm,omitempty"`
}
@ -184,6 +230,56 @@ func NewOptionsGroupSelectBlockElement(
}
}
// MultiSelectBlockElement defines a multiselect menu, with a static list
// of options passed in when defining the element.
//
// More Information: https://api.slack.com/reference/messaging/block-elements#multi_select
type MultiSelectBlockElement struct {
Type string `json:"type,omitempty"`
Placeholder *TextBlockObject `json:"placeholder,omitempty"`
ActionID string `json:"action_id,omitempty"`
Options []*OptionBlockObject `json:"options,omitempty"`
OptionGroups []*OptionGroupBlockObject `json:"option_groups,omitempty"`
InitialOptions []*OptionBlockObject `json:"initial_options,omitempty"`
InitialUsers []string `json:"initial_users,omitempty"`
InitialConversations []string `json:"initial_conversations,omitempty"`
InitialChannels []string `json:"initial_channels,omitempty"`
MinQueryLength *int `json:"min_query_length,omitempty"`
Confirm *ConfirmationBlockObject `json:"confirm,omitempty"`
}
// ElementType returns the type of the Element
func (s MultiSelectBlockElement) ElementType() MessageElementType {
return MessageElementType(s.Type)
}
// NewOptionsMultiSelectBlockElement returns a new instance of SelectBlockElement for use with
// the Options object only.
func NewOptionsMultiSelectBlockElement(optType string, placeholder *TextBlockObject, actionID string, options ...*OptionBlockObject) *MultiSelectBlockElement {
return &MultiSelectBlockElement{
Type: optType,
Placeholder: placeholder,
ActionID: actionID,
Options: options,
}
}
// NewOptionsGroupMultiSelectBlockElement returns a new instance of MultiSelectBlockElement for use with
// the Options object only.
func NewOptionsGroupMultiSelectBlockElement(
optType string,
placeholder *TextBlockObject,
actionID string,
optGroups ...*OptionGroupBlockObject,
) *MultiSelectBlockElement {
return &MultiSelectBlockElement{
Type: optType,
Placeholder: placeholder,
ActionID: actionID,
OptionGroups: optGroups,
}
}
// OverflowBlockElement defines the fields needed to use an overflow element.
// And Overflow Element is like a cross between a button and a select menu -
// when a user clicks on this overflow button, they will be presented with a
@ -236,3 +332,59 @@ func NewDatePickerBlockElement(actionID string) *DatePickerBlockElement {
ActionID: actionID,
}
}
// PlainTextInputBlockElement creates a field where a user can enter freeform
// data.
// Plain-text input elements are currently only available in modals.
//
// More Information: https://api.slack.com/reference/block-kit/block-elements#input
type PlainTextInputBlockElement struct {
Type MessageElementType `json:"type"`
ActionID string `json:"action_id"`
Placeholder *TextBlockObject `json:"placeholder,omitempty"`
InitialValue string `json:"initial_value,omitempty"`
Multiline bool `json:"multiline,omitempty"`
MinLength int `json:"min_length,omitempty"`
MaxLength int `json:"max_length,omitempty"`
}
// ElementType returns the type of the Element
func (s PlainTextInputBlockElement) ElementType() MessageElementType {
return s.Type
}
// NewPlainTextInputBlockElement returns an instance of a plain-text input
// element
func NewPlainTextInputBlockElement(placeholder *TextBlockObject, actionID string) *PlainTextInputBlockElement {
return &PlainTextInputBlockElement{
Type: METPlainTextInput,
ActionID: actionID,
Placeholder: placeholder,
}
}
// RadioButtonsBlockElement defines an element which lets users choose one item
// from a list of possible options.
//
// More Information: https://api.slack.com/reference/block-kit/block-elements#radio
type RadioButtonsBlockElement struct {
Type MessageElementType `json:"type"`
ActionID string `json:"action_id"`
Options []*OptionBlockObject `json:"options"`
InitialOption *OptionBlockObject `json:"initial_option,omitempty"`
Confirm *ConfirmationBlockObject `json:"confirm,omitempty"`
}
// ElementType returns the type of the Element
func (s RadioButtonsBlockElement) ElementType() MessageElementType {
return s.Type
}
// NewRadioButtonsBlockElement returns an instance of a radio buttons element.
func NewRadioButtonsBlockElement(actionID string, options ...*OptionBlockObject) *RadioButtonsBlockElement {
return &RadioButtonsBlockElement{
Type: METRadioButtons,
ActionID: actionID,
Options: options,
}
}

26
vendor/github.com/slack-go/slack/block_file.go generated vendored Normal file
View File

@ -0,0 +1,26 @@
package slack
// FileBlock defines data that is used to display a remote file.
//
// More Information: https://api.slack.com/reference/block-kit/blocks#file
type FileBlock struct {
Type MessageBlockType `json:"type"`
BlockID string `json:"block_id,omitempty"`
ExternalID string `json:"external_id"`
Source string `json:"source"`
}
// BlockType returns the type of the block
func (s FileBlock) BlockType() MessageBlockType {
return s.Type
}
// NewFileBlock returns a new instance of a file block
func NewFileBlock(blockID string, externalID string, source string) *FileBlock {
return &FileBlock{
Type: MBTFile,
BlockID: blockID,
ExternalID: externalID,
Source: source,
}
}

28
vendor/github.com/slack-go/slack/block_input.go generated vendored Normal file
View File

@ -0,0 +1,28 @@
package slack
// InputBlock defines data that is used to display user input fields.
//
// More Information: https://api.slack.com/reference/block-kit/blocks#input
type InputBlock struct {
Type MessageBlockType `json:"type"`
BlockID string `json:"block_id,omitempty"`
Label *TextBlockObject `json:"label"`
Element BlockElement `json:"element"`
Hint *TextBlockObject `json:"hint,omitempty"`
Optional bool `json:"optional,omitempty"`
}
// BlockType returns the type of the block
func (s InputBlock) BlockType() MessageBlockType {
return s.Type
}
// NewInputBlock returns a new instance of an input block
func NewInputBlock(blockID string, label *TextBlockObject, element BlockElement) *InputBlock {
return &InputBlock{
Type: MBTInput,
BlockID: blockID,
Label: label,
Element: element,
}
}

View File

@ -145,6 +145,14 @@ func NewTextBlockObject(elementType, text string, emoji, verbatim bool) *TextBlo
}
}
// BlockType returns the type of the block
func (t TextBlockObject) BlockType() MessageBlockType {
if t.Type == "mrkdown" {
return MarkdownType
}
return PlainTextType
}
// ConfirmationBlockObject defines a dialog that provides a confirmation step to
// any interactive element. This dialog will ask the user to confirm their action by
// offering a confirm and deny buttons.

13
vendor/github.com/slack-go/slack/block_unknown.go generated vendored Normal file
View File

@ -0,0 +1,13 @@
package slack
// UnknownBlock represents a block type that is not yet known. This block type exists to prevent Slack from introducing
// new and unknown block types that break this library.
type UnknownBlock struct {
Type MessageBlockType `json:"type"`
BlockID string `json:"block_id,omitempty"`
}
// BlockType returns the type of the block
func (b UnknownBlock) BlockType() MessageBlockType {
return b.Type
}

View File

@ -4,6 +4,7 @@ import (
"context"
"net/url"
"strconv"
"time"
)
type channelResponseFull struct {
@ -14,6 +15,7 @@ type channelResponseFull struct {
NotInChannel bool `json:"not_in_channel"`
History
SlackResponse
Metadata ResponseMetadata `json:"response_metadata"`
}
// Channel contains information about the channel
@ -35,25 +37,21 @@ func (api *Client) channelRequest(ctx context.Context, path string, values url.V
return response, response.Err()
}
type channelsConfig struct {
values url.Values
}
// GetChannelsOption option provided when getting channels.
type GetChannelsOption func(*channelsConfig) error
type GetChannelsOption func(*ChannelPagination) error
// GetChannelsOptionExcludeMembers excludes the members collection from each channel.
func GetChannelsOptionExcludeMembers() GetChannelsOption {
return func(config *channelsConfig) error {
config.values.Add("exclude_members", "true")
return func(p *ChannelPagination) error {
p.excludeMembers = true
return nil
}
}
// GetChannelsOptionExcludeArchived excludes archived channels from results.
func GetChannelsOptionExcludeArchived() GetChannelsOption {
return func(config *channelsConfig) error {
config.values.Add("exclude_archived", "true")
return func(p *ChannelPagination) error {
p.excludeArchived = true
return nil
}
}
@ -266,6 +264,78 @@ func (api *Client) KickUserFromChannelContext(ctx context.Context, channelID, us
return err
}
func newChannelPagination(c *Client, options ...GetChannelsOption) (cp ChannelPagination) {
cp = ChannelPagination{
c: c,
limit: 200, // per slack api documentation.
}
for _, opt := range options {
opt(&cp)
}
return cp
}
// ChannelPagination allows for paginating over the channels
type ChannelPagination struct {
Channels []Channel
limit int
excludeArchived bool
excludeMembers bool
previousResp *ResponseMetadata
c *Client
}
// Done checks if the pagination has completed
func (ChannelPagination) Done(err error) bool {
return err == errPaginationComplete
}
// Failure checks if pagination failed.
func (t ChannelPagination) Failure(err error) error {
if t.Done(err) {
return nil
}
return err
}
func (t ChannelPagination) Next(ctx context.Context) (_ ChannelPagination, err error) {
var (
resp *channelResponseFull
)
if t.c == nil || (t.previousResp != nil && t.previousResp.Cursor == "") {
return t, errPaginationComplete
}
t.previousResp = t.previousResp.initialize()
values := url.Values{
"limit": {strconv.Itoa(t.limit)},
"exclude_archived": {strconv.FormatBool(t.excludeArchived)},
"exclude_members": {strconv.FormatBool(t.excludeMembers)},
"token": {t.c.token},
"cursor": {t.previousResp.Cursor},
}
if resp, err = t.c.channelRequest(ctx, "channels.list", values); err != nil {
return t, err
}
t.c.Debugf("GetChannelsContext: got %d channels; metadata %v", len(resp.Channels), resp.Metadata)
t.Channels = resp.Channels
t.previousResp = &resp.Metadata
return t, nil
}
// GetChannelsPaginated fetches channels in a paginated fashion, see GetChannelsContext for usage.
func (api *Client) GetChannelsPaginated(options ...GetChannelsOption) ChannelPagination {
return newChannelPagination(api, options...)
}
// GetChannels retrieves all the channels
// see https://api.slack.com/methods/channels.list
func (api *Client) GetChannels(excludeArchived bool, options ...GetChannelsOption) ([]Channel, error) {
@ -274,28 +344,27 @@ func (api *Client) GetChannels(excludeArchived bool, options ...GetChannelsOptio
// GetChannelsContext retrieves all the channels with a custom context
// see https://api.slack.com/methods/channels.list
func (api *Client) GetChannelsContext(ctx context.Context, excludeArchived bool, options ...GetChannelsOption) ([]Channel, error) {
config := channelsConfig{
values: url.Values{
"token": {api.token},
},
}
func (api *Client) GetChannelsContext(ctx context.Context, excludeArchived bool, options ...GetChannelsOption) (results []Channel, err error) {
if excludeArchived {
options = append(options, GetChannelsOptionExcludeArchived())
}
for _, opt := range options {
if err := opt(&config); err != nil {
return nil, err
p := api.GetChannelsPaginated(options...)
for err == nil {
p, err = p.Next(ctx)
if err == nil {
results = append(results, p.Channels...)
} else if rateLimitedError, ok := err.(*RateLimitedError); ok {
select {
case <-ctx.Done():
err = ctx.Err()
case <-time.After(rateLimitedError.RetryAfter):
err = nil
}
}
}
response, err := api.channelRequest(ctx, "channels.list", config.values)
if err != nil {
return nil, err
}
return response.Channels, nil
return results, p.Failure(err)
}
// SetChannelReadMark sets the read mark of a given channel to a specific point

View File

@ -5,8 +5,9 @@ import (
"encoding/json"
"net/http"
"net/url"
"strconv"
"github.com/nlopes/slack/slackutilsx"
"github.com/slack-go/slack/slackutilsx"
)
const (
@ -25,10 +26,11 @@ const (
)
type chatResponseFull struct {
Channel string `json:"channel"`
Timestamp string `json:"ts"` //Regular message timestamp
MessageTimeStamp string `json:"message_ts"` //Ephemeral message timestamp
Text string `json:"text"`
Channel string `json:"channel"`
Timestamp string `json:"ts"` //Regular message timestamp
MessageTimeStamp string `json:"message_ts"` //Ephemeral message timestamp
ScheduledMessageID string `json:"scheduled_message_id,omitempty"` //Scheduled message id
Text string `json:"text"`
SlackResponse
}
@ -82,13 +84,34 @@ func NewPostMessageParameters() PostMessageParameters {
// DeleteMessage deletes a message in a channel
func (api *Client) DeleteMessage(channel, messageTimestamp string) (string, string, error) {
respChannel, respTimestamp, _, err := api.SendMessageContext(context.Background(), channel, MsgOptionDelete(messageTimestamp))
respChannel, respTimestamp, _, err := api.SendMessageContext(
context.Background(),
channel,
MsgOptionDelete(messageTimestamp),
)
return respChannel, respTimestamp, err
}
// DeleteMessageContext deletes a message in a channel with a custom context
func (api *Client) DeleteMessageContext(ctx context.Context, channel, messageTimestamp string) (string, string, error) {
respChannel, respTimestamp, _, err := api.SendMessageContext(ctx, channel, MsgOptionDelete(messageTimestamp))
respChannel, respTimestamp, _, err := api.SendMessageContext(
ctx,
channel,
MsgOptionDelete(messageTimestamp),
)
return respChannel, respTimestamp, err
}
// ScheduleMessage sends a message to a channel.
// Message is escaped by default according to https://api.slack.com/docs/formatting
// Use http://davestevens.github.io/slack-message-builder/ to help crafting your message.
func (api *Client) ScheduleMessage(channelID, postAt string, options ...MsgOption) (string, string, error) {
respChannel, respTimestamp, _, err := api.SendMessageContext(
context.Background(),
channelID,
MsgOptionSchedule(postAt),
MsgOptionCompose(options...),
)
return respChannel, respTimestamp, err
}
@ -132,18 +155,33 @@ func (api *Client) PostEphemeral(channelID, userID string, options ...MsgOption)
// PostEphemeralContext sends an ephemeal message to a user in a channel with a custom context
// For more details, see PostEphemeral documentation
func (api *Client) PostEphemeralContext(ctx context.Context, channelID, userID string, options ...MsgOption) (timestamp string, err error) {
_, timestamp, _, err = api.SendMessageContext(ctx, channelID, MsgOptionPostEphemeral(userID), MsgOptionCompose(options...))
_, timestamp, _, err = api.SendMessageContext(
ctx,
channelID,
MsgOptionPostEphemeral(userID),
MsgOptionCompose(options...),
)
return timestamp, err
}
// UpdateMessage updates a message in a channel
func (api *Client) UpdateMessage(channelID, timestamp string, options ...MsgOption) (string, string, string, error) {
return api.SendMessageContext(context.Background(), channelID, MsgOptionUpdate(timestamp), MsgOptionCompose(options...))
return api.SendMessageContext(
context.Background(),
channelID,
MsgOptionUpdate(timestamp),
MsgOptionCompose(options...),
)
}
// UpdateMessageContext updates a message in a channel
func (api *Client) UpdateMessageContext(ctx context.Context, channelID, timestamp string, options ...MsgOption) (string, string, string, error) {
return api.SendMessageContext(ctx, channelID, MsgOptionUpdate(timestamp), MsgOptionCompose(options...))
return api.SendMessageContext(
ctx,
channelID,
MsgOptionUpdate(timestamp),
MsgOptionCompose(options...),
)
}
// UnfurlMessage unfurls a message in a channel
@ -212,13 +250,14 @@ func buildSender(apiurl string, options ...MsgOption) sendConfig {
type sendMode string
const (
chatUpdate sendMode = "chat.update"
chatPostMessage sendMode = "chat.postMessage"
chatDelete sendMode = "chat.delete"
chatPostEphemeral sendMode = "chat.postEphemeral"
chatResponse sendMode = "chat.responseURL"
chatMeMessage sendMode = "chat.meMessage"
chatUnfurl sendMode = "chat.unfurl"
chatUpdate sendMode = "chat.update"
chatPostMessage sendMode = "chat.postMessage"
chatScheduleMessage sendMode = "chat.scheduleMessage"
chatDelete sendMode = "chat.delete"
chatPostEphemeral sendMode = "chat.postEphemeral"
chatResponse sendMode = "chat.responseURL"
chatMeMessage sendMode = "chat.meMessage"
chatUnfurl sendMode = "chat.unfurl"
)
type sendConfig struct {
@ -287,6 +326,15 @@ func (t responseURLSender) BuildRequest() (*http.Request, func(*chatResponseFull
// MsgOption option provided when sending a message.
type MsgOption func(*sendConfig) error
// MsgOptionSchedule schedules a messages.
func MsgOptionSchedule(postAt string) MsgOption {
return func(config *sendConfig) error {
config.endpoint = config.apiurl + string(chatScheduleMessage)
config.values.Add("post_at", postAt)
return nil
}
}
// MsgOptionPost posts a messages, this is the default.
func MsgOptionPost() MsgOption {
return func(config *sendConfig) error {
@ -347,11 +395,11 @@ func MsgOptionUnfurl(timestamp string, unfurls map[string]Attachment) MsgOption
}
// MsgOptionResponseURL supplies a url to use as the endpoint.
func MsgOptionResponseURL(url string, rt string) MsgOption {
func MsgOptionResponseURL(url string, responseType string) MsgOption {
return func(config *sendConfig) error {
config.mode = chatResponse
config.endpoint = url
config.responseType = rt
config.responseType = responseType
config.values.Del("ts")
return nil
}
@ -625,3 +673,81 @@ func (api *Client) GetPermalinkContext(ctx context.Context, params *PermalinkPar
}
return response.Permalink, response.Err()
}
type GetScheduledMessagesParameters struct {
Channel string
Cursor string
Latest string
Limit int
Oldest string
}
// GetScheduledMessages returns the list of scheduled messages based on params
func (api *Client) GetScheduledMessages(params *GetScheduledMessagesParameters) (channels []Message, nextCursor string, err error) {
return api.GetScheduledMessagesContext(context.Background(), params)
}
// GetScheduledMessagesContext returns the list of scheduled messages in a Slack team with a custom context
func (api *Client) GetScheduledMessagesContext(ctx context.Context, params *GetScheduledMessagesParameters) (channels []Message, nextCursor string, err error) {
values := url.Values{
"token": {api.token},
}
if params.Channel != "" {
values.Add("channel", params.Channel)
}
if params.Cursor != "" {
values.Add("cursor", params.Cursor)
}
if params.Limit != 0 {
values.Add("limit", strconv.Itoa(params.Limit))
}
if params.Latest != "" {
values.Add("latest", params.Latest)
}
if params.Oldest != "" {
values.Add("oldest", params.Oldest)
}
response := struct {
Messages []Message `json:"scheduled_messages"`
ResponseMetaData responseMetaData `json:"response_metadata"`
SlackResponse
}{}
err = api.postMethod(ctx, "chat.scheduledMessages.list", values, &response)
if err != nil {
return nil, "", err
}
return response.Messages, response.ResponseMetaData.NextCursor, response.Err()
}
type DeleteScheduledMessageParameters struct {
Channel string
ScheduledMessageID string
AsUser bool
}
// DeleteScheduledMessage returns the list of scheduled messages based on params
func (api *Client) DeleteScheduledMessage(params *DeleteScheduledMessageParameters) (bool, error) {
return api.DeleteScheduledMessageContext(context.Background(), params)
}
// DeleteScheduledMessageContext returns the list of scheduled messages in a Slack team with a custom context
func (api *Client) DeleteScheduledMessageContext(ctx context.Context, params *DeleteScheduledMessageParameters) (bool, error) {
values := url.Values{
"token": {api.token},
"channel": {params.Channel},
"scheduled_message_id": {params.ScheduledMessageID},
"as_user": {strconv.FormatBool(params.AsUser)},
}
response := struct {
SlackResponse
}{}
err := api.postMethod(ctx, "chat.deleteScheduledMessage", values, &response)
if err != nil {
return false, err
}
return response.Ok, response.Err()
}

View File

@ -1,6 +1,6 @@
package slack
import "github.com/nlopes/slack/internal/errorsx"
import "github.com/slack-go/slack/internal/errorsx"
// Errors returned by various methods.
const (

11
vendor/github.com/slack-go/slack/go.mod generated vendored Normal file
View File

@ -0,0 +1,11 @@
module github.com/slack-go/slack
require (
github.com/go-test/deep v1.0.4
github.com/gorilla/websocket v1.2.0
github.com/nlopes/slack v0.6.0
github.com/pkg/errors v0.8.0
github.com/stretchr/testify v1.2.2
)
go 1.13

14
vendor/github.com/slack-go/slack/go.sum generated vendored Normal file
View File

@ -0,0 +1,14 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/nlopes/slack v0.6.0 h1:jt0jxVQGhssx1Ib7naAOZEZcGdtIhTzkP0nopK0AsRA=
github.com/nlopes/slack v0.6.0/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=

468
vendor/github.com/slack-go/slack/info.go generated vendored Normal file
View File

@ -0,0 +1,468 @@
package slack
import (
"bytes"
"context"
"fmt"
"net/url"
"strconv"
"strings"
"time"
)
type UserPrefsCarrier struct {
SlackResponse
UserPrefs *UserPrefs `json:"prefs"`
}
// UserPrefs carries a bunch of user settings including some unknown types
type UserPrefs struct {
UserColors string `json:"user_colors,omitempty"`
ColorNamesInList bool `json:"color_names_in_list,omitempty"`
// Keyboard UnknownType `json:"keyboard"`
EmailAlerts string `json:"email_alerts,omitempty"`
EmailAlertsSleepUntil int `json:"email_alerts_sleep_until,omitempty"`
EmailTips bool `json:"email_tips,omitempty"`
EmailWeekly bool `json:"email_weekly,omitempty"`
EmailOffers bool `json:"email_offers,omitempty"`
EmailResearch bool `json:"email_research,omitempty"`
EmailDeveloper bool `json:"email_developer,omitempty"`
WelcomeMessageHidden bool `json:"welcome_message_hidden,omitempty"`
SearchSort string `json:"search_sort,omitempty"`
SearchFileSort string `json:"search_file_sort,omitempty"`
SearchChannelSort string `json:"search_channel_sort,omitempty"`
SearchPeopleSort string `json:"search_people_sort,omitempty"`
ExpandInlineImages bool `json:"expand_inline_images,omitempty"`
ExpandInternalInlineImages bool `json:"expand_internal_inline_images,omitempty"`
ExpandSnippets bool `json:"expand_snippets,omitempty"`
PostsFormattingGuide bool `json:"posts_formatting_guide,omitempty"`
SeenWelcome2 bool `json:"seen_welcome_2,omitempty"`
SeenSSBPrompt bool `json:"seen_ssb_prompt,omitempty"`
SpacesNewXpBannerDismissed bool `json:"spaces_new_xp_banner_dismissed,omitempty"`
SearchOnlyMyChannels bool `json:"search_only_my_channels,omitempty"`
SearchOnlyCurrentTeam bool `json:"search_only_current_team,omitempty"`
SearchHideMyChannels bool `json:"search_hide_my_channels,omitempty"`
SearchOnlyShowOnline bool `json:"search_only_show_online,omitempty"`
SearchHideDeactivatedUsers bool `json:"search_hide_deactivated_users,omitempty"`
EmojiMode string `json:"emoji_mode,omitempty"`
EmojiUse string `json:"emoji_use,omitempty"`
HasInvited bool `json:"has_invited,omitempty"`
HasUploaded bool `json:"has_uploaded,omitempty"`
HasCreatedChannel bool `json:"has_created_channel,omitempty"`
HasSearched bool `json:"has_searched,omitempty"`
SearchExcludeChannels string `json:"search_exclude_channels,omitempty"`
MessagesTheme string `json:"messages_theme,omitempty"`
WebappSpellcheck bool `json:"webapp_spellcheck,omitempty"`
NoJoinedOverlays bool `json:"no_joined_overlays,omitempty"`
NoCreatedOverlays bool `json:"no_created_overlays,omitempty"`
DropboxEnabled bool `json:"dropbox_enabled,omitempty"`
SeenDomainInviteReminder bool `json:"seen_domain_invite_reminder,omitempty"`
SeenMemberInviteReminder bool `json:"seen_member_invite_reminder,omitempty"`
MuteSounds bool `json:"mute_sounds,omitempty"`
ArrowHistory bool `json:"arrow_history,omitempty"`
TabUIReturnSelects bool `json:"tab_ui_return_selects,omitempty"`
ObeyInlineImgLimit bool `json:"obey_inline_img_limit,omitempty"`
RequireAt bool `json:"require_at,omitempty"`
SsbSpaceWindow string `json:"ssb_space_window,omitempty"`
MacSsbBounce string `json:"mac_ssb_bounce,omitempty"`
MacSsbBullet bool `json:"mac_ssb_bullet,omitempty"`
ExpandNonMediaAttachments bool `json:"expand_non_media_attachments,omitempty"`
ShowTyping bool `json:"show_typing,omitempty"`
PagekeysHandled bool `json:"pagekeys_handled,omitempty"`
LastSnippetType string `json:"last_snippet_type,omitempty"`
DisplayRealNamesOverride int `json:"display_real_names_override,omitempty"`
DisplayDisplayNames bool `json:"display_display_names,omitempty"`
Time24 bool `json:"time24,omitempty"`
EnterIsSpecialInTbt bool `json:"enter_is_special_in_tbt,omitempty"`
MsgInputSendBtn bool `json:"msg_input_send_btn,omitempty"`
MsgInputSendBtnAutoSet bool `json:"msg_input_send_btn_auto_set,omitempty"`
MsgInputStickyComposer bool `json:"msg_input_sticky_composer,omitempty"`
GraphicEmoticons bool `json:"graphic_emoticons,omitempty"`
ConvertEmoticons bool `json:"convert_emoticons,omitempty"`
SsEmojis bool `json:"ss_emojis,omitempty"`
SeenOnboardingStart bool `json:"seen_onboarding_start,omitempty"`
OnboardingCancelled bool `json:"onboarding_cancelled,omitempty"`
SeenOnboardingSlackbotConversation bool `json:"seen_onboarding_slackbot_conversation,omitempty"`
SeenOnboardingChannels bool `json:"seen_onboarding_channels,omitempty"`
SeenOnboardingDirectMessages bool `json:"seen_onboarding_direct_messages,omitempty"`
SeenOnboardingInvites bool `json:"seen_onboarding_invites,omitempty"`
SeenOnboardingSearch bool `json:"seen_onboarding_search,omitempty"`
SeenOnboardingRecentMentions bool `json:"seen_onboarding_recent_mentions,omitempty"`
SeenOnboardingStarredItems bool `json:"seen_onboarding_starred_items,omitempty"`
SeenOnboardingPrivateGroups bool `json:"seen_onboarding_private_groups,omitempty"`
SeenOnboardingBanner bool `json:"seen_onboarding_banner,omitempty"`
OnboardingSlackbotConversationStep int `json:"onboarding_slackbot_conversation_step,omitempty"`
SetTzAutomatically bool `json:"set_tz_automatically,omitempty"`
SuppressLinkWarning bool `json:"suppress_link_warning,omitempty"`
DndEnabled bool `json:"dnd_enabled,omitempty"`
DndStartHour string `json:"dnd_start_hour,omitempty"`
DndEndHour string `json:"dnd_end_hour,omitempty"`
DndBeforeMonday string `json:"dnd_before_monday,omitempty"`
DndAfterMonday string `json:"dnd_after_monday,omitempty"`
DndEnabledMonday string `json:"dnd_enabled_monday,omitempty"`
DndBeforeTuesday string `json:"dnd_before_tuesday,omitempty"`
DndAfterTuesday string `json:"dnd_after_tuesday,omitempty"`
DndEnabledTuesday string `json:"dnd_enabled_tuesday,omitempty"`
DndBeforeWednesday string `json:"dnd_before_wednesday,omitempty"`
DndAfterWednesday string `json:"dnd_after_wednesday,omitempty"`
DndEnabledWednesday string `json:"dnd_enabled_wednesday,omitempty"`
DndBeforeThursday string `json:"dnd_before_thursday,omitempty"`
DndAfterThursday string `json:"dnd_after_thursday,omitempty"`
DndEnabledThursday string `json:"dnd_enabled_thursday,omitempty"`
DndBeforeFriday string `json:"dnd_before_friday,omitempty"`
DndAfterFriday string `json:"dnd_after_friday,omitempty"`
DndEnabledFriday string `json:"dnd_enabled_friday,omitempty"`
DndBeforeSaturday string `json:"dnd_before_saturday,omitempty"`
DndAfterSaturday string `json:"dnd_after_saturday,omitempty"`
DndEnabledSaturday string `json:"dnd_enabled_saturday,omitempty"`
DndBeforeSunday string `json:"dnd_before_sunday,omitempty"`
DndAfterSunday string `json:"dnd_after_sunday,omitempty"`
DndEnabledSunday string `json:"dnd_enabled_sunday,omitempty"`
DndDays string `json:"dnd_days,omitempty"`
DndCustomNewBadgeSeen bool `json:"dnd_custom_new_badge_seen,omitempty"`
DndNotificationScheduleNewBadgeSeen bool `json:"dnd_notification_schedule_new_badge_seen,omitempty"`
// UnreadCollapsedChannels unknownType `json:"unread_collapsed_channels,omitempty"`
SidebarBehavior string `json:"sidebar_behavior,omitempty"`
ChannelSort string `json:"channel_sort,omitempty"`
SeparatePrivateChannels bool `json:"separate_private_channels,omitempty"`
SeparateSharedChannels bool `json:"separate_shared_channels,omitempty"`
SidebarTheme string `json:"sidebar_theme,omitempty"`
SidebarThemeCustomValues string `json:"sidebar_theme_custom_values,omitempty"`
NoInvitesWidgetInSidebar bool `json:"no_invites_widget_in_sidebar,omitempty"`
NoOmniboxInChannels bool `json:"no_omnibox_in_channels,omitempty"`
KKeyOmniboxAutoHideCount int `json:"k_key_omnibox_auto_hide_count,omitempty"`
ShowSidebarQuickswitcherButton bool `json:"show_sidebar_quickswitcher_button,omitempty"`
EntOrgWideChannelsSidebar bool `json:"ent_org_wide_channels_sidebar,omitempty"`
MarkMsgsReadImmediately bool `json:"mark_msgs_read_immediately,omitempty"`
StartScrollAtOldest bool `json:"start_scroll_at_oldest,omitempty"`
SnippetEditorWrapLongLines bool `json:"snippet_editor_wrap_long_lines,omitempty"`
LsDisabled bool `json:"ls_disabled,omitempty"`
FKeySearch bool `json:"f_key_search,omitempty"`
KKeyOmnibox bool `json:"k_key_omnibox,omitempty"`
PromptedForEmailDisabling bool `json:"prompted_for_email_disabling,omitempty"`
NoMacelectronBanner bool `json:"no_macelectron_banner,omitempty"`
NoMacssb1Banner bool `json:"no_macssb1_banner,omitempty"`
NoMacssb2Banner bool `json:"no_macssb2_banner,omitempty"`
NoWinssb1Banner bool `json:"no_winssb1_banner,omitempty"`
HideUserGroupInfoPane bool `json:"hide_user_group_info_pane,omitempty"`
MentionsExcludeAtUserGroups bool `json:"mentions_exclude_at_user_groups,omitempty"`
MentionsExcludeReactions bool `json:"mentions_exclude_reactions,omitempty"`
PrivacyPolicySeen bool `json:"privacy_policy_seen,omitempty"`
EnterpriseMigrationSeen bool `json:"enterprise_migration_seen,omitempty"`
LastTosAcknowledged string `json:"last_tos_acknowledged,omitempty"`
SearchExcludeBots bool `json:"search_exclude_bots,omitempty"`
LoadLato2 bool `json:"load_lato_2,omitempty"`
FullerTimestamps bool `json:"fuller_timestamps,omitempty"`
LastSeenAtChannelWarning int `json:"last_seen_at_channel_warning,omitempty"`
EmojiAutocompleteBig bool `json:"emoji_autocomplete_big,omitempty"`
TwoFactorAuthEnabled bool `json:"two_factor_auth_enabled,omitempty"`
// TwoFactorType unknownType `json:"two_factor_type,omitempty"`
// TwoFactorBackupType unknownType `json:"two_factor_backup_type,omitempty"`
HideHexSwatch bool `json:"hide_hex_swatch,omitempty"`
ShowJumperScores bool `json:"show_jumper_scores,omitempty"`
EnterpriseMdmCustomMsg string `json:"enterprise_mdm_custom_msg,omitempty"`
// EnterpriseExcludedAppTeams unknownType `json:"enterprise_excluded_app_teams,omitempty"`
ClientLogsPri string `json:"client_logs_pri,omitempty"`
FlannelServerPool string `json:"flannel_server_pool,omitempty"`
MentionsExcludeAtChannels bool `json:"mentions_exclude_at_channels,omitempty"`
ConfirmClearAllUnreads bool `json:"confirm_clear_all_unreads,omitempty"`
ConfirmUserMarkedAway bool `json:"confirm_user_marked_away,omitempty"`
BoxEnabled bool `json:"box_enabled,omitempty"`
SeenSingleEmojiMsg bool `json:"seen_single_emoji_msg,omitempty"`
ConfirmShCallStart bool `json:"confirm_sh_call_start,omitempty"`
PreferredSkinTone string `json:"preferred_skin_tone,omitempty"`
ShowAllSkinTones bool `json:"show_all_skin_tones,omitempty"`
WhatsNewRead int `json:"whats_new_read,omitempty"`
// FrecencyJumper unknownType `json:"frecency_jumper,omitempty"`
FrecencyEntJumper string `json:"frecency_ent_jumper,omitempty"`
FrecencyEntJumperBackup string `json:"frecency_ent_jumper_backup,omitempty"`
Jumbomoji bool `json:"jumbomoji,omitempty"`
NewxpSeenLastMessage int `json:"newxp_seen_last_message,omitempty"`
ShowMemoryInstrument bool `json:"show_memory_instrument,omitempty"`
EnableUnreadView bool `json:"enable_unread_view,omitempty"`
SeenUnreadViewCoachmark bool `json:"seen_unread_view_coachmark,omitempty"`
EnableReactEmojiPicker bool `json:"enable_react_emoji_picker,omitempty"`
SeenCustomStatusBadge bool `json:"seen_custom_status_badge,omitempty"`
SeenCustomStatusCallout bool `json:"seen_custom_status_callout,omitempty"`
SeenCustomStatusExpirationBadge bool `json:"seen_custom_status_expiration_badge,omitempty"`
UsedCustomStatusKbShortcut bool `json:"used_custom_status_kb_shortcut,omitempty"`
SeenGuestAdminSlackbotAnnouncement bool `json:"seen_guest_admin_slackbot_announcement,omitempty"`
SeenThreadsNotificationBanner bool `json:"seen_threads_notification_banner,omitempty"`
SeenNameTaggingCoachmark bool `json:"seen_name_tagging_coachmark,omitempty"`
AllUnreadsSortOrder string `json:"all_unreads_sort_order,omitempty"`
Locale string `json:"locale,omitempty"`
SeenIntlChannelNamesCoachmark bool `json:"seen_intl_channel_names_coachmark,omitempty"`
SeenP2LocaleChangeMessage int `json:"seen_p2_locale_change_message,omitempty"`
SeenLocaleChangeMessage int `json:"seen_locale_change_message,omitempty"`
SeenJapaneseLocaleChangeMessage bool `json:"seen_japanese_locale_change_message,omitempty"`
SeenSharedChannelsCoachmark bool `json:"seen_shared_channels_coachmark,omitempty"`
SeenSharedChannelsOptInChangeMessage bool `json:"seen_shared_channels_opt_in_change_message,omitempty"`
HasRecentlySharedaChannel bool `json:"has_recently_shared_a_channel,omitempty"`
SeenChannelBrowserAdminCoachmark bool `json:"seen_channel_browser_admin_coachmark,omitempty"`
SeenAdministrationMenu bool `json:"seen_administration_menu,omitempty"`
SeenDraftsSectionCoachmark bool `json:"seen_drafts_section_coachmark,omitempty"`
SeenEmojiUpdateOverlayCoachmark bool `json:"seen_emoji_update_overlay_coachmark,omitempty"`
SeenSonicDeluxeToast int `json:"seen_sonic_deluxe_toast,omitempty"`
SeenWysiwygDeluxeToast bool `json:"seen_wysiwyg_deluxe_toast,omitempty"`
SeenMarkdownPasteToast int `json:"seen_markdown_paste_toast,omitempty"`
SeenMarkdownPasteShortcut int `json:"seen_markdown_paste_shortcut,omitempty"`
SeenIaEducation bool `json:"seen_ia_education,omitempty"`
PlainTextMode bool `json:"plain_text_mode,omitempty"`
ShowSharedChannelsEducationBanner bool `json:"show_shared_channels_education_banner,omitempty"`
AllowCallsToSetCurrentStatus bool `json:"allow_calls_to_set_current_status,omitempty"`
InInteractiveMasMigrationFlow bool `json:"in_interactive_mas_migration_flow,omitempty"`
SunsetInteractiveMessageViews int `json:"sunset_interactive_message_views,omitempty"`
ShdepPromoCodeSubmitted bool `json:"shdep_promo_code_submitted,omitempty"`
SeenShdepSlackbotMessage bool `json:"seen_shdep_slackbot_message,omitempty"`
SeenCallsInteractiveCoachmark bool `json:"seen_calls_interactive_coachmark,omitempty"`
AllowCmdTabIss bool `json:"allow_cmd_tab_iss,omitempty"`
SeenWorkflowBuilderDeluxeToast bool `json:"seen_workflow_builder_deluxe_toast,omitempty"`
WorkflowBuilderIntroModalClickedThrough bool `json:"workflow_builder_intro_modal_clicked_through,omitempty"`
// WorkflowBuilderCoachmarks unknownType `json:"workflow_builder_coachmarks,omitempty"`
SeenGdriveCoachmark bool `json:"seen_gdrive_coachmark,omitempty"`
OverloadedMessageEnabled bool `json:"overloaded_message_enabled,omitempty"`
SeenHighlightsCoachmark bool `json:"seen_highlights_coachmark,omitempty"`
SeenHighlightsArrowsCoachmark bool `json:"seen_highlights_arrows_coachmark,omitempty"`
SeenHighlightsWarmWelcome bool `json:"seen_highlights_warm_welcome,omitempty"`
SeenNewSearchUi bool `json:"seen_new_search_ui,omitempty"`
SeenChannelSearch bool `json:"seen_channel_search,omitempty"`
SeenPeopleSearch bool `json:"seen_people_search,omitempty"`
SeenPeopleSearchCount int `json:"seen_people_search_count,omitempty"`
DismissedScrollSearchTooltipCount int `json:"dismissed_scroll_search_tooltip_count,omitempty"`
LastDismissedScrollSearchTooltipTimestamp int `json:"last_dismissed_scroll_search_tooltip_timestamp,omitempty"`
HasUsedQuickswitcherShortcut bool `json:"has_used_quickswitcher_shortcut,omitempty"`
SeenQuickswitcherShortcutTipCount int `json:"seen_quickswitcher_shortcut_tip_count,omitempty"`
BrowsersDismissedChannelsLowResultsEducation bool `json:"browsers_dismissed_channels_low_results_education,omitempty"`
BrowsersSeenInitialChannelsEducation bool `json:"browsers_seen_initial_channels_education,omitempty"`
BrowsersDismissedPeopleLowResultsEducation bool `json:"browsers_dismissed_people_low_results_education,omitempty"`
BrowsersSeenInitialPeopleEducation bool `json:"browsers_seen_initial_people_education,omitempty"`
BrowsersDismissedUserGroupsLowResultsEducation bool `json:"browsers_dismissed_user_groups_low_results_education,omitempty"`
BrowsersSeenInitialUserGroupsEducation bool `json:"browsers_seen_initial_user_groups_education,omitempty"`
BrowsersDismissedFilesLowResultsEducation bool `json:"browsers_dismissed_files_low_results_education,omitempty"`
BrowsersSeenInitialFilesEducation bool `json:"browsers_seen_initial_files_education,omitempty"`
A11yAnimations bool `json:"a11y_animations,omitempty"`
SeenKeyboardShortcutsCoachmark bool `json:"seen_keyboard_shortcuts_coachmark,omitempty"`
NeedsInitialPasswordSet bool `json:"needs_initial_password_set,omitempty"`
LessonsEnabled bool `json:"lessons_enabled,omitempty"`
TractorEnabled bool `json:"tractor_enabled,omitempty"`
TractorExperimentGroup string `json:"tractor_experiment_group,omitempty"`
OpenedSlackbotDm bool `json:"opened_slackbot_dm,omitempty"`
NewxpSuggestedChannels string `json:"newxp_suggested_channels,omitempty"`
OnboardingComplete bool `json:"onboarding_complete,omitempty"`
WelcomePlaceState string `json:"welcome_place_state,omitempty"`
// OnboardingRoleApps unknownType `json:"onboarding_role_apps,omitempty"`
HasReceivedThreadedMessage bool `json:"has_received_threaded_message,omitempty"`
SendYourFirstMessageBannerEnabled bool `json:"send_your_first_message_banner_enabled,omitempty"`
WhocanseethisDmMpdmBadge bool `json:"whocanseethis_dm_mpdm_badge,omitempty"`
HighlightWords string `json:"highlight_words,omitempty"`
ThreadsEverything bool `json:"threads_everything,omitempty"`
NoTextInNotifications bool `json:"no_text_in_notifications,omitempty"`
PushShowPreview bool `json:"push_show_preview,omitempty"`
GrowlsEnabled bool `json:"growls_enabled,omitempty"`
AllChannelsLoud bool `json:"all_channels_loud,omitempty"`
PushDmAlert bool `json:"push_dm_alert,omitempty"`
PushMentionAlert bool `json:"push_mention_alert,omitempty"`
PushEverything bool `json:"push_everything,omitempty"`
PushIdleWait int `json:"push_idle_wait,omitempty"`
PushSound string `json:"push_sound,omitempty"`
NewMsgSnd string `json:"new_msg_snd,omitempty"`
PushLoudChannels string `json:"push_loud_channels,omitempty"`
PushMentionChannels string `json:"push_mention_channels,omitempty"`
PushLoudChannelsSet string `json:"push_loud_channels_set,omitempty"`
LoudChannels string `json:"loud_channels,omitempty"`
NeverChannels string `json:"never_channels,omitempty"`
LoudChannelsSet string `json:"loud_channels_set,omitempty"`
AtChannelSuppressedChannels string `json:"at_channel_suppressed_channels,omitempty"`
PushAtChannelSuppressedChannels string `json:"push_at_channel_suppressed_channels,omitempty"`
MutedChannels string `json:"muted_channels,omitempty"`
// AllNotificationsPrefs unknownType `json:"all_notifications_prefs,omitempty"`
GrowthMsgLimitApproachingCtaCount int `json:"growth_msg_limit_approaching_cta_count,omitempty"`
GrowthMsgLimitApproachingCtaTs int `json:"growth_msg_limit_approaching_cta_ts,omitempty"`
GrowthMsgLimitReachedCtaCount int `json:"growth_msg_limit_reached_cta_count,omitempty"`
GrowthMsgLimitReachedCtaLastTs int `json:"growth_msg_limit_reached_cta_last_ts,omitempty"`
GrowthMsgLimitLongReachedCtaCount int `json:"growth_msg_limit_long_reached_cta_count,omitempty"`
GrowthMsgLimitLongReachedCtaLastTs int `json:"growth_msg_limit_long_reached_cta_last_ts,omitempty"`
GrowthMsgLimitSixtyDayBannerCtaCount int `json:"growth_msg_limit_sixty_day_banner_cta_count,omitempty"`
GrowthMsgLimitSixtyDayBannerCtaLastTs int `json:"growth_msg_limit_sixty_day_banner_cta_last_ts,omitempty"`
// GrowthAllBannersPrefs unknownType `json:"growth_all_banners_prefs,omitempty"`
AnalyticsUpsellCoachmarkSeen bool `json:"analytics_upsell_coachmark_seen,omitempty"`
SeenAppSpaceCoachmark bool `json:"seen_app_space_coachmark,omitempty"`
SeenAppSpaceTutorial bool `json:"seen_app_space_tutorial,omitempty"`
DismissedAppLauncherWelcome bool `json:"dismissed_app_launcher_welcome,omitempty"`
DismissedAppLauncherLimit bool `json:"dismissed_app_launcher_limit,omitempty"`
Purchaser bool `json:"purchaser,omitempty"`
ShowEntOnboarding bool `json:"show_ent_onboarding,omitempty"`
FoldersEnabled bool `json:"folders_enabled,omitempty"`
// FolderData unknownType `json:"folder_data,omitempty"`
SeenCorporateExportAlert bool `json:"seen_corporate_export_alert,omitempty"`
ShowAutocompleteHelp int `json:"show_autocomplete_help,omitempty"`
DeprecationToastLastSeen int `json:"deprecation_toast_last_seen,omitempty"`
DeprecationModalLastSeen int `json:"deprecation_modal_last_seen,omitempty"`
Iap1Lab int `json:"iap1_lab,omitempty"`
IaTopNavTheme string `json:"ia_top_nav_theme,omitempty"`
IaPlatformActionsLab int `json:"ia_platform_actions_lab,omitempty"`
ActivityView string `json:"activity_view,omitempty"`
FailoverProxyCheckCompleted int `json:"failover_proxy_check_completed,omitempty"`
EdgeUploadProxyCheckCompleted int `json:"edge_upload_proxy_check_completed,omitempty"`
AppSubdomainCheckCompleted int `json:"app_subdomain_check_completed,omitempty"`
AddAppsPromptDismissed bool `json:"add_apps_prompt_dismissed,omitempty"`
AddChannelPromptDismissed bool `json:"add_channel_prompt_dismissed,omitempty"`
ChannelSidebarHideInvite bool `json:"channel_sidebar_hide_invite,omitempty"`
InProdSurveysEnabled bool `json:"in_prod_surveys_enabled,omitempty"`
DismissedInstalledAppDmSuggestions string `json:"dismissed_installed_app_dm_suggestions,omitempty"`
SeenContextualMessageShortcutsModal bool `json:"seen_contextual_message_shortcuts_modal,omitempty"`
SeenMessageNavigationEducationalToast bool `json:"seen_message_navigation_educational_toast,omitempty"`
ContextualMessageShortcutsModalWasSeen bool `json:"contextual_message_shortcuts_modal_was_seen,omitempty"`
MessageNavigationToastWasSeen bool `json:"message_navigation_toast_was_seen,omitempty"`
UpToBrowseKbShortcut bool `json:"up_to_browse_kb_shortcut,omitempty"`
ChannelSections string `json:"channel_sections,omitempty"`
TZ string `json:"tz,omitempty"`
}
func (api *Client) GetUserPrefs() (*UserPrefsCarrier, error) {
values := url.Values{"token": {api.token}}
response := UserPrefsCarrier{}
err := api.getMethod(context.Background(), "users.prefs.get", values, &response)
if err != nil {
return nil, err
}
return &response, response.Err()
}
func (api *Client) MuteChat(channelID string) (*UserPrefsCarrier, error) {
prefs, err := api.GetUserPrefs()
if err != nil {
return nil, err
}
chnls := strings.Split(prefs.UserPrefs.MutedChannels, ",")
for _, chn := range chnls {
if chn == channelID {
return nil, nil // noop
}
}
newChnls := prefs.UserPrefs.MutedChannels + "," + channelID
values := url.Values{"token": {api.token}, "muted_channels": {newChnls}, "reason": {"update-muted-channels"}}
response := UserPrefsCarrier{}
err = api.postMethod(context.Background(), "users.prefs.set", values, &response)
if err != nil {
return nil, err
}
return &response, response.Err()
}
func (api *Client) UnMuteChat(channelID string) (*UserPrefsCarrier, error) {
prefs, err := api.GetUserPrefs()
if err != nil {
return nil, err
}
chnls := strings.Split(prefs.UserPrefs.MutedChannels, ",")
newChnls := make([]string, len(chnls)-1)
for i, chn := range chnls {
if chn == channelID {
return nil, nil // noop
}
newChnls[i] = chn
}
values := url.Values{"token": {api.token}, "muted_channels": {strings.Join(newChnls, ",")}, "reason": {"update-muted-channels"}}
response := UserPrefsCarrier{}
err = api.postMethod(context.Background(), "users.prefs.set", values, &response)
if err != nil {
return nil, err
}
return &response, response.Err()
}
// UserDetails contains user details coming in the initial response from StartRTM
type UserDetails struct {
ID string `json:"id"`
Name string `json:"name"`
Created JSONTime `json:"created"`
ManualPresence string `json:"manual_presence"`
Prefs UserPrefs `json:"prefs"`
}
// JSONTime exists so that we can have a String method converting the date
type JSONTime int64
// String converts the unix timestamp into a string
func (t JSONTime) String() string {
tm := t.Time()
return fmt.Sprintf("\"%s\"", tm.Format("Mon Jan _2"))
}
// Time returns a `time.Time` representation of this value.
func (t JSONTime) Time() time.Time {
return time.Unix(int64(t), 0)
}
// UnmarshalJSON will unmarshal both string and int JSON values
func (t *JSONTime) UnmarshalJSON(buf []byte) error {
s := bytes.Trim(buf, `"`)
v, err := strconv.Atoi(string(s))
if err != nil {
return err
}
*t = JSONTime(int64(v))
return nil
}
// Team contains details about a team
type Team struct {
ID string `json:"id"`
Name string `json:"name"`
Domain string `json:"domain"`
}
// Icons XXX: needs further investigation
type Icons struct {
Image36 string `json:"image_36,omitempty"`
Image48 string `json:"image_48,omitempty"`
Image72 string `json:"image_72,omitempty"`
}
// Info contains various details about the authenticated user and team.
// It is returned by StartRTM or included in the "ConnectedEvent" RTM event.
type Info struct {
URL string `json:"url,omitempty"`
User *UserDetails `json:"self,omitempty"`
Team *Team `json:"team,omitempty"`
}
type infoResponseFull struct {
Info
SlackResponse
}
// GetBotByID is deprecated and returns nil
func (info Info) GetBotByID(botID string) *Bot {
return nil
}
// GetUserByID is deprecated and returns nil
func (info Info) GetUserByID(userID string) *User {
return nil
}
// GetChannelByID is deprecated and returns nil
func (info Info) GetChannelByID(channelID string) *Channel {
return nil
}
// GetGroupByID is deprecated and returns nil
func (info Info) GetGroupByID(groupID string) *Group {
return nil
}
// GetIMByID is deprecated and returns nil
func (info Info) GetIMByID(imID string) *IM {
return nil
}

View File

@ -24,6 +24,9 @@ const (
InteractionTypeInteractionMessage = InteractionType("interactive_message")
InteractionTypeMessageAction = InteractionType("message_action")
InteractionTypeBlockActions = InteractionType("block_actions")
InteractionTypeBlockSuggestion = InteractionType("block_suggestion")
InteractionTypeViewSubmission = InteractionType("view_submission")
InteractionTypeViewClosed = InteractionType("view_closed")
)
// InteractionCallback is sent from slack when a user interactions with a button or dialog.
@ -44,7 +47,19 @@ type InteractionCallback struct {
MessageTs string `json:"message_ts"`
AttachmentID string `json:"attachment_id"`
ActionCallback ActionCallbacks `json:"actions"`
View View `json:"view"`
ActionID string `json:"action_id"`
APIAppID string `json:"api_app_id"`
BlockID string `json:"block_id"`
Container Container `json:"container"`
DialogSubmissionCallback
ViewSubmissionCallback
ViewClosedCallback
}
type Container struct {
Type string `json:"type"`
ViewID string `json:"view_id"`
}
// ActionCallback is a convenience struct defined to allow dynamic unmarshalling of

View File

@ -15,13 +15,14 @@ type OutgoingMessage struct {
// Message is an auxiliary type to allow us to have a message containing sub messages
type Message struct {
Msg
SubMessage *Msg `json:"message,omitempty"`
SubMessage *Msg `json:"message,omitempty"`
PreviousMessage *Msg `json:"previous_message,omitempty"`
}
// Msg contains information about a slack message
type Msg struct {
// Basic Message
ClientMsgID string `json:"client_msg_id"`
Type string `json:"type,omitempty"`
Channel string `json:"channel,omitempty"`
User string `json:"user,omitempty"`

View File

@ -31,6 +31,40 @@ type OAuthResponse struct {
SlackResponse
}
// OAuthV2Response ...
type OAuthV2Response struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
Scope string `json:"scope"`
BotUserID string `json:"bot_user_id"`
AppID string `json:"app_id"`
TeamID string `json:"team_id"`
Team OAuthV2ResponseTeam `json:"team"`
Enterprise OAuthV2ResponseEnterprise `json:"enterprise"`
AuthedUser OAuthV2ResponseAuthedUser `json:"authed_user"`
SlackResponse
}
// OAuthV2ResponseTeam ...
type OAuthV2ResponseTeam struct {
ID string `json:"id"`
Name string `json:"name"`
}
// OAuthV2ResponseEnterprise ...
type OAuthV2ResponseEnterprise struct {
ID string `json:"id"`
Name string `json:"name"`
}
// OAuthV2ResponseAuthedUser ...
type OAuthV2ResponseAuthedUser struct {
ID string `json:"id"`
Scope string `json:"scope"`
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
}
// GetOAuthToken retrieves an AccessToken
func GetOAuthToken(client httpClient, clientID, clientSecret, code, redirectURI string) (accessToken string, scope string, err error) {
return GetOAuthTokenContext(context.Background(), client, clientID, clientSecret, code, redirectURI)
@ -62,3 +96,23 @@ func GetOAuthResponseContext(ctx context.Context, client httpClient, clientID, c
}
return response, response.Err()
}
// GetOAuthV2Response gets a V2 OAuth access token response - https://api.slack.com/methods/oauth.v2.access
func GetOAuthV2Response(client httpClient, clientID, clientSecret, code, redirectURI string) (resp *OAuthV2Response, err error) {
return GetOAuthV2ResponseContext(context.Background(), client, clientID, clientSecret, code, redirectURI)
}
// GetOAuthV2ResponseContext with a context, gets a V2 OAuth access token response
func GetOAuthV2ResponseContext(ctx context.Context, client httpClient, clientID, clientSecret, code, redirectURI string) (resp *OAuthV2Response, err error) {
values := url.Values{
"client_id": {clientID},
"client_secret": {clientSecret},
"code": {code},
"redirect_uri": {redirectURI},
}
response := &OAuthV2Response{}
if err = postForm(ctx, client, APIURL+"oauth.v2.access", values, response, discard{}); err != nil {
return nil, err
}
return response, response.Err()
}

View File

@ -96,7 +96,7 @@ func New(token string, options ...Option) *Client {
token: token,
endpoint: APIURL,
httpclient: &http.Client{},
log: log.New(os.Stderr, "nlopes/slack", log.LstdFlags|log.Lshortfile),
log: log.New(os.Stderr, "slack-go/slack", log.LstdFlags|log.Lshortfile),
}
for _, opt := range options {

View File

@ -206,7 +206,7 @@ func (api *Client) UpdateUserGroupContext(ctx context.Context, userGroup UserGro
if userGroup.Description != "" {
values["description"] = []string{userGroup.Description}
}
if len(userGroup.Prefs.Channels) > 0 {
values["channels"] = []string{strings.Join(userGroup.Prefs.Channels, ",")}
}

View File

@ -44,14 +44,14 @@ type UserProfile struct {
// UserProfileCustomFields represents user profile's custom fields.
// Slack API's response data type is inconsistent so we use the struct.
// For detail, please see below.
// https://github.com/nlopes/slack/pull/298#discussion_r185159233
// https://github.com/slack-go/slack/pull/298#discussion_r185159233
type UserProfileCustomFields struct {
fields map[string]UserProfileCustomField
}
// UnmarshalJSON is the implementation of the json.Unmarshaler interface.
func (fields *UserProfileCustomFields) UnmarshalJSON(b []byte) error {
// https://github.com/nlopes/slack/pull/298#discussion_r185159233
// https://github.com/slack-go/slack/pull/298#discussion_r185159233
if string(b) == "[]" {
return nil
}

275
vendor/github.com/slack-go/slack/views.go generated vendored Normal file
View File

@ -0,0 +1,275 @@
package slack
import (
"context"
"encoding/json"
)
const (
VTModal ViewType = "modal"
VTHomeTab ViewType = "home"
)
type ViewType string
type ViewState struct {
Values map[string]map[string]BlockAction `json:"values"`
}
type View struct {
SlackResponse
ID string `json:"id"`
TeamID string `json:"team_id"`
Type ViewType `json:"type"`
Title *TextBlockObject `json:"title"`
Close *TextBlockObject `json:"close"`
Submit *TextBlockObject `json:"submit"`
Blocks Blocks `json:"blocks"`
PrivateMetadata string `json:"private_metadata"`
CallbackID string `json:"callback_id"`
State *ViewState `json:"state"`
Hash string `json:"hash"`
ClearOnClose bool `json:"clear_on_close"`
NotifyOnClose bool `json:"notify_on_close"`
RootViewID string `json:"root_view_id"`
PreviousViewID string `json:"previous_view_id"`
AppID string `json:"app_id"`
ExternalID string `json:"external_id"`
BotID string `json:"bot_id"`
}
type ViewSubmissionCallback struct {
Hash string `json:"hash"`
}
type ViewClosedCallback struct {
IsCleared bool `json:"is_cleared"`
}
const (
RAClear ViewResponseAction = "clear"
RAUpdate ViewResponseAction = "update"
RAPush ViewResponseAction = "push"
RAErrors ViewResponseAction = "errors"
)
type ViewResponseAction string
type ViewSubmissionResponse struct {
ResponseAction ViewResponseAction `json:"response_action"`
View *ModalViewRequest `json:"view,omitempty"`
Errors map[string]string `json:"errors,omitempty"`
}
func NewClearViewSubmissionResponse() *ViewSubmissionResponse {
return &ViewSubmissionResponse{
ResponseAction: RAClear,
}
}
func NewUpdateViewSubmissionResponse(view *ModalViewRequest) *ViewSubmissionResponse {
return &ViewSubmissionResponse{
ResponseAction: RAUpdate,
View: view,
}
}
func NewPushViewSubmissionResponse(view *ModalViewRequest) *ViewSubmissionResponse {
return &ViewSubmissionResponse{
ResponseAction: RAPush,
View: view,
}
}
func NewErrorsViewSubmissionResponse(errors map[string]string) *ViewSubmissionResponse {
return &ViewSubmissionResponse{
ResponseAction: RAErrors,
Errors: errors,
}
}
type ModalViewRequest struct {
Type ViewType `json:"type"`
Title *TextBlockObject `json:"title"`
Blocks Blocks `json:"blocks"`
Close *TextBlockObject `json:"close,omitempty"`
Submit *TextBlockObject `json:"submit,omitempty"`
PrivateMetadata string `json:"private_metadata,omitempty"`
CallbackID string `json:"callback_id,omitempty"`
ClearOnClose bool `json:"clear_on_close,omitempty"`
NotifyOnClose bool `json:"notify_on_close,omitempty"`
ExternalID string `json:"external_id,omitempty"`
}
func (v *ModalViewRequest) ViewType() ViewType {
return v.Type
}
type HomeTabViewRequest struct {
Type ViewType `json:"type"`
Blocks Blocks `json:"blocks"`
PrivateMetadata string `json:"private_metadata,omitempty"`
CallbackID string `json:"callback_id,omitempty"`
ExternalID string `json:"external_id,omitempty"`
}
func (v *HomeTabViewRequest) ViewType() ViewType {
return v.Type
}
type openViewRequest struct {
TriggerID string `json:"trigger_id"`
View ModalViewRequest `json:"view"`
}
type publishViewRequest struct {
UserID string `json:"user_id"`
View HomeTabViewRequest `json:"view"`
Hash string `json:"hash,omitempty"`
}
type pushViewRequest struct {
TriggerID string `json:"trigger_id"`
View ModalViewRequest `json:"view"`
}
type updateViewRequest struct {
View ModalViewRequest `json:"view"`
ExternalID string `json:"external_id,omitempty"`
Hash string `json:"hash,omitempty"`
ViewID string `json:"view_id,omitempty"`
}
type ViewResponse struct {
SlackResponse
View `json:"view"`
}
// OpenView opens a view for a user.
func (api *Client) OpenView(triggerID string, view ModalViewRequest) (*ViewResponse, error) {
return api.OpenViewContext(context.Background(), triggerID, view)
}
// OpenViewContext opens a view for a user with a custom context.
func (api *Client) OpenViewContext(
ctx context.Context,
triggerID string,
view ModalViewRequest,
) (*ViewResponse, error) {
if triggerID == "" {
return nil, ErrParametersMissing
}
req := openViewRequest{
TriggerID: triggerID,
View: view,
}
encoded, err := json.Marshal(req)
if err != nil {
return nil, err
}
endpoint := api.endpoint + "views.open"
resp := &ViewResponse{}
err = postJSON(ctx, api.httpclient, endpoint, api.token, encoded, resp, api)
if err != nil {
return nil, err
}
return resp, resp.Err()
}
// PublishView publishes a static view for a user.
func (api *Client) PublishView(userID string, view HomeTabViewRequest, hash string) (*ViewResponse, error) {
return api.PublishViewContext(context.Background(), userID, view, hash)
}
// PublishViewContext publishes a static view for a user with a custom context.
func (api *Client) PublishViewContext(
ctx context.Context,
userID string,
view HomeTabViewRequest,
hash string,
) (*ViewResponse, error) {
if userID == "" {
return nil, ErrParametersMissing
}
req := publishViewRequest{
UserID: userID,
View: view,
Hash: hash,
}
encoded, err := json.Marshal(req)
if err != nil {
return nil, err
}
endpoint := api.endpoint + "views.publish"
resp := &ViewResponse{}
err = postJSON(ctx, api.httpclient, endpoint, api.token, encoded, resp, api)
if err != nil {
return nil, err
}
return resp, resp.Err()
}
// PushView pushes a view onto the stack of a root view.
func (api *Client) PushView(triggerID string, view ModalViewRequest) (*ViewResponse, error) {
return api.PushViewContext(context.Background(), triggerID, view)
}
// PublishViewContext pushes a view onto the stack of a root view with a custom context.
func (api *Client) PushViewContext(
ctx context.Context,
triggerID string,
view ModalViewRequest,
) (*ViewResponse, error) {
if triggerID == "" {
return nil, ErrParametersMissing
}
req := pushViewRequest{
TriggerID: triggerID,
View: view,
}
encoded, err := json.Marshal(req)
if err != nil {
return nil, err
}
endpoint := api.endpoint + "views.push"
resp := &ViewResponse{}
err = postJSON(ctx, api.httpclient, endpoint, api.token, encoded, resp, api)
if err != nil {
return nil, err
}
return resp, resp.Err()
}
// UpdateView updates an existing view.
func (api *Client) UpdateView(view ModalViewRequest, externalID, hash, viewID string) (*ViewResponse, error) {
return api.UpdateViewContext(context.Background(), view, externalID, hash, viewID)
}
// UpdateViewContext updates an existing view with a custom context.
func (api *Client) UpdateViewContext(
ctx context.Context,
view ModalViewRequest,
externalID, hash,
viewID string,
) (*ViewResponse, error) {
if externalID == "" && viewID == "" {
return nil, ErrParametersMissing
}
req := updateViewRequest{
View: view,
ExternalID: externalID,
Hash: hash,
ViewID: viewID,
}
encoded, err := json.Marshal(req)
if err != nil {
return nil, err
}
endpoint := api.endpoint + "views.update"
resp := &ViewResponse{}
err = postJSON(ctx, api.httpclient, endpoint, api.token, encoded, resp, api)
if err != nil {
return nil, err
}
return resp, resp.Err()
}

View File

@ -1,11 +1,8 @@
package slack
import (
"bytes"
"encoding/json"
"context"
"net/http"
"github.com/pkg/errors"
)
type WebhookMessage struct {
@ -20,21 +17,13 @@ type WebhookMessage struct {
}
func PostWebhook(url string, msg *WebhookMessage) error {
return PostWebhookCustomHTTP(url, http.DefaultClient, msg)
return PostWebhookCustomHTTPContext(context.Background(), url, http.DefaultClient, msg)
}
func PostWebhookContext(ctx context.Context, url string, msg *WebhookMessage) error {
return PostWebhookCustomHTTPContext(ctx, url, http.DefaultClient, msg)
}
func PostWebhookCustomHTTP(url string, httpClient *http.Client, msg *WebhookMessage) error {
raw, err := json.Marshal(msg)
if err != nil {
return errors.Wrap(err, "marshal failed")
}
response, err := httpClient.Post(url, "application/json", bytes.NewReader(raw))
if err != nil {
return errors.Wrap(err, "failed to post webhook")
}
return checkStatusCode(response, discard{})
return PostWebhookCustomHTTPContext(context.Background(), url, httpClient, msg)
}

34
vendor/github.com/slack-go/slack/webhooks_go112.go generated vendored Normal file
View File

@ -0,0 +1,34 @@
// +build !go1.13
package slack
import (
"bytes"
"context"
"encoding/json"
"net/http"
"github.com/pkg/errors"
)
func PostWebhookCustomHTTPContext(ctx context.Context, url string, httpClient *http.Client, msg *WebhookMessage) error {
raw, err := json.Marshal(msg)
if err != nil {
return errors.Wrap(err, "marshal failed")
}
req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(raw))
if err != nil {
return errors.Wrap(err, "failed new request")
}
req = req.WithContext(ctx)
req.Header.Set("Content-Type", "application/json")
resp, err := httpClient.Do(req)
if err != nil {
return errors.Wrap(err, "failed to post webhook")
}
defer resp.Body.Close()
return checkStatusCode(resp, discard{})
}

33
vendor/github.com/slack-go/slack/webhooks_go113.go generated vendored Normal file
View File

@ -0,0 +1,33 @@
// +build go1.13
package slack
import (
"bytes"
"context"
"encoding/json"
"net/http"
"github.com/pkg/errors"
)
func PostWebhookCustomHTTPContext(ctx context.Context, url string, httpClient *http.Client, msg *WebhookMessage) error {
raw, err := json.Marshal(msg)
if err != nil {
return errors.Wrap(err, "marshal failed")
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(raw))
if err != nil {
return errors.Wrap(err, "failed new request")
}
req.Header.Set("Content-Type", "application/json")
resp, err := httpClient.Do(req)
if err != nil {
return errors.Wrap(err, "failed to post webhook")
}
defer resp.Body.Close()
return checkStatusCode(resp, discard{})
}

View File

@ -45,7 +45,7 @@ type ChannelRenameEvent struct {
type ChannelRenameInfo struct {
ID string `json:"id"`
Name string `json:"name"`
Created string `json:"created"`
Created int `json:"created"`
}
// ChannelHistoryChangedEvent represents the Channel history changed event

View File

@ -10,8 +10,8 @@ import (
"time"
"github.com/gorilla/websocket"
"github.com/nlopes/slack/internal/errorsx"
"github.com/nlopes/slack/internal/timex"
"github.com/slack-go/slack/internal/errorsx"
"github.com/slack-go/slack/internal/timex"
)
// ManageConnection can be called on a Slack RTM instance returned by the
@ -577,5 +577,6 @@ var EventMapping = map[string]interface{}{
"subteam_self_removed": SubteamSelfRemovedEvent{},
"subteam_updated": SubteamUpdatedEvent{},
"desktop_notification": DesktopNotificationEvent{},
"desktop_notification": DesktopNotificationEvent{},
"mobile_in_app_notification": MobileInAppNotificationEvent{},
}

View File

@ -0,0 +1,20 @@
package slack
// MobileInAppNotificationEvent represents the update event for Mobile App Notification.
type MobileInAppNotificationEvent struct {
Type string `json:"type"`
Title string `json:"title"`
Subtitle string `json:"subtitle"`
Timestamp string `json:"ts"`
Channel string `json:"channel"`
AvatarImage string `json:"avatarImage"`
IsShared bool `json:"is_shared"`
ChannelName string `json:"channel_name"`
AuthorID string `json:"author_id"`
AuthorDisplayName string `json:"author_display_name"`
MessageText string `json:"msg_text"`
PushID string `json:"push_id"`
NotifcationID string `json:"notif_id"`
MobileLaunchURI string `json:"mobileLaunchUri"`
EventTimestamp string `json:"event_ts"`
}

Some files were not shown because too many files have changed in this diff Show More