From 7e4ea3a9ffa998a16d7f4f952423cff6270441a8 Mon Sep 17 00:00:00 2001 From: Luke Rogers Date: Wed, 2 Oct 2013 13:33:17 +1300 Subject: [PATCH] started removing bullshit magic --- cloudbot.py | 11 +++----- config.default | 5 ++-- core/bot.py | 7 ++++- core/{reload.py => loader.py} | 49 +++++++++++------------------------ core/main.py | 29 +++++++++++---------- plugins/geoip.py | 2 +- 6 files changed, 44 insertions(+), 59 deletions(-) rename core/{reload.py => loader.py} (75%) mode change 100755 => 100644 diff --git a/cloudbot.py b/cloudbot.py index 76349dc..b0a930b 100644 --- a/cloudbot.py +++ b/cloudbot.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # we import bot as _bot for now, for legacy reasons from core import bot as _bot +from core import loader, main import os import Queue @@ -16,20 +17,14 @@ print 'CloudBot REFRESH ' bot = _bot.Bot("cloudbot") bot.logger.debug("Bot initalized.") -# bootstrap the reloader -bot.logger.debug("Bootstrapping reloader.") -eval(compile(open(os.path.join('core', 'reload.py'), 'U').read(), - os.path.join('core', 'reload.py'), 'exec')) -reload(init=True) - bot.logger.debug("Starting main loop.") while True: - reload() # these functions only do things + loader.reload(bot) # these functions only do things for connection in bot.connections.itervalues(): try: out = connection.out.get_nowait() - main(connection, out) + main.main(bot, connection, out) except Queue.Empty: pass while all(connection.out.empty() for connection in bot.connections.itervalues()): diff --git a/config.default b/config.default index ca53241..13198e8 100644 --- a/config.default +++ b/config.default @@ -9,7 +9,7 @@ "ssl": false, "ignore_cert": true }, - "nick": "MyCloudBot", + "nick": "MyCloueqerdBot", "user": "cloudbot", "real_name": "CloudBot - http://git.io/cloudbotirc", "channels": ["#cloudbot", "#cloudbot2"], @@ -52,5 +52,6 @@ "rdio_key": "", "rdio_secret": "", "steam_key": "" - } + }, + "disabled_plugins": [] } diff --git a/core/bot.py b/core/bot.py index 0929855..40f9a73 100644 --- a/core/bot.py +++ b/core/bot.py @@ -3,7 +3,7 @@ import logging import re import os -from core import config, irc +from core import config, irc, loader def clean_name(n): @@ -25,6 +25,11 @@ class Bot(object): self.connections = {} self.connect() + # run plugin loader + self.logger.debug("Bootstrapping reloader.") + loader.reload(self, init=True) + + def connect(self): """connect to all the networks defined in the bot config""" for conf in self.config['connections']: diff --git a/core/reload.py b/core/loader.py old mode 100755 new mode 100644 similarity index 75% rename from core/reload.py rename to core/loader.py index f1bfeb6..7987c17 --- a/core/reload.py +++ b/core/loader.py @@ -3,8 +3,11 @@ import glob import os import re import sys +import Queue import traceback +from core import main + if 'mtimes' not in globals(): mtimes = {} @@ -31,40 +34,18 @@ def format_plug(plug, kind='', lpad=0): return out -def reload(init=False): +def reload(bot, init=False): changed = False if init: - bot.plugs = collections.defaultdict(list) + bot.plugins = collections.defaultdict(list) bot.threads = {} - core_fileset = set(glob.glob(os.path.join("core", "*.py"))) - - for filename in core_fileset: - mtime = os.stat(filename).st_mtime - if mtime != mtimes.get(filename): - mtimes[filename] = mtime - - changed = True - - try: - eval(compile(open(filename, 'U').read(), filename, 'exec'), - globals()) - except Exception: - traceback.print_exc() - if init: # stop if there's an error (syntax?) in a core - sys.exit() # script on startup - continue - - if filename == os.path.join('core', 'reload.py'): - reload(init=init) - return - fileset = set(glob.glob(os.path.join('plugins', '*.py'))) # remove deleted/moved plugins - for name, data in bot.plugs.iteritems(): - bot.plugs[name] = [x for x in data if x[0]._filename in fileset] + for name, data in bot.plugins.iteritems(): + bot.plugins[name] = [x for x in data if x[0]._filename in fileset] for filename in list(mtimes): if filename not in fileset and filename not in core_fileset: @@ -72,7 +53,7 @@ def reload(init=False): for func, handler in list(bot.threads.iteritems()): if func._filename not in fileset: - handler.stop() + main.handler.stop() del bot.threads[func] # compile new plugins @@ -92,8 +73,8 @@ def reload(init=False): continue # remove plugins already loaded from this filename - for name, data in bot.plugs.iteritems(): - bot.plugs[name] = [x for x in data + for name, data in bot.plugins.iteritems(): + bot.plugins[name] = [x for x in data if x[0]._filename != filename] for func, handler in list(bot.threads.iteritems()): @@ -104,10 +85,10 @@ def reload(init=False): for obj in namespace.itervalues(): if hasattr(obj, '_hook'): # check for magic if obj._thread: - bot.threads[obj] = Handler(obj) + bot.threads[obj] = main.Handler(bot, obj) for type, data in obj._hook: - bot.plugs[type] += [data] + bot.plugins[type] += [data] if not init: print '### new plugin (type: %s) loaded:' % \ @@ -115,7 +96,7 @@ def reload(init=False): if changed: bot.commands = {} - for plug in bot.plugs['command']: + for plug in bot.plugins['command']: name = plug[1]['name'].lower() if not re.match(r'^\w+$', name): print '### ERROR: invalid command name "{}" ({})'.format(name, format_plug(plug)) @@ -128,7 +109,7 @@ def reload(init=False): bot.commands[name] = plug bot.events = collections.defaultdict(list) - for func, args in bot.plugs['event']: + for func, args in bot.plugins['event']: for event in args['events']: bot.events[event].append((func, args)) @@ -151,7 +132,7 @@ def reload(init=False): out += ' ' * (50 - len(out)) + ', '.join(names) print out - for kind, plugs in sorted(bot.plugs.iteritems()): + for kind, plugs in sorted(bot.plugins.iteritems()): if kind == 'command': continue print ' {}:'.format(kind) diff --git a/core/main.py b/core/main.py index dac6112..b1649ef 100755 --- a/core/main.py +++ b/core/main.py @@ -1,12 +1,14 @@ import thread import traceback +import Queue +import re thread.stack_size(1024 * 512) # reduce vm size class Input(dict): - def __init__(self, conn, raw, prefix, command, params, + def __init__(self, bot, conn, raw, prefix, command, params, nick, user, host, mask, paraml, msg): chan = paraml[0].lower() @@ -84,8 +86,9 @@ def do_sieve(sieve, bot, input, func, type, args): class Handler(object): """Runs plugins in their own threads (ensures order)""" - def __init__(self, func): + def __init__(self, func, bot): self.func = func + self.bot = bot self.input_queue = Queue.Queue() thread.start_new_thread(self.start, ()) @@ -101,7 +104,7 @@ class Handler(object): if uses_db: db = db_conns.get(input.conn) if db is None: - db = bot.get_db_connection(input.conn) + db = self.bot.get_db_connection(input.conn) db_conns[input.conn] = db input.db = db @@ -119,8 +122,8 @@ class Handler(object): self.input_queue.put(value) -def dispatch(input, kind, func, args, autohelp=False): - for sieve, in bot.plugs['sieve']: +def dispatch(bot, input, kind, func, args, autohelp=False): + for sieve, in bot.plugins['sieve']: input = do_sieve(sieve, bot, input, func, kind, args) if input is None: return @@ -135,7 +138,7 @@ def dispatch(input, kind, func, args, autohelp=False): thread.start_new_thread(run, (func, input)) -def match_command(command): +def match_command(bot, command): commands = list(bot.commands) # do some fuzzy matching @@ -148,13 +151,13 @@ def match_command(command): return command -def main(conn, out): - inp = Input(conn, *out) +def main(bot, conn, out): + inp = Input(bot, conn, *out) command_prefix = conn.conf.get('command_prefix', '.') # EVENTS for func, args in bot.events[inp.command] + bot.events['*']: - dispatch(Input(conn, *out), "event", func, args) + dispatch(bot, Input(bot, conn, *out), "event", func, args) if inp.command == 'PRIVMSG': # COMMANDS @@ -170,23 +173,23 @@ def main(conn, out): if m: trigger = m.group(1).lower() - command = match_command(trigger) + command = match_command(bot, trigger) if isinstance(command, list): # multiple potential matches input = Input(conn, *out) input.notice("Did you mean {} or {}?".format (', '.join(command[:-1]), command[-1])) elif command in bot.commands: - input = Input(conn, *out) + input = Input(bot, conn, *out) input.trigger = trigger input.inp_unstripped = m.group(2) input.inp = input.inp_unstripped.strip() func, args = bot.commands[command] - dispatch(input, "command", func, args, autohelp=True) + dispatch(bot, input, "command", func, args, autohelp=True) # REGEXES - for func, args in bot.plugs['regex']: + for func, args in bot.plugins['regex']: m = args['re'].search(inp.lastparam) if m: input = Input(conn, *out) diff --git a/plugins/geoip.py b/plugins/geoip.py index a4fab57..b0d05a4 100755 --- a/plugins/geoip.py +++ b/plugins/geoip.py @@ -1,6 +1,6 @@ from util import hook, http +from lib import pygeoip import os.path -import pygeoip import json import gzip from StringIO import StringIO