4 # Codé par 20-100 le 25/05/12
6 # Un bot IRC qui pose des questions d'histoire
16 from cast_as_date
import *
18 # Oui, j'ai recodé ma version d'irclib pour pouvoir rattrapper les SIGHUP
19 sys
.path
.insert(0, "/home/vincent/scripts/python-myirclib")
23 config_password
="EtTaMère,ElleEstNéeQuand?"
24 config_pseudo
="historien"
25 config_chanlist
=["#bot","#flood"]
26 config_play_channels
=["#flood"]
27 config_stay_channels
=["#flood","#bot"]
28 config_overops
=["[20-100]","[20-100]_"]
29 config_ops
=["PEB","Petite-Peste"]
31 config_source_file
="dates.txt"
32 config_played_file_template
="played.%s.txt" #il faut rajouter le nom du serveur
33 def get_config_played_file(serveur
):
34 serveurs
={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
35 return config_played_file_template
%(serveurs
[serveur
])
36 ttrig
=120 #time trigger (normalement 120, mais diminué pour les tests)
37 Ttrig
=600 #between two enigms
38 config_time_incompressible
=15 #on peut pas retrigger en dessous de ce temps (60)
39 config_time_incompressible_clue
=60 #on peut pas forcer la demande d'indice en dessous
41 config_score_file
="scores.pickle"
43 config_tag_triggers
=[u
"t(|a)g",u
"ta gueule",u
"la ferme",u
"ferme( |-)la",u
"tais-toi",u
"chut"]
44 config_tag_actions
=[u
"se tait",u
"ferme sa gueule",u
"se la ferme",u
"la ferme"]
45 config_tag_answers
=[u
"J'me tais si j'veux !",
46 u
"Je t'entends pas :°",
48 u
"Non, j'ai pas envie",
49 u
"Peut-être quand toi tu la fermeras, et encore…"]
54 config_debug_stdout
= True
55 config_logfile_template
="historien.%s.log"
56 def get_config_logfile(serveur
):
57 serveurs
={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
58 return config_logfile_template
%(serveurs
[serveur
])
60 config_quit_messages
=[u
"%s : %s quitte le serveur IRC"]
62 config_leave_messages
=[u
"%s : %s quitte le channel"]
64 # Quand personne ne cause, on finit par se taire
65 # temps au bout duquel, si personne n'a parlé, on se tait
66 config_idle_time
=20*60
67 # liste des bots, qui ne sont pas considérés comme de l'activité
68 config_idle_bots
=["deconnaisseur","Basile","historien","hung","salesman","Shadobot","Wen","___","Sanctuary","Saturnin"]
70 class UnicodeBotError(Exception):
72 def bot_unicode(chain
):
75 except UnicodeDecodeError:
78 def log(serveur
,channel
,auteur
=None,message
=None):
79 f
=open(get_config_logfile(serveur
),"a")
80 if auteur
==message
==None:
81 # alors c'est que c'est pas un channel mais juste une ligne de log
82 chain
="%s %s"%(time
.strftime("%F %T"),channel
)
84 chain
="%s [%s:%s] %s"%(time
.strftime("%F %T"),channel
,auteur
,message
)
86 if config_debug_stdout
:
95 config_noscore
=["[20-100]","[20-100]_"] # parce que 20-100 est nul en histoire
97 class GoodCentury(Exception):
100 class GoodDeceny(Exception):
103 def reussi(message
,answer
,auteur
):
104 if auteur
in config_level3
:
105 return answer
in message
106 if auteur
in config_level2
:
107 return answer
in message
110 date
=cast_as_date(message
.lower().strip())
111 except ThisIsNotADate
:
113 realdate
=map(lambda x
:int(x
), answer
.split('/'))
116 if date
[0]==realdate
[0]:
117 score
=config_score_annee
118 if date
[1]==realdate
[1]:
119 score
+=config_score_mois
120 if date
[2]==realdate
[2]:
121 score
+=config_score_jour
122 elif date
[0]/10 == realdate
[0]/10:
124 elif date
[0]/100 == realdate
[0]/100:
128 def is_something(chain
,matches
,avant
=u
".*(?:^| )",apres
=u
"(?:$|\.| |,|;).*",case_sensitive
=False,debug
=False):
130 chain
=unicode(chain
,"utf8")
132 chain
=unicode(chain
,"utf8").lower()
133 allmatches
="("+"|".join(matches
)+")"
134 reg
=(avant
+allmatches
+apres
).lower()
135 o
=re
.match(reg
,chain
)
139 return is_something(chain
,config_tag_triggers
)
141 class RefuseError(Exception):
144 class Historien(ircbot
.SingleServerIRCBot
):
145 def __init__(self
,serveur
,debug
=False):
146 temporary_pseudo
=config_pseudo
+str(random
.randrange(10000,100000))
147 ircbot
.SingleServerIRCBot
.__init
__(self
, [(serveur
, 6667)],
148 temporary_pseudo
,"Un bot irc qui a au moins l'agreg d'histoire", 10)
151 self
.overops
=config_overops
152 self
.ops
=self
.overops
+config_ops
153 self
.chanlist
=config_chanlist
154 self
.stay_channels
=config_stay_channels
155 self
.play_channels
=config_play_channels
156 self
.play_status
={i
:[0] for i
in self
.play_channels
}
157 self
.last_activity
={}
158 self
.quiet_channels
=[]
160 def give_me_my_pseudo(self
,serv
):
161 serv
.privmsg("NickServ","RECOVER %s %s"%(config_pseudo
,config_password
))
162 serv
.privmsg("NickServ","RELEASE %s %s"%(config_pseudo
,config_password
))
164 serv
.nick(config_pseudo
)
166 def on_welcome(self
, serv
, ev
):
167 self
.serv
=serv
# ça serv ira :)
168 self
.give_me_my_pseudo(serv
)
169 serv
.privmsg("NickServ","identify %s"%(config_password))
170 log(self
.serveur
,"Connected")
172 self
.chanlist
=["#bot"]
173 self
.play_channels
=["#bot"]
174 for c
in self
.chanlist
:
175 log(self
.serveur
,"JOIN %s"%(c))
177 self
.update_activity(c
,"") # la chaîne vide ne sera jamais un nom de bot et donc marchera toujours
178 for c
in self
.play_channels
:
179 token
=time
.time()-3600
180 self
.play_status
[c
]=[0,token
]
181 serv
.execute_delayed(random
.randrange(ttrig
),self
.start_enigme
,(serv
,c
,token
))
183 def start_enigme(self
,serv
,channel
,token
=None):
184 # On reste silencieux si lechan n'est pas actif
185 if not self
.is_active(channel
):
186 serv
.execute_delayed(ttrig
*5,self
.start_enigme
,(serv
,channel
,token
))
188 if self
.play_status
[channel
][0]==0 and channel
in self
.play_channels
:
190 if token
==self
.play_status
[channel
][-1]:
193 if time
.time() > self
.play_status
[channel
][-1]+config_time_incompressible
:
198 date
,evenement
=self
.get_enigme()
199 log(self
.serveur
,channel
,u
"$Date$".encode("utf8"),("%s : %s"%(date
, evenement
)).encode("utf8"))
200 serv
.privmsg(channel
,evenement
.encode("utf8"))
202 # le 0 est le flag "bon siècle" n'a pas encore été dit
203 self
.play_status
[channel
]=[1,date
,evenement
,0,token
]
204 serv
.execute_delayed(random
.randrange(ttrig
*3,ttrig
*5),self
.give_indice
,(serv
,channel
,token
))
207 def give_indice(self
,serv
,channel
,token
):
208 if self
.play_status
[channel
][0]==1:
210 # c'est donc que l'indice a été demandé
211 if self
.play_status
[channel
][-1]+config_time_incompressible_clue
<time
.time():
212 token
=self
.play_status
[channel
][-1]
213 if self
.play_status
[channel
][-1]==token
:
214 date
=self
.play_status
[channel
][1]
216 serv
.privmsg(channel
,"indice : %s"%(indice).encode("utf8"))
217 self
.play_status
[channel
][0]=2
218 serv
.execute_delayed(random
.randrange(ttrig
*1,ttrig
*3),self
.give_answer
,(serv
,channel
,token
))
219 def give_answer(self
,serv
,channel
,token
):
220 if self
.play_status
[channel
][0]==2 and self
.play_status
[channel
][-1]==token
:
221 date
=self
.play_status
[channel
][1]
222 serv
.privmsg(channel
,"C'était le %s"%(date).encode("utf8"))
224 self
.play_status
[channel
]=[0,token
]
225 serv
.execute_delayed(random
.randrange(Ttrig
*5,Ttrig
*10),self
.start_enigme
,(serv
,channel
,token
))
227 def get_enigme(self
):
228 # on récupère les dates
229 f
=open(config_source_file
)
232 l
=[i
.split(" : ",2) for i
in l
]
233 dates
={int(i
[0]):i
[1:] for i
in l
}
234 # on va chercher combien de fois elles ont été jouées
235 played_file
=get_config_played_file(self
.serveur
)
239 l
=re
.findall("(.*):(.*)",t
)
240 played
={int(i
[0]):int(i
[1]) for i
in l
}
241 # on récupère le nombre d'occurrences le plus faible
242 mini
=min(played
.values())
243 # on choisit un id dans ceux qui ont ce nombre d'occurences
244 id_choisi
=random
.choice([k
for k
,v
in played
.items() if v
==mini
])
245 date
,evenement
=dates
[id_choisi
]
246 evenement
=evenement
.replace("\n","")
247 # on incrémente la choisie
249 # on enregistre le played_file
250 f
=open(played_file
,"w")
251 f
.write("\n".join(["%-4s : %s"%(k
,v
) for k
,v
in played
.items()]))
253 return map(lambda x
:x
.decode("utf8"), [date
,evenement
])
255 def pourmoi(self
, serv
, message
):
258 if message
[:size
]==pseudo
and len(message
)>size
and message
[size
]==":":
259 return (True,message
[size
+1:].strip(" "))
261 return (False,message
)
263 def on_privmsg(self
, serv
, ev
):
264 message
=ev
.arguments()[0]
265 auteur
= irclib
.nm_to_n(ev
.source())
267 test
=bot_unicode(message
)
268 except UnicodeBotError
:
270 "Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…")
272 message
=message
.split()
273 cmd
=message
[0].lower()
276 helpmsg_default
="""Liste des commandes :
277 HELP Affiche ce message d'aide
278 SCORE Affiche ton score (SCORE TRANSFERT <pseudo> [<n>] pour transférer des points)
279 SCORES Affiche les scores"""
281 JOIN Faire rejoindre un channel (sans paramètres, donne la liste des chans actuels)
282 LEAVE Faire quitter un channel
283 PLAY Passe un channel en mode "jouer"
284 NOPLAY Passe un channel en mode "ne pas jouer"
285 QUIET Se taire sur un channel
286 NOQUIET Opposé de QUIET"""
288 SCORES {DEL|ADD|SUB} Tu veux un dessin ?
289 SAY Fais envoyer un message sur un chan ou à une personne
290 STAY Ignorera les prochains LEAVE pour un chan
291 NOSTAY Opposé de STAY
292 STATUS Montre l'état courant
294 helpmsg
=helpmsg_default
295 if auteur
in self
.ops
:
297 if auteur
in self
.overops
:
298 helpmsg
+=helpmsg_overops
299 for ligne
in helpmsg
.split("\n"):
300 serv
.privmsg(auteur
,ligne
)
302 if auteur
in self
.ops
:
304 if message
[1] in self
.chanlist
:
305 serv
.privmsg(auteur
,"Je suis déjà sur %s"%(message
[1]))
307 serv
.join(message
[1])
308 self
.chanlist
.append(message
[1])
309 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
310 log(self
.serveur
,"priv",auteur
," ".join(message
))
312 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
316 if auteur
in self
.ops
and len(message
)>1:
317 if message
[1] in self
.chanlist
:
318 if not (message
[1] in self
.stay_channels
) or auteur
in self
.overops
:
319 self
.quitter(message
[1]," ".join(message
[2:]))
320 self
.chanlist
.remove(message
[1])
321 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
323 serv
.privmsg(auteur
,"Non, je reste !")
324 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
326 serv
.privmsg(auteur
,"Je ne suis pas sur %s"%(message
[1]))
330 if auteur
in self
.overops
:
332 if message
[1] in self
.stay_channels
:
333 serv
.privmsg(auteur
,"Je stay déjà sur %s."%(message
[1]))
334 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
336 self
.stay_channels
.append(message
[1])
337 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
338 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
340 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
344 if auteur
in self
.overops
:
346 if message
[1] in self
.stay_channels
:
347 self
.stay_channels
.remove(message
[1])
348 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
349 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
351 serv
.privmsg(auteur
,"Je ne stay pas sur %s."%(message
[1]))
352 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
356 if auteur
in self
.ops
:
358 if message
[1] in self
.play_channels
:
359 serv
.privmsg(auteur
,"Je play déjà sur %s."%(message
[1]))
360 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
362 self
.play_channels
.append(message
[1])
363 self
.play_status
[message
[1]]=[0,time
.time()-3600]
364 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
365 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
367 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
371 if auteur
in self
.ops
:
373 if message
[1] in self
.play_channels
:
374 self
.play_channels
.remove(message
[1])
375 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
376 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
378 serv
.privmsg(auteur
,"Je ne play pas sur %s."%(message
[1]))
379 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
383 if auteur
in self
.ops
:
385 if message
[1] in self
.quiet_channels
:
386 serv
.privmsg(auteur
,"Je me la ferme déjà sur %s"%(message
[1]))
387 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
389 self
.quiet_channels
.append(message
[1])
390 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
391 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
393 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
397 if auteur
in self
.ops
:
399 if message
[1] in self
.quiet_channels
:
400 self
.quiet_channels
.remove(message
[1])
401 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
402 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
404 serv
.privmsg(auteur
,"Je ne me la ferme pas sur %s."%(message
[1]))
405 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
408 elif cmd
in ["states","status"]:
409 if auteur
in self
.overops
:
410 for k
in self
.play_status
.keys():
411 serv
.privmsg(auteur
,(u
"%s : %s"%(k
," | ".join([unicode(i
) for i
in self
.play_status
[k
]]))).encode("utf8") )
413 if auteur
in self
.overops
and len(message
)>2:
414 serv
.privmsg(message
[1]," ".join(message
[2:]))
415 log(self
.serveur
,"priv",auteur
," ".join(message
))
416 elif len(message
)<=2:
417 serv
.privmsg(auteur
,"Syntaxe : SAY <channel> <message>")
421 if auteur
in self
.overops
:
422 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
426 if len(message
) in [3,4] and message
[1].lower()=="transfert":
427 scores
=self
.get_scores()
428 de
,to
=auteur
,message
[2]
429 value
=scores
.get(de
,0)
432 asked
=int(message
[3])
434 serv
.privmsg(auteur
,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
439 serv
.privmsg(auteur
,"Vous n'avez pas de points")
442 serv
.privmsg(auteur
,"Bien tenté…")
445 serv
.privmsg(auteur
,"Vous n'avez que %s points"%(value))
448 self
.add_score(de
,-asked
)
449 self
.add_score(to
,asked
)
450 serv
.privmsg(auteur
,"Transfert de %s points de %s à %s"%(asked
,de
,to
))
452 serv
.privmsg(auteur
,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
454 serv
.privmsg(auteur
,"Votre score : %s"%(self
.get_scores().get(auteur
,0)) )
457 scores
=self
.get_scores().items()
459 scores
.sort(lambda x
,y
:cmp(x
[1],y
[1]))
461 serv
.privmsg(auteur
,"Scores by score : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
463 scores
.sort(lambda x
,y
:cmp(x
[0].lower(),y
[0].lower()))
464 serv
.privmsg(auteur
,"Scores by pseudo : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
465 elif auteur
in self
.overops
:
466 souscmd
=message
[1].lower()
470 scores
=self
.get_scores()
471 if scores
.has_key(todelete
):
473 self
.save_scores(scores
)
474 serv
.privmsg(auteur
,"Score de %s supprimé"%(todelete))
476 serv
.privmsg(auteur
,"Ce score n'existe pas : %s"%(todelete))
478 serv
.privmsg(auteur
,"Syntaxe : SCORES DEL <pseudo>")
479 elif souscmd
in ["add","sub"]:
481 toadd
,val
=message
[2],message
[3]
485 serv
.privmsg(auteur
,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
489 self
.add_score(toadd
,val
)
490 serv
.privmsg(auteur
,"Done")
492 serv
.privmsg(auteur
,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
494 serv
.privmsg(auteur
,"Syntaxe : SCORES {DEL|ADD|SUB} <pseudo> [<n>]")
500 serv
.privmsg(auteur
,"Je n'ai pas compris. Essaye HELP…")
502 def on_pubmsg(self
, serv
, ev
):
503 auteur
= irclib
.nm_to_n(ev
.source())
505 message
= ev
.arguments()[0]
506 self
.update_activity(canal
,auteur
)
508 test
=bot_unicode(message
)
509 except UnicodeBotError
:
510 if not canal
in self
.quiet_channels
:
512 "%s: Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…"%(auteur))
515 pour_moi
,message
=self
.pourmoi(serv
,message
)
516 if pour_moi
and message
.split()!=[]:
517 cmd
=message
.split()[0].lower()
519 args
=" ".join(message
.split()[1:])
522 if cmd
in ["meurs","die","crève"]:
523 if auteur
in self
.overops
:
525 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
527 serv
.privmsg(canal
,"%s: crève !"%(auteur))
528 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
529 if cmd
in ["meur", "meurt","meurre","meurres"] and not canal
in self
.quiet_channels
:
530 serv
.privmsg(canal
,'%s: Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)'%(auteur))
531 if cmd
in ["part","leave","dégage"]:
532 if auteur
in self
.ops
and (not (canal
in self
.stay_channels
)
533 or auteur
in self
.overops
):
535 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
536 self
.chanlist
.remove(canal
)
538 serv
.privmsg(canal
,"%s: Non, je reste !"%(auteur))
539 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
541 if cmd
in ["deviens","pseudo"]:
542 if auteur
in self
.ops
:
545 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
546 if cmd
in ["coucou"] and not canal
in self
.quiet_channels
:
547 serv
.privmsg(canal
,"%s: coucou"%(auteur))
548 if cmd
in ["ping"] and not canal
in self
.quiet_channels
:
549 serv
.privmsg(canal
,"%s: pong"%(auteur))
550 if cmd
in ["date","dates","histoire","énigme","enigme","encore"]:
551 if canal
in self
.play_channels
:
552 if self
.play_status
.get(canal
,[-1])[0]==0:
554 self
.start_enigme(serv
,canal
)
556 serv
.privmsg(canal
,"%s: Je peux souffler une minute ?"%(auteur))
558 serv
.privmsg(canal
,("%s: Rappel : %s"%(auteur
,self
.play_status
[canal
][2])).encode("utf8") )
560 serv
.privmsg(canal
,"%s: pas ici…"%(auteur))
561 if cmd
in ["score","!score"]:
562 serv
.privmsg(auteur
,"Votre score : %s"%(self
.get_scores().get(auteur
,0)) )
563 if cmd
in ["scores","!scores"]:
564 scores
=self
.get_scores().items()
566 scores
.sort(lambda x
,y
:cmp(x
[1],y
[1]))
568 serv
.privmsg(auteur
,"Scores by score : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
570 scores
.sort(lambda x
,y
:cmp(x
[0].lower(),y
[0].lower()))
571 serv
.privmsg(auteur
,"Scores by pseudo : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
572 if cmd
=="indice" and canal
in self
.play_channels
:
573 self
.give_indice(serv
,canal
,None)
574 if is_tag(message
) and not canal
in self
.quiet_channels
:
575 if auteur
in self
.ops
:
576 action
=random
.choice(config_tag_actions
)
577 serv
.action(canal
,action
.encode("utf8"))
578 self
.quiet_channels
.append(canal
)
580 answer
=random
.choice(config_tag_answers
)
581 for ligne
in answer
.split("\n"):
582 serv
.privmsg(canal
,"%s: %s"%(auteur
,ligne
.encode("utf8")))
588 if self
.play_status
.get(canal
,[-1])[0] in [1,2]:
589 answer
=self
.play_status
[canal
][1]
590 flag_century
=self
.play_status
[canal
][3]
592 score_obtenu
=reussi(message
.decode("utf8"),answer
,auteur
)
595 serv
.privmsg(canal
,"%s: C'est le bon siècle, mais pas la bonne année, cherche encore ;)"%(auteur))
596 self
.play_status
[canal
][3]=1
599 if flag_century
in [0,1]:
600 serv
.privmsg(canal
,"%s: C'est la bonne décennie, mais pas la bonne année, encore un effort ;)"%(auteur))
601 self
.play_status
[canal
][3]=2
604 if self
.play_status
[canal
][0]==1:
605 bonusmsg
=u
" [+bonus_mois"*(score_obtenu
>config_score_annee
)+u
"+bonus_jour"*(score_obtenu
>config_score_annee
+config_score_mois
)
611 serv
.privmsg(canal
,(u
"%s: bravo ! (C'était le %s)%s"%(auteur
,answer
,bonusmsg
)).encode("utf8"))
612 log(self
.serveur
,canal
,auteur
+"$win",message
)
613 if auteur
in config_noscore
:
615 self
.add_score(auteur
,score_obtenu
)
617 self
.play_status
[canal
]=[0,token
]
618 serv
.execute_delayed(random
.randrange(Ttrig
*5,Ttrig
*10),self
.start_enigme
,(serv
,canal
,token
))
620 def on_kick(self
,serv
,ev
):
621 auteur
= irclib
.nm_to_n(ev
.source())
622 channel
= ev
.target()
623 victime
= ev
.arguments()[0]
624 raison
= ev
.arguments()[1]
625 if victime
==self
.nick
:
626 log(self
.serveur
,"%s kické de %s par %s (raison : %s)" %(victime
,channel
,auteur
,raison
))
629 self
.update_activity(channel
,"")
630 # on ne dit rien au rejoin
631 #l1,l2=config_kick_answers,config_kick_actions
632 #n1,n2=len(l1),len(l2)
633 #i=random.randrange(n1+n2)
635 # serv.action(channel,l2[i-n1].format(auteur).encode("utf8"))
637 # serv.privmsg(channel,l1[i].format(auteur).encode("utf8"))
639 def quitter(self
,chan
,leave_message
=None):
640 if leave_message
==None:
641 leave_message
=random
.choice(config_leave_messages
)
643 leave_message
=leave_message
%(time
.strftime("le %d/%m/%Y à %T").decode("utf8"),self
.nick
)
646 self
.serv
.part(chan
,message
=leave_message
.encode("utf8"))
649 quit_message
=random
.choice(config_quit_messages
)
651 quit_message
=quit_message
%(time
.strftime("le %d/%m/%Y à %T").decode("utf8"),self
.nick
)
654 self
.die(msg
=quit_message
.encode("utf8"))
656 def get_scores(self
):
657 f
=open(config_score_file
)
658 scores
=pickle
.load(f
)
662 def add_score(self
,pseudo
,value
):
663 scores
=self
.get_scores()
664 if scores
.has_key(pseudo
):
665 scores
[pseudo
]+=value
668 self
.save_scores(scores
)
670 def save_scores(self
,scores
):
671 f
=open(config_score_file
,"w")
672 pickle
.dump(scores
,f
)
676 return self
.serv
.get_nickname()
677 nick
= property(_getnick
)
679 def update_activity(self
,canal
,pseudo
):
680 if not pseudo
in config_idle_bots
:
681 self
.last_activity
[canal
]=time
.time()
682 def is_active(self
,canal
):
683 return time
.time()-self
.last_activity
[canal
]<config_idle_time
685 def start_as_daemon(self
, outfile
):
686 sys
.stderr
= Logger(outfile
)
690 class Logger(object):
691 """Pour écrire ailleurs que sur stdout"""
692 def __init__(self
, filename
="historien.full.log"):
693 self
.filename
= filename
695 def write(self
, message
):
696 f
= open(self
.filename
, "a")
701 if __name__
=="__main__":
704 print "Usage : historien.py <serveur> [--debug] [--no-output] [--daemon [--pidfile]] [--outfile]"
705 print " --outfile sans --no-output ni --daemon n'a aucun effet"
708 if "--daemon" in sys
.argv
:
709 thisfile
= os
.path
.realpath(__file__
)
710 thisdirectory
= thisfile
.rsplit("/", 1)[0]
711 os
.chdir(thisdirectory
)
715 if "debug" in sys
.argv
or "--debug" in sys
.argv
:
719 if "--no-output" in sys
.argv
or "--daemon" in sys
.argv
:
720 outfile
= "/var/log/bots/historien.full.log"
723 if arg
[0].strip('-') in ["out", "outfile", "logfile"]:
725 sys
.stdout
= Logger(outfile
)
726 serveurs
={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
727 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"}
729 serveur
=serveurs
[serveur
]
731 print "Server Unknown : %s"%(serveur)
733 historien
=Historien(serveur
,debug
)
735 child_pid
= os
.fork()
738 historien
.start_as_daemon(outfile
)
740 # on enregistre le pid de historien
741 pidfile
= "/var/run/bots/historien.pid"
744 if arg
[0].strip('-') in ["pidfile"]:
746 f
= open(pidfile
, "w")
747 f
.write("%s\n" % child_pid
)