--- /dev/null
+#!/usr/local/bin/python
+#
+# Joel Rosdahl <joel@rosdahl.net>
+# Andrew Walkingshaw <andrew@lexical.org.uk>
+#
+# This file is part of Acrobat.
+#
+# Acrobat is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 2 of the License,
+# or (at your option) any later version.
+#
+# Foobar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with Foobar; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+
+"""
+ disconnect -- Disconnect the bot. The bot will try to reconnect
+ after 60 seconds.
+
+ die -- Let the bot cease to exist.
+
+ google -- search, 'I'm Feeling Lucky', and notice the user who searches
+ back with the url.
+"""
+
+import string, urllib, sys, cPickle, os
+from ircbot import SingleServerIRCBot
+from irclib import nm_to_n, irc_lower
+
+class Karma:
+ def __init__(self):
+ self.dict = {}
+
+class Acrobat(SingleServerIRCBot):
+ def __init__(self, channel, nickname, server, owner, port=6667):
+ SingleServerIRCBot.__init__(self,
+ [(server, port)], nickname, nickname)
+ self.channel = channel
+ self.owner = owner
+ # load the karma db
+ try:
+ f = open("karmadump", "r")
+ self.karma = cPickle.load(f)
+ f.close()
+ except IOError:
+ self.karma = Karma()
+
+ ## EVENT HANDLERS
+
+ def on_welcome(self, conn, evt):
+ conn.join(self.channel)
+
+ def on_privmsg(self, conn, evt):
+ self.do_command(nm_to_n(evt.source()), evt.arguments()[0])
+
+ def on_pubmsg(self, conn, evt):
+ payload = evt.arguments()[0]
+ a = string.split(evt.arguments()[0], " ", 1)
+ if len(a) > 1 \
+ and (irc_lower(a[0]) == irc_lower(self.connection.get_nickname())
+ or irc_lower(a[0])[:-1] == irc_lower(self.connection.get_nickname())):
+
+ self.do_command(self.channel, string.strip(a[1]), public = 1)
+ if a[0].endswith("++"):
+ self.karmaup(a[0])
+ if a[0].endswith("--"):
+ self.karmadown(a[0])
+ if payload[0] == "!" and len(payload)>1:
+ self.do_command(self.channel, string.strip(payload[1:]), public=1)
+ if payload[0] == "~" and len(payload)>1:
+ self.do_command(self.channel, string.strip(payload[1:]), public=1)
+
+ # And now bot commands;
+
+ # increment karma
+ def karmaup(self, cmd):
+ if self.karma.dict.has_key(cmd.split()[0][:-2]):
+ self.karma.dict[cmd.split()[0][:-2]] += 1
+ else:
+ self.karma.dict[cmd.split()[0][:-2]] = 1
+
+ #decrement karma
+ def karmadown(self, cmd):
+ if self.karma.dict.has_key(cmd.split()[0][:-2]):
+ self.karma.dict[cmd.split()[0][:-2]] -= 1
+ else:
+ self.karma.dict[cmd.split()[0][:-2]] = -1
+
+ # query karma
+ def karmaq(self, cmd, conn, nick, public):
+ # in public
+ if public == 1:
+ try:
+ if self.karma.dict.has_key(cmd.split()[1]):
+ conn.privmsg(self.channel, "%s has karma %s."
+ %(cmd.split()[1],
+ self.karma.dict[cmd.split()[1]]))
+ else:
+ conn.privmsg(self.channel, "%s has no karma set." %
+ cmd.split()[1])
+ except IndexError:
+ conn.privmsg(self.channel, "I have karma on %s items." %
+ len(self.karma.dict.keys()))
+ # in private
+ else:
+ try:
+ if self.karma.dict.has_key(cmd.split()[1]):
+ conn.notice(nick, "%s has karma %s." %
+ (cmd.split()[1],
+ self.karma.dict[cmd.split()[1]]))
+ else:
+ conn.notice(nick, "I have karma on %s items." %
+ len(self.karma.dict.keys()))
+ except IndexError:
+ conn.notice(nick, "I have karma on %s items." %
+ len(self.karma.dict.keys()))
+ # query bot status
+ def infoq(self, cmd, nick, conn, public):
+ if public == 1:
+ conn.privmsg(self.channel,
+ "I am Acrobat 0.2chiark, on %s, as nick %s." %
+ (self.channel, self.connection.get_nickname()))
+ conn.privmsg(self.channel,
+ "My owner is %s; I have karma on %s items." %
+ (self.owner, len(self.karma.dict.keys())))
+ else:
+ conn.notice(nick, "I am Acrobat 0.2chiark, on %s, as nick %s." %
+ (self.channel, self.connection.get_nickname()))
+ conn.notice(nick, "My owner is %s; I have karma on %s items." %
+ (self.owner, len(self.karma.dict.keys())))
+
+ # quit irc
+ def quit(self, cmd, nick, conn, public):
+ if irc_lower(nick) == irc_lower(self.owner):
+ f = open("karmadump", "w")
+ cPickle.dump(self.karma, f)
+ f.close()
+ self.die(msg="I have been chosen!")
+ elif public == 1:
+ conn.privmsg(nick, "Such aggression in public!")
+ else:
+ conn.notice(nick, "You're not my owner.")
+
+ # google for something
+ def googleq(self, cmd, nick, conn, public):
+ cmdrest = string.join(cmd.split()[1:])
+ # "I'm Feeling Lucky" rather than try and parse the html
+ targ = ("http://www.google.com/search?q=%s&btnI=I'm+Feeling+Lucky"
+ % urllib.quote_plus(cmdrest))
+ try:
+ # get redirected and grab the resulting url for returning
+ gsearch = urllib.urlopen(targ).geturl()
+ if gsearch != targ: # we've found something
+ if public == 0:
+ conn.notice(nick, str(gsearch))
+ else: # we haven't found anything.
+ conn.privmsg(nick, str(gsearch))
+ else:
+ if public == 0:
+ conn.notice(nick, "No pages found.")
+ else:
+ conn.privmsg(nick, "No pages found.")
+ except IOError: # if the connection times out. This blocks. :(
+ if public == 0:
+ conn,notice(nick, "The web's broken. Waah!")
+ else:
+ conn.privmsg(nick, "The web's broken. Waah!")
+
+ # General query handler
+ def do_command(self, nick, cmd, public=0):
+ conn = self.connection
+ # karma: up
+ if cmd.split()[0].endswith("++"):
+ self.karmaup(cmd)
+
+ # karma: down
+ if cmd.split()[0].endswith("--"):
+ self.karmadown(cmd)
+
+ # karma: query
+ if cmd.split()[0] == "karma" or cmd.split()[0] == "Karma":
+ self.karmaq(cmd, conn, nick, public)
+
+ # bot's vital statistics
+ if cmd == "info":
+ self.infoq(cmd, nick, conn, public)
+
+ #disconnect
+ if cmd == "disconnect": # hop off for 60s
+ self.disconnect(msg="Be right back.")
+
+ # say to msg/channel
+ elif cmd.split()[0] == "say" \
+ and irc_lower(nick) == irc_lower(self.owner):
+ conn.privmsg(self.channel, string.join(cmd.split()[1:]))
+
+ # action to msg/channel
+ elif cmd.split()[0] == "do" \
+ and irc_lower(nick) == irc_lower(self.owner):
+ conn.action(self.channel, string.join(cmd.split()[1:]))
+
+ # quit IRC
+ elif cmd == "die":
+ self.quit(cmd, nick, conn, public)
+
+ # Google!
+ elif (cmd.split()[0] == "google" or cmd.split()[0] == "Google"):
+ self.googleq(cmd, nick, conn, public)
+
+def main():
+ if len(sys.argv) != 5: # insufficient arguments
+ print "Usage: acrobat <server[:port]> <channel> <nickname> owner"
+ sys.exit(1)
+ sv_port = string.split(sys.argv[1], ":", 1) # tuple; (server, port)
+ server = sv_port[0]
+ if len(sv_port) == 2:
+ try:
+ port = int(sv_port[1])
+ except ValueError:
+ print "Error: Erroneous port."
+ sys.exit(1)
+ else:
+ port = 6667 # default irc port
+ channel = sys.argv[2]
+ nickname = sys.argv[3]
+ owner = sys.argv[4]
+ # initialize the bot
+ bot = Acrobat(channel, nickname, server, owner, port)
+ sys.stderr.write("Trying to connect...\n")
+ # and the event loop
+ bot.start()
+
+if __name__ == "__main__":
+ main()