X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~matthewv/git?p=irc.git;a=blobdiff_plain;f=commands.py;h=38769876bff1ff5a4a730f78f6f95c729952475c;hp=6f6d1f73dc3f5ff265f86a1825d549517b36b557;hb=cc7c72dc4957bce0f434a3434c72f12c02ac00f9;hpb=295d92cb0299714aa2694f4e68992cb5ba53ec91 diff --git a/commands.py b/commands.py old mode 100644 new mode 100755 index 6f6d1f7..3876987 --- a/commands.py +++ b/commands.py @@ -1,98 +1,209 @@ # Part of Acrobat. -import string, cPickle, random, urllib, sys +import string, cPickle, random, urllib, sys, time, re, os, twitter, subprocess, datetime from irclib import irc_lower, nm_to_n # query karma -def karmaq(bot, cmd, nick, conn, public): - # in public - if public == 1: - try: - if bot.karma.dict.has_key(cmd.split()[1]): - conn.privmsg(bot.channel, "%s has karma %s." - %(cmd.split()[1], - bot.karma.dict[cmd.split()[1]])) - else: - conn.privmsg(bot.channel, "%s has no karma set." % - cmd.split()[1]) - except IndexError: - conn.privmsg(bot.channel, "I have karma on %s items." % - len(bot.karma.dict.keys())) - # in private - else: - try: - if bot.karma.dict.has_key(cmd.split()[1]): - conn.notice(nick, "%s has karma %s." % - (cmd.split()[1], - bot.karma.dict[cmd.split()[1]])) - else: - conn.notice(nick, "I have karma on %s items." % - len(bot.karma.dict.keys())) - except IndexError: - conn.notice(nick, "I have karma on %s items." % - len(bot.karma.dict.keys())) -# query bot status -def infoq(bot, cmd, nick, conn, public): - if public == 1: - conn.privmsg(bot.channel, - "I am Acrobat %s, on %s, as nick %s." % - (bot.revision.split()[1], bot.channel, conn.get_nickname())) - conn.privmsg(bot.channel, - "My owner is %s; I have karma on %s items." % - (bot.owner, len(bot.karma.dict.keys()))) +def karmaq(bot, cmd, nick, conn, public, karma): + try: + item=cmd.split()[1].lower() + except IndexError: + item=None + if item==None: + bot.automsg(public,nick,"I have karma on %s items." % + len(karma.keys())) + elif karma.has_key(item): + bot.automsg(public,nick,"%s has karma %s." + %(item,karma[item])) else: - conn.notice(nick, "I am Acrobat %s, on %s, as nick %s." % - (bot.revision.split()[1], bot.channel, conn.get_nickname())) - conn.notice(nick, "My owner is %s; I have karma on %s items." % - (bot.owner, len(bot.karma.dict.keys()))) + bot.automsg(public,nick, "%s has no karma set." % item) -# trout someone -def troutq(bot, cmd, nick, conn, public): +# delete karma +def karmadelq(bot, cmd, nick, conn, public, karma): try: - target = string.join(cmd.split()[1:]) - me = bot.connection.get_nickname() - trout_msg = random.choice(bot.trouts) - # The bot won't trout itself; - if irc_lower(me) == irc_lower(target): - target = nick - conn.action(bot.channel, trout_msg % target) - if public == 0: - if random.random() <= bot.config.selftroutrisk: - conn.action(bot.channel, - "notes %s is conducting a whispering campaign." % nick) + item=cmd.split()[1].lower() except IndexError: - conn.notice(nick, "Who do you wish me to trout?") + conn.notice(nick, "What should I delete?") + return + if nick != bot.owner: + conn.notice(nick, "You are not my owner.") + return + if karma.has_key(item): + del karma[item] + conn.notice(nick, "Item %s deleted."%item) + else: + conn.notice(nick, "There is no karma stored for %s."%item) + +# help - provides the URL of the help file +def helpq(bot, cmd, nick, conn, public): + bot.automsg(public,nick, + "For help see http://www.chiark.greenend.org.uk/~matthewv/irc/servus.html") + + +# query bot status +def infoq(bot, cmd, nick, conn, public, karma): + bot.automsg(public,nick, + ("I am Acrobat %s, on %s, as nick %s. "+ + "My owner is %s; I have karma on %s items.") % + (bot.revision.split()[1], bot.channel, conn.get_nickname(), + bot.owner, len(karma.keys()))) + +# Check on fish stocks +def fish_quota(pond): + if pond.DoS: + if time.time()>=pond.quotatime: + pond.DoS=0 + else: + return + if (time.time()-pond.quotatime)>pond.fish_time_inc: + pond.cur_fish+=(((time.time()-pond.quotatime) + /pond.fish_time_inc)*pond.fish_inc) + if pond.cur_fish>pond.max_fish: + pond.cur_fish=pond.max_fish + pond.quotatime=time.time() + +# List of things the bot might be called to work round the self-trouting code +synonyms=["itself","the bot","themself"] + +# trout someone, or flirt with them +def troutq(bot, cmd, nick, conn, public, cfg): + fishlist=cfg[0] + selftrout=cfg[1] + quietmsg=cfg[2] + notargetmsg=cfg[3] + nofishmsg=cfg[4] + fishpond=cfg[5] + selftroutchance=cfg[6] + + fish_quota(fishpond) + if fishpond.DoS: + conn.notice(nick, quietmsg%fishpond.Boring_Git) + return + if fishpond.cur_fish<=0: + conn.notice(nick, nofishmsg) + return + target = string.join(cmd.split()[1:]) + if len(target)==0: + conn.notice(nick, notargetmsg) + return + me = bot.connection.get_nickname() + trout_msg = random.choice(fishlist) + fishpond.last=trout_msg + # The bot won't trout or flirt with itself; + if irc_lower(me) == irc_lower(target) or irc_lower(target) in synonyms: + target = nick + # There's a chance the game may be given away if the request was not + # public... + if not public: + if random.random()<=selftroutchance: + trout_msg=trout_msg+(selftrout%nick) + + conn.action(bot.channel, trout_msg % target) + fishpond.cur_fish-=1 + +# slash a pair +def slashq(bot, cmd, nick, conn, public, cfg): + fishlist=cfg[0] + selfslash=cfg[1] + quietmsg=cfg[2] + notargetmsg=cfg[3] + nofishmsg=cfg[4] + fishpond=cfg[5] + selfslashchance=cfg[6] + + fish_quota(fishpond) + if fishpond.DoS: + conn.notice(nick, quietmsg%fishpond.Boring_Git) + return + if fishpond.cur_fish<=0: + conn.notice(nick, nofishmsg) + return + target = string.join(cmd.split()[1:]) + #who = cmd.split()[1:] + who = ' '.join(cmd.split()[1:]).split(' / ') + if len(who) < 2: + conn.notice(nick, "it takes two to tango!") + return + elif len(who) > 2: + conn.notice(nick, "we'll have none of that round here") + return + me = bot.connection.get_nickname() + slash_msg = random.choice(fishlist) + fishpond.last=slash_msg + # The bot won't slash people with themselves + if irc_lower(who[0]) == irc_lower(who[1]): + conn.notice(nick, "oooooh no missus!") + return + # The bot won't slash with itself, instead slashing the requester + for n in [0,1]: + if irc_lower(me) == irc_lower(who[n]) or irc_lower(who[n]) in synonyms: + who[n] = nick + # Perhaps someone asked to slash themselves with the bot then we get + if irc_lower(who[0]) == irc_lower(who[1]): + conn.notice(nick, "you wish!") + return + # There's a chance the game may be given away if the request was not + # public... + if not public: + if random.random()<=selfslashchance: + slash_msg=slash_msg+(selfslash%nick) + + conn.action(bot.channel, slash_msg % (who[0], who[1])) + fishpond.cur_fish-=1 + +#query units +def unitq(bot, cmd, nick, conn, public): + args = ' '.join(cmd.split()[1:]).split(' as ') + if len(args) != 2: + args = ' '.join(cmd.split()[1:]).split(' / ') + if len(args) != 2: + conn.notice(nick, "syntax: units arg1 as arg2") + return + if args[1]=='?': + sin,sout=os.popen4(["units","--verbose","--",args[0]],"r") + else: + sin,sout=os.popen4(["units","--verbose","--",args[0],args[1]],"r") + sin.close() + res=sout.readlines() + #popen2 doesn't clean up the child properly. Do this by hand + child=os.wait() + if os.WEXITSTATUS(child[1])==0: + bot.automsg(public,nick,res[0].strip()) + else: + conn.notice(nick,'; '.join(map(lambda x: x.strip(),res))) + +# Shut up trouting for a minute +def nofishq(bot, cmd, nick, conn, public, fish): + fish.cur_fish=0 + fish.DoS=1 + fish.Boring_Git=nick + fish.quotatime=time.time() + fish.quotatime+=fish.nofish_time + conn.notice(nick, "Fish stocks depleted, as you wish.") # rehash bot config def reloadq(bot, cmd, nick, conn, public): - if irc_lower(nick) == irc_lower(bot.owner): + if not public and irc_lower(nick) == irc_lower(bot.owner): try: reload(bot.config) - bot.trouts = bot.config.trouts - conn.privmsg(nick, "Config reloaded.") + conn.notice(nick, "Config reloaded.") except ImportError: conn.notice(nick, "Config reloading failed!") else: - conn.notice(nick, "This command can only be invoked by my owner.") + bot.automsg(public,nick, + "Configuration can only be reloaded by my owner, by /msg.") # quit irc def quitq(bot, cmd, nick, conn, public): if irc_lower(nick) == irc_lower(bot.owner): - try: - f = open(bot.karmafilename, "w") - cPickle.dump(bot.karma, f) - f.close() - except IOError: - sys.stderr.write("Problems dumping karma: probably lost :(") bot.die(msg = "I have been chosen!") - elif public == 1: - conn.privmsg(nick, "Such aggression in public!") + elif public: + conn.notice(nick, "Such aggression in public!") else: conn.notice(nick, "You're not my owner.") # google for something def googleq(bot, cmd, nick, conn, public): cmdrest = string.join(cmd.split()[1:]) - #sys.stderr.write(conn) # "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)) @@ -100,40 +211,314 @@ def googleq(bot, cmd, nick, conn, public): # 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)) + bot.automsg(public,nick,str(gsearch)) + else: # we haven't found anything. + bot.automsg(public,nick,"No pages found.") + except IOError: # if the connection times out. This blocks. :( + bot.automsg(public,nick,"The web's broken. Waah!") + +# Look up the definition of something using google +def defineq(bot, cmd, nick, conn, public): + #this doesn't work any more + bot.automsg(public,nick,"'define' is broken because google are bastards :(") + return + cmdrest = string.join(cmd.split()[1:]) + targ = ("http://www.google.co.uk/search?q=define%%3A%s&ie=utf-8&oe=utf-8" + % urllib.quote_plus(cmdrest)) + try: + # Just slurp everything into a string + defnpage = urllib.urlopen(targ).read() + # For definitions we really do have to parse the HTML, sadly. + # This is of course going to be a bit fragile. We first look for + # 'Definitions of %s on the Web' -- if this isn't present we + # assume we have the 'no definitions found page'. + # The first defn starts after the following

tag, but as the + # first

  • in a