@@ -11,103 +11,89 @@ import (
11
11
"sort"
12
12
"strings"
13
13
"text/tabwriter"
14
-
15
- "github.com/nlopes/slack"
16
14
)
17
15
18
- // Bot describes a generic bot
19
- type Bot interface {
20
- Name () string
21
- Config () Config
22
- AddCommand ( trigger string , command Command )
16
+ type BotCommandRunner interface {
17
+ RunCommand ( args [] string , channel string ) error
18
+ }
19
+
20
+ type BotBackend interface {
23
21
SendMessage (text string , channel string )
24
- HelpMessage () string
25
- SetHelp (help string )
26
- Label () string
27
- SetDefault (command Command )
28
- Listen ()
22
+ Listen (BotCommandRunner )
29
23
}
30
24
31
- // SlackBot is a Slack bot
32
- type SlackBot struct {
33
- api * slack.Client
34
- rtm * slack.RTM
35
- commands map [string ]Command
36
- defaultCommand Command
37
- channelIDs map [string ]string
25
+ // Bot describes a generic bot
26
+ type Bot struct {
27
+ backend BotBackend
38
28
help string
39
29
name string
40
30
label string
41
31
config Config
32
+ commands map [string ]Command
33
+ defaultCommand Command
42
34
}
43
35
44
- // NewBot constructs a bot from a Slack token
45
- func NewBot (token string , name string , label string , config Config ) (Bot , error ) {
46
- api := slack .New (token )
47
- //api.SetDebug(true)
48
-
49
- channelIDs , err := LoadChannelIDs (* api )
50
- if err != nil {
51
- return nil , err
52
- }
53
-
54
- bot := newBot (config )
55
- bot .api = api
56
- bot .rtm = api .NewRTM ()
57
- bot .channelIDs = channelIDs
58
- bot .name = name
59
- bot .label = label
60
-
61
- return bot , nil
62
- }
63
-
64
- func newBot (config Config ) * SlackBot {
65
- bot := SlackBot {
36
+ func NewBot (config Config , name , label string , backend BotBackend ) * Bot {
37
+ return & Bot {
38
+ backend : backend ,
66
39
config : config ,
67
40
commands : make (map [string ]Command ),
41
+ name : name ,
42
+ label : label ,
68
43
}
69
- return & bot
70
44
}
71
45
72
- // NewTestBot returns a bot for testing
73
- func NewTestBot () (Bot , error ) {
74
- return newBot (NewConfig (true , false )), nil
46
+ func (b * Bot ) Name () string {
47
+ return b .name
75
48
}
76
49
77
- // AddCommand adds a command to the Bot
78
- func (b * SlackBot ) AddCommand (trigger string , command Command ) {
79
- b .commands [trigger ] = command
50
+ func (b * Bot ) Config () Config {
51
+ return b .config
80
52
}
81
53
82
- // Name returns bot name
83
- func (b * SlackBot ) Name () string {
84
- return b .name
54
+ func (b * Bot ) AddCommand (trigger string , command Command ) {
55
+ b .commands [trigger ] = command
85
56
}
86
57
87
- // Label returns bot label
88
- func (b * SlackBot ) Label () string {
89
- return b .label
58
+ func (b * Bot ) triggers () []string {
59
+ triggers := make ([]string , 0 , len (b .commands ))
60
+ for trigger := range b .commands {
61
+ triggers = append (triggers , trigger )
62
+ }
63
+ sort .Strings (triggers )
64
+ return triggers
90
65
}
91
66
92
- // Config returns bot config
93
- func (b * SlackBot ) Config () Config {
94
- return b .config
67
+ // HelpMessage is the default help message for the bot
68
+ func (b * Bot ) HelpMessage () string {
69
+ w := new (tabwriter.Writer )
70
+ buf := new (bytes.Buffer )
71
+ w .Init (buf , 8 , 8 , 8 , ' ' , 0 )
72
+ fmt .Fprintln (w , "Command\t Description" )
73
+ for _ , trigger := range b .triggers () {
74
+ command := b .commands [trigger ]
75
+ fmt .Fprintln (w , fmt .Sprintf ("%s\t %s" , trigger , command .Description ()))
76
+ }
77
+ _ = w .Flush ()
78
+ return BlockQuote (buf .String ())
95
79
}
96
80
97
- // SetHelp sets the help info
98
- func (b * SlackBot ) SetHelp (help string ) {
81
+ func (b * Bot ) SetHelp (help string ) {
99
82
b .help = help
100
83
}
101
84
102
- // SetDefault is the default command, if no command added for trigger
103
- func (b * SlackBot ) SetDefault (command Command ) {
85
+ func (b * Bot ) Label () string {
86
+ return b .label
87
+ }
88
+
89
+ func (b * Bot ) SetDefault (command Command ) {
104
90
b .defaultCommand = command
105
91
}
106
92
107
93
// RunCommand runs a command
108
- func (b * SlackBot ) RunCommand (args []string , channel string ) error {
94
+ func (b * Bot ) RunCommand (args []string , channel string ) error {
109
95
if len (args ) == 0 || args [0 ] == "help" {
110
- b .SendHelpMessage (channel )
96
+ b .sendHelpMessage (channel )
111
97
return nil
112
98
}
113
99
@@ -121,128 +107,52 @@ func (b *SlackBot) RunCommand(args []string, channel string) error {
121
107
}
122
108
123
109
if args [0 ] != "resume" && args [0 ] != "config" && b .Config ().Paused () {
124
- b .SendMessage ("I can't do that, I'm paused." , channel )
110
+ b .backend . SendMessage ("I can't do that, I'm paused." , channel )
125
111
return nil
126
112
}
127
113
128
114
go b .run (args , command , channel )
129
115
return nil
130
116
}
131
117
132
- func (b * SlackBot ) run (args []string , command Command , channel string ) {
118
+ func (b * Bot ) run (args []string , command Command , channel string ) {
133
119
out , err := command .Run (channel , args )
134
120
if err != nil {
135
121
log .Printf ("Error %s running: %#v; %s\n " , err , command , out )
136
- b .SendMessage (fmt .Sprintf ("Oops, there was an error in %q:\n %s" , strings .Join (args , " " ), SlackBlockQuote (out )), channel )
122
+ b .backend .SendMessage (fmt .Sprintf ("Oops, there was an error in %q:\n %s" , strings .Join (args , " " ),
123
+ BlockQuote (out )), channel )
137
124
return
138
125
}
139
126
log .Printf ("Output: %s\n " , out )
140
127
if command .ShowResult () {
141
- b .SendMessage (out , channel )
128
+ b .backend . SendMessage (out , channel )
142
129
}
143
130
}
144
131
145
- // SendMessage sends a message to a channel
146
- func (b * SlackBot ) SendMessage (text string , channel string ) {
147
- cid := b .channelIDs [channel ]
148
- if cid == "" {
149
- cid = channel
150
- }
151
-
152
- if channel == "" {
153
- log .Printf ("No channel to send message: %s" , text )
154
- return
155
- }
156
-
157
- if b .rtm != nil {
158
- b .rtm .SendMessage (b .rtm .NewOutgoingMessage (text , cid ))
159
- } else {
160
- log .Printf ("Unable to send message: %s" , text )
161
- }
162
- }
163
-
164
- // Triggers returns list of supported triggers
165
- func (b * SlackBot ) Triggers () []string {
166
- triggers := make ([]string , 0 , len (b .commands ))
167
- for trigger := range b .commands {
168
- triggers = append (triggers , trigger )
169
- }
170
- sort .Strings (triggers )
171
- return triggers
172
- }
173
-
174
- // HelpMessage is the default help message for the bot
175
- func (b * SlackBot ) HelpMessage () string {
176
- w := new (tabwriter.Writer )
177
- buf := new (bytes.Buffer )
178
- w .Init (buf , 8 , 8 , 8 , ' ' , 0 )
179
- fmt .Fprintln (w , "Command\t Description" )
180
- for _ , trigger := range b .Triggers () {
181
- command := b .commands [trigger ]
182
- fmt .Fprintln (w , fmt .Sprintf ("%s\t %s" , trigger , command .Description ()))
183
- }
184
- _ = w .Flush ()
185
-
186
- return SlackBlockQuote (buf .String ())
187
- }
188
-
189
- // SendHelpMessage displays help message to the channel
190
- func (b * SlackBot ) SendHelpMessage (channel string ) {
132
+ func (b * Bot ) sendHelpMessage (channel string ) {
191
133
help := b .help
192
134
if help == "" {
193
135
help = b .HelpMessage ()
194
136
}
195
- b .SendMessage (help , channel )
137
+ b .backend . SendMessage (help , channel )
196
138
}
197
139
198
- // Listen starts listening on the connection
199
- func (b * SlackBot ) Listen () {
200
- go b .rtm .ManageConnection ()
201
-
202
- auth , err := b .api .AuthTest ()
203
- if err != nil {
204
- panic (err )
205
- }
206
- // The Slack bot "tuxbot" should expect commands to start with "!tuxbot".
207
- log .Printf ("Connected to Slack as %q" , auth .User )
208
- commandPrefix := "!" + auth .User
209
-
210
- Loop:
211
- for {
212
- msg := <- b .rtm .IncomingEvents
213
- switch ev := msg .Data .(type ) {
214
- case * slack.HelloEvent :
215
-
216
- case * slack.ConnectedEvent :
217
-
218
- case * slack.MessageEvent :
219
- args := parseInput (ev .Text )
220
- if len (args ) > 0 && args [0 ] == commandPrefix {
221
- cmd := args [1 :]
222
- b .RunCommand (cmd , ev .Channel )
223
- }
224
-
225
- case * slack.PresenceChangeEvent :
226
- //log.Printf("Presence Change: %v\n", ev)
227
-
228
- case * slack.LatencyReport :
229
- //log.Printf("Current latency: %v\n", ev.Value)
230
-
231
- case * slack.RTMError :
232
- log .Printf ("Error: %s\n " , ev .Error ())
140
+ func (b * Bot ) SendMessage (text string , channel string ) {
141
+ b .backend .SendMessage (text , channel )
142
+ }
233
143
234
- case * slack. InvalidAuthEvent :
235
- log . Printf ( "Invalid credentials \n " )
236
- break Loop
144
+ func ( b * Bot ) Listen () {
145
+ b . backend . Listen ( b )
146
+ }
237
147
238
- default :
239
- // log.Printf("Unexpected: %v\n", msg.Data)
240
- }
241
- }
148
+ // NewTestBot returns a bot for testing
149
+ func NewTestBot () ( * Bot , error ) {
150
+ backend := & SlackBotBackend { }
151
+ return NewBot ( NewConfig ( true , false ), "testbot" , "" , backend ), nil
242
152
}
243
153
244
- // SlackBlockQuote returns the string block-quoted
245
- func SlackBlockQuote (s string ) string {
154
+ // BlockQuote returns the string block-quoted
155
+ func BlockQuote (s string ) string {
246
156
if ! strings .HasSuffix (s , "\n " ) {
247
157
s += "\n "
248
158
}
0 commit comments