]> gitweb.pimeys.fr Git - bots/basile.git/blob - basile.py
de3eee9f617570f8432b73c8ea9821054ad8fd51
[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"]
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]_", "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 for c in self.chanlist:
379 log(self.serveur,"JOIN %s"%(c))
380 serv.join(c)
381 # on ouvre la connexion note de Basile, special user
382 self.nk=self.new_connection_NK(serv,config_note_pseudo,config_note_password,"special")[1]
383 if self.nk==None:
384 for report in self.report_bugs_to:
385 serv.privmsg(report,"Connection to NK2015 failed, invalid password ?")
386
387 def lost(self,serv,channel,forced=False):
388 if self.last_perdu+config_time_between_perdu<time.time() or forced:
389 if not channel in self.quiet_channels or forced:
390 serv.privmsg(channel,"J'ai perdu !")
391 self.last_perdu=time.time()
392 delay=config_time_between_perdu_trigger
393 delta=config_time_between_perdu_trigger_delta
394 serv.execute_delayed(random.randrange(delay-delta,delay+delta),self.lost,(serv,channel))
395
396 def pourmoi(self, serv, message):
397 """renvoie (False,lemessage) ou (True, le message amputé de "pseudo: ")"""
398 pseudo=self.nick
399 size=len(pseudo)
400 if message[:size]==pseudo and len(message)>size and message[size]==":":
401 return (True,message[size+1:].lstrip(" "))
402 else:
403 return (False,message)
404
405 def on_privmsg(self, serv, ev):
406 message=ev.arguments()[0]
407 auteur = irclib.nm_to_n(ev.source())
408 try:
409 test=bot_unicode(message)
410 except UnicodeBotError:
411 serv.privmsg(auteur,
412 "Si je n'avais pas été créé avec la plus grande attention, votre encodage aurait eu raison de moi…")
413 return
414 message=message.split()
415 cmd=message[0].lower()
416 notunderstood=False
417 if cmd=="help":
418 helpdico={"help":["""HELP <commande>
419 Affiche de l'aide sur la commande""",None,None],
420 "identify": ["""IDENTIFY <username> <password>
421 Vérifie le mot de passe et me permet de savoir à l'avenir quel est votre pseudo note kfet.
422 Sans paramètre, je vous précise sous quel pseudo je vous connais.""",None,None],
423 "drop":["""DROP <password>
424 Vérifie le mot de passe et me fait d'oublier votre pseudo note kfet.""",None,None],
425 "solde": ["""SOLDE
426 Affiche votre solde, si je connais votre pseudo note kfet.""",
427 """SOLDE <pseudo>
428 Affiche le solde de la personne désignée (par son pseudo note).""",None],
429 "join": [None, """JOIN <channel>
430 Me fait rejoindre le channel""",None],
431 "leave": [None,"""LEAVE <channel>
432 Me fait quitter le channel (sauf s'il est dans ma stay_list).""",None],
433 "quiet": [None,"""QUIET <channel>
434 Me rend silencieux sur le channel.""",None],
435 "noquiet": [None,"""NOQUIET <channel>
436 Me rend la parole sur le channel.""",None],
437 "lost": [None,"""LOST <channel>
438 Me fait perdre sur le channel.""",None],
439 "reconnect": [None,"""RECONNECT
440 Établit à nouveau la connexion avec le serveur NK2015""",None],
441 "say": [None,None,"""SAY <channel> <message>
442 Me fait parler sur le channel."""],
443 "do": [None,None,"""DO <channel> <action>
444 Me fait faitre une action (/me) sur le channel."""],
445 "stay": [None,None,"""STAY <channel>
446 Ajoute le channel à ma stay_list."""],
447 "nostay": [None,None,"""NOSTAY <channel>
448 Retire le channel de ma stay_list."""],
449 "ops": [None,None,"""OPS
450 Affiche la liste des ops."""],
451 "overops": [None,None,"""OVEROPS
452 Affiche la liste des overops."""],
453 "kick": [None,None,"""KICK <channel> <pseudo> [<raison>]
454 Kicke <pseudo> du channel (Il faut bien entendu que j'y sois op)."""],
455 "die": [None,None,"""DIE
456 Me déconnecte du serveur IRC."""]
457 }
458 helpmsg_default="Liste des commandes disponibles :\nHELP IDENTIFY DROP SOLDE"
459 helpmsg_ops=" JOIN LEAVE QUIET NOQUIET LOST RECONNECT"
460 helpmsg_overops=" SAY DO STAY NOSTAY OPS OVEROPS KICK DIE"
461 op,overop=auteur in self.ops, auteur in self.overops
462 if len(message)==1:
463 helpmsg=helpmsg_default
464 if op:
465 helpmsg+=helpmsg_ops
466 if overop:
467 helpmsg+=helpmsg_overops
468 else:
469 helpmsgs=helpdico.get(message[1].lower(),["Commande inconnue.",None,None])
470 helpmsg=helpmsgs[0]
471 if op and helpmsgs[1]:
472 if helpmsg:
473 helpmsg+="\n"+helpmsgs[1]
474 else:
475 helpmsg=helpmsgs[1]
476 if overop and helpmsgs[2]:
477 if helpmsg:
478 helpmsg+="\n"+helpmsgs[2]
479 else:
480 helpmsg=helpmsgs[2]
481 for ligne in helpmsg.split("\n"):
482 serv.privmsg(auteur,ligne)
483 elif cmd=="identify":
484 if len(message)==1:
485 if self.identities.has_key(auteur):
486 serv.privmsg(auteur,"Je vous connais sous le pseudo note %s."%(
487 self.identities[auteur].encode("utf8")))
488 else:
489 serv.privmsg(auteur,"Je ne connais pas votre pseudo note.")
490 elif len(message)>=3:
491 username,password=message[1],unicode(" ".join(message[2:]),"utf8")
492 success,_=self.new_connection_NK(serv,username,password)
493 if success:
494 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
495 serv.privmsg(auteur,"Identité enregistrée.")
496 self.identities[auteur]=username
497 pickle.dump(Xself.identities,open("identities.pickle","w"))
498 else:
499 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
500 serv.privmsg(auteur,"Mot de passe invalide. (ou serveur down)")
501 else:
502 serv.privmsg(auteur,u"Syntaxe : IDENTIFY [<username> <password>]")
503 elif cmd=="drop":
504 if len(message)>1:
505 if self.identities.has_key(auteur):
506 password=" ".join(message[1:])
507 success,_=self.new_connection_NK(serv,self.identities[auteur],password)
508 if success:
509 del self.identities[auteur]
510 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
511 pickle.dump(self.identities,open("identities.pickle","w"))
512 serv.privmsg(auteur,"Identité oubliée.")
513 else:
514 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
515 serv.privmsg(auteur,"Mot de passe invalide. (ou serveur down)")
516 else:
517 serv.privmsg(auteur,"Je ne connais pas ton pseudo note.")
518 else:
519 serv.privmsg(auteur,"Syntaxe : DROP <password>")
520 elif cmd=="join":
521 if auteur in self.ops:
522 if len(message)>1:
523 if message[1] in self.chanlist:
524 serv.privmsg(auteur,"Je suis déjà sur %s"%(message[1]))
525 else:
526 serv.join(message[1])
527 self.chanlist.append(message[1])
528 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
529 log(self.serveur,"priv",auteur," ".join(message))
530 else:
531 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
532 else:
533 notunderstood=True
534 elif cmd=="leave":
535 if auteur in self.ops and len(message)>1:
536 if message[1] in self.chanlist:
537 if not (message[1] in self.stay_channels) or auteur in self.overops:
538 self.quitter(message[1]," ".join(message[2:]))
539 self.chanlist.remove(message[1])
540 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
541 else:
542 serv.privmsg(auteur,"Non, je reste !")
543 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
544 else:
545 serv.privmsg(auteur,"Je ne suis pas sur %s"%(message[1]))
546 else:
547 notunderstood=True
548 elif cmd=="stay":
549 if auteur in self.overops:
550 if len(message)>1:
551 if message[1] in self.stay_channels:
552 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
553 serv.privmsg(auteur,"Je stay déjà sur %s."%(message[1]))
554 else:
555 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
556 self.stay_channels.append(message[1])
557 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
558 else:
559 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
560 else:
561 notunderstood=True
562 elif cmd=="nostay":
563 if auteur in self.overops:
564 if len(message)>1:
565 if message[1] in self.stay_channels:
566 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
567 self.stay_channels.remove(message[1])
568 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
569 else:
570 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
571 serv.privmsg(auteur,"Je ne stay pas sur %s."%(message[1]))
572
573 else:
574 notunderstood=True
575 elif cmd=="die":
576 if auteur in self.overops:
577 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
578 self.mourir()
579 else:
580 notunderstood=True
581 elif cmd=="reconnect":
582 if auteur in self.ops:
583 try:
584 self.nk=self.new_connection_NK(serv,config_note_pseudo,
585 config_note_password,"special")[1]
586 except Exception as exc:
587 self.nk=None
588 log(self.serveur,"""Erreur dans on_pubmsg/"cmd in ["reconnect"]\n"""+str(exc))
589 if self.nk!=None:
590 serv.privmsg(auteur,"%s: done"%(auteur))
591 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
592 else:
593 serv.privmsg(auteur,"%s: failed"%(auteur))
594 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
595 for report in self.report_bugs_to:
596 serv.privmsg(report,"Connection to NK2015 failed, invalid password ? Server dead ?")
597 else:
598 notunderstood=True
599 elif cmd=="quiet":
600 if auteur in self.ops:
601 if len(message)>1:
602 if message[1] in self.quiet_channels:
603 serv.privmsg(auteur,"Je me la ferme déjà sur %s"%(message[1]))
604 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
605 else:
606 self.quiet_channels.append(message[1])
607 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
608 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
609 else:
610 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
611 else:
612 notunderstood=True
613 elif cmd=="noquiet":
614 if auteur in self.ops:
615 if len(message)>1:
616 if message[1] in self.quiet_channels:
617 self.quiet_channels.remove(message[1])
618 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
619 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
620 else:
621 serv.privmsg(auteur,"Je ne me la ferme pas sur %s."%(message[1]))
622 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
623 else:
624 notunderstood=True
625 elif cmd=="say":
626 if auteur in self.overops and len(message)>2:
627 serv.privmsg(message[1]," ".join(message[2:]))
628 log(self.serveur,"priv",auteur," ".join(message))
629 elif len(message)<=2:
630 serv.privmsg(auteur,"Syntaxe : SAY <channel> <message>")
631 else:
632 notunderstood=True
633 elif cmd=="do":
634 if auteur in self.overops and len(message)>2:
635 serv.action(message[1]," ".join(message[2:]))
636 log(self.serveur,"priv",auteur," ".join(message))
637 elif len(message)<=2:
638 serv.privmsg(auteur,"Syntaxe : DO <channel> <action>")
639 else:
640 notunderstood=True
641 elif cmd=="kick":
642 if auteur in self.overops and len(message)>2:
643 serv.kick(message[1],message[2]," ".join(message[3:]))
644 log(self.serveur,"priv",auteur," ".join(message))
645 elif len(message)<=2:
646 serv.privmsg(auteur,"Syntaxe : KICK <channel> <pseudo> [<raison>]")
647 else:
648 notunderstood=True
649 elif cmd=="lost":
650 if auteur in self.ops and len(message)>1:
651 serv.privmsg(message[1],"J'ai perdu !")
652 log(self.serveur,"priv",auteur," ".join(message))
653 elif len(message)<=1:
654 serv.privmsg(auteur,"Syntaxe : LOST <channel>")
655 else:
656 notunderstood=True
657 elif cmd=="solde":
658 if len(message)==1:
659 if self.identities.has_key(auteur):
660 try:
661 self.nk.write('search ["x",["pseudo"],%s]'%(json.dumps(self.identities[auteur])))
662 ret=json.loads(self.nk.read())
663 solde=ret["msg"][0]["solde"]
664 pseudo=ret["msg"][0]["pseudo"]
665 except Exception as exc:
666 print exc
667 serv.privmsg(auteur,"failed")
668 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
669 return
670 serv.privmsg(auteur,"%s (%s)"%(float(solde)/100,pseudo.encode("utf8")))
671 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
672 else:
673 serv.privmsg(canal,"Je ne connais pas ton pseudo note.")
674 elif auteur in self.ops:
675 try:
676 self.nk.write('search ["x",["pseudo"],%s]'%(json.dumps(message[1])))
677 ret=json.loads(self.nk.read())
678 solde=ret["msg"][0]["solde"]
679 pseudo=ret["msg"][0]["pseudo"]
680 except Exception as exc:
681 serv.privmsg(auteur,"failed")
682 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
683 return
684 serv.privmsg(auteur,"%s (%s)"%(float(solde)/100,pseudo.encode("utf8")))
685 elif cmd=="ops":
686 if auteur in self.overops:
687 serv.privmsg(auteur," ".join(self.ops))
688 else:
689 notunderstood=True
690 elif cmd=="overops":
691 if auteur in self.overops:
692 serv.privmsg(auteur," ".join(self.overops))
693 else:
694 notunderstood=True
695 else:
696 notunderstood=True
697 if notunderstood:
698 serv.privmsg(auteur,"Je n'ai pas compris. Essayez HELP…")
699
700 def on_pubmsg(self, serv, ev):
701 auteur = irclib.nm_to_n(ev.source())
702 canal = ev.target()
703 message = ev.arguments()[0]
704 try:
705 test=bot_unicode(message)
706 except UnicodeBotError:
707 if not canal in self.quiet_channels:
708 serv.privmsg(canal,
709 "%s: Si je n'avais pas été créé avec la plus grande attention, votre encodage aurait eu raison de moi…"%(auteur))
710 return
711 pour_moi,message=self.pourmoi(serv,message)
712 if pour_moi and message.split()!=[]:
713 cmd=message.split()[0].lower()
714 try:
715 args=" ".join(message.split()[1:])
716 except:
717 args=""
718 if cmd in ["meurs","die","crève"]:
719 if auteur in self.overops:
720 log(self.serveur,canal,auteur,message+"[successful]")
721 self.mourir()
722 else:
723 serv.privmsg(canal,"%s: mourrez vous-même !"%(auteur))
724 log(self.serveur,canal,auteur,message+"[failed]")
725
726 elif cmd in ["part","leave","dégage","va-t-en","tut'tiresailleurs,c'estmesgalets"]:
727 if auteur in self.ops and (not (canal in self.stay_channels)
728 or auteur in self.overops):
729 self.quitter(canal)
730 log(self.serveur,canal,auteur,message+"[successful]")
731 if canal in self.chanlist:
732 self.chanlist.remove(canal)
733 else:
734 serv.privmsg(canal,"%s: Navré, mais je me vois contraint de refuser, je ne peux pas céder aux exigences du premier venu."%(auteur))
735 log(self.serveur,canal,auteur,message+"[failed]")
736
737 elif cmd in ["reconnect"]:
738 if auteur in self.ops:
739 try:
740 self.nk=self.new_connection_NK(serv,config_note_pseudo,
741 config_note_password,"special")[1]
742 except Exception as exc:
743 self.nk=None
744 log(self.serveur,"""Erreur dans on_pubmsg/"cmd in ["reconnect"]\n"""+str(exc))
745 if self.nk!=None:
746 serv.privmsg(canal,"%s: done"%(auteur))
747 log(self.serveur,canal,auteur,message+"[successful]")
748 else:
749 serv.privmsg(canal,"%s: failed"%(auteur))
750 log(self.serveur,canal,auteur,message+"[failed]")
751 for report in self.report_bugs_to:
752 serv.privmsg(report,"Connection to NK2015 failed, invalid password ? Server dead ?")
753 else:
754 serv.privmsg(canal,"%s: Encore eût-il fallu que je sois programmé pour vous obéir !"%(auteur))
755 log(self.serveur,canal,auteur,message+"[failed]")
756
757 elif cmd in ["deviens","pseudo"]:
758 if auteur in self.ops:
759 become=args
760 serv.nick(become)
761 log(self.serveur,canal,auteur,message+"[successful]")
762
763 if cmd in ["meur", "meurt","meurre","meurres"] and not canal in self.quiet_channels:
764 serv.privmsg(canal,'%s: Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)'%(auteur))
765 elif cmd in ["ping"] and not canal in self.quiet_channels:
766 serv.privmsg(canal,"%s: pong"%(auteur))
767
768 elif cmd in ["solde","!solde"]:
769 if self.identities.has_key(auteur):
770 pseudo=self.identities[auteur]
771 try:
772 self.nk.write('search ["x",["pseudo"],%s]'%(json.dumps(pseudo)))
773 ret=json.loads(self.nk.read())
774 solde=ret["msg"][0]["solde"]
775 pseudo=ret["msg"][0]["pseudo"]
776 except Exception as exc:
777 serv.privmsg(canal,"%s: failed"%(auteur))
778 log(self.serveur,canal,auteur,message+"[failed]")
779 else:
780 serv.privmsg(canal,"%s: %s (%s)"%(auteur,float(solde)/100,pseudo.encode("utf8")))
781 log(self.serveur,canal,auteur,message+"[successful]")
782 else:
783 serv.privmsg(canal,"%s: Je ne connais pas votre pseudo note."%(auteur))
784 log(self.serveur,canal,auteur,message+"[unknown]")
785 elif (re.match("!?(pain au chocolat|chocolatine)",message.lower())
786 and not canal in self.quiet_channels):
787 serv.action(canal,"sert un pain au chocolat à %s"%(auteur))
788 elif re.match("!?manzana",message.lower()) and not canal in self.quiet_channels:
789 if auteur in config_manzana:
790 serv.action(canal,"sert une bouteille de manzana à %s"%(auteur))
791 elif auteur in config_manzana_bis:
792 serv.action(canal,"sert un grand verre de jus de pomme à %s : tout le monde sait qu'il ne boit pas."%(auteur))
793 else:
794 serv.action(canal,"sert un verre de manzana à %s"%(auteur))
795 if is_insult(message) and not canal in self.quiet_channels:
796 if is_not_insult(message):
797 answer=random.choice(config_compliment_answers)
798 for ligne in answer.split("\n"):
799 serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
800 else:
801 answer=random.choice(config_insultes_answers)
802 for ligne in answer.split("\n"):
803 serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
804 elif is_compliment(message) and not canal in self.quiet_channels:
805 answer=random.choice(config_compliment_answers)
806 for ligne in answer.split("\n"):
807 serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
808 gros_match=is_gros(message)
809 if gros_match and not canal in self.quiet_channels:
810 taille=get_filesize()
811 answer=u"Mais non, je ne suis pas %s, %sKo tout au plus…"%(gros_match.groups()[0],taille)
812 serv.privmsg(canal,"%s: %s"%(auteur,answer.encode("utf8")))
813 if is_tesla(message) and not canal in self.quiet_channels:
814 l1,l2=config_tesla_answers,config_tesla_actions
815 n1,n2=len(l1),len(l2)
816 i=random.randrange(n1+n2)
817 if i>=n1:
818 serv.action(canal,l2[i-n1].encode("utf8"))
819 else:
820 serv.privmsg(canal,"%s: %s"%(auteur,l1[i].encode("utf8")))
821 if is_tamere(message) and not canal in self.quiet_channels:
822 answer=random.choice(config_tamere_answers)
823 for ligne in answer.split("\n"):
824 serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
825 if is_tag(message) and not canal in self.quiet_channels:
826 if auteur in self.ops:
827 action=random.choice(config_tag_actions)
828 serv.action(canal,action.encode("utf8"))
829 self.quiet_channels.append(canal)
830 else:
831 answer=random.choice(config_tag_answers)
832 for ligne in answer.split("\n"):
833 serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
834 if is_merci(message):
835 answer=random.choice(config_merci_answers)
836 for ligne in answer.split("\n"):
837 serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
838 out=re.match(ur"^([A-Z[]|\\|[0-9]+|(¹|²|³|⁴|⁵|⁶|⁷|⁸|⁹|⁰)+)(?:| \?| !)$",
839 unicode(message.upper(),"utf8"))
840 if re.match("ma bite dans ton oreille",message) and not canal in self.quiet_channels:
841 serv.privmsg(canal,"%s: Seul un olasd peut imiter un olasd dans un de ses grands jours !"%(auteur))
842 if out and not canal in self.quiet_channels:
843 out=out.groups()[0]
844 try:
845 out=int(out)
846 serv.privmsg(canal,"%s: %s !"%(auteur,out+1))
847 if out==2147483647:
848 serv.privmsg(canal,"%s: Ciel, un maxint ! Heureusement que je suis en python…"%(auteur))
849 return
850 if out+1>1000 and random.randrange(4)==0:
851 serv.privmsg(canal,"%s: Vous savez, moi et les chiffres…"%(auteur))
852 return
853 except Exception as exc:
854 pass
855 if re.match("[A-Y]",out):
856 alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
857 serv.privmsg(canal,"%s: %s !"%(auteur,alphabet[alphabet.index(out)+1]))
858 elif out=="Z":
859 serv.privmsg(canal,"%s: Je ne vous remercie pas, j'ai l'air idiot ainsi… [ ?"%(auteur))
860 elif out in "[\\":
861 serv.privmsg(canal,"%s: Nous devrions nous en tenir là, ça va finir par poser des problèmes…"%(auteur))
862 elif re.match(ur"(¹|²|³|⁴|⁵|⁶|⁷|⁸|⁹|⁰)+",out):
863 def translate(mess):
864 return "".join([{u"⁰¹²³⁴⁵⁶⁷⁸⁹0123456789"[i]:u"0123456789⁰¹²³⁴⁵⁶⁷⁸⁹"[i]
865 for i in range(20)}[j]
866 for j in mess])
867 out=int(translate(out))
868 serv.privmsg(canal,"%s: %s !"%(auteur,translate(str(out+1)).encode("utf8")))
869 if is_bonjour(message) and not canal in self.quiet_channels:
870 if is_night():
871 answer=random.choice(config_night_answers)
872 elif is_day():
873 answer=random.choice(config_bonjour_answers)
874 else:
875 answer=random.choice(config_bonsoir_answers)
876 serv.privmsg(canal,answer.format(auteur).encode("utf8"))
877 if is_bonne_nuit(message) and not canal in self.quiet_channels:
878 answer=random.choice(config_bonne_nuit_answers)
879 serv.privmsg(canal,answer.format(auteur).encode("utf8"))
880 if is_pan(message) and not canal in self.quiet_channels:
881 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))
882 else:
883 if message in ["!pain au chocolat","!chocolatine"] and not canal in self.quiet_channels:
884 serv.action(canal,"sert un pain au chocolat à %s"%(auteur))
885 if message in ["!manzana"] and not canal in self.quiet_channels:
886 if auteur in config_manzana:
887 serv.action(canal,"sert une bouteille de manzana à %s"%(auteur))
888 elif auteur in config_manzana_bis:
889 serv.action(canal,"sert un grand verre de jus de pomme à %s : tout le monde sait qu'il ne boit pas."%(auteur))
890 else:
891 serv.action(canal,"sert un verre de manzana à %s"%(auteur))
892 if re.match(u'^ *(.|§|!|/|/|:|)(w|b) [0-9]+$',message.decode("utf8")) and not canal in self.quiet_channels:
893 failanswers=config_buffer_fail_answers
894 answer=random.choice(failanswers)
895 serv.privmsg(canal,("%s: %s"%(auteur,answer)).encode("utf8"))
896 if not canal in self.quiet_channels:
897 mypseudo=self.nick
898 if re.match((u"^("+u"|".join(config_bonjour_triggers)
899 +u")( {}| all| tout le monde|(|à) tous)(\.|( |)!|)$"
900 ).format(mypseudo).lower(), message.strip().lower()):
901 answer=random.choice(config_bonjour_answers)
902 serv.privmsg(canal,answer.format(auteur).encode("utf8"))
903 if (is_perdu(message) and not canal in self.quiet_channels):
904 # proba de perdre sur trigger :
905 # avant 30min (enfin, config) : 0
906 # ensuite, +25%/30min, linéairement
907 deltat=time.time()-self.last_perdu
908 barre=(deltat-config_time_between_perdu)/(2*3600.0)
909 if random.uniform(0,1)<barre:
910 serv.privmsg(canal,"%s: J'ai perdu !"%(auteur))
911 self.last_perdu=time.time()
912
913 def on_action(self, serv, ev):
914 action = ev.arguments()[0]
915 auteur = irclib.nm_to_n(ev.source())
916 channel = ev.target()
917 try:
918 test=bot_unicode(action)
919 except UnicodeBotError:
920 serv.privmsg(channel,
921 "%s: Si je n'avais pas été créé avec la plus grande attention, votre encodage m'aurait déjà tué…"%(auteur))
922 return
923 mypseudo=self.nick
924
925 if is_bad_action_trigger(action,mypseudo) and not channel in self.quiet_channels:
926 l1,l2=config_bad_action_answers,config_bad_action_actions
927 n1,n2=len(l1),len(l2)
928 i=random.randrange(n1+n2)
929 if i>=n1:
930 serv.action(channel,l2[i-n1].format(auteur).encode("utf8"))
931 else:
932 serv.privmsg(channel,l1[i].format(auteur).format(auteur).encode("utf8"))
933 if is_good_action_trigger(action,mypseudo) and not channel in self.quiet_channels:
934 l1,l2=config_good_action_answers,config_good_action_actions
935 n1,n2=len(l1),len(l2)
936 i=random.randrange(n1+n2)
937 if i>=n1:
938 serv.action(channel,l2[i-n1].format(auteur).format(auteur).encode("utf8"))
939 else:
940 serv.privmsg(channel,l1[i].format(auteur).format(auteur).encode("utf8"))
941
942 def on_kick(self,serv,ev):
943 auteur = irclib.nm_to_n(ev.source())
944 channel = ev.target()
945 victime = ev.arguments()[0]
946 raison = ev.arguments()[1]
947 if victime==self.nick:
948 log(self.serveur,"%s kické de %s par %s (raison : %s)" %(victime,channel,auteur,raison))
949 time.sleep(2)
950 serv.join(channel)
951 l1,l2=config_kick_answers,config_kick_actions
952 n1,n2=len(l1),len(l2)
953 i=random.randrange(n1+n2)
954 if i>=n1:
955 serv.action(channel,l2[i-n1].format(auteur).encode("utf8"))
956 else:
957 serv.privmsg(channel,l1[i].format(auteur).encode("utf8"))
958
959 def quitter(self,chan,leave_message=None):
960 if leave_message==None:
961 leave_message=random.choice(config_leave_messages)
962 self.serv.part(chan,message=leave_message.encode("utf8"))
963
964 def mourir(self):
965 quit_message=random.choice(config_quit_messages)
966 self.die(msg=quit_message.encode("utf8"))
967
968 def _getnick(self):
969 return self.serv.get_nickname()
970 nick=property(_getnick)
971
972
973 if __name__=="__main__":
974 import sys
975 if len(sys.argv)==1:
976 print "Usage : basile.py <serveur> [--debug]"
977 exit(1)
978 serveur=sys.argv[1]
979 if "debug" in sys.argv or "--debug" in sys.argv:
980 debug=True
981 else:
982 debug=False
983 serveurs={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
984 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"}
985 try:
986 serveur=serveurs[serveur]
987 except KeyError:
988 print "Server Unknown : %s"%(serveur)
989 exit(404)
990 basile=Basile(serveur,debug)
991 basile.start()