4 # Codé par 20-100 le 23/04/12
6 # Un bot IRC qui sort des déconnaissances
16 from remplace_accents
import remplace_accents
18 # Oui, j'ai recodé ma version d'irclib pour pouvoir rattrapper les SIGHUP
19 sys
.path
.insert(0, "/home/vincent/scripts/python-myirclib")
24 config_password
="PatrickSébastien"
25 config_pseudo
="deconnaisseur"
26 config_chanlist
=["#bot","#flood"]
27 config_play_channels
=["#flood"]
28 config_stay_channels
=["#flood","#bot"]
29 config_overops
=["[20-100]","[20-100]_","PEB"]
30 config_ops
=["Nit","Eguel","Harry"]
32 config_source_file
="deconnaissances.txt"
33 config_played_file_template
="played.%s.txt" #il faut rajouter le nom du serveur
34 def get_config_played_file(serveur
):
35 serveurs
={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
36 return config_played_file_template
%(serveurs
[serveur
])
37 ttrig
=120 #time trigger (normalement 120, mais diminué pour les tests)
38 Ttrig
=600 #between two enigms (600)
39 config_time_incompressible
=15 #on peut pas retrigger en dessous de ce temps (60)
40 config_time_incompressible_clue
=60 #on peut pas forcer la demande d'indice en dessous
42 config_score_file
="scores.pickle"
44 config_tag_triggers
=[u
"t(|a)g",u
"ta gueule",u
"la ferme",u
"ferme( |-)la",u
"tais-toi",u
"chut"]
45 config_tag_actions
=[u
"se tait",u
"ferme sa gueule",u
"se la ferme",u
"la ferme"]
46 config_tag_answers
=[u
"J'me tais si j'veux !",
47 u
"Je t'entends pas :°",
49 u
"Non, j'ai pas envie",
50 u
"Peut-être quand toi tu la fermeras, et encore…"]
53 config_level3
=["[20-100]","Petite-Peste","PEB","Constance","pika"]
55 config_debug_stdout
= True
56 config_logfile_template
="deconnaisseur.%s.log"
57 def get_config_logfile(serveur
):
58 serveurs
={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
59 return config_logfile_template
%(serveurs
[serveur
])
61 config_quit_messages
=[u
"Se décrocher la mâchoire, pas cuit bras d'oiseau ou métalld précieuxld"]
63 config_leave_messages
=[u
"On continuera à jouer plus tard ;)"]
65 # Quand personne ne cause, on finit par se taire
66 # temps au bout duquel, si personne n'a parlé, on se tait
67 config_idle_time
=20*60
68 # liste des bots, qui ne sont pas considérés comme de l'activité
69 config_idle_bots
=["deconnaisseur","Basile","historien","hung","salesman","Shadobot","Wen","___","Sanctuary","Saturnin"]
71 class UnicodeBotError(Exception):
73 def bot_unicode(chain
):
76 except UnicodeDecodeError:
79 def log(serveur
,channel
,auteur
=None,message
=None):
80 f
=open(get_config_logfile(serveur
),"a")
81 if auteur
==message
==None:
82 # alors c'est que c'est pas un channel mais juste une ligne de log
83 chain
="%s %s"%(time
.strftime("%F %T"),channel
)
85 chain
="%s [%s:%s] %s"%(time
.strftime("%F %T"),channel
,auteur
,message
)
87 if config_debug_stdout
:
92 def reussi(message
,answer
,answer_regexp
,auteur
):
93 if auteur
in config_level3
:
94 return answer
in message
95 if auteur
in config_level2
:
96 return remplace_accents(answer
) in message
98 if re
.match(remplace_accents(answer_regexp
).lower(),remplace_accents(message
).lower()):
101 def is_something(chain
,matches
,avant
=u
".*(?:^| )",apres
=u
"(?:$|\.| |,|;).*",case_sensitive
=False,debug
=False):
103 chain
=unicode(chain
,"utf8")
105 chain
=unicode(chain
,"utf8").lower()
106 allmatches
="("+"|".join(matches
)+")"
107 reg
=(avant
+allmatches
+apres
).lower()
108 o
=re
.match(reg
,chain
)
112 return is_something(chain
,config_tag_triggers
)
114 class RefuseError(Exception):
117 class Deconnaisseur(ircbot
.SingleServerIRCBot
):
118 def __init__(self
,serveur
,debug
=False):
119 temporary_pseudo
=config_pseudo
+str(random
.randrange(10000,100000))
120 ircbot
.SingleServerIRCBot
.__init
__(self
, [(serveur
, 6667)],
121 temporary_pseudo
,"Un bot irc.[flagellez 20-100, il le mérite]", 10)
124 self
.overops
=config_overops
125 self
.ops
=self
.overops
+config_ops
126 self
.chanlist
=config_chanlist
127 self
.stay_channels
=config_stay_channels
128 self
.play_channels
=config_play_channels
129 self
.play_status
={i
:[0] for i
in self
.play_channels
}
130 self
.last_activity
={}
131 self
.quiet_channels
=[]
133 def give_me_my_pseudo(self
,serv
):
134 serv
.privmsg("NickServ","RECOVER %s %s"%(config_pseudo
,config_password
))
135 serv
.privmsg("NickServ","RELEASE %s %s"%(config_pseudo
,config_password
))
137 serv
.nick(config_pseudo
)
139 def on_welcome(self
, serv
, ev
):
140 self
.serv
=serv
# ça serv ira :)
141 self
.give_me_my_pseudo(serv
)
142 serv
.privmsg("NickServ","identify %s"%(config_password))
143 log(self
.serveur
,"Connected")
145 self
.chanlist
=["#bot"]
146 self
.play_channels
=["#bot"]
147 for c
in self
.chanlist
:
148 log(self
.serveur
,"JOIN %s"%(c))
150 self
.update_activity(c
,"") # la chaîne vide ne sera jamais un nom de bot et donc marchera toujours
151 for c
in self
.play_channels
:
152 token
=time
.time()-3600
153 self
.play_status
[c
]=[0,token
]
154 serv
.execute_delayed(random
.randrange(ttrig
),self
.start_enigme
,(serv
,c
,token
))
156 def start_enigme(self
,serv
,channel
,token
=None):
157 # On reste silencieux si lechan n'est pas actif
158 if not self
.is_active(channel
):
159 serv
.execute_delayed(ttrig
*5,self
.start_enigme
,(serv
,channel
,token
))
161 if self
.play_status
[channel
][0]==0 and channel
in self
.play_channels
:
163 if token
==self
.play_status
[channel
][-1]:
166 if time
.time() > self
.play_status
[channel
][-1]+config_time_incompressible
:
171 enigme
,indice
,answer_reg
,answer
=self
.get_enigme()
172 log(self
.serveur
,channel
,u
"$Énigme$".encode("utf8"),("%s; %s; %s; %s"%(enigme
, indice
, answer_reg
, answer
)).encode("utf8"))
173 serv
.privmsg(channel
,enigme
.encode("utf8"))
175 self
.play_status
[channel
]=[1,enigme
,indice
,answer_reg
,answer
,token
]
176 serv
.execute_delayed(random
.randrange(ttrig
*3,ttrig
*5),self
.give_indice
,(serv
,channel
,token
))
179 def give_indice(self
,serv
,channel
,token
):
180 if self
.play_status
[channel
][0]==1:
182 # c'est donc que l'indice a été demandé
183 if self
.play_status
[channel
][-1]+config_time_incompressible_clue
<time
.time():
184 token
=self
.play_status
[channel
][-1]
185 if self
.play_status
[channel
][-1]==token
:
186 indice
=self
.play_status
[channel
][2]
187 serv
.privmsg(channel
,"indice : %s"%(indice).encode("utf8"))
188 self
.play_status
[channel
][0]=2
189 serv
.execute_delayed(random
.randrange(ttrig
*1,ttrig
*3),self
.give_answer
,(serv
,channel
,token
))
190 def give_answer(self
,serv
,channel
,token
):
191 if self
.play_status
[channel
][0]==2 and self
.play_status
[channel
][-1]==token
:
192 answer
=self
.play_status
[channel
][4]
193 serv
.privmsg(channel
,"C'était : %s"%(answer).encode("utf8"))
195 self
.play_status
[channel
]=[0,token
]
196 serv
.execute_delayed(random
.randrange(Ttrig
*5,Ttrig
*10),self
.start_enigme
,(serv
,channel
,token
))
198 def get_enigme(self
):
199 # on récupère les déconnaissances
200 f
=open(config_source_file
)
203 l
=re
.findall("%\n(.*)\n(.*)\n(.*)\n(.*)\n(.*)\n",t
)
204 dec
={int(i
[0]):list(i
[1:]) for i
in l
if len(i
)==5}
205 # on va chercher combien de fois elles ont été jouées
206 played_file
=get_config_played_file(self
.serveur
)
210 l
=re
.findall("(.*):(.*)",t
)
211 played
={int(i
[0]):int(i
[1]) for i
in l
}
212 # on récupère le nombre d'occurrences le plus faible
213 mini
=min(played
.values())
214 # on choisit un id dans ceux qui ont ce nombre d'occurences
215 id_choisi
=random
.choice([k
for k
,v
in played
.items() if v
==mini
])
216 enigme
,indice
,answer_reg
,answer
=dec
[id_choisi
]
217 # on incrémente la choisie
219 # on enregistre le played_file
220 f
=open(played_file
,"w")
221 f
.write("\n".join(["%-3s : %s"%(k
,v
) for k
,v
in played
.items()]))
223 return enigme
.decode("utf8"),indice
.decode("utf8"),answer_reg
.decode("utf8"),answer
.decode("utf8")
225 def pourmoi(self
, serv
, message
):
228 if message
[:size
]==pseudo
and len(message
)>size
and message
[size
]==":":
229 return (True,message
[size
+1:].strip(" "))
231 return (False,message
)
233 def on_privmsg(self
, serv
, ev
):
234 message
=ev
.arguments()[0]
235 auteur
= irclib
.nm_to_n(ev
.source())
237 test
=bot_unicode(message
)
238 except UnicodeBotError
:
240 "Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…")
242 message
=message
.split()
243 cmd
=message
[0].lower()
246 helpmsg_default
="""Liste des commandes :
247 HELP Affiche ce message d'aide
248 SCORE Affiche ton score (SCORE TRANSFERT <pseudo> [<n>] pour transférer des points)
249 SCORES Affiche les scores"""
251 JOIN Faire rejoindre un channel (sans paramètres, donne la liste des chans actuels)
252 LEAVE Faire quitter un channel
253 PLAY Passe un channel en mode "jouer"
254 NOPLAY Passe un channel en mode "ne pas jouer"
255 QUIET Se taire sur un channel
256 NOQUIET Opposé de QUIET"""
258 SCORES {DEL|ADD|SUB} Tu veux un dessin ?
259 SAY Fais envoyer un message sur un chan ou à une personne
260 STAY Ignorera les prochains LEAVE pour un chan
261 NOSTAY Opposé de STAY
262 STATUS Montre l'état courant
264 helpmsg
=helpmsg_default
265 if auteur
in self
.ops
:
267 if auteur
in self
.overops
:
268 helpmsg
+=helpmsg_overops
269 for ligne
in helpmsg
.split("\n"):
270 serv
.privmsg(auteur
,ligne
)
272 if auteur
in self
.ops
:
274 if message
[1] in self
.chanlist
:
275 serv
.privmsg(auteur
,"Je suis déjà sur %s"%(message
[1]))
277 serv
.join(message
[1])
278 self
.chanlist
.append(message
[1])
279 self
.update_activity(message
[1],"")
280 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
281 log(self
.serveur
,"priv",auteur
," ".join(message
))
283 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
287 if auteur
in self
.ops
and len(message
)>1:
288 if message
[1] in self
.chanlist
:
289 if not (message
[1] in self
.stay_channels
) or auteur
in self
.overops
:
290 self
.quitter(message
[1]," ".join(message
[2:]))
291 self
.chanlist
.remove(message
[1])
292 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
294 serv
.privmsg(auteur
,"Non, je reste !")
295 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
297 serv
.privmsg(auteur
,"Je ne suis pas sur %s"%(message
[1]))
301 if auteur
in self
.overops
:
303 if message
[1] in self
.stay_channels
:
304 serv
.privmsg(auteur
,"Je stay déjà sur %s."%(message
[1]))
305 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
307 self
.stay_channels
.append(message
[1])
308 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
309 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
311 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
315 if auteur
in self
.overops
:
317 if message
[1] in self
.stay_channels
:
318 self
.stay_channels
.remove(message
[1])
319 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
320 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
322 serv
.privmsg(auteur
,"Je ne stay pas sur %s."%(message
[1]))
323 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
327 if auteur
in self
.ops
:
329 if message
[1] in self
.play_channels
:
330 serv
.privmsg(auteur
,"Je play déjà sur %s."%(message
[1]))
331 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
333 self
.play_channels
.append(message
[1])
334 self
.play_status
[message
[1]]=[0,time
.time()-3600]
335 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
336 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
338 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
342 if auteur
in self
.ops
:
344 if message
[1] in self
.play_channels
:
345 self
.play_channels
.remove(message
[1])
346 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
347 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
349 serv
.privmsg(auteur
,"Je ne play pas sur %s."%(message
[1]))
350 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
354 if auteur
in self
.ops
:
356 if message
[1] in self
.quiet_channels
:
357 serv
.privmsg(auteur
,"Je me la ferme déjà sur %s"%(message
[1]))
358 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
360 self
.quiet_channels
.append(message
[1])
361 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
362 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
364 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
368 if auteur
in self
.ops
:
370 if message
[1] in self
.quiet_channels
:
371 self
.quiet_channels
.remove(message
[1])
372 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
373 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
375 serv
.privmsg(auteur
,"Je ne me la ferme pas sur %s."%(message
[1]))
376 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
379 elif cmd
in ["states","status"]:
380 if auteur
in self
.overops
:
381 for k
in self
.play_status
.keys():
382 serv
.privmsg(auteur
,(u
"%s : %s"%(k
,"; ".join([unicode(i
) for i
in self
.play_status
[k
]]))).encode("utf8") )
384 if auteur
in self
.overops
and len(message
)>2:
385 serv
.privmsg(message
[1]," ".join(message
[2:]))
386 log(self
.serveur
,"priv",auteur
," ".join(message
))
387 elif len(message
)<=2:
388 serv
.privmsg(auteur
,"Syntaxe : SAY <channel> <message>")
392 if auteur
in self
.overops
:
393 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
397 if len(message
) in [3,4] and message
[1].lower()=="transfert":
398 scores
=self
.get_scores()
399 de
,to
=auteur
,message
[2]
400 value
=scores
.get(de
,0)
403 asked
=int(message
[3])
405 serv
.privmsg(auteur
,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
410 serv
.privmsg(auteur
,"Vous n'avez pas de points")
413 serv
.privmsg(auteur
,"Bien tenté…")
416 serv
.privmsg(auteur
,"Vous n'avez que %s points"%(value))
419 self
.add_score(de
,-asked
)
420 self
.add_score(to
,asked
)
421 serv
.privmsg(auteur
,"Transfert de %s points de %s à %s"%(asked
,de
,to
))
423 serv
.privmsg(auteur
,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
425 serv
.privmsg(auteur
,"Votre score : %s"%(self
.get_scores().get(auteur
,0)) )
428 scores
=self
.get_scores().items()
430 scores
.sort(lambda x
,y
:cmp(x
[1],y
[1]))
432 serv
.privmsg(auteur
,"Scores by score : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
434 scores
.sort(lambda x
,y
:cmp(x
[0].lower(),y
[0].lower()))
435 serv
.privmsg(auteur
,"Scores by pseudo : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
436 elif auteur
in self
.overops
:
437 souscmd
=message
[1].lower()
441 scores
=self
.get_scores()
442 if scores
.has_key(todelete
):
444 self
.save_scores(scores
)
445 serv
.privmsg(auteur
,"Score de %s supprimé"%(todelete))
447 serv
.privmsg(auteur
,"Ce score n'existe pas : %s"%(todelete))
449 serv
.privmsg(auteur
,"Syntaxe : SCORES DEL <pseudo>")
450 elif souscmd
in ["add","sub"]:
452 toadd
,val
=message
[2],message
[3]
456 serv
.privmsg(auteur
,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
460 self
.add_score(toadd
,val
)
461 serv
.privmsg(auteur
,"Done")
463 serv
.privmsg(auteur
,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
465 serv
.privmsg(auteur
,"Syntaxe : SCORES {DEL|ADD|SUB} <pseudo> [<n>]")
471 serv
.privmsg(auteur
,"Je n'ai pas compris. Essaye HELP…")
473 def on_pubmsg(self
, serv
, ev
):
474 auteur
= irclib
.nm_to_n(ev
.source())
476 message
= ev
.arguments()[0]
477 self
.update_activity(canal
,auteur
)
479 test
=bot_unicode(message
)
480 except UnicodeBotError
:
481 if not canal
in self
.quiet_channels
:
483 "%s: Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…"%(auteur))
486 pour_moi
,message
=self
.pourmoi(serv
,message
)
487 if pour_moi
and message
.split()!=[]:
488 cmd
=message
.split()[0].lower()
490 args
=" ".join(message
.split()[1:])
493 if cmd
in ["meurs","die","crève"]:
494 if auteur
in self
.overops
:
496 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
498 serv
.privmsg(canal
,"%s: crève !"%(auteur))
499 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
500 if cmd
in ["meur", "meurt","meurre","meurres"] and not canal
in self
.quiet_channels
:
501 serv
.privmsg(canal
,'%s: Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)'%(auteur))
502 if cmd
in ["part","leave","dégage"]:
503 if auteur
in self
.ops
and (not (canal
in self
.stay_channels
)
504 or auteur
in self
.overops
):
506 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
507 self
.chanlist
.remove(canal
)
509 serv
.privmsg(canal
,"%s: Non, je reste !"%(auteur))
510 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
512 if cmd
in ["deviens","pseudo"]:
513 if auteur
in self
.ops
:
516 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
517 if cmd
in ["coucou"] and not canal
in self
.quiet_channels
:
518 serv
.privmsg(canal
,"%s: coucou"%(auteur))
519 if cmd
in ["ping"] and not canal
in self
.quiet_channels
:
520 serv
.privmsg(canal
,"%s: pong"%(auteur))
521 if cmd
in ["déconnaissance","deconnaissance","énigme","enigme","encore"]:
522 if canal
in self
.play_channels
:
523 if self
.play_status
.get(canal
,[-1])[0]==0:
525 self
.start_enigme(serv
,canal
)
527 serv
.privmsg(canal
,"%s: Je peux souffler une minute ?"%(auteur))
529 serv
.privmsg(canal
,("%s: Rappel : %s"%(auteur
,self
.play_status
[canal
][1])).encode("utf8") )
531 serv
.privmsg(canal
,"%s: pas ici…"%(auteur))
532 if cmd
in ["score","!score"]:
533 serv
.privmsg(auteur
,"Votre score : %s"%(self
.get_scores().get(auteur
,0)) )
534 if cmd
in ["scores","!scores"]:
535 scores
=self
.get_scores().items()
537 scores
.sort(lambda x
,y
:cmp(x
[1],y
[1]))
539 serv
.privmsg(auteur
,"Scores by score : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
541 scores
.sort(lambda x
,y
:cmp(x
[0].lower(),y
[0].lower()))
542 serv
.privmsg(auteur
,"Scores by pseudo : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
543 if cmd
=="indice" and canal
in self
.play_channels
:
544 self
.give_indice(serv
,canal
,None)
545 if is_tag(message
) and not canal
in self
.quiet_channels
:
546 if auteur
in self
.ops
:
547 action
=random
.choice(config_tag_actions
)
548 serv
.action(canal
,action
.encode("utf8"))
549 self
.quiet_channels
.append(canal
)
551 answer
=random
.choice(config_tag_answers
)
552 for ligne
in answer
.split("\n"):
553 serv
.privmsg(canal
,"%s: %s"%(auteur
,ligne
.encode("utf8")))
554 if "Bâille, cru aile ou orld" in message
:
555 self
.mourir(u
"Un de mes easters eggs (non en fait j'en ai qu'un) a été découvert par %s !"%auteur
)
561 if self
.play_status
.get(canal
,[-1])[0] in [1,2]:
562 answer_regexp
=self
.play_status
[canal
][3]
563 answer
=self
.play_status
[canal
][4]
564 if reussi(message
.decode("utf8"),answer
,answer_regexp
,auteur
):
565 serv
.privmsg(canal
,(u
"%s: bravo ! (C'était %s)"%(auteur
,answer
)).encode("utf8"))
566 log(self
.serveur
,canal
,auteur
+"$win",message
)
567 self
.add_score(auteur
,1)
569 self
.play_status
[canal
]=[0,token
]
570 serv
.execute_delayed(random
.randrange(Ttrig
*5,Ttrig
*10),self
.start_enigme
,(serv
,canal
,token
))
572 def on_kick(self
,serv
,ev
):
573 auteur
= irclib
.nm_to_n(ev
.source())
574 channel
= ev
.target()
575 victime
= ev
.arguments()[0]
576 raison
= ev
.arguments()[1]
577 if victime
==self
.nick
:
578 log(self
.serveur
,"%s kické de %s par %s (raison : %s)" %(victime
,channel
,auteur
,raison
))
581 self
.update_activity(channel
,"")
582 # on ne dit rien au rejoin
583 #l1,l2=config_kick_answers,config_kick_actions
584 #n1,n2=len(l1),len(l2)
585 #i=random.randrange(n1+n2)
587 # serv.action(channel,l2[i-n1].format(auteur).encode("utf8"))
589 # serv.privmsg(channel,l1[i].format(auteur).encode("utf8"))
591 def quitter(self
,chan
,leave_message
=None):
592 if leave_message
==None:
593 leave_message
=random
.choice(config_leave_messages
)
594 self
.serv
.part(chan
,message
=leave_message
.encode("utf8"))
596 def mourir(self
,quit_message
=None):
597 if quit_message
==None:
598 quit_message
=random
.choice(config_quit_messages
)
599 self
.die(msg
=quit_message
.encode("utf8"))
601 def get_scores(self
):
602 f
=open(config_score_file
)
603 scores
=pickle
.load(f
)
607 def add_score(self
,pseudo
,value
):
608 scores
=self
.get_scores()
609 if scores
.has_key(pseudo
):
610 scores
[pseudo
]+=value
613 self
.save_scores(scores
)
615 def save_scores(self
,scores
):
616 f
=open(config_score_file
,"w")
617 pickle
.dump(scores
,f
)
621 return self
.serv
.get_nickname()
622 nick
= property(_getnick
)
624 def update_activity(self
,canal
,pseudo
):
625 if not pseudo
in config_idle_bots
:
626 self
.last_activity
[canal
]=time
.time()
627 def is_active(self
,canal
):
628 return time
.time()-self
.last_activity
[canal
]<config_idle_time
630 def start_as_daemon(self
, outfile
):
631 sys
.stderr
= Logger(outfile
)
635 class Logger(object):
636 """Pour écrire ailleurs que sur stdout"""
637 def __init__(self
, filename
="deconnaisseur.full.log"):
638 self
.filename
= filename
640 def write(self
, message
):
641 f
= open(self
.filename
, "a")
646 if __name__
=="__main__":
649 print "Usage : deconnaisseur.py <serveur> [--debug] [--no-output] [--daemon [--pidfile]] [--outfile]"
650 print " --outfile sans --no-output ni --daemon n'a aucun effet"
653 if "--daemon" in sys
.argv
:
654 thisfile
= os
.path
.realpath(__file__
)
655 thisdirectory
= thisfile
.rsplit("/", 1)[0]
656 os
.chdir(thisdirectory
)
660 if "debug" in sys
.argv
or "--debug" in sys
.argv
:
664 serveurs
={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
665 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"}
666 if "--no-output" in sys
.argv
or "--daemon" in sys
.argv
:
667 outfile
= "/var/log/bots/deconnaisseur.full.log"
670 if arg
[0].strip('-') in ["out", "outfile", "logfile"]:
672 sys
.stdout
= Logger(outfile
)
674 serveur
=serveurs
[serveur
]
676 print "Server Unknown : %s"%(serveur)
678 deconnaisseur
=Deconnaisseur(serveur
,debug
)
680 child_pid
= os
.fork()
683 deconnaisseur
.start_as_daemon(outfile
)
685 # on enregistre le pid de deconnaisseur
686 pidfile
= "/var/run/bots/deconnaisseur.pid"
689 if arg
[0].strip('-') in ["pidfile"]:
691 f
= open(pidfile
, "w")
692 f
.write("%s\n" % child_pid
)
695 deconnaisseur
.start()