1 # This file is part of Acrobat.
3 # Acrobat is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published
5 # by the Free Software Foundation; either version 2 of the License,
6 # or (at your option) any later version.
8 # Acrobat is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with Acrobat; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 # Andrew Walkingshaw <andrew@lexical.org.uk>
19 # Peter Corbett <ptc24@cam.ac.uk>
20 # Matthew Vernon <matthew@debian.org>
21 # Stephen Early <steve@greenend.org.uk>
22 # Richard Kettlewell <rjk@greenend.org.uk
24 # Acrobat configuration file
26 # The following definitions are required to be present in this module:
32 # Also a function called "command"; see later.
34 # Everything else in this file is configuration-specific.
38 # Most command implementations are stored in a separate module.
41 # This fishpond is shared between trouts and flirts. It doesn't have to be;
42 # you can define as many ponds as you like.
53 # load a file full of flirts or trouts
56 f = open(filename, "r")
57 r = [l.strip() for l in f.readlines() if l.find("%s") != -1]
60 r = [ "doesn't know what to do about %s." ]
63 # (troutlist,selftroutmsg,DoSmsg,notargetmsg,nofishmsg,fishpond,selftroutprob)
66 ' (at the instigation of %s)',
67 "Sorry, but %s is being a spoilsport.",
68 "Who do you wish me to trout?",
69 "Fish stocks exhausted.",
75 ' (but %s is their secret admirer)',
76 "Sorry, but %s made me take Holy Orders.",
77 "Who do you wish me to flirt with?",
78 "My libido is over-used!",
84 ' (while %s watches)',
85 "Sorry, but %s stole my pen.",
86 "Who do you want to slash?",
87 "I have writer's block!",
91 # Hacky command to output the current fishpond state
92 def fishq(bot, cmd, nick, conn, public,f):
93 from irclib import irc_lower
94 if not public and irc_lower(nick) == irc_lower(bot.owner):
95 state=("Fishpond state: cur_fish=%d, max_fish=%d, nofish_time=%d, "
96 +"fish_time_inc=%d, fish_inc=%d, DoS=%d, Boring_Git=%s, "
97 +"quotatime=%d")%(f.cur_fish,f.max_fish,f.nofish_time,
98 f.fish_time_inc,f.fish_inc,f.DoS,f.Boring_Git,
100 bot.automsg(public,nick,state)
102 # Karma implementation
104 karmafilename = "chiark-karma"
107 f = open(karmafilename, "r")
108 karmadb = cPickle.load(f)
113 def karma(cmd, amount):
114 thing=cmd.split()[0][:-2].lower()
115 if karmadb.has_key(thing):
116 karmadb[thing] += amount
118 karmadb[thing] = amount
121 tmp = "%s.tmp" % karmafilename
124 cPickle.dump(karmadb, f)
126 os.rename(tmp, karmafilename)
128 sys.stderr.write("error writing karma: %s" % e)
130 def quit(bot,cmd,nick,conn,public):
131 c.quitq(bot,cmd,nick,conn,public)
132 def reload(bot,cmd,nick,conn,public):
133 c.reloadq(bot,cmd,nick,conn,public)
139 minlose=24*60*60 #1 day
140 maxlose=14*minlose #2 weeks
141 losetime=time.time()+300000
143 def canonical_url(urlstring):
144 # canonicalise BBC URLs
145 if (urlstring.find("news.bbc.co.uk") != -1):
146 for middle in ("/low/","/mobile/"):
147 x = urlstring.find(middle)
149 urlstring.replace(middle,"/hi/")
152 def nicetime(tempus):
154 tm="%d seconds ago"%int(tempus)
156 tm="%d minutes ago"%int(tempus/60)
158 tm="%d hours ago"%int(tempus/3600)
162 urlre = re.compile("(https?://[^ ]+)( |$)")
163 urlcomplaints = [" contemporary","n interesting"," fascinating","n overused"," vastly overused"]
165 def urlq(bot, cmd, nick, conn, public):
166 print "debug: ",bot,cmd,nick,conn,public
167 if (not urlre.search(cmd)):
168 bot.automsg(False,nick,"Please use 'url' only with http URLs")
171 url="".join(cmd.split(" ")[1:])
174 url=canonical_url(url)
177 complaint="The url %s was mentioned %s by %s"%(url,nicetime(time.time()-users[-1][1]),users[-1][0])
179 complaint=complaint+". Furthermore it defeats the point of this command to use it other than via /msg."
180 bot.automsg(False,nick,complaint)
183 bot.automsg(False,nick,"That URL was unique. There is little point in using !url out loud; please use it via /msg")
185 conn.privmsg(bot.channel,"%s would like to draw your attention to %s"%(nick,url))
186 urldb[url]=[[nick,time.time()]]
187 print [bot, cmd, nick, conn]
189 def dourl(bot,conn,nick,command):
190 urlstring=urlre.search(command).group(1)
191 print "dourl: ",urlstring
192 urlstring=canonical_url(urlstring)
194 if urlstring in urldb:
198 if uci >= len(urlcomplaints):
199 uci = len(urlcomplaints)
200 message="observes a"+urlcomplaints[uci-1]+" URL: mentioned by "
205 for t in range(len(T)-1,cutoff,-1):
206 tempus = time.time()-T[t][1]
207 message += T[t][0]+" ("+nicetime(tempus)+")"
211 message += ", amongst others"
212 conn.action(bot.channel, message)
213 urldb[urlstring]=[[nick,time.time()]]+urldb[urlstring]
215 urldb[urlstring]=[[nick,time.time()]]
217 # Command processing: whenever something is said that the bot can hear,
218 # "command" is invoked and must decide what to do. This configuration
219 # defines a couple of special cases (for karma) but is otherwise driven
220 # by a dictionary of commands.
222 commands = {"karma": (c.karmaq,karmadb),
223 "karmalist": (c.listkeysq,karmadb),
224 "karmadel": (c.karmadelq,karmadb),
225 "info": (c.infoq,karmadb),
226 "trout": (c.troutq,troutcfg),
227 "slash": (c.slashq, slashcfg),
229 "fish": (fishq,fish),
230 "flirt": (c.troutq,flirtcfg),
231 "quiet": (c.nofishq,fish),
240 # "game": (c.gameq,game),
243 # disconnect and hop annoy people
244 # "disconnect": c.disconnq,
245 # "hop": c.disconnq }
246 commands["list"]=(c.listkeysq,commands,True)
248 triggers = ("!", "~") # what character should the bot be invoked by:
249 # eg !trout, ~trout etc.
251 def command(bot, cmd, nick, conn, public):
254 if public and cmd[0] in triggers:
259 command = cmd.split()[0]
264 if cmd.find("http") != -1:
265 dourl(bot,conn,nick,cmd)
268 if command.endswith("++"):
271 if command.endswith("--"):
274 if ours and command.lower() in commands.keys():
275 e=commands[command.lower()]
277 e(bot,cmd,nick,conn,public)
279 e[0](bot,cmd,nick,conn,public,*e[1:])
281 # if cmd.find("GAME")!=-1: #someone else lost
282 # grace.grace=time.time()+60*20
283 # elif cmd.find(game.trigger)!=-1 and len(game.trigger)>2: #we lost!
284 # c.gameq(bot,"pad "+game.trigger,bot.owner,conn,False,game)
285 # elif time.time()>game.losetime: #we randomly lost, take new trigger
286 # c.gameq(bot,cmd,bot.owner,conn,False,game)