From 038793c226c9d8b73865a50a9ee2e5222cb460d8 Mon Sep 17 00:00:00 2001 From: Ryan Hitchman Date: Fri, 16 Oct 2009 19:36:02 -0600 Subject: [PATCH 1/3] move irc into core/, fix reload plugin display --- bot.py | 10 +++++----- core/reload.py | 14 +++++++++----- plugins/util/hook.py | 8 ++++++++ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/bot.py b/bot.py index 1bcc46b..0fb66da 100755 --- a/bot.py +++ b/bot.py @@ -1,8 +1,8 @@ #!/usr/bin/python -network = "irc.synirc.net" +network = "localhost" nick = "skybot" -channel = "#cobol" +channel = "#test" import sys import os @@ -12,25 +12,25 @@ sys.path += ['plugins'] # so 'import hook' works without duplication sys.path += ['lib'] os.chdir(sys.path[0]) # do stuff relative to the installation directory -import irc - class Bot(object): pass + bot = Bot() print 'Loading plugins' # bootstrap the reloader eval(compile(open('core/reload.py', 'U').read(), 'core/reload.py', 'exec')) +reload(init=True) print 'Connecting to IRC' bot.nick = nick bot.channel = channel bot.network = network -bot.irc = irc.irc(network, nick) +bot.irc = irc(network, nick) bot.irc.join(channel) bot.persist_dir = os.path.abspath('persist') diff --git a/core/reload.py b/core/reload.py index 68df8ee..d6365aa 100644 --- a/core/reload.py +++ b/core/reload.py @@ -8,11 +8,9 @@ if 'mtimes' not in globals(): if 'lastfiles' not in globals(): lastfiles = set() -def reload(): - init = False - if not hasattr(bot, 'plugs'): +def reload(init=False): + if init: bot.plugs = collections.defaultdict(lambda: []) - init = True for filename in glob.glob("core/*.py"): mtime = os.stat(filename).st_mtime @@ -26,7 +24,7 @@ def reload(): continue if filename == 'core/reload.py': - reload() + reload(init=init) return fileset = set(glob.glob("plugins/*py")) @@ -53,6 +51,12 @@ def reload(): if hasattr(obj, '_skybot_hook'): #check for magic for type, data in obj._skybot_hook: bot.plugs[type] += [data] + + if type == 'init': + try: + obj(bot) + except Exception: + traceback.print_exc(Exception) if init: print ' plugin listing:' diff --git a/plugins/util/hook.py b/plugins/util/hook.py index e27bc23..767c52e 100644 --- a/plugins/util/hook.py +++ b/plugins/util/hook.py @@ -30,6 +30,14 @@ 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 = {} From d8026cb5357a5a418f40d3bbe07a9fac61d6c381 Mon Sep 17 00:00:00 2001 From: Ryan Hitchman Date: Sat, 7 Nov 2009 11:37:38 -0700 Subject: [PATCH 2/3] more reload improvements --- core/reload.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/core/reload.py b/core/reload.py index d6365aa..8b21bba 100644 --- a/core/reload.py +++ b/core/reload.py @@ -8,6 +8,12 @@ if 'mtimes' not in globals(): if 'lastfiles' not in globals(): lastfiles = set() +def format_plug(plug, lpad=0, width=40): + out = ' ' * lpad + '%s:%s:%s' % (plug[0]) + if len(plug) == 3 and 'hook' in plug[2]: + out += '%s%s' % (' ' * (width - len(out)), plug[2]['hook']) + return out + def reload(init=False): if init: bot.plugs = collections.defaultdict(lambda: []) @@ -51,10 +57,13 @@ def reload(init=False): if hasattr(obj, '_skybot_hook'): #check for magic for type, data in obj._skybot_hook: bot.plugs[type] += [data] + + if not init: + print '### new plugin (type: %s) loaded:' % type, format_plug(data) - if type == 'init': + if type == 'init': # run-once functions try: - obj(bot) + obj(bot) # not thread-safe! except Exception: traceback.print_exc(Exception) @@ -64,9 +73,5 @@ def reload(init=False): print ' %s:' % type for plug in plugs: out = ' %s:%s:%s' % (plug[0]) - print out, - if len(plug) == 3 and 'hook' in plug[2]: - print '%s%s' % (' ' * (40 - len(out)), plug[2]['hook']) - else: - print + print format_plug(plug, lpad=6) print From 16bc9abecddc2e04c7798e1207c984841cee8ed5 Mon Sep 17 00:00:00 2001 From: Ryan Hitchman Date: Sat, 7 Nov 2009 11:41:21 -0700 Subject: [PATCH 3/3] fixing outstanding changes --- irc.py | 108 --------------------------------------------------------- 1 file changed, 108 deletions(-) delete mode 100644 irc.py diff --git a/irc.py b/irc.py deleted file mode 100644 index e8a09dd..0000000 --- a/irc.py +++ /dev/null @@ -1,108 +0,0 @@ -import sys -import re -import socket -import thread -import asyncore -import asynchat -import Queue - - -def decode(txt): - for codec in ('utf-8', 'iso-8859-1', 'shift_jis', 'cp1252'): - try: - return txt.decode(codec) - except UnicodeDecodeError: - continue - return txt.decode('utf-8', 'ignore') - - -class crlf_tcp(asynchat.async_chat): - "Handles tcp connections that consist of utf-8 lines ending with crlf" - - def __init__(self, host, port): - asynchat.async_chat.__init__(self) - self.set_terminator('\r\n') - self.buffer = "" - self.obuffer = "" - self.oqueue = Queue.Queue() #where we stick things that need to be sent - self.iqueue = Queue.Queue() #where we stick things that were received - self.create_socket(socket.AF_INET, socket.SOCK_STREAM) - self.socket.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 0) - self.host = host - self.port = port - - def run(self): - self.connect((self.host, self.port)) - asyncore.loop() - - def handle_connect(self): - thread.start_new_thread(self.queue_read_loop, ()) - - def queue_read_loop(self): - while True: - line = self.oqueue.get().splitlines()[0][:500] - print ">>> %r" % line - self.push(line.encode('utf-8', 'replace') + '\r\n') - - def collect_incoming_data(self, data): - self.buffer += data - - def found_terminator(self): - line = self.buffer - self.iqueue.put(decode(line)) - self.buffer = '' - -irc_prefix_rem = re.compile(r'(.*?) (.*?) (.*)').match -irc_noprefix_rem = re.compile(r'()(.*?) (.*)').match -irc_netmask_rem = re.compile(r':?([^!@]*)!?([^@]*)@?(.*)').match -irc_param_ref = re.compile(r'(?:^|(?<= ))(:.*|[^ ]+)').findall - - -class irc(object): - "handles the IRC protocol" - #see the docs/ folder for more information on the protocol - - def __init__(self, network, nick, port=6667): - self.conn = crlf_tcp(network, port) - thread.start_new_thread(self.conn.run, ()) - self.out = Queue.Queue() #responses from the server are placed here - # format: [rawline, prefix, command, params, - # nick, user, host, paramlist, msg] - self.nick(nick) - self.cmd("USER", ["skybot v0.01", "0", "bot"]) - thread.start_new_thread(self.parse_loop, ()) - - def parse_loop(self): - while True: - msg = self.conn.iqueue.get() - if msg.startswith(":"): #has a prefix - prefix, command, params = irc_prefix_rem(msg).groups() - else: - prefix, command, params = irc_noprefix_rem(msg).groups() - nick, user, host = irc_netmask_rem(prefix).groups() - paramlist = irc_param_ref(params) - lastparam = "" - if paramlist and paramlist[-1].startswith(':'): - lastparam = paramlist[-1][1:] - self.out.put([msg, prefix, command, params, nick, user, host, - paramlist, lastparam]) - if command == "PING": - self.cmd("PONG", [params]) - - def nick(self, nick): - self.cmd("NICK", [nick]) - - def join(self, channel): - self.cmd("JOIN", [":"+channel]) - - def msg(self, target, text): - self.cmd("PRIVMSG", [target, ":"+text]) - - def cmd(self, command, params=None): - if params: - self.send(command+' '+' '.join(params)) - else: - self.send(command) - - def send(self, str): - self.conn.oqueue.put(str)