18
18
19
19
from zulip import Client
20
20
21
+ from collections import OrderedDict
22
+
21
23
def exit_gracefully (signum , frame ):
22
24
# type: (int, Optional[Any]) -> None
23
25
sys .exit (0 )
@@ -188,6 +190,48 @@ def is_private_message_from_another_user(message_dict, current_user_id):
188
190
return current_user_id != message_dict ['sender_id' ]
189
191
return False
190
192
193
+ def setup_default_commands (bot_details , message_handler ):
194
+ def def_about ():
195
+ if bot_details ['description' ] == "" :
196
+ return "**{}**" .format (bot_details ['name' ])
197
+ return "**{}**: {}" .format (bot_details ['name' ], bot_details ['description' ])
198
+
199
+ def def_help ():
200
+ return ("\n " .join ("**{}** - {}" .format (k , v [1 ])
201
+ for k , v in defaults .items () if k ) + "\n " +
202
+ "\n " .join ("**{}** - {}" .format (k , v )
203
+ for k , v in bot_details ['commands' ].items () if k ))
204
+
205
+ def def_commands ():
206
+ return "**Commands**: {} {}" .format (
207
+ " " .join (k for k in defaults if k ),
208
+ " " .join (k for k in bot_details ['commands' ] if k ))
209
+ defaults = OrderedDict ([ # Variable definition required for callbacks above
210
+ ('' , (lambda : "Oops. Your message was empty." , "[BLANK MESSAGE NOT SHOWN]" )),
211
+ ('about' , (def_about , "The type and use of this bot" )),
212
+ ('usage' , ((lambda : message_handler .usage (), "Bot-provided usage text" ))),
213
+ ('help' , (lambda : "{}\n {}\n {}" .format (def_about (), message_handler .usage (), def_help ()),
214
+ "This help text" )),
215
+ ('commands' , (def_commands , "A short list of supported commands" ))
216
+ ])
217
+ return defaults
218
+
219
+ def sync_botdetails_defaultcommands (bot_details , default_commands ):
220
+ # Update default_commands from any changes in bot_details
221
+ if not bot_details ['defaults' ]: # Bot class will handle all commands
222
+ default_commands = {}
223
+ else :
224
+ if len (bot_details ['commands' ]) == 0 : # No commands specified, so don't use this feature
225
+ del default_commands ['commands' ]
226
+ del default_commands ['help' ]
227
+ else :
228
+ for command in bot_details ['commands' ]: # Bot commands override defaults
229
+ if command in default_commands :
230
+ del default_commands [command ]
231
+ # Sync default_commands changes with bot_details
232
+ if len (default_commands ) == 0 :
233
+ bot_details ['defaults' ] = False
234
+
191
235
def run_message_handler_for_bot (lib_module , quiet , config_file , bot_name ):
192
236
# type: (Any, bool, str) -> Any
193
237
#
@@ -207,7 +251,23 @@ def run_message_handler_for_bot(lib_module, quiet, config_file, bot_name):
207
251
208
252
state_handler = StateHandler ()
209
253
254
+ # Set default bot_details, then override from class, if provided
255
+ bot_details = {
256
+ 'name' : bot_name .capitalize (),
257
+ 'description' : "" ,
258
+ 'commands' : {},
259
+ 'defaults' : True ,
260
+ }
261
+ bot_details .update (getattr (lib_module .handler_class , 'META' , {}))
262
+
263
+ # Initialise default commands, then override & sync with bot_details
264
+ default_commands = setup_default_commands (bot_details , message_handler )
265
+ sync_botdetails_defaultcommands (bot_details , default_commands )
266
+
210
267
if not quiet :
268
+ print ("Running {} Bot:" .format (bot_details ['name' ]))
269
+ if bot_details ['description' ] != "" :
270
+ print ("\n {}" .format (bot_details ['description' ]))
211
271
print (message_handler .usage ())
212
272
213
273
def handle_message (message ):
@@ -228,6 +288,18 @@ def handle_message(message):
228
288
return
229
289
230
290
if is_private_message or is_mentioned :
291
+ # Handle any default_commands first
292
+ if len (default_commands ) > 0 :
293
+ if '' in default_commands and len (message ['content' ]) == 0 :
294
+ restricted_client .send_reply (message , default_commands ['' ][0 ]())
295
+ return
296
+ for command in default_commands :
297
+ if command == '' :
298
+ continue
299
+ if message ['content' ].startswith (command ):
300
+ restricted_client .send_reply (message , default_commands [command ][0 ]())
301
+ return
302
+ # ...then pass anything else to bot to deal with
231
303
message_handler .handle_message (
232
304
message = message ,
233
305
bot_handler = restricted_client ,
0 commit comments