diff --git a/core/main.py b/core/main.py index 23e3edd..7d0b42a 100644 --- a/core/main.py +++ b/core/main.py @@ -6,6 +6,7 @@ class Input(object): def __init__(self, conn, raw, prefix, command, params, nick, user, host, paraml, msg): self.conn = conn + self.server = conn.server self.raw = raw self.prefix = prefix self.command = command @@ -28,7 +29,6 @@ class FakeBot(object): self.bot = bot self.conn = conn self.persist_dir = bot.persist_dir - self.server = conn.server self.input = input self.msg = conn.msg self.cmd = conn.cmd @@ -56,6 +56,9 @@ class FakeBot(object): self.say(unicode(out)) def main(conn, out): + for csig, func, args in bot.plugs['tee']: + input = Input(conn, *out) + func._iqueue.put((bot, input)) for csig, func, args in (bot.plugs['command'] + bot.plugs['event']): input = Input(conn, *out) for fsig, sieve in bot.plugs['sieve']: diff --git a/core/reload.py b/core/reload.py index 976d639..e838fe3 100644 --- a/core/reload.py +++ b/core/reload.py @@ -51,6 +51,12 @@ def reload(init=False): # remove plugins already loaded from this filename for name, data in bot.plugs.iteritems(): + + if name == 'tee': # signal tee trampolines to stop + for csig, func, args in data: + if csig[0] == filename: + func._iqueue.put(StopIteration) + bot.plugs[name] = filter(lambda x: x[0][0] != filename, data) for obj in namespace.itervalues(): @@ -61,12 +67,6 @@ def reload(init=False): if not init: print '### new plugin (type: %s) loaded:' % \ type, format_plug(data) - - if type == 'init': # run-once functions - try: - obj(bot) # not thread-safe! - except Exception: - traceback.print_exc(Exception) if init: print ' plugin listing:' diff --git a/plugins/log.py b/plugins/log.py index 4fe5c9b..6bd69db 100644 --- a/plugins/log.py +++ b/plugins/log.py @@ -83,12 +83,12 @@ def get_log_fd(dir, server, chan): return fd -@hook.event(ignorebots=False) +@hook.tee def log(bot, input): with lock: timestamp = gmtime(timestamp_format) - fd = get_log_fd(bot.persist_dir, bot.server, 'raw') + fd = get_log_fd(bot.persist_dir, input.server, 'raw') fd.write(timestamp + ' ' + input.raw + '\n') if input.command == 'QUIT': # these are temporary fixes until proper @@ -104,5 +104,5 @@ def log(bot, input): print '%s %s %s' % (timestamp, input.chan, beau) if input.chan: - fd = get_log_fd(bot.persist_dir, bot.server, input.chan) + fd = get_log_fd(bot.persist_dir, input.server, input.chan) fd.write(timestamp + ' ' + beau + '\n') diff --git a/plugins/util/hook.py b/plugins/util/hook.py index 767c52e..c4e0445 100644 --- a/plugins/util/hook.py +++ b/plugins/util/hook.py @@ -1,10 +1,6 @@ import Queue +import thread -class queue(Queue.Queue): - - def __init__(self, maxsize=0): - Queue.Queue.__init__(self, maxsize) - self._skybot_hook = [['queue', self]] def _isfunc(x): if type(x) == type(_isfunc): @@ -30,14 +26,6 @@ def sieve(func): return func -def init(func): - if func.func_code.co_argcount != 1: - raise ValueError( - 'initializers must take 1 argument: bot') - _hook_add(func, ['init', (_make_sig(func), func)]) - return func - - def command(func=None, hook=None, **kwargs): args = {} @@ -79,3 +67,25 @@ def event(arg=None, **kwargs): if arg is not None: args['events'] = arg.split() return event_wrapper + + +def tee(func, **kwargs): + "passes _all_ input lines to function, in order (skips sieves)" + + if func.func_code.co_argcount != 2: + raise ValueError('tees must take 2 arguments: (bot, input)') + + _hook_add(func, ['tee', (_make_sig(func), func, kwargs)]) + func._iqueue = Queue.Queue() + + def trampoline(func): + input = None + while True: + input = func._iqueue.get() + if input == StopIteration: + return + func(*input) + + thread.start_new_thread(trampoline, (func,)) + + return func