]>
gitweb.pimeys.fr Git - bots/historien.git/blob - historien.py
66a4ff6a9b604b2d7d79793c1da72445a6e0d32d
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 if config
.auto_trigger
:
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 if config
.auto_trigger
:
156 serv
.execute_delayed(config
.ttrig
*5,self
.start_enigme
,(serv
,channel
,token
))
158 if self
.play_status
[channel
][0]==0 and channel
in self
.play_channels
:
160 if token
==self
.play_status
[channel
][-1]:
163 if time
.time() > self
.play_status
[channel
][-1]+config
.time_incompressible
:
168 date
,evenement
=self
.get_enigme()
169 log(self
.serveur
,channel
,u
"$Date$".encode("utf8"),("%s : %s"%(date
, evenement
)).encode("utf8"))
170 serv
.privmsg(channel
,evenement
.encode("utf8"))
172 # le 0 est le flag "bon siècle" n'a pas encore été dit
173 self
.play_status
[channel
]=[1,date
,evenement
,0,token
]
174 serv
.execute_delayed(random
.randrange(config
.ttrig
*3,config
.ttrig
*5),self
.give_indice
,(serv
,channel
,token
))
177 def give_indice(self
,serv
,channel
,token
):
178 if self
.play_status
[channel
][0]==1:
180 # c'est donc que l'indice a été demandé
181 if self
.play_status
[channel
][-1]+config
.time_incompressible_clue
<time
.time():
182 token
=self
.play_status
[channel
][-1]
183 if self
.play_status
[channel
][-1]==token
:
184 date
=self
.play_status
[channel
][1]
186 serv
.privmsg(channel
,"indice : %s"%(indice).encode("utf8"))
187 self
.play_status
[channel
][0]=2
188 serv
.execute_delayed(random
.randrange(config
.ttrig
*1,config
.ttrig
*3),self
.give_answer
,(serv
,channel
,token
))
189 def give_answer(self
,serv
,channel
,token
):
190 if self
.play_status
[channel
][0]==2 and self
.play_status
[channel
][-1]==token
:
191 date
=self
.play_status
[channel
][1]
192 serv
.privmsg(channel
,"C'était le %s"%(date).encode("utf8"))
194 self
.play_status
[channel
]=[0,token
]
195 if config
.auto_trigger
:
196 serv
.execute_delayed(random
.randrange(config
.Ttrig
*5,config
.Ttrig
*10),self
.start_enigme
,(serv
,channel
,token
))
198 def get_enigme(self
):
199 # on récupère les dates
200 f
=open(config
.source_file
)
203 l
=[i
.split(" : ",2) for i
in l
]
204 dates
={int(i
[0]):i
[1:] for i
in l
}
205 # on va chercher combien de fois elles ont été jouées
206 played_file
=get_config_played_file(self
.serveur
)
210 l
=re
.findall("(.*):(.*)",t
)
211 played
={int(i
[0]):int(i
[1]) for i
in l
}
212 # on récupère le nombre d'occurrences le plus faible
213 mini
=min(played
.values())
214 # on choisit un id dans ceux qui ont ce nombre d'occurences
215 id_choisi
=random
.choice([k
for k
,v
in played
.items() if v
==mini
])
216 date
,evenement
=dates
[id_choisi
]
217 evenement
=evenement
.replace("\n","")
218 # on incrémente la choisie
220 # on enregistre le played_file
221 f
=open(played_file
,"w")
222 f
.write("\n".join(["%-4s : %s"%(k
,v
) for k
,v
in played
.items()]))
224 return map(lambda x
:x
.decode("utf8"), [date
,evenement
])
226 def pourmoi(self
, serv
, message
):
229 if message
[:size
]==pseudo
and len(message
)>size
and message
[size
]==":":
230 return (True,message
[size
+1:].strip(" "))
232 return (False,message
)
234 def on_privmsg(self
, serv
, ev
):
235 if ignore_event(serv
, ev
):
237 message
=ev
.arguments()[0]
238 auteur
= irclib
.nm_to_n(ev
.source())
240 test
=bot_unicode(message
)
241 except UnicodeBotError
:
242 if config
.utf8_trigger
:
243 serv
.privmsg(auteur
, random
.choice(config
.utf8_fail_answers
).encode("utf8"))
245 message
=message
.split()
246 cmd
=message
[0].lower()
249 helpmsg_default
="""Liste des commandes :
250 HELP Affiche ce message d'aide
251 SCORE Affiche ton score (SCORE TRANSFERT <pseudo> [<n>] pour transférer des points)
252 SCORES Affiche les scores"""
254 JOIN Faire rejoindre un channel (sans paramètres, donne la liste des chans actuels)
255 LEAVE Faire quitter un channel
256 PLAY Passe un channel en mode "jouer"
257 NOPLAY Passe un channel en mode "ne pas jouer"
258 QUIET Se taire sur un channel
259 NOQUIET Opposé de QUIET
260 RELOAD Me fait recharger la conf"""
262 SCORES {DEL|ADD|SUB} Tu veux un dessin ?
263 SAY Fais envoyer un message sur un chan ou à une personne
264 STAY Ignorera les prochains LEAVE pour un chan
265 NOSTAY Opposé de STAY
266 STATUS Montre l'état courant
268 helpmsg
=helpmsg_default
269 if auteur
in self
.ops
:
271 if auteur
in self
.overops
:
272 helpmsg
+=helpmsg_overops
273 for ligne
in helpmsg
.split("\n"):
274 serv
.privmsg(auteur
,ligne
)
276 if auteur
in self
.ops
:
278 if message
[1] in self
.chanlist
:
279 serv
.privmsg(auteur
,"Je suis déjà sur %s"%(message
[1]))
281 serv
.join(message
[1])
282 self
.chanlist
.append(message
[1])
283 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
284 log(self
.serveur
,"priv",auteur
," ".join(message
))
286 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
290 if auteur
in self
.ops
and len(message
)>1:
291 if message
[1] in self
.chanlist
:
292 if not (message
[1] in self
.stay_channels
) or auteur
in self
.overops
:
293 self
.quitter(message
[1]," ".join(message
[2:]))
294 self
.chanlist
.remove(message
[1])
295 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
297 serv
.privmsg(auteur
,"Non, je reste !")
298 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
300 serv
.privmsg(auteur
,"Je ne suis pas sur %s"%(message
[1]))
304 if auteur
in self
.overops
:
306 if message
[1] in self
.stay_channels
:
307 serv
.privmsg(auteur
,"Je stay déjà sur %s."%(message
[1]))
308 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
310 self
.stay_channels
.append(message
[1])
311 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
312 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
314 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
318 if auteur
in self
.overops
:
320 if message
[1] in self
.stay_channels
:
321 self
.stay_channels
.remove(message
[1])
322 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
323 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
325 serv
.privmsg(auteur
,"Je ne stay pas sur %s."%(message
[1]))
326 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
330 if auteur
in self
.ops
:
332 if message
[1] in self
.play_channels
:
333 serv
.privmsg(auteur
,"Je play déjà sur %s."%(message
[1]))
334 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
336 self
.play_channels
.append(message
[1])
337 self
.play_status
[message
[1]]=[0,time
.time()-3600]
338 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
339 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
341 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
345 if auteur
in self
.ops
:
347 if message
[1] in self
.play_channels
:
348 self
.play_channels
.remove(message
[1])
349 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
350 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
352 serv
.privmsg(auteur
,"Je ne play pas sur %s."%(message
[1]))
353 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
357 if auteur
in self
.ops
:
359 if message
[1] in self
.quiet_channels
:
360 serv
.privmsg(auteur
,"Je me la ferme déjà sur %s"%(message
[1]))
361 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
363 self
.quiet_channels
.append(message
[1])
364 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
365 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
367 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
371 if auteur
in self
.ops
:
373 if message
[1] in self
.quiet_channels
:
374 self
.quiet_channels
.remove(message
[1])
375 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
376 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
378 serv
.privmsg(auteur
,"Je ne me la ferme pas sur %s."%(message
[1]))
379 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
383 if auteur
in self
.ops
:
385 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
388 elif cmd
in ["states","status"]:
389 if auteur
in self
.overops
:
390 for k
in self
.play_status
.keys():
391 serv
.privmsg(auteur
,(u
"%s : %s"%(k
," | ".join([unicode(i
) for i
in self
.play_status
[k
]]))).encode("utf8") )
393 if auteur
in self
.overops
and len(message
)>2:
394 serv
.privmsg(message
[1]," ".join(message
[2:]))
395 log(self
.serveur
,"priv",auteur
," ".join(message
))
396 elif len(message
)<=2:
397 serv
.privmsg(auteur
,"Syntaxe : SAY <channel> <message>")
401 if auteur
in self
.overops
:
402 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
406 if len(message
) in [3,4] and message
[1].lower()=="transfert":
407 scores
=self
.get_scores()
408 de
,to
=auteur
,message
[2]
409 value
=scores
.get(de
,0)
412 asked
=int(message
[3])
414 serv
.privmsg(auteur
,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
419 serv
.privmsg(auteur
,"Vous n'avez pas de points")
422 serv
.privmsg(auteur
,"Bien tenté…")
425 serv
.privmsg(auteur
,"Vous n'avez que %s points"%(value))
428 self
.add_score(de
,-asked
)
429 self
.add_score(to
,asked
)
430 serv
.privmsg(auteur
,"Transfert de %s points de %s à %s"%(asked
,de
,to
))
432 serv
.privmsg(auteur
,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
434 serv
.privmsg(auteur
,"Votre score : %s"%(self
.get_scores().get(auteur
,0)) )
437 scores
=self
.get_scores().items()
439 scores
.sort(lambda x
,y
:cmp(x
[1],y
[1]))
441 serv
.privmsg(auteur
,"Scores by score : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
443 scores
.sort(lambda x
,y
:cmp(x
[0].lower(),y
[0].lower()))
444 serv
.privmsg(auteur
,"Scores by pseudo : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
445 elif auteur
in self
.overops
:
446 souscmd
=message
[1].lower()
450 scores
=self
.get_scores()
451 if scores
.has_key(todelete
):
453 self
.save_scores(scores
)
454 serv
.privmsg(auteur
,"Score de %s supprimé"%(todelete))
456 serv
.privmsg(auteur
,"Ce score n'existe pas : %s"%(todelete))
458 serv
.privmsg(auteur
,"Syntaxe : SCORES DEL <pseudo>")
459 elif souscmd
in ["add","sub"]:
461 toadd
,val
=message
[2],message
[3]
465 serv
.privmsg(auteur
,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
469 self
.add_score(toadd
,val
)
470 serv
.privmsg(auteur
,"Done")
472 serv
.privmsg(auteur
,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
474 serv
.privmsg(auteur
,"Syntaxe : SCORES {DEL|ADD|SUB} <pseudo> [<n>]")
480 serv
.privmsg(auteur
,"Je n'ai pas compris. Essaye HELP…")
482 def on_pubmsg(self
, serv
, ev
):
483 if ignore_event(serv
, ev
):
485 auteur
= irclib
.nm_to_n(ev
.source())
487 message
= ev
.arguments()[0]
488 self
.update_activity(canal
,auteur
,message
)
490 test
=bot_unicode(message
)
491 except UnicodeBotError
:
492 if config
.utf8_trigger
and not canal
in self
.quiet_channels
:
493 serv
.privmsg(canal
, (u
"%s: %s"%(auteur
, random
.choice(config
.utf8_fail_answers
))).encode("utf8"))
496 pour_moi
,message
=self
.pourmoi(serv
,message
)
497 if pour_moi
and message
.split()!=[]:
498 cmd
=message
.split()[0].lower()
500 args
=" ".join(message
.split()[1:])
503 if cmd
in ["meurs","die","crève"]:
504 if auteur
in self
.overops
:
506 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
508 serv
.privmsg(canal
,"%s: crève !"%(auteur))
509 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
510 elif cmd
in ["meur", "meurt","meurre","meurres"] and not canal
in self
.quiet_channels
:
511 serv
.privmsg(canal
,'%s: Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)'%(auteur))
512 elif cmd
== "reload":
513 if auteur
in self
.ops
:
514 log(self
.serveur
, canal
, auteur
, message
+"[successful]")
516 elif cmd
in ["part","leave","dégage"]:
517 if auteur
in self
.ops
and (not (canal
in self
.stay_channels
)
518 or auteur
in self
.overops
):
520 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
521 self
.chanlist
.remove(canal
)
523 serv
.privmsg(canal
,"%s: Non, je reste !"%(auteur))
524 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
526 elif cmd
in ["deviens","pseudo"]:
527 if auteur
in self
.ops
:
530 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
531 elif cmd
in ["coucou"] and not canal
in self
.quiet_channels
:
532 serv
.privmsg(canal
,"%s: coucou"%(auteur))
533 elif cmd
in ["ping"] and not canal
in self
.quiet_channels
:
534 serv
.privmsg(canal
,"%s: pong"%(auteur))
535 elif cmd
in ["date","dates","histoire","énigme","enigme","encore"]:
536 if canal
in self
.play_channels
:
537 if self
.play_status
.get(canal
,[-1])[0]==0:
539 self
.start_enigme(serv
,canal
)
541 serv
.privmsg(canal
,"%s: Je peux souffler une minute ?"%(auteur))
543 serv
.privmsg(canal
,("%s: Rappel : %s"%(auteur
,self
.play_status
[canal
][2])).encode("utf8") )
545 serv
.privmsg(canal
,"%s: pas ici…"%(auteur))
546 elif cmd
in ["score","!score"]:
547 serv
.privmsg(auteur
,"Votre score : %s"%(self
.get_scores().get(auteur
,0)) )
548 elif cmd
in ["scores","!scores"]:
549 scores
=self
.get_scores().items()
551 scores
.sort(lambda x
,y
:cmp(x
[1],y
[1]))
553 serv
.privmsg(auteur
,"Scores by score : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
555 scores
.sort(lambda x
,y
:cmp(x
[0].lower(),y
[0].lower()))
556 serv
.privmsg(auteur
,"Scores by pseudo : "+" ; ".join(["%s %s"%(i
[0],i
[1]) for i
in scores
]))
557 elif cmd
== "indice" and canal
in self
.play_channels
:
558 self
.give_indice(serv
,canal
,None)
559 elif is_tag(message
) and not canal
in self
.quiet_channels
:
560 if auteur
in self
.ops
:
561 action
=random
.choice(config
.tag_actions
)
562 serv
.action(canal
,action
.encode("utf8"))
563 self
.quiet_channels
.append(canal
)
565 answer
=random
.choice(config
.tag_answers
)
566 for ligne
in answer
.split("\n"):
567 serv
.privmsg(canal
,"%s: %s"%(auteur
,ligne
.encode("utf8")))
573 if self
.play_status
.get(canal
,[-1])[0] in [1,2]:
574 answer
=self
.play_status
[canal
][1]
575 flag_century
=self
.play_status
[canal
][3]
577 score_obtenu
=reussi(message
.decode("utf8"),answer
,auteur
)
580 serv
.privmsg(canal
,"%s: C'est le bon siècle, mais pas la bonne année, cherche encore ;)"%(auteur))
581 self
.play_status
[canal
][3]=1
584 if flag_century
in [0,1]:
585 serv
.privmsg(canal
,"%s: C'est la bonne décennie, mais pas la bonne année, encore un effort ;)"%(auteur))
586 self
.play_status
[canal
][3]=2
589 if self
.play_status
[canal
][0]==1:
590 bonusmsg
=u
" [+bonus_mois"*(score_obtenu
>config
.score_annee
)+u
"+bonus_jour"*(score_obtenu
>config
.score_annee
+config
.score_mois
)
596 serv
.privmsg(canal
,(u
"%s: bravo ! (C'était le %s)%s"%(auteur
,answer
,bonusmsg
)).encode("utf8"))
597 log(self
.serveur
,canal
,auteur
+"$win",message
)
598 if auteur
in config
.noscore
:
600 self
.add_score(auteur
,score_obtenu
)
602 self
.play_status
[canal
]=[0,token
]
603 if config
.auto_trigger
:
604 serv
.execute_delayed(random
.randrange(config
.Ttrig
*5,config
.Ttrig
*10),self
.start_enigme
,(serv
,canal
,token
))
606 def on_kick(self
,serv
,ev
):
607 auteur
= irclib
.nm_to_n(ev
.source())
608 channel
= ev
.target()
609 victime
= ev
.arguments()[0]
610 raison
= ev
.arguments()[1]
611 if victime
==self
.nick
:
612 log(self
.serveur
,"%s kické de %s par %s (raison : %s)" %(victime
,channel
,auteur
,raison
))
615 self
.update_activity(channel
,force
=True)
616 # on ne dit rien au rejoin
617 #l1,l2=config.kick_answers,config.kick_actions
618 #n1,n2=len(l1),len(l2)
619 #i=random.randrange(n1+n2)
621 # serv.action(channel,l2[i-n1].format(auteur).encode("utf8"))
623 # serv.privmsg(channel,l1[i].format(auteur).encode("utf8"))
625 def quitter(self
,chan
,leave_message
=None):
626 if leave_message
==None:
627 leave_message
=random
.choice(config
.leave_messages
)
629 leave_message
=leave_message
%(time
.strftime("le %d/%m/%Y à %T").decode("utf8"),self
.nick
)
632 self
.serv
.part(chan
,message
=leave_message
.encode("utf8"))
635 quit_message
=random
.choice(config
.quit_messages
)
637 quit_message
=quit_message
%(time
.strftime("le %d/%m/%Y à %T").decode("utf8"),self
.nick
)
640 self
.die(msg
=quit_message
.encode("utf8"))
642 def get_scores(self
):
643 f
=open(config
.score_file
)
644 scores
=pickle
.load(f
)
648 def add_score(self
,pseudo
,value
):
649 scores
=self
.get_scores()
650 if scores
.has_key(pseudo
):
651 scores
[pseudo
]+=value
654 self
.save_scores(scores
)
656 def save_scores(self
,scores
):
657 f
=open(config
.score_file
,"w")
658 pickle
.dump(scores
,f
)
662 return self
.serv
.get_nickname()
663 nick
= property(_getnick
)
665 def update_activity(self
,canal
="",pseudo
="",message
="",force
=False):
666 if force
or (not pseudo
in config
.idle_bots
and all([not re
.match(ignore
, message
) for ignore
in config
.idle_messages
])):
667 self
.last_activity
[canal
]=time
.time()
668 def is_active(self
,canal
):
669 # Si on n'a pas d'info sur le chan, il est inactif
670 return time
.time()-self
.last_activity
.get(canal
, config
.idle_time
)<config
.idle_time
672 def reload(self
, auteur
=None):
674 if auteur
in [None, "SIGHUP"]:
675 towrite
= "Config reloaded" + " (SIGHUP received)"*(auteur
== "SIGHUP")
676 for to
in config
.report_bugs_to
:
677 self
.serv
.privmsg(to
, towrite
)
678 log(self
.serveur
, towrite
)
680 self
.serv
.privmsg(auteur
,"Config reloaded")
682 def start_as_daemon(self
, outfile
):
683 sys
.stderr
= Logger(outfile
)
687 class Logger(object):
688 """Pour écrire ailleurs que sur stdout"""
689 def __init__(self
, filename
="historien.full.log"):
690 self
.filename
= filename
692 def write(self
, message
):
693 f
= open(self
.filename
, "a")
698 if __name__
=="__main__":
701 print "Usage : historien.py <serveur> [--debug] [--no-output] [--daemon [--pidfile]] [--outfile]"
702 print " --outfile sans --no-output ni --daemon n'a aucun effet"
705 if "--daemon" in sys
.argv
:
706 thisfile
= os
.path
.realpath(__file__
)
707 thisdirectory
= thisfile
.rsplit("/", 1)[0]
708 os
.chdir(thisdirectory
)
712 if "debug" in sys
.argv
or "--debug" in sys
.argv
:
716 if "--no-output" in sys
.argv
or "--daemon" in sys
.argv
:
717 outfile
= "/var/log/bots/historien.full.log"
720 if arg
[0].strip('-') in ["out", "outfile", "logfile"]:
722 sys
.stdout
= Logger(outfile
)
723 serveurs
={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
724 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"}
726 serveur
=serveurs
[serveur
]
728 print "Server Unknown : %s"%(serveur)
730 historien
=Historien(serveur
,debug
)
731 # Si on reçoit un SIGHUP, on reload la config
732 def sighup_handler(signum
, frame
):
733 historien
.reload("SIGHUP")
734 signal
.signal(signal
.SIGHUP
, sighup_handler
)
736 child_pid
= os
.fork()
739 historien
.start_as_daemon(outfile
)
741 # on enregistre le pid de historien
742 pidfile
= "/var/run/bots/historien.pid"
745 if arg
[0].strip('-') in ["pidfile"]:
747 f
= open(pidfile
, "w")
748 f
.write("%s\n" % child_pid
)