]> gitweb.pimeys.fr Git - bots/deconnaisseur.git/blob - deconnaisseur.py
Allez, fonce, baudet ! (avec la bonne pontuation)
[bots/deconnaisseur.git] / deconnaisseur.py
1 #!/usr/bin/python
2 # -*- coding:utf8 -*-
3
4 # Codé par 20-100 le 23/04/12
5
6 # Un bot IRC qui sort des déconnaissances
7
8 import irclib
9 import ircbot
10 import threading
11 import random
12 import time
13 import pickle
14 import re
15 from remplace_accents import remplace_accents
16
17 config_password="PatrickSébastien"
18 config_pseudo="deconnaisseur"
19 config_chanlist=["#bot","#flood"]
20 config_play_channels=["#flood"]
21 config_stay_channels=["#flood","#bot"]
22 config_overops=["[20-100]","[20-100]_","PEB"]
23 config_ops=["Nit","Eguel","Harry"]
24
25 config_source_file="deconnaissances.txt"
26 config_played_file_template="played.%s.txt" #il faut rajouter le nom du serveur
27 def get_config_played_file(serveur):
28 serveurs={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
29 return config_played_file_template%(serveurs[serveur])
30 ttrig=120 #time trigger (normalement 120, mais diminué pour les tests)
31 Ttrig=600 #between two enigms
32 config_time_incompressible=15 #on peut pas retrigger en dessous de ce temps (60)
33 config_time_incompressible_clue=60 #on peut pas forcer la demande d'indice en dessous
34
35 config_score_file="scores.pickle"
36
37 config_tag_triggers=[u"t(|a)g",u"ta gueule",u"la ferme",u"ferme( |-)la",u"tais-toi",u"chut"]
38 config_tag_actions=[u"se tait",u"ferme sa gueule",u"se la ferme",u"la ferme"]
39 config_tag_answers=[u"J'me tais si j'veux !",
40 u"Je t'entends pas :°",
41 u"Héhé, try again",
42 u"Non, j'ai pas envie",
43 u"Peut-être quand toi tu la fermeras, et encore…"]
44
45 config_level2=[]
46 config_level3=["[20-100]","Petite-Peste","PEB"]
47
48 class UnicodeBotError(Exception):
49 pass
50 def bot_unicode(chain):
51 try:
52 unicode(chain,"utf8")
53 except UnicodeDecodeError:
54 raise UnicodeBotError
55
56 def log(serveur,channel="prout",auteur=None,message=None):
57 #f=open(config_logfile,"a")
58 #if auteur==message==None:
59 # chain=channel
60 #else:
61 # chain="%s [%s:%s] %s"%(time.strftime("%T"),channel,auteur,message)
62 #f.write(chain+"\n")
63 #print chain
64 #f.close()
65 a=0 # does nothing
66
67
68 def reussi(message,answer,answer_regexp,auteur):
69 if auteur in config_level3:
70 return answer in message
71 if auteur in config_level2:
72 return remplace_accents(answer) in message
73 else:
74 if re.match(remplace_accents(answer_regexp).lower(),remplace_accents(message).lower()):
75 return True
76
77 def is_something(chain,matches,avant=u".*(?:^| )",apres=u"(?:$|\.| |,|;).*",case_sensitive=False,debug=False):
78 if case_sensitive:
79 chain=unicode(chain,"utf8")
80 else:
81 chain=unicode(chain,"utf8").lower()
82 allmatches="("+"|".join(matches)+")"
83 reg=(avant+allmatches+apres).lower()
84 o=re.match(reg,chain)
85 return o
86
87 def is_tag(chain):
88 return is_something(chain,config_tag_triggers)
89
90 class RefuseError(Exception):
91 pass
92
93 class Deconnaisseur(ircbot.SingleServerIRCBot):
94 def __init__(self,serveur,debug=False):
95 temporary_pseudo=config_pseudo+str(random.randrange(10000,100000))
96 ircbot.SingleServerIRCBot.__init__(self, [(serveur, 6667)],
97 temporary_pseudo,"Un bot irc.[flagellez 20-100, il le mérite]", 10)
98 self.debug=debug
99 self.serveur=serveur
100 self.overops=config_overops
101 self.ops=self.overops+config_ops
102 self.chanlist=config_chanlist
103 self.stay_channels=config_stay_channels
104 self.play_channels=config_play_channels
105 self.play_status={i:[0] for i in self.play_channels}
106 self.quiet_channels=[]
107
108 def give_me_my_pseudo(self,serv):
109 serv.privmsg("NickServ","RECOVER %s %s"%(config_pseudo,config_password))
110 serv.privmsg("NickServ","RELEASE %s %s"%(config_pseudo,config_password))
111 time.sleep(0.3)
112 serv.nick(config_pseudo)
113
114 def on_welcome(self, serv, ev):
115 self.give_me_my_pseudo(serv)
116 serv.privmsg("NickServ","identify %s"%(config_password))
117 log("Connected")
118 if self.debug:
119 self.chanlist=["#bot"]
120 self.play_channels=["#bot"]
121 for c in self.chanlist:
122 log("JOIN %s"%(c))
123 serv.join(c)
124 for c in self.play_channels:
125 token=time.time()-3600
126 self.play_status[c]=[0,token]
127 serv.execute_delayed(random.randrange(ttrig),self.start_enigme,(serv,c,token))
128
129 def start_enigme(self,serv,channel,token=None):
130 if self.play_status[channel][0]==0 and channel in self.play_channels:
131 ok="skip"
132 if token==self.play_status[channel][-1]:
133 ok="do_it"
134 if token==None:
135 if time.time() > self.play_status[channel][-1]+config_time_incompressible:
136 ok="do_it"
137 else:
138 ok="refuse"
139 if ok=="do_it":
140 enigme,indice,answer_reg,answer=self.get_enigme()
141 print "%s; %s; %s; %s"%(enigme, indice, answer_reg, answer)
142 serv.privmsg(channel,enigme.encode("utf8"))
143 token=time.time()
144 self.play_status[channel]=[1,enigme,indice,answer_reg,answer,token]
145 serv.execute_delayed(random.randrange(ttrig*3,ttrig*5),self.give_indice,(serv,channel,token))
146 elif ok=="refuse":
147 raise RefuseError
148 def give_indice(self,serv,channel,token):
149 if self.play_status[channel][0]==1:
150 if token==None:
151 # c'est donc que l'indice a été demandé
152 if self.play_status[channel][-1]+config_time_incompressible_clue<time.time():
153 token=self.play_status[channel][-1]
154 if self.play_status[channel][-1]==token:
155 indice=self.play_status[channel][2]
156 serv.privmsg(channel,"indice : %s"%(indice).encode("utf8"))
157 self.play_status[channel][0]=2
158 serv.execute_delayed(random.randrange(ttrig*1,ttrig*3),self.give_answer,(serv,channel,token))
159 def give_answer(self,serv,channel,token):
160 if self.play_status[channel][0]==2 and self.play_status[channel][-1]==token:
161 answer=self.play_status[channel][4]
162 serv.privmsg(channel,"C'était : %s"%(answer).encode("utf8"))
163 token=time.time()
164 self.play_status[channel]=[0,token]
165 serv.execute_delayed(random.randrange(Ttrig*5,Ttrig*10),self.start_enigme,(serv,channel,token))
166
167 def get_enigme(self):
168 # on récupère les déconnaissances
169 f=open(config_source_file)
170 t=f.read()
171 f.close()
172 l=re.findall("%\n(.*)\n(.*)\n(.*)\n(.*)\n(.*)\n",t)
173 dec={int(i[0]):list(i[1:]) for i in l if len(i)==5}
174 # on va chercher combien de fois elles ont été jouées
175 played_file=get_config_played_file(self.serveur)
176 f=open(played_file)
177 t=f.read()
178 f.close()
179 l=re.findall("(.*):(.*)",t)
180 played={int(i[0]):int(i[1]) for i in l}
181 # on récupère le nombre d'occurrences le plus faible
182 mini=min(played.values())
183 # on choisit un id dans ceux qui ont ce nombre d'occurences
184 id_choisi=random.choice([k for k,v in played.items() if v==mini])
185 enigme,indice,answer_reg,answer=dec[id_choisi]
186 # on incrémente la choisie
187 played[id_choisi]+=1
188 # on enregistre le played_file
189 f=open(played_file,"w")
190 f.write("\n".join(["%-3s : %s"%(k,v) for k,v in played.items()]))
191 f.close()
192 return enigme.decode("utf8"),indice.decode("utf8"),answer_reg.decode("utf8"),answer.decode("utf8")
193
194 def pourmoi(self, serv, message):
195 pseudo=serv.get_nickname()
196 size=len(pseudo)
197 if message[:size]==pseudo and len(message)>size and message[size]==":":
198 return (True,message[size+1:].strip(" "))
199 else:
200 return (False,message)
201
202 def on_privmsg(self, serv, ev):
203 message=ev.arguments()[0]
204 auteur = irclib.nm_to_n(ev.source())
205 try:
206 test=bot_unicode(message)
207 except UnicodeBotError:
208 serv.privmsg(auteur,
209 "Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…")
210 return
211 message=message.split()
212 cmd=message[0].lower()
213 notunderstood=False
214 if cmd=="help":
215 helpmsg_default="""Liste des commandes :
216 HELP Affiche ce message d'aide
217 SCORE Affiche ton score (SCORE TRANSFERT <pseudo> [<n>] pour transférer des points)
218 SCORES Affiche les scores"""
219 helpmsg_ops="""
220 JOIN Faire rejoindre un channel (sans paramètres, donne la liste des chans actuels)
221 LEAVE Faire quitter un channel
222 PLAY Passe un channel en mode "jouer"
223 NOPLAY Passe un channel en mode "ne pas jouer"
224 QUIET Se taire sur un channel
225 NOQUIET Opposé de QUIET"""
226 helpmsg_overops="""
227 SCORES {DEL|ADD|SUB} Tu veux un dessin ?
228 SAY Fais envoyer un message sur un chan ou à une personne
229 STAY Ignorera les prochains LEAVE pour un chan
230 NOSTAY Opposé de STAY
231 STATUS Montre l'état courant
232 DIE Mourir"""
233 helpmsg=helpmsg_default
234 if auteur in self.ops:
235 helpmsg+=helpmsg_ops
236 if auteur in self.overops:
237 helpmsg+=helpmsg_overops
238 for ligne in helpmsg.split("\n"):
239 serv.privmsg(auteur,ligne)
240 elif cmd=="join":
241 if auteur in self.ops:
242 if len(message)>1:
243 if message[1] in self.chanlist:
244 serv.privmsg(auteur,"Je suis déjà sur %s"%(message[1]))
245 else:
246 serv.join(message[1])
247 self.chanlist.append(message[1])
248 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
249 log("priv",auteur," ".join(message))
250 else:
251 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
252 else:
253 notunderstood=True
254 elif cmd=="leave":
255 if auteur in self.ops and len(message)>1:
256 if message[1] in self.chanlist:
257 if not (message[1] in self.stay_channels) or auteur in self.overops:
258 serv.part(message[1])
259 self.chanlist.remove(message[1])
260 log("priv",auteur," ".join(message)+"[successful]")
261 else:
262 serv.privmsg(auteur,"Non, je reste !")
263 log("priv",auteur," ".join(message)+"[failed]")
264 else:
265 serv.privmsg(auteur,"Je ne suis pas sur %s"%(message[1]))
266 else:
267 notunderstood=True
268 elif cmd=="stay":
269 if auteur in self.overops:
270 if len(message)>1:
271 if message[1] in self.stay_channels:
272 serv.privmsg(auteur,"Je stay déjà sur %s."%(message[1]))
273 log("priv",auteur," ".join(message)+"[failed]")
274 else:
275 self.stay_channels.append(message[1])
276 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
277 log("priv",auteur," ".join(message)+"[successful]")
278 else:
279 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
280 else:
281 notunderstood=True
282 elif cmd=="nostay":
283 if auteur in self.overops:
284 if len(message)>1:
285 if message[1] in self.stay_channels:
286 self.stay_channels.remove(message[1])
287 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
288 log("priv",auteur," ".join(message)+"[successful]")
289 else:
290 serv.privmsg(auteur,"Je ne stay pas sur %s."%(message[1]))
291 log("priv",auteur," ".join(message)+"[failed]")
292 else:
293 notunderstood=True
294 elif cmd=="play":
295 if auteur in self.ops:
296 if len(message)>1:
297 if message[1] in self.play_channels:
298 serv.privmsg(auteur,"Je play déjà sur %s."%(message[1]))
299 log("priv",auteur," ".join(message)+"[failed]")
300 else:
301 self.play_channels.append(message[1])
302 self.play_status[message[1]]=[0,time.time()-3600]
303 serv.privmsg(auteur,"Play channels : "+" ".join(self.play_channels))
304 log("priv",auteur," ".join(message)+"[successful]")
305 else:
306 serv.privmsg(auteur,"Play channels : "+" ".join(self.play_channels))
307 else:
308 notunderstood=True
309 elif cmd=="noplay":
310 if auteur in self.ops:
311 if len(message)>1:
312 if message[1] in self.play_channels:
313 self.play_channels.remove(message[1])
314 serv.privmsg(auteur,"Play channels : "+" ".join(self.play_channels))
315 log("priv",auteur," ".join(message)+"[successful]")
316 else:
317 serv.privmsg(auteur,"Je ne play pas sur %s."%(message[1]))
318 log("priv",auteur," ".join(message)+"[failed]")
319 else:
320 notunderstood=True
321 elif cmd=="quiet":
322 if auteur in self.ops:
323 if len(message)>1:
324 if message[1] in self.quiet_channels:
325 serv.privmsg(auteur,"Je me la ferme déjà sur %s"%(message[1]))
326 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
327 else:
328 self.quiet_channels.append(message[1])
329 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
330 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
331 else:
332 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
333 else:
334 notunderstood=True
335 elif cmd=="noquiet":
336 if auteur in self.ops:
337 if len(message)>1:
338 if message[1] in self.quiet_channels:
339 self.quiet_channels.remove(message[1])
340 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
341 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
342 else:
343 serv.privmsg(auteur,"Je ne me la ferme pas sur %s."%(message[1]))
344 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
345 else:
346 notunderstood=True
347 elif cmd in ["states","status"]:
348 if auteur in self.overops:
349 for k in self.play_status.keys():
350 serv.privmsg(auteur,(u"%s : %s"%(k,"; ".join([unicode(i) for i in self.play_status[k]]))).encode("utf8") )
351 elif cmd=="say":
352 if auteur in self.overops and len(message)>2:
353 serv.privmsg(message[1]," ".join(message[2:]))
354 log("priv",auteur," ".join(message))
355 elif len(message)<=2:
356 serv.privmsg(auteur,"Syntaxe : SAY <channel> <message>")
357 else:
358 notunderstood=True
359 elif cmd=="die":
360 if auteur in self.overops:
361 self.die()
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 serv.privmsg(auteur,"Votre score : %s"%(self.get_scores().get(auteur,0)) )
393 elif cmd=="scores":
394 if len(message)==1:
395 scores=self.get_scores().items()
396 # trie par score
397 scores.sort(lambda x,y:cmp(x[1],y[1]))
398 scores.reverse()
399 serv.privmsg(auteur,"Scores by score : "+" ; ".join(["%s %s"%(i[0],i[1]) for i in scores]))
400 # trie par pseudo
401 scores.sort(lambda x,y:cmp(x[0].lower(),y[0].lower()))
402 serv.privmsg(auteur,"Scores by pseudo : "+" ; ".join(["%s %s"%(i[0],i[1]) for i in scores]))
403 elif auteur in self.overops:
404 souscmd=message[1].lower()
405 if souscmd=="del":
406 if len(message)==3:
407 todelete=message[2]
408 scores=self.get_scores()
409 if scores.has_key(todelete):
410 del scores[todelete]
411 self.save_scores(scores)
412 serv.privmsg(auteur,"Score de %s supprimé"%(todelete))
413 else:
414 serv.privmsg(auteur,"Ce score n'existe pas : %s"%(todelete))
415 else:
416 serv.privmsg(auteur,"Syntaxe : SCORES DEL <pseudo>")
417 elif souscmd in ["add","sub"]:
418 if len(message)==4:
419 toadd,val=message[2],message[3]
420 try:
421 val=int(val)
422 except ValueError:
423 serv.privmsg(auteur,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
424 return
425 if souscmd=="sub":
426 val=-val
427 self.add_score(toadd,val)
428 serv.privmsg(auteur,"Done")
429 else:
430 serv.privmsg(auteur,"Syntaxe : SCORES {ADD|SUB} <pseudo> <n>")
431 else:
432 serv.privmsg(auteur,"Syntaxe : SCORES {DEL|ADD|SUB} <pseudo> [<n>]")
433 else:
434 notunderstood=True
435 else:
436 notunderstood=True
437 if notunderstood:
438 serv.privmsg(auteur,"Je n'ai pas compris. Essaye HELP…")
439
440 def on_pubmsg(self, serv, ev):
441 auteur = irclib.nm_to_n(ev.source())
442 canal = ev.target()
443 message = ev.arguments()[0]
444 try:
445 test=bot_unicode(message)
446 except UnicodeBotError:
447 if not canal in self.quiet_channels:
448 serv.privmsg(canal,
449 "%s: Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…"%(auteur))
450 return
451 tryother=False
452 pour_moi,message=self.pourmoi(serv,message)
453 if pour_moi and message.split()!=[]:
454 cmd=message.split()[0].lower()
455 try:
456 args=" ".join(message.split()[1:])
457 except:
458 args=""
459 if cmd in ["meurs","die","crève"]:
460 if auteur in self.overops:
461 self.die()
462 log(canal,auteur,message+"[successful]")
463 else:
464 serv.privmsg(canal,"%s: crève !"%(auteur))
465 log(canal,auteur,message+"[failed]")
466 if cmd in ["meur", "meurt","meurre","meurres"] and not canal in self.quiet_channels:
467 serv.privmsg(canal,'%s: Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)'%(auteur))
468 if cmd in ["part","leave","dégage"]:
469 if auteur in self.ops and (not (canal in self.stay_channels)
470 or auteur in self.overops):
471 serv.part(canal,message="Éjecté par %s"%(auteur))
472 log(canal,auteur,message+"[successful]")
473 self.chanlist.remove(canal)
474 else:
475 serv.privmsg(canal,"%s: Non, je reste !"%(auteur))
476 log(canal,auteur,message+"[failed]")
477
478 if cmd in ["deviens","pseudo"]:
479 if auteur in self.ops:
480 become=args
481 serv.nick(become)
482 log(canal,auteur,message+"[successful]")
483 if cmd in ["coucou"] and not canal in self.quiet_channels:
484 serv.privmsg(canal,"%s: coucou"%(auteur))
485 if cmd in ["ping"] and not canal in self.quiet_channels:
486 serv.privmsg(canal,"%s: pong"%(auteur))
487 if cmd in ["déconnaissance","deconnaissance","énigme","enigme","encore"]:
488 if canal in self.play_channels:
489 if self.play_status.get(canal,[-1])[0]==0:
490 try:
491 self.start_enigme(serv,canal)
492 except RefuseError:
493 serv.privmsg(canal,"%s: Je peux souffler une minute ?"%(auteur))
494 else:
495 serv.privmsg(canal,("%s: Rappel : %s"%(auteur,self.play_status[canal][1])).encode("utf8") )
496 else:
497 serv.privmsg(canal,"%s: pas ici…"%(auteur))
498 if cmd in ["score","!score"]:
499 serv.privmsg(auteur,"Votre score : %s"%(self.get_scores().get(auteur,0)) )
500 if cmd in ["scores","!scores"]:
501 scores=self.get_scores().items()
502 # trie par score
503 scores.sort(lambda x,y:cmp(x[1],y[1]))
504 scores.reverse()
505 serv.privmsg(auteur,"Scores by score : "+" ; ".join(["%s %s"%(i[0],i[1]) for i in scores]))
506 # trie par pseudo
507 scores.sort(lambda x,y:cmp(x[0].lower(),y[0].lower()))
508 serv.privmsg(auteur,"Scores by pseudo : "+" ; ".join(["%s %s"%(i[0],i[1]) for i in scores]))
509 if cmd=="indice" and canal in self.play_channels:
510 self.give_indice(serv,canal,None)
511 if is_tag(message) and not canal in self.quiet_channels:
512 if auteur in self.ops:
513 action=random.choice(config_tag_actions)
514 serv.action(canal,action.encode("utf8"))
515 self.quiet_channels.append(canal)
516 else:
517 answer=random.choice(config_tag_answers)
518 for ligne in answer.split("\n"):
519 serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
520 else:
521 tryother=True
522 else:
523 tryother=True
524 if tryother:
525 if self.play_status.get(canal,[-1])[0] in [1,2]:
526 answer_regexp=self.play_status[canal][3]
527 answer=self.play_status[canal][4]
528 if reussi(message.decode("utf8"),answer,answer_regexp,auteur):
529 serv.privmsg(canal,(u"%s: bravo ! (C'était %s)"%(auteur,answer)).encode("utf8"))
530 self.add_score(auteur,1)
531 token=time.time()
532 self.play_status[canal]=[0,token]
533 serv.execute_delayed(random.randrange(Ttrig*5,Ttrig*10),self.start_enigme,(serv,canal,token))
534 def get_scores(self):
535 f=open(config_score_file)
536 scores=pickle.load(f)
537 f.close()
538 return scores
539
540 def add_score(self,pseudo,value):
541 scores=self.get_scores()
542 if scores.has_key(pseudo):
543 scores[pseudo]+=value
544 else:
545 scores[pseudo]=value
546 self.save_scores(scores)
547
548 def save_scores(self,scores):
549 f=open(config_score_file,"w")
550 pickle.dump(scores,f)
551 f.close()
552
553 if __name__=="__main__":
554 import sys
555 if len(sys.argv)==1:
556 print "Usage : deconnaisseur.py <serveur> [--debug]"
557 exit(1)
558 serveur=sys.argv[1]
559 if "debug" in sys.argv or "--debug" in sys.argv:
560 debug=True
561 else:
562 debug=False
563 serveurs={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
564 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"}
565 try:
566 serveur=serveurs[serveur]
567 except KeyError:
568 print "Server Unknown : %s"%(serveur)
569 exit(404)
570 deco=Deconnaisseur(serveur,debug)
571 deco.start()