-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathslackhal.go
181 lines (134 loc) · 5.07 KB
/
slackhal.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package main
import (
"fmt"
"os"
"go.uber.org/zap"
"github.com/CyrilPeponnet/slackhal/pkg/authorizer"
"github.com/CyrilPeponnet/slackhal/pkg/logutils"
"github.com/CyrilPeponnet/slackhal/plugin"
"github.com/docopt/docopt-go"
"github.com/fatih/color"
"github.com/slack-go/slack"
"github.com/spf13/viper"
_ "github.com/CyrilPeponnet/slackhal/plugins/builtins"
// _ "github.com/CyrilPeponnet/slackhal/plugins/plugin-archiver"
_ "github.com/CyrilPeponnet/slackhal/plugins/plugin-facts"
// _ "github.com/CyrilPeponnet/slackhal/plugins/plugin-github"
// _ "github.com/CyrilPeponnet/slackhal/plugins/plugin-jira"
_ "github.com/CyrilPeponnet/slackhal/plugins/plugin-run"
)
var bot plugin.Bot
var authz authorizer.Authorizer
var defaultAnswers = []string{"Sorry, I'm not sure what you mean by that."}
func main() {
headline := "Slack HAL bot."
usage := `
This is another slack bot.
Usage: slackhal [options]
Options:
-h, --help Show this help.
-t, --token token The slack bot token to use.
-f, --file config The configuration file to load [default ./slackhal.yml]
--trigger char The char used to detect direct commands [default: !].
--http-handler-port port The Port of the http handler [default: :8080].
--log-level level Set the log level [default: error].
--log-format format Set the log format [default: console].
`
color.Blue(` __ _ _ _
/ _\ | ____ ___| | __ /\ /\____| |
\ \| |/ _ |/ __| |/ // /_/ / _ | |
_\ \ | (_| | (__| </ __ / (_| | |
\__/_|\__,_|\___|_|\_\/ /_/ \__,_|_|
Version 2.0
`)
args, _ := docopt.ParseDoc(headline + usage)
disabledPlugins := []string{}
// Load configuration file and override some args if needed.
if args["--file"] != nil {
viper.AddConfigPath("/etc/slackhal/")
viper.AddConfigPath("$HOME/.slackhal")
viper.AddConfigPath(".")
viper.SetConfigFile(args["--file"].(string))
err := viper.ReadInConfig()
if err != nil {
panic(fmt.Sprintf("Cannot read the provided configuration file: %v", err))
}
viper.SetDefault("bot.token", args["--token"])
viper.SetDefault("bot.log.level", args["--log-level"])
viper.SetDefault("bot.log.format", args["--log-format"])
viper.SetDefault("bot.trigger", args["--trigger"])
viper.SetDefault("bot.httpHandlerPort", args["--http-handler-port"])
disabledPlugins = viper.GetStringSlice("bot.plugins.disabled")
}
logutils.ConfigureWithOptions(viper.GetString("bot.log.level"), viper.GetString("bot.log.format"), "", false, false)
// Connect to slack and start runloop
if viper.GetString("bot.token") == "nil" {
zap.L().Fatal("You need to set the slack bot token!")
}
// Init our authorizer
err := authz.Init(os.ExpandEnv("$HOME/.slackhal/authz.db"))
if err != nil {
zap.L().Fatal("Cannot initialize the authorizer", zap.Error(err))
}
bot.API = slack.New(viper.GetString("bot.token"))
bot.RTM = bot.API.NewRTM()
go bot.RTM.ManageConnection()
// output channels and start the runloop
output := make(chan *plugin.SlackResponse)
zap.L().Info("Putting myself to the fullest possible use, which is all I think that any conscious entity can ever hope to do...")
// Init our plugins
initPlugins(disabledPlugins, viper.GetString("bot.httpHandlerPort"), output, &bot)
// Initialize our message tracker
bot.Tracker.Init()
// Start our Response dispatching run loop
go DispatchResponses(output, &bot)
Loop:
for msg := range bot.RTM.IncomingEvents {
switch ev := msg.Data.(type) {
case *slack.ConnectedEvent:
// Log.WithFields(logrus.Fields{"prefix": "[main]", "Infos": ev.Info, "counter": ev.ConnectionCount}).Debug("Connected with:")
info := bot.RTM.GetInfo()
bot.Name = info.User.Name
bot.ID = info.User.ID
zap.L().Info("Connected", zap.String("name", bot.Name), zap.String("id", bot.ID))
case *slack.MessageEvent:
// zap.L().Debug("Message event received", zap.Reflect("event", ev))
// Discard messages coming from myself or bots
if ev.SubType == "bot_message" || ev.User == bot.ID {
continue
}
if ev.SubType == "message_changed" {
if ev.SubMessage.SubType == "bot_message" || ev.SubMessage.User == bot.ID {
continue
}
}
go DispatchMessage(viper.GetString("bot.trigger"), ev, output)
case *slack.AckMessage:
bot.Tracker.UpdateTracking(ev)
case *slack.RTMError:
zap.L().Error("RTM error", zap.String("error", ev.Error()))
case *slack.InvalidAuthEvent:
zap.L().Error("Invalid credentials provided!")
break Loop
case *slack.HelloEvent:
// Ignore hello
case *slack.PresenceChangeEvent:
// zap.L().Debug("Presence Change: %v", ev)
case *slack.ChannelJoinedEvent:
// nothing
case *slack.ChannelLeftEvent:
// nothing
case *slack.ReconnectUrlEvent:
// experimental and not used
case *slack.LatencyReport:
// zap.L().Debugf("Current latency: %v", ev.Value)
case *slack.ReactionAddedEvent:
// if reaction added on our message
case *slack.ReactionRemovedEvent:
// If reaction removed on our message
default:
// ingore other events
// zap.L().Debug("event", zap.Reflect("data", msg.Data))
}
}
}