Update vendor (#1461)

* Update vendored libs

* Fix slack api changes
This commit is contained in:
Wim 2021-05-05 22:03:28 +02:00 committed by GitHub
parent af543dcd05
commit a0bca42a7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 430 additions and 1652 deletions

View File

@ -156,7 +156,7 @@ func (b *Bslack) JoinChannel(channel config.ChannelInfo) error {
// try to join a channel when in legacy // try to join a channel when in legacy
if b.legacy { if b.legacy {
_, err := b.sc.JoinChannel(channel.Name) _, _, _, err := b.sc.JoinConversation(channel.Name)
if err != nil { if err != nil {
switch err.Error() { switch err.Error() {
case "name_taken", "restricted_action": case "name_taken", "restricted_action":

View File

@ -283,7 +283,7 @@ func (b *channels) populateChannels(wait bool) {
// We only retrieve public and private channels, not IMs // We only retrieve public and private channels, not IMs
// and MPIMs as those do not have a channel name. // and MPIMs as those do not have a channel name.
queryParams := &slack.GetConversationsParameters{ queryParams := &slack.GetConversationsParameters{
ExcludeArchived: "true", ExcludeArchived: true,
Types: []string{"public_channel,private_channel"}, Types: []string{"public_channel,private_channel"},
} }
for { for {

12
go.mod
View File

@ -6,13 +6,13 @@ require (
github.com/Jeffail/gabs v1.4.0 // indirect github.com/Jeffail/gabs v1.4.0 // indirect
github.com/Philipp15b/go-steam v1.0.1-0.20200727090957-6ae9b3c0a560 github.com/Philipp15b/go-steam v1.0.1-0.20200727090957-6ae9b3c0a560
github.com/Rhymen/go-whatsapp v0.1.2-0.20210126174449-3c094ebae0ce github.com/Rhymen/go-whatsapp v0.1.2-0.20210126174449-3c094ebae0ce
github.com/SevereCloud/vksdk/v2 v2.9.0 github.com/SevereCloud/vksdk/v2 v2.9.1
github.com/d5/tengo/v2 v2.7.0 github.com/d5/tengo/v2 v2.7.0
github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew v1.1.1
github.com/fsnotify/fsnotify v1.4.9 github.com/fsnotify/fsnotify v1.4.9
github.com/go-telegram-bot-api/telegram-bot-api v1.0.1-0.20200524105306-7434b0456e81 github.com/go-telegram-bot-api/telegram-bot-api v1.0.1-0.20200524105306-7434b0456e81
github.com/gomarkdown/markdown v0.0.0-20210208175418-bda154fe17d8 github.com/gomarkdown/markdown v0.0.0-20210408062403-ad838ccf8cdd
github.com/google/gops v0.3.17 github.com/google/gops v0.3.18
github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4 // indirect github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4 // indirect
github.com/gorilla/schema v1.2.0 github.com/gorilla/schema v1.2.0
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
@ -20,7 +20,7 @@ require (
github.com/jpillora/backoff v1.0.0 github.com/jpillora/backoff v1.0.0
github.com/keybase/go-keybase-chat-bot v0.0.0-20200505163032-5cacf52379da github.com/keybase/go-keybase-chat-bot v0.0.0-20200505163032-5cacf52379da
github.com/kyokomi/emoji/v2 v2.2.8 github.com/kyokomi/emoji/v2 v2.2.8
github.com/labstack/echo/v4 v4.2.1 github.com/labstack/echo/v4 v4.2.2
github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7 github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7
github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20210403163225-761e8622445d github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20210403163225-761e8622445d
@ -41,7 +41,7 @@ require (
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca
github.com/shazow/ssh-chat v1.10.1 github.com/shazow/ssh-chat v1.10.1
github.com/sirupsen/logrus v1.8.1 github.com/sirupsen/logrus v1.8.1
github.com/slack-go/slack v0.8.2 github.com/slack-go/slack v0.9.0
github.com/spf13/afero v1.3.4 // indirect github.com/spf13/afero v1.3.4 // indirect
github.com/spf13/cast v1.3.1 // indirect github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/viper v1.7.1 github.com/spf13/viper v1.7.1
@ -52,7 +52,7 @@ require (
github.com/yaegashi/msgraph.go v0.1.4 github.com/yaegashi/msgraph.go v0.1.4
github.com/zfjagann/golang-ring v0.0.0-20210116075443-7c86fdb43134 github.com/zfjagann/golang-ring v0.0.0-20210116075443-7c86fdb43134
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c
gomod.garykim.dev/nc-talk v0.1.7 gomod.garykim.dev/nc-talk v0.1.7
gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376 gopkg.in/olahol/melody.v1 v1.0.0-20170518105555-d52139073376
layeh.com/gumble v0.0.0-20200818122324-146f9205029b layeh.com/gumble v0.0.0-20200818122324-146f9205029b

27
go.sum
View File

@ -85,8 +85,8 @@ github.com/Rhymen/go-whatsapp/examples/sendImage v0.0.0-20190325075644-cc2581bbf
github.com/Rhymen/go-whatsapp/examples/sendTextMessages v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:suwzklatySS3Q0+NCxCDh5hYfgXdQUWU1DNcxwAxStM= github.com/Rhymen/go-whatsapp/examples/sendTextMessages v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:suwzklatySS3Q0+NCxCDh5hYfgXdQUWU1DNcxwAxStM=
github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
github.com/RoaringBitmap/roaring v0.5.1/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= github.com/RoaringBitmap/roaring v0.5.1/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
github.com/SevereCloud/vksdk/v2 v2.9.0 h1:39qjzmozK5FDfnDkfA+YN0CtKi4mDrzjPtoT5GN9Xg0= github.com/SevereCloud/vksdk/v2 v2.9.1 h1:5+8feQenzF21UJFVE3UVu3EfLJWWiWo47LKNjpg4VqY=
github.com/SevereCloud/vksdk/v2 v2.9.0/go.mod h1:IBmfJ3rs+zDLD9NHCoJEpgg5A4UOoxgUU/g8p5lYb48= github.com/SevereCloud/vksdk/v2 v2.9.1/go.mod h1:jCicWsIOXu4bfbGGuvVw4dM/EbrC8dOyA+0ccvhiFEo=
github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
@ -320,8 +320,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomarkdown/markdown v0.0.0-20210208175418-bda154fe17d8 h1:nWU6p08f1VgIalT6iZyqXi4o5cZsz4X6qa87nusfcsc= github.com/gomarkdown/markdown v0.0.0-20210408062403-ad838ccf8cdd h1:0b8AqsWQb6A0jjx80UXLG/uMTXQkGD0IGuXWqsrNz1M=
github.com/gomarkdown/markdown v0.0.0-20210208175418-bda154fe17d8/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU= github.com/gomarkdown/markdown v0.0.0-20210408062403-ad838ccf8cdd/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU=
github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@ -338,8 +338,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gops v0.3.17 h1:CguOcnDVYG32soOj2YevV8mW9asrIh1lZw3d7Ovty/o= github.com/google/gops v0.3.18 h1:my259V+172PVFmduS2RAsq4FKH+HjKqdh7pLr17Ot8c=
github.com/google/gops v0.3.17/go.mod h1:Pfp8hWGIFdV/7rY9/O/U5WgdjYQXf/GiEK4NVuVd2ZE= github.com/google/gops v0.3.18/go.mod h1:Pfp8hWGIFdV/7rY9/O/U5WgdjYQXf/GiEK4NVuVd2ZE=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
@ -509,8 +509,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kyokomi/emoji/v2 v2.2.8 h1:jcofPxjHWEkJtkIbcLHvZhxKgCPl6C7MyjTrD4KDqUE= github.com/kyokomi/emoji/v2 v2.2.8 h1:jcofPxjHWEkJtkIbcLHvZhxKgCPl6C7MyjTrD4KDqUE=
github.com/kyokomi/emoji/v2 v2.2.8/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE= github.com/kyokomi/emoji/v2 v2.2.8/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
github.com/labstack/echo/v4 v4.2.1 h1:LF5Iq7t/jrtUuSutNuiEWtB5eiHfZ5gSe2pcu5exjQw= github.com/labstack/echo/v4 v4.2.2 h1:bq2fdZCionY1jck8rzUpQEu2YSmI8QbX6LHrCa60IVs=
github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= github.com/labstack/echo/v4 v4.2.2/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=
github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0= github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o=
@ -816,8 +816,8 @@ github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9 h1:lpEzuenPuO1XNTeikEmvqYFcU37GVLl8SRNblzyvGBE= github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9 h1:lpEzuenPuO1XNTeikEmvqYFcU37GVLl8SRNblzyvGBE=
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo= github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9/go.mod h1:PLPIyL7ikehBD1OAjmKKiOEhbvWyHGaNDjquXMcYABo=
github.com/slack-go/slack v0.8.2 h1:D7jNu0AInBfdQ4QyKPtVSp+ZxQes3EzWW17RZ/va4JE= github.com/slack-go/slack v0.9.0 h1:C4VCefOTthLSHlq2g+Stww33TdW+P+ewk7VDYXCHT/o=
github.com/slack-go/slack v0.8.2/go.mod h1:FGqNzJBmxIsZURAxh2a8D21AnOVvvXZvGligs4npPUM= github.com/slack-go/slack v0.9.0/go.mod h1:wWL//kk0ho+FcQXcBTmEafUI5dz4qz5f4mMk8oIkioQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8= github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8=
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
@ -1094,8 +1094,8 @@ golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c h1:SgVl/sCtkicsS7psKkje4H9YtjdEl3xsYh7N+5TDHqY=
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -1171,8 +1171,9 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

View File

@ -39,6 +39,13 @@ linters:
- tparallel - tparallel
- errorlint - errorlint
- paralleltest - paralleltest
- forbidigo
- makezero
- thelper
- predeclared
- ifshort
- revive
- durationcheck
# - wrapcheck # TODO: v3 Fix # - wrapcheck # TODO: v3 Fix
# - testpackage # TODO: Fix testpackage # - testpackage # TODO: Fix testpackage
@ -62,6 +69,7 @@ linters:
# - nlreturn # - nlreturn
# - gci # - gci
# - exhaustivestruct # - exhaustivestruct
# - cyclop
issues: issues:
exclude-rules: exclude-rules:

View File

@ -7,6 +7,6 @@ package vksdk
// Module constants. // Module constants.
const ( const (
Version = "2.9.0" Version = "2.9.1"
API = "5.126" API = "5.126"
) )

View File

@ -316,40 +316,40 @@ type LikeRemoveObject struct {
// DonutSubscriptionCreateObject struct. // DonutSubscriptionCreateObject struct.
type DonutSubscriptionCreateObject struct { type DonutSubscriptionCreateObject struct {
Amount int `json:"amount"` Amount float64 `json:"amount"`
AmountWithoutFee float64 `json:"amount_without_fee"` AmountWithoutFee float64 `json:"amount_without_fee"`
UserID int `json:"user_id"` UserID float64 `json:"user_id"`
} }
// DonutSubscriptionProlongedObject struct. // DonutSubscriptionProlongedObject struct.
type DonutSubscriptionProlongedObject struct { type DonutSubscriptionProlongedObject struct {
Amount int `json:"amount"` Amount float64 `json:"amount"`
AmountWithoutFee float64 `json:"amount_without_fee"` AmountWithoutFee float64 `json:"amount_without_fee"`
UserID int `json:"user_id"` UserID float64 `json:"user_id"`
} }
// DonutSubscriptionExpiredObject struct. // DonutSubscriptionExpiredObject struct.
type DonutSubscriptionExpiredObject struct { type DonutSubscriptionExpiredObject struct {
UserID int `json:"user_id"` UserID float64 `json:"user_id"`
} }
// DonutSubscriptionCancelledObject struct. // DonutSubscriptionCancelledObject struct.
type DonutSubscriptionCancelledObject struct { type DonutSubscriptionCancelledObject struct {
UserID int `json:"user_id"` UserID float64 `json:"user_id"`
} }
// DonutSubscriptionPriceChangedObject struct. // DonutSubscriptionPriceChangedObject struct.
type DonutSubscriptionPriceChangedObject struct { type DonutSubscriptionPriceChangedObject struct {
AmountOld int `json:"amount_old"` AmountOld float64 `json:"amount_old"`
AmountNew int `json:"amount_new"` AmountNew float64 `json:"amount_new"`
AmountDiff float64 `json:"amount_diff"` AmountDiff float64 `json:"amount_diff"`
AmountDiffWithoutFee float64 `json:"amount_diff_without_fee"` AmountDiffWithoutFee float64 `json:"amount_diff_without_fee"`
UserID int `json:"user_id"` UserID float64 `json:"user_id"`
} }
// DonutMoneyWithdrawObject struct. // DonutMoneyWithdrawObject struct.
type DonutMoneyWithdrawObject struct { type DonutMoneyWithdrawObject struct {
Amount int `json:"amount"` Amount float64 `json:"amount"`
AmountWithoutFee float64 `json:"amount_without_fee"` AmountWithoutFee float64 `json:"amount_without_fee"`
} }

View File

@ -5,6 +5,6 @@ go 1.13
require ( require (
github.com/gorilla/schema v1.2.0 github.com/gorilla/schema v1.2.0
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/stretchr/testify v1.6.1 github.com/stretchr/testify v1.7.0
golang.org/x/text v0.3.4 golang.org/x/text v0.3.5
) )

View File

@ -7,10 +7,10 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -207,8 +207,7 @@ type AdsStatsSexAge struct {
} }
// AdsTargSettings struct. // AdsTargSettings struct.
type AdsTargSettings struct { type AdsTargSettings struct{}
}
// AdsTargStats struct. // AdsTargStats struct.
type AdsTargStats struct { type AdsTargStats struct {

View File

@ -721,8 +721,7 @@ type MessagesPinnedMessage struct {
} }
// MessagesUserXtrInvitedBy struct. // MessagesUserXtrInvitedBy struct.
type MessagesUserXtrInvitedBy struct { type MessagesUserXtrInvitedBy struct{}
}
// MessagesForward struct. // MessagesForward struct.
type MessagesForward struct { type MessagesForward struct {

View File

@ -87,11 +87,11 @@ type NewsfeedItemStoriesBlock struct {
} }
// NewsfeedItemTopic struct. // NewsfeedItemTopic struct.
type NewsfeedItemTopic struct { //
// Comments BaseCommentsInfo `json:"comments"` // Comments BaseCommentsInfo `json:"comments"`
// Likes BaseLikesInfo `json:"likes"` // Likes BaseLikesInfo `json:"likes"`
// Text string `json:"text"` // Post text // Text string `json:"text"` // Post text.
} type NewsfeedItemTopic struct{}
// NewsfeedItemVideo struct. // NewsfeedItemVideo struct.
type NewsfeedItemVideo struct { type NewsfeedItemVideo struct {

View File

@ -142,7 +142,7 @@ type WallWallpost struct {
FriendsOnly int `json:"friends_only"` FriendsOnly int `json:"friends_only"`
Comments BaseCommentsInfo `json:"comments"` Comments BaseCommentsInfo `json:"comments"`
Likes BaseLikesInfo `json:"likes"` // Count of likes Likes BaseLikesInfo `json:"likes"` // Count of likes
Reposts BaseRepostsInfo `json:"reposts"` // Count of views Reposts BaseRepostsInfo `json:"reposts"` // Count of reposts
Views WallViews `json:"views"` // Count of views Views WallViews `json:"views"` // Count of views
PostType string `json:"post_type"` PostType string `json:"post_type"`
PostSource WallPostSource `json:"post_source"` PostSource WallPostSource `json:"post_source"`

View File

@ -9,7 +9,7 @@ A renderer can be configured with multiple options:
flags := html.CommonFlags | html.CompletePage | html.HrefTargetBlank flags := html.CommonFlags | html.CompletePage | html.HrefTargetBlank
opts := html.RendererOptions{ opts := html.RendererOptions{
TItle: "A custom title", Title: "A custom title",
Flags: flags, Flags: flags,
} }
renderer := html.NewRenderer(opts) renderer := html.NewRenderer(opts)

View File

@ -43,6 +43,7 @@ const (
SmartypantsAngledQuotes // Enable angled double quotes (with Smartypants) for double quotes rendering SmartypantsAngledQuotes // Enable angled double quotes (with Smartypants) for double quotes rendering
SmartypantsQuotesNBSP // Enable « French guillemets » (with Smartypants) SmartypantsQuotesNBSP // Enable « French guillemets » (with Smartypants)
TOC // Generate a table of contents TOC // Generate a table of contents
LazyLoadImages // Include loading="lazy" with images
CommonFlags Flags = Smartypants | SmartypantsFractions | SmartypantsDashes | SmartypantsLatexDashes CommonFlags Flags = Smartypants | SmartypantsFractions | SmartypantsDashes | SmartypantsLatexDashes
) )
@ -589,7 +590,11 @@ func (r *Renderer) imageEnter(w io.Writer, image *ast.Image) {
//if options.safe && potentiallyUnsafe(dest) { //if options.safe && potentiallyUnsafe(dest) {
//out(w, `<img src="" alt="`) //out(w, `<img src="" alt="`)
//} else { //} else {
r.Outs(w, `<img src="`) if r.opts.Flags&LazyLoadImages != 0 {
r.Outs(w, `<img loading="lazy" src="`)
} else {
r.Outs(w, `<img src="`)
}
escLink(w, dest) escLink(w, dest)
r.Outs(w, `" alt="`) r.Outs(w, `" alt="`)
//} //}

View File

@ -59,7 +59,7 @@ type Options struct {
ShutdownCleanup bool ShutdownCleanup bool
// ReuseSocketAddrAndPort determines whether the SO_REUSEADDR and // ReuseSocketAddrAndPort determines whether the SO_REUSEADDR and
// SO_REUSEADDR socket options should be set on the listening socket of // SO_REUSEPORT socket options should be set on the listening socket of
// the agent. This option is only effective on unix-like OSes and if // the agent. This option is only effective on unix-like OSes and if
// Addr is set to a fixed host:port. // Addr is set to a fixed host:port.
// Optional. // Optional.

View File

@ -1,5 +1,15 @@
# Changelog # Changelog
## v4.2.2 - 2020-04-07
**Fixes**
* Allow proxy middleware to use query part in rewrite (#1802)
* Fix timeout middleware not sending status code when handler returns an error (#1805)
* Fix Bind() when target is array/slice and path/query params complains bind target not being struct (#1835)
* Fix panic in redirect middleware on short host name (#1813)
* Fix timeout middleware docs (#1836)
## v4.2.1 - 2020-03-08 ## v4.2.1 - 2020-03-08
**Important notes** **Important notes**

View File

@ -134,6 +134,10 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
// !struct // !struct
if typ.Kind() != reflect.Struct { if typ.Kind() != reflect.Struct {
if tag == "param" || tag == "query" {
// incompatible type, data is probably to be found in the body
return nil
}
return errors.New("binding element must be a struct") return errors.New("binding element must be a struct")
} }

View File

@ -234,7 +234,7 @@ const (
const ( const (
// Version of Echo // Version of Echo
Version = "4.2.1" Version = "4.2.2"
website = "https://echo.labstack.com" website = "https://echo.labstack.com"
// http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo // http://patorjk.com/software/taag/#p=display&f=Small%20Slant&t=Echo
banner = ` banner = `

View File

@ -2,7 +2,6 @@ package middleware
import ( import (
"net/http" "net/http"
"net/url"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
@ -49,30 +48,39 @@ func rewriteRulesRegex(rewrite map[string]string) map[*regexp.Regexp]string {
return rulesRegex return rulesRegex
} }
func rewritePath(rewriteRegex map[*regexp.Regexp]string, req *http.Request) { func rewriteURL(rewriteRegex map[*regexp.Regexp]string, req *http.Request) error {
for k, v := range rewriteRegex { if len(rewriteRegex) == 0 {
rawPath := req.URL.RawPath return nil
if rawPath != "" { }
// RawPath is only set when there has been escaping done. In that case Path must be deduced from rewritten RawPath
// because encoded Path could match rules that RawPath did not
if replacer := captureTokens(k, rawPath); replacer != nil {
rawPath = replacer.Replace(v)
req.URL.RawPath = rawPath // Depending how HTTP request is sent RequestURI could contain Scheme://Host/path or be just /path.
req.URL.Path, _ = url.PathUnescape(rawPath) // We only want to use path part for rewriting and therefore trim prefix if it exists
rawURI := req.RequestURI
return // rewrite only once if rawURI != "" && rawURI[0] != '/' {
} prefix := ""
if req.URL.Scheme != "" {
continue prefix = req.URL.Scheme + "://"
} }
if req.URL.Host != "" {
if replacer := captureTokens(k, req.URL.Path); replacer != nil { prefix += req.URL.Host // host or host:port
req.URL.Path = replacer.Replace(v) }
if prefix != "" {
return // rewrite only once rawURI = strings.TrimPrefix(rawURI, prefix)
} }
} }
for k, v := range rewriteRegex {
if replacer := captureTokens(k, rawURI); replacer != nil {
url, err := req.URL.Parse(replacer.Replace(v))
if err != nil {
return err
}
req.URL = url
return nil // rewrite only once
}
}
return nil
} }
// DefaultSkipper returns false which processes the middleware. // DefaultSkipper returns false which processes the middleware.

View File

@ -231,8 +231,9 @@ func ProxyWithConfig(config ProxyConfig) echo.MiddlewareFunc {
tgt := config.Balancer.Next(c) tgt := config.Balancer.Next(c)
c.Set(config.ContextKey, tgt) c.Set(config.ContextKey, tgt)
// Set rewrite path and raw path if err := rewriteURL(config.RegexRewrite, req); err != nil {
rewritePath(config.RegexRewrite, req) return err
}
// Fix header // Fix header
// Basically it's not good practice to unconditionally pass incoming x-real-ip header to upstream. // Basically it's not good practice to unconditionally pass incoming x-real-ip header to upstream.

View File

@ -2,6 +2,7 @@ package middleware
import ( import (
"net/http" "net/http"
"strings"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
) )
@ -40,11 +41,11 @@ func HTTPSRedirect() echo.MiddlewareFunc {
// HTTPSRedirectWithConfig returns an HTTPSRedirect middleware with config. // HTTPSRedirectWithConfig returns an HTTPSRedirect middleware with config.
// See `HTTPSRedirect()`. // See `HTTPSRedirect()`.
func HTTPSRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc { func HTTPSRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
return redirect(config, func(scheme, host, uri string) (ok bool, url string) { return redirect(config, func(scheme, host, uri string) (bool, string) {
if ok = scheme != "https"; ok { if scheme != "https" {
url = "https://" + host + uri return true, "https://" + host + uri
} }
return return false, ""
}) })
} }
@ -59,11 +60,11 @@ func HTTPSWWWRedirect() echo.MiddlewareFunc {
// HTTPSWWWRedirectWithConfig returns an HTTPSRedirect middleware with config. // HTTPSWWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
// See `HTTPSWWWRedirect()`. // See `HTTPSWWWRedirect()`.
func HTTPSWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc { func HTTPSWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
return redirect(config, func(scheme, host, uri string) (ok bool, url string) { return redirect(config, func(scheme, host, uri string) (bool, string) {
if ok = scheme != "https" && host[:4] != www; ok { if scheme != "https" && !strings.HasPrefix(host, www) {
url = "https://www." + host + uri return true, "https://www." + host + uri
} }
return return false, ""
}) })
} }
@ -79,13 +80,11 @@ func HTTPSNonWWWRedirect() echo.MiddlewareFunc {
// See `HTTPSNonWWWRedirect()`. // See `HTTPSNonWWWRedirect()`.
func HTTPSNonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc { func HTTPSNonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
return redirect(config, func(scheme, host, uri string) (ok bool, url string) { return redirect(config, func(scheme, host, uri string) (ok bool, url string) {
if ok = scheme != "https"; ok { if scheme != "https" {
if host[:4] == www { host = strings.TrimPrefix(host, www)
host = host[4:] return true, "https://" + host + uri
}
url = "https://" + host + uri
} }
return return false, ""
}) })
} }
@ -100,11 +99,11 @@ func WWWRedirect() echo.MiddlewareFunc {
// WWWRedirectWithConfig returns an HTTPSRedirect middleware with config. // WWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
// See `WWWRedirect()`. // See `WWWRedirect()`.
func WWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc { func WWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
return redirect(config, func(scheme, host, uri string) (ok bool, url string) { return redirect(config, func(scheme, host, uri string) (bool, string) {
if ok = host[:4] != www; ok { if !strings.HasPrefix(host, www) {
url = scheme + "://www." + host + uri return true, scheme + "://www." + host + uri
} }
return return false, ""
}) })
} }
@ -119,17 +118,17 @@ func NonWWWRedirect() echo.MiddlewareFunc {
// NonWWWRedirectWithConfig returns an HTTPSRedirect middleware with config. // NonWWWRedirectWithConfig returns an HTTPSRedirect middleware with config.
// See `NonWWWRedirect()`. // See `NonWWWRedirect()`.
func NonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc { func NonWWWRedirectWithConfig(config RedirectConfig) echo.MiddlewareFunc {
return redirect(config, func(scheme, host, uri string) (ok bool, url string) { return redirect(config, func(scheme, host, uri string) (bool, string) {
if ok = host[:4] == www; ok { if strings.HasPrefix(host, www) {
url = scheme + "://" + host[4:] + uri return true, scheme + "://" + host[4:] + uri
} }
return return false, ""
}) })
} }
func redirect(config RedirectConfig, cb redirectLogic) echo.MiddlewareFunc { func redirect(config RedirectConfig, cb redirectLogic) echo.MiddlewareFunc {
if config.Skipper == nil { if config.Skipper == nil {
config.Skipper = DefaultTrailingSlashConfig.Skipper config.Skipper = DefaultRedirectConfig.Skipper
} }
if config.Code == 0 { if config.Code == 0 {
config.Code = DefaultRedirectConfig.Code config.Code = DefaultRedirectConfig.Code

View File

@ -72,9 +72,9 @@ func RewriteWithConfig(config RewriteConfig) echo.MiddlewareFunc {
return next(c) return next(c)
} }
req := c.Request() if err := rewriteURL(config.RegexRules, c.Request()); err != nil {
// Set rewrite path and raw path return err
rewritePath(config.RegexRules, req) }
return next(c) return next(c)
} }
} }

View File

@ -42,8 +42,8 @@ var (
} }
) )
// Timeout returns a middleware which recovers from panics anywhere in the chain // Timeout returns a middleware which returns error (503 Service Unavailable error) to client immediately when handler
// and handles the control to the centralized HTTPErrorHandler. // call runs for longer than its time limit. NB: timeout does not stop handler execution.
func Timeout() echo.MiddlewareFunc { func Timeout() echo.MiddlewareFunc {
return TimeoutWithConfig(DefaultTimeoutConfig) return TimeoutWithConfig(DefaultTimeoutConfig)
} }
@ -106,6 +106,11 @@ func (t echoHandlerFuncWrapper) ServeHTTP(rw http.ResponseWriter, r *http.Reques
// so on timeout writer stays what http.TimeoutHandler uses and prevents writing headers/body // so on timeout writer stays what http.TimeoutHandler uses and prevents writing headers/body
t.ctx.Response().Writer = originalWriter t.ctx.Response().Writer = originalWriter
if err != nil { if err != nil {
// call global error handler to write error to the client. This is needed or `http.TimeoutHandler` will send status code by itself
// and after that our tries to write status code will not work anymore
t.ctx.Error(err)
// we pass error from handler to middlewares up in handler chain to act on it if needed. But this means that
// global error handler is probably be called twice as `t.ctx.Error` already does that.
t.errChan <- err t.errChan <- err
} }
} }

View File

@ -1,5 +1,6 @@
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) Slack API in Go [![Go Reference](https://pkg.go.dev/badge/github.com/slack-go/slack.svg)](https://pkg.go.dev/github.com/slack-go/slack)
=============== ===============
This is the original Slack library for Go created by Norberto Lopes, transferred to a Github organization. This is the original Slack library for Go created by Norberto Lopes, 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) [![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)
@ -14,7 +15,7 @@ a fully managed way.
There is currently no major version released. There is currently no major version released.
Therefore, minor version releases may include backward incompatible changes. Therefore, minor version releases may include backward incompatible changes.
See [CHANGELOG.md](https://github.com/slack-go/slack/blob/master/CHANGELOG.md) for more information about the changes. See [CHANGELOG.md](https://github.com/slack-go/slack/blob/master/CHANGELOG.md) or [Releases](https://github.com/slack-go/slack/releases) for more information about the changes.
## Installing ## Installing

View File

@ -45,14 +45,13 @@ func (api *Client) ListEventAuthorizationsContext(ctx context.Context, eventCont
func (api *Client) UninstallApp(clientID, clientSecret string) error { func (api *Client) UninstallApp(clientID, clientSecret string) error {
values := url.Values{ values := url.Values{
"token": {api.token},
"client_id": {clientID}, "client_id": {clientID},
"client_secret": {clientSecret}, "client_secret": {clientSecret},
} }
response := SlackResponse{} response := SlackResponse{}
err := api.getMethod(context.Background(), "apps.uninstall", values, &response) err := api.getMethod(context.Background(), "apps.uninstall", api.token, values, &response)
if err != nil { if err != nil {
return err return err
} }

View File

@ -17,7 +17,7 @@ type AttachmentAction struct {
Name string `json:"name"` // Required. Name string `json:"name"` // Required.
Text string `json:"text"` // Required. Text string `json:"text"` // Required.
Style string `json:"style,omitempty"` // Optional. Allowed values: "default", "primary", "danger". Style string `json:"style,omitempty"` // Optional. Allowed values: "default", "primary", "danger".
Type actionType `json:"type"` // Required. Must be set to "button" or "select". Type ActionType `json:"type"` // Required. Must be set to "button" or "select".
Value string `json:"value,omitempty"` // Optional. Value string `json:"value,omitempty"` // Optional.
DataSource string `json:"data_source,omitempty"` // Optional. DataSource string `json:"data_source,omitempty"` // Optional.
MinQueryLength int `json:"min_query_length,omitempty"` // Optional. Default value is 1. MinQueryLength int `json:"min_query_length,omitempty"` // Optional. Default value is 1.
@ -29,7 +29,7 @@ type AttachmentAction struct {
} }
// actionType returns the type of the action // actionType returns the type of the action
func (a AttachmentAction) actionType() actionType { func (a AttachmentAction) actionType() ActionType {
return a.Type return a.Type
} }

View File

@ -35,7 +35,7 @@ type Blocks struct {
type BlockAction struct { type BlockAction struct {
ActionID string `json:"action_id"` ActionID string `json:"action_id"`
BlockID string `json:"block_id"` BlockID string `json:"block_id"`
Type actionType `json:"type"` Type ActionType `json:"type"`
Text TextBlockObject `json:"text"` Text TextBlockObject `json:"text"`
Value string `json:"value"` Value string `json:"value"`
ActionTs string `json:"action_ts"` ActionTs string `json:"action_ts"`
@ -58,7 +58,7 @@ type BlockAction struct {
} }
// actionType returns the type of the action // actionType returns the type of the action
func (b BlockAction) actionType() actionType { func (b BlockAction) actionType() ActionType {
return b.Type return b.Type
} }

View File

@ -181,6 +181,8 @@ func (b *BlockElements) UnmarshalJSON(data []byte) error {
blockElement = &OverflowBlockElement{} blockElement = &OverflowBlockElement{}
case "datepicker": case "datepicker":
blockElement = &DatePickerBlockElement{} blockElement = &DatePickerBlockElement{}
case "timepicker":
blockElement = &TimePickerBlockElement{}
case "plain_text_input": case "plain_text_input":
blockElement = &PlainTextInputBlockElement{} blockElement = &PlainTextInputBlockElement{}
case "checkboxes": case "checkboxes":

View File

@ -3,8 +3,6 @@ package slack
import ( import (
"context" "context"
"net/url" "net/url"
"strconv"
"time"
) )
type channelResponseFull struct { type channelResponseFull struct {
@ -19,12 +17,6 @@ type channelResponseFull struct {
} }
// Channel contains information about the channel // Channel contains information about the channel
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
type Channel struct { type Channel struct {
GroupConversation GroupConversation
IsChannel bool `json:"is_channel"` IsChannel bool `json:"is_channel"`
@ -42,673 +34,3 @@ func (api *Client) channelRequest(ctx context.Context, path string, values url.V
return response, response.Err() return response, response.Err()
} }
// GetChannelsOption option provided when getting channels.
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
type GetChannelsOption func(*ChannelPagination) error
// GetChannelsOptionExcludeMembers excludes the members collection from each channel.
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func GetChannelsOptionExcludeMembers() GetChannelsOption {
return func(p *ChannelPagination) error {
p.excludeMembers = true
return nil
}
}
// GetChannelsOptionExcludeArchived excludes archived channels from results.
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func GetChannelsOptionExcludeArchived() GetChannelsOption {
return func(p *ChannelPagination) error {
p.excludeArchived = true
return nil
}
}
// ArchiveChannel archives the given channel
// see https://api.slack.com/methods/channels.archive
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) ArchiveChannel(channelID string) error {
return api.ArchiveChannelContext(context.Background(), channelID)
}
// ArchiveChannelContext archives the given channel with a custom context
// see https://api.slack.com/methods/channels.archive
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) ArchiveChannelContext(ctx context.Context, channelID string) (err error) {
values := url.Values{
"token": {api.token},
"channel": {channelID},
}
_, err = api.channelRequest(ctx, "channels.archive", values)
return err
}
// UnarchiveChannel unarchives the given channel
// see https://api.slack.com/methods/channels.unarchive
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) UnarchiveChannel(channelID string) error {
return api.UnarchiveChannelContext(context.Background(), channelID)
}
// UnarchiveChannelContext unarchives the given channel with a custom context
// see https://api.slack.com/methods/channels.unarchive
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) UnarchiveChannelContext(ctx context.Context, channelID string) (err error) {
values := url.Values{
"token": {api.token},
"channel": {channelID},
}
_, err = api.channelRequest(ctx, "channels.unarchive", values)
return err
}
// CreateChannel creates a channel with the given name and returns a *Channel
// see https://api.slack.com/methods/channels.create
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CreateChannel(channelName string) (*Channel, error) {
return api.CreateChannelContext(context.Background(), channelName)
}
// CreateChannelContext creates a channel with the given name and returns a *Channel with a custom context
// see https://api.slack.com/methods/channels.create
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CreateChannelContext(ctx context.Context, channelName string) (*Channel, error) {
values := url.Values{
"token": {api.token},
"name": {channelName},
}
response, err := api.channelRequest(ctx, "channels.create", values)
if err != nil {
return nil, err
}
return &response.Channel, nil
}
// GetChannelHistory retrieves the channel history
// see https://api.slack.com/methods/channels.history
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelHistory(channelID string, params HistoryParameters) (*History, error) {
return api.GetChannelHistoryContext(context.Background(), channelID, params)
}
// GetChannelHistoryContext retrieves the channel history with a custom context
// see https://api.slack.com/methods/channels.history
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelHistoryContext(ctx context.Context, channelID string, params HistoryParameters) (*History, error) {
values := url.Values{
"token": {api.token},
"channel": {channelID},
}
if params.Latest != DEFAULT_HISTORY_LATEST {
values.Add("latest", params.Latest)
}
if params.Oldest != DEFAULT_HISTORY_OLDEST {
values.Add("oldest", params.Oldest)
}
if params.Count != DEFAULT_HISTORY_COUNT {
values.Add("count", strconv.Itoa(params.Count))
}
if params.Inclusive != DEFAULT_HISTORY_INCLUSIVE {
if params.Inclusive {
values.Add("inclusive", "1")
} else {
values.Add("inclusive", "0")
}
}
if params.Unreads != DEFAULT_HISTORY_UNREADS {
if params.Unreads {
values.Add("unreads", "1")
} else {
values.Add("unreads", "0")
}
}
response, err := api.channelRequest(ctx, "channels.history", values)
if err != nil {
return nil, err
}
return &response.History, nil
}
// GetChannelInfo retrieves the given channel
// see https://api.slack.com/methods/channels.info
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelInfo(channelID string) (*Channel, error) {
return api.GetChannelInfoContext(context.Background(), channelID)
}
// GetChannelInfoContext retrieves the given channel with a custom context
// see https://api.slack.com/methods/channels.info
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelInfoContext(ctx context.Context, channelID string) (*Channel, error) {
values := url.Values{
"token": {api.token},
"channel": {channelID},
"include_locale": {strconv.FormatBool(true)},
}
response, err := api.channelRequest(ctx, "channels.info", values)
if err != nil {
return nil, err
}
return &response.Channel, nil
}
// InviteUserToChannel invites a user to a given channel and returns a *Channel
// see https://api.slack.com/methods/channels.invite
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) InviteUserToChannel(channelID, user string) (*Channel, error) {
return api.InviteUserToChannelContext(context.Background(), channelID, user)
}
// InviteUserToChannelContext invites a user to a given channel and returns a *Channel with a custom context
// see https://api.slack.com/methods/channels.invite
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) InviteUserToChannelContext(ctx context.Context, channelID, user string) (*Channel, error) {
values := url.Values{
"token": {api.token},
"channel": {channelID},
"user": {user},
}
response, err := api.channelRequest(ctx, "channels.invite", values)
if err != nil {
return nil, err
}
return &response.Channel, nil
}
// JoinChannel joins the currently authenticated user to a channel
// see https://api.slack.com/methods/channels.join
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) JoinChannel(channelName string) (*Channel, error) {
return api.JoinChannelContext(context.Background(), channelName)
}
// JoinChannelContext joins the currently authenticated user to a channel with a custom context
// see https://api.slack.com/methods/channels.join
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) JoinChannelContext(ctx context.Context, channelName string) (*Channel, error) {
values := url.Values{
"token": {api.token},
"name": {channelName},
}
response, err := api.channelRequest(ctx, "channels.join", values)
if err != nil {
return nil, err
}
return &response.Channel, nil
}
// LeaveChannel makes the authenticated user leave the given channel
// see https://api.slack.com/methods/channels.leave
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) LeaveChannel(channelID string) (bool, error) {
return api.LeaveChannelContext(context.Background(), channelID)
}
// LeaveChannelContext makes the authenticated user leave the given channel with a custom context
// see https://api.slack.com/methods/channels.leave
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) LeaveChannelContext(ctx context.Context, channelID string) (bool, error) {
values := url.Values{
"token": {api.token},
"channel": {channelID},
}
response, err := api.channelRequest(ctx, "channels.leave", values)
if err != nil {
return false, err
}
return response.NotInChannel, nil
}
// KickUserFromChannel kicks a user from a given channel
// see https://api.slack.com/methods/channels.kick
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) KickUserFromChannel(channelID, user string) error {
return api.KickUserFromChannelContext(context.Background(), channelID, user)
}
// KickUserFromChannelContext kicks a user from a given channel with a custom context
// see https://api.slack.com/methods/channels.kick
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) KickUserFromChannelContext(ctx context.Context, channelID, user string) (err error) {
values := url.Values{
"token": {api.token},
"channel": {channelID},
"user": {user},
}
_, err = api.channelRequest(ctx, "channels.kick", values)
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
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
type ChannelPagination struct {
Channels []Channel
limit int
excludeArchived bool
excludeMembers bool
previousResp *ResponseMetadata
c *Client
}
// Done checks if the pagination has completed
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (ChannelPagination) Done(err error) bool {
return err == errPaginationComplete
}
// Failure checks if pagination failed.
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (t ChannelPagination) Failure(err error) error {
if t.Done(err) {
return nil
}
return err
}
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
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.
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelsPaginated(options ...GetChannelsOption) ChannelPagination {
return newChannelPagination(api, options...)
}
// GetChannels retrieves all the channels
// see https://api.slack.com/methods/channels.list
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannels(excludeArchived bool, options ...GetChannelsOption) ([]Channel, error) {
return api.GetChannelsContext(context.Background(), excludeArchived, options...)
}
// GetChannelsContext retrieves all the channels with a custom context
// see https://api.slack.com/methods/channels.list
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelsContext(ctx context.Context, excludeArchived bool, options ...GetChannelsOption) (results []Channel, err error) {
if excludeArchived {
options = append(options, GetChannelsOptionExcludeArchived())
}
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
}
}
}
return results, p.Failure(err)
}
// SetChannelReadMark sets the read mark of a given channel to a specific point
// Clients should try to avoid making this call too often. When needing to mark a read position, a client should set a
// timer before making the call. In this way, any further updates needed during the timeout will not generate extra calls
// (just one per channel). This is useful for when reading scroll-back history, or following a busy live channel. A
// timeout of 5 seconds is a good starting point. Be sure to flush these calls on shutdown/logout.
// see https://api.slack.com/methods/channels.mark
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetChannelReadMark(channelID, ts string) error {
return api.SetChannelReadMarkContext(context.Background(), channelID, ts)
}
// SetChannelReadMarkContext sets the read mark of a given channel to a specific point with a custom context
// For more details see SetChannelReadMark documentation
// see https://api.slack.com/methods/channels.mark
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetChannelReadMarkContext(ctx context.Context, channelID, ts string) (err error) {
values := url.Values{
"token": {api.token},
"channel": {channelID},
"ts": {ts},
}
_, err = api.channelRequest(ctx, "channels.mark", values)
return err
}
// RenameChannel renames a given channel
// see https://api.slack.com/methods/channels.rename
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) RenameChannel(channelID, name string) (*Channel, error) {
return api.RenameChannelContext(context.Background(), channelID, name)
}
// RenameChannelContext renames a given channel with a custom context
// see https://api.slack.com/methods/channels.rename
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) RenameChannelContext(ctx context.Context, channelID, name string) (*Channel, error) {
values := url.Values{
"token": {api.token},
"channel": {channelID},
"name": {name},
}
// XXX: the created entry in this call returns a string instead of a number
// so I may have to do some workaround to solve it.
response, err := api.channelRequest(ctx, "channels.rename", values)
if err != nil {
return nil, err
}
return &response.Channel, nil
}
// SetChannelPurpose sets the channel purpose and returns the purpose that was successfully set
// see https://api.slack.com/methods/channels.setPurpose
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetChannelPurpose(channelID, purpose string) (string, error) {
return api.SetChannelPurposeContext(context.Background(), channelID, purpose)
}
// SetChannelPurposeContext sets the channel purpose and returns the purpose that was successfully set with a custom context
// see https://api.slack.com/methods/channels.setPurpose
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetChannelPurposeContext(ctx context.Context, channelID, purpose string) (string, error) {
values := url.Values{
"token": {api.token},
"channel": {channelID},
"purpose": {purpose},
}
response, err := api.channelRequest(ctx, "channels.setPurpose", values)
if err != nil {
return "", err
}
return response.Purpose, nil
}
// SetChannelTopic sets the channel topic and returns the topic that was successfully set
// see https://api.slack.com/methods/channels.setTopic
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetChannelTopic(channelID, topic string) (string, error) {
return api.SetChannelTopicContext(context.Background(), channelID, topic)
}
// SetChannelTopicContext sets the channel topic and returns the topic that was successfully set with a custom context
// see https://api.slack.com/methods/channels.setTopic
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetChannelTopicContext(ctx context.Context, channelID, topic string) (string, error) {
values := url.Values{
"token": {api.token},
"channel": {channelID},
"topic": {topic},
}
response, err := api.channelRequest(ctx, "channels.setTopic", values)
if err != nil {
return "", err
}
return response.Topic, nil
}
// GetChannelReplies gets an entire thread (a message plus all the messages in reply to it).
// see https://api.slack.com/methods/channels.replies
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelReplies(channelID, thread_ts string) ([]Message, error) {
return api.GetChannelRepliesContext(context.Background(), channelID, thread_ts)
}
// GetChannelRepliesContext gets an entire thread (a message plus all the messages in reply to it) with a custom context
// see https://api.slack.com/methods/channels.replies
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetChannelRepliesContext(ctx context.Context, channelID, thread_ts string) ([]Message, error) {
values := url.Values{
"token": {api.token},
"channel": {channelID},
"thread_ts": {thread_ts},
}
response, err := api.channelRequest(ctx, "channels.replies", values)
if err != nil {
return nil, err
}
return response.History.Messages, nil
}

View File

@ -744,7 +744,6 @@ func (api *Client) GetPermalink(params *PermalinkParameters) (string, error) {
// GetPermalinkContext returns the permalink for a message using a custom context. // GetPermalinkContext returns the permalink for a message using a custom context.
func (api *Client) GetPermalinkContext(ctx context.Context, params *PermalinkParameters) (string, error) { func (api *Client) GetPermalinkContext(ctx context.Context, params *PermalinkParameters) (string, error) {
values := url.Values{ values := url.Values{
"token": {api.token},
"channel": {params.Channel}, "channel": {params.Channel},
"message_ts": {params.Ts}, "message_ts": {params.Ts},
} }
@ -754,7 +753,7 @@ func (api *Client) GetPermalinkContext(ctx context.Context, params *PermalinkPar
Permalink string `json:"permalink"` Permalink string `json:"permalink"`
SlackResponse SlackResponse
}{} }{}
err := api.getMethod(ctx, "chat.getPermalink", values, &response) err := api.getMethod(ctx, "chat.getPermalink", api.token, values, &response)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -455,7 +455,7 @@ func (api *Client) GetConversationRepliesContext(ctx context.Context, params *Ge
type GetConversationsParameters struct { type GetConversationsParameters struct {
Cursor string Cursor string
ExcludeArchived string ExcludeArchived bool
Limit int Limit int
Types []string Types []string
} }
@ -479,8 +479,8 @@ func (api *Client) GetConversationsContext(ctx context.Context, params *GetConve
if params.Types != nil { if params.Types != nil {
values.Add("types", strings.Join(params.Types, ",")) values.Add("types", strings.Join(params.Types, ","))
} }
if params.ExcludeArchived == "true" { if params.ExcludeArchived {
values.Add("exclude_archived", "true") values.Add("exclude_archived", strconv.FormatBool(params.ExcludeArchived))
} }
response := struct { response := struct {

View File

@ -295,9 +295,7 @@ func (api *Client) UploadFileContext(ctx context.Context, params FileUploadParam
return nil, err return nil, err
} }
response := &fileResponseFull{} response := &fileResponseFull{}
values := url.Values{ values := url.Values{}
"token": {api.token},
}
if params.Filetype != "" { if params.Filetype != "" {
values.Add("filetype", params.Filetype) values.Add("filetype", params.Filetype)
} }
@ -320,12 +318,12 @@ func (api *Client) UploadFileContext(ctx context.Context, params FileUploadParam
values.Add("content", params.Content) values.Add("content", params.Content)
err = api.postMethod(ctx, "files.upload", values, response) err = api.postMethod(ctx, "files.upload", values, response)
} else if params.File != "" { } else if params.File != "" {
err = postLocalWithMultipartResponse(ctx, api.httpclient, api.endpoint+"files.upload", params.File, "file", values, response, api) err = postLocalWithMultipartResponse(ctx, api.httpclient, api.endpoint+"files.upload", params.File, "file", api.token, values, response, api)
} else if params.Reader != nil { } else if params.Reader != nil {
if params.Filename == "" { if params.Filename == "" {
return nil, fmt.Errorf("files.upload: FileUploadParameters.Filename is mandatory when using FileUploadParameters.Reader") return nil, fmt.Errorf("files.upload: FileUploadParameters.Filename is mandatory when using FileUploadParameters.Reader")
} }
err = postWithMultipartResponse(ctx, api.httpclient, api.endpoint+"files.upload", params.Filename, "file", values, params.Reader, response, api) err = postWithMultipartResponse(ctx, api.httpclient, api.endpoint+"files.upload", params.Filename, "file", api.token, values, params.Reader, response, api)
} }
if err != nil { if err != nil {

View File

@ -9,4 +9,4 @@ require (
github.com/stretchr/testify v1.2.2 github.com/stretchr/testify v1.2.2
) )
go 1.13 go 1.16

View File

@ -1,574 +1,7 @@
package slack package slack
import (
"context"
"net/url"
"strconv"
)
// Group contains all the information for a group // Group contains all the information for a group
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
type Group struct { type Group struct {
GroupConversation GroupConversation
IsGroup bool `json:"is_group"` IsGroup bool `json:"is_group"`
} }
type groupResponseFull struct {
Group Group `json:"group"`
Groups []Group `json:"groups"`
Purpose string `json:"purpose"`
Topic string `json:"topic"`
NotInGroup bool `json:"not_in_group"`
NoOp bool `json:"no_op"`
AlreadyClosed bool `json:"already_closed"`
AlreadyOpen bool `json:"already_open"`
AlreadyInGroup bool `json:"already_in_group"`
Channel Channel `json:"channel"`
History
SlackResponse
}
func (api *Client) groupRequest(ctx context.Context, path string, values url.Values) (*groupResponseFull, error) {
response := &groupResponseFull{}
err := api.postMethod(ctx, path, values, response)
if err != nil {
return nil, err
}
return response, response.Err()
}
// ArchiveGroup archives a private group
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) ArchiveGroup(group string) error {
return api.ArchiveGroupContext(context.Background(), group)
}
// ArchiveGroupContext archives a private group
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) ArchiveGroupContext(ctx context.Context, group string) error {
values := url.Values{
"token": {api.token},
"channel": {group},
}
_, err := api.groupRequest(ctx, "groups.archive", values)
return err
}
// UnarchiveGroup unarchives a private group
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) UnarchiveGroup(group string) error {
return api.UnarchiveGroupContext(context.Background(), group)
}
// UnarchiveGroupContext unarchives a private group
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) UnarchiveGroupContext(ctx context.Context, group string) error {
values := url.Values{
"token": {api.token},
"channel": {group},
}
_, err := api.groupRequest(ctx, "groups.unarchive", values)
return err
}
// CreateGroup creates a private group
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CreateGroup(group string) (*Group, error) {
return api.CreateGroupContext(context.Background(), group)
}
// CreateGroupContext creates a private group
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CreateGroupContext(ctx context.Context, group string) (*Group, error) {
values := url.Values{
"token": {api.token},
"name": {group},
}
response, err := api.groupRequest(ctx, "groups.create", values)
if err != nil {
return nil, err
}
return &response.Group, nil
}
// CreateChildGroup creates a new private group archiving the old one
// This method takes an existing private group and performs the following steps:
// 1. Renames the existing group (from "example" to "example-archived").
// 2. Archives the existing group.
// 3. Creates a new group with the name of the existing group.
// 4. Adds all members of the existing group to the new group.
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CreateChildGroup(group string) (*Group, error) {
return api.CreateChildGroupContext(context.Background(), group)
}
// CreateChildGroupContext creates a new private group archiving the old one with a custom context
// For more information see CreateChildGroup
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CreateChildGroupContext(ctx context.Context, group string) (*Group, error) {
values := url.Values{
"token": {api.token},
"channel": {group},
}
response, err := api.groupRequest(ctx, "groups.createChild", values)
if err != nil {
return nil, err
}
return &response.Group, nil
}
// GetGroupHistory fetches all the history for a private group
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroupHistory(group string, params HistoryParameters) (*History, error) {
return api.GetGroupHistoryContext(context.Background(), group, params)
}
// GetGroupHistoryContext fetches all the history for a private group with a custom context
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroupHistoryContext(ctx context.Context, group string, params HistoryParameters) (*History, error) {
values := url.Values{
"token": {api.token},
"channel": {group},
}
if params.Latest != DEFAULT_HISTORY_LATEST {
values.Add("latest", params.Latest)
}
if params.Oldest != DEFAULT_HISTORY_OLDEST {
values.Add("oldest", params.Oldest)
}
if params.Count != DEFAULT_HISTORY_COUNT {
values.Add("count", strconv.Itoa(params.Count))
}
if params.Inclusive != DEFAULT_HISTORY_INCLUSIVE {
if params.Inclusive {
values.Add("inclusive", "1")
} else {
values.Add("inclusive", "0")
}
}
if params.Unreads != DEFAULT_HISTORY_UNREADS {
if params.Unreads {
values.Add("unreads", "1")
} else {
values.Add("unreads", "0")
}
}
response, err := api.groupRequest(ctx, "groups.history", values)
if err != nil {
return nil, err
}
return &response.History, nil
}
// InviteUserToGroup invites a specific user to a private group
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) InviteUserToGroup(group, user string) (*Group, bool, error) {
return api.InviteUserToGroupContext(context.Background(), group, user)
}
// InviteUserToGroupContext invites a specific user to a private group with a custom context
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) InviteUserToGroupContext(ctx context.Context, group, user string) (*Group, bool, error) {
values := url.Values{
"token": {api.token},
"channel": {group},
"user": {user},
}
response, err := api.groupRequest(ctx, "groups.invite", values)
if err != nil {
return nil, false, err
}
return &response.Group, response.AlreadyInGroup, nil
}
// LeaveGroup makes authenticated user leave the group
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) LeaveGroup(group string) error {
return api.LeaveGroupContext(context.Background(), group)
}
// LeaveGroupContext makes authenticated user leave the group with a custom context
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) LeaveGroupContext(ctx context.Context, group string) (err error) {
values := url.Values{
"token": {api.token},
"channel": {group},
}
_, err = api.groupRequest(ctx, "groups.leave", values)
return err
}
// KickUserFromGroup kicks a user from a group
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) KickUserFromGroup(group, user string) error {
return api.KickUserFromGroupContext(context.Background(), group, user)
}
// KickUserFromGroupContext kicks a user from a group with a custom context
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) KickUserFromGroupContext(ctx context.Context, group, user string) (err error) {
values := url.Values{
"token": {api.token},
"channel": {group},
"user": {user},
}
_, err = api.groupRequest(ctx, "groups.kick", values)
return err
}
// GetGroups retrieves all groups
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroups(excludeArchived bool) ([]Group, error) {
return api.GetGroupsContext(context.Background(), excludeArchived)
}
// GetGroupsContext retrieves all groups with a custom context
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroupsContext(ctx context.Context, excludeArchived bool) ([]Group, error) {
values := url.Values{
"token": {api.token},
}
if excludeArchived {
values.Add("exclude_archived", "1")
}
response, err := api.groupRequest(ctx, "groups.list", values)
if err != nil {
return nil, err
}
return response.Groups, nil
}
// GetGroupInfo retrieves the given group
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroupInfo(group string) (*Group, error) {
return api.GetGroupInfoContext(context.Background(), group)
}
// GetGroupInfoContext retrieves the given group with a custom context
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroupInfoContext(ctx context.Context, group string) (*Group, error) {
values := url.Values{
"token": {api.token},
"channel": {group},
"include_locale": {strconv.FormatBool(true)},
}
response, err := api.groupRequest(ctx, "groups.info", values)
if err != nil {
return nil, err
}
return &response.Group, nil
}
// SetGroupReadMark sets the read mark on a private group
// Clients should try to avoid making this call too often. When needing to mark a read position, a client should set a
// timer before making the call. In this way, any further updates needed during the timeout will not generate extra
// calls (just one per channel). This is useful for when reading scroll-back history, or following a busy live
// channel. A timeout of 5 seconds is a good starting point. Be sure to flush these calls on shutdown/logout.
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetGroupReadMark(group, ts string) error {
return api.SetGroupReadMarkContext(context.Background(), group, ts)
}
// SetGroupReadMarkContext sets the read mark on a private group with a custom context
// For more details see SetGroupReadMark
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetGroupReadMarkContext(ctx context.Context, group, ts string) (err error) {
values := url.Values{
"token": {api.token},
"channel": {group},
"ts": {ts},
}
_, err = api.groupRequest(ctx, "groups.mark", values)
return err
}
// OpenGroup opens a private group
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) OpenGroup(group string) (bool, bool, error) {
return api.OpenGroupContext(context.Background(), group)
}
// OpenGroupContext opens a private group with a custom context
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) OpenGroupContext(ctx context.Context, group string) (bool, bool, error) {
values := url.Values{
"token": {api.token},
"channel": {group},
}
response, err := api.groupRequest(ctx, "groups.open", values)
if err != nil {
return false, false, err
}
return response.NoOp, response.AlreadyOpen, nil
}
// RenameGroup renames a group
// XXX: They return a channel, not a group. What is this crap? :(
// Inconsistent api it seems.
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) RenameGroup(group, name string) (*Channel, error) {
return api.RenameGroupContext(context.Background(), group, name)
}
// RenameGroupContext renames a group with a custom context
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) RenameGroupContext(ctx context.Context, group, name string) (*Channel, error) {
values := url.Values{
"token": {api.token},
"channel": {group},
"name": {name},
}
// XXX: the created entry in this call returns a string instead of a number
// so I may have to do some workaround to solve it.
response, err := api.groupRequest(ctx, "groups.rename", values)
if err != nil {
return nil, err
}
return &response.Channel, nil
}
// SetGroupPurpose sets the group purpose
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetGroupPurpose(group, purpose string) (string, error) {
return api.SetGroupPurposeContext(context.Background(), group, purpose)
}
// SetGroupPurposeContext sets the group purpose with a custom context
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetGroupPurposeContext(ctx context.Context, group, purpose string) (string, error) {
values := url.Values{
"token": {api.token},
"channel": {group},
"purpose": {purpose},
}
response, err := api.groupRequest(ctx, "groups.setPurpose", values)
if err != nil {
return "", err
}
return response.Purpose, nil
}
// SetGroupTopic sets the group topic
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetGroupTopic(group, topic string) (string, error) {
return api.SetGroupTopicContext(context.Background(), group, topic)
}
// SetGroupTopicContext sets the group topic with a custom context
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) SetGroupTopicContext(ctx context.Context, group, topic string) (string, error) {
values := url.Values{
"token": {api.token},
"channel": {group},
"topic": {topic},
}
response, err := api.groupRequest(ctx, "groups.setTopic", values)
if err != nil {
return "", err
}
return response.Topic, nil
}
// GetGroupReplies gets an entire thread (a message plus all the messages in reply to it).
// see https://api.slack.com/methods/groups.replies
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroupReplies(channelID, thread_ts string) ([]Message, error) {
return api.GetGroupRepliesContext(context.Background(), channelID, thread_ts)
}
// GetGroupRepliesContext gets an entire thread (a message plus all the messages in reply to it) with a custom context
// see https://api.slack.com/methods/groups.replies
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetGroupRepliesContext(ctx context.Context, channelID, thread_ts string) ([]Message, error) {
values := url.Values{
"token": {api.token},
"channel": {channelID},
"thread_ts": {thread_ts},
}
response, err := api.groupRequest(ctx, "groups.replies", values)
if err != nil {
return nil, err
}
return response.History.Messages, nil
}

View File

@ -1,11 +1,5 @@
package slack package slack
import (
"context"
"net/url"
"strconv"
)
type imChannel struct { type imChannel struct {
ID string `json:"id"` ID string `json:"id"`
} }
@ -21,200 +15,7 @@ type imResponseFull struct {
} }
// IM contains information related to the Direct Message channel // IM contains information related to the Direct Message channel
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
type IM struct { type IM struct {
Conversation Conversation
IsUserDeleted bool `json:"is_user_deleted"` IsUserDeleted bool `json:"is_user_deleted"`
} }
func (api *Client) imRequest(ctx context.Context, path string, values url.Values) (*imResponseFull, error) {
response := &imResponseFull{}
err := api.postMethod(ctx, path, values, response)
if err != nil {
return nil, err
}
return response, response.Err()
}
// CloseIMChannel closes the direct message channel
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CloseIMChannel(channel string) (bool, bool, error) {
return api.CloseIMChannelContext(context.Background(), channel)
}
// CloseIMChannelContext closes the direct message channel with a custom context
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) CloseIMChannelContext(ctx context.Context, channel string) (bool, bool, error) {
values := url.Values{
"token": {api.token},
"channel": {channel},
}
response, err := api.imRequest(ctx, "im.close", values)
if err != nil {
return false, false, err
}
return response.NoOp, response.AlreadyClosed, nil
}
// OpenIMChannel opens a direct message channel to the user provided as argument
// Returns some status and the channel ID
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) OpenIMChannel(user string) (bool, bool, string, error) {
return api.OpenIMChannelContext(context.Background(), user)
}
// OpenIMChannelContext opens a direct message channel to the user provided as argument with a custom context
// Returns some status and the channel ID
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) OpenIMChannelContext(ctx context.Context, user string) (bool, bool, string, error) {
values := url.Values{
"token": {api.token},
"user": {user},
}
response, err := api.imRequest(ctx, "im.open", values)
if err != nil {
return false, false, "", err
}
return response.NoOp, response.AlreadyOpen, response.Channel.ID, nil
}
// MarkIMChannel sets the read mark of a direct message channel to a specific point
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) MarkIMChannel(channel, ts string) (err error) {
return api.MarkIMChannelContext(context.Background(), channel, ts)
}
// MarkIMChannelContext sets the read mark of a direct message channel to a specific point with a custom context
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) MarkIMChannelContext(ctx context.Context, channel, ts string) error {
values := url.Values{
"token": {api.token},
"channel": {channel},
"ts": {ts},
}
_, err := api.imRequest(ctx, "im.mark", values)
return err
}
// GetIMHistory retrieves the direct message channel history
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetIMHistory(channel string, params HistoryParameters) (*History, error) {
return api.GetIMHistoryContext(context.Background(), channel, params)
}
// GetIMHistoryContext retrieves the direct message channel history with a custom context
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetIMHistoryContext(ctx context.Context, channel string, params HistoryParameters) (*History, error) {
values := url.Values{
"token": {api.token},
"channel": {channel},
}
if params.Latest != DEFAULT_HISTORY_LATEST {
values.Add("latest", params.Latest)
}
if params.Oldest != DEFAULT_HISTORY_OLDEST {
values.Add("oldest", params.Oldest)
}
if params.Count != DEFAULT_HISTORY_COUNT {
values.Add("count", strconv.Itoa(params.Count))
}
if params.Inclusive != DEFAULT_HISTORY_INCLUSIVE {
if params.Inclusive {
values.Add("inclusive", "1")
} else {
values.Add("inclusive", "0")
}
}
if params.Unreads != DEFAULT_HISTORY_UNREADS {
if params.Unreads {
values.Add("unreads", "1")
} else {
values.Add("unreads", "0")
}
}
response, err := api.imRequest(ctx, "im.history", values)
if err != nil {
return nil, err
}
return &response.History, nil
}
// GetIMChannels returns the list of direct message channels
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetIMChannels() ([]IM, error) {
return api.GetIMChannelsContext(context.Background())
}
// GetIMChannelsContext returns the list of direct message channels with a custom context
//
// Deprecated: channels.*, groups.* im.* and mpim.* methods will be deprecated in the next version.
// In Slack, these API are no longer available for newly Apps created after June 10th, 2020.
// Also, existing applications will not be able to use these APIs after February 24th, 2021.
//
// See also: https://api.slack.com/changelog/2020-01-deprecating-antecedents-to-the-conversations-api
func (api *Client) GetIMChannelsContext(ctx context.Context) ([]IM, error) {
values := url.Values{
"token": {api.token},
}
response, err := api.imRequest(ctx, "im.list", values)
if err != nil {
return nil, err
}
return response.IMs, nil
}

View File

@ -321,10 +321,9 @@ type UserPrefs struct {
} }
func (api *Client) GetUserPrefs() (*UserPrefsCarrier, error) { func (api *Client) GetUserPrefs() (*UserPrefsCarrier, error) {
values := url.Values{"token": {api.token}}
response := UserPrefsCarrier{} response := UserPrefsCarrier{}
err := api.getMethod(context.Background(), "users.prefs.get", values, &response) err := api.getMethod(context.Background(), "users.prefs.get", api.token, url.Values{}, &response)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -9,11 +9,11 @@ import (
type InteractionType string type InteractionType string
// ActionType type represents the type of action (attachment, block, etc.) // ActionType type represents the type of action (attachment, block, etc.)
type actionType string type ActionType string
// action is an interface that should be implemented by all callback action types // action is an interface that should be implemented by all callback action types
type action interface { type action interface {
actionType() actionType actionType() ActionType
} }
// Types of interactions that can be received. // Types of interactions that can be received.

View File

@ -135,7 +135,7 @@ func parseResponseBody(body io.ReadCloser, intf interface{}, d Debug) error {
return json.Unmarshal(response, intf) return json.Unmarshal(response, intf)
} }
func postLocalWithMultipartResponse(ctx context.Context, client httpClient, method, fpath, fieldname string, values url.Values, intf interface{}, d Debug) error { func postLocalWithMultipartResponse(ctx context.Context, client httpClient, method, fpath, fieldname, token string, values url.Values, intf interface{}, d Debug) error {
fullpath, err := filepath.Abs(fpath) fullpath, err := filepath.Abs(fpath)
if err != nil { if err != nil {
return err return err
@ -146,10 +146,10 @@ func postLocalWithMultipartResponse(ctx context.Context, client httpClient, meth
} }
defer file.Close() defer file.Close()
return postWithMultipartResponse(ctx, client, method, filepath.Base(fpath), fieldname, values, file, intf, d) return postWithMultipartResponse(ctx, client, method, filepath.Base(fpath), fieldname, token, values, file, intf, d)
} }
func postWithMultipartResponse(ctx context.Context, client httpClient, path, name, fieldname string, values url.Values, r io.Reader, intf interface{}, d Debug) error { func postWithMultipartResponse(ctx context.Context, client httpClient, path, name, fieldname, token string, values url.Values, r io.Reader, intf interface{}, d Debug) error {
pipeReader, pipeWriter := io.Pipe() pipeReader, pipeWriter := io.Pipe()
wr := multipart.NewWriter(pipeWriter) wr := multipart.NewWriter(pipeWriter)
errc := make(chan error) errc := make(chan error)
@ -175,6 +175,7 @@ func postWithMultipartResponse(ctx context.Context, client httpClient, path, nam
return err return err
} }
req.Header.Add("Content-Type", wr.FormDataContentType()) req.Header.Add("Content-Type", wr.FormDataContentType())
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
req = req.WithContext(ctx) req = req.WithContext(ctx)
resp, err := client.Do(req) resp, err := client.Do(req)
@ -236,12 +237,14 @@ func postForm(ctx context.Context, client httpClient, endpoint string, values ur
return doPost(ctx, client, req, newJSONParser(intf), d) return doPost(ctx, client, req, newJSONParser(intf), d)
} }
func getResource(ctx context.Context, client httpClient, endpoint string, values url.Values, intf interface{}, d Debug) error { func getResource(ctx context.Context, client httpClient, endpoint, token string, values url.Values, intf interface{}, d Debug) error {
req, err := http.NewRequest("GET", endpoint, nil) req, err := http.NewRequest("GET", endpoint, nil)
if err != nil { if err != nil {
return err return err
} }
req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
req.URL.RawQuery = values.Encode() req.URL.RawQuery = values.Encode()
return doPost(ctx, client, req, newJSONParser(intf), d) return doPost(ctx, client, req, newJSONParser(intf), d)

View File

@ -157,6 +157,6 @@ func (api *Client) postMethod(ctx context.Context, path string, values url.Value
} }
// get a slack web method. // get a slack web method.
func (api *Client) getMethod(ctx context.Context, path string, values url.Values, intf interface{}) error { func (api *Client) getMethod(ctx context.Context, path string, token string, values url.Values, intf interface{}) error {
return getResource(ctx, api.httpclient, api.endpoint+path, values, intf, api) return getResource(ctx, api.httpclient, api.endpoint+path, token, values, intf, api)
} }

View File

@ -482,7 +482,7 @@ func (api *Client) SetUserPhotoContext(ctx context.Context, image string, params
values.Add("crop_w", strconv.Itoa(params.CropW)) values.Add("crop_w", strconv.Itoa(params.CropW))
} }
err = postLocalWithMultipartResponse(ctx, api.httpclient, api.endpoint+"users.setPhoto", image, "image", values, response, api) err = postLocalWithMultipartResponse(ctx, api.httpclient, api.endpoint+"users.setPhoto", image, "image", api.token, values, response, api)
if err != nil { if err != nil {
return err return err
} }
@ -632,9 +632,15 @@ func (api *Client) UnsetUserCustomStatusContext(ctx context.Context) error {
return api.SetUserCustomStatusContext(ctx, "", "", 0) return api.SetUserCustomStatusContext(ctx, "", "", 0)
} }
// GetUserProfileParameters are the parameters required to get user profile
type GetUserProfileParameters struct {
UserID string
IncludeLabels bool
}
// GetUserProfile retrieves a user's profile information. // GetUserProfile retrieves a user's profile information.
func (api *Client) GetUserProfile(userID string, includeLabels bool) (*UserProfile, error) { func (api *Client) GetUserProfile(params *GetUserProfileParameters) (*UserProfile, error) {
return api.GetUserProfileContext(context.Background(), userID, includeLabels) return api.GetUserProfileContext(context.Background(), params)
} }
type getUserProfileResponse struct { type getUserProfileResponse struct {
@ -643,13 +649,14 @@ type getUserProfileResponse struct {
} }
// GetUserProfileContext retrieves a user's profile information with a context. // GetUserProfileContext retrieves a user's profile information with a context.
func (api *Client) GetUserProfileContext(ctx context.Context, userID string, includeLabels bool) (*UserProfile, error) { func (api *Client) GetUserProfileContext(ctx context.Context, params *GetUserProfileParameters) (*UserProfile, error) {
values := url.Values{"token": {api.token}} values := url.Values{"token": {api.token}}
if includeLabels {
values.Add("include_labels", "true") if params.UserID != "" {
values.Add("user", params.UserID)
} }
if userID != "" { if params.IncludeLabels {
values.Add("user", userID) values.Add("include_labels", "true")
} }
resp := &getUserProfileResponse{} resp := &getUserProfileResponse{}

View File

@ -57,7 +57,7 @@ loop:
err = transform.ErrShortSrc err = transform.ErrShortSrc
break loop break loop
} }
r = utf8.RuneError r, size = utf8.RuneError, 1
goto write goto write
} }
size = 2 size = 2

View File

@ -133,14 +133,15 @@ func (s *scanner) resizeRange(oldStart, oldEnd, newSize int) {
s.start = oldStart s.start = oldStart
if end := oldStart + newSize; end != oldEnd { if end := oldStart + newSize; end != oldEnd {
diff := end - oldEnd diff := end - oldEnd
if end < cap(s.b) { var b []byte
b := make([]byte, len(s.b)+diff) if n := len(s.b) + diff; n > cap(s.b) {
b = make([]byte, n)
copy(b, s.b[:oldStart]) copy(b, s.b[:oldStart])
copy(b[end:], s.b[oldEnd:])
s.b = b
} else { } else {
s.b = append(s.b[end:], s.b[oldEnd:]...) b = s.b[:n:n]
} }
copy(b[end:], s.b[oldEnd:])
s.b = b
s.next = end + (s.next - s.end) s.next = end + (s.next - s.end)
s.end = end s.end = end
} }

View File

@ -12,15 +12,14 @@
// and without notice. // and without notice.
package bidi // import "golang.org/x/text/unicode/bidi" package bidi // import "golang.org/x/text/unicode/bidi"
// TODO: // TODO
// The following functionality would not be hard to implement, but hinges on
// the definition of a Segmenter interface. For now this is up to the user.
// - Iterate over paragraphs
// - Segmenter to iterate over runs directly from a given text.
// Also:
// - Transformer for reordering? // - Transformer for reordering?
// - Transformer (validator, really) for Bidi Rule. // - Transformer (validator, really) for Bidi Rule.
import (
"bytes"
)
// This API tries to avoid dealing with embedding levels for now. Under the hood // This API tries to avoid dealing with embedding levels for now. Under the hood
// these will be computed, but the question is to which extent the user should // these will be computed, but the question is to which extent the user should
// know they exist. We should at some point allow the user to specify an // know they exist. We should at some point allow the user to specify an
@ -49,7 +48,9 @@ const (
Neutral Neutral
) )
type options struct{} type options struct {
defaultDirection Direction
}
// An Option is an option for Bidi processing. // An Option is an option for Bidi processing.
type Option func(*options) type Option func(*options)
@ -66,12 +67,62 @@ type Option func(*options)
// DefaultDirection sets the default direction for a Paragraph. The direction is // DefaultDirection sets the default direction for a Paragraph. The direction is
// overridden if the text contains directional characters. // overridden if the text contains directional characters.
func DefaultDirection(d Direction) Option { func DefaultDirection(d Direction) Option {
panic("unimplemented") return func(opts *options) {
opts.defaultDirection = d
}
} }
// A Paragraph holds a single Paragraph for Bidi processing. // A Paragraph holds a single Paragraph for Bidi processing.
type Paragraph struct { type Paragraph struct {
// buffers p []byte
o Ordering
opts []Option
types []Class
pairTypes []bracketType
pairValues []rune
runes []rune
options options
}
// Initialize the p.pairTypes, p.pairValues and p.types from the input previously
// set by p.SetBytes() or p.SetString(). Also limit the input up to (and including) a paragraph
// separator (bidi class B).
//
// The function p.Order() needs these values to be set, so this preparation could be postponed.
// But since the SetBytes and SetStrings functions return the length of the input up to the paragraph
// separator, the whole input needs to be processed anyway and should not be done twice.
//
// The function has the same return values as SetBytes() / SetString()
func (p *Paragraph) prepareInput() (n int, err error) {
p.runes = bytes.Runes(p.p)
bytecount := 0
// clear slices from previous SetString or SetBytes
p.pairTypes = nil
p.pairValues = nil
p.types = nil
for _, r := range p.runes {
props, i := LookupRune(r)
bytecount += i
cls := props.Class()
if cls == B {
return bytecount, nil
}
p.types = append(p.types, cls)
if props.IsOpeningBracket() {
p.pairTypes = append(p.pairTypes, bpOpen)
p.pairValues = append(p.pairValues, r)
} else if props.IsBracket() {
// this must be a closing bracket,
// since IsOpeningBracket is not true
p.pairTypes = append(p.pairTypes, bpClose)
p.pairValues = append(p.pairValues, r)
} else {
p.pairTypes = append(p.pairTypes, bpNone)
p.pairValues = append(p.pairValues, 0)
}
}
return bytecount, nil
} }
// SetBytes configures p for the given paragraph text. It replaces text // SetBytes configures p for the given paragraph text. It replaces text
@ -80,70 +131,150 @@ type Paragraph struct {
// consumed from b including this separator. Error may be non-nil if options are // consumed from b including this separator. Error may be non-nil if options are
// given. // given.
func (p *Paragraph) SetBytes(b []byte, opts ...Option) (n int, err error) { func (p *Paragraph) SetBytes(b []byte, opts ...Option) (n int, err error) {
panic("unimplemented") p.p = b
p.opts = opts
return p.prepareInput()
} }
// SetString configures p for the given paragraph text. It replaces text // SetString configures s for the given paragraph text. It replaces text
// previously set by SetBytes or SetString. If b contains a paragraph separator // previously set by SetBytes or SetString. If s contains a paragraph separator
// it will only process the first paragraph and report the number of bytes // it will only process the first paragraph and report the number of bytes
// consumed from b including this separator. Error may be non-nil if options are // consumed from s including this separator. Error may be non-nil if options are
// given. // given.
func (p *Paragraph) SetString(s string, opts ...Option) (n int, err error) { func (p *Paragraph) SetString(s string, opts ...Option) (n int, err error) {
panic("unimplemented") p.p = []byte(s)
p.opts = opts
return p.prepareInput()
} }
// IsLeftToRight reports whether the principle direction of rendering for this // IsLeftToRight reports whether the principle direction of rendering for this
// paragraphs is left-to-right. If this returns false, the principle direction // paragraphs is left-to-right. If this returns false, the principle direction
// of rendering is right-to-left. // of rendering is right-to-left.
func (p *Paragraph) IsLeftToRight() bool { func (p *Paragraph) IsLeftToRight() bool {
panic("unimplemented") return p.Direction() == LeftToRight
} }
// Direction returns the direction of the text of this paragraph. // Direction returns the direction of the text of this paragraph.
// //
// The direction may be LeftToRight, RightToLeft, Mixed, or Neutral. // The direction may be LeftToRight, RightToLeft, Mixed, or Neutral.
func (p *Paragraph) Direction() Direction { func (p *Paragraph) Direction() Direction {
panic("unimplemented") return p.o.Direction()
} }
// TODO: what happens if the position is > len(input)? This should return an error.
// RunAt reports the Run at the given position of the input text. // RunAt reports the Run at the given position of the input text.
// //
// This method can be used for computing line breaks on paragraphs. // This method can be used for computing line breaks on paragraphs.
func (p *Paragraph) RunAt(pos int) Run { func (p *Paragraph) RunAt(pos int) Run {
panic("unimplemented") c := 0
runNumber := 0
for i, r := range p.o.runes {
c += len(r)
if pos < c {
runNumber = i
}
}
return p.o.Run(runNumber)
}
func calculateOrdering(levels []level, runes []rune) Ordering {
var curDir Direction
prevDir := Neutral
prevI := 0
o := Ordering{}
// lvl = 0,2,4,...: left to right
// lvl = 1,3,5,...: right to left
for i, lvl := range levels {
if lvl%2 == 0 {
curDir = LeftToRight
} else {
curDir = RightToLeft
}
if curDir != prevDir {
if i > 0 {
o.runes = append(o.runes, runes[prevI:i])
o.directions = append(o.directions, prevDir)
o.startpos = append(o.startpos, prevI)
}
prevI = i
prevDir = curDir
}
}
o.runes = append(o.runes, runes[prevI:])
o.directions = append(o.directions, prevDir)
o.startpos = append(o.startpos, prevI)
return o
} }
// Order computes the visual ordering of all the runs in a Paragraph. // Order computes the visual ordering of all the runs in a Paragraph.
func (p *Paragraph) Order() (Ordering, error) { func (p *Paragraph) Order() (Ordering, error) {
panic("unimplemented") if len(p.types) == 0 {
return Ordering{}, nil
}
for _, fn := range p.opts {
fn(&p.options)
}
lvl := level(-1)
if p.options.defaultDirection == RightToLeft {
lvl = 1
}
para, err := newParagraph(p.types, p.pairTypes, p.pairValues, lvl)
if err != nil {
return Ordering{}, err
}
levels := para.getLevels([]int{len(p.types)})
p.o = calculateOrdering(levels, p.runes)
return p.o, nil
} }
// Line computes the visual ordering of runs for a single line starting and // Line computes the visual ordering of runs for a single line starting and
// ending at the given positions in the original text. // ending at the given positions in the original text.
func (p *Paragraph) Line(start, end int) (Ordering, error) { func (p *Paragraph) Line(start, end int) (Ordering, error) {
panic("unimplemented") lineTypes := p.types[start:end]
para, err := newParagraph(lineTypes, p.pairTypes[start:end], p.pairValues[start:end], -1)
if err != nil {
return Ordering{}, err
}
levels := para.getLevels([]int{len(lineTypes)})
o := calculateOrdering(levels, p.runes[start:end])
return o, nil
} }
// An Ordering holds the computed visual order of runs of a Paragraph. Calling // An Ordering holds the computed visual order of runs of a Paragraph. Calling
// SetBytes or SetString on the originating Paragraph invalidates an Ordering. // SetBytes or SetString on the originating Paragraph invalidates an Ordering.
// The methods of an Ordering should only be called by one goroutine at a time. // The methods of an Ordering should only be called by one goroutine at a time.
type Ordering struct{} type Ordering struct {
runes [][]rune
directions []Direction
startpos []int
}
// Direction reports the directionality of the runs. // Direction reports the directionality of the runs.
// //
// The direction may be LeftToRight, RightToLeft, Mixed, or Neutral. // The direction may be LeftToRight, RightToLeft, Mixed, or Neutral.
func (o *Ordering) Direction() Direction { func (o *Ordering) Direction() Direction {
panic("unimplemented") return o.directions[0]
} }
// NumRuns returns the number of runs. // NumRuns returns the number of runs.
func (o *Ordering) NumRuns() int { func (o *Ordering) NumRuns() int {
panic("unimplemented") return len(o.runes)
} }
// Run returns the ith run within the ordering. // Run returns the ith run within the ordering.
func (o *Ordering) Run(i int) Run { func (o *Ordering) Run(i int) Run {
panic("unimplemented") r := Run{
runes: o.runes[i],
direction: o.directions[i],
startpos: o.startpos[i],
}
return r
} }
// TODO: perhaps with options. // TODO: perhaps with options.
@ -155,16 +286,19 @@ func (o *Ordering) Run(i int) Run {
// A Run is a continuous sequence of characters of a single direction. // A Run is a continuous sequence of characters of a single direction.
type Run struct { type Run struct {
runes []rune
direction Direction
startpos int
} }
// String returns the text of the run in its original order. // String returns the text of the run in its original order.
func (r *Run) String() string { func (r *Run) String() string {
panic("unimplemented") return string(r.runes)
} }
// Bytes returns the text of the run in its original order. // Bytes returns the text of the run in its original order.
func (r *Run) Bytes() []byte { func (r *Run) Bytes() []byte {
panic("unimplemented") return []byte(r.String())
} }
// TODO: methods for // TODO: methods for
@ -174,25 +308,52 @@ func (r *Run) Bytes() []byte {
// Direction reports the direction of the run. // Direction reports the direction of the run.
func (r *Run) Direction() Direction { func (r *Run) Direction() Direction {
panic("unimplemented") return r.direction
} }
// Position of the Run within the text passed to SetBytes or SetString of the // Pos returns the position of the Run within the text passed to SetBytes or SetString of the
// originating Paragraph value. // originating Paragraph value.
func (r *Run) Pos() (start, end int) { func (r *Run) Pos() (start, end int) {
panic("unimplemented") return r.startpos, r.startpos + len(r.runes) - 1
} }
// AppendReverse reverses the order of characters of in, appends them to out, // AppendReverse reverses the order of characters of in, appends them to out,
// and returns the result. Modifiers will still follow the runes they modify. // and returns the result. Modifiers will still follow the runes they modify.
// Brackets are replaced with their counterparts. // Brackets are replaced with their counterparts.
func AppendReverse(out, in []byte) []byte { func AppendReverse(out, in []byte) []byte {
panic("unimplemented") ret := make([]byte, len(in)+len(out))
copy(ret, out)
inRunes := bytes.Runes(in)
for i, r := range inRunes {
prop, _ := LookupRune(r)
if prop.IsBracket() {
inRunes[i] = prop.reverseBracket(r)
}
}
for i, j := 0, len(inRunes)-1; i < j; i, j = i+1, j-1 {
inRunes[i], inRunes[j] = inRunes[j], inRunes[i]
}
copy(ret[len(out):], string(inRunes))
return ret
} }
// ReverseString reverses the order of characters in s and returns a new string. // ReverseString reverses the order of characters in s and returns a new string.
// Modifiers will still follow the runes they modify. Brackets are replaced with // Modifiers will still follow the runes they modify. Brackets are replaced with
// their counterparts. // their counterparts.
func ReverseString(s string) string { func ReverseString(s string) string {
panic("unimplemented") input := []rune(s)
li := len(input)
ret := make([]rune, li)
for i, r := range input {
prop, _ := LookupRune(r)
if prop.IsBracket() {
ret[li-i-1] = prop.reverseBracket(r)
} else {
ret[li-i-1] = r
}
}
return string(ret)
} }

View File

@ -4,7 +4,10 @@
package bidi package bidi
import "log" import (
"fmt"
"log"
)
// This implementation is a port based on the reference implementation found at: // This implementation is a port based on the reference implementation found at:
// https://www.unicode.org/Public/PROGRAMS/BidiReferenceJava/ // https://www.unicode.org/Public/PROGRAMS/BidiReferenceJava/
@ -97,13 +100,20 @@ type paragraph struct {
// rune (suggested is the rune of the open bracket for opening and matching // rune (suggested is the rune of the open bracket for opening and matching
// close brackets, after normalization). The embedding levels are optional, but // close brackets, after normalization). The embedding levels are optional, but
// may be supplied to encode embedding levels of styled text. // may be supplied to encode embedding levels of styled text.
// func newParagraph(types []Class, pairTypes []bracketType, pairValues []rune, levels level) (*paragraph, error) {
// TODO: return an error. var err error
func newParagraph(types []Class, pairTypes []bracketType, pairValues []rune, levels level) *paragraph { if err = validateTypes(types); err != nil {
validateTypes(types) return nil, err
validatePbTypes(pairTypes) }
validatePbValues(pairValues, pairTypes) if err = validatePbTypes(pairTypes); err != nil {
validateParagraphEmbeddingLevel(levels) return nil, err
}
if err = validatePbValues(pairValues, pairTypes); err != nil {
return nil, err
}
if err = validateParagraphEmbeddingLevel(levels); err != nil {
return nil, err
}
p := &paragraph{ p := &paragraph{
initialTypes: append([]Class(nil), types...), initialTypes: append([]Class(nil), types...),
@ -115,7 +125,7 @@ func newParagraph(types []Class, pairTypes []bracketType, pairValues []rune, lev
resultTypes: append([]Class(nil), types...), resultTypes: append([]Class(nil), types...),
} }
p.run() p.run()
return p return p, nil
} }
func (p *paragraph) Len() int { return len(p.initialTypes) } func (p *paragraph) Len() int { return len(p.initialTypes) }
@ -1001,58 +1011,61 @@ func typeForLevel(level level) Class {
return R return R
} }
// TODO: change validation to not panic func validateTypes(types []Class) error {
func validateTypes(types []Class) {
if len(types) == 0 { if len(types) == 0 {
log.Panic("types is null") return fmt.Errorf("types is null")
} }
for i, t := range types[:len(types)-1] { for i, t := range types[:len(types)-1] {
if t == B { if t == B {
log.Panicf("B type before end of paragraph at index: %d", i) return fmt.Errorf("B type before end of paragraph at index: %d", i)
} }
} }
return nil
} }
func validateParagraphEmbeddingLevel(embeddingLevel level) { func validateParagraphEmbeddingLevel(embeddingLevel level) error {
if embeddingLevel != implicitLevel && if embeddingLevel != implicitLevel &&
embeddingLevel != 0 && embeddingLevel != 0 &&
embeddingLevel != 1 { embeddingLevel != 1 {
log.Panicf("illegal paragraph embedding level: %d", embeddingLevel) return fmt.Errorf("illegal paragraph embedding level: %d", embeddingLevel)
} }
return nil
} }
func validateLineBreaks(linebreaks []int, textLength int) { func validateLineBreaks(linebreaks []int, textLength int) error {
prev := 0 prev := 0
for i, next := range linebreaks { for i, next := range linebreaks {
if next <= prev { if next <= prev {
log.Panicf("bad linebreak: %d at index: %d", next, i) return fmt.Errorf("bad linebreak: %d at index: %d", next, i)
} }
prev = next prev = next
} }
if prev != textLength { if prev != textLength {
log.Panicf("last linebreak was %d, want %d", prev, textLength) return fmt.Errorf("last linebreak was %d, want %d", prev, textLength)
} }
return nil
} }
func validatePbTypes(pairTypes []bracketType) { func validatePbTypes(pairTypes []bracketType) error {
if len(pairTypes) == 0 { if len(pairTypes) == 0 {
log.Panic("pairTypes is null") return fmt.Errorf("pairTypes is null")
} }
for i, pt := range pairTypes { for i, pt := range pairTypes {
switch pt { switch pt {
case bpNone, bpOpen, bpClose: case bpNone, bpOpen, bpClose:
default: default:
log.Panicf("illegal pairType value at %d: %v", i, pairTypes[i]) return fmt.Errorf("illegal pairType value at %d: %v", i, pairTypes[i])
} }
} }
return nil
} }
func validatePbValues(pairValues []rune, pairTypes []bracketType) { func validatePbValues(pairValues []rune, pairTypes []bracketType) error {
if pairValues == nil { if pairValues == nil {
log.Panic("pairValues is null") return fmt.Errorf("pairValues is null")
} }
if len(pairTypes) != len(pairValues) { if len(pairTypes) != len(pairValues) {
log.Panic("pairTypes is different length from pairValues") return fmt.Errorf("pairTypes is different length from pairValues")
} }
return nil
} }

14
vendor/modules.txt vendored
View File

@ -28,7 +28,7 @@ github.com/Rhymen/go-whatsapp/binary/token
github.com/Rhymen/go-whatsapp/crypto/cbc github.com/Rhymen/go-whatsapp/crypto/cbc
github.com/Rhymen/go-whatsapp/crypto/curve25519 github.com/Rhymen/go-whatsapp/crypto/curve25519
github.com/Rhymen/go-whatsapp/crypto/hkdf github.com/Rhymen/go-whatsapp/crypto/hkdf
# github.com/SevereCloud/vksdk/v2 v2.9.0 # github.com/SevereCloud/vksdk/v2 v2.9.1
## explicit ## explicit
github.com/SevereCloud/vksdk/v2 github.com/SevereCloud/vksdk/v2
github.com/SevereCloud/vksdk/v2/api github.com/SevereCloud/vksdk/v2/api
@ -67,13 +67,13 @@ github.com/go-telegram-bot-api/telegram-bot-api
# github.com/golang/protobuf v1.4.2 # github.com/golang/protobuf v1.4.2
github.com/golang/protobuf/proto github.com/golang/protobuf/proto
github.com/golang/protobuf/protoc-gen-go/descriptor github.com/golang/protobuf/protoc-gen-go/descriptor
# github.com/gomarkdown/markdown v0.0.0-20210208175418-bda154fe17d8 # github.com/gomarkdown/markdown v0.0.0-20210408062403-ad838ccf8cdd
## explicit ## explicit
github.com/gomarkdown/markdown github.com/gomarkdown/markdown
github.com/gomarkdown/markdown/ast github.com/gomarkdown/markdown/ast
github.com/gomarkdown/markdown/html github.com/gomarkdown/markdown/html
github.com/gomarkdown/markdown/parser github.com/gomarkdown/markdown/parser
# github.com/google/gops v0.3.17 # github.com/google/gops v0.3.18
## explicit ## explicit
github.com/google/gops/agent github.com/google/gops/agent
github.com/google/gops/internal github.com/google/gops/internal
@ -121,7 +121,7 @@ github.com/keybase/go-keybase-chat-bot/kbchat/types/stellar1
# github.com/kyokomi/emoji/v2 v2.2.8 # github.com/kyokomi/emoji/v2 v2.2.8
## explicit ## explicit
github.com/kyokomi/emoji/v2 github.com/kyokomi/emoji/v2
# github.com/labstack/echo/v4 v4.2.1 # github.com/labstack/echo/v4 v4.2.2
## explicit ## explicit
github.com/labstack/echo/v4 github.com/labstack/echo/v4
github.com/labstack/echo/v4/middleware github.com/labstack/echo/v4/middleware
@ -242,7 +242,7 @@ github.com/sirupsen/logrus
github.com/skip2/go-qrcode github.com/skip2/go-qrcode
github.com/skip2/go-qrcode/bitset github.com/skip2/go-qrcode/bitset
github.com/skip2/go-qrcode/reedsolomon github.com/skip2/go-qrcode/reedsolomon
# github.com/slack-go/slack v0.8.2 # github.com/slack-go/slack v0.9.0
## explicit ## explicit
github.com/slack-go/slack github.com/slack-go/slack
github.com/slack-go/slack/internal/backoff github.com/slack-go/slack/internal/backoff
@ -352,7 +352,7 @@ golang.org/x/net/http2/h2c
golang.org/x/net/http2/hpack golang.org/x/net/http2/hpack
golang.org/x/net/idna golang.org/x/net/idna
golang.org/x/net/websocket golang.org/x/net/websocket
# golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 # golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c
## explicit ## explicit
golang.org/x/oauth2 golang.org/x/oauth2
golang.org/x/oauth2/clientcredentials golang.org/x/oauth2/clientcredentials
@ -363,7 +363,7 @@ golang.org/x/sys/cpu
golang.org/x/sys/internal/unsafeheader golang.org/x/sys/internal/unsafeheader
golang.org/x/sys/unix golang.org/x/sys/unix
golang.org/x/sys/windows golang.org/x/sys/windows
# golang.org/x/text v0.3.4 # golang.org/x/text v0.3.5
golang.org/x/text/encoding golang.org/x/text/encoding
golang.org/x/text/encoding/charmap golang.org/x/text/encoding/charmap
golang.org/x/text/encoding/internal golang.org/x/text/encoding/internal