h/bot.py

163 lines
4.2 KiB
Python
Raw Normal View History

2008-06-09 11:59:56 +00:00
#!/usr/bin/python
2009-03-15 06:51:39 +00:00
network = "irc.synirc.net"
nick = "skybot"
channel = "#cobol"
2008-06-09 11:59:56 +00:00
2009-03-15 03:06:36 +00:00
import sys
import os
import glob
import re
import thread
import Queue
import collections
2008-06-09 11:59:56 +00:00
sys.path += ['plugins'] # so 'import hook' works without duplication
2009-03-15 03:06:36 +00:00
import irc
import yaml
2008-06-09 11:59:56 +00:00
2009-03-16 04:51:06 +00:00
os.chdir(sys.path[0]) # do stuff relative to the installation directory
2008-06-09 11:59:56 +00:00
2008-06-09 11:59:56 +00:00
class Bot(object):
2009-03-15 20:04:02 +00:00
def __init__(self, nick, channel, network):
self.nick = nick
self.channel = channel
self.network = network
2008-06-09 11:59:56 +00:00
2009-03-15 20:04:02 +00:00
bot = Bot(nick, channel, network)
2008-06-09 11:59:56 +00:00
print 'Loading plugins'
2009-03-15 04:14:07 +00:00
plugin_mtimes = {}
def reload_plugins():
if not hasattr(bot, 'plugs'):
bot.plugs = collections.defaultdict(lambda: [])
for filename in glob.glob("core/*.py") + glob.glob("plugins/*.py"):
mtime = os.stat(filename).st_mtime
if mtime != plugin_mtimes.get(filename):
try:
code = compile(open(filename, 'U').read(), filename, 'exec')
2009-04-18 01:34:16 +00:00
namespace = {}
eval(code, namespace)
except Exception, e:
print ' error:', e
continue
# remove plugins already loaded from this filename
for name, data in bot.plugs.iteritems():
bot.plugs[name] = filter(lambda x: x[0][0] != filename, data)
2009-03-15 04:14:07 +00:00
2009-04-18 01:34:16 +00:00
for obj in namespace.itervalues():
if hasattr(obj, '_skybot_hook'): #check for magic
for type, data in obj._skybot_hook:
bot.plugs[type] += [data]
2009-03-15 04:14:07 +00:00
plugin_mtimes[filename] = mtime
2009-03-15 04:14:07 +00:00
reload_plugins()
2008-06-09 11:59:56 +00:00
print ' plugin listing:'
for type, plugs in sorted(bot.plugs.iteritems()):
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
2008-06-09 11:59:56 +00:00
print 'Connecting to IRC'
2009-03-15 06:51:39 +00:00
bot.irc = irc.irc(network, nick)
2008-06-09 11:59:56 +00:00
bot.irc.join(channel)
2009-04-03 03:50:38 +00:00
bot.persist_dir = os.path.abspath('persist')
2008-06-09 11:59:56 +00:00
print 'Running main loop'
2008-06-09 11:59:56 +00:00
class Input(object):
def __init__(self, raw, prefix, command,
2008-06-09 11:59:56 +00:00
params, nick, user, host, paraml, msg):
self.raw = raw
self.prefix = prefix
self.command = command
self.params = params
self.nick = nick
self.user = user
self.host = host
self.paraml = paraml
self.msg = msg
2009-04-03 03:50:38 +00:00
if command == "PRIVMSG":
if paraml[0] != bot.nick:
self.chan = paraml[0]
else:
self.chan = nick
2009-04-17 21:54:11 +00:00
else:
self.chan = ""
2008-06-09 11:59:56 +00:00
2008-06-09 11:59:56 +00:00
class FakeBot(object):
def __init__(self, bot, input, func):
2008-06-09 11:59:56 +00:00
self.bot = bot
2009-04-03 03:50:38 +00:00
self.persist_dir = bot.persist_dir
2009-04-17 21:54:11 +00:00
self.network = bot.network
2008-06-09 11:59:56 +00:00
self.input = input
2009-03-15 03:06:36 +00:00
self.msg = bot.irc.msg
self.cmd = bot.irc.cmd
2009-03-15 06:51:39 +00:00
self.join = bot.irc.join
2009-03-15 03:06:36 +00:00
self.func = func
2009-03-15 06:51:39 +00:00
self.doreply = True
2009-04-17 21:54:11 +00:00
self.chan = input.chan
2009-03-15 06:51:39 +00:00
2008-06-09 11:59:56 +00:00
def say(self, msg):
self.bot.irc.msg(self.chan, msg)
2008-06-09 11:59:56 +00:00
def reply(self, msg):
2009-03-15 04:14:07 +00:00
self.say(self.input.nick + ': ' + msg)
2008-06-09 11:59:56 +00:00
2009-03-15 03:06:36 +00:00
def run(self):
ac = self.func.func_code.co_argcount
if ac == 2:
out = self.func(self, self.input)
elif ac == 1:
out = self.func(self.input.inp)
2009-03-15 03:06:36 +00:00
if out is not None:
2009-03-15 04:14:07 +00:00
if self.doreply:
self.reply(unicode(out))
else:
self.say(unicode(out))
2009-03-15 03:06:36 +00:00
2008-06-09 11:59:56 +00:00
while True:
try:
2008-06-09 11:59:56 +00:00
out = bot.irc.out.get(timeout=1)
2009-03-15 04:14:07 +00:00
reload_plugins()
2009-04-17 21:54:11 +00:00
printed = False
for csig, func, args in (bot.plugs['command'] + bot.plugs['event']):
2008-06-09 11:59:56 +00:00
input = Input(*out)
for fsig, sieve in bot.plugs['sieve']:
2009-03-25 04:45:33 +00:00
try:
input = sieve(bot, input, func, args)
except Exception, e:
print 'filter error:', e
input = None
2009-03-15 03:06:36 +00:00
if input == None:
2008-06-09 11:59:56 +00:00
break
2009-03-15 03:06:36 +00:00
if input == None:
2009-03-15 04:14:07 +00:00
continue
2009-04-17 21:54:11 +00:00
if not printed:
print '<<<', input.raw
printed = True
thread.start_new_thread(FakeBot(bot, input, func).run, ())
2008-06-09 11:59:56 +00:00
except Queue.Empty:
pass