4 # Codé par 20-100 le 25/05/12
6 # Un bot IRC qui pose des questions d'histoire
15 from cast_as_date
import *
17 # Oui, j'ai recodé ma version d'irclib pour pouvoir rattrapper les SIGHUP
18 sys
.path
.insert(0, "/home/vincent/scripts/python-myirclib")
22 config_password
="EtTaMère,ElleEstNéeQuand?"
23 config_pseudo
="historien"
24 config_chanlist
=["#bot","#flood"]
25 config_play_channels
=["#flood"]
26 config_stay_channels
=["#flood","#bot"]
27 config_overops
=["[20-100]","[20-100]_"]
28 config_ops
=["PEB","Petite-Peste"]
30 config_source_file
="dates.txt"
31 config_played_file_template
="played.%s.txt" #il faut rajouter le nom du serveur
32 def get_config_played_file(serveur
):
33 serveurs
={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
34 return config_played_file_template
%(serveurs
[serveur
])
35 ttrig
=120 #time trigger (normalement 120, mais diminué pour les tests)
36 Ttrig
=600 #between two enigms
37 config_time_incompressible
=15 #on peut pas retrigger en dessous de ce temps (60)
38 config_time_incompressible_clue
=60 #on peut pas forcer la demande d'indice en dessous
40 config_score_file
="scores.pickle"
42 config_tag_triggers
=[u
"t(|a)g",u
"ta gueule",u
"la ferme",u
"ferme( |-)la",u
"tais-toi",u
"chut"]
43 config_tag_actions
=[u
"se tait",u
"ferme sa gueule",u
"se la ferme",u
"la ferme"]
44 config_tag_answers
=[u
"J'me tais si j'veux !",
45 u
"Je t'entends pas :°",
47 u
"Non, j'ai pas envie",
48 u
"Peut-être quand toi tu la fermeras, et encore…"]
53 config_debug_stdout
= True
54 config_logfile_template
="historien.%s.log"
55 def get_config_logfile(serveur
):
56 serveurs
={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
57 return config_logfile_template
%(serveurs
[serveur
])
59 config_quit_messages
=[u
"%s : %s quitte le serveur IRC"]
61 config_leave_messages
=[u
"%s : %s quitte le channel"]
63 # Quand personne ne cause, on finit par se taire
64 # temps au bout duquel, si personne n'a parlé, on se tait
65 config_idle_time
=20*60
66 # liste des bots, qui ne sont pas considérés comme de l'activité
67 config_idle_bots
=["deconnaisseur","Basile","historien","hung","salesman","Shadobot","Wen","___","Sanctuary","Saturnin"]
69 class UnicodeBotError(Exception):
71 def bot_unicode(chain
):
74 except UnicodeDecodeError:
77 def log(serveur
,channel
,auteur
=None,message
=None):
78 f
=open(get_config_logfile(serveur
),"a")
79 if auteur
==message
==None:
80 # alors c'est que c'est pas un channel mais juste une ligne de log
81 chain
="%s %s"%(time
.strftime("%F %T"),channel
)
83 chain
="%s [%s:%s] %s"%(time
.strftime("%F %T"),channel
,auteur
,message
)
85 if config_debug_stdout
:
94 config_noscore
=["[20-100]","[20-100]_"] # parce que 20-100 est nul en histoire
96 class GoodCentury(Exception):
99 class GoodDeceny(Exception):
102 def reussi(message
,answer
,auteur
):
103 if auteur
in config_level3
:
104 return answer
in message
105 if auteur
in config_level2
:
106 return answer
in message
109 date
=cast_as_date(message
.lower().strip())
110 except ThisIsNotADate
:
112 realdate
=map(lambda x
:int(x
), answer
.split('/'))
115 if date
[0]==realdate
[0]:
116 score
=config_score_annee
117 if date
[1]==realdate
[1]:
118 score
+=config_score_mois
119 if date
[2]==realdate
[2]:
120 score
+=config_score_jour
121 elif date
[0]/10 == realdate
[0]/10:
123 elif date
[0]/100 == realdate
[0]/100:
127 def is_something(chain
,matches
,avant
=u
".*(?:^| )",apres
=u
"(?:$|\.| |,|;).*",case_sensitive
=False,debug
=False):
129 chain
=unicode(chain
,"utf8")
131 chain
=unicode(chain
,"utf8").lower()
132 allmatches
="("+"|".join(matches
)+")"
133 reg
=(avant
+allmatches
+apres
).lower()
134 o
=re
.match(reg
,chain
)
138 return is_something(chain
,config_tag_triggers
)
140 class RefuseError(Exception):
143 class Historien(ircbot
.SingleServerIRCBot
):
144 def __init__(self
,serveur
,debug
=False):
145 temporary_pseudo
=config_pseudo
+str(random
.randrange(10000,100000))
146 ircbot
.SingleServerIRCBot
.__init
__(self
, [(serveur
, 6667)],
147 temporary_pseudo
,"Un bot irc qui a au moins l'agreg d'histoire", 10)
150 self
.overops
=config_overops
151 self
.ops
=self
.overops
+config_ops
152 self
.chanlist
=config_chanlist
153 self
.stay_channels
=config_stay_channels
154 self
.play_channels
=config_play_channels
155 self
.play_status
={i
:[0] for i
in self
.play_channels
}
156 self
.last_activity
={}
157 self
.quiet_channels
=[]
159 def give_me_my_pseudo(self
,serv
):
160 serv
.privmsg("NickServ","RECOVER %s %s"%(config_pseudo
,config_password
))
161 serv
.privmsg("NickServ","RELEASE %s %s"%(config_pseudo
,config_password
))
163 serv
.nick(config_pseudo
)
165 def on_welcome(self
, serv
, ev
):
166 self
.serv
=serv
# ça serv ira :)
167 self
.give_me_my_pseudo(serv
)
168 serv
.privmsg("NickServ","identify %s"%(config_password))
169 log(self
.serveur
,"Connected")
171 self
.chanlist
=["#bot"]
172 self
.play_channels
=["#bot"]
173 for c
in self
.chanlist
:
174 log(self
.serveur
,"JOIN %s"%(c))
176 self
.update_activity(c
,"") # la chaîne vide ne sera jamais un nom de bot et donc marchera toujours
177 for c
in self
.play_channels
:
178 token
=time
.time()-3600
179 self
.play_status
[c
]=[0,token
]
180 serv
.execute_delayed(random
.randrange(ttrig
),self
.start_enigme
,(serv
,c
,token
))
182 def start_enigme(self
,serv
,channel
,token
=None):
183 # On reste silencieux si lechan n'est pas actif
184 if not self
.is_active(channel
):
185 serv
.execute_delayed(ttrig
*5,self
.start_enigme
,(serv
,channel
,token
))
187 if self
.play_status
[channel
][0]==0 and channel
in self
.play_channels
:
189 if token
==self
.play_status
[channel
][-1]:
192 if time
.time() > self
.play_status
[channel
][-1]+config_time_incompressible
:
197 date
,evenement
=self
.get_enigme()
198 log(self
.serveur
,channel
,u
"$Date$".encode("utf8"),("%s : %s"%(date
, evenement
)).encode("utf8"))
199 serv
.privmsg(channel
,evenement
.encode("utf8"))
201 # le 0 est le flag "bon siècle" n'a pas encore été dit
202 self
.play_status
[channel
]=[1,date
,evenement
,0,token
]
203 serv
.execute_delayed(random
.randrange(ttrig
*3,ttrig
*5),self
.give_indice
,(serv
,channel
,token
))
206 def give_indice(self
,serv
,channel
,token
):
207 if self
.play_status
[channel
][0]==1:
209 # c'est donc que l'indice a été demandé
210 if self
.play_status
[channel
][-1]+config_time_incompressible_clue
<time
.time():
211 token
=self
.play_status
[channel
][-1]
212 if self
.play_status
[channel
][-1]==token
:
213 date
=self
.play_status
[channel
][1]
215 serv
.privmsg(channel
,"indice : %s"%(indice).encode("utf8"))
216 self
.play_status
[channel
][0]=2
217 serv
.execute_delayed(random
.randrange(ttrig
*1,ttrig
*3),self
.give_answer
,(serv
,channel
,token
))
218 def give_answer(self
,serv
,channel
,token
):
219 if self
.play_status
[channel
][0]==2 and self
.play_status
[channel
][-1]==token
:
220 date
=self
.play_status
[channel
][1]
221 serv
.privmsg(channel
,"C'était le %s"%(date).encode("utf8"))
223 self
.play_status
[channel
]=[0,token
]
224 serv
.execute_delayed(random
.randrange(Ttrig
*5,Ttrig
*10),self
.start_enigme
,(serv
,channel
,token
))
226 def get_enigme(self
):
227 # on récupère les dates
228 f
=open(config_source_file
)
231 l
=[i
.split(" : ",2) for i
in l
]
232 dates
={int(i
[0]):i
[1:] for i
in l
}
233 # on va chercher combien de fois elles ont été jouées
234 played_file
=get_config_played_file(self
.serveur
)
238 l
=re
.findall("(.*):(.*)",t
)
239 played
={int(i
[0]):int(i
[1]) for i
in l
}
240 # on récupère le nombre d'occurrences le plus faible
241 mini
=min(played
.values())
242 # on choisit un id dans ceux qui ont ce nombre d'occurences
243 id_choisi
=random
.choice([k
for k
,v
in played
.items() if v
==mini
])
244 date
,evenement
=dates
[id_choisi
]
245 evenement
=evenement
.replace("\n","")
246 # on incrémente la choisie
248 # on enregistre le played_file
249 f
=open(played_file
,"w")
250 f
.write("\n".join(["%-4s : %s"%(k
,v
) for k
,v
in played
.items()]))
252 return map(lambda x
:x
.decode("utf8"), [date
,evenement
])
254 def pourmoi(self
, serv
, message
):
257 if message
[:size
]==pseudo
and len(message
)>size
and message
[size
]==":":
258 return (True,message
[size
+1:].strip(" "))
260 return (False,message
)
262 def on_privmsg(self
, serv
, ev
):
263 message
=ev
.arguments()[0]
264 auteur
= irclib
.nm_to_n(ev
.source())
266 test
=bot_unicode(message
)
267 except UnicodeBotError
:
269 "Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…")
271 message
=message
.split()
272 cmd
=message
[0].lower()
275 helpmsg_default
="""Liste des commandes :
276 HELP Affiche ce message d'aide
277 SCORE Affiche ton score (SCORE TRANSFERT <pseudo> [<n>] pour transférer des points)
278 SCORES Affiche les scores"""
280 JOIN Faire rejoindre un channel (sans paramètres, donne la liste des chans actuels)
281 LEAVE Faire quitter un channel
282 PLAY Passe un channel en mode "jouer"
283 NOPLAY Passe un channel en mode "ne pas jouer"
284 QUIET Se taire sur un channel
285 NOQUIET Opposé de QUIET"""
287 SCORES {DEL|ADD|SUB} Tu veux un dessin ?
288 SAY Fais envoyer un message sur un chan ou à une personne
289 STAY Ignorera les prochains LEAVE pour un chan
290 NOSTAY Opposé de STAY
291 STATUS Montre l'état courant
293 helpmsg
=helpmsg_default
294 if auteur
in self
.ops
:
296 if auteur
in self
.overops
:
297 helpmsg
+=helpmsg_overops
298 for ligne
in helpmsg
.split("\n"):
299 serv
.privmsg(auteur
,ligne
)
301 if auteur
in self
.ops
:
303 if message
[1] in self
.chanlist
:
304 serv
.privmsg(auteur
,"Je suis déjà sur %s"%(message
[1]))
306 serv
.join(message
[1])
307 self
.chanlist
.append(message
[1])
308 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
309 log(self
.serveur
,"priv",auteur
," ".join(message
))
311 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
315 if auteur
in self
.ops
and len(message
)>1:
316 if message
[1] in self
.chanlist
:
317 if not (message
[1] in self
.stay_channels
) or auteur
in self
.overops
:
318 self
.quitter(message
[1]," ".join(message
[2:]))
319 self
.chanlist
.remove(message
[1])
320 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
322 serv
.privmsg(auteur
,"Non, je reste !")
323 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
325 serv
.privmsg(auteur
,"Je ne suis pas sur %s"%(message
[1]))
329 if auteur
in self
.overops
:
331 if message
[1] in self
.stay_channels
:
332 serv
.privmsg(auteur
,"Je stay déjà sur %s."%(message
[1]))
333 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
335 self
.stay_channels
.append(message
[1])
336 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
337 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
339 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
343 if auteur
in self
.overops
:
345 if message
[1] in self
.stay_channels
:
346 self
.stay_channels
.remove(message
[1])
347 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
348 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
350 serv
.privmsg(auteur
,"Je ne stay pas sur %s."%(message
[1]))
351 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
355 if auteur
in self
.ops
:
357 if message
[1] in self
.play_channels
:
358 serv
.privmsg(auteur
,"Je play déjà sur %s."%(message
[1]))
359 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
361 self
.play_channels
.append(message
[1])
362 self
.play_status
[message
[1]]=[0,time
.time()-3600]
363 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
364 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
366 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
370 if auteur
in self
.ops
:
372 if message
[1] in self
.play_channels
:
373 self
.play_channels
.remove(message
[1])
374 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
375 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
377 serv
.privmsg(auteur
,"Je ne play pas sur %s."%(message
[1]))
378 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
382 if auteur
in self
.ops
:
384 if message
[1] in self
.quiet_channels
:
385 serv
.privmsg(auteur
,"Je me la ferme déjà sur %s"%(message
[1]))
386 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
388 self
.quiet_channels
.append(message
[1])
389 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
390 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
392 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
396 if auteur
in self
.ops
:
398 if message
[1] in self
.quiet_channels
:
399 self
.quiet_channels
.remove(message
[1])
400 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
401 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
403 serv
.privmsg(auteur
,"Je ne me la ferme pas sur %s."%(message
[1]))
404 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
407 elif cmd
in ["states","status"]:
408 if auteur
in self
.overops
:
409 for k
in self
.play_status
.keys():
410 serv
.privmsg(auteur
,(u
"%s : %s"%(k
," | ".join([unicode(i
) for i
in self
.play_status
[k
]]))).encode("utf8") )
412 if auteur
in self
.overops
and len(message
)>2:
413 serv
.privmsg(message
[1]," ".join(message
[2:]))
414 log(self
.serveur
,"priv",auteur
," ".join(message
))
415 elif len(message
)<=2:
416 serv
.privmsg(auteur
,"Syntaxe : SAY <channel> <message>")
420 if auteur
in self
.overops
:
421 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
425 if len(message
) in [3,4] and message
[1].lower()=="transfert":
426 scores
=self
.get_scores()
427 de
,to
=auteur
,message
[2]
428 value
=scores
.get(de
,0)
431 asked
=int(message
[3])
433 serv
.privmsg(auteur
,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
438 serv
.privmsg(auteur
,"Vous n'avez pas de points")
441 serv
.privmsg(auteur
,"Bien tenté…")
444 serv
.privmsg(auteur
,"Vous n'avez que %s points"%(value))
447 self
.add_score(de
,-asked
)
448 self
.add_score(to
,asked
)
449 serv
.privmsg(auteur
,"Transfert de %s points de %s à %s"%(asked
,de
,to
))
451 serv
.privmsg(auteur
,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
453 serv
.privmsg(auteur
,"Votre score : %s"%(self
.get_scores().get(auteur
,0)) )
456 scores
=self
.get_scores().items()
458 scores
.sort(lambda x
,y
:cmp(x
[1],y
[1]))
460 serv
.privmsg(auteur
,"Scores by score : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
462 scores
.sort(lambda x
,y
:cmp(x
[0].lower(),y
[0].lower()))
463 serv
.privmsg(auteur
,"Scores by pseudo : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
464 elif auteur
in self
.overops
:
465 souscmd
=message
[1].lower()
469 scores
=self
.get_scores()
470 if scores
.has_key(todelete
):
472 self
.save_scores(scores
)
473 serv
.privmsg(auteur
,"Score de %s supprimé"%(todelete))
475 serv
.privmsg(auteur
,"Ce score n'existe pas : %s"%(todelete))
477 serv
.privmsg(auteur
,"Syntaxe : SCORES DEL <pseudo>")
478 elif souscmd
in ["add","sub"]:
480 toadd
,val
=message
[2],message
[3]
484 serv
.privmsg(auteur
,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
488 self
.add_score(toadd
,val
)
489 serv
.privmsg(auteur
,"Done")
491 serv
.privmsg(auteur
,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
493 serv
.privmsg(auteur
,"Syntaxe : SCORES {DEL|ADD|SUB} <pseudo> [<n>]")
499 serv
.privmsg(auteur
,"Je n'ai pas compris. Essaye HELP…")
501 def on_pubmsg(self
, serv
, ev
):
502 auteur
= irclib
.nm_to_n(ev
.source())
504 message
= ev
.arguments()[0]
505 self
.update_activity(canal
,auteur
)
507 test
=bot_unicode(message
)
508 except UnicodeBotError
:
509 if not canal
in self
.quiet_channels
:
511 "%s: Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…"%(auteur))
514 pour_moi
,message
=self
.pourmoi(serv
,message
)
515 if pour_moi
and message
.split()!=[]:
516 cmd
=message
.split()[0].lower()
518 args
=" ".join(message
.split()[1:])
521 if cmd
in ["meurs","die","crève"]:
522 if auteur
in self
.overops
:
524 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
526 serv
.privmsg(canal
,"%s: crève !"%(auteur))
527 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
528 if cmd
in ["meur", "meurt","meurre","meurres"] and not canal
in self
.quiet_channels
:
529 serv
.privmsg(canal
,'%s: Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)'%(auteur))
530 if cmd
in ["part","leave","dégage"]:
531 if auteur
in self
.ops
and (not (canal
in self
.stay_channels
)
532 or auteur
in self
.overops
):
534 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
535 self
.chanlist
.remove(canal
)
537 serv
.privmsg(canal
,"%s: Non, je reste !"%(auteur))
538 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
540 if cmd
in ["deviens","pseudo"]:
541 if auteur
in self
.ops
:
544 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
545 if cmd
in ["coucou"] and not canal
in self
.quiet_channels
:
546 serv
.privmsg(canal
,"%s: coucou"%(auteur))
547 if cmd
in ["ping"] and not canal
in self
.quiet_channels
:
548 serv
.privmsg(canal
,"%s: pong"%(auteur))
549 if cmd
in ["date","dates","histoire","énigme","enigme","encore"]:
550 if canal
in self
.play_channels
:
551 if self
.play_status
.get(canal
,[-1])[0]==0:
553 self
.start_enigme(serv
,canal
)
555 serv
.privmsg(canal
,"%s: Je peux souffler une minute ?"%(auteur))
557 serv
.privmsg(canal
,("%s: Rappel : %s"%(auteur
,self
.play_status
[canal
][2])).encode("utf8") )
559 serv
.privmsg(canal
,"%s: pas ici…"%(auteur))
560 if cmd
in ["score","!score"]:
561 serv
.privmsg(auteur
,"Votre score : %s"%(self
.get_scores().get(auteur
,0)) )
562 if cmd
in ["scores","!scores"]:
563 scores
=self
.get_scores().items()
565 scores
.sort(lambda x
,y
:cmp(x
[1],y
[1]))
567 serv
.privmsg(auteur
,"Scores by score : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
569 scores
.sort(lambda x
,y
:cmp(x
[0].lower(),y
[0].lower()))
570 serv
.privmsg(auteur
,"Scores by pseudo : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
571 if cmd
=="indice" and canal
in self
.play_channels
:
572 self
.give_indice(serv
,canal
,None)
573 if is_tag(message
) and not canal
in self
.quiet_channels
:
574 if auteur
in self
.ops
:
575 action
=random
.choice(config_tag_actions
)
576 serv
.action(canal
,action
.encode("utf8"))
577 self
.quiet_channels
.append(canal
)
579 answer
=random
.choice(config_tag_answers
)
580 for ligne
in answer
.split("\n"):
581 serv
.privmsg(canal
,"%s: %s"%(auteur
,ligne
.encode("utf8")))
587 if self
.play_status
.get(canal
,[-1])[0] in [1,2]:
588 answer
=self
.play_status
[canal
][1]
589 flag_century
=self
.play_status
[canal
][3]
591 score_obtenu
=reussi(message
.decode("utf8"),answer
,auteur
)
594 serv
.privmsg(canal
,"%s: C'est le bon siècle, mais pas la bonne année, cherche encore ;)"%(auteur))
595 self
.play_status
[canal
][3]=1
598 if flag_century
in [0,1]:
599 serv
.privmsg(canal
,"%s: C'est la bonne décennie, mais pas la bonne année, encore un effort ;)"%(auteur))
600 self
.play_status
[canal
][3]=2
603 if self
.play_status
[canal
][0]==1:
604 bonusmsg
=u
" [+bonus_mois"*(score_obtenu
>config_score_annee
)+u
"+bonus_jour"*(score_obtenu
>config_score_annee
+config_score_mois
)
610 serv
.privmsg(canal
,(u
"%s: bravo ! (C'était le %s)%s"%(auteur
,answer
,bonusmsg
)).encode("utf8"))
611 log(self
.serveur
,canal
,auteur
+"$win",message
)
612 if auteur
in config_noscore
:
614 self
.add_score(auteur
,score_obtenu
)
616 self
.play_status
[canal
]=[0,token
]
617 serv
.execute_delayed(random
.randrange(Ttrig
*5,Ttrig
*10),self
.start_enigme
,(serv
,canal
,token
))
619 def on_kick(self
,serv
,ev
):
620 auteur
= irclib
.nm_to_n(ev
.source())
621 channel
= ev
.target()
622 victime
= ev
.arguments()[0]
623 raison
= ev
.arguments()[1]
624 if victime
==self
.nick
:
625 log(self
.serveur
,"%s kické de %s par %s (raison : %s)" %(victime
,channel
,auteur
,raison
))
628 self
.update_activity(channel
,"")
629 # on ne dit rien au rejoin
630 #l1,l2=config_kick_answers,config_kick_actions
631 #n1,n2=len(l1),len(l2)
632 #i=random.randrange(n1+n2)
634 # serv.action(channel,l2[i-n1].format(auteur).encode("utf8"))
636 # serv.privmsg(channel,l1[i].format(auteur).encode("utf8"))
638 def quitter(self
,chan
,leave_message
=None):
639 if leave_message
==None:
640 leave_message
=random
.choice(config_leave_messages
)
642 leave_message
=leave_message
%(time
.strftime("le %d/%m/%Y à %T").decode("utf8"),self
.nick
)
645 self
.serv
.part(chan
,message
=leave_message
.encode("utf8"))
648 quit_message
=random
.choice(config_quit_messages
)
650 quit_message
=quit_message
%(time
.strftime("le %d/%m/%Y à %T").decode("utf8"),self
.nick
)
653 self
.die(msg
=quit_message
.encode("utf8"))
655 def get_scores(self
):
656 f
=open(config_score_file
)
657 scores
=pickle
.load(f
)
661 def add_score(self
,pseudo
,value
):
662 scores
=self
.get_scores()
663 if scores
.has_key(pseudo
):
664 scores
[pseudo
]+=value
667 self
.save_scores(scores
)
669 def save_scores(self
,scores
):
670 f
=open(config_score_file
,"w")
671 pickle
.dump(scores
,f
)
675 return self
.serv
.get_nickname()
676 nick
= property(_getnick
)
678 def update_activity(self
,canal
,pseudo
):
679 if not pseudo
in config_idle_bots
:
680 self
.last_activity
[canal
]=time
.time()
681 def is_active(self
,canal
):
682 return time
.time()-self
.last_activity
[canal
]<config_idle_time
684 def start_as_daemon(self
, outfile
):
685 sys
.stderr
= Logger(outfile
)
689 class Logger(object):
690 """Pour écrire ailleurs que sur stdout"""
691 def __init__(self
, filename
="historien.full.log"):
692 self
.filename
= filename
694 def write(self
, message
):
695 f
= open(self
.filename
, "a")
700 if __name__
=="__main__":
703 print "Usage : historien.py <serveur> [--debug] [--no-output] [--daemon [--pidfile]] [--outfile]"
704 print " --outfile sans --no-output ni --daemon n'a aucun effet"
707 if "--daemon" in sys
.argv
:
708 thisfile
= os
.path
.realpath(__file__
)
709 thisdirectory
= thisfile
.rsplit("/", 1)[0]
710 os
.chdir(thisdirectory
)
714 if "debug" in sys
.argv
or "--debug" in sys
.argv
:
718 if "--no-output" in sys
.argv
or "--daemon" in sys
.argv
:
719 outfile
= "/var/log/bots/historien.full.log"
722 if arg
[0].strip('-') in ["out", "outfile", "logfile"]:
724 sys
.stdout
= Logger(outfile
)
725 serveurs
={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
726 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"}
728 serveur
=serveurs
[serveur
]
730 print "Server Unknown : %s"%(serveur)
732 historien
=Historien(serveur
,debug
)
734 child_pid
= os
.fork()
737 historien
.start_as_daemon(outfile
)
739 # on enregistre le pid de historien
740 pidfile
= "/var/run/bots/historien.pid"
743 if arg
[0].strip('-') in ["pidfile"]:
745 f
= open(pidfile
, "w")
746 f
.write("%s\n" % child_pid
)