]>
gitweb.pimeys.fr Git - bots/historien.git/blob - historien.py
a550556a96bfd9bd52dd3ae14a2a7aba70bd5a87
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
:
55 class GoodCentury(Exception):
58 class GoodDeceny(Exception):
61 def reussi(message
,answer
,auteur
):
62 if auteur
in config
.level3
:
63 return answer
in message
64 if auteur
in config
.level2
:
65 return answer
in message
68 date
=cast_as_date(message
.lower().strip())
69 except ThisIsNotADate
:
71 realdate
=map(lambda x
:int(x
), answer
.split('/'))
74 if date
[0]==realdate
[0]:
75 score
=config
.score_annee
76 if date
[1]==realdate
[1]:
77 score
+=config
.score_mois
78 if date
[2]==realdate
[2]:
79 score
+=config
.score_jour
80 elif date
[0]/10 == realdate
[0]/10:
82 elif date
[0]/100 == realdate
[0]/100:
86 def is_something(chain
,matches
,avant
=u
".*(?:^| )",apres
=u
"(?:$|\.| |,|;).*",case_sensitive
=False,debug
=False):
88 chain
=unicode(chain
,"utf8")
90 chain
=unicode(chain
,"utf8").lower()
91 allmatches
="("+"|".join(matches
)+")"
92 reg
=(avant
+allmatches
+apres
).lower()
97 return is_something(chain
,config
.tag_triggers
)
99 class RefuseError(Exception):
102 class Historien(ircbot
.SingleServerIRCBot
):
103 def __init__(self
,serveur
,debug
=False):
104 temporary_pseudo
=config
.pseudo
+str(random
.randrange(10000,100000))
105 ircbot
.SingleServerIRCBot
.__init
__(self
, [(serveur
, 6667)],
106 temporary_pseudo
,"Un bot irc qui a au moins l'agreg d'histoire", 10)
109 self
.overops
=config
.overops
110 self
.ops
=self
.overops
+config
.ops
111 self
.chanlist
=config
.chanlist
112 self
.stay_channels
=config
.stay_channels
113 self
.play_channels
=config
.play_channels
114 self
.play_status
={i
:[0] for i
in self
.play_channels
}
115 self
.last_activity
={}
116 self
.quiet_channels
=[]
118 def give_me_my_pseudo(self
,serv
):
119 serv
.privmsg("NickServ","RECOVER %s %s"%(config
.pseudo
,config
.password
))
120 serv
.privmsg("NickServ","RELEASE %s %s"%(config
.pseudo
,config
.password
))
122 serv
.nick(config
.pseudo
)
124 def on_welcome(self
, serv
, ev
):
125 self
.serv
=serv
# ça serv ira :)
126 self
.give_me_my_pseudo(serv
)
127 serv
.privmsg("NickServ","identify %s"%(config
.password
))
128 log(self
.serveur
,"Connected")
130 self
.chanlist
=["#bot"]
131 self
.play_channels
=["#bot"]
132 for c
in self
.chanlist
:
133 log(self
.serveur
,"JOIN %s"%(c))
135 self
.update_activity(c
,force
=True)
136 for c
in self
.play_channels
:
137 token
=time
.time()-3600
138 self
.play_status
[c
]=[0,token
]
139 serv
.execute_delayed(random
.randrange(config
.ttrig
),self
.start_enigme
,(serv
,c
,token
))
141 def start_enigme(self
,serv
,channel
,token
=None):
142 # On reste silencieux si lechan n'est pas actif
143 if not self
.is_active(channel
):
144 serv
.execute_delayed(config
.ttrig
*5,self
.start_enigme
,(serv
,channel
,token
))
146 if self
.play_status
[channel
][0]==0 and channel
in self
.play_channels
:
148 if token
==self
.play_status
[channel
][-1]:
151 if time
.time() > self
.play_status
[channel
][-1]+config
.time_incompressible
:
156 date
,evenement
=self
.get_enigme()
157 log(self
.serveur
,channel
,u
"$Date$".encode("utf8"),("%s : %s"%(date
, evenement
)).encode("utf8"))
158 serv
.privmsg(channel
,evenement
.encode("utf8"))
160 # le 0 est le flag "bon siècle" n'a pas encore été dit
161 self
.play_status
[channel
]=[1,date
,evenement
,0,token
]
162 serv
.execute_delayed(random
.randrange(config
.ttrig
*3,config
.ttrig
*5),self
.give_indice
,(serv
,channel
,token
))
165 def give_indice(self
,serv
,channel
,token
):
166 if self
.play_status
[channel
][0]==1:
168 # c'est donc que l'indice a été demandé
169 if self
.play_status
[channel
][-1]+config
.time_incompressible_clue
<time
.time():
170 token
=self
.play_status
[channel
][-1]
171 if self
.play_status
[channel
][-1]==token
:
172 date
=self
.play_status
[channel
][1]
174 serv
.privmsg(channel
,"indice : %s"%(indice).encode("utf8"))
175 self
.play_status
[channel
][0]=2
176 serv
.execute_delayed(random
.randrange(config
.ttrig
*1,config
.ttrig
*3),self
.give_answer
,(serv
,channel
,token
))
177 def give_answer(self
,serv
,channel
,token
):
178 if self
.play_status
[channel
][0]==2 and self
.play_status
[channel
][-1]==token
:
179 date
=self
.play_status
[channel
][1]
180 serv
.privmsg(channel
,"C'était le %s"%(date).encode("utf8"))
182 self
.play_status
[channel
]=[0,token
]
183 serv
.execute_delayed(random
.randrange(config
.Ttrig
*5,config
.Ttrig
*10),self
.start_enigme
,(serv
,channel
,token
))
185 def get_enigme(self
):
186 # on récupère les dates
187 f
=open(config
.source_file
)
190 l
=[i
.split(" : ",2) for i
in l
]
191 dates
={int(i
[0]):i
[1:] for i
in l
}
192 # on va chercher combien de fois elles ont été jouées
193 played_file
=get_config_played_file(self
.serveur
)
197 l
=re
.findall("(.*):(.*)",t
)
198 played
={int(i
[0]):int(i
[1]) for i
in l
}
199 # on récupère le nombre d'occurrences le plus faible
200 mini
=min(played
.values())
201 # on choisit un id dans ceux qui ont ce nombre d'occurences
202 id_choisi
=random
.choice([k
for k
,v
in played
.items() if v
==mini
])
203 date
,evenement
=dates
[id_choisi
]
204 evenement
=evenement
.replace("\n","")
205 # on incrémente la choisie
207 # on enregistre le played_file
208 f
=open(played_file
,"w")
209 f
.write("\n".join(["%-4s : %s"%(k
,v
) for k
,v
in played
.items()]))
211 return map(lambda x
:x
.decode("utf8"), [date
,evenement
])
213 def pourmoi(self
, serv
, message
):
216 if message
[:size
]==pseudo
and len(message
)>size
and message
[size
]==":":
217 return (True,message
[size
+1:].strip(" "))
219 return (False,message
)
221 def on_privmsg(self
, serv
, ev
):
222 message
=ev
.arguments()[0]
223 auteur
= irclib
.nm_to_n(ev
.source())
225 test
=bot_unicode(message
)
226 except UnicodeBotError
:
227 if config
.utf8_trigger
:
228 serv
.privmsg(auteur
, random
.choice(config
.utf8_fail_answers
).encode("utf8"))
230 message
=message
.split()
231 cmd
=message
[0].lower()
234 helpmsg_default
="""Liste des commandes :
235 HELP Affiche ce message d'aide
236 SCORE Affiche ton score (SCORE TRANSFERT <pseudo> [<n>] pour transférer des points)
237 SCORES Affiche les scores"""
239 JOIN Faire rejoindre un channel (sans paramètres, donne la liste des chans actuels)
240 LEAVE Faire quitter un channel
241 PLAY Passe un channel en mode "jouer"
242 NOPLAY Passe un channel en mode "ne pas jouer"
243 QUIET Se taire sur un channel
244 NOQUIET Opposé de QUIET
245 RELOAD Me fait recharger la conf"""
247 SCORES {DEL|ADD|SUB} Tu veux un dessin ?
248 SAY Fais envoyer un message sur un chan ou à une personne
249 STAY Ignorera les prochains LEAVE pour un chan
250 NOSTAY Opposé de STAY
251 STATUS Montre l'état courant
253 helpmsg
=helpmsg_default
254 if auteur
in self
.ops
:
256 if auteur
in self
.overops
:
257 helpmsg
+=helpmsg_overops
258 for ligne
in helpmsg
.split("\n"):
259 serv
.privmsg(auteur
,ligne
)
261 if auteur
in self
.ops
:
263 if message
[1] in self
.chanlist
:
264 serv
.privmsg(auteur
,"Je suis déjà sur %s"%(message
[1]))
266 serv
.join(message
[1])
267 self
.chanlist
.append(message
[1])
268 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
269 log(self
.serveur
,"priv",auteur
," ".join(message
))
271 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
275 if auteur
in self
.ops
and len(message
)>1:
276 if message
[1] in self
.chanlist
:
277 if not (message
[1] in self
.stay_channels
) or auteur
in self
.overops
:
278 self
.quitter(message
[1]," ".join(message
[2:]))
279 self
.chanlist
.remove(message
[1])
280 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
282 serv
.privmsg(auteur
,"Non, je reste !")
283 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
285 serv
.privmsg(auteur
,"Je ne suis pas sur %s"%(message
[1]))
289 if auteur
in self
.overops
:
291 if message
[1] in self
.stay_channels
:
292 serv
.privmsg(auteur
,"Je stay déjà sur %s."%(message
[1]))
293 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
295 self
.stay_channels
.append(message
[1])
296 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
297 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
299 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
303 if auteur
in self
.overops
:
305 if message
[1] in self
.stay_channels
:
306 self
.stay_channels
.remove(message
[1])
307 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
308 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
310 serv
.privmsg(auteur
,"Je ne stay pas sur %s."%(message
[1]))
311 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
315 if auteur
in self
.ops
:
317 if message
[1] in self
.play_channels
:
318 serv
.privmsg(auteur
,"Je play déjà sur %s."%(message
[1]))
319 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
321 self
.play_channels
.append(message
[1])
322 self
.play_status
[message
[1]]=[0,time
.time()-3600]
323 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
324 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
326 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
330 if auteur
in self
.ops
:
332 if message
[1] in self
.play_channels
:
333 self
.play_channels
.remove(message
[1])
334 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
335 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
337 serv
.privmsg(auteur
,"Je ne play pas sur %s."%(message
[1]))
338 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
342 if auteur
in self
.ops
:
344 if message
[1] in self
.quiet_channels
:
345 serv
.privmsg(auteur
,"Je me la ferme déjà sur %s"%(message
[1]))
346 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
348 self
.quiet_channels
.append(message
[1])
349 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
350 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
352 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
356 if auteur
in self
.ops
:
358 if message
[1] in self
.quiet_channels
:
359 self
.quiet_channels
.remove(message
[1])
360 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
361 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
363 serv
.privmsg(auteur
,"Je ne me la ferme pas sur %s."%(message
[1]))
364 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
368 if auteur
in self
.ops
:
370 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
373 elif cmd
in ["states","status"]:
374 if auteur
in self
.overops
:
375 for k
in self
.play_status
.keys():
376 serv
.privmsg(auteur
,(u
"%s : %s"%(k
," | ".join([unicode(i
) for i
in self
.play_status
[k
]]))).encode("utf8") )
378 if auteur
in self
.overops
and len(message
)>2:
379 serv
.privmsg(message
[1]," ".join(message
[2:]))
380 log(self
.serveur
,"priv",auteur
," ".join(message
))
381 elif len(message
)<=2:
382 serv
.privmsg(auteur
,"Syntaxe : SAY <channel> <message>")
386 if auteur
in self
.overops
:
387 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
391 if len(message
) in [3,4] and message
[1].lower()=="transfert":
392 scores
=self
.get_scores()
393 de
,to
=auteur
,message
[2]
394 value
=scores
.get(de
,0)
397 asked
=int(message
[3])
399 serv
.privmsg(auteur
,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
404 serv
.privmsg(auteur
,"Vous n'avez pas de points")
407 serv
.privmsg(auteur
,"Bien tenté…")
410 serv
.privmsg(auteur
,"Vous n'avez que %s points"%(value))
413 self
.add_score(de
,-asked
)
414 self
.add_score(to
,asked
)
415 serv
.privmsg(auteur
,"Transfert de %s points de %s à %s"%(asked
,de
,to
))
417 serv
.privmsg(auteur
,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
419 serv
.privmsg(auteur
,"Votre score : %s"%(self
.get_scores().get(auteur
,0)) )
422 scores
=self
.get_scores().items()
424 scores
.sort(lambda x
,y
:cmp(x
[1],y
[1]))
426 serv
.privmsg(auteur
,"Scores by score : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
428 scores
.sort(lambda x
,y
:cmp(x
[0].lower(),y
[0].lower()))
429 serv
.privmsg(auteur
,"Scores by pseudo : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
430 elif auteur
in self
.overops
:
431 souscmd
=message
[1].lower()
435 scores
=self
.get_scores()
436 if scores
.has_key(todelete
):
438 self
.save_scores(scores
)
439 serv
.privmsg(auteur
,"Score de %s supprimé"%(todelete))
441 serv
.privmsg(auteur
,"Ce score n'existe pas : %s"%(todelete))
443 serv
.privmsg(auteur
,"Syntaxe : SCORES DEL <pseudo>")
444 elif souscmd
in ["add","sub"]:
446 toadd
,val
=message
[2],message
[3]
450 serv
.privmsg(auteur
,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
454 self
.add_score(toadd
,val
)
455 serv
.privmsg(auteur
,"Done")
457 serv
.privmsg(auteur
,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
459 serv
.privmsg(auteur
,"Syntaxe : SCORES {DEL|ADD|SUB} <pseudo> [<n>]")
465 serv
.privmsg(auteur
,"Je n'ai pas compris. Essaye HELP…")
467 def on_pubmsg(self
, serv
, ev
):
468 auteur
= irclib
.nm_to_n(ev
.source())
470 message
= ev
.arguments()[0]
471 self
.update_activity(canal
,auteur
,message
)
473 test
=bot_unicode(message
)
474 except UnicodeBotError
:
475 if config
.utf8_trigger
and not canal
in self
.quiet_channels
:
476 serv
.privmsg(canal
, (u
"%s: %s"%(auteur
, random
.choice(config
.utf8_fail_answers
))).encode("utf8"))
479 pour_moi
,message
=self
.pourmoi(serv
,message
)
480 if pour_moi
and message
.split()!=[]:
481 cmd
=message
.split()[0].lower()
483 args
=" ".join(message
.split()[1:])
486 if cmd
in ["meurs","die","crève"]:
487 if auteur
in self
.overops
:
489 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
491 serv
.privmsg(canal
,"%s: crève !"%(auteur))
492 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
493 elif cmd
in ["meur", "meurt","meurre","meurres"] and not canal
in self
.quiet_channels
:
494 serv
.privmsg(canal
,'%s: Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)'%(auteur))
495 elif cmd
== "reload":
496 if auteur
in self
.ops
:
497 log(self
.serveur
, canal
, auteur
, message
+"[successful]")
499 elif cmd
in ["part","leave","dégage"]:
500 if auteur
in self
.ops
and (not (canal
in self
.stay_channels
)
501 or auteur
in self
.overops
):
503 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
504 self
.chanlist
.remove(canal
)
506 serv
.privmsg(canal
,"%s: Non, je reste !"%(auteur))
507 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
509 elif cmd
in ["deviens","pseudo"]:
510 if auteur
in self
.ops
:
513 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
514 elif cmd
in ["coucou"] and not canal
in self
.quiet_channels
:
515 serv
.privmsg(canal
,"%s: coucou"%(auteur))
516 elif cmd
in ["ping"] and not canal
in self
.quiet_channels
:
517 serv
.privmsg(canal
,"%s: pong"%(auteur))
518 elif cmd
in ["date","dates","histoire","énigme","enigme","encore"]:
519 if canal
in self
.play_channels
:
520 if self
.play_status
.get(canal
,[-1])[0]==0:
522 self
.start_enigme(serv
,canal
)
524 serv
.privmsg(canal
,"%s: Je peux souffler une minute ?"%(auteur))
526 serv
.privmsg(canal
,("%s: Rappel : %s"%(auteur
,self
.play_status
[canal
][2])).encode("utf8") )
528 serv
.privmsg(canal
,"%s: pas ici…"%(auteur))
529 elif cmd
in ["score","!score"]:
530 serv
.privmsg(auteur
,"Votre score : %s"%(self
.get_scores().get(auteur
,0)) )
531 elif cmd
in ["scores","!scores"]:
532 scores
=self
.get_scores().items()
534 scores
.sort(lambda x
,y
:cmp(x
[1],y
[1]))
536 serv
.privmsg(auteur
,"Scores by score : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
538 scores
.sort(lambda x
,y
:cmp(x
[0].lower(),y
[0].lower()))
539 serv
.privmsg(auteur
,"Scores by pseudo : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
540 elif cmd
== "indice" and canal
in self
.play_channels
:
541 self
.give_indice(serv
,canal
,None)
542 elif is_tag(message
) and not canal
in self
.quiet_channels
:
543 if auteur
in self
.ops
:
544 action
=random
.choice(config
.tag_actions
)
545 serv
.action(canal
,action
.encode("utf8"))
546 self
.quiet_channels
.append(canal
)
548 answer
=random
.choice(config
.tag_answers
)
549 for ligne
in answer
.split("\n"):
550 serv
.privmsg(canal
,"%s: %s"%(auteur
,ligne
.encode("utf8")))
556 if self
.play_status
.get(canal
,[-1])[0] in [1,2]:
557 answer
=self
.play_status
[canal
][1]
558 flag_century
=self
.play_status
[canal
][3]
560 score_obtenu
=reussi(message
.decode("utf8"),answer
,auteur
)
563 serv
.privmsg(canal
,"%s: C'est le bon siècle, mais pas la bonne année, cherche encore ;)"%(auteur))
564 self
.play_status
[canal
][3]=1
567 if flag_century
in [0,1]:
568 serv
.privmsg(canal
,"%s: C'est la bonne décennie, mais pas la bonne année, encore un effort ;)"%(auteur))
569 self
.play_status
[canal
][3]=2
572 if self
.play_status
[canal
][0]==1:
573 bonusmsg
=u
" [+bonus_mois"*(score_obtenu
>config
.score_annee
)+u
"+bonus_jour"*(score_obtenu
>config
.score_annee
+config
.score_mois
)
579 serv
.privmsg(canal
,(u
"%s: bravo ! (C'était le %s)%s"%(auteur
,answer
,bonusmsg
)).encode("utf8"))
580 log(self
.serveur
,canal
,auteur
+"$win",message
)
581 if auteur
in config
.noscore
:
583 self
.add_score(auteur
,score_obtenu
)
585 self
.play_status
[canal
]=[0,token
]
586 serv
.execute_delayed(random
.randrange(config
.Ttrig
*5,config
.Ttrig
*10),self
.start_enigme
,(serv
,canal
,token
))
588 def on_kick(self
,serv
,ev
):
589 auteur
= irclib
.nm_to_n(ev
.source())
590 channel
= ev
.target()
591 victime
= ev
.arguments()[0]
592 raison
= ev
.arguments()[1]
593 if victime
==self
.nick
:
594 log(self
.serveur
,"%s kické de %s par %s (raison : %s)" %(victime
,channel
,auteur
,raison
))
597 self
.update_activity(channel
,force
=True)
598 # on ne dit rien au rejoin
599 #l1,l2=config.kick_answers,config.kick_actions
600 #n1,n2=len(l1),len(l2)
601 #i=random.randrange(n1+n2)
603 # serv.action(channel,l2[i-n1].format(auteur).encode("utf8"))
605 # serv.privmsg(channel,l1[i].format(auteur).encode("utf8"))
607 def quitter(self
,chan
,leave_message
=None):
608 if leave_message
==None:
609 leave_message
=random
.choice(config
.leave_messages
)
611 leave_message
=leave_message
%(time
.strftime("le %d/%m/%Y à %T").decode("utf8"),self
.nick
)
614 self
.serv
.part(chan
,message
=leave_message
.encode("utf8"))
617 quit_message
=random
.choice(config
.quit_messages
)
619 quit_message
=quit_message
%(time
.strftime("le %d/%m/%Y à %T").decode("utf8"),self
.nick
)
622 self
.die(msg
=quit_message
.encode("utf8"))
624 def get_scores(self
):
625 f
=open(config
.score_file
)
626 scores
=pickle
.load(f
)
630 def add_score(self
,pseudo
,value
):
631 scores
=self
.get_scores()
632 if scores
.has_key(pseudo
):
633 scores
[pseudo
]+=value
636 self
.save_scores(scores
)
638 def save_scores(self
,scores
):
639 f
=open(config
.score_file
,"w")
640 pickle
.dump(scores
,f
)
644 return self
.serv
.get_nickname()
645 nick
= property(_getnick
)
647 def update_activity(self
,canal
,pseudo
,message
):
648 if force
or (not pseudo
in config
.idle_bots
and all([not re
.match(ignore
, message
) for ignore
in config
.idle_messages
])):
649 self
.last_activity
[canal
]=time
.time()
650 def is_active(self
,canal
):
651 return time
.time()-self
.last_activity
[canal
]<config
.idle_time
653 def reload(self
, auteur
=None):
655 if auteur
in [None, "SIGHUP"]:
656 towrite
= "Config reloaded" + " (SIGHUP received)"*(auteur
== "SIGHUP")
657 for to
in config
.report_bugs_to
:
658 self
.serv
.privmsg(to
, towrite
)
659 log(self
.serveur
, towrite
)
661 self
.serv
.privmsg(auteur
,"Config reloaded")
663 def start_as_daemon(self
, outfile
):
664 sys
.stderr
= Logger(outfile
)
668 class Logger(object):
669 """Pour écrire ailleurs que sur stdout"""
670 def __init__(self
, filename
="historien.full.log"):
671 self
.filename
= filename
673 def write(self
, message
):
674 f
= open(self
.filename
, "a")
679 if __name__
=="__main__":
682 print "Usage : historien.py <serveur> [--debug] [--no-output] [--daemon [--pidfile]] [--outfile]"
683 print " --outfile sans --no-output ni --daemon n'a aucun effet"
686 if "--daemon" in sys
.argv
:
687 thisfile
= os
.path
.realpath(__file__
)
688 thisdirectory
= thisfile
.rsplit("/", 1)[0]
689 os
.chdir(thisdirectory
)
693 if "debug" in sys
.argv
or "--debug" in sys
.argv
:
697 if "--no-output" in sys
.argv
or "--daemon" in sys
.argv
:
698 outfile
= "/var/log/bots/historien.full.log"
701 if arg
[0].strip('-') in ["out", "outfile", "logfile"]:
703 sys
.stdout
= Logger(outfile
)
704 serveurs
={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
705 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"}
707 serveur
=serveurs
[serveur
]
709 print "Server Unknown : %s"%(serveur)
711 historien
=Historien(serveur
,debug
)
712 # Si on reçoit un SIGHUP, on reload la config
713 def sighup_handler(signum
, frame
):
714 historien
.reload("SIGHUP")
715 signal
.signal(signal
.SIGHUP
, sighup_handler
)
717 child_pid
= os
.fork()
720 historien
.start_as_daemon(outfile
)
722 # on enregistre le pid de historien
723 pidfile
= "/var/run/bots/historien.pid"
726 if arg
[0].strip('-') in ["pidfile"]:
728 f
= open(pidfile
, "w")
729 f
.write("%s\n" % child_pid
)