2007-08-24 10:57:29 -06:00
|
|
|
import irc
|
|
|
|
import re
|
|
|
|
import random
|
|
|
|
import types
|
2008-03-27 16:57:17 -06:00
|
|
|
import os
|
2007-08-24 10:57:29 -06:00
|
|
|
|
|
|
|
class Match:
|
|
|
|
"""A wrapper around a regex match, to replace \008 with a word.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, m, txt):
|
|
|
|
self.m = m
|
|
|
|
self.txt = txt
|
|
|
|
|
|
|
|
def group(self, grp):
|
|
|
|
g = self.m.group(grp)
|
|
|
|
if g:
|
|
|
|
g = g.replace('\008', self.txt)
|
|
|
|
return g
|
|
|
|
|
|
|
|
|
|
|
|
class BindingsBot(irc.Bot):
|
|
|
|
"""An IRC bot with regex function bindings
|
|
|
|
|
|
|
|
You can bind functions to things said in the channel by regular
|
|
|
|
expression with this. See wouldmatch for an example of how to do
|
|
|
|
this.
|
|
|
|
"""
|
|
|
|
|
|
|
|
msg_cat = {} # message catalog
|
|
|
|
bindings = [] # function/catalog bindings to regexen
|
|
|
|
|
|
|
|
def __init__(self, *gar):
|
|
|
|
irc.Bot.__init__(self, *gar)
|
|
|
|
self.last_tb = "Nothing's gone wrong yet!"
|
|
|
|
|
|
|
|
def err(self, exception):
|
|
|
|
"""Save the traceback for later inspection"""
|
|
|
|
irc.Bot.err(self, exception)
|
|
|
|
t,v,tb = exception
|
2008-03-27 16:57:17 -06:00
|
|
|
info = []
|
2007-08-24 10:57:29 -06:00
|
|
|
while 1:
|
2008-03-27 16:57:17 -06:00
|
|
|
info.append('%s:%d(%s)' % (os.path.basename(tb.tb_frame.f_code.co_filename),
|
|
|
|
tb.tb_lineno,
|
|
|
|
tb.tb_frame.f_code.co_name))
|
2007-08-24 10:57:29 -06:00
|
|
|
tb = tb.tb_next
|
|
|
|
if not tb:
|
|
|
|
break
|
2008-03-27 16:57:17 -06:00
|
|
|
del tb # just to be safe
|
|
|
|
infostr = '[' + '] ['.join(info) + ']'
|
|
|
|
self.last_tb = '%s %s %s' % (t, v, infostr)
|
2007-08-24 10:57:29 -06:00
|
|
|
print self.last_tb
|
|
|
|
|
|
|
|
def matches(self, text):
|
|
|
|
matches = []
|
|
|
|
btext = text.replace(self.nick, '\008')
|
|
|
|
for b in self.bindings:
|
|
|
|
m = b[0].match(btext)
|
|
|
|
if m:
|
|
|
|
matches.append((m, b))
|
|
|
|
return matches
|
|
|
|
|
|
|
|
def cmd_privmsg(self, sender, forum, addl):
|
|
|
|
for m, b in self.matches(addl[0]):
|
|
|
|
f = b[1]
|
|
|
|
if callable(f):
|
|
|
|
cont = f(self, sender, forum, addl, Match(m, self.nick))
|
|
|
|
elif type(f) == types.StringType:
|
|
|
|
forum.msg(self.gettext(f, sender=sender.name(),
|
|
|
|
forum=forum.name(), me=self.nick))
|
|
|
|
cont = False
|
|
|
|
else:
|
|
|
|
raise ValueError("Can't handle type of %s", `f`)
|
|
|
|
if not cont:
|
|
|
|
break
|
|
|
|
|
|
|
|
def gettext(self, msg, **dict):
|
|
|
|
"""Format a message from the message catalog.
|
|
|
|
|
|
|
|
Retrieve from the message catalog the message specified by msg,
|
|
|
|
filling in arguments as specified by dict.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
m = random.choice(self.msg_cat[msg])
|
|
|
|
return m % dict
|
|
|
|
|
|
|
|
def tbinfo(self, sender, forum, addl, match):
|
|
|
|
forum.msg(self.last_tb)
|
|
|
|
bindings.append((re.compile(r"^\008[,: ]+(tbinfo|traceback)$"),
|
|
|
|
tbinfo))
|
|
|
|
|
|
|
|
def wouldmatch(self, sender, forum, addl, match):
|
|
|
|
"""Show what binding would be matched"""
|
|
|
|
|
|
|
|
text = match.group(1)
|
|
|
|
matches = self.matches(text)
|
|
|
|
m = [i[1][1] for i in matches]
|
|
|
|
forum.msg('%s => %s' % (`text`, `m`))
|
|
|
|
bindings.append((re.compile(r"^\008[,: ]+match (.+)$"),
|
|
|
|
wouldmatch))
|
|
|
|
|
|
|
|
#
|
|
|
|
# Message catalog
|
|
|
|
#
|
|
|
|
|
|
|
|
msg_cat['okay'] = ('Okay, %(sender)s.',)
|
|
|
|
|
|
|
|
|
|
|
|
|