4 # Codé par 20-100 le 23/04/12
6 # Un bot IRC qui sort des déconnaissances
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"]
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
34 class UnicodeBotError(Exception):
36 def bot_unicode(chain
):
39 except UnicodeDecodeError:
42 def log(channel
,auteur
=None,message
=None):
43 #f=open(config_logfile,"a")
44 #if auteur==message==None:
47 # chain="%s [%s:%s] %s"%(time.strftime("%T"),channel,auteur,message)
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)")
66 class RefuseError(Exception):
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)
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
}
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
))
87 serv
.nick(config_pseudo
)
89 def on_welcome(self
, serv
, ev
):
90 self
.give_me_my_pseudo(serv
)
91 serv
.privmsg("NickServ","identify %s"%(config_password))
94 self
.chanlist
=["#bot"]
95 self
.play_channels
=["#bot"]
96 for c
in self
.chanlist
:
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
))
104 def start_enigme(self
,serv
,channel
,token
=None):
105 if self
.play_status
[channel
][0]==0 and channel
in self
.play_channels
:
107 if token
==self
.play_status
[channel
][-1]:
110 if time
.time() > self
.play_status
[channel
][-1]+config_time_incompressible
:
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
)
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
))
123 def give_indice(self
,serv
,channel
,token
):
124 if self
.play_status
[channel
][0]==1:
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))
139 self
.play_status
[channel
]=[0,token
]
140 serv
.execute_delayed(random
.randrange(Ttrig
*5,Ttrig
*10),self
.start_enigme
,(serv
,channel
,token
))
142 def get_enigme(self
):
143 f
=open(get_config_source_file(self
.serveur
))
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
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%")
160 return enigme
,indice
,answer_reg
,answer
162 def pourmoi(self
, serv
, message
):
163 pseudo
=serv
.get_nickname()
165 if message
[:size
]==pseudo
and message
[size
]==":":
166 return (True,message
[size
+1:].strip(" "))
168 return (False,message
)
170 def on_privmsg(self
, serv
, ev
):
171 message
=ev
.arguments()[0]
172 auteur
= irclib
.nm_to_n(ev
.source())
174 test
=bot_unicode(message
)
175 except UnicodeBotError
:
177 "Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…")
179 message
=message
.split()
180 cmd
=message
[0].lower()
183 helpmsg_default
="""Liste des commandes :
184 HELP Affiche ce message d'aide"""
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" """
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
196 helpmsg
=helpmsg_default
197 if auteur
in self
.ops
:
199 if auteur
in self
.overops
:
200 helpmsg
+=helpmsg_overops
201 for ligne
in helpmsg
.split("\n"):
202 serv
.privmsg(auteur
,ligne
)
204 if auteur
in self
.ops
:
206 if message
[1] in self
.chanlist
:
207 serv
.privmsg(auteur
,"Je suis déjà sur %s"%(message
[1]))
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
))
214 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
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]")
225 serv
.privmsg(auteur
,"Non, je reste !")
226 log("priv",auteur
," ".join(message
)+"[failed]")
228 serv
.privmsg(auteur
,"Je ne suis pas sur %s"%(message
[1]))
232 if auteur
in self
.overops
:
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]")
238 self
.stay_channels
.append(message
[1])
239 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
240 log("priv",auteur
," ".join(message
)+"[successful]")
242 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
246 if auteur
in self
.overops
:
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]")
253 serv
.privmsg(auteur
,"Je ne stay pas sur %s."%(message
[1]))
254 log("priv",auteur
," ".join(message
)+"[failed]")
258 if auteur
in self
.ops
:
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]")
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]")
269 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
273 if auteur
in self
.ops
:
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]")
280 serv
.privmsg(auteur
,"Je ne play pas sur %s."%(message
[1]))
281 log("priv",auteur
," ".join(message
)+"[failed]")
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
]])))
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>")
297 if auteur
in self
.overops
:
302 serv
.privmsg(auteur
,"Je n'ai pas compris. Essaye HELP…")
304 def on_pubmsg(self
, serv
, ev
):
305 auteur
= irclib
.nm_to_n(ev
.source())
307 message
= ev
.arguments()[0]
309 test
=bot_unicode(message
)
310 except UnicodeBotError
:
312 "%s: Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…"%(auteur))
315 pour_moi
,message
=self
.pourmoi(serv
,message
)
316 if pour_moi
and message
.split()!=[]:
317 cmd
=message
.split()[0].lower()
319 args
=" ".join(message
.split()[1:])
322 if cmd
in ["meurs","die","crève"]:
323 if auteur
in self
.overops
:
325 log(canal
,auteur
,message
+"[successful]")
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]")
337 serv
.privmsg(canal
,"%s: Non, je reste !"%(auteur))
338 log(canal
,auteur
,message
+"[failed]")
340 if cmd
in ["deviens","pseudo"]:
341 if auteur
in self
.ops
:
344 log(canal
,auteur
,message
+"[successful]")
346 if cmd
in ["coucou"]:
347 serv
.privmsg(canal
,"%s: coucou"%(auteur))
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:
354 self
.start_enigme(serv
,canal
)
356 serv
.privmsg(canal
,"%s: Je peux souffler une minute ?"%(auteur))
358 serv
.privmsg(canal
,"%s: Rappel : %s"%(auteur
,self
.play_status
[canal
][1]))
360 serv
.privmsg(canal
,"%s: pas ici…"%(auteur))
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
))
371 self
.play_status
[canal
]=[0,token
]
372 serv
.execute_delayed(random
.randrange(Ttrig
*5,Ttrig
*10),self
.start_enigme
,(serv
,canal
,token
))
375 if __name__
=="__main__":
378 print "Usage : deconnaisseur.py <serveur> [--debug]"
381 if "debug" in sys
.argv
or "--debug" in sys
.argv
:
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"}
388 serveur
=serveurs
[serveur
]
390 print "Server Unknown : %s"%(serveur)
392 deco
=Deconnaisseur(serveur
,debug
)