]> gitweb.pimeys.fr Git - bots/saturnin.git/blob - saturnin.py
Oubli de "Aw crap..."
[bots/saturnin.git] / saturnin.py
1 #!/usr/bin/python
2 # -*- encoding: utf-8 -*-
3
4 # Codé par 20-100
5
6 # Un bot IRC pour remplacer le canard.
7 # parce que le canard, c'est le bien et que braice ne pong pas
8
9 import threading
10 import random
11 import time
12 import socket, ssl, json
13 import pickle
14 import re
15 import os
16 import signal
17 import sys
18 from commands import getstatusoutput as ex
19
20 # Oui, j'ai recodé ma version d'irclib pour pouvoir rattrapper les SIGHUP
21 sys.path.insert(0, "/home/vincent/scripts/python-myirclib")
22 import irclib
23 import ircbot
24
25 # on récupère la config
26 import config
27
28
29
30 def get_config_logfile(serveur):
31 serveurs={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
32 return config.logfile_template%(serveurs[serveur])
33
34 def log(serveur,channel,auteur=None,message=None):
35 f=open(get_config_logfile(serveur),"a")
36 if auteur==message==None:
37 # alors c'est que c'est pas un channel mais juste une ligne de log
38 chain="%s %s"%(time.strftime("%F %T"),channel)
39 else:
40 chain="%s [%s:%s] %s"%(time.strftime("%F %T"),channel,auteur,message)
41 f.write(chain+"\n")
42 if config.debug_stdout:
43 print chain
44 f.close()
45
46 def is_something(chain,matches,avant=u".*(?:^| )",apres=u"(?:$|\.| |,|;).*",case_sensitive=False,debug=False):
47 if case_sensitive:
48 chain=unicode(chain,"utf8")
49 else:
50 chain=unicode(chain,"utf8").lower()
51 allmatches="("+"|".join(matches)+")"
52 reg=(avant+allmatches+apres).lower()
53 o=re.match(reg,chain)
54 return o
55
56 regexp_pan = re.compile(u".*(" + "|".join(config.killwords) + u").*")
57 def is_pan(chain):
58 return regexp_pan.match(unicode(chain,"utf8").lower())
59
60 class UnicodeBotError(Exception):
61 pass
62 def bot_unicode(chain):
63 try:
64 unicode(chain,"utf8")
65 except UnicodeDecodeError as exc:
66 raise UnicodeBotError
67
68 class Saturnin(ircbot.SingleServerIRCBot):
69 def __init__(self,serveur,debug=False):
70 temporary_pseudo=config.irc_pseudo+str(random.randrange(10000,100000))
71 ircbot.SingleServerIRCBot.__init__(self, [(serveur, 6667)],
72 temporary_pseudo,"Coin ? ©braice [mais 'faut frapper 20-100]", 10)
73 self.debug=debug
74 self.serveur=serveur
75 self.overops=config.overops
76 self.ops=self.overops+config.ops
77 self.chanlist=config.chanlist
78 self.stay_channels=config.stay_channels
79 self.quiet_channels=config.quiet_channels
80 self.play_channels=config.play_channels
81 self.status = { chan : [0, None] for chan in self.play_channels }
82 # 0 : pas de spawn prévu
83 # 1 : un spawn prévu,
84 # avec en deuxième paramètre le timestamp du moment où il a été déclenché (pas du moment où il se fera)
85 # 2 : alive
86 self.last_perdu=0
87
88 def give_me_my_pseudo(self,serv):
89 serv.privmsg("NickServ","RECOVER %s %s"%(config.irc_pseudo,config.irc_password))
90 serv.privmsg("NickServ","RELEASE %s %s"%(config.irc_pseudo,config.irc_password))
91 time.sleep(0.3)
92 serv.nick(config.irc_pseudo)
93
94 def on_welcome(self, serv, ev):
95 self.serv=serv # ça serv ira :)
96 self.give_me_my_pseudo(serv)
97 serv.privmsg("NickServ","IDENTIFY %s"%(config.irc_password))
98 log(self.serveur,"Connected")
99 if self.debug:
100 self.chanlist = self.play_channels = ["#bot"]
101 self.status = { chan : [0, 0] for chan in self.play_channels }
102 for c in self.chanlist:
103 log(self.serveur,"JOIN %s"%(c))
104 serv.join(c)
105 if c in self.play_channels:
106 spawn_delay = random.randrange(*config.spawn_delays)
107 self.spawn(c, time.time(), spawn_delay)
108
109 def pourmoi(self, serv, message):
110 """renvoie (False,lemessage) ou (True, le message amputé de "pseudo: ")"""
111 pseudo=self.nick
112 size=len(pseudo)
113 if message[:size]==pseudo and len(message)>size and message[size]==":":
114 return (True,message[size+1:].lstrip(" "))
115 else:
116 return (False,message)
117
118 def on_privmsg(self, serv, ev):
119 message=ev.arguments()[0]
120 auteur = irclib.nm_to_n(ev.source())
121 try:
122 test=bot_unicode(message)
123 except UnicodeBotError:
124 if config.utf8_trigger:
125 serv.privmsg(auteur, random.choice(config.utf8_fail_answers).encode("utf8"))
126 return
127 message=message.split()
128 cmd=message[0].lower()
129 notunderstood=False
130 if cmd=="help":
131 helpdico={"help":["""HELP <commande>
132 Affiche de l'aide sur la commande""",None,None],
133 "score":["""SCORE
134 Affiche votre score""", None, None],
135 "scores":["""SCORES
136 Afficher tous les scores""", None, None],
137 "join": [None, """JOIN <channel>
138 Me fait rejoindre le channel""",None],
139 "leave": [None,"""LEAVE <channel>
140 Me fait quitter le channel (sauf s'il est dans ma stay_list).""",None],
141 "quiet": [None,"""QUIET <channel>
142 Me rend silencieux sur le channel.""",None],
143 "noquiet": [None,"""NOQUIET <channel>
144 Me rend la parole sur le channel.""",None],
145 "play": [None, """PLAY
146 Passe un channel en mode "jouer" """,None],
147 "noplay": [None, """NOPLAY
148 Passe un channel en mode "ne pas jouer" """,None],
149 "SPAWN": [None, """SPAWN <channel>
150 Me fait spawner sur le channel.""",None],
151 "reload": [None,"""RELOAD
152 Recharge la configuration.""",None],
153 "say": [None,None,"""SAY <channel> <message>
154 Me fait parler sur le channel."""],
155 "do": [None,None,"""DO <channel> <action>
156 Me fait faitre une action (/me) sur le channel."""],
157 "stay": [None,None,"""STAY <channel>
158 Ajoute le channel à ma stay_list."""],
159 "nostay": [None,None,"""NOSTAY <channel>
160 Retire le channel de ma stay_list."""],
161 "ops": [None,None,"""OPS
162 Affiche la liste des ops."""],
163 "overops": [None,None,"""OVEROPS
164 Affiche la liste des overops."""],
165 "kick": [None,None,"""KICK <channel> <pseudo> [<raison>]
166 Kicke <pseudo> du channel (Il faut bien entendu que j'y sois op)."""],
167 "die": [None,None,"""DIE
168 Me déconnecte du serveur IRC."""]
169 }
170 helpmsg_default="Liste des commandes disponibles :\nHELP SCORE SCORES"
171 helpmsg_ops=" JOIN LEAVE QUIET NOQUIET PLAY NOPLAY SPAWN"
172 helpmsg_overops=" SAY DO STAY NOSTAY OPS OVEROPS KICK DIE"
173 op,overop=auteur in self.ops, auteur in self.overops
174 if len(message)==1:
175 helpmsg=helpmsg_default
176 if op:
177 helpmsg+=helpmsg_ops
178 if overop:
179 helpmsg+=helpmsg_overops
180 else:
181 helpmsgs=helpdico.get(message[1].lower(),["Commande inconnue.",None,None])
182 helpmsg=helpmsgs[0]
183 if op and helpmsgs[1]:
184 if helpmsg:
185 helpmsg+="\n"+helpmsgs[1]
186 else:
187 helpmsg=helpmsgs[1]
188 if overop and helpmsgs[2]:
189 if helpmsg:
190 helpmsg+="\n"+helpmsgs[2]
191 else:
192 helpmsg=helpmsgs[2]
193 for ligne in helpmsg.split("\n"):
194 serv.privmsg(auteur,ligne)
195 elif cmd=="join":
196 if auteur in self.ops:
197 if len(message)>1:
198 if message[1] in self.chanlist:
199 serv.privmsg(auteur,"Je suis déjà sur %s"%(message[1]))
200 else:
201 serv.join(message[1])
202 self.chanlist.append(message[1])
203 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
204 log(self.serveur,"priv",auteur," ".join(message))
205 else:
206 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
207 else:
208 notunderstood=True
209 elif cmd=="leave":
210 if auteur in self.ops and len(message)>1:
211 if message[1] in self.chanlist:
212 if not (message[1] in self.stay_channels) or auteur in self.overops:
213 self.quitter(message[1]," ".join(message[2:]))
214 self.chanlist.remove(message[1])
215 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
216 else:
217 serv.privmsg(auteur,"Non, je reste !")
218 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
219 else:
220 serv.privmsg(auteur,"Je ne suis pas sur %s"%(message[1]))
221 else:
222 notunderstood=True
223 elif cmd=="stay":
224 if auteur in self.overops:
225 if len(message)>1:
226 if message[1] in self.stay_channels:
227 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
228 serv.privmsg(auteur,"Je stay déjà sur %s."%(message[1]))
229 else:
230 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
231 self.stay_channels.append(message[1])
232 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
233 else:
234 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
235 else:
236 notunderstood=True
237 elif cmd=="nostay":
238 if auteur in self.overops:
239 if len(message)>1:
240 if message[1] in self.stay_channels:
241 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
242 self.stay_channels.remove(message[1])
243 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
244 else:
245 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
246 serv.privmsg(auteur,"Je ne stay pas sur %s."%(message[1]))
247
248 else:
249 notunderstood=True
250 elif cmd=="die":
251 if auteur in self.overops:
252 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
253 self.mourir()
254 else:
255 notunderstood=True
256 elif cmd=="quiet":
257 if auteur in self.ops:
258 if len(message)>1:
259 if message[1] in self.quiet_channels:
260 serv.privmsg(auteur,"Je me la ferme déjà sur %s"%(message[1]))
261 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
262 else:
263 self.quiet_channels.append(message[1])
264 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
265 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
266 else:
267 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
268 else:
269 notunderstood=True
270 elif cmd=="noquiet":
271 if auteur in self.ops:
272 if len(message)>1:
273 if message[1] in self.quiet_channels:
274 self.quiet_channels.remove(message[1])
275 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
276 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
277 else:
278 serv.privmsg(auteur,"Je ne me la ferme pas sur %s."%(message[1]))
279 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
280 else:
281 notunderstood=True
282 elif cmd=="play":
283 if auteur in self.ops:
284 if len(message)>1:
285 if message[1] in self.play_channels:
286 serv.privmsg(auteur,"Je play déjà sur %s."%(message[1]))
287 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
288 else:
289 self.play_channels.append(message[1])
290 self.spawn(message[1], 1)
291 serv.privmsg(auteur,"Play channels : "+" ".join(self.play_channels))
292 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
293 else:
294 serv.privmsg(auteur,"Play channels : "+" ".join(self.play_channels))
295 else:
296 notunderstood=True
297 elif cmd=="noplay":
298 if auteur in self.ops:
299 if len(message)>1:
300 if message[1] in self.play_channels:
301 self.play_channels.remove(message[1])
302 serv.privmsg(auteur,"Play channels : "+" ".join(self.play_channels))
303 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
304 else:
305 serv.privmsg(auteur,"Je ne play pas sur %s."%(message[1]))
306 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
307 else:
308 notunderstood=True
309 elif cmd=="spawn":
310 if auteur in self.ops:
311 if len(message)>1:
312 if message[1] in self.play_channels:
313 # Le plus pratique pour pas s'embêter c'est de mettre un
314 # delay d'une seconde, comme ça .spawn() fait le boulot
315 self.spawn(message[1], time.time(), 1)
316 else:
317 serv.privmsg(auteur, "Je ne joue pas sur %s" % message[1])
318 else:
319 serv.privmsg(auteur, "Syntaxe : SPAWN <channel>")
320 else:
321 notunderstood=True
322 elif cmd=="say":
323 if auteur in self.overops and len(message)>2:
324 serv.privmsg(message[1]," ".join(message[2:]))
325 log(self.serveur,"priv",auteur," ".join(message))
326 elif len(message)<=2:
327 serv.privmsg(auteur,"Syntaxe : SAY <channel> <message>")
328 else:
329 notunderstood=True
330 elif cmd=="do":
331 if auteur in self.overops and len(message)>2:
332 serv.action(message[1]," ".join(message[2:]))
333 log(self.serveur,"priv",auteur," ".join(message))
334 elif len(message)<=2:
335 serv.privmsg(auteur,"Syntaxe : DO <channel> <action>")
336 else:
337 notunderstood=True
338 elif cmd=="kick":
339 if auteur in self.overops and len(message)>2:
340 serv.kick(message[1],message[2]," ".join(message[3:]))
341 log(self.serveur,"priv",auteur," ".join(message))
342 elif len(message)<=2:
343 serv.privmsg(auteur,"Syntaxe : KICK <channel> <pseudo> [<raison>]")
344 else:
345 notunderstood=True
346 elif cmd=="ops":
347 if auteur in self.overops:
348 serv.privmsg(auteur," ".join(self.ops))
349 else:
350 notunderstood=True
351 elif cmd=="overops":
352 if auteur in self.overops:
353 serv.privmsg(auteur," ".join(self.overops))
354 else:
355 notunderstood=True
356 elif cmd=="reload":
357 if auteur in self.ops:
358 reload(config)
359 serv.privmsg(auteur,"done")
360 else:
361 notunderstood=True
362 elif cmd=="score":
363 if len(message)>1:
364 if len(message) in [3,4] and message[1].lower()=="transfert":
365 scores=self.get_scores()
366 de,to=auteur,message[2]
367 value=scores.get(de,0)
368 if len(message)==4:
369 try:
370 asked=int(message[3])
371 except ValueError:
372 serv.privmsg(auteur,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
373 return
374 else:
375 asked=value
376 if value==0:
377 serv.privmsg(auteur,"Vous n'avez pas de points")
378 return
379 elif asked<=0:
380 serv.privmsg(auteur,"Bien tenté…")
381 return
382 elif asked>value:
383 serv.privmsg(auteur,"Vous n'avez que %s points"%(value))
384 return
385 else:
386 self.add_score(de,-asked)
387 self.add_score(to,asked)
388 serv.privmsg(auteur,"Transfert de %s points de %s à %s"%(asked,de,to))
389 else:
390 serv.privmsg(auteur,"Syntaxe : SCORE TRANSFERT <pseudo> [<n>]")
391 else:
392 self.sendscore(auteur)
393 elif cmd=="scores":
394 if len(message)==1:
395 self.sendscores(auteur)
396 elif auteur in self.overops:
397 souscmd=message[1].lower()
398 if souscmd=="del":
399 if len(message)==3:
400 todelete=message[2]
401 scores=self.get_scores()
402 if scores.has_key(todelete):
403 del scores[todelete]
404 self.save_scores(scores)
405 serv.privmsg(auteur,"Score de %s supprimé"%(todelete))
406 else:
407 serv.privmsg(auteur,"Ce score n'existe pas : %s"%(todelete))
408 else:
409 serv.privmsg(auteur,"Syntaxe : SCORES DEL <pseudo>")
410 elif souscmd in ["add","sub"]:
411 if len(message)==4:
412 toadd,val=message[2],message[3]
413 try:
414 val=int(val)
415 except ValueError:
416 serv.privmsg(auteur,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
417 return
418 if souscmd=="sub":
419 val=-val
420 self.add_score(toadd,val)
421 serv.privmsg(auteur,"Done")
422 else:
423 serv.privmsg(auteur,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
424 else:
425 serv.privmsg(auteur,"Syntaxe : SCORES {DEL|ADD|SUB} <pseudo> [<n>]")
426 else:
427 notunderstood=True
428 else:
429 notunderstood=True
430 if notunderstood:
431 serv.privmsg(auteur,"Je n'ai pas compris. Essayez HELP…")
432
433 def sendscore(self, to):
434 self.serv.privmsg(to, "Votre score : %s"%(self.get_scores().get(to,0)) )
435
436 def sendscores(self, to):
437 scores=self.get_scores().items()
438 # trie par score
439 scores.sort(lambda x,y:cmp(x[1],y[1]))
440 scores.reverse()
441 self.serv.privmsg(to, "Scores by score : "+" ; ".join(["%s %s"%(i[0],i[1]) for i in scores]))
442 # trie par pseudo
443 scores.sort(lambda x,y:cmp(x[0].lower(),y[0].lower()))
444 self.serv.privmsg(to, "Scores by pseudo : "+" ; ".join(["%s %s"%(i[0],i[1]) for i in scores]))
445
446 def on_pubmsg(self, serv, ev):
447 auteur = irclib.nm_to_n(ev.source())
448 channel = ev.target()
449 message = ev.arguments()[0]
450 try:
451 test=bot_unicode(message)
452 except UnicodeBotError:
453 if config.utf8_trigger and not channel in self.quiet_channels:
454 serv.privmsg(channel, (u"%s: %s"%(auteur,random.choice(config.utf8_fail_answers))).encode("utf8"))
455 return
456 pour_moi,message=self.pourmoi(serv,message)
457 if pour_moi and message.split()!=[]:
458 cmd=message.split()[0].lower()
459 try:
460 args=" ".join(message.split()[1:])
461 except:
462 args=""
463 if cmd in ["meurs","die","crève"]:
464 if auteur in self.overops:
465 log(self.serveur,channel,auteur,message+"[successful]")
466 self.mourir()
467 else:
468 serv.privmsg(channel,("%s: %s"%(auteur,random.choice(config.quit_fail_messages))).encode("utf8"))
469 log(self.serveur,channel,auteur,message+"[failed]")
470 elif cmd in ["part","leave","dégage","va-t-en","tut'tiresailleurs,c'estmesgalets"]:
471 if auteur in self.ops and (not (channel in self.stay_channels)
472 or auteur in self.overops):
473 self.quitter(channel)
474 log(self.serveur,channel,auteur,message+"[successful]")
475 if channel in self.chanlist:
476 self.chanlist.remove(channel)
477 else:
478 serv.privmsg(channel,("%s: %s"%(auteur,random.choice(config.leave_fail_messages))).encode("utf8"))
479 log(self.serveur,channel,auteur,message+"[failed]")
480 elif cmd == "score":
481 self.sendscore(auteur)
482 elif cmd == "scores":
483 self.sendscores(auteur)
484 else:
485 if is_pan(message):
486 self.shot(channel, auteur)
487
488 def on_action(self, serv, ev):
489 action = ev.arguments()[0]
490 auteur = irclib.nm_to_n(ev.source())
491 channel = ev.target()
492 #~ try:
493 #~ test=bot_unicode(action)
494 #~ except UnicodeBotError:
495 #~ if config.utf8_trigger and not channel in self.quiet_channels:
496 #~ serv.privmsg(channel, (u"%s: %s"%(auteur,random.choice(config.utf8_fail_answers))).encode("utf8"))
497 #~ return
498 #~ mypseudo=self.nick
499
500 def on_kick(self,serv,ev):
501 auteur = irclib.nm_to_n(ev.source())
502 channel = ev.target()
503 victime = ev.arguments()[0]
504 raison = ev.arguments()[1]
505 if victime==self.nick:
506 log(self.serveur,"%s kické de %s par %s (raison : %s)" %(victime,channel,auteur,raison))
507 time.sleep(2)
508 serv.join(channel)
509 #~ l1,l2=config.kick_answers,config.kick_actions
510 #~ n1,n2=len(l1),len(l2)
511 #~ i=random.randrange(n1+n2)
512 #~ if i>=n1:
513 #~ serv.action(channel,l2[i-n1].format(auteur).encode("utf8"))
514 #~ else:
515 #~ serv.privmsg(channel,l1[i].format(auteur).encode("utf8"))
516
517 def spawn(self, channel, timestamp, delay=0):
518 if channel in self.play_channels:
519 if delay>0:
520 self.serv.execute_delayed(delay, self.spawn, (channel, timestamp))
521 self.status[channel] = [1, timestamp]
522 else:
523 # on teste le timestamp pour pas s'emmêler dans les spawn
524 infos = self.status.get(channel, [0,0])
525 if infos == [1, timestamp]:
526 spawn_sentence = random.choice(config.canards) + random.choice(config.spawn_sentences)
527 self.serv.privmsg(channel, spawn_sentence.encode("utf8"))
528 self.status[channel] = [2, timestamp]
529 times_up_delay = random.randrange(*config.times_up_delays)
530 self.serv.execute_delayed(times_up_delay, self.too_slow, (channel, timestamp))
531
532 def too_slow(self, channel, timestamp):
533 infos = self.status.get(channel, [0,0])
534 if infos == [2, timestamp]:
535 self.serv.privmsg(channel, random.choice(config.times_up_sentences).encode("utf8"))
536 respawn_delay = random.randrange(*config.spawn_delays)
537 self.spawn(channel, time.time(), respawn_delay)
538
539 def shot(self, channel, auteur):
540 if self.status.get(channel, [0, 0])[0] == 2:
541 succeed = random.randrange(0,101) > config.proba_miss
542 if succeed:
543 self.serv.privmsg(channel, random.choice(config.killed_templates).format(auteur).encode("utf8"))
544 self.add_score(auteur, 1)
545 if random.randrange(0, 101) < config.proba_killed_sentence:
546 self.serv.privmsg(channel, random.choice(config.killed_sentences).encode("utf8"))
547 respawn_delay = random.randrange(*config.spawn_delays)
548 self.spawn(channel, time.time(), respawn_delay)
549 else:
550 self.serv.privmsg(channel, random.choice(config.miss_templates).format(auteur).encode("utf8"))
551 if random.randrange(0,101) < config.proba_miss_sentence:
552 self.serv.privmsg(channel, random.choice(config.miss_sentences).encode("utf8"))
553
554 def quitter(self,chan,leave_message=None):
555 if leave_message==None:
556 leave_message=random.choice(config.leave_messages)
557 self.serv.part(chan,message=leave_message.encode("utf8"))
558
559 def mourir(self):
560 quit_message=random.choice(config.quit_messages)
561 self.die(msg=quit_message.encode("utf8"))
562
563 def get_scores(self):
564 f=open(config.score_file)
565 scores=pickle.load(f)
566 f.close()
567 return scores
568
569 def add_score(self, pseudo, value):
570 scores=self.get_scores()
571 if scores.has_key(pseudo):
572 scores[pseudo]+=value
573 else:
574 scores[pseudo]=value
575 self.save_scores(scores)
576
577 def save_scores(self,scores):
578 f=open(config.score_file,"w")
579 pickle.dump(scores,f)
580 f.close()
581
582 def _getnick(self):
583 return self.serv.get_nickname()
584 nick=property(_getnick)
585
586 def start_as_daemon(self, outfile):
587 sys.stderr = Logger(outfile)
588 self.start()
589
590
591 class Logger(object):
592 """Pour écrire ailleurs que sur stdout"""
593 def __init__(self, filename="saturnin.full.log"):
594 self.filename = filename
595
596 def write(self, message):
597 f = open(self.filename, "a")
598 f.write(message)
599 f.close()
600
601
602 if __name__=="__main__":
603 import sys
604 if len(sys.argv)==1:
605 print "Usage : saturnin.py <serveur> [--debug] [--no-output] [--daemon [--pidfile]] [--outfile]"
606 print " --outfile sans --no-output ni --daemon n'a aucun effet"
607 exit(1)
608 serveur=sys.argv[1]
609 if "--daemon" in sys.argv:
610 thisfile = os.path.realpath(__file__)
611 thisdirectory = thisfile.rsplit("/", 1)[0]
612 os.chdir(thisdirectory)
613 daemon = True
614 else:
615 daemon = False
616 if "debug" in sys.argv or "--debug" in sys.argv:
617 debug=True
618 else:
619 debug=False
620 if "--no-output" in sys.argv or "--daemon" in sys.argv:
621 outfile = "/var/log/bots/saturnin.full.log"
622 for arg in sys.argv:
623 arg = arg.split("=")
624 if arg[0].strip('-') in ["out", "outfile", "logfile"]:
625 outfile = arg[1]
626 sys.stdout = Logger(outfile)
627 if "--quiet" in sys.argv:
628 config.debug_stdout=False
629 serveurs={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
630 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"}
631 try:
632 serveur=serveurs[serveur]
633 except KeyError:
634 print "Server Unknown : %s"%(serveur)
635 exit(404)
636 saturnin = Saturnin(serveur,debug)
637 if daemon:
638 child_pid = os.fork()
639 if child_pid == 0:
640 os.setsid()
641 saturnin.start_as_daemon(outfile)
642 else:
643 # on enregistre le pid de saturnin
644 pidfile = "/var/run/bots/saturnin.pid"
645 for arg in sys.argv:
646 arg = arg.split("=")
647 if arg[0].strip('-') in ["pidfile"]:
648 pidfile = arg[1]
649 f = open(pidfile, "w")
650 f.write("%s\n" % child_pid)
651 f.close()
652 else:
653 saturnin.start()
654