4 # Codé par 20-100 le 23/04/12
6 # Un test de bot irc, parce que c'est cool
13 import socket
, ssl
, json
17 from commands
import getstatusoutput
as ex
20 config_debug_stdout
=True
21 if "--quiet" in sys
.argv
:
22 config_debug_stdout
=False
24 config_irc_password
="NK2015BasileB0t"
25 config_irc_pseudo
="Basile"
26 config_chanlist
=["#bot","#flood"]
27 config_stay_channels
=["#bot","#flood"]
28 config_quiet_channels
=[]
29 config_note_pseudo
="Basile"
30 config_note_password
="NK2015BasileB0tr4nd0omp4assword]6_+{#]78{"
31 config_logfile_template
="basile.%s.log"
32 def get_config_logfile(serveur
):
33 serveurs
={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
34 return config_logfile_template
%(serveurs
[serveur
])
35 config_overops
=["[20-100]","[20-100]_"]
36 config_ops
=["PEB","Nit"]
37 config_report_bugs_to
=["[20-100]"]
39 config_insultes
=[u
"conna(rd|sse)",u
"pute",u
"con(|ne)",u
"enf(oiré|lure)",
40 u
"sal(op(|e(|rie)|ard)|aud)",u
"p(e|')tite bite",u
"imbécile",u
"idiot",u
"stupid(|e)",u
"débile",u
"crétin",
41 u
"pétasse",u
"enculé",u
"chagasse",u
"cagole",u
"abruti",u
"ahuri",u
"analphabète",u
"andouille",
42 u
"atardé",u
"avorton",u
"bachibouzouk",u
"(balais|brosse) (de|à) chiotte(|s)",
43 u
"batard",u
"blaireau",u
"bouffon",u
"branque",u
"bouseux",u
"branleur",u
"catin",u
"chacal",
44 u
"charogne",u
"chiant(|e)",u
"chieur",u
"cochon",u
"coprophage",u
"couillon",u
"crapule",u
"crevard",
45 u
"cruche",u
"cuistre",u
"ducon",u
"décérébré",
46 u
"emmerdeur",u
"feignasse",u
"fainéant",u
"fourbe",u
"freluquet",u
"frigide",
47 u
"garce",u
"glandu",u
"gogol",u
"goujat",u
"gourdasse",u
"gredin",u
"gringalet",u
"grognasse",
48 u
"naze",u
"truie",u
"iconoclaste",
49 u
"peigne(-|)cul",u
"ignare",u
"illétré",u
"lèche(|-)cul",u
"malotru",u
"motherfucker",u
"nabot",u
"nigaud",
50 u
"nul",u
"escroc",u
"pouffiasse",u
"pourriture",u
"raclure",u
"relou",u
"sagouin",u
"putain",
52 config_insultes_answers
=[u
"toi-même",
53 u
"Oh non ! Quelle insulte ! Je crois que je ne m'en reléverai jamais…\nAh si, ça y est.",
54 u
"J'entends comme un vague murmure, tu disais ?",
55 u
"Je vais prendre ça pour un compliment.",
56 u
"Tu sais, pour toi c'est peut-être une insulte, mais pour moi ce n'est qu'une suite de 0 et de 1…",
57 u
"Si tu allais voir sur un autre chan si j'y suis ?",
58 u
"Permets-moi de te retourner le compliment.",
59 u
"Mais je ne te permets pas !"]
63 config_buffer_fail_answers
=["haha !","You type like you drive","encore un effort ;)"]
65 config_premier_groupe_terminaisons
=u
"(e|es|ons|ez|ent|er(|ai|as|a|ons|ez|ont)|(|er)(ais|ait|ions|iez|aient)|(a(i|s|)|â(mes|tes|t)|èrent)|ass(e(|s|nt)|i(ons|ez))|é(|s|e|es))"
66 config_regexp_etre
=u
"(être|suis|e(s|t)|so(mmes|nt)|êtes|(ét|ser)(ai(s|t|ent)|i(ons|ent)|)|ser(ai|as|a|ons|ez|ont)|so(i(s|t|ent)|y(ons|ez))|f(u(s|t|rent)|û(mes|tes|t))|fuss(e(|s|nt)|i(ons|ez))|étant)"
67 config_regexp_etre_avec_c
=u
"c'(e(s|st)|étai(t|ent))"
68 config_regexp_faire
=u
"fais"
69 config_perdu
=[u
"perd(|s|ons|ez|ent|r(e|ai|as|a|ons|ez|ont)|(|r)(ais|ait|ions|iez|aient))"
70 u
"perd(i(s|t|rent)|î(mes|tes|t))", # oui, j'ai inclus qu'il perdît
71 u
"perdiss(e(|s|nt)|i(ons|ez))",
72 u
"perdu(|s|e|es)",u
"perdant(|s|e|es)",u
"perte(|s)",
74 u
"(gagn|trouv)"+config_premier_groupe_terminaisons
,u
"gagnant(|s|e|es)",u
"gain(|s)",
76 u
"trouvant",u
"trouvaille(|s)",
78 u
"victoire(|s)",u
"vaincu(|s|e|es)",
79 u
"loose",u
"lost",u
"looser(|s)",u
"win(|ner)(|s)",
80 u
"jeu(|x)",u
"game(|s)"]
81 config_time_between_perdu_trigger
=3600*3 #temps moyen pour perdre en l'absence de trigger
82 config_time_between_perdu_trigger_delta
= 30*60 #marge autorisée autour de ^^^
83 config_time_between_perdu
=30*60 #temps pendant lequel on ne peut pas perdre
85 config_tag
=[u
"t(|a)g",u
"ta gueule",u
"la ferme",u
"ferme( |-)la",u
"tais-toi",u
"chut"]
86 config_tag_actions
=[u
"se tait",u
"ferme sa gueule",u
"se la ferme",u
"la ferme"]
87 config_tag_answers
=[u
"J'me tais si j'veux !",
88 u
"Je t'entends pas :°",
90 u
"Non, j'ai pas envie",
91 u
"Peut-être quand toi tu la fermeras, et encore…"]
93 config_tesla
=[u
"t('|u )es là \?",u
"\?",u
"plop \?",u
"plouf \?"]
94 config_tesla_answers
=[u
"Oui, je suis là",u
"Oui ?",u
"En quoi puis-je me rendre utile ?"]
95 config_tesla_actions
=[u
"est là",u
"attend des instructions",u
"is alive"]
97 config_compliment
=[u
"gentil",u
"cool",u
"sympa"]
98 config_compliment_answers
=[u
"Merci, c'est gentil :)",u
"Je te retourne le compliment",u
"C'est gentil ça."]
100 config_merci
=[u
"merci",u
"remercie",u
"thx",u
"thank(|s)"]
101 config_merci_answers
=[u
"Mais de rien.",u
"À ton service ;)",u
"Quand tu veux ^^",
102 u
"Tout le plaisir est pour moi."]
104 config_tamere
=[u
"ta mère"]
105 config_tamere_answers
=[u
"Laisse ma mère en dehors de ça !",
106 u
"Tu veux qu'on parle de ta soœur ?",
108 u
"Ce que fait ma mère c'est comme ce que tu fais avec ta bite, ça nous regarde pas…",
109 u
"♩ J'ai vu ta mère sur chat rouleeeeeeette ♫"
110 u
"On avait dit \"pas les mamans\""]
112 config_action_trigger
=[u
"(frappe|cogne|tape)(| sur)",u
"(démolit|dégomme|fouette|agresse)",
113 u
"vomit sur",u
"slap(|s)"]
114 config_action_answers
=[u
"Hey ! Mais qu'est-ce que j'ai fait ?",
117 u
"Mais j'ai rien demandé moi !"]
118 config_action_actions
=[u
"prend de la distance, par précaution…",u
"part en courant",u
"esquive"]
120 config_bonjour
=[u
"(s|)(a|'|)lu(t|)",u
"hello",u
"plop",u
"plip",u
"pr(ou|ü)t",u
"bonjour",u
"bonsoir"]
121 config_bonjour_answers
=[u
"Salut {}",u
"Hello {} :)",u
"Bonjour {}",u
"Hello {}",u
"{}: hello",u
"{}: bonjour"]
124 config_thisfile
= os
.path
.realpath( __file__
)
126 return ex("ls -s %s"%(config_thisfile))[1].split()[0]
128 class NKError(Exception):
129 def __init__(self
,msg
):
130 Exception.__init
__(self
)
134 def __unicode__(self
):
135 return unicode(self
.msg
)
137 class NKRefused(NKError
):
140 class NKHelloFailed(NKError
):
143 class NKUnknownError(NKError
):
146 def log(serveur
,channel
,auteur
=None,message
=None):
147 f
=open(get_config_logfile(serveur
),"a")
148 if auteur
==message
==None:
149 # alors c'est que c'est pas un channel mais juste une ligne de log
150 chain
="%s %s"%(time
.strftime("%F %T"),channel
)
152 chain
="%s [%s:%s] %s"%(time
.strftime("%F %T"),channel
,auteur
,message
)
154 if config_debug_stdout
:
161 # On établit la connexion sur port 4242
162 sock
.connect(("127.0.0.1",4242))
164 sock
=ssl
.wrap_socket(sock
,ca_certs
='../keys/ca_.crt')
166 sock
.write('hello "Basile"')
167 # On récupère la réponse du hello
170 except Exception as exc
:
171 # Si on a foiré quelque part, c'est que le serveur est down
172 raise NKRefused(str(exc
))
173 if out
["retcode"]==0:
175 elif out
["retcode"]==11:
176 raise NKHelloFailed(out
["errmsg"])
178 raise NKUnknownError(out
["errmsg"])
180 def login_NK(username
,password
,typ
="bdd"):
182 if typ
=="special": # ça c'est pour Basile lui-même
185 masque
='[["all"],["all"],false]'
187 # Basile a un compte special user
188 commande
='login [%s,%s,"%s",%s]'%(json
.dumps(username
),json
.dumps(password
),typ
,masque
)
191 except Exception as exc
:
192 # Si on a foiré quelque part, c'est que le serveur est down
193 raise NKRefused(str(exc
))
194 # On vérifie ensuite que le login
195 return json
.loads(out
),sock
198 def is_something(chain
,matches
,avant
=u
".*(^| )",apres
=u
"($|\.| |,|;).*",case_sensitive
=False,debug
=False):
200 chain
=unicode(chain
,"utf8")
202 chain
=unicode(chain
,"utf8").lower()
203 allmatches
="("+"|".join(matches
)+")"
204 reg
=(avant
+allmatches
+apres
).lower()
205 if re
.match(reg
,chain
):
209 def is_insult(chain
,debug
=True):
210 return is_something(chain
,config_insultes
,avant
=".*(^| |')")
211 def is_not_insult(chain
):
212 chain
=unicode(chain
,"utf8")
213 insult_regexp
=u
"("+u
"|".join(config_insultes
)+u
")"
214 middle_regexp
=u
"(un(|e) ((putain|enfoiré) d(e |'))*|)(| super )( (gros|petit|grand|énorme) |)"
215 reg
=".*pas %s%s.*"%(middle_regexp
,insult_regexp
)
216 if re
.match(reg
,chain
):
221 return is_something(chain
,config_perdu
)
223 return is_something(chain
,config_tag
)
225 return is_something(chain
,config_gros
)
227 return is_something(chain
,config_tesla
,avant
=u
"^",apres
=u
"$",debug
=True)
229 return is_something(chain
,config_merci
)
230 def is_tamere(chain
):
231 return is_something(chain
,config_tamere
)
232 def is_action_trigger(chain
,pseudo
):
233 return is_something(chain
,config_action_trigger
,avant
=u
"^",
234 apres
="( [a-z]*ment)? %s($|\.| |,|;).*"%(pseudo))
236 return re
.match(u
"^(pan|bim|bang)$",unicode(chain
,"utf8").lower().strip())
240 class UnicodeBotError(Exception):
242 def bot_unicode(chain
):
244 unicode(chain
,"utf8")
245 except UnicodeDecodeError as exc
:
246 raise UnicodeBotError
248 class Basile(ircbot
.SingleServerIRCBot
):
249 def __init__(self
,serveur
,debug
=False):
250 temporary_pseudo
=config_irc_pseudo
+str(random
.randrange(10000,100000))
251 ircbot
.SingleServerIRCBot
.__init
__(self
, [(serveur
, 6667)],
252 temporary_pseudo
,"Basile, le bot irc.[Codé par 20-100, fouettez-le]", 10)
255 self
.overops
=config_overops
256 self
.ops
=self
.overops
+config_ops
257 self
.report_bugs_to
=config_report_bugs_to
258 self
.chanlist
=config_chanlist
260 self
.identities
=pickle
.load(open("identities.pickle","r"))
261 self
.stay_channels
=config_stay_channels
262 self
.quiet_channels
=config_quiet_channels
266 def new_connection_NK(self
,serv
,username
,password
,typ
="bdd"):
268 login_result
,sock
=login_NK(username
,password
,typ
)
269 droits
,retcode
,errmsg
=login_result
["msg"],login_result
["retcode"],login_result
["errmsg"]
270 except NKRefused
as exc
:
271 for report
in self
.report_bugs_to
:
272 serv
.privmsg(report
,"Le Serveur NK2015 est down.")
274 except NKHelloFailed
as exc
:
275 for report
in self
.report_bugs_to
:
277 "La version du site utilisée n'est pas supportée par le serveur NK2015.")
279 except NKUnknownError
as exc
:
280 erreurs
=["Une fucking erreur inconnue s'est produite"]
281 erreurs
+=str(exc
).split("\n")
282 for report
in self
.report_bugs_to
:
284 serv
.privmsg(report
,err
)
286 except Exception as exc
:
287 # Exception qui ne vient pas de la communication avec le serveur NK2015
288 log(self
.serveur
,"Erreur dans new_connection_NK\n"+str(exc
))
295 def give_me_my_pseudo(self
,serv
):
296 serv
.privmsg("NickServ","RECOVER %s %s"%(config_irc_pseudo
,config_irc_password
))
297 serv
.privmsg("NickServ","RELEASE %s %s"%(config_irc_pseudo
,config_irc_password
))
299 serv
.nick(config_irc_pseudo
)
301 def on_welcome(self
, serv
, ev
):
302 self
.give_me_my_pseudo(serv
)
303 serv
.privmsg("NickServ","identify %s"%(config_irc_password))
304 log(self
.serveur
,"Connected")
306 self
.chanlist
=["#bot"]
307 for c
in self
.chanlist
:
308 log(self
.serveur
,"JOIN %s"%(c))
310 # on ouvre la connexion note de Basile, special user
311 self
.nk
=self
.new_connection_NK(serv
,config_note_pseudo
,config_note_password
,"special")[1]
313 for report
in self
.report_bugs_to
:
314 serv
.privmsg(report
,"Connection to NK2015 failed, invalid password ?")
316 def lost(self
,serv
,channel
,forced
=False):
317 if self
.last_perdu
+config_time_between_perdu
<time
.time() or forced
:
318 if not channel
in self
.quiet_channels
or forced
:
319 serv
.privmsg(channel
,"J'ai perdu !")
320 self
.last_perdu
=time
.time()
321 delay
=config_time_between_perdu_trigger
322 delta
=config_time_between_perdu_trigger_delta
323 serv
.execute_delayed(random
.randrange(delay
-delta
,delay
+delta
),self
.lost
,(serv
,channel
))
325 def try_tamere(self
,serv
,channel
,auteur
,message
):
326 """Essaye de trigger un ta mère"""
327 #pas à chaque fois quand même
328 if random
.randrange(4)==0:
329 debuts
=u
"("+config_regexp_etre
+u
"|"+config_regexp_etre_avec_c
+u
")"
330 adjectifs
={u
"bon(|ne|s|nes)":u
"bonne",
331 u
"baisable(|s)":u
"baisable",
332 u
"faisable(|s)":u
"faisable",
333 u
"pas ch(ère(|s)|er(|s))":u
"pas chère",
334 u
"facile(|s)":u
"facile",
335 u
"chaud(|e|s|es)":u
"chaude",
336 u
"gratuit(|e|s|es)":u
"gratuite",
337 u
"payant(|e|s|es)":u
"payante",
338 u
"ouvert(|e|s|es)":u
"ouverte",
340 u
"plein(|s|es)":u
"pleine",
341 u
"bien plein(|e|s|es)":u
"bien pleine",
342 u
"innocent(|e|s|es)":u
"innocente"}
343 adj_reg
=u
"(?P<adjectif>"+u
"|".join(adjectifs
.keys())+u
")"
344 reg
=u
".*(^| |')"+debuts
+u
" "+adj_reg
+u
"($|,|;|\.| ).*"
345 matched
=re
.match(reg
,message
)
347 # il faut repasser l'adjectif au féminin singulier
348 found
=matched
.groupdict()["adjectif"]
349 for adj
in adjectifs
.keys():
350 if re
.match(adj
,found
):
351 adjectif
=adjectifs
[adj
]
353 serv
.privmsg(channel
,(u
"%s: c'est ta mère qui est %s !"%(auteur
,adjectif
)).encode("utf8"))
354 elif random
.randrange(5)==0:
355 # deuxième type de trigger, mais moins probable
356 matched
=re
.match(adj_reg
,message
)
358 found
=matched
.groupdict()["adjectif"]
359 for adj
in adjectifs
.keys():
360 if re
.match(adj
,found
):
361 adjectif
=adjectifs
[adj
]
363 fille
=random
.choice([u
"mère",u
"soœur"])
364 serv
.privmsg(channel
,(u
"%s: et ta %s, elle est %s ?"%
365 (auteur
,fille
,adjectif
)).encode("utf8"))
367 # troisième type de trigger
368 cpgt
=config_premier_groupe_terminaisons
369 verbes
={u
"tourn"+cpgt
:u
"tourne",
370 u
"balad"+cpgt
+u
" sur le trottoir":u
"se balade sur le trottoir",
371 u
"prom(e|è)n"+cpgt
+" sur le trottoir":u
"se promène sur le trottoir",
373 vb_reg
=u
".*(^| )(?P<verbe>"+"|".join(verbes
.keys())+")( |,|;|\.|$)"
374 matched
=re
.match(vb_reg
,message
)
376 found
=matched
.groupdict()["verbe"]
377 for vb
in verbes
.keys():
378 if re
.match(vb
,found
):
381 fille
=random
.choice([u
"mère",u
"soœur"])
382 serv
.privmsg(channel
,(u
"%s: et ta %s, elle %s ?"%
383 (auteur
,fille
,verbe
)).encode("utf8"))
384 def pourmoi(self
, serv
, message
):
385 """renvoie (False,lemessage) ou (True, le message amputé de "pseudo: ")"""
386 pseudo
=serv
.get_nickname()
388 if message
[:size
]==pseudo
and len(message
)>size
and message
[size
]==":":
389 return (True,message
[size
+1:].lstrip(" "))
391 return (False,message
)
393 def on_privmsg(self
, serv
, ev
):
394 message
=ev
.arguments()[0]
395 auteur
= irclib
.nm_to_n(ev
.source())
397 test
=bot_unicode(message
)
398 except UnicodeBotError
:
400 "Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…")
402 message
=message
.split()
403 cmd
=message
[0].lower()
406 if not len(message
) in [2,3]:
407 serv
.privmsg(auteur
,"Syntaxe : CONNECT [<username>] <password>")
411 username
=(message
[1])
412 password
=" ".join(message
[2:])
414 password
=" ".join(message
[1:])
415 success
,sock
=self
.new_connection_NK(serv
,username
,password
)
417 self
.sockets
[username
]=sock
418 serv
.privmsg(auteur
,"Connection successful")
419 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
421 serv
.privmsg(auteur
,"Connection failed")
422 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
425 helpdico
={"connect": """CONNECT [<username>] <password>
426 Ouvre une connexion au serveur NoteKfet.
427 Si <username> n'est pas précisé, j'utiliserais l'identité sous laquelle je te connais, ou, à défaut, ton pseudo.""",
428 "identify": """IDENTIFY <username> <password>
429 Vérifie le mot de passe et me permet de savoir à l'avenir quel est ton pseudo note kfet.
430 Sans paramètre, je réponds sous quel pseudo je te connais.""",
431 "drop":"""DROP <password>
432 Vérifie le mot de passe et me fait d'oublier ton pseudo note kfet."""}
433 helpmsg_default
="""Liste des commandes :
434 HELP Affiche de l'aide sur une commande.
435 CONNECT Ouvre une connection au serveur Note Kfet.
436 IDENTIFY Me permet de savoir qui tu es sur la note kfet.
437 DROP Me fait oublier ton identité.
438 SOLDE Obtenir ton solde"""
440 JOIN Faire rejoindre un chan
441 LEAVE Faire quitter un chan
442 QUIET Se taire sur un chan
443 NOQUIET Opposé de QUIET
444 LOST Perdre sur un chan
445 SOLDE <pseudo> Donner le solde de quelqu'un"""
447 SAY Fait envoyer un message sur un chan ou à une personne
448 STAY Ignorera les prochains LEAVE pour un chan
449 NOSTAY Opposé de STAY
452 helpmsg
=helpmsg_default
453 if auteur
in self
.ops
:
455 if auteur
in self
.overops
:
456 helpmsg
+=helpmsg_overops
458 helpmsg
=helpdico
.get(message
[1].lower(),"Commande inconnue.")
459 for ligne
in helpmsg
.split("\n"):
460 serv
.privmsg(auteur
,ligne
)
461 elif cmd
=="identify":
463 if self
.identities
.has_key(auteur
):
464 serv
.privmsg(auteur
,"Je te connais sous le pseudo note %s."%(
465 self
.identities
[auteur
].encode("utf8")))
467 serv
.privmsg(auteur
,"Je ne connais pas ton pseudo note.")
468 elif len(message
)>=3:
469 username
,password
=message
[1],unicode(" ".join(message
[2:]),"utf8")
470 success
,_
=self
.new_connection_NK(serv
,username
,password
)
472 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
473 serv
.privmsg(auteur
,"Identité enregistrée.")
474 self
.identities
[auteur
]=username
475 pickle
.dump(self
.identities
,open("identities.pickle","w"))
477 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
478 serv
.privmsg(auteur
,"Mot de passe invalide. (ou serveur down)")
480 serv
.privmsg(auteur
,u
"Syntaxe : IDENTIFY [<username> <password>]")
483 if self
.identities
.has_key(auteur
):
484 password
=" ".join(message
[1:])
485 success
,_
=self
.new_connection_NK(serv
,self
.identities
[auteur
],password
)
487 del self
.identities
[auteur
]
488 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
489 pickle
.dump(self
.identities
,open("identities.pickle","w"))
490 serv
.privmsg(auteur
,"Identité oubliée.")
492 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
493 serv
.privmsg(auteur
,"Mot de passe invalide. (ou serveur down)")
495 serv
.privmsg(auteur
,"Je ne connais pas ton pseudo note.")
497 serv
.privmsg(auteur
,"Syntaxe : DROP <password>")
499 if auteur
in self
.ops
:
501 if message
[1] in self
.chanlist
:
502 serv
.privmsg(auteur
,"Je suis déjà sur %s"%(message
[1]))
504 serv
.join(message
[1])
505 self
.chanlist
.append(message
[1])
506 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
507 log(self
.serveur
,"priv",auteur
," ".join(message
))
509 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
513 if auteur
in self
.ops
and len(message
)>1:
514 if message
[1] in self
.chanlist
:
515 if not (message
[1] in self
.stay_channels
) or auteur
in self
.overops
:
516 serv
.part(message
[1])
517 self
.chanlist
.remove(message
[1])
518 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
520 serv
.privmsg(auteur
,"Non, je reste !")
521 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
523 serv
.privmsg(auteur
,"Je ne suis pas sur %s"%(message
[1]))
527 if auteur
in self
.overops
:
529 if message
[1] in self
.stay_channels
:
530 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
531 serv
.privmsg(auteur
,"Je stay déjà sur %s."%(message
[1]))
533 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
534 self
.stay_channels
.append(message
[1])
535 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
537 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
541 if auteur
in self
.overops
:
543 if message
[1] in self
.stay_channels
:
544 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
545 self
.stay_channels
.remove(message
[1])
546 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
548 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
549 serv
.privmsg(auteur
,"Je ne stay pas sur %s."%(message
[1]))
554 if auteur
in self
.overops
:
555 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
560 if auteur
in self
.ops
:
562 if message
[1] in self
.quiet_channels
:
563 serv
.privmsg(auteur
,"Je me la ferme déjà sur %s"%(message
[1]))
564 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
566 self
.quiet_channels
.append(message
[1])
567 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
568 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
570 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
574 if auteur
in self
.ops
:
576 if message
[1] in self
.quiet_channels
:
577 self
.quiet_channels
.remove(message
[1])
578 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
579 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
581 serv
.privmsg(auteur
,"Je ne me la ferme pas sur %s."%(message
[1]))
582 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
586 if auteur
in self
.overops
and len(message
)>2:
587 serv
.privmsg(message
[1]," ".join(message
[2:]))
588 log(self
.serveur
,"priv",auteur
," ".join(message
))
589 elif len(message
)<=2:
590 serv
.privmsg(auteur
,"Syntaxe : SAY <channel> <message>")
594 if auteur
in self
.ops
and len(message
)>1:
595 serv
.privmsg(message
[1],"J'ai perdu !")
596 log(self
.serveur
,"priv",auteur
," ".join(message
))
597 elif len(message
)<=1:
598 serv
.privmsg(auteur
,"Syntaxe : LOST <channel>")
603 if self
.identities
.has_key(auteur
):
605 self
.nk
.write('search ["x",["pseudo"],%s]'%(json
.dumps(self
.identities
[auteur
])))
606 ret
=json
.loads(self
.nk
.read())
607 solde
=ret
["msg"][0]["solde"]
608 pseudo
=ret
["msg"][0]["pseudo"]
609 except Exception as exc
:
611 serv
.privmsg(auteur
,"failed")
612 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
614 serv
.privmsg(auteur
,"%s (%s)"%(float(solde
)/100,pseudo
.encode("utf8")))
616 serv
.privmsg(canal
,"Je ne connais pas ton pseudo note.")
617 elif auteur
in self
.ops
:
619 self
.nk
.write('search ["x",["pseudo"],%s]'%(json
.dumps(message
[1])))
620 ret
=json
.loads(self
.nk
.read())
621 solde
=ret
["msg"][0]["solde"]
622 pseudo
=ret
["msg"][0]["pseudo"]
623 except Exception as exc
:
624 serv
.privmsg(auteur
,"failed")
625 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
627 serv
.privmsg(auteur
,"%s (%s)"%(float(solde
)/100,pseudo
.encode("utf8")))
631 serv
.privmsg(auteur
,"Je n'ai pas compris. Essaye HELP…")
633 def on_pubmsg(self
, serv
, ev
):
634 auteur
= irclib
.nm_to_n(ev
.source())
636 message
= ev
.arguments()[0]
638 test
=bot_unicode(message
)
639 except UnicodeBotError
:
640 if not canal
in self
.quiet_channels
:
642 "%s: Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…"%(auteur))
644 pour_moi
,message
=self
.pourmoi(serv
,message
)
645 if pour_moi
and message
.split()!=[]:
646 cmd
=message
.split()[0].lower()
648 args
=" ".join(message
.split()[1:])
651 if cmd
in ["meurs","die","crève"]:
652 if auteur
in self
.overops
:
653 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
656 serv
.privmsg(canal
,"%s: crève !"%(auteur))
657 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
659 elif cmd
in ["part","leave","dégage"]:
660 if auteur
in self
.ops
and (not (canal
in self
.stay_channels
)
661 or auteur
in self
.overops
):
662 serv
.part(canal
,message
="Éjecté par %s"%(auteur))
663 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
665 serv
.privmsg(canal
,"%s: Non, je reste !"%(auteur))
666 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
668 elif cmd
in ["reconnect"]:
669 if auteur
in self
.ops
:
671 self
.nk
=self
.new_connection_NK(serv
,config_note_pseudo
,
672 config_note_password
,"special")[1]
673 except Exception as exc
:
675 log(self
.serveur
,"""Erreur dans on_pubmsg/"cmd in ["reconnect"]\n"""+str(exc
))
677 serv
.privmsg(canal
,"%s: done"%(auteur))
678 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
680 serv
.privmsg(canal
,"%s: failed"%(auteur))
681 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
682 for report
in self
.report_bugs_to
:
683 serv
.privmsg(report
,"Connection to NK2015 failed, invalid password ?")
685 serv
.privmsg(canal
,"%s: crève !"%(auteur))
686 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
688 elif cmd
in ["deviens","pseudo"]:
689 if auteur
in self
.ops
:
692 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
694 elif cmd
in ["coucou"] and not canal
in self
.quiet_channels
:
695 serv
.privmsg(canal
,"%s: coucou"%(auteur))
696 elif cmd
in ["ping"] and not canal
in self
.quiet_channels
:
697 serv
.privmsg(canal
,"%s: pong"%(auteur))
699 elif cmd
in ["solde","!solde"]:
700 if self
.identities
.has_key(auteur
):
701 pseudo
=self
.identities
[auteur
]
703 self
.nk
.write('search ["x",["pseudo"],%s]'%(json
.dumps(pseudo
)))
704 ret
=json
.loads(self
.nk
.read())
705 solde
=ret
["msg"][0]["solde"]
706 pseudo
=ret
["msg"][0]["pseudo"]
707 except Exception as exc
:
708 serv
.privmsg(canal
,"%s: failed"%(auteur))
709 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
711 serv
.privmsg(canal
,"%s: %s (%s)"%(auteur
,float(solde
)/100,pseudo
.encode("utf8")))
712 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
714 serv
.privmsg(canal
,"%s: Je ne connais pas ton pseudo note."%(auteur))
715 log(self
.serveur
,canal
,auteur
,message
+"[unknown]")
716 elif (re
.match("!?(pain au chocolat|chocolatine)",message
.lower())
717 and not canal
in self
.quiet_channels
):
718 serv
.action(canal
,"sert un pain au chocolat à %s"%(auteur))
719 elif re
.match("!?manzana",message
.lower()) and not canal
in self
.quiet_channels
:
720 if auteur
=="[20-100]":
721 serv
.action(canal
,"sert une bouteille de manzana à %s"%(auteur))
723 serv
.action(canal
,"sert un verre de manzana à %s"%(auteur))
724 if is_insult(message
) and not canal
in self
.quiet_channels
:
725 if is_not_insult(message
):
726 answer
=random
.choice(config_compliment_answers
)
727 for ligne
in answer
.split("\n"):
728 serv
.privmsg(canal
,"%s: %s"%(auteur
,ligne
.encode("utf8")))
730 answer
=random
.choice(config_insultes_answers
)
731 for ligne
in answer
.split("\n"):
732 serv
.privmsg(canal
,"%s: %s"%(auteur
,ligne
.encode("utf8")))
733 if is_gros(message
) and not canal
in self
.quiet_channels
:
734 taille
=get_filesize()
735 answer
=u
"Mais non, je ne suis pas gros, %sKo tout au plus…"%(taille)
736 serv
.privmsg(canal
,"%s: %s"%(auteur
,answer
.encode("utf8")))
737 if is_tesla(message
) and not canal
in self
.quiet_channels
:
738 l1
,l2
=config_tesla_answers
,config_tesla_actions
739 n1
,n2
=len(l1
),len(l2
)
740 i
=random
.randrange(n1
+n2
)
742 serv
.action(canal
,l2
[i
-n1
])
744 serv
.privmsg(canal
,"%s: %s"%(auteur
,l1
[i
].encode("utf8")))
745 if is_tamere(message
) and not canal
in self
.quiet_channels
:
746 answer
=random
.choice(config_tamere_answers
)
747 for ligne
in answer
.split("\n"):
748 serv
.privmsg(canal
,"%s: %s"%(auteur
,ligne
.encode("utf8")))
749 if is_tag(message
) and not canal
in self
.quiet_channels
:
750 if auteur
in self
.ops
:
751 action
=random
.choice(config_tag_actions
)
752 serv
.action(canal
,action
.encode("utf8"))
753 self
.quiet_channels
.append(canal
)
755 answer
=random
.choice(config_tag_answers
)
756 for ligne
in answer
.split("\n"):
757 serv
.privmsg(canal
,"%s: %s"%(auteur
,ligne
.encode("utf8")))
758 if is_merci(message
):
759 answer
=random
.choice(config_merci_answers
)
760 for ligne
in answer
.split("\n"):
761 serv
.privmsg(canal
,"%s: %s"%(auteur
,ligne
.encode("utf8")))
762 out
=re
.match(u
"^([A-Z[]|\\|[0-9]+|(¹|²|³|⁴|⁵|⁶|⁷|⁸|⁹|⁰)+)(?:| \?| !)$",
763 unicode(message
.upper(),"utf8"))
764 if out
and not canal
in self
.quiet_channels
:
768 serv
.privmsg(canal
,"%s: %s !"%(auteur
,out
+1))
769 if out
+1>1000 and random
.randrange(4)==0:
770 serv
.privmsg(canal
,"%s: Tu sais, je peux continuer longtemps comme ça…"%(auteur))
772 serv
.privmsg(canal
,"%s: Tu croyais m'avoir sur le maxint ? J'suis en python mon vieux, 'va falloir trouver mieux…"%(auteur))
774 except Exception as exc
:
776 if re
.match("[A-Y]",out
):
777 alphabet
="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
778 serv
.privmsg(canal
,"%s: %s !"%(auteur
,alphabet
[alphabet
.index(out
)+1]))
780 serv
.privmsg(canal
,"%s: pfff, j'ai l'air malin maintenant… [ ?"%(auteur))
782 serv
.privmsg(canal
,"%s: nan mais il faut qu'on arrête, ça va finir par poser des problèmes…"%(auteur))
783 elif re
.match(r
"(¹|²|³|⁴|⁵|⁶|⁷|⁸|⁹|⁰)+",out
):
785 return "".join([{u
"⁰¹²³⁴⁵⁶⁷⁸⁹0123456789"[i
]:u
"0123456789⁰¹²³⁴⁵⁶⁷⁸⁹"[i
]
786 for i
in range(20)}[j
]
788 out
=int(translate(out
))
789 serv
.privmsg(canal
,"%s: %s !"%(auteur
,translate(str(out
+1)).encode("utf8")))
790 if (not canal
in self
.quiet_channels
791 and re
.match((u
"^("+"|".join(config_bonjour
)+").*").lower(),message
.lower()) ):
792 answer
=random
.choice(config_bonjour_answers
)
793 serv
.privmsg(canal
,answer
.format(auteur
).encode("utf8"))
795 serv
.privmsg(canal
,"%s: c'est pas sur moi qu'il faut tirer !"%(auteur))
797 if message
in ["!pain au chocolat","!chocolatine"] and not canal
in self
.quiet_channels
:
798 serv
.action(canal
,"sert un pain au chocolat à %s"%(auteur))
799 if message
in ["!manzana"] and not canal
in self
.quiet_channels
:
800 if auteur
=="[20-100]":
801 serv
.action(canal
,"sert une bouteille de manzana à %s"%(auteur))
803 serv
.action(canal
,"sert un verre de manzana à %s"%(auteur))
804 if re
.match('^(.|§|:|)(w|b) [0-9]+$',message
) and not canal
in self
.quiet_channels
:
805 failanswers
=config_buffer_fail_answers
806 answer
=random
.choice(failanswers
)
807 serv
.privmsg(canal
,"%s: %s"%(auteur
,answer
))
808 if not canal
in self
.quiet_channels
:
809 self
.try_tamere(serv
,canal
,auteur
,message
)
810 mypseudo
=serv
.get_nickname()
811 if re
.match((u
"^("+u
"|".join(config_bonjour
)
812 +u
")( {}| all| tout le monde|(|à) tous)(\.|( |)!|)$"
813 ).format(mypseudo
).lower(), message
.strip().lower()):
814 answer
=random
.choice(config_bonjour_answers
)
815 serv
.privmsg(canal
,answer
.format(auteur
).encode("utf8"))
816 if (is_perdu(message
) and not canal
in self
.quiet_channels
):
817 # proba de perdre sur trigger :
818 # avant 30min (enfin, config) : 0
819 # ensuite, +25%/30min, linéairement
820 deltat
=time
.time()-self
.last_perdu
821 barre
=(deltat
-config_time_between_perdu
)/(2*3600.0)
822 if random
.uniform(0,1)<barre
:
823 serv
.privmsg(canal
,"%s: J'ai perdu !"%(auteur))
824 self
.last_perdu
=time
.time()
826 def on_action(self
, serv
, ev
):
827 action
= ev
.arguments()[0]
828 auteur
= irclib
.nm_to_n(ev
.source())
829 channel
= ev
.target()
831 test
=bot_unicode(action
)
832 except UnicodeBotError
:
833 serv
.privmsg(channel
,
834 "%s : Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…"%(auteur))
836 mypseudo
=serv
.get_nickname()
838 if is_action_trigger(action
,mypseudo
) and not channel
in self
.quiet_channels
:
839 l1
,l2
=config_action_answers
,config_action_actions
840 n1
,n2
=len(l1
),len(l2
)
841 i
=random
.randrange(n1
+n2
)
843 serv
.action(channel
,l2
[i
-n1
].encode("utf8"))
845 serv
.privmsg(channel
,"%s: %s"%(auteur
,l1
[i
].encode("utf8")))
847 if __name__
=="__main__":
850 print "Usage : basile.py <serveur> [--debug]"
853 if "debug" in sys
.argv
or "--debug" in sys
.argv
:
857 serveurs
={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
858 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"}
860 serveur
=serveurs
[serveur
]
862 print "Server Unknown : %s"%(serveur)
864 basile
=Basile(serveur
,debug
)