firebot/contrib/bindingsbot.py

112 lines
3.1 KiB
Python

import irc
import re
import random
import types
import os
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
info = []
while 1:
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))
tb = tb.tb_next
if not tb:
break
del tb # just to be safe
infostr = '[' + '] ['.join(info) + ']'
self.last_tb = '%s %s %s' % (t, v, infostr)
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.',)