-
Notifications
You must be signed in to change notification settings - Fork 42
/
listener.go
79 lines (69 loc) · 2.61 KB
/
listener.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package bot
import (
"os"
"os/signal"
"syscall"
"github.com/innogames/slack-bot/v2/bot/stats"
"github.com/innogames/slack-bot/v2/bot/util"
"github.com/innogames/slack-bot/v2/client"
log "github.com/sirupsen/logrus"
"github.com/slack-go/slack"
"github.com/slack-go/slack/slackevents"
"github.com/slack-go/slack/socketmode"
)
// Run is blocking method to handle new incoming events...from different sources
func (b *Bot) Run(ctx *util.ServerContext) {
b.startRunnables(ctx)
// initialize Socket Mode:
// https://api.slack.com/apis/connections/socket
go b.slackClient.Socket.Run()
// graceful shutdown via sigterm/sigint
stopChan := make(chan os.Signal, 2)
signal.Notify(stopChan, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
for {
select {
case event := <-b.slackClient.Socket.Events:
// message from Socket Mode
b.handleSocketModeEvent(event)
case message := <-client.InternalMessages:
// e.g. triggered by "delay" or "macro" command. They are still executed in original event context
// -> will post in same channel as the user posted the original command
message.InternalMessage = true
go b.ProcessMessage(message, false)
case <-stopChan:
// wait until other services are properly shut down
ctx.StopTheWorld()
return
case <-ctx.Done():
return
}
}
}
// startRunnables starts all background tasks and ctx.StopTheWorld() will stop them then properly
func (b *Bot) startRunnables(ctx *util.ServerContext) {
// each command can have a background task which is executed in the background
for _, cmd := range b.commands.commands {
if runnable, ok := cmd.(Runnable); ok {
go runnable.RunAsync(ctx)
}
}
// special handler which are executed in the background
stats.InitMetrics(b.config, ctx)
}
func (b *Bot) handleSocketModeEvent(event socketmode.Event) {
if event.Request != nil && event.Type != socketmode.EventTypeHello {
b.slackClient.Socket.Ack(*event.Request)
}
switch event.Type {
case socketmode.EventTypeConnectionError, socketmode.EventTypeErrorBadMessage, socketmode.EventTypeErrorWriteFailed, socketmode.EventTypeIncomingError, socketmode.EventTypeInvalidAuth:
log.Warnf("Socket Mode error: %s - %s", event.Type, event.Data)
case socketmode.EventTypeEventsAPI:
b.handleEvent(event.Data.(slackevents.EventsAPIEvent))
case socketmode.EventTypeInteractive:
b.handleInteraction(event.Data.(slack.InteractionCallback))
case socketmode.EventTypeConnected, socketmode.EventTypeConnecting, socketmode.EventTypeHello, socketmode.EventTypeDisconnect, socketmode.EventTypeSlashCommand:
// ignore
default:
log.Infof("Unexpected event type received: %s\n", event.Type)
}
}