]> gitweb.pimeys.fr Git - bots/themis.git/blob - themis.py
[brown paperbag] c'est une liste !
[bots/themis.git] / themis.py
1 #!/usr/bin/python
2 # -*- coding:utf8 -*-
3 # Codé par 20-100 (commencé le 21/06/12)
4
5 # Un bot IRC pour kicker à tour de bras de #déprime
6
7 import threading
8 import random
9 import time
10 import socket, ssl, json
11 import pickle
12 import re
13 import os
14 import signal
15 import sys
16
17 # Oui, j'ai recodé ma version d'irclib pour pouvoir rattrapper les SIGHUP
18 sys.path.insert(0, "/home/vincent/scripts/python-myirclib")
19 import irclib
20 import ircbot
21
22 import sys
23
24 # Fichier de conf
25 import config
26
27 def get_config_logfile(serveur):
28 serveurs={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
29 return config.logfile_template%(serveurs[serveur])
30
31
32 def log(serveur,channel,auteur=None,message=None):
33 f=open(get_config_logfile(serveur),"a")
34 if auteur==message==None:
35 # alors c'est que c'est pas un channel mais juste une ligne de log
36 chain="%s %s"%(time.strftime("%F %T"),channel)
37 else:
38 chain="%s [%s:%s] %s"%(time.strftime("%F %T"),channel,auteur,message)
39 f.write(chain+"\n")
40 if config.debug_stdout:
41 print chain
42 f.close()
43
44 reg_is_smiley = re.compile(u".*("+u"|".join(config.smileys)+u")")
45 def is_smiley(chain):
46 chain=unicode(chain,"utf8")
47 o=re.match(reg_is_smiley,chain)
48 return o
49
50 reg_is_anglicisme = re.compile(u".*(?:^| )(" + u"|".join(config.anglicismes) + u")(?:$|\.| |,|;)")
51 def is_anglicisme(chain):
52 chain = unicode(chain, "utf8").lower()
53 o = re.match(reg_is_anglicisme, chain)
54 return o
55
56 # Cette liste contient la liste des raisons pour lesquelles on peut se faire kicker
57 # chaque élément contient :
58 # - la fonction de détection du kick (qui matchera une regexp et renverra l'objet de match)
59 # - la raison donnée au moment du kick ({0} étant remplacé par ce qui a matché)
60 config.kicking_list = [
61 [is_smiley, u'"{0}" ? Ici on déprime.'],
62 [is_anglicisme, u'"{0}" ? Get out, you and your fucking anglicism !']
63 ]
64
65 def is_something(chain,matches,avant=u".*(?:^| )",apres=u"(?:$|\.| |,|;).*",case_sensitive=False,debug=False):
66 if case_sensitive:
67 chain=unicode(chain,"utf8")
68 else:
69 chain=unicode(chain,"utf8").lower()
70 allmatches="("+"|".join(matches)+")"
71 reg=(avant+allmatches+apres).lower()
72 o=re.match(reg,chain)
73 return o
74
75 def is_insult(chain,debug=True):
76 return is_something(chain,config.insultes,avant=".*(?:^| |')")
77 def is_not_insult(chain):
78 chain=unicode(chain,"utf8")
79 insult_regexp=u"("+u"|".join(config.insultes)+u")"
80 middle_regexp=u"(une? (?:(?:putain|enfoiré) d(?:e |'))*|)(?:| super )(?: (?:gros|petit|grand|énorme) |)"
81 reg=".*pas %s%s.*"%(middle_regexp,insult_regexp)
82 if re.match(reg,chain):
83 return True
84 else:
85 return False
86 def is_compliment(chain,debug=True):
87 return is_something(chain,config.compliment_triggers,avant=".*(?:^| |')")
88 def is_perdu(chain):
89 return is_something(chain,config.perdu)
90 def is_tag(chain):
91 return is_something(chain,config.tag_triggers)
92 def is_tesla(chain):
93 return is_something(chain,config.tesla_triggers,avant=u"^",apres=u"$",debug=True)
94 def is_merci(chain):
95 return is_something(chain,config.merci_triggers)
96 def is_tamere(chain):
97 return is_something(chain,config.tamere_triggers)
98 def is_bad_action_trigger(chain,pseudo):
99 return is_something(chain,config.bad_action_triggers,avant=u"^",
100 apres="(?: [a-z]*ment)? %s($|\.| |,|;).*"%(pseudo))
101 def is_good_action_trigger(chain,pseudo):
102 return is_something(chain,config.good_action_triggers,avant=u"^",
103 apres="(?: [a-z]*ment)? %s($|\.| |,|;).*"%(pseudo))
104 def is_bonjour(chain):
105 return is_something(chain,config.bonjour_triggers,avant=u"^")
106 def is_bonne_nuit(chain):
107 return is_something(chain,config.bonne_nuit_triggers,avant=u"^")
108 def is_pan(chain):
109 return re.match(u"^(pan|bim|bang)( .*)?$",unicode(chain,"utf8").lower().strip())
110
111 def is_time(conf):
112 _,_,_,h,m,s,_,_,_=time.localtime()
113 return (conf[0],0,0)<(h,m,s)<(conf[1],0,0)
114 def is_day():
115 return is_time(config.daytime)
116 def is_night():
117 return is_time(config.nighttime)
118
119
120 class UnicodeBotError(Exception):
121 pass
122 def bot_unicode(chain):
123 try:
124 unicode(chain,"utf8")
125 except UnicodeDecodeError as exc:
126 raise UnicodeBotError
127
128 class Themis(ircbot.SingleServerIRCBot):
129 def __init__(self,serveur,debug=False):
130 temporary_pseudo=config.irc_pseudo+str(random.randrange(10000,100000))
131 ircbot.SingleServerIRCBot.__init__(self, [(serveur, 6667)],
132 temporary_pseudo,"Des[bot]e de #déprime", 10)
133 self.debug=debug
134 self.serveur=serveur
135 self.overops=config.overops
136 self.ops=self.overops+config.ops
137 self.report_bugs_to=config.report_bugs_to
138 self.chanlist=config.chanlist
139 self.kick_channels=config.kick_channels
140 self.stay_channels=config.stay_channels
141 self.quiet_channels=config.quiet_channels
142 self.last_perdu=0
143
144
145 def give_me_my_pseudo(self,serv):
146 serv.privmsg("NickServ","RECOVER %s %s"%(config.irc_pseudo,config.irc_password))
147 serv.privmsg("NickServ","RELEASE %s %s"%(config.irc_pseudo,config.irc_password))
148 time.sleep(0.3)
149 serv.nick(config.irc_pseudo)
150
151 def give_me_my_op_status(self,serv,chan):
152 serv.privmsg("ChanServ","OP %s"%(chan))
153
154 def on_welcome(self, serv, ev):
155 self.serv=serv # ça serv ira
156 self.give_me_my_pseudo(serv)
157 serv.privmsg("NickServ","identify %s"%(config.irc_password))
158 log(self.serveur,"Connected")
159 if self.debug:
160 self.chanlist=["#bot"]
161 self.kick_channels=["#bot"]
162 for c in self.chanlist:
163 log(self.serveur,"JOIN %s"%(c))
164 serv.join(c)
165 self.give_me_my_op_status(serv,c)
166
167
168 def lost(self,serv,channel,forced=False):
169 if self.last_perdu+config.time_between_perdu<time.time() or forced:
170 if not channel in self.quiet_channels or forced:
171 serv.privmsg(channel,"J'ai perdu !")
172 self.last_perdu=time.time()
173 delay=config.time_between_perdu_trigger
174 delta=config.time_between_perdu_trigger_delta
175 serv.execute_delayed(random.randrange(delay-delta,delay+delta),self.lost,(serv,channel))
176
177 def pourmoi(self, serv, message):
178 """renvoie (False,lemessage) ou (True, le message amputé de "pseudo: ")"""
179 pseudo=self.nick
180 size=len(pseudo)
181 if message[:size]==pseudo and len(message)>size and message[size]==":":
182 return (True,message[size+1:].lstrip(" "))
183 else:
184 return (False,message)
185
186 def on_privmsg(self, serv, ev):
187 message=ev.arguments()[0]
188 auteur = irclib.nm_to_n(ev.source())
189 try:
190 test=bot_unicode(message)
191 except UnicodeBotError:
192 if config.utf8_trigger:
193 serv.privmsg(auteur, random.choice(config.utf8_fail_answers).encode("utf8"))
194 return
195 message=message.split()
196 cmd=message[0].lower()
197 notunderstood=False
198 if cmd=="help":
199 helpdico={"help":["""HELP <commande>
200 Affiche de l'aide sur la commande""",None,None],
201 "join": [None, """JOIN <channel>
202 Me fait rejoindre le channel""",None],
203 "leave": [None,"""LEAVE <channel>
204 Me fait quitter le channel (sauf s'il est dans ma stay_list).""",None],
205 "quiet": [None,"""QUIET <channel>
206 Me rend silencieux sur le channel.""",None],
207 "noquiet": [None,"""NOQUIET <channel>
208 Me rend la parole sur le channel.""",None],
209 "reload": [None,"""RELOAD
210 Recharge la configuration.""",None],
211 "say": [None,None,"""SAY <channel> <message>
212 Me fait parler sur le channel."""],
213 "do": [None,None,"""DO <channel> <action>
214 Me fait faitre une action (/me) sur le channel."""],
215 "stay": [None,None,"""STAY <channel>
216 Ajoute le channel à ma stay_list."""],
217 "nostay": [None,None,"""NOSTAY <channel>
218 Retire le channel de ma stay_list."""],
219 "ops": [None,None,"""OPS
220 Affiche la liste des ops."""],
221 "overops": [None,None,"""OVEROPS
222 Affiche la liste des overops."""],
223 "kick": [None,None,"""KICK <channel> <pseudo> [<raison>]
224 Kicke <pseudo> du channel (Il faut bien entendu que j'y sois op)."""],
225 "die": [None,None,"""DIE
226 Me déconnecte du serveur IRC."""]
227 }
228 helpmsg_default="Liste des commandes disponibles :\nHELP"
229 helpmsg_ops=" JOIN LEAVE QUIET NOQUIET LOST RELOAD"
230 helpmsg_overops=" SAY DO STAY NOSTAY OPS OVEROPS KICK DIE"
231 op,overop=auteur in self.ops, auteur in self.overops
232 if len(message)==1:
233 helpmsg=helpmsg_default
234 if op:
235 helpmsg+=helpmsg_ops
236 if overop:
237 helpmsg+=helpmsg_overops
238 else:
239 helpmsgs=helpdico.get(message[1].lower(),["Commande inconnue.",None,None])
240 helpmsg=helpmsgs[0]
241 if op and helpmsgs[1]:
242 if helpmsg:
243 helpmsg+="\n"+helpmsgs[1]
244 else:
245 helpmsg=helpmsgs[1]
246 if overop and helpmsgs[2]:
247 if helpmsg:
248 helpmsg+="\n"+helpmsgs[2]
249 else:
250 helpmsg=helpmsgs[2]
251 for ligne in helpmsg.split("\n"):
252 serv.privmsg(auteur,ligne)
253 elif cmd=="join":
254 if auteur in self.ops:
255 if len(message)>1:
256 if message[1] in self.chanlist:
257 serv.privmsg(auteur,"Je suis déjà sur %s"%(message[1]))
258 else:
259 serv.join(message[1])
260 self.chanlist.append(message[1])
261 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
262 log(self.serveur,"priv",auteur," ".join(message))
263 else:
264 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
265 else:
266 notunderstood=True
267 elif cmd=="leave":
268 if auteur in self.ops and len(message)>1:
269 if message[1] in self.chanlist:
270 if not (message[1] in self.stay_channels) or auteur in self.overops:
271 self.quitter(message[1]," ".join(message[2:]))
272 self.chanlist.remove(message[1])
273 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
274 else:
275 serv.privmsg(auteur,random.choice(config.leave_fail_messages))
276 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
277 else:
278 serv.privmsg(auteur,"Je ne suis pas sur %s"%(message[1]))
279 else:
280 notunderstood=True
281 elif cmd=="stay":
282 if auteur in self.overops:
283 if len(message)>1:
284 if message[1] in self.stay_channels:
285 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
286 serv.privmsg(auteur,"Je stay déjà sur %s."%(message[1]))
287 else:
288 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
289 self.stay_channels.append(message[1])
290 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
291 else:
292 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
293 else:
294 notunderstood=True
295 elif cmd=="nostay":
296 if auteur in self.overops:
297 if len(message)>1:
298 if message[1] in self.stay_channels:
299 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
300 self.stay_channels.remove(message[1])
301 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
302 else:
303 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
304 serv.privmsg(auteur,"Je ne stay pas sur %s."%(message[1]))
305
306 else:
307 notunderstood=True
308 elif cmd=="die":
309 if auteur in self.overops:
310 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
311 self.mourir()
312 else:
313 notunderstood=True
314 elif cmd=="quiet":
315 if auteur in self.ops:
316 if len(message)>1:
317 if message[1] in self.quiet_channels:
318 serv.privmsg(auteur,"Je me la ferme déjà sur %s"%(message[1]))
319 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
320 else:
321 self.quiet_channels.append(message[1])
322 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
323 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
324 else:
325 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
326 else:
327 notunderstood=True
328 elif cmd=="noquiet":
329 if auteur in self.ops:
330 if len(message)>1:
331 if message[1] in self.quiet_channels:
332 self.quiet_channels.remove(message[1])
333 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
334 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
335 else:
336 serv.privmsg(auteur,"Je ne me la ferme pas sur %s."%(message[1]))
337 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
338 else:
339 notunderstood=True
340 elif cmd=="reload":
341 if auteur in self.ops:
342 self.reload(auteur)
343 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
344 else:
345 notunderstood=True
346 elif cmd=="say":
347 if auteur in self.overops and len(message)>2:
348 serv.privmsg(message[1]," ".join(message[2:]))
349 log(self.serveur,"priv",auteur," ".join(message))
350 elif len(message)<=2:
351 serv.privmsg(auteur,"Syntaxe : SAY <channel> <message>")
352 else:
353 notunderstood=True
354 elif cmd=="do":
355 if auteur in self.overops and len(message)>2:
356 serv.action(message[1]," ".join(message[2:]))
357 log(self.serveur,"priv",auteur," ".join(message))
358 elif len(message)<=2:
359 serv.privmsg(auteur,"Syntaxe : DO <channel> <action>")
360 else:
361 notunderstood=True
362 elif cmd=="kick":
363 if auteur in self.overops and len(message)>2:
364 serv.kick(message[1],message[2]," ".join(message[3:]))
365 log(self.serveur,"priv",auteur," ".join(message))
366 elif len(message)<=2:
367 serv.privmsg(auteur,"Syntaxe : KICK <channel> <pseudo> [<raison>]")
368 else:
369 notunderstood=True
370 elif cmd=="ops":
371 if auteur in self.overops:
372 serv.privmsg(auteur," ".join(self.ops))
373 else:
374 notunderstood=True
375 elif cmd=="overops":
376 if auteur in self.overops:
377 serv.privmsg(auteur," ".join(self.overops))
378 else:
379 notunderstood=True
380 else:
381 notunderstood=True
382 if notunderstood:
383 serv.privmsg(auteur,"Je n'ai pas compris. Essayez HELP…")
384
385 def on_pubmsg(self, serv, ev):
386 auteur = irclib.nm_to_n(ev.source())
387 canal = ev.target()
388 message = ev.arguments()[0]
389 try:
390 test=bot_unicode(message)
391 except UnicodeBotError:
392 if config.utf8_trigger and not canal in self.quiet_channels:
393 serv.privmsg(canal, (u"%s: %s"%(auteur,random.choice(config.utf8_fail_answers))).encode("utf8"))
394 return
395 pour_moi,message=self.pourmoi(serv,message)
396 for (detect, reason) in config.kicking_list:
397 matching = detect(message)
398 if matching:
399 if canal in self.kick_channels:
400 serv.kick(canal,auteur,(reason.format(matching.groups()[0])).encode("utf8"))
401 return
402 if pour_moi and message.split()!=[]:
403 cmd=message.split()[0].lower()
404 try:
405 args=" ".join(message.split()[1:])
406 except:
407 args=""
408 if cmd in ["meurs","die","crève","pends-toi"]:
409 if auteur in self.overops:
410 log(self.serveur,canal,auteur,message+"[successful]")
411 self.mourir()
412 else:
413 serv.privmsg(canal,"%s: %s"%(auteur,random.choice(config.quit_fail_messages)))
414 log(self.serveur,canal,auteur,message+"[failed]")
415 elif cmd == "reload":
416 if auteur in self.ops:
417 log(self.serveur, canal, auteur, message+"[successful]")
418 self.reload(canal)
419 elif cmd in ["part","leave","dégage","va-t-en"]:
420 if auteur in self.ops and (not (canal in self.stay_channels)
421 or auteur in self.overops):
422 self.quitter(canal)
423 log(self.serveur,canal,auteur,message+"[successful]")
424 if canal in self.chanlist:
425 self.chanlist.remove(canal)
426 else:
427 serv.privmsg(canal,"%s: %s"%(auteur,random.choice(config.leave_fail_messages)))
428 log(self.serveur,canal,auteur,message+"[failed]")
429
430 elif cmd in ["deviens","pseudo"]:
431 if auteur in self.ops:
432 become=args
433 serv.nick(become)
434 log(self.serveur,canal,auteur,message+"[successful]")
435
436 elif cmd in ["meur", "meurt","meurre","meurres"] and not canal in self.quiet_channels:
437 serv.privmsg(canal,'%s: Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)'%(auteur))
438 elif cmd in ["ping"] and not canal in self.quiet_channels:
439 serv.privmsg(canal,"%s: pong"%(auteur))
440 # if is_insult(message) and not canal in self.quiet_channels:
441 # if is_not_insult(message):
442 # answer=random.choice(config.compliment_answers)
443 # for ligne in answer.split("\n"):
444 # serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
445 # else:
446 # answer=random.choice(config.insultes_answers)
447 # for ligne in answer.split("\n"):
448 # serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
449 # elif is_compliment(message) and not canal in self.quiet_channels:
450 # answer=random.choice(config.compliment_answers)
451 # for ligne in answer.split("\n"):
452 # serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
453 elif is_tesla(message) and not canal in self.quiet_channels:
454 l1,l2=config.tesla_answers,config.tesla_actions
455 n1,n2=len(l1),len(l2)
456 i=random.randrange(n1+n2)
457 if i>=n1:
458 serv.action(canal,l2[i-n1].encode("utf8"))
459 else:
460 serv.privmsg(canal,"%s: %s"%(auteur,l1[i].encode("utf8")))
461 elif is_tag(message) and not canal in self.quiet_channels:
462 if auteur in self.ops:
463 action=random.choice(config.tag_actions)
464 serv.action(canal,action.encode("utf8"))
465 self.quiet_channels.append(canal)
466 else:
467 answer=random.choice(config.tag_answers)
468 for ligne in answer.split("\n"):
469 serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
470 elif is_bonjour(message) and not canal in self.quiet_channels:
471 if is_night():
472 answer=random.choice(config.night_answers)
473 elif is_day():
474 answer=random.choice(config.bonjour_answers)
475 else:
476 answer=random.choice(config.bonsoir_answers)
477 serv.privmsg(canal,answer.format(auteur).encode("utf8"))
478 elif is_bonne_nuit(message) and not canal in self.quiet_channels:
479 answer=random.choice(config.bonne_nuit_answers)
480 serv.privmsg(canal,answer.format(auteur).encode("utf8"))
481 else:
482 if not canal in self.quiet_channels:
483 mypseudo=self.nick
484 if re.match((u"^("+u"|".join(config.bonjour_triggers)
485 +u")( {}| all| tout le monde|(|à) tous)(\.|( |)!|)$"
486 ).format(mypseudo).lower(), message.strip().lower()):
487 answer=random.choice(config.bonjour_answers)
488 serv.privmsg(canal,answer.format(auteur).encode("utf8"))
489
490 def on_action(self, serv, ev):
491 action = ev.arguments()[0]
492 auteur = irclib.nm_to_n(ev.source())
493 channel = ev.target()
494 try:
495 test=bot_unicode(action)
496 except UnicodeBotError:
497 if config.utf8_trigger and not canal in self.quiet_channels:
498 serv.privmsg(canal, (u"%s: %s"%(auteur,random.choice(config.utf8_fail_answers))).encode("utf8"))
499 return
500 mypseudo=self.nick
501
502 # if is_bad_action_trigger(action,mypseudo) and not channel in self.quiet_channels:
503 # l1,l2=config.bad_action_answers,config.bad_action_actions
504 # n1,n2=len(l1),len(l2)
505 # i=random.randrange(n1+n2)
506 # if i>=n1:
507 # serv.action(channel,l2[i-n1].format(auteur).encode("utf8"))
508 # else:
509 # serv.privmsg(channel,l1[i].format(auteur).format(auteur).encode("utf8"))
510 # if is_good_action_trigger(action,mypseudo) and not channel in self.quiet_channels:
511 # l1,l2=config.good_action_answers,config.good_action_actions
512 # n1,n2=len(l1),len(l2)
513 # i=random.randrange(n1+n2)
514 # if i>=n1:
515 # serv.action(channel,l2[i-n1].format(auteur).format(auteur).encode("utf8"))
516 # else:
517 # serv.privmsg(channel,l1[i].format(auteur).format(auteur).encode("utf8"))
518
519 def on_kick(self,serv,ev):
520 auteur = irclib.nm_to_n(ev.source())
521 channel = ev.target()
522 victime = ev.arguments()[0]
523 raison = ev.arguments()[1]
524 if victime==self.nick:
525 log(self.serveur,"%s kické de %s par %s (raison : %s)" %(victime,channel,auteur,raison))
526 time.sleep(2)
527 serv.join(channel)
528 username = irclib.nm_to_u(ev.source()).lower()
529 print ev.source()
530 print channel, username
531 if channel == "#déprime" and "peb" in username or "becue" in username:
532 time.sleep(5)
533 serv.kick(auteur, "Va abuser de tes droits ailleurs !")
534
535 def kicker(self, chan, pseudo, raison=None):
536 if raison==None:
537 raison = config.kick_default_reason
538 self.serv.kick(chan,pseudo,raison)
539
540 def quitter(self,chan,leave_message=None):
541 if leave_message==None:
542 leave_message=random.choice(config.leave_messages)
543 self.serv.part(chan,message=leave_message.encode("utf8"))
544
545 def mourir(self):
546 quit_message=random.choice(config.quit_messages)
547 self.die(msg=quit_message.encode("utf8"))
548
549 def _getnick(self):
550 return self.serv.get_nickname()
551 nick=property(_getnick)
552
553 def reload(self, auteur=None):
554 reload(config)
555 if auteur in [None, "SIGHUP"]:
556 towrite = "Config reloaded" + " (SIGHUP received)"*(auteur == "SIGHUP")
557 for to in config.report_bugs_to:
558 self.serv.privmsg(to, towrite)
559 log(self.serveur, towrite)
560 else:
561 self.serv.privmsg(auteur,"Config reloaded")
562
563 def start_as_daemon(self, outfile):
564 sys.stderr = Logger(outfile)
565 self.start()
566
567
568 class Logger(object):
569 """Pour écrire ailleurs que sur stdout"""
570 def __init__(self, filename="themis.full.log"):
571 self.filename = filename
572
573 def write(self, message):
574 f = open(self.filename, "a")
575 f.write(message)
576 f.close()
577
578
579 if __name__=="__main__":
580 import sys
581 if len(sys.argv)==1:
582 print "Usage : themis.py <serveur> [--debug] [--no-output] [--daemon [--pidfile]] [--outfile]"
583 print " --outfile sans --no-output ni --daemon n'a aucun effet"
584 exit(1)
585 serveur=sys.argv[1]
586 if "--daemon" in sys.argv:
587 thisfile = os.path.realpath(__file__)
588 thisdirectory = thisfile.rsplit("/", 1)[0]
589 os.chdir(thisdirectory)
590 daemon = True
591 else:
592 daemon = False
593 if "debug" in sys.argv or "--debug" in sys.argv:
594 debug=True
595 else:
596 debug=False
597 if "--no-output" in sys.argv or "--daemon" in sys.argv:
598 outfile = "/var/log/bots/themis.full.log"
599 for arg in sys.argv:
600 arg = arg.split("=")
601 if arg[0].strip('-') in ["out", "outfile", "logfile"]:
602 outfile = arg[1]
603 sys.stdout = Logger(outfile)
604 serveurs={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
605 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"}
606 try:
607 serveur=serveurs[serveur]
608 except KeyError:
609 print "Server Unknown : %s"%(serveur)
610 exit(404)
611 themis=Themis(serveur,debug)
612 # Si on reçoit un SIGHUP, on reload la config
613 def sighup_handler(signum, frame):
614 themis.reload("SIGHUP")
615 signal.signal(signal.SIGHUP, sighup_handler)
616 if daemon:
617 child_pid = os.fork()
618 if child_pid == 0:
619 os.setsid()
620 themis.start_as_daemon(outfile)
621 else:
622 # on enregistre le pid de themis
623 pidfile = "/var/run/bots/themis.pid"
624 for arg in sys.argv:
625 arg = arg.split("=")
626 if arg[0].strip('-') in ["pidfile"]:
627 pidfile = arg[1]
628 f = open(pidfile, "w")
629 f.write("%s\n" % child_pid)
630 f.close()
631 else:
632 themis.start()
633