99 "github.com/42wim/matterbridge/bridge/config"
1010 "github.com/42wim/matterbridge/bridge/helper"
1111 "github.com/slack-go/slack"
12+ "github.com/slack-go/slack/slackevents"
13+ "github.com/slack-go/slack/socketmode"
1214)
1315
1416// ErrEventIgnored is for events that should be ignored
@@ -48,65 +50,74 @@ func (b *Bslack) handleSlack() {
4850}
4951
5052func (b * Bslack ) handleSlackClient (messages chan * config.Message ) {
51- for msg := range b .rtm .IncomingEvents {
52- if msg .Type != sUserTyping && msg .Type != sHello && msg .Type != sLatencyReport {
53- b .Log .Debugf ("== Receiving event %#v" , msg .Data )
54- }
55- switch ev := msg .Data .(type ) {
56- case * slack.UserTypingEvent :
57- if ! b .GetBool ("ShowUserTyping" ) {
58- continue
59- }
60- rmsg , err := b .handleTypingEvent (ev )
61- if err == ErrEventIgnored {
62- continue
63- } else if err != nil {
64- b .Log .Errorf ("%#v" , err )
65- continue
53+ for msg := range b .smc .Events {
54+ switch msg .Type {
55+ case socketmode .EventTypeConnected :
56+ if authTest , authErr := b .smc .AuthTest (); authErr == nil {
57+ if botInfo , infoErr := b .smc .GetBotInfo (authTest .BotID ); infoErr == nil {
58+ b .si = botInfo
59+
60+ b .channels .populateChannels (true )
61+ b .users .populateUsers (true )
62+ } else {
63+ b .Log .Fatalf ("Unable to identify bot user" )
64+ }
65+ } else {
66+ b .Log .Fatalf ("Unable to identify bot user" )
6667 }
68+ case socketmode .EventTypeConnectionError :
69+ ev , _ := msg .Data .(slack.ConnectionErrorEvent )
70+
71+ b .Log .Errorf ("Connection failed %#v %#v" , ev .Error (), ev .ErrorObj )
72+ case socketmode .EventTypeErrorWriteFailed :
73+ ev , _ := msg .Data .(socketmode.ErrorWriteFailed )
74+
75+ b .Log .Debugf ("%#v" , ev .Cause .Error ())
76+ case socketmode .EventTypeInvalidAuth :
77+ ev , _ := msg .Data .(slack.InvalidAuthEvent )
78+
79+ b .Log .Fatalf ("Invalid Token %#v" , ev )
80+ case socketmode .EventTypeHello , socketmode .EventTypeConnecting :
81+ continue
82+
83+ case socketmode .EventTypeEventsAPI :
84+ b .smc .Ack (* msg .Request )
85+
86+ eventsAPIEvent , ok := msg .Data .(slackevents.EventsAPIEvent )
87+
88+ if ! ok {
89+ b .Log .Debugf ("Ignored %+v" , eventsAPIEvent )
6790
68- messages <- rmsg
69- case * slack.MessageEvent :
70- if b .skipMessageEvent (ev ) {
71- b .Log .Debugf ("Skipped message: %#v" , ev )
72- continue
73- }
74- rmsg , err := b .handleMessageEvent (ev )
75- if err != nil {
76- b .Log .Errorf ("%#v" , err )
7791 continue
7892 }
79- messages <- rmsg
80- case * slack.FileDeletedEvent :
81- rmsg , err := b .handleFileDeletedEvent (ev )
82- if err != nil {
83- b .Log .Errorf ("%#v" , err )
84- continue
93+
94+ switch innerEventData := eventsAPIEvent .InnerEvent .Data .(type ) {
95+ case * slackevents.MessageEvent :
96+ if b .skipMessageEvent (innerEventData ) {
97+ b .Log .Debugf ("Skipped message: %#v" , innerEventData )
98+ continue
99+ }
100+ rmsg , err := b .handleMessageEvent (innerEventData )
101+ if err != nil {
102+ b .Log .Errorf ("%#v" , err )
103+ continue
104+ }
105+ messages <- rmsg
106+ case * slackevents.MemberJoinedChannelEvent :
107+ if innerEventData .User == b .si .UserID {
108+ channel , err := b .smc .GetConversationInfo (innerEventData .Channel , false )
109+
110+ if err != nil {
111+ b .Log .Errorf ("Unable to get conversation info for channel %s" , innerEventData .Channel )
112+ }
113+
114+ b .channels .registerChannel (* channel )
115+ } else {
116+ b .users .populateUser (innerEventData .User )
117+ }
85118 }
86- messages <- rmsg
87- case * slack.OutgoingErrorEvent :
88- b .Log .Debugf ("%#v" , ev .Error ())
89- case * slack.ChannelJoinedEvent :
90- // When we join a channel we update the full list of users as
91- // well as the information for the channel that we joined as this
92- // should now tell that we are a member of it.
93- b .channels .registerChannel (ev .Channel )
94- case * slack.ConnectedEvent :
95- b .si = ev .Info
96- b .channels .populateChannels (true )
97- b .users .populateUsers (true )
98- case * slack.InvalidAuthEvent :
99- b .Log .Fatalf ("Invalid Token %#v" , ev )
100- case * slack.ConnectionErrorEvent :
101- b .Log .Errorf ("Connection failed %#v %#v" , ev .Error (), ev .ErrorObj )
102- case * slack.MemberJoinedChannelEvent :
103- b .users .populateUser (ev .User )
104- case * slack.HelloEvent , * slack.LatencyReport , * slack.ConnectingEvent :
105- continue
106- case * slack.UserChangeEvent :
107- b .users .invalidateUser (ev .User .ID )
108119 default :
109- b .Log .Debugf ("Unhandled incoming event: %T " , ev )
120+ b .Log .Debugf ("== Receiving event %#v " , msg . Data )
110121 }
111122 }
112123}
@@ -127,47 +138,44 @@ func (b *Bslack) handleMatterHook(messages chan *config.Message) {
127138}
128139
129140// skipMessageEvent skips event that need to be skipped :-)
130- func (b * Bslack ) skipMessageEvent (ev * slack .MessageEvent ) bool {
141+ func (b * Bslack ) skipMessageEvent (ev * slackevents .MessageEvent ) bool {
131142 switch ev .SubType {
132143 case sChannelLeave , sChannelJoin :
133144 return b .GetBool (noSendJoinConfig )
134145 case sPinnedItem , sUnpinnedItem :
135146 return true
136147 case sChannelTopic , sChannelPurpose :
137148 // Skip the event if our bot/user account changed the topic/purpose
138- if ev .User == b .si . User .ID {
149+ if ev .BotID == b .si .ID {
139150 return true
140151 }
141152 }
142153
143154 // Check for our callback ID
144155 hasOurCallbackID := false
145- if len (ev .Blocks .BlockSet ) == 1 {
146- block , ok := ev .Blocks .BlockSet [0 ].(* slack.SectionBlock )
156+
157+ if len (ev .Attachments ) == 1 {
158+ block , ok := ev .Attachments [0 ].Blocks .BlockSet [0 ].(* slack.SectionBlock )
147159 hasOurCallbackID = ok && block .BlockID == "matterbridge_" + b .uuid
148160 }
149161
150- if ev .SubMessage != nil {
162+ if ev .Message != nil {
151163 // It seems ev.SubMessage.Edited == nil when slack unfurls.
152164 // Do not forward these messages. See Github issue #266.
153- if ev .SubMessage . ThreadTimestamp != ev .SubMessage . Timestamp &&
154- ev .SubMessage .Edited == nil {
165+ if ev .Message . ThreadTimeStamp != ev .Message . TimeStamp &&
166+ ev .Message .Edited == nil {
155167 return true
156168 }
157- // see hidden subtypes at https://api.slack.com/events/message
158- // these messages are sent when we add a message to a thread #709
159- if ev .SubType == "message_replied" && ev .Hidden {
160- return true
161- }
162- if len (ev .SubMessage .Blocks .BlockSet ) == 1 {
163- block , ok := ev .SubMessage .Blocks .BlockSet [0 ].(* slack.SectionBlock )
169+
170+ if len (ev .Message .Attachments ) == 1 {
171+ block , ok := ev .Message .Attachments [0 ].Blocks .BlockSet [0 ].(* slack.SectionBlock )
164172 hasOurCallbackID = ok && block .BlockID == "matterbridge_" + b .uuid
165173 }
166174 }
167175
168176 // Skip any messages that we made ourselves or from 'slackbot' (see #527).
169177 if ev .Username == sSlackBotUser ||
170- (b .rtm != nil && ev .Username == b .si .User . Name ) || hasOurCallbackID {
178+ (b .smc != nil && ev .BotID == b .si .ID ) || hasOurCallbackID {
171179 return true
172180 }
173181
@@ -177,7 +185,7 @@ func (b *Bslack) skipMessageEvent(ev *slack.MessageEvent) bool {
177185 return false
178186}
179187
180- func (b * Bslack ) filesCached (files []slack .File ) bool {
188+ func (b * Bslack ) filesCached (files []slackevents .File ) bool {
181189 for i := range files {
182190 if ! b .fileCached (& files [i ]) {
183191 return false
@@ -202,7 +210,7 @@ func (b *Bslack) filesCached(files []slack.File) bool {
202210// 5. Handle any attachments of the received event.
203211// 6. Check that the Matterbridge message that we end up with after at the end of the
204212// pipeline is valid before sending it to the Matterbridge router.
205- func (b * Bslack ) handleMessageEvent (ev * slack .MessageEvent ) (* config.Message , error ) {
213+ func (b * Bslack ) handleMessageEvent (ev * slackevents .MessageEvent ) (* config.Message , error ) {
206214 rmsg , err := b .populateReceivedMessage (ev )
207215 if err != nil {
208216 return nil , err
@@ -222,14 +230,15 @@ func (b *Bslack) handleMessageEvent(ev *slack.MessageEvent) (*config.Message, er
222230 // This is probably a webhook we couldn't resolve.
223231 return nil , fmt .Errorf ("message handling resulted in an empty bot message (probably an incoming webhook we couldn't resolve): %#v" , ev )
224232 }
225- if ev .SubMessage != nil {
226- return nil , fmt .Errorf ("message handling resulted in an empty message: %#v with submessage %#v" , ev , ev .SubMessage )
233+ if ev .Message != nil {
234+ return nil , fmt .Errorf ("message handling resulted in an empty message: %#v with submessage %#v" , ev , ev .Message )
227235 }
228236 return nil , fmt .Errorf ("message handling resulted in an empty message: %#v" , ev )
229237 }
230238 return rmsg , nil
231239}
232240
241+ // TODO: implement file deletion handle when slack-go library will expose this event
233242func (b * Bslack ) handleFileDeletedEvent (ev * slack.FileDeletedEvent ) (* config.Message , error ) {
234243 if rawChannel , ok := b .cache .Get (cfileDownloadChannel + ev .FileID ); ok {
235244 channel , err := b .channels .getChannelByID (rawChannel .(string ))
@@ -250,7 +259,7 @@ func (b *Bslack) handleFileDeletedEvent(ev *slack.FileDeletedEvent) (*config.Mes
250259 return nil , fmt .Errorf ("channel ID for file ID %s not found" , ev .FileID )
251260}
252261
253- func (b * Bslack ) handleStatusEvent (ev * slack .MessageEvent , rmsg * config.Message ) bool {
262+ func (b * Bslack ) handleStatusEvent (ev * slackevents .MessageEvent , rmsg * config.Message ) bool {
254263 switch ev .SubType {
255264 case sChannelJoined , sMemberJoined :
256265 // There's no further processing needed on channel events
@@ -263,16 +272,16 @@ func (b *Bslack) handleStatusEvent(ev *slack.MessageEvent, rmsg *config.Message)
263272 b .channels .populateChannels (false )
264273 rmsg .Event = config .EventTopicChange
265274 case sMessageChanged :
266- rmsg .Text = ev .SubMessage .Text
275+ rmsg .Text = ev .Message .Text
267276 // handle deleted thread starting messages
268- if ev .SubMessage .Text == "This message was deleted." {
277+ if ev .Message .Text == "This message was deleted." {
269278 rmsg .Event = config .EventMsgDelete
270279 return true
271280 }
272281 case sMessageDeleted :
273282 rmsg .Text = config .EventMsgDelete
274283 rmsg .Event = config .EventMsgDelete
275- rmsg .ID = ev .DeletedTimestamp
284+ rmsg .ID = ev .PreviousMessage . TimeStamp
276285 // If a message is being deleted we do not need to process
277286 // the event any further so we return 'true'.
278287 return true
@@ -282,7 +291,7 @@ func (b *Bslack) handleStatusEvent(ev *slack.MessageEvent, rmsg *config.Message)
282291 return false
283292}
284293
285- func (b * Bslack ) handleAttachments (ev * slack .MessageEvent , rmsg * config.Message ) {
294+ func (b * Bslack ) handleAttachments (ev * slackevents .MessageEvent , rmsg * config.Message ) {
286295 // File comments are set by the system (because there is no username given).
287296 if ev .SubType == sFileComment {
288297 rmsg .Username = sSystemUser
@@ -317,23 +326,8 @@ func (b *Bslack) handleAttachments(ev *slack.MessageEvent, rmsg *config.Message)
317326 }
318327}
319328
320- func (b * Bslack ) handleTypingEvent (ev * slack.UserTypingEvent ) (* config.Message , error ) {
321- if ev .User == b .si .User .ID {
322- return nil , ErrEventIgnored
323- }
324- channelInfo , err := b .channels .getChannelByID (ev .Channel )
325- if err != nil {
326- return nil , err
327- }
328- return & config.Message {
329- Channel : channelInfo .Name ,
330- Account : b .Account ,
331- Event : config .EventUserTyping ,
332- }, nil
333- }
334-
335329// handleDownloadFile handles file download
336- func (b * Bslack ) handleDownloadFile (rmsg * config.Message , file * slack .File , retry bool ) error {
330+ func (b * Bslack ) handleDownloadFile (rmsg * config.Message , file * slackevents .File , retry bool ) error {
337331 if b .fileCached (file ) {
338332 return nil
339333 }
@@ -395,7 +389,7 @@ func (b *Bslack) handleGetChannelMembers(rmsg *config.Message) bool {
395389// identically named file but with different content will be uploaded correctly
396390// (the assumption is that such name collisions will not occur within the given
397391// timeframes).
398- func (b * Bslack ) fileCached (file * slack .File ) bool {
392+ func (b * Bslack ) fileCached (file * slackevents .File ) bool {
399393 if ts , ok := b .cache .Get ("file" + file .ID ); ok && time .Since (ts .(time.Time )) < time .Minute {
400394 return true
401395 } else if ts , ok = b .cache .Get ("filename" + file .Name ); ok && time .Since (ts .(time.Time )) < 10 * time .Second {
0 commit comments