]>
gitweb.pimeys.fr Git - bots/historien.git/blob - historien.py
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")
26 def get_config_played_file(serveur
):
27 serveurs
={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
28 return config
.played_file_template
%(serveurs
[serveur
])
30 def get_config_logfile(serveur
):
31 serveurs
={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
32 return config
.logfile_template
%(serveurs
[serveur
])
34 class UnicodeBotError(Exception):
36 def bot_unicode(chain
):
39 except UnicodeDecodeError:
42 def log(serveur
,channel
,auteur
=None,message
=None):
43 f
=open(get_config_logfile(serveur
),"a")
44 if auteur
==message
==None:
45 # alors c'est que c'est pas un channel mais juste une ligne de log
46 chain
="%s %s"%(time
.strftime("%F %T"),channel
)
48 chain
="%s [%s:%s] %s"%(time
.strftime("%F %T"),channel
,auteur
,message
)
50 if config
.debug_stdout
:
54 def ignore_event(serv
, ev
):
55 """Retourne ``True`` si il faut ignorer cet évènement."""
56 for (blackmask
, exceptmask
) in config
.blacklisted_masks
:
57 usermask
= ev
.source()
58 if exceptmask
is None:
61 exceptit
= bool(irclib
.mask_matches(usermask
, exceptmask
))
62 blackit
= bool(irclib
.mask_matches(usermask
, blackmask
))
63 if blackit
and not exceptit
:
66 class GoodCentury(Exception):
69 class GoodDeceny(Exception):
72 def reussi(message
,answer
,auteur
):
73 if auteur
in config
.level3
:
74 return answer
in message
75 if auteur
in config
.level2
:
76 return answer
in message
79 date
=cast_as_date(message
.lower().strip())
80 except ThisIsNotADate
:
82 realdate
=map(lambda x
:int(x
), answer
.split('/'))
85 if date
[0]==realdate
[0]:
86 score
=config
.score_annee
87 if date
[1]==realdate
[1]:
88 score
+=config
.score_mois
89 if date
[2]==realdate
[2]:
90 score
+=config
.score_jour
91 elif date
[0]/10 == realdate
[0]/10:
93 elif date
[0]/100 == realdate
[0]/100:
97 def is_something(chain
,matches
,avant
=u
".*(?:^| )",apres
=u
"(?:$|\.| |,|;).*",case_sensitive
=False,debug
=False):
99 chain
=unicode(chain
,"utf8")
101 chain
=unicode(chain
,"utf8").lower()
102 allmatches
="("+"|".join(matches
)+")"
103 reg
=(avant
+allmatches
+apres
).lower()
104 o
=re
.match(reg
,chain
)
108 return is_something(chain
,config
.tag_triggers
)
110 class RefuseError(Exception):
113 class Historien(ircbot
.SingleServerIRCBot
):
114 def __init__(self
,serveur
,debug
=False):
115 temporary_pseudo
=config
.pseudo
+str(random
.randrange(10000,100000))
116 ircbot
.SingleServerIRCBot
.__init
__(self
, [(serveur
, 6667)],
117 temporary_pseudo
,"Un bot irc qui a au moins l'agreg d'histoire", 10)
120 self
.overops
=config
.overops
121 self
.ops
=self
.overops
+config
.ops
122 self
.chanlist
=config
.chanlist
123 self
.stay_channels
=config
.stay_channels
124 self
.play_channels
=config
.play_channels
125 self
.play_status
={i
:[0] for i
in self
.play_channels
}
126 self
.last_activity
={}
127 self
.quiet_channels
=[]
129 def give_me_my_pseudo(self
,serv
):
130 serv
.privmsg("NickServ","RECOVER %s %s"%(config
.pseudo
,config
.password
))
131 serv
.privmsg("NickServ","RELEASE %s %s"%(config
.pseudo
,config
.password
))
133 serv
.nick(config
.pseudo
)
135 def on_welcome(self
, serv
, ev
):
136 self
.serv
=serv
# ça serv ira :)
137 self
.give_me_my_pseudo(serv
)
138 serv
.privmsg("NickServ","identify %s"%(config
.password
))
139 log(self
.serveur
,"Connected")
141 self
.chanlist
=["#bot"]
142 self
.play_channels
=["#bot"]
143 for c
in self
.chanlist
:
144 log(self
.serveur
,"JOIN %s"%(c))
146 self
.update_activity(c
,force
=True)
147 for c
in self
.play_channels
:
148 token
=time
.time()-3600
149 self
.play_status
[c
]=[0,token
]
150 serv
.execute_delayed(random
.randrange(config
.ttrig
),self
.start_enigme
,(serv
,c
,token
))
152 def start_enigme(self
,serv
,channel
,token
=None):
153 # On reste silencieux si lechan n'est pas actif
154 if not self
.is_active(channel
):
155 serv
.execute_delayed(config
.ttrig
*5,self
.start_enigme
,(serv
,channel
,token
))
157 if self
.play_status
[channel
][0]==0 and channel
in self
.play_channels
:
159 if token
==self
.play_status
[channel
][-1]:
162 if time
.time() > self
.play_status
[channel
][-1]+config
.time_incompressible
:
167 date
,evenement
=self
.get_enigme()
168 log(self
.serveur
,channel
,u
"$Date$".encode("utf8"),("%s : %s"%(date
, evenement
)).encode("utf8"))
169 serv
.privmsg(channel
,evenement
.encode("utf8"))
171 # le 0 est le flag "bon siècle" n'a pas encore été dit
172 self
.play_status
[channel
]=[1,date
,evenement
,0,token
]
173 serv
.execute_delayed(random
.randrange(config
.ttrig
*3,config
.ttrig
*5),self
.give_indice
,(serv
,channel
,token
))
176 def give_indice(self
,serv
,channel
,token
):
177 if self
.play_status
[channel
][0]==1:
179 # c'est donc que l'indice a été demandé
180 if self
.play_status
[channel
][-1]+config
.time_incompressible_clue
<time
.time():
181 token
=self
.play_status
[channel
][-1]
182 if self
.play_status
[channel
][-1]==token
:
183 date
=self
.play_status
[channel
][1]
185 serv
.privmsg(channel
,"indice : %s"%(indice).encode("utf8"))
186 self
.play_status
[channel
][0]=2
187 serv
.execute_delayed(random
.randrange(config
.ttrig
*1,config
.ttrig
*3),self
.give_answer
,(serv
,channel
,token
))
188 def give_answer(self
,serv
,channel
,token
):
189 if self
.play_status
[channel
][0]==2 and self
.play_status
[channel
][-1]==token
:
190 date
=self
.play_status
[channel
][1]
191 serv
.privmsg(channel
,"C'était le %s"%(date).encode("utf8"))
193 self
.play_status
[channel
]=[0,token
]
194 serv
.execute_delayed(random
.randrange(config
.Ttrig
*5,config
.Ttrig
*10),self
.start_enigme
,(serv
,channel
,token
))
196 def get_enigme(self
):
197 # on récupère les dates
198 f
=open(config
.source_file
)
201 l
=[i
.split(" : ",2) for i
in l
]
202 dates
={int(i
[0]):i
[1:] for i
in l
}
203 # on va chercher combien de fois elles ont été jouées
204 played_file
=get_config_played_file(self
.serveur
)
208 l
=re
.findall("(.*):(.*)",t
)
209 played
={int(i
[0]):int(i
[1]) for i
in l
}
210 # on récupère le nombre d'occurrences le plus faible
211 mini
=min(played
.values())
212 # on choisit un id dans ceux qui ont ce nombre d'occurences
213 id_choisi
=random
.choice([k
for k
,v
in played
.items() if v
==mini
])
214 date
,evenement
=dates
[id_choisi
]
215 evenement
=evenement
.replace("\n","")
216 # on incrémente la choisie
218 # on enregistre le played_file
219 f
=open(played_file
,"w")
220 f
.write("\n".join(["%-4s : %s"%(k
,v
) for k
,v
in played
.items()]))
222 return map(lambda x
:x
.decode("utf8"), [date
,evenement
])
224 def pourmoi(self
, serv
, message
):
227 if message
[:size
]==pseudo
and len(message
)>size
and message
[size
]==":":
228 return (True,message
[size
+1:].strip(" "))
230 return (False,message
)
232 def on_privmsg(self
, serv
, ev
):
233 if ignore_event(serv
, ev
):
235 message
=ev
.arguments()[0]
236 auteur
= irclib
.nm_to_n(ev
.source())
238 test
=bot_unicode(message
)
239 except UnicodeBotError
:
240 if config
.utf8_trigger
:
241 serv
.privmsg(auteur
, random
.choice(config
.utf8_fail_answers
).encode("utf8"))
243 message
=message
.split()
244 cmd
=message
[0].lower()
247 helpmsg_default
="""Liste des commandes :
248 HELP Affiche ce message d'aide
249 SCORE Affiche ton score (SCORE TRANSFERT <pseudo> [<n>] pour transférer des points)
250 SCORES Affiche les scores"""
252 JOIN Faire rejoindre un channel (sans paramètres, donne la liste des chans actuels)
253 LEAVE Faire quitter un channel
254 PLAY Passe un channel en mode "jouer"
255 NOPLAY Passe un channel en mode "ne pas jouer"
256 QUIET Se taire sur un channel
257 NOQUIET Opposé de QUIET
258 RELOAD Me fait recharger la conf"""
260 SCORES {DEL|ADD|SUB} Tu veux un dessin ?
261 SAY Fais envoyer un message sur un chan ou à une personne
262 STAY Ignorera les prochains LEAVE pour un chan
263 NOSTAY Opposé de STAY
264 STATUS Montre l'état courant
266 helpmsg
=helpmsg_default
267 if auteur
in self
.ops
:
269 if auteur
in self
.overops
:
270 helpmsg
+=helpmsg_overops
271 for ligne
in helpmsg
.split("\n"):
272 serv
.privmsg(auteur
,ligne
)
274 if auteur
in self
.ops
:
276 if message
[1] in self
.chanlist
:
277 serv
.privmsg(auteur
,"Je suis déjà sur %s"%(message
[1]))
279 serv
.join(message
[1])
280 self
.chanlist
.append(message
[1])
281 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
282 log(self
.serveur
,"priv",auteur
," ".join(message
))
284 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
288 if auteur
in self
.ops
and len(message
)>1:
289 if message
[1] in self
.chanlist
:
290 if not (message
[1] in self
.stay_channels
) or auteur
in self
.overops
:
291 self
.quitter(message
[1]," ".join(message
[2:]))
292 self
.chanlist
.remove(message
[1])
293 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
295 serv
.privmsg(auteur
,"Non, je reste !")
296 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
298 serv
.privmsg(auteur
,"Je ne suis pas sur %s"%(message
[1]))
302 if auteur
in self
.overops
:
304 if message
[1] in self
.stay_channels
:
305 serv
.privmsg(auteur
,"Je stay déjà sur %s."%(message
[1]))
306 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
308 self
.stay_channels
.append(message
[1])
309 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
310 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
312 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
316 if auteur
in self
.overops
:
318 if message
[1] in self
.stay_channels
:
319 self
.stay_channels
.remove(message
[1])
320 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
321 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
323 serv
.privmsg(auteur
,"Je ne stay pas sur %s."%(message
[1]))
324 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
328 if auteur
in self
.ops
:
330 if message
[1] in self
.play_channels
:
331 serv
.privmsg(auteur
,"Je play déjà sur %s."%(message
[1]))
332 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
334 self
.play_channels
.append(message
[1])
335 self
.play_status
[message
[1]]=[0,time
.time()-3600]
336 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
337 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
339 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
343 if auteur
in self
.ops
:
345 if message
[1] in self
.play_channels
:
346 self
.play_channels
.remove(message
[1])
347 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
348 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
350 serv
.privmsg(auteur
,"Je ne play 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
.quiet_channels
:
358 serv
.privmsg(auteur
,"Je me la ferme déjà sur %s"%(message
[1]))
359 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
361 self
.quiet_channels
.append(message
[1])
362 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
363 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
365 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
369 if auteur
in self
.ops
:
371 if message
[1] in self
.quiet_channels
:
372 self
.quiet_channels
.remove(message
[1])
373 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
374 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
376 serv
.privmsg(auteur
,"Je ne me la ferme pas sur %s."%(message
[1]))
377 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
381 if auteur
in self
.ops
:
383 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
386 elif cmd
in ["states","status"]:
387 if auteur
in self
.overops
:
388 for k
in self
.play_status
.keys():
389 serv
.privmsg(auteur
,(u
"%s : %s"%(k
," | ".join([unicode(i
) for i
in self
.play_status
[k
]]))).encode("utf8") )
391 if auteur
in self
.overops
and len(message
)>2:
392 serv
.privmsg(message
[1]," ".join(message
[2:]))
393 log(self
.serveur
,"priv",auteur
," ".join(message
))
394 elif len(message
)<=2:
395 serv
.privmsg(auteur
,"Syntaxe : SAY <channel> <message>")
399 if auteur
in self
.overops
:
400 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
404 if len(message
) in [3,4] and message
[1].lower()=="transfert":
405 scores
=self
.get_scores()
406 de
,to
=auteur
,message
[2]
407 value
=scores
.get(de
,0)
410 asked
=int(message
[3])
412 serv
.privmsg(auteur
,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
417 serv
.privmsg(auteur
,"Vous n'avez pas de points")
420 serv
.privmsg(auteur
,"Bien tenté…")
423 serv
.privmsg(auteur
,"Vous n'avez que %s points"%(value))
426 self
.add_score(de
,-asked
)
427 self
.add_score(to
,asked
)
428 serv
.privmsg(auteur
,"Transfert de %s points de %s à %s"%(asked
,de
,to
))
430 serv
.privmsg(auteur
,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
432 serv
.privmsg(auteur
,"Votre score : %s"%(self
.get_scores().get(auteur
,0)) )
435 scores
=self
.get_scores().items()
437 scores
.sort(lambda x
,y
:cmp(x
[1],y
[1]))
439 serv
.privmsg(auteur
,"Scores by score : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
441 scores
.sort(lambda x
,y
:cmp(x
[0].lower(),y
[0].lower()))
442 serv
.privmsg(auteur
,"Scores by pseudo : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
443 elif auteur
in self
.overops
:
444 souscmd
=message
[1].lower()
448 scores
=self
.get_scores()
449 if scores
.has_key(todelete
):
451 self
.save_scores(scores
)
452 serv
.privmsg(auteur
,"Score de %s supprimé"%(todelete))
454 serv
.privmsg(auteur
,"Ce score n'existe pas : %s"%(todelete))
456 serv
.privmsg(auteur
,"Syntaxe : SCORES DEL <pseudo>")
457 elif souscmd
in ["add","sub"]:
459 toadd
,val
=message
[2],message
[3]
463 serv
.privmsg(auteur
,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
467 self
.add_score(toadd
,val
)
468 serv
.privmsg(auteur
,"Done")
470 serv
.privmsg(auteur
,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
472 serv
.privmsg(auteur
,"Syntaxe : SCORES {DEL|ADD|SUB} <pseudo> [<n>]")
478 serv
.privmsg(auteur
,"Je n'ai pas compris. Essaye HELP…")
480 def on_pubmsg(self
, serv
, ev
):
481 if ignore_event(serv
, ev
):
483 auteur
= irclib
.nm_to_n(ev
.source())
485 message
= ev
.arguments()[0]
486 self
.update_activity(canal
,auteur
,message
)
488 test
=bot_unicode(message
)
489 except UnicodeBotError
:
490 if config
.utf8_trigger
and not canal
in self
.quiet_channels
:
491 serv
.privmsg(canal
, (u
"%s: %s"%(auteur
, random
.choice(config
.utf8_fail_answers
))).encode("utf8"))
494 pour_moi
,message
=self
.pourmoi(serv
,message
)
495 if pour_moi
and message
.split()!=[]:
496 cmd
=message
.split()[0].lower()
498 args
=" ".join(message
.split()[1:])
501 if cmd
in ["meurs","die","crève"]:
502 if auteur
in self
.overops
:
504 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
506 serv
.privmsg(canal
,"%s: crève !"%(auteur))
507 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
508 elif cmd
in ["meur", "meurt","meurre","meurres"] and not canal
in self
.quiet_channels
:
509 serv
.privmsg(canal
,'%s: Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)'%(auteur))
510 elif cmd
== "reload":
511 if auteur
in self
.ops
:
512 log(self
.serveur
, canal
, auteur
, message
+"[successful]")
514 elif cmd
in ["part","leave","dégage"]:
515 if auteur
in self
.ops
and (not (canal
in self
.stay_channels
)
516 or auteur
in self
.overops
):
518 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
519 self
.chanlist
.remove(canal
)
521 serv
.privmsg(canal
,"%s: Non, je reste !"%(auteur))
522 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
524 elif cmd
in ["deviens","pseudo"]:
525 if auteur
in self
.ops
:
528 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
529 elif cmd
in ["coucou"] and not canal
in self
.quiet_channels
:
530 serv
.privmsg(canal
,"%s: coucou"%(auteur))
531 elif cmd
in ["ping"] and not canal
in self
.quiet_channels
:
532 serv
.privmsg(canal
,"%s: pong"%(auteur))
533 elif cmd
in ["date","dates","histoire","énigme","enigme","encore"]:
534 if canal
in self
.play_channels
:
535 if self
.play_status
.get(canal
,[-1])[0]==0:
537 self
.start_enigme(serv
,canal
)
539 serv
.privmsg(canal
,"%s: Je peux souffler une minute ?"%(auteur))
541 serv
.privmsg(canal
,("%s: Rappel : %s"%(auteur
,self
.play_status
[canal
][2])).encode("utf8") )
543 serv
.privmsg(canal
,"%s: pas ici…"%(auteur))
544 elif cmd
in ["score","!score"]:
545 serv
.privmsg(auteur
,"Votre score : %s"%(self
.get_scores().get(auteur
,0)) )
546 elif cmd
in ["scores","!scores"]:
547 scores
=self
.get_scores().items()
549 scores
.sort(lambda x
,y
:cmp(x
[1],y
[1]))
551 serv
.privmsg(auteur
,"Scores by score : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
553 scores
.sort(lambda x
,y
:cmp(x
[0].lower(),y
[0].lower()))
554 serv
.privmsg(auteur
,"Scores by pseudo : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
555 elif cmd
== "indice" and canal
in self
.play_channels
:
556 self
.give_indice(serv
,canal
,None)
557 elif is_tag(message
) and not canal
in self
.quiet_channels
:
558 if auteur
in self
.ops
:
559 action
=random
.choice(config
.tag_actions
)
560 serv
.action(canal
,action
.encode("utf8"))
561 self
.quiet_channels
.append(canal
)
563 answer
=random
.choice(config
.tag_answers
)
564 for ligne
in answer
.split("\n"):
565 serv
.privmsg(canal
,"%s: %s"%(auteur
,ligne
.encode("utf8")))
571 if self
.play_status
.get(canal
,[-1])[0] in [1,2]:
572 answer
=self
.play_status
[canal
][1]
573 flag_century
=self
.play_status
[canal
][3]
575 score_obtenu
=reussi(message
.decode("utf8"),answer
,auteur
)
578 serv
.privmsg(canal
,"%s: C'est le bon siècle, mais pas la bonne année, cherche encore ;)"%(auteur))
579 self
.play_status
[canal
][3]=1
582 if flag_century
in [0,1]:
583 serv
.privmsg(canal
,"%s: C'est la bonne décennie, mais pas la bonne année, encore un effort ;)"%(auteur))
584 self
.play_status
[canal
][3]=2
587 if self
.play_status
[canal
][0]==1:
588 bonusmsg
=u
" [+bonus_mois"*(score_obtenu
>config
.score_annee
)+u
"+bonus_jour"*(score_obtenu
>config
.score_annee
+config
.score_mois
)
594 serv
.privmsg(canal
,(u
"%s: bravo ! (C'était le %s)%s"%(auteur
,answer
,bonusmsg
)).encode("utf8"))
595 log(self
.serveur
,canal
,auteur
+"$win",message
)
596 if auteur
in config
.noscore
:
598 self
.add_score(auteur
,score_obtenu
)
600 self
.play_status
[canal
]=[0,token
]
601 serv
.execute_delayed(random
.randrange(config
.Ttrig
*5,config
.Ttrig
*10),self
.start_enigme
,(serv
,canal
,token
))
603 def on_kick(self
,serv
,ev
):
604 auteur
= irclib
.nm_to_n(ev
.source())
605 channel
= ev
.target()
606 victime
= ev
.arguments()[0]
607 raison
= ev
.arguments()[1]
608 if victime
==self
.nick
:
609 log(self
.serveur
,"%s kické de %s par %s (raison : %s)" %(victime
,channel
,auteur
,raison
))
612 self
.update_activity(channel
,force
=True)
613 # on ne dit rien au rejoin
614 #l1,l2=config.kick_answers,config.kick_actions
615 #n1,n2=len(l1),len(l2)
616 #i=random.randrange(n1+n2)
618 # serv.action(channel,l2[i-n1].format(auteur).encode("utf8"))
620 # serv.privmsg(channel,l1[i].format(auteur).encode("utf8"))
622 def quitter(self
,chan
,leave_message
=None):
623 if leave_message
==None:
624 leave_message
=random
.choice(config
.leave_messages
)
626 leave_message
=leave_message
%(time
.strftime("le %d/%m/%Y à %T").decode("utf8"),self
.nick
)
629 self
.serv
.part(chan
,message
=leave_message
.encode("utf8"))
632 quit_message
=random
.choice(config
.quit_messages
)
634 quit_message
=quit_message
%(time
.strftime("le %d/%m/%Y à %T").decode("utf8"),self
.nick
)
637 self
.die(msg
=quit_message
.encode("utf8"))
639 def get_scores(self
):
640 f
=open(config
.score_file
)
641 scores
=pickle
.load(f
)
645 def add_score(self
,pseudo
,value
):
646 scores
=self
.get_scores()
647 if scores
.has_key(pseudo
):
648 scores
[pseudo
]+=value
651 self
.save_scores(scores
)
653 def save_scores(self
,scores
):
654 f
=open(config
.score_file
,"w")
655 pickle
.dump(scores
,f
)
659 return self
.serv
.get_nickname()
660 nick
= property(_getnick
)
662 def update_activity(self
,canal
="",pseudo
="",message
="",force
=False):
663 if force
or (not pseudo
in config
.idle_bots
and all([not re
.match(ignore
, message
) for ignore
in config
.idle_messages
])):
664 self
.last_activity
[canal
]=time
.time()
665 def is_active(self
,canal
):
666 return time
.time()-self
.last_activity
[canal
]<config
.idle_time
668 def reload(self
, auteur
=None):
670 if auteur
in [None, "SIGHUP"]:
671 towrite
= "Config reloaded" + " (SIGHUP received)"*(auteur
== "SIGHUP")
672 for to
in config
.report_bugs_to
:
673 self
.serv
.privmsg(to
, towrite
)
674 log(self
.serveur
, towrite
)
676 self
.serv
.privmsg(auteur
,"Config reloaded")
678 def start_as_daemon(self
, outfile
):
679 sys
.stderr
= Logger(outfile
)
683 class Logger(object):
684 """Pour écrire ailleurs que sur stdout"""
685 def __init__(self
, filename
="historien.full.log"):
686 self
.filename
= filename
688 def write(self
, message
):
689 f
= open(self
.filename
, "a")
694 if __name__
=="__main__":
697 print "Usage : historien.py <serveur> [--debug] [--no-output] [--daemon [--pidfile]] [--outfile]"
698 print " --outfile sans --no-output ni --daemon n'a aucun effet"
701 if "--daemon" in sys
.argv
:
702 thisfile
= os
.path
.realpath(__file__
)
703 thisdirectory
= thisfile
.rsplit("/", 1)[0]
704 os
.chdir(thisdirectory
)
708 if "debug" in sys
.argv
or "--debug" in sys
.argv
:
712 if "--no-output" in sys
.argv
or "--daemon" in sys
.argv
:
713 outfile
= "/var/log/bots/historien.full.log"
716 if arg
[0].strip('-') in ["out", "outfile", "logfile"]:
718 sys
.stdout
= Logger(outfile
)
719 serveurs
={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
720 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"}
722 serveur
=serveurs
[serveur
]
724 print "Server Unknown : %s"%(serveur)
726 historien
=Historien(serveur
,debug
)
727 # Si on reçoit un SIGHUP, on reload la config
728 def sighup_handler(signum
, frame
):
729 historien
.reload("SIGHUP")
730 signal
.signal(signal
.SIGHUP
, sighup_handler
)
732 child_pid
= os
.fork()
735 historien
.start_as_daemon(outfile
)
737 # on enregistre le pid de historien
738 pidfile
= "/var/run/bots/historien.pid"
741 if arg
[0].strip('-') in ["pidfile"]:
743 f
= open(pidfile
, "w")
744 f
.write("%s\n" % child_pid
)