# HG changeset patch # User Teemu Piippo # Date 1439757011 -10800 # Node ID df862cca177365c507e25a895359048760360cce # Parent 497b7290977dbb3cd825c72e6c99288d50d23fd5 Added ability to define an IRC command with a function decorator instead of a manifest entry diff -r 497b7290977d -r df862cca1773 hgdb.py --- a/hgdb.py Sun Aug 16 19:27:14 2015 +0300 +++ b/hgdb.py Sun Aug 16 23:30:11 2015 +0300 @@ -101,8 +101,8 @@ ''', (node + '%',)) names = cursor.fetchall() - names = set (zip (*names)[0]) if names else set() - return [hgpoll.RepositoriesByName[name] for name in names] + names = list (zip (*names))[0] if names else [] + return [hgpoll.RepositoriesByName[name] for name in set (names)] def find_commit_by_dateversion (self, dateversion): cursor = self.db.execute (''' diff -r 497b7290977d -r df862cca1773 mod_util.py --- a/mod_util.py Sun Aug 16 19:27:14 2015 +0300 +++ b/mod_util.py Sun Aug 16 23:30:11 2015 +0300 @@ -30,8 +30,7 @@ import math import json import re -from modulecore import command_error -import modulecore as ModuleCore +import modulecore import utility import calc import urllib.parse @@ -108,21 +107,14 @@ 'args': '', 'level': 'normal' }, - - { - 'name': 'py', - 'description': 'Evaluates python', - 'args': '', - 'level': 'normal' - } ] } -def cmd_convert (bot, args, reply, **rest): +def cmd_convert (bot, args, reply, error, **rest): try: value = float (args['value']) except Exception as e: - command_error (str (e)) + error (str (e)) valuetype = args['valuetype'] @@ -148,10 +140,10 @@ reply ('%s degrees celsius, %s degrees fahrenheit' % (celvalue, fahrvalue)) return - command_error ('unknown valuetype %s, expected one of: degrees, radians (angle conversion), ' + + error ('unknown valuetype %s, expected one of: degrees, radians (angle conversion), ' + 'celsius, fahrenheit (temperature conversion)' % valuetype) -def cmd_ud (bot, args, reply, **rest): +def cmd_ud (bot, args, reply, error, **rest): try: url = 'http://api.urbandictionary.com/v0/define?term=%s' % (args['term'].replace (' ', '%20')) response = utility.read_url (url) @@ -161,7 +153,7 @@ or len(data['list']) == 0 \ or not 'word' in data['list'][0] \ or not 'definition' in data['list'][0]: - command_error ("couldn't find a definition of \002%s\002" % args['term']) + error ("couldn't find a definition of \002%s\002" % args['term']) word = data['list'][0]['word'] definition = data['list'][0]['definition'].replace ('\r', ' ').replace ('\n', ' ').replace (' ', ' ') @@ -169,10 +161,10 @@ down = data['list'][0]['thumbs_down'] reply ("\002%s\002: %s\0033 %d\003 up,\0035 %d\003 down" % (word, definition, up, down)) except Exception as e: - command_error ('Urban dictionary lookup failed: %s' % e) + error ('Urban dictionary lookup failed: %s' % e) def cmd_commands (bot, reply, ident, host, **rest): - commandlist = ModuleCore.get_available_commands (ident, host) + commandlist = modulecore.get_available_commands (ident, host) partitioned=[] while len (commandlist) > 0: @@ -182,27 +174,17 @@ for part in partitioned: reply ('\002Available commands\002: %s' % (", ".join (part))) -def cmd_help (bot, reply, ident, host, args, **rest): - cmd = ModuleCore.get_command_by_name (args['command']) +def cmd_help (bot, reply, ident, host, args, error, **rest): + cmd = modulecore.get_command_by_name (args['command']) if not cmd: - command_error ('unknown command \'%s\'' % args['command']) + error ('unknown command \'%s\'' % args['command']) - if not ModuleCore.is_available (cmd, ident, host): - command_error ('you may not use %s' % cmd['name']) + if not modulecore.is_available (cmd, ident, host): + error ('you may not use %s' % cmd['name']) reply ('%s %s: %s' % (cmd['name'], cmd['args'], cmd['description'])) -def mathsubstitute (expr, token, value): - rex = re.compile (r'^(.*)\b' + token + r'\b(.*)$') - match = rex.match (expr) - - while match: - expr = match.group(1) + str (value) + match.group(2) - match = rex.match (expr) - - return expr - def cmd_calcfunctions (bot, reply, **rest): reply ('Available functions for .calc: %s' % \ ', '.join (sorted ([name for name, data in calc.Functions.items()]))) @@ -211,20 +193,26 @@ reply (calc.Calculator().calc (args['expression'])) def cmd_more (commandObject, **rest): - ModuleCore.print_responses (commandObject) + modulecore.print_responses (commandObject) def cmd_yes (**k): - ModuleCore.confirm (k, True) + modulecore.confirm (k, True) def cmd_no (**k): - ModuleCore.confirm (k, False) + modulecore.confirm (k, False) def cmd_bitly (reply, args, **k): reply ('Result: %s' % utility.shorten_link (args['link'])) -def cmd_py (reply, args, **rest): +@modulecore.irc_command (args='') +def py (reply, args, **rest): + ''' Evaluates the given Python string using appspot.com ''' url = 'http://eval.appspot.com/eval?statement=' + urllib.parse.quote (args['command']) - result = utility.read_url (url).splitlines() + result = utility.read_url (url, timeout=15).splitlines() + + if not result: + reply ('No output.') + return # \x0f is the 'reset colors' code, prepended to all reply lines to prevent other bots from # reacting to this .py call. diff -r 497b7290977d -r df862cca1773 modulecore.py --- a/modulecore.py Sun Aug 16 19:27:14 2015 +0300 +++ b/modulecore.py Sun Aug 16 23:30:11 2015 +0300 @@ -30,6 +30,7 @@ import os import re import time +import sys from configfile import Config Modules = {} @@ -63,24 +64,7 @@ Modules[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) + install_command (cmd, module) if 'hooks' in module.ModuleData: for key, hooks in module.ModuleData['hooks'].items(): @@ -96,6 +80,28 @@ print ('''Loaded %d commands and %d hooks in %d modules''' % (len (Commands), numHooks, len (Modules))) +def install_command (cmd, module): + if cmd['args'] == None: + cmd['args'] = '' + + Modules[module.__name__] = module + cmd['module'] = module + cmd['regex'] = make_regex (cmd['args']) + cmd['argnames'] = [] + + for argname in cmd['args'].split (' '): + argname = argname[1:-1] + + if argname[-3:] == '...': + argname = argname[0:-3] + + if argname == '': + continue + + cmd['argnames'].append (argname) + + Commands[cmd['name']] = cmd + # # command_error (message) # @@ -181,8 +187,8 @@ global g_lastConfirm global g_confirmCommand - if 'function' in commandObject: - func = commandObject['function'] + if 'function' in commandObject['info']: + func = commandObject['info']['function'] else: cmdname = commandObject['cmdname'] @@ -379,3 +385,22 @@ regex += r'\s*' return '^[^ ]+%s$' % regex + +def irc_command (**command): + def result (fn): + command['name'] = fn.__name__ + command['description'] = fn.__doc__ + command['function'] = fn + + if command['description'] == None: + command['description'] = '' + + if 'level' not in command: + command['level'] = 'normal' + + if 'args' not in command: + command['args'] = None + + install_command (command, sys.modules[fn.__module__]) + return fn + return result \ No newline at end of file diff -r 497b7290977d -r df862cca1773 utility.py --- a/utility.py Sun Aug 16 19:27:14 2015 +0300 +++ b/utility.py Sun Aug 16 23:30:11 2015 +0300 @@ -51,8 +51,13 @@ return link -def read_url (url): - data = urllib.request.urlopen (urllib.request.Request (url)).read() +def read_url (url, timeout=None): + args = [urllib.request.Request (url), None] + + if timeout: + args += [timeout] + + data = urllib.request.urlopen (*args).read() return data.decode ('utf-8') def make_progress_bar (p, barLength, colored=True):