]> gitweb.pimeys.fr Git - bots/basile.git/blob - basile.py
Basile est le bienvenu sur #note-dev
[bots/basile.git] / basile.py
1 #!/usr/bin/python
2 # -*- coding:utf8 -*-
3
4 # Codé par 20-100 (commencé le 23/04/12)
5
6 # Un bot IRC qui, un jour, s'interfacera avec la Note Kfet 2015
7
8 import irclib
9 import ircbot
10 import threading
11 import random
12 import time
13 import socket, ssl, json
14 import pickle
15 import re
16 import os
17 from commands import getstatusoutput as ex
18
19 import sys
20 config_debug_stdout=True
21 if "--quiet" in sys.argv:
22 config_debug_stdout=False
23
24 config_irc_password="NK2015BasileB0t"
25 config_irc_pseudo="Basile"
26 config_chanlist=["#bot","#flood","#note-dev"]
27 config_stay_channels=["#bot","#flood","#note-dev"]
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]_", "PEB"]
36 config_ops=["Nit"]
37 config_report_bugs_to=["[20-100]"]
38
39 # config "ce bot a été codé par 20-100, tu te rappelles ?"
40 config_manzana = ["[20-100]", "Petite-Peste"]
41 # config "mais PEB aussi est passé par là"
42 config_manzana_bis = ["PEB"]
43
44 # config "tu m'traites ?"
45 config_insultes=[u"conna(rd|sse)",u"pute",u"con(|ne)",u"enf(oiré|lure)",
46 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",
47 u"pétasse",u"enculé",u"chagasse",u"cagole",u"abruti",u"ahuri",u"analphabète",u"andouille",
48 u"atardé",u"avorton",u"bachibouzouk",u"(balais|brosse) (de|à) chiotte(|s)",
49 u"batard",u"blaireau",u"bouffon",u"branque",u"bouseux",u"branleur",u"catin",u"chacal",
50 u"charogne",u"chiant(|e)",u"chieur",u"cochon",u"coprophage",u"couillon",u"crapule",u"crevard",
51 u"cruche",u"cuistre",u"ducon",u"décérébré",
52 u"emmerdeur",u"feignasse",u"fainéant",u"fourbe",u"freluquet",u"frigide",
53 u"garce",u"glandu",u"gogol",u"goujat",u"gourdasse",u"gredin",u"gringalet",u"grognasse",
54 u"naze",u"truie",u"iconoclaste",
55 u"peigne(-|)cul",u"ignare",u"illétré",u"lèche(|-)cul",u"malotru",u"motherfucker",u"nabot",u"nigaud",
56 u"nul",u"escroc",u"pouffiasse",u"pourriture",u"raclure",u"relou",u"sagouin",u"putain",
57 u"péripatéticienne"]
58 config_insultes_answers=[
59 u"Oh non ! Quelle insulte ! Je crois que je ne m'en relèverai jamais…\nEnfin presque.",
60 u"J'entends comme un vague murmure, vous disiez ?",
61 u"Je vais prendre ça pour un compliment.",
62 u"Vous savez, pour vous c'est peut-être une insulte, mais pour moi ce n'est qu'une suite de 0 et de 1…",
63 u"Permettez-moi de vous retourner le compliment.",
64 u"Votre indélicatesse vous sied à ravir.",
65 u"Parfois, je me demande pourquoi je fais encore ce métier…",
66 u"Le saviez-vous : l'invective ne déshonore que son auteur.",
67 u"Le saviez-vous : vous perdez plus de temps à m'insulter qu'à vous taire.",
68 u"Mais je ne vous permets pas ! Enfin, pas comme ça…"]
69
70 # config "à peine quelques kilos octets"
71 config_gros=[u"gros",u"énorme",u"lourd"]
72 config_thisfile= os.path.realpath( __file__ )
73 def get_filesize():
74 return ex("ls -s %s"%(config_thisfile))[1].split()[0]
75
76 # config spéciale-iota
77 config_buffer_fail_answers=[u"Pas de chance !",u"Révisez vos classiques !",
78 u"Encore un effort, je sais que vous pouvez le faire. ;)",
79 u"Where did you learn to type?"]
80
81 # config "jeu", d'ailleurs, j'ai perdu.
82 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))"
83 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)"
84 config_regexp_etre_avec_c=u"c'(e(s|st)|étai(t|ent))"
85 config_regexp_faire=u"fais"
86 config_perdu=[u"perd(|s|ons|ez|ent|r(e|ai|as|a|ons|ez|ont)|(|r)(ais|ait|ions|iez|aient))"
87 u"perd(i(s|t|rent)|î(mes|tes|t))", # oui, j'ai inclus qu'il perdît
88 u"perdiss(e(|s|nt)|i(ons|ez))",
89 u"perdu(|s|e|es)",u"perdant(|s|e|es)",u"perte(|s)",
90
91 u"(gagn|trouv)"+config_premier_groupe_terminaisons,u"gagnant(|s|e|es)",u"gain(|s)",
92
93 u"trouvant",u"trouvaille(|s)",
94
95 u"victoire(|s)",u"vaincu(|s|e|es)",
96 u"loose",u"lost",u"looser(|s)",u"win(|ner)(|s)",
97 u"jeu(|x)",u"game(|s)"]
98 config_time_between_perdu_trigger=3600*3 #temps moyen pour perdre en l'absence de trigger
99 config_time_between_perdu_trigger_delta = 30*60 #marge autorisée autour de ^^^
100 config_time_between_perdu=30*60 #temps pendant lequel on ne peut pas perdre
101
102 # config "tais-toi"
103 config_tag_triggers=[u"t(|a)g",u"ta gueule",u"la ferme",u"ferme( |-)la",u"tais-toi",u"chut",u"tu fais trop de bruit",u"tu parles trop"]
104 config_tag_actions=[u"se tait",u"se tient coi"]
105 config_tag_answers=[
106 u"Ç'aurait été avec plaisir, mais je ne crois pas que vous puissiez vous passer de mes services.",
107 u"Dès que cela sera utile.",
108 u"Une autre fois, peut-être.",
109 u"Si je me tais, qui vous rappellera combien vous me devez ?",
110 u"J'aurais aimé accéder à votre requête, mais après mûre réflexion, j'en ai perdu l'envie.",
111 u"Je ne ressens pas de besoin irrésistible de me taire, navré."]
112
113 # config ping
114 config_tesla_triggers=[u"t('|u )es là \?",u"\?",u"plop \?",u"plouf \?"]
115 config_tesla_answers=[
116 u"Oui, je suis là.",
117 u"J'écoute.",
118 u"En quoi puis-je me rendre utile ?",
119 u"On a besoin de moi ?"
120 ]
121 config_tesla_actions=[u"est là",u"attend des instructions",u"est toujours disponible"]
122
123 # config en cas de non-insulte
124 config_compliment_triggers=[u"gentil",u"cool",u"sympa",u"efficace"]
125 config_compliment_answers=[
126 u"Merci, c'est gentil de votre part. :)",
127 u"Permettez-moi de vous retourner le compliment, sans ironie cette fois.",
128 u"Je vous remercie.",
129 u"C'est trop d'honneur.",
130 u"Vous êtes bien aimable."
131 ]
132
133 # config merci
134 config_merci_triggers=[u"merci",u"remercie",u"thx",u"thank(|s)"]
135 config_merci_answers=[u"Mais de rien.",u"À votre service. ;)",u"Quand vous voulez. :)",
136 u"Tout le plaisir est pour moi."]
137
138 # config "ta mère"
139 config_tamere_triggers=[u"ta mère"]
140 config_tamere_answers=[u"Laissez donc ma mère en dehors de ça !",
141 u"Puis-je préciser que je n'ai pas de mère ? Seulement deux pères…",
142 u"""Un certain Max chantait "♩ J'ai vu ta mère sur chat rouleeeeeeette ♫", vous êtes de sa famille ?""",
143 u"""N'avait-on pas dit "pas les mamans" ?"""]
144
145 # config pour les actions désagréables à Basile
146 config_bad_action_triggers=[u"(frappe|cogne|tape)(| sur)",u"(démolit|dégomme|fouette|agresse|tabasse)",
147 u"(vomit|pisse|chie|crache) sur",u"slap(|s)"]
148 config_bad_action_answers=[
149 u"Je ne peux pas dire que j'apprécie, mais je l'ai sans doute bien mérité.",
150 u"{}: Pourquoi tant de violence en ce monde si doux ?",
151 u"""Si je n'étais pas aussi prude, je dirais "Mais euh…", cependant, je me contenterai de hausser un sourcil.""",
152 u"{}: J'aurais préféré que vous ne fassiez pas cela en public.",
153 u"{}: Entre nous, cela vous gratifie-t-il ?",
154 u"{}: Une telle relation entre nous deux n'est pas saine, revenons à quelque chose de plus conventionnel. :D",
155 u"J'ai la désagréable impression que {} cherche comment tuer le temps en ce moment…"
156 ]
157 config_bad_action_actions=[u"prend de la distance, par précaution…",u"esquive",u"est bon pour prendre une semaine de repos… virtuel !",u"n'aime pas servir de souffre douleur, mais n'a malheureusement pas le choix", u"s'en souviendra sans doute longtemps… de quoi parlait-on déjà ?"]
158
159 # config pour les actions agréables à Basile
160 config_good_action_triggers=[u"fait (:?des bisous|un c(?:â|a)lin|des c(?:â|a)lins) à",u"embrasse",u"c(?:â|a)line",u"caresse"]
161 config_good_action_answers=[u":D",u"{}: Moi aussi je vous aime. ♡",u"Tant de délicatesse ne saurait être ignorée !",u"Pour une fois que quelqu'un me considère à ma juste valeur…"]
162 config_good_action_actions=[u"ronronne",u"aimerait exprimer avec des mots simples le bonheur que {} lui procure !",u"éprouve une joie indescriptible",u"apprécie que des personnes comme {} soient sur IRC, sans quoi il n'y aurait sans doute jamais personne pour tenir compte de lui"]
163
164 # config bonjour/bonsoir/que fais-tu encore debout à cette heure, gros sale !
165 config_bonjour_triggers=[u"(s|)(a|'|)lu(t|)",u"hello",u"pl(o|i)p",u"pr(ou|ü)t",u"bonjour",u"bonsoir",u"coucou"]
166 config_bonjour_answers=[u"Bien le bonjour, {}.",u"Bonjour {}.",u"{}: bonjour.",u"{}: Quel beau temps aujourd'hui (arrêtez-moi si je me trompe) !",u"Meteo: Cachan"]
167 config_bonsoir_answers=[u"Bonsoir {} !",u"{}: bonsoir.",u"Quel beau te… euh… bonsoir !",u"{}: Je cherche désespérément une formule pour vous dire bonsoir, mais j'avoue que mon lexique est un peu… limité."]
168 config_night_answers=[u"{}: vous m'avez fait peur, je m'étais assoupi !", u"Debout à une heure pareille, {} ? Que vous arrive-t-il ?",u"Vous venez prendre la relève, {} ?"]
169 config_daytime = [7,18]
170 config_nighttime = [3, 6]
171
172 # config dodo
173 config_bonne_nuit_triggers=[u"bonne nuit",u"'?nite",u"'?nuit",u"'?night",u"good night",u"'?nenuit"]
174 config_bonne_nuit_answers=[u"{}: thanks, make sweet dreams tonight ! ;)",u"Bonne nuit {}.",u"À demain {}. :)",u"{}: si seulement j'avais le droit de dormir… enfin, bonne nuit !",u"{}: à vous aussi !"]
175
176 # config PEB est encore en train d'abuser de ses droits.
177 config_kick_answers=[u"Suis-je de trop ici ?",u"{}: je m'excuse pour ce bruit indu qui a stimulé votre colère",u"{} a le /kick facile, sans doute la fatigue.",u"{}: j'ai l'impression que vous n'allez pas bien aujourd'hui, vous vous en prenez à un robot !"]
178 config_kick_actions=[u"sera désormais exemplaire",u"prépare une lettre d'excuses à {}",u"essaiera de ne plus s'attirer les foudres de {}",u"croyait avoir tout bien fait… cruelle déception."]
179
180 # config on m'a demandé de mourir/partir
181 config_quit_messages=[u"Bien que cela me désole, je me vois dans l'obligation de vous abandonner."]
182 config_leave_messages=config_quit_messages
183
184 class NKError(Exception):
185 def __init__(self,msg):
186 Exception.__init__(self)
187 self.msg=msg
188 def __str__(self):
189 return str(self.msg)
190 def __unicode__(self):
191 return unicode(self.msg)
192
193 class NKRefused(NKError):
194 pass
195
196 class NKHelloFailed(NKError):
197 pass
198
199 class NKUnknownError(NKError):
200 pass
201
202 def log(serveur,channel,auteur=None,message=None):
203 f=open(get_config_logfile(serveur),"a")
204 if auteur==message==None:
205 # alors c'est que c'est pas un channel mais juste une ligne de log
206 chain="%s %s"%(time.strftime("%F %T"),channel)
207 else:
208 chain="%s [%s:%s] %s"%(time.strftime("%F %T"),channel,auteur,message)
209 f.write(chain+"\n")
210 if config_debug_stdout:
211 print chain
212 f.close()
213
214 def connect_NK():
215 sock=socket.socket()
216 try:
217 # On établit la connexion sur port 4242
218 sock.connect(("127.0.0.1",4242))
219 # On passe en SSL
220 sock=ssl.wrap_socket(sock,ca_certs='../keys/ca_.crt')
221 # On fait un hello
222 sock.write('hello "Basile"')
223 # On récupère la réponse du hello
224 out=sock.read()
225 out=json.loads(out)
226 except Exception as exc:
227 # Si on a foiré quelque part, c'est que le serveur est down
228 raise NKRefused(str(exc))
229 if out["retcode"]==0:
230 return sock
231 elif out["retcode"]==11:
232 raise NKHelloFailed(out["errmsg"])
233 else:
234 raise NKUnknownError(out["errmsg"])
235
236 def login_NK(username,password,typ="bdd"):
237 sock=connect_NK()
238 if typ=="special": # ça c'est pour Basile lui-même
239 masque='["note"]'
240 elif typ=="bdd":
241 masque='[["all"],["all"],false]'
242 try:
243 # Basile a un compte special user
244 commande='login [%s,%s,"%s",%s]'%(json.dumps(username),json.dumps(password),typ,masque)
245 sock.write(commande)
246 out=sock.read()
247 except Exception as exc:
248 # Si on a foiré quelque part, c'est que le serveur est down
249 raise NKRefused(str(exc))
250 # On vérifie ensuite que le login
251 return json.loads(out),sock
252
253
254 def is_something(chain,matches,avant=u".*(?:^| )",apres=u"(?:$|\.| |,|;).*",case_sensitive=False,debug=False):
255 if case_sensitive:
256 chain=unicode(chain,"utf8")
257 else:
258 chain=unicode(chain,"utf8").lower()
259 allmatches="("+"|".join(matches)+")"
260 reg=(avant+allmatches+apres).lower()
261 o=re.match(reg,chain)
262 return o
263
264 def is_insult(chain,debug=True):
265 return is_something(chain,config_insultes,avant=".*(?:^| |')")
266 def is_not_insult(chain):
267 chain=unicode(chain,"utf8")
268 insult_regexp=u"("+u"|".join(config_insultes)+u")"
269 middle_regexp=u"(une? (?:(?:putain|enfoiré) d(?:e |'))*|)(?:| super )(?: (?:gros|petit|grand|énorme) |)"
270 reg=".*pas %s%s.*"%(middle_regexp,insult_regexp)
271 if re.match(reg,chain):
272 return True
273 else:
274 return False
275 def is_compliment(chain,debug=True):
276 return is_something(chain,config_compliment_triggers,avant=".*(?:^| |')")
277 def is_perdu(chain):
278 return is_something(chain,config_perdu)
279 def is_tag(chain):
280 return is_something(chain,config_tag_triggers)
281 def is_gros(chain):
282 return is_something(chain,config_gros)
283 def is_tesla(chain):
284 return is_something(chain,config_tesla_triggers,avant=u"^",apres=u"$",debug=True)
285 def is_merci(chain):
286 return is_something(chain,config_merci_triggers)
287 def is_tamere(chain):
288 return is_something(chain,config_tamere_triggers)
289 def is_bad_action_trigger(chain,pseudo):
290 return is_something(chain,config_bad_action_triggers,avant=u"^",
291 apres="(?: [a-z]*ment)? %s($|\.| |,|;).*"%(pseudo))
292 def is_good_action_trigger(chain,pseudo):
293 return is_something(chain,config_good_action_triggers,avant=u"^",
294 apres="(?: [a-z]*ment)? %s($|\.| |,|;).*"%(pseudo))
295 def is_bonjour(chain):
296 return is_something(chain,config_bonjour_triggers,avant=u"^")
297 def is_bonne_nuit(chain):
298 return is_something(chain,config_bonne_nuit_triggers,avant=u"^")
299 def is_pan(chain):
300 return re.match(u"^(pan|bim|bang)( .*)?$",unicode(chain,"utf8").lower().strip())
301
302 def is_time(conf):
303 _,_,_,h,m,s,_,_,_=time.localtime()
304 return (conf[0],0,0)<(h,m,s)<(conf[1],0,0)
305 def is_day():
306 return is_time(config_daytime)
307 def is_night():
308 return is_time(config_nighttime)
309
310
311 class UnicodeBotError(Exception):
312 pass
313 def bot_unicode(chain):
314 try:
315 unicode(chain,"utf8")
316 except UnicodeDecodeError as exc:
317 raise UnicodeBotError
318
319 class Basile(ircbot.SingleServerIRCBot):
320 def __init__(self,serveur,debug=False):
321 temporary_pseudo=config_irc_pseudo+str(random.randrange(10000,100000))
322 ircbot.SingleServerIRCBot.__init__(self, [(serveur, 6667)],
323 temporary_pseudo,"Basile, le bot irc.[Codé par 20-100, fouettez-le]", 10)
324 self.debug=debug
325 self.serveur=serveur
326 self.overops=config_overops
327 self.ops=self.overops+config_ops
328 self.report_bugs_to=config_report_bugs_to
329 self.chanlist=config_chanlist
330 self.identities=pickle.load(open("identities.pickle","r"))
331 self.stay_channels=config_stay_channels
332 self.quiet_channels=config_quiet_channels
333 self.last_perdu=0
334
335
336 def new_connection_NK(self,serv,username,password,typ="bdd"):
337 try:
338 login_result,sock=login_NK(username,password,typ)
339 droits,retcode,errmsg=login_result["msg"],login_result["retcode"],login_result["errmsg"]
340 except NKRefused as exc:
341 for report in self.report_bugs_to:
342 serv.privmsg(report,"Le Serveur NK2015 est down.")
343 return (False,None)
344 except NKHelloFailed as exc:
345 for report in self.report_bugs_to:
346 serv.privmsg(report,
347 "La version du site utilisée n'est pas supportée par le serveur NK2015.")
348 return (False,None)
349 except NKUnknownError as exc:
350 erreurs=["Une fucking erreur inconnue s'est produite"]
351 erreurs+=str(exc).split("\n")
352 for report in self.report_bugs_to:
353 for err in erreurs:
354 serv.privmsg(report,err)
355 return (False,None)
356 except Exception as exc:
357 # Exception qui ne vient pas de la communication avec le serveur NK2015
358 log(self.serveur,"Erreur dans new_connection_NK\n"+str(exc))
359 return (False,None)
360 if retcode==0:
361 return (True,sock)
362 else:
363 return (False,None)
364
365 def give_me_my_pseudo(self,serv):
366 serv.privmsg("NickServ","RECOVER %s %s"%(config_irc_pseudo,config_irc_password))
367 serv.privmsg("NickServ","RELEASE %s %s"%(config_irc_pseudo,config_irc_password))
368 time.sleep(0.3)
369 serv.nick(config_irc_pseudo)
370
371 def on_welcome(self, serv, ev):
372 self.serv=serv # ça serv ira :)
373 self.give_me_my_pseudo(serv)
374 serv.privmsg("NickServ","identify %s"%(config_irc_password))
375 log(self.serveur,"Connected")
376 if self.debug:
377 self.chanlist=["#bot"]
378 else:
379 serv.privmsg("ChanServ INVITE #note-dev")
380 for c in self.chanlist:
381 log(self.serveur,"JOIN %s"%(c))
382 serv.join(c)
383 # on ouvre la connexion note de Basile, special user
384 self.nk=self.new_connection_NK(serv,config_note_pseudo,config_note_password,"special")[1]
385 if self.nk==None:
386 for report in self.report_bugs_to:
387 serv.privmsg(report,"Connection to NK2015 failed, invalid password ?")
388
389 def lost(self,serv,channel,forced=False):
390 if self.last_perdu+config_time_between_perdu<time.time() or forced:
391 if not channel in self.quiet_channels or forced:
392 serv.privmsg(channel,"J'ai perdu !")
393 self.last_perdu=time.time()
394 delay=config_time_between_perdu_trigger
395 delta=config_time_between_perdu_trigger_delta
396 serv.execute_delayed(random.randrange(delay-delta,delay+delta),self.lost,(serv,channel))
397
398 def pourmoi(self, serv, message):
399 """renvoie (False,lemessage) ou (True, le message amputé de "pseudo: ")"""
400 pseudo=self.nick
401 size=len(pseudo)
402 if message[:size]==pseudo and len(message)>size and message[size]==":":
403 return (True,message[size+1:].lstrip(" "))
404 else:
405 return (False,message)
406
407 def on_privmsg(self, serv, ev):
408 message=ev.arguments()[0]
409 auteur = irclib.nm_to_n(ev.source())
410 try:
411 test=bot_unicode(message)
412 except UnicodeBotError:
413 serv.privmsg(auteur,
414 "Si je n'avais pas été créé avec la plus grande attention, votre encodage aurait eu raison de moi…")
415 return
416 message=message.split()
417 cmd=message[0].lower()
418 notunderstood=False
419 if cmd=="help":
420 helpdico={"help":["""HELP <commande>
421 Affiche de l'aide sur la commande""",None,None],
422 "identify": ["""IDENTIFY <username> <password>
423 Vérifie le mot de passe et me permet de savoir à l'avenir quel est votre pseudo note kfet.
424 Sans paramètre, je vous précise sous quel pseudo je vous connais.""",None,None],
425 "drop":["""DROP <password>
426 Vérifie le mot de passe et me fait d'oublier votre pseudo note kfet.""",None,None],
427 "solde": ["""SOLDE
428 Affiche votre solde, si je connais votre pseudo note kfet.""",
429 """SOLDE <pseudo>
430 Affiche le solde de la personne désignée (par son pseudo note).""",None],
431 "join": [None, """JOIN <channel>
432 Me fait rejoindre le channel""",None],
433 "leave": [None,"""LEAVE <channel>
434 Me fait quitter le channel (sauf s'il est dans ma stay_list).""",None],
435 "quiet": [None,"""QUIET <channel>
436 Me rend silencieux sur le channel.""",None],
437 "noquiet": [None,"""NOQUIET <channel>
438 Me rend la parole sur le channel.""",None],
439 "lost": [None,"""LOST <channel>
440 Me fait perdre sur le channel.""",None],
441 "reconnect": [None,"""RECONNECT
442 Établit à nouveau la connexion avec le serveur NK2015""",None],
443 "say": [None,None,"""SAY <channel> <message>
444 Me fait parler sur le channel."""],
445 "do": [None,None,"""DO <channel> <action>
446 Me fait faitre une action (/me) sur le channel."""],
447 "stay": [None,None,"""STAY <channel>
448 Ajoute le channel à ma stay_list."""],
449 "nostay": [None,None,"""NOSTAY <channel>
450 Retire le channel de ma stay_list."""],
451 "ops": [None,None,"""OPS
452 Affiche la liste des ops."""],
453 "overops": [None,None,"""OVEROPS
454 Affiche la liste des overops."""],
455 "kick": [None,None,"""KICK <channel> <pseudo> [<raison>]
456 Kicke <pseudo> du channel (Il faut bien entendu que j'y sois op)."""],
457 "die": [None,None,"""DIE
458 Me déconnecte du serveur IRC."""]
459 }
460 helpmsg_default="Liste des commandes disponibles :\nHELP IDENTIFY DROP SOLDE"
461 helpmsg_ops=" JOIN LEAVE QUIET NOQUIET LOST RECONNECT"
462 helpmsg_overops=" SAY DO STAY NOSTAY OPS OVEROPS KICK DIE"
463 op,overop=auteur in self.ops, auteur in self.overops
464 if len(message)==1:
465 helpmsg=helpmsg_default
466 if op:
467 helpmsg+=helpmsg_ops
468 if overop:
469 helpmsg+=helpmsg_overops
470 else:
471 helpmsgs=helpdico.get(message[1].lower(),["Commande inconnue.",None,None])
472 helpmsg=helpmsgs[0]
473 if op and helpmsgs[1]:
474 if helpmsg:
475 helpmsg+="\n"+helpmsgs[1]
476 else:
477 helpmsg=helpmsgs[1]
478 if overop and helpmsgs[2]:
479 if helpmsg:
480 helpmsg+="\n"+helpmsgs[2]
481 else:
482 helpmsg=helpmsgs[2]
483 for ligne in helpmsg.split("\n"):
484 serv.privmsg(auteur,ligne)
485 elif cmd=="identify":
486 if len(message)==1:
487 if self.identities.has_key(auteur):
488 serv.privmsg(auteur,"Je vous connais sous le pseudo note %s."%(
489 self.identities[auteur].encode("utf8")))
490 else:
491 serv.privmsg(auteur,"Je ne connais pas votre pseudo note.")
492 elif len(message)>=3:
493 username,password=message[1],unicode(" ".join(message[2:]),"utf8")
494 success,_=self.new_connection_NK(serv,username,password)
495 if success:
496 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
497 serv.privmsg(auteur,"Identité enregistrée.")
498 self.identities[auteur]=username
499 pickle.dump(Xself.identities,open("identities.pickle","w"))
500 else:
501 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
502 serv.privmsg(auteur,"Mot de passe invalide. (ou serveur down)")
503 else:
504 serv.privmsg(auteur,u"Syntaxe : IDENTIFY [<username> <password>]")
505 elif cmd=="drop":
506 if len(message)>1:
507 if self.identities.has_key(auteur):
508 password=" ".join(message[1:])
509 success,_=self.new_connection_NK(serv,self.identities[auteur],password)
510 if success:
511 del self.identities[auteur]
512 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
513 pickle.dump(self.identities,open("identities.pickle","w"))
514 serv.privmsg(auteur,"Identité oubliée.")
515 else:
516 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
517 serv.privmsg(auteur,"Mot de passe invalide. (ou serveur down)")
518 else:
519 serv.privmsg(auteur,"Je ne connais pas ton pseudo note.")
520 else:
521 serv.privmsg(auteur,"Syntaxe : DROP <password>")
522 elif cmd=="join":
523 if auteur in self.ops:
524 if len(message)>1:
525 if message[1] in self.chanlist:
526 serv.privmsg(auteur,"Je suis déjà sur %s"%(message[1]))
527 else:
528 serv.join(message[1])
529 self.chanlist.append(message[1])
530 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
531 log(self.serveur,"priv",auteur," ".join(message))
532 else:
533 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
534 else:
535 notunderstood=True
536 elif cmd=="leave":
537 if auteur in self.ops and len(message)>1:
538 if message[1] in self.chanlist:
539 if not (message[1] in self.stay_channels) or auteur in self.overops:
540 self.quitter(message[1]," ".join(message[2:]))
541 self.chanlist.remove(message[1])
542 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
543 else:
544 serv.privmsg(auteur,"Non, je reste !")
545 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
546 else:
547 serv.privmsg(auteur,"Je ne suis pas sur %s"%(message[1]))
548 else:
549 notunderstood=True
550 elif cmd=="stay":
551 if auteur in self.overops:
552 if len(message)>1:
553 if message[1] in self.stay_channels:
554 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
555 serv.privmsg(auteur,"Je stay déjà sur %s."%(message[1]))
556 else:
557 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
558 self.stay_channels.append(message[1])
559 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
560 else:
561 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
562 else:
563 notunderstood=True
564 elif cmd=="nostay":
565 if auteur in self.overops:
566 if len(message)>1:
567 if message[1] in self.stay_channels:
568 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
569 self.stay_channels.remove(message[1])
570 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
571 else:
572 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
573 serv.privmsg(auteur,"Je ne stay pas sur %s."%(message[1]))
574
575 else:
576 notunderstood=True
577 elif cmd=="die":
578 if auteur in self.overops:
579 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
580 self.mourir()
581 else:
582 notunderstood=True
583 elif cmd=="reconnect":
584 if auteur in self.ops:
585 try:
586 self.nk=self.new_connection_NK(serv,config_note_pseudo,
587 config_note_password,"special")[1]
588 except Exception as exc:
589 self.nk=None
590 log(self.serveur,"""Erreur dans on_pubmsg/"cmd in ["reconnect"]\n"""+str(exc))
591 if self.nk!=None:
592 serv.privmsg(auteur,"%s: done"%(auteur))
593 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
594 else:
595 serv.privmsg(auteur,"%s: failed"%(auteur))
596 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
597 for report in self.report_bugs_to:
598 serv.privmsg(report,"Connection to NK2015 failed, invalid password ? Server dead ?")
599 else:
600 notunderstood=True
601 elif cmd=="quiet":
602 if auteur in self.ops:
603 if len(message)>1:
604 if message[1] in self.quiet_channels:
605 serv.privmsg(auteur,"Je me la ferme déjà sur %s"%(message[1]))
606 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
607 else:
608 self.quiet_channels.append(message[1])
609 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
610 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
611 else:
612 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
613 else:
614 notunderstood=True
615 elif cmd=="noquiet":
616 if auteur in self.ops:
617 if len(message)>1:
618 if message[1] in self.quiet_channels:
619 self.quiet_channels.remove(message[1])
620 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
621 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
622 else:
623 serv.privmsg(auteur,"Je ne me la ferme pas sur %s."%(message[1]))
624 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
625 else:
626 notunderstood=True
627 elif cmd=="say":
628 if auteur in self.overops and len(message)>2:
629 serv.privmsg(message[1]," ".join(message[2:]))
630 log(self.serveur,"priv",auteur," ".join(message))
631 elif len(message)<=2:
632 serv.privmsg(auteur,"Syntaxe : SAY <channel> <message>")
633 else:
634 notunderstood=True
635 elif cmd=="do":
636 if auteur in self.overops and len(message)>2:
637 serv.action(message[1]," ".join(message[2:]))
638 log(self.serveur,"priv",auteur," ".join(message))
639 elif len(message)<=2:
640 serv.privmsg(auteur,"Syntaxe : DO <channel> <action>")
641 else:
642 notunderstood=True
643 elif cmd=="kick":
644 if auteur in self.overops and len(message)>2:
645 serv.kick(message[1],message[2]," ".join(message[3:]))
646 log(self.serveur,"priv",auteur," ".join(message))
647 elif len(message)<=2:
648 serv.privmsg(auteur,"Syntaxe : KICK <channel> <pseudo> [<raison>]")
649 else:
650 notunderstood=True
651 elif cmd=="lost":
652 if auteur in self.ops and len(message)>1:
653 serv.privmsg(message[1],"J'ai perdu !")
654 log(self.serveur,"priv",auteur," ".join(message))
655 elif len(message)<=1:
656 serv.privmsg(auteur,"Syntaxe : LOST <channel>")
657 else:
658 notunderstood=True
659 elif cmd=="solde":
660 if len(message)==1:
661 if self.identities.has_key(auteur):
662 try:
663 self.nk.write('search ["x",["pseudo"],%s]'%(json.dumps(self.identities[auteur])))
664 ret=json.loads(self.nk.read())
665 solde=ret["msg"][0]["solde"]
666 pseudo=ret["msg"][0]["pseudo"]
667 except Exception as exc:
668 print exc
669 serv.privmsg(auteur,"failed")
670 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
671 return
672 serv.privmsg(auteur,"%s (%s)"%(float(solde)/100,pseudo.encode("utf8")))
673 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
674 else:
675 serv.privmsg(canal,"Je ne connais pas ton pseudo note.")
676 elif auteur in self.ops:
677 try:
678 self.nk.write('search ["x",["pseudo"],%s]'%(json.dumps(message[1])))
679 ret=json.loads(self.nk.read())
680 solde=ret["msg"][0]["solde"]
681 pseudo=ret["msg"][0]["pseudo"]
682 except Exception as exc:
683 serv.privmsg(auteur,"failed")
684 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
685 return
686 serv.privmsg(auteur,"%s (%s)"%(float(solde)/100,pseudo.encode("utf8")))
687 elif cmd=="ops":
688 if auteur in self.overops:
689 serv.privmsg(auteur," ".join(self.ops))
690 else:
691 notunderstood=True
692 elif cmd=="overops":
693 if auteur in self.overops:
694 serv.privmsg(auteur," ".join(self.overops))
695 else:
696 notunderstood=True
697 else:
698 notunderstood=True
699 if notunderstood:
700 serv.privmsg(auteur,"Je n'ai pas compris. Essayez HELP…")
701
702 def on_pubmsg(self, serv, ev):
703 auteur = irclib.nm_to_n(ev.source())
704 canal = ev.target()
705 message = ev.arguments()[0]
706 try:
707 test=bot_unicode(message)
708 except UnicodeBotError:
709 if not canal in self.quiet_channels:
710 serv.privmsg(canal,
711 "%s: Si je n'avais pas été créé avec la plus grande attention, votre encodage aurait eu raison de moi…"%(auteur))
712 return
713 pour_moi,message=self.pourmoi(serv,message)
714 if pour_moi and message.split()!=[]:
715 cmd=message.split()[0].lower()
716 try:
717 args=" ".join(message.split()[1:])
718 except:
719 args=""
720 if cmd in ["meurs","die","crève"]:
721 if auteur in self.overops:
722 log(self.serveur,canal,auteur,message+"[successful]")
723 self.mourir()
724 else:
725 serv.privmsg(canal,"%s: mourrez vous-même !"%(auteur))
726 log(self.serveur,canal,auteur,message+"[failed]")
727
728 elif cmd in ["part","leave","dégage","va-t-en","tut'tiresailleurs,c'estmesgalets"]:
729 if auteur in self.ops and (not (canal in self.stay_channels)
730 or auteur in self.overops):
731 self.quitter(canal)
732 log(self.serveur,canal,auteur,message+"[successful]")
733 if canal in self.chanlist:
734 self.chanlist.remove(canal)
735 else:
736 serv.privmsg(canal,"%s: Navré, mais je me vois contraint de refuser, je ne peux pas céder aux exigences du premier venu."%(auteur))
737 log(self.serveur,canal,auteur,message+"[failed]")
738
739 elif cmd in ["reconnect"]:
740 if auteur in self.ops:
741 try:
742 self.nk=self.new_connection_NK(serv,config_note_pseudo,
743 config_note_password,"special")[1]
744 except Exception as exc:
745 self.nk=None
746 log(self.serveur,"""Erreur dans on_pubmsg/"cmd in ["reconnect"]\n"""+str(exc))
747 if self.nk!=None:
748 serv.privmsg(canal,"%s: done"%(auteur))
749 log(self.serveur,canal,auteur,message+"[successful]")
750 else:
751 serv.privmsg(canal,"%s: failed"%(auteur))
752 log(self.serveur,canal,auteur,message+"[failed]")
753 for report in self.report_bugs_to:
754 serv.privmsg(report,"Connection to NK2015 failed, invalid password ? Server dead ?")
755 else:
756 serv.privmsg(canal,"%s: Encore eût-il fallu que je sois programmé pour vous obéir !"%(auteur))
757 log(self.serveur,canal,auteur,message+"[failed]")
758
759 elif cmd in ["deviens","pseudo"]:
760 if auteur in self.ops:
761 become=args
762 serv.nick(become)
763 log(self.serveur,canal,auteur,message+"[successful]")
764
765 if cmd in ["meur", "meurt","meurre","meurres"] and not canal in self.quiet_channels:
766 serv.privmsg(canal,'%s: Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)'%(auteur))
767 elif cmd in ["ping"] and not canal in self.quiet_channels:
768 serv.privmsg(canal,"%s: pong"%(auteur))
769
770 elif cmd in ["solde","!solde"]:
771 if self.identities.has_key(auteur):
772 pseudo=self.identities[auteur]
773 try:
774 self.nk.write('search ["x",["pseudo"],%s]'%(json.dumps(pseudo)))
775 ret=json.loads(self.nk.read())
776 solde=ret["msg"][0]["solde"]
777 pseudo=ret["msg"][0]["pseudo"]
778 except Exception as exc:
779 serv.privmsg(canal,"%s: failed"%(auteur))
780 log(self.serveur,canal,auteur,message+"[failed]")
781 else:
782 serv.privmsg(canal,"%s: %s (%s)"%(auteur,float(solde)/100,pseudo.encode("utf8")))
783 log(self.serveur,canal,auteur,message+"[successful]")
784 else:
785 serv.privmsg(canal,"%s: Je ne connais pas votre pseudo note."%(auteur))
786 log(self.serveur,canal,auteur,message+"[unknown]")
787 elif (re.match("!?(pain au chocolat|chocolatine)",message.lower())
788 and not canal in self.quiet_channels):
789 serv.action(canal,"sert un pain au chocolat à %s"%(auteur))
790 elif re.match("!?manzana",message.lower()) and not canal in self.quiet_channels:
791 if auteur in config_manzana:
792 serv.action(canal,"sert une bouteille de manzana à %s"%(auteur))
793 elif auteur in config_manzana_bis:
794 serv.action(canal,"sert un grand verre de jus de pomme à %s : tout le monde sait qu'il ne boit pas."%(auteur))
795 else:
796 serv.action(canal,"sert un verre de manzana à %s"%(auteur))
797 if is_insult(message) and not canal in self.quiet_channels:
798 if is_not_insult(message):
799 answer=random.choice(config_compliment_answers)
800 for ligne in answer.split("\n"):
801 serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
802 else:
803 answer=random.choice(config_insultes_answers)
804 for ligne in answer.split("\n"):
805 serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
806 elif is_compliment(message) and not canal in self.quiet_channels:
807 answer=random.choice(config_compliment_answers)
808 for ligne in answer.split("\n"):
809 serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
810 gros_match=is_gros(message)
811 if gros_match and not canal in self.quiet_channels:
812 taille=get_filesize()
813 answer=u"Mais non, je ne suis pas %s, %sKo tout au plus…"%(gros_match.groups()[0],taille)
814 serv.privmsg(canal,"%s: %s"%(auteur,answer.encode("utf8")))
815 if is_tesla(message) and not canal in self.quiet_channels:
816 l1,l2=config_tesla_answers,config_tesla_actions
817 n1,n2=len(l1),len(l2)
818 i=random.randrange(n1+n2)
819 if i>=n1:
820 serv.action(canal,l2[i-n1].encode("utf8"))
821 else:
822 serv.privmsg(canal,"%s: %s"%(auteur,l1[i].encode("utf8")))
823 if is_tamere(message) and not canal in self.quiet_channels:
824 answer=random.choice(config_tamere_answers)
825 for ligne in answer.split("\n"):
826 serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
827 if is_tag(message) and not canal in self.quiet_channels:
828 if auteur in self.ops:
829 action=random.choice(config_tag_actions)
830 serv.action(canal,action.encode("utf8"))
831 self.quiet_channels.append(canal)
832 else:
833 answer=random.choice(config_tag_answers)
834 for ligne in answer.split("\n"):
835 serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
836 if is_merci(message):
837 answer=random.choice(config_merci_answers)
838 for ligne in answer.split("\n"):
839 serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
840 out=re.match(ur"^([A-Z[]|\\|[0-9]+|(¹|²|³|⁴|⁵|⁶|⁷|⁸|⁹|⁰)+)(?:| \?| !)$",
841 unicode(message.upper(),"utf8"))
842 if re.match("ma bite dans ton oreille",message) and not canal in self.quiet_channels:
843 serv.privmsg(canal,"%s: Seul un olasd peut imiter un olasd dans un de ses grands jours !"%(auteur))
844 if out and not canal in self.quiet_channels:
845 out=out.groups()[0]
846 try:
847 out=int(out)
848 serv.privmsg(canal,"%s: %s !"%(auteur,out+1))
849 if out==2147483647:
850 serv.privmsg(canal,"%s: Ciel, un maxint ! Heureusement que je suis en python…"%(auteur))
851 return
852 if out+1>1000 and random.randrange(4)==0:
853 serv.privmsg(canal,"%s: Vous savez, moi et les chiffres…"%(auteur))
854 return
855 except Exception as exc:
856 pass
857 if re.match("[A-Y]",out):
858 alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
859 serv.privmsg(canal,"%s: %s !"%(auteur,alphabet[alphabet.index(out)+1]))
860 elif out=="Z":
861 serv.privmsg(canal,"%s: Je ne vous remercie pas, j'ai l'air idiot ainsi… [ ?"%(auteur))
862 elif out in "[\\":
863 serv.privmsg(canal,"%s: Nous devrions nous en tenir là, ça va finir par poser des problèmes…"%(auteur))
864 elif re.match(ur"(¹|²|³|⁴|⁵|⁶|⁷|⁸|⁹|⁰)+",out):
865 def translate(mess):
866 return "".join([{u"⁰¹²³⁴⁵⁶⁷⁸⁹0123456789"[i]:u"0123456789⁰¹²³⁴⁵⁶⁷⁸⁹"[i]
867 for i in range(20)}[j]
868 for j in mess])
869 out=int(translate(out))
870 serv.privmsg(canal,"%s: %s !"%(auteur,translate(str(out+1)).encode("utf8")))
871 if is_bonjour(message) and not canal in self.quiet_channels:
872 if is_night():
873 answer=random.choice(config_night_answers)
874 elif is_day():
875 answer=random.choice(config_bonjour_answers)
876 else:
877 answer=random.choice(config_bonsoir_answers)
878 serv.privmsg(canal,answer.format(auteur).encode("utf8"))
879 if is_bonne_nuit(message) and not canal in self.quiet_channels:
880 answer=random.choice(config_bonne_nuit_answers)
881 serv.privmsg(canal,answer.format(auteur).encode("utf8"))
882 if is_pan(message) and not canal in self.quiet_channels:
883 serv.privmsg(canal,"%s: ce n'est pas sur moi qu'il faut tirer, même si je sais que j'attire l'œil !"%(auteur))
884 else:
885 if message in ["!pain au chocolat","!chocolatine"] and not canal in self.quiet_channels:
886 serv.action(canal,"sert un pain au chocolat à %s"%(auteur))
887 if message in ["!manzana"] and not canal in self.quiet_channels:
888 if auteur in config_manzana:
889 serv.action(canal,"sert une bouteille de manzana à %s"%(auteur))
890 elif auteur in config_manzana_bis:
891 serv.action(canal,"sert un grand verre de jus de pomme à %s : tout le monde sait qu'il ne boit pas."%(auteur))
892 else:
893 serv.action(canal,"sert un verre de manzana à %s"%(auteur))
894 if re.match(u'^ *(.|§|!|/|/|:|)(w|b) [0-9]+$',message.decode("utf8")) and not canal in self.quiet_channels:
895 failanswers=config_buffer_fail_answers
896 answer=random.choice(failanswers)
897 serv.privmsg(canal,("%s: %s"%(auteur,answer)).encode("utf8"))
898 if not canal in self.quiet_channels:
899 mypseudo=self.nick
900 if re.match((u"^("+u"|".join(config_bonjour_triggers)
901 +u")( {}| all| tout le monde|(|à) tous)(\.|( |)!|)$"
902 ).format(mypseudo).lower(), message.strip().lower()):
903 answer=random.choice(config_bonjour_answers)
904 serv.privmsg(canal,answer.format(auteur).encode("utf8"))
905 if (is_perdu(message) and not canal in self.quiet_channels):
906 # proba de perdre sur trigger :
907 # avant 30min (enfin, config) : 0
908 # ensuite, +25%/30min, linéairement
909 deltat=time.time()-self.last_perdu
910 barre=(deltat-config_time_between_perdu)/(2*3600.0)
911 if random.uniform(0,1)<barre:
912 serv.privmsg(canal,"%s: J'ai perdu !"%(auteur))
913 self.last_perdu=time.time()
914
915 def on_action(self, serv, ev):
916 action = ev.arguments()[0]
917 auteur = irclib.nm_to_n(ev.source())
918 channel = ev.target()
919 try:
920 test=bot_unicode(action)
921 except UnicodeBotError:
922 serv.privmsg(channel,
923 "%s: Si je n'avais pas été créé avec la plus grande attention, votre encodage m'aurait déjà tué…"%(auteur))
924 return
925 mypseudo=self.nick
926
927 if is_bad_action_trigger(action,mypseudo) and not channel in self.quiet_channels:
928 l1,l2=config_bad_action_answers,config_bad_action_actions
929 n1,n2=len(l1),len(l2)
930 i=random.randrange(n1+n2)
931 if i>=n1:
932 serv.action(channel,l2[i-n1].format(auteur).encode("utf8"))
933 else:
934 serv.privmsg(channel,l1[i].format(auteur).format(auteur).encode("utf8"))
935 if is_good_action_trigger(action,mypseudo) and not channel in self.quiet_channels:
936 l1,l2=config_good_action_answers,config_good_action_actions
937 n1,n2=len(l1),len(l2)
938 i=random.randrange(n1+n2)
939 if i>=n1:
940 serv.action(channel,l2[i-n1].format(auteur).format(auteur).encode("utf8"))
941 else:
942 serv.privmsg(channel,l1[i].format(auteur).format(auteur).encode("utf8"))
943
944 def on_kick(self,serv,ev):
945 auteur = irclib.nm_to_n(ev.source())
946 channel = ev.target()
947 victime = ev.arguments()[0]
948 raison = ev.arguments()[1]
949 if victime==self.nick:
950 log(self.serveur,"%s kické de %s par %s (raison : %s)" %(victime,channel,auteur,raison))
951 time.sleep(2)
952 serv.join(channel)
953 l1,l2=config_kick_answers,config_kick_actions
954 n1,n2=len(l1),len(l2)
955 i=random.randrange(n1+n2)
956 if i>=n1:
957 serv.action(channel,l2[i-n1].format(auteur).encode("utf8"))
958 else:
959 serv.privmsg(channel,l1[i].format(auteur).encode("utf8"))
960
961 def quitter(self,chan,leave_message=None):
962 if leave_message==None:
963 leave_message=random.choice(config_leave_messages)
964 self.serv.part(chan,message=leave_message.encode("utf8"))
965
966 def mourir(self):
967 quit_message=random.choice(config_quit_messages)
968 self.die(msg=quit_message.encode("utf8"))
969
970 def _getnick(self):
971 return self.serv.get_nickname()
972 nick=property(_getnick)
973
974
975 if __name__=="__main__":
976 import sys
977 if len(sys.argv)==1:
978 print "Usage : basile.py <serveur> [--debug]"
979 exit(1)
980 serveur=sys.argv[1]
981 if "debug" in sys.argv or "--debug" in sys.argv:
982 debug=True
983 else:
984 debug=False
985 serveurs={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
986 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"}
987 try:
988 serveur=serveurs[serveur]
989 except KeyError:
990 print "Server Unknown : %s"%(serveur)
991 exit(404)
992 basile=Basile(serveur,debug)
993 basile.start()