diff --git a/bot.py b/bot.py new file mode 100755 index 0000000..70eb50c --- /dev/null +++ b/bot.py @@ -0,0 +1,113 @@ +#!/usr/bin/python + +network = "irc.synirc.net" +nickname = "skybot" +channel = "#mongbot" + +import sys, os, glob, imp, re +import thread, Queue, copy +import irc, yaml + +os.chdir(sys.path[0]) #do stuff relative to the installation directory + + +class Empty(object): #this is used to store attributes + pass + + +class Bot(object): + def __init__(self): + self.plugins = {} + self.commands = {} + self.listens = {} + self.filters = {} + self.daemons = {} + + def command(self, name, func, **filterargs): + self.commands[name] = (func, filterargs) + + def listen(self, name, func): + self.listens[name] = func + + def filter(self, name, func): + self.filters[name] = func + + def daemon(self, name, func): + self.daemons[name] = func + +bot = Bot() + +print 'Loading plugins' +for filename in glob.glob("plugins/*.py"): + shortname = os.path.splitext(os.path.basename(filename))[0] + try: + bot.plugins[shortname] = imp.load_source(shortname,filename) + except Exception, e: + print e + +print bot.plugins + +print 'Registering plugins' +for name, plugin in bot.plugins.iteritems(): + if hasattr(plugin, 'setup'): + try: + plugin.setup(bot) + except Exception, e: + print e + +print 'Connecting to IRC' + +bot.irc = irc.irc(network, nickname) +bot.irc.join(channel) +bot.commandprefix = '^(?:\.|'+nickname+'[:,]*\s*)' + +if bot.daemons: + print 'Running daemons' + for daemon in bot.daemons.itervalues(): + thread.start_new_thread(daemon, ()) + +print 'Running main loop' + +class Input(object): + def __init__(self, raw, prefix, command, + 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 + +class FakeBot(object): + def __init__(self, bot, input): + self.bot = bot + self.input = input + + def say(self, msg): + self.bot.irc.msg(input.paraml[0], msg) + + def reply(self, msg): + self.say(input.nick + ': ' + msg) + +print bot.commands + +while True: + try: + out = bot.irc.out.get(timeout=1) + #print repr(out) + for func, args in bot.commands.itervalues(): + input = Input(*out) + for filt in bot.filters.itervalues(): + input = filt(bot, func, args, input) + if input == False: + break + if input == False: + continue + thread.start_new_thread(func,(FakeBot(bot, input), input)) + except Queue.Empty: + pass + #except KeyboardInterrupt: + # sys.exit() diff --git a/irc.pyc b/irc.pyc new file mode 100644 index 0000000..55f544e Binary files /dev/null and b/irc.pyc differ diff --git a/plugins/filter.py b/plugins/filter.py new file mode 100644 index 0000000..51102ac --- /dev/null +++ b/plugins/filter.py @@ -0,0 +1,24 @@ +import re + +def setup(bot): + bot.filter("default_filters", filter_suite) + +def filter_suite(bot, func, args, input): + args.setdefault('events', ['PRIVMSG']) + + if input.command not in args['events']: + return False + + args.setdefault('hook', r'(.*)') + args.setdefault('prefix', True) + + hook = args['hook'] + if args['prefix']: + hook = bot.commandprefix + args['hook'] + + m = re.match(hook, input.msg) + if not m: + return False + + input.re = m + return input diff --git a/plugins/weather.py b/plugins/weather.py new file mode 100755 index 0000000..75fe09d --- /dev/null +++ b/plugins/weather.py @@ -0,0 +1,54 @@ +"weather, thanks to google" + +import urllib, re, pickle, os +from xml.dom import minidom + +WEATHER_URL = 'http://www.google.com/ig/api' + +def setup(bot): + bot.command("weather", weather, hook=r"weather (.*)") + +def goog_weather(query): + data = urllib.urlencode({'weather':query}) + url = WEATHER_URL + "?" + data + #print url + dom = minidom.parse(urllib.urlopen(url)) + + if len(dom.getElementsByTagName('problem_cause')): + return {'error': True} + + place = dom.getElementsByTagName('city')[0].getAttribute('data') + temp = dom.getElementsByTagName('temp_f')[0].getAttribute('data') + + conditions = dom.getElementsByTagName('current_conditions')[0] + condition = conditions.getElementsByTagName('condition')[0].getAttribute('data') + wind = conditions.getElementsByTagName('wind_condition')[0].getAttribute('data') + humidity = conditions.getElementsByTagName('humidity')[0].getAttribute('data') + + forecast = dom.getElementsByTagName('forecast_conditions')[0] + high = forecast.getElementsByTagName('high')[0].getAttribute('data') + low = forecast.getElementsByTagName('low')[0].getAttribute('data') + + return { + 'place': place, + 'temp': temp, + 'high': high, + 'low': low, + 'condition': condition, + 'wind': wind, + 'humidity': humidity + } + +def weather(bot, input): + ".weather -- queries google weather API for weather data" + q = input.re.groups()[0] + cond = goog_weather(q) + + if cond.has_key('error'): + bot.reply(u'Couldn\'t fetch weather data for "%s", try using a zip/postal code' % (q)) + return + + format = u'%s %sF (%s/%s/%s) (h:%sF,l:%sF)' + args = (cond['place'],cond['temp'],cond['condition'],cond['wind'],cond['humidity'],cond['high'],cond['low']) + + bot.reply(format.encode('utf-8') % args)