]> gitweb.pimeys.fr Git - bots/deconnaisseur.git/blob - backup/dummy/deconnaisseur.py
e0a50936dccfdb0fb43b7d686f6523dd7fd09834
[bots/deconnaisseur.git] / backup / dummy / deconnaisseur.py
1 #!/usr/bin/python
2 # -*- coding:utf8 -*-
3
4 # Codé par 20-100 le 23/04/12
5
6 # Un bot IRC qui sort des déconnaissances
7
8 import irclib
9 import ircbot
10 import threading
11 import random
12 import time
13 import pickle
14 import re
15
16 config_password="PatrickSébastien"
17 config_pseudo="deconnaisseur"
18 config_chanlist=["#bot","#flood"]
19 config_play_channels=["#flood"]
20 config_stay_channels=["#flood","#bot"]
21 config_overops=["[20-100]","[20-100]_","PEB"]
22 config_ops=["Nit","Eguel","Harry"]
23
24 config_source_file_template="deconnaissances.%s.txt" #il faut rajouter le nom du serveur
25 def get_config_source_file(serveur):
26 serveurs={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
27 return config_source_file_template%(serveurs[serveur])
28 ttrig=120 #time trigger (normalement 120, mais diminué pour les tests)
29 Ttrig=600 #between two enigms
30 config_time_incompressible=60 #on peut pas retrigger en dessous de ce temps (60)
31 config_time_incompressible_clue=60 #on peut pas forcer la demande d'indice en dessous
32
33
34 class UnicodeBotError(Exception):
35 pass
36 def bot_unicode(chain):
37 try:
38 unicode(chain,"utf8")
39 except UnicodeDecodeError:
40 raise UnicodeBotError
41
42 def log(channel,auteur=None,message=None):
43 #f=open(config_logfile,"a")
44 #if auteur==message==None:
45 # chain=channel
46 #else:
47 # chain="%s [%s:%s] %s"%(time.strftime("%T"),channel,auteur,message)
48 #f.write(chain+"\n")
49 #print chain
50 #f.close()
51 a=0 # does nothing
52
53
54 def tolere(regexp):
55 """Renvoie une regexp plus tolérante"""
56 reg=unicode(regexp,"utf8").lower()
57 reg=reg.replace(u"á",u"(á|a)").replace(u"à",u"(à|a)").replace(u"â",u"(â|a)").replace(u"ä",u"(ä|a)")
58 reg=reg.replace(u"é",u"(é|e)").replace(u"è",u"(è|e)").replace(u"ê",u"(ê|e)").replace(u"ë",u"(ë|e)")
59 reg=reg.replace(u"í",u"(í|i)").replace(u"ì",u"(ì|i)").replace(u"î",u"(î|i)").replace(u"ï",u"(ï|i)")
60 reg=reg.replace(u"ó",u"(ó|o)").replace(u"ò",u"(ò|o)").replace(u"ê",u"(ô|o)").replace(u"ö",u"(ö|o)")
61 reg=reg.replace(u"ú",u"(ú|u)").replace(u"ù",u"(ù|u)").replace(u"ê",u"(û|u)").replace(u"ü",u"(ü|u)")
62 reg=reg.replace(u"ý",u"(ý|y)").replace(u"ỳ",u"(ỳ|y)").replace(u"ê",u"(ŷ|y)").replace(u"ÿ",u"(ÿ|y)")
63 reg=reg.replace(u"œ",u"(œ|oe)").replace(u"æ",u"(æ|ae)")
64 return reg
65
66 class RefuseError(Exception):
67 pass
68
69 class Deconnaisseur(ircbot.SingleServerIRCBot):
70 def __init__(self,serveur,debug=False):
71 temporary_pseudo=config_pseudo+str(random.randrange(10000,100000))
72 ircbot.SingleServerIRCBot.__init__(self, [(serveur, 6667)],
73 temporary_pseudo,"Un bot irc.[flagellez 20-100, il le mérite]", 10)
74 self.debug=debug
75 self.serveur=serveur
76 self.overops=config_overops
77 self.ops=self.overops+config_ops
78 self.chanlist=config_chanlist
79 self.stay_channels=config_stay_channels
80 self.play_channels=config_play_channels
81 self.play_status={i:[0] for i in self.play_channels}
82
83 def give_me_my_pseudo(self,serv):
84 serv.privmsg("NickServ","RECOVER %s %s"%(config_pseudo,config_password))
85 serv.privmsg("NickServ","RELEASE %s %s"%(config_pseudo,config_password))
86 time.sleep(0.3)
87 serv.nick(config_pseudo)
88
89 def on_welcome(self, serv, ev):
90 self.give_me_my_pseudo(serv)
91 serv.privmsg("NickServ","identify %s"%(config_password))
92 log("Connected")
93 if self.debug:
94 self.chanlist=["#bot"]
95 self.play_channels=["#bot"]
96 for c in self.chanlist:
97 log("JOIN %s"%(c))
98 serv.join(c)
99 for c in self.play_channels:
100 token=time.time()-3600
101 self.play_status[c]=[0,token]
102 serv.execute_delayed(random.randrange(ttrig),self.start_enigme,(serv,c,token))
103
104 def start_enigme(self,serv,channel,token=None):
105 if self.play_status[channel][0]==0 and channel in self.play_channels:
106 ok="skip"
107 if token==self.play_status[channel][-1]:
108 ok="do_it"
109 if token==None:
110 if time.time() > self.play_status[channel][-1]+config_time_incompressible:
111 ok="do_it"
112 else:
113 ok="refuse"
114 if ok=="do_it":
115 enigme,indice,answer_reg,answer=self.get_enigme()
116 print "%s; %s; %s; %s"%(enigme, indice, answer_reg, answer)
117 serv.privmsg(channel,enigme)
118 token=time.time()
119 self.play_status[channel]=[1,enigme,indice,answer_reg,answer,token]
120 serv.execute_delayed(random.randrange(ttrig*3,ttrig*5),self.give_indice,(serv,channel,token))
121 elif ok=="refuse":
122 raise RefuseError
123 def give_indice(self,serv,channel,token):
124 if self.play_status[channel][0]==1:
125 if token==None:
126 # c'est donc que l'indice a été demandé
127 if self.play_status[channe][-1]+config_time_incompressible_clue<time.time():
128 token=self.play_status[channel][-1]
129 if self.play_status[channel][-1]==token:
130 indice=self.play_status[channel][2]
131 serv.privmsg(channel,"indice : %s"%(indice))
132 self.play_status[channel][0]=2
133 serv.execute_delayed(random.randrange(ttrig*1,ttrig*3),self.give_answer,(serv,channel,token))
134 def give_answer(self,serv,channel,token):
135 if self.play_status[channel][0]==2 and self.play_status[channel][-1]==token:
136 answer=self.play_status[channel][4]
137 serv.privmsg(channel,"C'était : %s"%(answer))
138 token=time.time()
139 self.play_status[channel]=[0,token]
140 serv.execute_delayed(random.randrange(Ttrig*5,Ttrig*10),self.start_enigme,(serv,channel,token))
141
142 def get_enigme(self):
143 f=open(get_config_source_file(self.serveur))
144 t=f.read()
145 l=re.findall("%\n(.*)\n(.*)\n(.*)\n(.*)\n(.*)\n",t)
146 l=[list(i) for i in l if len(i)==5]
147 l.sort(lambda x,y: cmp(int(x[4]),int(y[4])))
148 # on récupère le nombre d'occurrences le plus faible
149 mini=l[0][4]
150 # on garde que ceux qui ont le même nombre d'occurrences
151 l_mini=[en for en in l if en[4]==mini]
152 # on tire au hasard dedans
153 choisi=random.randrange(len(l_mini))
154 enigme,indice,answer_reg,answer,_=l_mini[choisi]
155 real_index=l.index(l_mini[choisi])
156 l[real_index][4]=str(int(l[real_index][4])+1)
157 f=open(get_config_source_file(self.serveur),"w")
158 f.write("%\n"+"\n%\n".join(["%s\n%s\n%s\n%s\n%s"%(i[0],i[1],i[2],i[3],i[4]) for i in l])+"\n%")
159 f.close()
160 return enigme,indice,answer_reg,answer
161
162 def pourmoi(self, serv, message):
163 pseudo=serv.get_nickname()
164 size=len(pseudo)
165 if message[:size]==pseudo and message[size]==":":
166 return (True,message[size+1:].strip(" "))
167 else:
168 return (False,message)
169
170 def on_privmsg(self, serv, ev):
171 message=ev.arguments()[0]
172 auteur = irclib.nm_to_n(ev.source())
173 try:
174 test=bot_unicode(message)
175 except UnicodeBotError:
176 serv.privmsg(auteur,
177 "Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…")
178 return
179 message=message.split()
180 cmd=message[0].lower()
181 notunderstood=False
182 if cmd=="help":
183 helpmsg_default="""Liste des commandes :
184 HELP Affiche ce message d'aide"""
185 helpmsg_ops="""
186 JOIN Faire rejoindre un channel (sans paramètres, donne la liste des chans actuels)
187 LEAVE Faire quitter un channel
188 PLAY Passe un channel en mode "jouer"
189 NOPLAY Passe un channel en mode "ne pas jouer" """
190 helpmsg_overops="""
191 SAY Fais envoyer un message sur un chan ou à une personne
192 STAY Ignorera les prochains LEAVE pour un chan
193 NOSTAY Opposé de STAY
194 STATUS Montre l'état courant
195 DIE Mourir"""
196 helpmsg=helpmsg_default
197 if auteur in self.ops:
198 helpmsg+=helpmsg_ops
199 if auteur in self.overops:
200 helpmsg+=helpmsg_overops
201 for ligne in helpmsg.split("\n"):
202 serv.privmsg(auteur,ligne)
203 elif cmd=="join":
204 if auteur in self.ops:
205 if len(message)>1:
206 if message[1] in self.chanlist:
207 serv.privmsg(auteur,"Je suis déjà sur %s"%(message[1]))
208 else:
209 serv.join(message[1])
210 self.chanlist.append(message[1])
211 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
212 log("priv",auteur," ".join(message))
213 else:
214 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
215 else:
216 notunderstood=True
217 elif cmd=="leave":
218 if auteur in self.ops and len(message)>1:
219 if message[1] in self.chanlist:
220 if not (message[1] in self.stay_channels) or auteur in self.overops:
221 serv.part(message[1])
222 self.chanlist.remove(message[1])
223 log("priv",auteur," ".join(message)+"[successful]")
224 else:
225 serv.privmsg(auteur,"Non, je reste !")
226 log("priv",auteur," ".join(message)+"[failed]")
227 else:
228 serv.privmsg(auteur,"Je ne suis pas sur %s"%(message[1]))
229 else:
230 notunderstood=True
231 elif cmd=="stay":
232 if auteur in self.overops:
233 if len(message)>1:
234 if message[1] in self.stay_channels:
235 serv.privmsg(auteur,"Je stay déjà sur %s."%(message[1]))
236 log("priv",auteur," ".join(message)+"[failed]")
237 else:
238 self.stay_channels.append(message[1])
239 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
240 log("priv",auteur," ".join(message)+"[successful]")
241 else:
242 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
243 else:
244 notunderstood=True
245 elif cmd=="nostay":
246 if auteur in self.overops:
247 if len(message)>1:
248 if message[1] in self.stay_channels:
249 self.stay_channels.remove(message[1])
250 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
251 log("priv",auteur," ".join(message)+"[successful]")
252 else:
253 serv.privmsg(auteur,"Je ne stay pas sur %s."%(message[1]))
254 log("priv",auteur," ".join(message)+"[failed]")
255 else:
256 notunderstood=True
257 elif cmd=="play":
258 if auteur in self.ops:
259 if len(message)>1:
260 if message[1] in self.play_channels:
261 serv.privmsg(auteur,"Je play déjà sur %s."%(message[1]))
262 log("priv",auteur," ".join(message)+"[failed]")
263 else:
264 self.play_channels.append(message[1])
265 self.play_status[message[1]]=[0,time.time()-3600]
266 serv.privmsg(auteur,"Play channels : "+" ".join(self.play_channels))
267 log("priv",auteur," ".join(message)+"[successful]")
268 else:
269 serv.privmsg(auteur,"Play channels : "+" ".join(self.play_channels))
270 else:
271 notunderstood=True
272 elif cmd=="noplay":
273 if auteur in self.ops:
274 if len(message)>1:
275 if message[1] in self.play_channels:
276 self.play_channels.remove(message[1])
277 serv.privmsg(auteur,"Play channels : "+" ".join(self.play_channels))
278 log("priv",auteur," ".join(message)+"[successful]")
279 else:
280 serv.privmsg(auteur,"Je ne play pas sur %s."%(message[1]))
281 log("priv",auteur," ".join(message)+"[failed]")
282 else:
283 notunderstood=True
284 elif cmd in ["states","status"]:
285 if auteur in self.overops:
286 for k in self.play_status.keys():
287 serv.privmsg(auteur,"%s : %s"%(k,"; ".join([str(i) for i in self.play_status[k]])))
288 elif cmd=="say":
289 if auteur in self.overops and len(message)>2:
290 serv.privmsg(message[1]," ".join(message[2:]))
291 log("priv",auteur," ".join(message))
292 elif len(message)<=2:
293 serv.privmsg(auteur,"Syntaxe : SAY <channel> <message>")
294 else:
295 notunderstood=True
296 elif cmd=="die":
297 if auteur in self.overops:
298 self.die()
299 else:
300 notunderstood=True
301 if notunderstood:
302 serv.privmsg(auteur,"Je n'ai pas compris. Essaye HELP…")
303
304 def on_pubmsg(self, serv, ev):
305 auteur = irclib.nm_to_n(ev.source())
306 canal = ev.target()
307 message = ev.arguments()[0]
308 try:
309 test=bot_unicode(message)
310 except UnicodeBotError:
311 serv.privmsg(canal,
312 "%s: Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…"%(auteur))
313 return
314 tryother=False
315 pour_moi,message=self.pourmoi(serv,message)
316 if pour_moi and message.split()!=[]:
317 cmd=message.split()[0].lower()
318 try:
319 args=" ".join(message.split()[1:])
320 except:
321 args=""
322 if cmd in ["meurs","die","crève"]:
323 if auteur in self.overops:
324 self.die()
325 log(canal,auteur,message+"[successful]")
326 else:
327 serv.privmsg(canal,"%s: crève !"%(auteur))
328 log(canal,auteur,message+"[failed]")
329 if cmd in ["meur", "meurt","meurre","meurres"]:
330 serv.privmsg(canal,'%s: Mourir, impératif, 2ème personne du pluriel : "meurs" (de rien)'%(auteur))
331 if cmd in ["part","leave","dégage"]:
332 if auteur in self.ops and (not (canal in self.stay_channels)
333 or auteur in self.overops):
334 serv.part(canal,message="Éjecté par %s"%(auteur))
335 log(canal,auteur,message+"[successful]")
336 else:
337 serv.privmsg(canal,"%s: Non, je reste !"%(auteur))
338 log(canal,auteur,message+"[failed]")
339
340 if cmd in ["deviens","pseudo"]:
341 if auteur in self.ops:
342 become=args
343 serv.nick(become)
344 log(canal,auteur,message+"[successful]")
345
346 if cmd in ["coucou"]:
347 serv.privmsg(canal,"%s: coucou"%(auteur))
348 if cmd in ["ping"]:
349 serv.privmsg(canal,"%s: pong"%(auteur))
350 if cmd in ["déconnaissance","deconnaissance","énigme","enigme","encore"]:
351 if canal in self.play_channels:
352 if self.play_status.get(canal,[-1])[0]==0:
353 try:
354 self.start_enigme(serv,canal)
355 except RefuseError:
356 serv.privmsg(canal,"%s: Je peux souffler une minute ?"%(auteur))
357 else:
358 serv.privmsg(canal,"%s: Rappel : %s"%(auteur,self.play_status[canal][1]))
359 else:
360 serv.privmsg(canal,"%s: pas ici…"%(auteur))
361 else:
362 tryother=True
363 else:
364 tryother=True
365 if tryother:
366 if self.play_status.get(canal,[-1])[0] in [1,2]:
367 answer=self.play_status[canal][3]
368 if re.match(tolere(answer),unicode(message,"utf8").lower()):
369 serv.privmsg(canal,"%s: bravo ! (C'était %s)"%(auteur,answer))
370 token=time.time()
371 self.play_status[canal]=[0,token]
372 serv.execute_delayed(random.randrange(Ttrig*5,Ttrig*10),self.start_enigme,(serv,canal,token))
373
374
375 if __name__=="__main__":
376 import sys
377 if len(sys.argv)==1:
378 print "Usage : deconnaisseur.py <serveur> [--debug]"
379 exit(1)
380 serveur=sys.argv[1]
381 if "debug" in sys.argv or "--debug" in sys.argv:
382 debug=True
383 else:
384 debug=False
385 serveurs={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
386 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"}
387 try:
388 serveur=serveurs[serveur]
389 except KeyError:
390 print "Server Unknown : %s"%(serveur)
391 exit(404)
392 deco=Deconnaisseur(serveur,debug)
393 deco.start()