--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commandhandler.py Wed Nov 05 00:19:15 2014 +0200 @@ -0,0 +1,156 @@ +import os +import re + +CommandModules = {} +Commands = {} + +class CommandError (Exception): + def __init__ (self, value): + self.value = value + def __str__ (self): + return self.value + +# +# init_data() +# +# Initializes command module data +# +def init_data(): + global Commands + global CommandModules + files = os.listdir ('.') + + for fn in files: + if fn[0:4] != 'cmd_' or fn[-3:] != '.py': + continue + + fn = fn[0:-3] + globals = {} + module = __import__ (fn) + CommandModules[fn] = module + + for cmd in module.ModuleData['commands']: + if cmd['args'] == None: + cmd['args'] = '' + + cmd['module'] = module + cmd['regex'] = make_regex (cmd['args']) + cmd['argnames'] = [] + Commands[cmd['name']] = cmd + + for argname in cmd['args'].split (' '): + argname = argname[1:-1] + + if argname[-3:] == '...': + argname = argname[0:-3] + + if argname == '': + continue + + cmd['argnames'].append (argname) + #done + #done + + print "Loaded command module %s" % fn + #done + + print 'Loaded %d commands in %d modules' % (len (Commands), len (CommandModules)) +#enddef + +# +# command_error (message) +# +# Raises a command error +# +def command_error (message): + raise CommandError (message) + +# +# call_command (bot, message, cmdname, **kvargs) +# +# Calls a cobalt command +# +def call_command (bot, message, cmdname, **kvargs): + try: + cmd = Commands[cmdname] + except KeyError: + return False + + if cmd['level'] == 'admin' and not bot.is_admin (kvargs['ident'], kvargs['host']): + command_error ("%s requires admin access" % cmdname) + + match = re.compile (cmd['regex']).match (message) + + if match == None: + # didn't match + command_error ('invalid arguments\nusage: %s %s' % (cmd['name'], cmd['args'])) + #fi + + i = 1 + args = {} + + for argname in cmd['argnames']: + args[argname] = match.group (i) + i += 1 + #done + + getattr (cmd['module'], "cmd_%s" % cmdname) (bot=bot, cmdname=cmdname, args=args, **kvargs) + return True + +# +# make_regex +# +# Takes the argument list and returns a corresponding regular expression +# +def make_regex (arglist): + if arglist == None: + return '^.+$' + + gotoptional = False + gotvariadic = False + regex = '' + + for arg in arglist.split (' '): + if gotvariadic: + raise CommandError ('variadic argument is not last') + + if arg == '': + continue + + if arg[0] == '[' and arg[-1] == ']': + arg = arg[1:-1] + gotoptional = True + elif arg[0] == '<' and arg[-1] == '>': + if gotoptional: + raise CommandError ('mandatory argument after optional one') + + arg = arg[1:-1] + else: + raise CommandError ('badly formed argument list') + #fi + + if arg[-3:] == '...': + gotvariadic = True + arg = arg[0:-3] + #fi + + if gotoptional == False: + regex += '\s+' + else: + regex += '\s*' + + if gotoptional: + if gotvariadic: + regex += r'(.*)' + else: + regex += r'([^ ]*)' + else: + if gotvariadic: + regex += r'(.+)' + else: + regex += r'([^ ]+)' + #fi + #done + + return '^[^ ]+%s$' % regex +#enddef \ No newline at end of file