]>
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 for c
in self
.play_channels
:
147 token
=time
.time()-3600
148 self
.play_status
[c
]=[0,token
]
149 serv
.execute_delayed(random
.randrange(config
.ttrig
),self
.start_enigme
,(serv
,c
,token
))
151 def start_enigme(self
,serv
,channel
,token
=None):
152 # On reste silencieux si lechan n'est pas actif
153 if not self
.is_active(channel
):
154 serv
.execute_delayed(config
.ttrig
*5,self
.start_enigme
,(serv
,channel
,token
))
156 if self
.play_status
[channel
][0]==0 and channel
in self
.play_channels
:
158 if token
==self
.play_status
[channel
][-1]:
161 if time
.time() > self
.play_status
[channel
][-1]+config
.time_incompressible
:
166 date
,evenement
=self
.get_enigme()
167 log(self
.serveur
,channel
,u
"$Date$".encode("utf8"),("%s : %s"%(date
, evenement
)).encode("utf8"))
168 serv
.privmsg(channel
,evenement
.encode("utf8"))
170 # le 0 est le flag "bon siècle" n'a pas encore été dit
171 self
.play_status
[channel
]=[1,date
,evenement
,0,token
]
172 serv
.execute_delayed(random
.randrange(config
.ttrig
*3,config
.ttrig
*5),self
.give_indice
,(serv
,channel
,token
))
175 def give_indice(self
,serv
,channel
,token
):
176 if self
.play_status
[channel
][0]==1:
178 # c'est donc que l'indice a été demandé
179 if self
.play_status
[channel
][-1]+config
.time_incompressible_clue
<time
.time():
180 token
=self
.play_status
[channel
][-1]
181 if self
.play_status
[channel
][-1]==token
:
182 date
=self
.play_status
[channel
][1]
184 serv
.privmsg(channel
,"indice : %s"%(indice).encode("utf8"))
185 self
.play_status
[channel
][0]=2
186 serv
.execute_delayed(random
.randrange(config
.ttrig
*1,config
.ttrig
*3),self
.give_answer
,(serv
,channel
,token
))
187 def give_answer(self
,serv
,channel
,token
):
188 if self
.play_status
[channel
][0]==2 and self
.play_status
[channel
][-1]==token
:
189 date
=self
.play_status
[channel
][1]
190 serv
.privmsg(channel
,"C'était le %s"%(date).encode("utf8"))
192 self
.play_status
[channel
]=[0,token
]
193 serv
.execute_delayed(random
.randrange(config
.Ttrig
*5,config
.Ttrig
*10),self
.start_enigme
,(serv
,channel
,token
))
195 def get_enigme(self
):
196 # on récupère les dates
197 f
=open(config
.source_file
)
200 l
=[i
.split(" : ",2) for i
in l
]
201 dates
={int(i
[0]):i
[1:] for i
in l
}
202 # on va chercher combien de fois elles ont été jouées
203 played_file
=get_config_played_file(self
.serveur
)
207 l
=re
.findall("(.*):(.*)",t
)
208 played
={int(i
[0]):int(i
[1]) for i
in l
}
209 # on récupère le nombre d'occurrences le plus faible
210 mini
=min(played
.values())
211 # on choisit un id dans ceux qui ont ce nombre d'occurences
212 id_choisi
=random
.choice([k
for k
,v
in played
.items() if v
==mini
])
213 date
,evenement
=dates
[id_choisi
]
214 evenement
=evenement
.replace("\n","")
215 # on incrémente la choisie
217 # on enregistre le played_file
218 f
=open(played_file
,"w")
219 f
.write("\n".join(["%-4s : %s"%(k
,v
) for k
,v
in played
.items()]))
221 return map(lambda x
:x
.decode("utf8"), [date
,evenement
])
223 def pourmoi(self
, serv
, message
):
226 if message
[:size
]==pseudo
and len(message
)>size
and message
[size
]==":":
227 return (True,message
[size
+1:].strip(" "))
229 return (False,message
)
231 def on_privmsg(self
, serv
, ev
):
232 if ignore_event(serv
, ev
):
234 message
=ev
.arguments()[0]
235 auteur
= irclib
.nm_to_n(ev
.source())
237 test
=bot_unicode(message
)
238 except UnicodeBotError
:
239 if config
.utf8_trigger
:
240 serv
.privmsg(auteur
, random
.choice(config
.utf8_fail_answers
).encode("utf8"))
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
257 RELOAD Me fait recharger la conf"""
259 SCORES {DEL|ADD|SUB} Tu veux un dessin ?
260 SAY Fais envoyer un message sur un chan ou à une personne
261 STAY Ignorera les prochains LEAVE pour un chan
262 NOSTAY Opposé de STAY
263 STATUS Montre l'état courant
265 helpmsg
=helpmsg_default
266 if auteur
in self
.ops
:
268 if auteur
in self
.overops
:
269 helpmsg
+=helpmsg_overops
270 for ligne
in helpmsg
.split("\n"):
271 serv
.privmsg(auteur
,ligne
)
273 if auteur
in self
.ops
:
275 if message
[1] in self
.chanlist
:
276 serv
.privmsg(auteur
,"Je suis déjà sur %s"%(message
[1]))
278 serv
.join(message
[1])
279 self
.chanlist
.append(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]")
380 if auteur
in self
.ops
:
382 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
385 elif cmd
in ["states","status"]:
386 if auteur
in self
.overops
:
387 for k
in self
.play_status
.keys():
388 serv
.privmsg(auteur
,(u
"%s : %s"%(k
," | ".join([unicode(i
) for i
in self
.play_status
[k
]]))).encode("utf8") )
390 if auteur
in self
.overops
and len(message
)>2:
391 serv
.privmsg(message
[1]," ".join(message
[2:]))
392 log(self
.serveur
,"priv",auteur
," ".join(message
))
393 elif len(message
)<=2:
394 serv
.privmsg(auteur
,"Syntaxe : SAY <channel> <message>")
398 if auteur
in self
.overops
:
399 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
403 if len(message
) in [3,4] and message
[1].lower()=="transfert":
404 scores
=self
.get_scores()
405 de
,to
=auteur
,message
[2]
406 value
=scores
.get(de
,0)
409 asked
=int(message
[3])
411 serv
.privmsg(auteur
,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
416 serv
.privmsg(auteur
,"Vous n'avez pas de points")
419 serv
.privmsg(auteur
,"Bien tenté…")
422 serv
.privmsg(auteur
,"Vous n'avez que %s points"%(value))
425 self
.add_score(de
,-asked
)
426 self
.add_score(to
,asked
)
427 serv
.privmsg(auteur
,"Transfert de %s points de %s à %s"%(asked
,de
,to
))
429 serv
.privmsg(auteur
,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
431 serv
.privmsg(auteur
,"Votre score : %s"%(self
.get_scores().get(auteur
,0)) )
434 scores
=self
.get_scores().items()
436 scores
.sort(lambda x
,y
:cmp(x
[1],y
[1]))
438 serv
.privmsg(auteur
,"Scores by score : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
440 scores
.sort(lambda x
,y
:cmp(x
[0].lower(),y
[0].lower()))
441 serv
.privmsg(auteur
,"Scores by pseudo : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
442 elif auteur
in self
.overops
:
443 souscmd
=message
[1].lower()
447 scores
=self
.get_scores()
448 if scores
.has_key(todelete
):
450 self
.save_scores(scores
)
451 serv
.privmsg(auteur
,"Score de %s supprimé"%(todelete))
453 serv
.privmsg(auteur
,"Ce score n'existe pas : %s"%(todelete))
455 serv
.privmsg(auteur
,"Syntaxe : SCORES DEL <pseudo>")
456 elif souscmd
in ["add","sub"]:
458 toadd
,val
=message
[2],message
[3]
462 serv
.privmsg(auteur
,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
466 self
.add_score(toadd
,val
)
467 serv
.privmsg(auteur
,"Done")
469 serv
.privmsg(auteur
,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
471 serv
.privmsg(auteur
,"Syntaxe : SCORES {DEL|ADD|SUB} <pseudo> [<n>]")
477 serv
.privmsg(auteur
,"Je n'ai pas compris. Essaye HELP…")
479 def on_pubmsg(self
, serv
, ev
):
480 if ignore_event(serv
, ev
):
482 auteur
= irclib
.nm_to_n(ev
.source())
484 message
= ev
.arguments()[0]
485 self
.update_activity(canal
,auteur
,message
)
487 test
=bot_unicode(message
)
488 except UnicodeBotError
:
489 if config
.utf8_trigger
and not canal
in self
.quiet_channels
:
490 serv
.privmsg(canal
, (u
"%s: %s"%(auteur
, random
.choice(config
.utf8_fail_answers
))).encode("utf8"))
493 pour_moi
,message
=self
.pourmoi(serv
,message
)
494 if pour_moi
and message
.split()!=[]:
495 cmd
=message
.split()[0].lower()
497 args
=" ".join(message
.split()[1:])
500 if cmd
in ["meurs","die","crève"]:
501 if auteur
in self
.overops
:
503 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
505 serv
.privmsg(canal
,"%s: crève !"%(auteur))
506 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
507 elif cmd
in ["meur", "meurt","meurre","meurres"] and not canal
in self
.quiet_channels
:
508 serv
.privmsg(canal
,'%s: Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)'%(auteur))
509 elif cmd
== "reload":
510 if auteur
in self
.ops
:
511 log(self
.serveur
, canal
, auteur
, message
+"[successful]")
513 elif cmd
in ["part","leave","dégage"]:
514 if auteur
in self
.ops
and (not (canal
in self
.stay_channels
)
515 or auteur
in self
.overops
):
517 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
518 self
.chanlist
.remove(canal
)
520 serv
.privmsg(canal
,"%s: Non, je reste !"%(auteur))
521 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
523 elif cmd
in ["deviens","pseudo"]:
524 if auteur
in self
.ops
:
527 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
528 elif cmd
in ["coucou"] and not canal
in self
.quiet_channels
:
529 serv
.privmsg(canal
,"%s: coucou"%(auteur))
530 elif cmd
in ["ping"] and not canal
in self
.quiet_channels
:
531 serv
.privmsg(canal
,"%s: pong"%(auteur))
532 elif cmd
in ["date","dates","histoire","énigme","enigme","encore"]:
533 if canal
in self
.play_channels
:
534 if self
.play_status
.get(canal
,[-1])[0]==0:
536 self
.start_enigme(serv
,canal
)
538 serv
.privmsg(canal
,"%s: Je peux souffler une minute ?"%(auteur))
540 serv
.privmsg(canal
,("%s: Rappel : %s"%(auteur
,self
.play_status
[canal
][2])).encode("utf8") )
542 serv
.privmsg(canal
,"%s: pas ici…"%(auteur))
543 elif cmd
in ["score","!score"]:
544 serv
.privmsg(auteur
,"Votre score : %s"%(self
.get_scores().get(auteur
,0)) )
545 elif cmd
in ["scores","!scores"]:
546 scores
=self
.get_scores().items()
548 scores
.sort(lambda x
,y
:cmp(x
[1],y
[1]))
550 serv
.privmsg(auteur
,"Scores by score : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
552 scores
.sort(lambda x
,y
:cmp(x
[0].lower(),y
[0].lower()))
553 serv
.privmsg(auteur
,"Scores by pseudo : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
554 elif cmd
== "indice" and canal
in self
.play_channels
:
555 self
.give_indice(serv
,canal
,None)
556 elif is_tag(message
) and not canal
in self
.quiet_channels
:
557 if auteur
in self
.ops
:
558 action
=random
.choice(config
.tag_actions
)
559 serv
.action(canal
,action
.encode("utf8"))
560 self
.quiet_channels
.append(canal
)
562 answer
=random
.choice(config
.tag_answers
)
563 for ligne
in answer
.split("\n"):
564 serv
.privmsg(canal
,"%s: %s"%(auteur
,ligne
.encode("utf8")))
570 if self
.play_status
.get(canal
,[-1])[0] in [1,2]:
571 answer
=self
.play_status
[canal
][1]
572 flag_century
=self
.play_status
[canal
][3]
574 score_obtenu
=reussi(message
.decode("utf8"),answer
,auteur
)
577 serv
.privmsg(canal
,"%s: C'est le bon siècle, mais pas la bonne année, cherche encore ;)"%(auteur))
578 self
.play_status
[canal
][3]=1
581 if flag_century
in [0,1]:
582 serv
.privmsg(canal
,"%s: C'est la bonne décennie, mais pas la bonne année, encore un effort ;)"%(auteur))
583 self
.play_status
[canal
][3]=2
586 if self
.play_status
[canal
][0]==1:
587 bonusmsg
=u
" [+bonus_mois"*(score_obtenu
>config
.score_annee
)+u
"+bonus_jour"*(score_obtenu
>config
.score_annee
+config
.score_mois
)
593 serv
.privmsg(canal
,(u
"%s: bravo ! (C'était le %s)%s"%(auteur
,answer
,bonusmsg
)).encode("utf8"))
594 log(self
.serveur
,canal
,auteur
+"$win",message
)
595 if auteur
in config
.noscore
:
597 self
.add_score(auteur
,score_obtenu
)
599 self
.play_status
[canal
]=[0,token
]
600 serv
.execute_delayed(random
.randrange(config
.Ttrig
*5,config
.Ttrig
*10),self
.start_enigme
,(serv
,canal
,token
))
602 def on_kick(self
,serv
,ev
):
603 auteur
= irclib
.nm_to_n(ev
.source())
604 channel
= ev
.target()
605 victime
= ev
.arguments()[0]
606 raison
= ev
.arguments()[1]
607 if victime
==self
.nick
:
608 log(self
.serveur
,"%s kické de %s par %s (raison : %s)" %(victime
,channel
,auteur
,raison
))
611 self
.update_activity(channel
,force
=True)
612 # on ne dit rien au rejoin
613 #l1,l2=config.kick_answers,config.kick_actions
614 #n1,n2=len(l1),len(l2)
615 #i=random.randrange(n1+n2)
617 # serv.action(channel,l2[i-n1].format(auteur).encode("utf8"))
619 # serv.privmsg(channel,l1[i].format(auteur).encode("utf8"))
621 def quitter(self
,chan
,leave_message
=None):
622 if leave_message
==None:
623 leave_message
=random
.choice(config
.leave_messages
)
625 leave_message
=leave_message
%(time
.strftime("le %d/%m/%Y à %T").decode("utf8"),self
.nick
)
628 self
.serv
.part(chan
,message
=leave_message
.encode("utf8"))
631 quit_message
=random
.choice(config
.quit_messages
)
633 quit_message
=quit_message
%(time
.strftime("le %d/%m/%Y à %T").decode("utf8"),self
.nick
)
636 self
.die(msg
=quit_message
.encode("utf8"))
638 def get_scores(self
):
639 f
=open(config
.score_file
)
640 scores
=pickle
.load(f
)
644 def add_score(self
,pseudo
,value
):
645 scores
=self
.get_scores()
646 if scores
.has_key(pseudo
):
647 scores
[pseudo
]+=value
650 self
.save_scores(scores
)
652 def save_scores(self
,scores
):
653 f
=open(config
.score_file
,"w")
654 pickle
.dump(scores
,f
)
658 return self
.serv
.get_nickname()
659 nick
= property(_getnick
)
661 def update_activity(self
,canal
="",pseudo
="",message
="",force
=False):
662 if force
or (not pseudo
in config
.idle_bots
and all([not re
.match(ignore
, message
) for ignore
in config
.idle_messages
])):
663 self
.last_activity
[canal
]=time
.time()
664 def is_active(self
,canal
):
665 # Si on n'a pas d'info sur le chan, il est inactif
666 return time
.time()-self
.last_activity
.get(canal
, config
.idle_time
)<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
)