]> gitweb.pimeys.fr Git - bots/deconnaisseur.git/blobdiff - deconnaisseur.py
Allez, fonce, baudet ! (avec la bonne pontuation)
[bots/deconnaisseur.git] / deconnaisseur.py
index 9444519bc7ca3eb60f9c2931b55f3464cb306309..25176490a5262b50d850f8498489719990d5a093 100755 (executable)
@@ -12,6 +12,7 @@ import random
 import time
 import pickle
 import re
 import time
 import pickle
 import re
+from remplace_accents import remplace_accents
 
 config_password="PatrickSébastien"
 config_pseudo="deconnaisseur"
 
 config_password="PatrickSébastien"
 config_pseudo="deconnaisseur"
@@ -21,17 +22,29 @@ config_stay_channels=["#flood","#bot"]
 config_overops=["[20-100]","[20-100]_","PEB"]
 config_ops=["Nit","Eguel","Harry"]
 
 config_overops=["[20-100]","[20-100]_","PEB"]
 config_ops=["Nit","Eguel","Harry"]
 
-config_source_file_template="deconnaissances.%s.txt" #il faut rajouter le nom du serveur
-def get_config_source_file(serveur):
+config_source_file="deconnaissances.txt"
+config_played_file_template="played.%s.txt" #il faut rajouter le nom du serveur
+def get_config_played_file(serveur):
     serveurs={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
     serveurs={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
-    return config_source_file_template%(serveurs[serveur])
+    return config_played_file_template%(serveurs[serveur])
 ttrig=120 #time trigger (normalement 120, mais diminué pour les tests)
 Ttrig=600 #between two enigms
 ttrig=120 #time trigger (normalement 120, mais diminué pour les tests)
 Ttrig=600 #between two enigms
-config_time_incompressible=60 #on peut pas retrigger en dessous de ce temps (60)
+config_time_incompressible=15 #on peut pas retrigger en dessous de ce temps (60)
 config_time_incompressible_clue=60 #on peut pas forcer la demande d'indice en dessous
 
 config_score_file="scores.pickle"
 
 config_time_incompressible_clue=60 #on peut pas forcer la demande d'indice en dessous
 
 config_score_file="scores.pickle"
 
+config_tag_triggers=[u"t(|a)g",u"ta gueule",u"la ferme",u"ferme( |-)la",u"tais-toi",u"chut"]
+config_tag_actions=[u"se tait",u"ferme sa gueule",u"se la ferme",u"la ferme"]
+config_tag_answers=[u"J'me tais si j'veux !",
+u"Je t'entends pas :°",
+u"Héhé, try again",
+u"Non, j'ai pas envie",
+u"Peut-être quand toi tu la fermeras, et encore…"]
+
+config_level2=[]
+config_level3=["[20-100]","Petite-Peste","PEB"]
+
 class UnicodeBotError(Exception):
     pass
 def bot_unicode(chain):
 class UnicodeBotError(Exception):
     pass
 def bot_unicode(chain):
@@ -40,7 +53,7 @@ def bot_unicode(chain):
     except UnicodeDecodeError:
         raise UnicodeBotError
 
     except UnicodeDecodeError:
         raise UnicodeBotError
 
-def log(channel,auteur=None,message=None):
+def log(serveur,channel="prout",auteur=None,message=None):
     #f=open(config_logfile,"a")
     #if auteur==message==None:
     #    chain=channel
     #f=open(config_logfile,"a")
     #if auteur==message==None:
     #    chain=channel
@@ -52,17 +65,27 @@ def log(channel,auteur=None,message=None):
     a=0 # does nothing
 
 
     a=0 # does nothing
 
 
-def tolere(regexp):
-    """Renvoie une regexp plus tolérante"""
-    reg=unicode(regexp,"utf8").lower()
-    reg=reg.replace(u"á",u"(á|a)").replace(u"à",u"(à|a)").replace(u"â",u"(â|a)").replace(u"ä",u"(ä|a)")
-    reg=reg.replace(u"é",u"(é|e)").replace(u"è",u"(è|e)").replace(u"ê",u"(ê|e)").replace(u"ë",u"(ë|e)")
-    reg=reg.replace(u"í",u"(í|i)").replace(u"ì",u"(ì|i)").replace(u"î",u"(î|i)").replace(u"ï",u"(ï|i)")
-    reg=reg.replace(u"ó",u"(ó|o)").replace(u"ò",u"(ò|o)").replace(u"ô",u"(ô|o)").replace(u"ö",u"(ö|o)")
-    reg=reg.replace(u"ú",u"(ú|u)").replace(u"ù",u"(ù|u)").replace(u"û",u"(û|u)").replace(u"ü",u"(ü|u)")
-    reg=reg.replace(u"ý",u"(ý|y)").replace(u"ỳ",u"(ỳ|y)").replace(u"ŷ",u"(ŷ|y)").replace(u"ÿ",u"(ÿ|y)")
-    reg=reg.replace(u"œ",u"(œ|oe)").replace(u"æ",u"(æ|ae)")
-    return reg
+def reussi(message,answer,answer_regexp,auteur):
+    if auteur in config_level3:
+        return answer in message
+    if auteur in config_level2:
+        return remplace_accents(answer) in message
+    else:
+        if re.match(remplace_accents(answer_regexp).lower(),remplace_accents(message).lower()):
+            return True
+
+def is_something(chain,matches,avant=u".*(?:^| )",apres=u"(?:$|\.| |,|;).*",case_sensitive=False,debug=False):
+    if case_sensitive:
+        chain=unicode(chain,"utf8")
+    else:
+        chain=unicode(chain,"utf8").lower()
+    allmatches="("+"|".join(matches)+")"
+    reg=(avant+allmatches+apres).lower()
+    o=re.match(reg,chain)
+    return o
+
+def is_tag(chain):
+    return is_something(chain,config_tag_triggers)
 
 class RefuseError(Exception):
     pass
 
 class RefuseError(Exception):
     pass
@@ -80,6 +103,7 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
         self.stay_channels=config_stay_channels
         self.play_channels=config_play_channels
         self.play_status={i:[0] for i in self.play_channels}
         self.stay_channels=config_stay_channels
         self.play_channels=config_play_channels
         self.play_status={i:[0] for i in self.play_channels}
+        self.quiet_channels=[]
 
     def give_me_my_pseudo(self,serv):
         serv.privmsg("NickServ","RECOVER %s %s"%(config_pseudo,config_password))
 
     def give_me_my_pseudo(self,serv):
         serv.privmsg("NickServ","RECOVER %s %s"%(config_pseudo,config_password))
@@ -115,7 +139,7 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
             if ok=="do_it":
                 enigme,indice,answer_reg,answer=self.get_enigme()
                 print "%s; %s; %s; %s"%(enigme, indice, answer_reg, answer)
             if ok=="do_it":
                 enigme,indice,answer_reg,answer=self.get_enigme()
                 print "%s; %s; %s; %s"%(enigme, indice, answer_reg, answer)
-                serv.privmsg(channel,enigme)
+                serv.privmsg(channel,enigme.encode("utf8"))
                 token=time.time()
                 self.play_status[channel]=[1,enigme,indice,answer_reg,answer,token]
                 serv.execute_delayed(random.randrange(ttrig*3,ttrig*5),self.give_indice,(serv,channel,token))
                 token=time.time()
                 self.play_status[channel]=[1,enigme,indice,answer_reg,answer,token]
                 serv.execute_delayed(random.randrange(ttrig*3,ttrig*5),self.give_indice,(serv,channel,token))
@@ -129,36 +153,43 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
                     token=self.play_status[channel][-1]
             if self.play_status[channel][-1]==token:
                 indice=self.play_status[channel][2]
                     token=self.play_status[channel][-1]
             if self.play_status[channel][-1]==token:
                 indice=self.play_status[channel][2]
-                serv.privmsg(channel,"indice : %s"%(indice))
+                serv.privmsg(channel,"indice : %s"%(indice).encode("utf8"))
                 self.play_status[channel][0]=2
                 serv.execute_delayed(random.randrange(ttrig*1,ttrig*3),self.give_answer,(serv,channel,token))
     def give_answer(self,serv,channel,token):
         if self.play_status[channel][0]==2 and self.play_status[channel][-1]==token:
             answer=self.play_status[channel][4]
                 self.play_status[channel][0]=2
                 serv.execute_delayed(random.randrange(ttrig*1,ttrig*3),self.give_answer,(serv,channel,token))
     def give_answer(self,serv,channel,token):
         if self.play_status[channel][0]==2 and self.play_status[channel][-1]==token:
             answer=self.play_status[channel][4]
-            serv.privmsg(channel,"C'était : %s"%(answer))
+            serv.privmsg(channel,"C'était : %s"%(answer).encode("utf8"))
             token=time.time()
             self.play_status[channel]=[0,token]
             serv.execute_delayed(random.randrange(Ttrig*5,Ttrig*10),self.start_enigme,(serv,channel,token))
 
     def get_enigme(self):
             token=time.time()
             self.play_status[channel]=[0,token]
             serv.execute_delayed(random.randrange(Ttrig*5,Ttrig*10),self.start_enigme,(serv,channel,token))
 
     def get_enigme(self):
-        f=open(get_config_source_file(self.serveur))
+        # on récupère les déconnaissances
+        f=open(config_source_file)
         t=f.read()
         t=f.read()
+        f.close()
         l=re.findall("%\n(.*)\n(.*)\n(.*)\n(.*)\n(.*)\n",t)
         l=re.findall("%\n(.*)\n(.*)\n(.*)\n(.*)\n(.*)\n",t)
-        l=[list(i) for i in l if len(i)==5]
-        l.sort(lambda x,y: cmp(int(x[4]),int(y[4])))
+        dec={int(i[0]):list(i[1:]) for i in l if len(i)==5}
+        # on va chercher combien de fois elles ont été jouées
+        played_file=get_config_played_file(self.serveur)
+        f=open(played_file)
+        t=f.read()
+        f.close()
+        l=re.findall("(.*):(.*)",t)
+        played={int(i[0]):int(i[1]) for i in l}
         # on récupère le nombre d'occurrences le plus faible
         # on récupère le nombre d'occurrences le plus faible
-        mini=l[0][4]
-        # on garde que ceux qui ont le même nombre d'occurrences
-        l_mini=[en for en in l if en[4]==mini]
-        # on tire au hasard dedans
-        choisi=random.randrange(len(l_mini))
-        enigme,indice,answer_reg,answer,_=l_mini[choisi]
-        real_index=l.index(l_mini[choisi])
-        l[real_index][4]=str(int(l[real_index][4])+1)
-        f=open(get_config_source_file(self.serveur),"w")
-        f.write("%\n"+"\n%\n".join(["%s\n%s\n%s\n%s\n%s"%(i[0],i[1],i[2],i[3],i[4]) for i in l])+"\n%")
+        mini=min(played.values())
+        # on choisit un id dans ceux qui ont ce nombre d'occurences
+        id_choisi=random.choice([k for k,v in played.items() if v==mini])
+        enigme,indice,answer_reg,answer=dec[id_choisi]
+        # on incrémente la choisie
+        played[id_choisi]+=1
+        # on enregistre le played_file
+        f=open(played_file,"w")
+        f.write("\n".join(["%-3s : %s"%(k,v) for k,v in played.items()]))
         f.close()
         f.close()
-        return enigme,indice,answer_reg,answer
+        return enigme.decode("utf8"),indice.decode("utf8"),answer_reg.decode("utf8"),answer.decode("utf8")
 
     def pourmoi(self, serv, message):
         pseudo=serv.get_nickname()
 
     def pourmoi(self, serv, message):
         pseudo=serv.get_nickname()
@@ -189,7 +220,9 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
  JOIN       Faire rejoindre un channel (sans paramètres, donne la liste des chans actuels)
  LEAVE      Faire quitter un channel
  PLAY       Passe un channel en mode "jouer"
  JOIN       Faire rejoindre un channel (sans paramètres, donne la liste des chans actuels)
  LEAVE      Faire quitter un channel
  PLAY       Passe un channel en mode "jouer"
- NOPLAY     Passe un channel en mode "ne pas jouer" """
+ NOPLAY     Passe un channel en mode "ne pas jouer"
+ QUIET      Se taire sur un channel
+ NOQUIET    Opposé de QUIET"""
             helpmsg_overops="""
  SCORES {DEL|ADD|SUB}   Tu veux un dessin ?
  SAY        Fais envoyer un message sur un chan ou à une personne
             helpmsg_overops="""
  SCORES {DEL|ADD|SUB}   Tu veux un dessin ?
  SAY        Fais envoyer un message sur un chan ou à une personne
@@ -285,10 +318,36 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
                         log("priv",auteur," ".join(message)+"[failed]")
             else:
                 notunderstood=True
                         log("priv",auteur," ".join(message)+"[failed]")
             else:
                 notunderstood=True
+        elif cmd=="quiet":
+            if auteur in self.ops:
+                if len(message)>1:
+                    if message[1] in self.quiet_channels:
+                        serv.privmsg(auteur,"Je me la ferme déjà sur %s"%(message[1]))
+                        log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
+                    else:
+                        self.quiet_channels.append(message[1])
+                        serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
+                        log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
+                else:
+                    serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
+            else:
+                notunderstood=True
+        elif cmd=="noquiet":
+            if auteur in self.ops:
+                if len(message)>1:
+                    if message[1] in self.quiet_channels:
+                        self.quiet_channels.remove(message[1])
+                        serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
+                        log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
+                    else:
+                        serv.privmsg(auteur,"Je ne me la ferme pas sur %s."%(message[1]))
+                        log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
+            else:
+                notunderstood=True
         elif cmd in ["states","status"]:
             if auteur in self.overops:
                 for k in self.play_status.keys():
         elif cmd in ["states","status"]:
             if auteur in self.overops:
                 for k in self.play_status.keys():
-                    serv.privmsg(auteur,"%s : %s"%(k,"; ".join([str(i) for i in self.play_status[k]])))
+                    serv.privmsg(auteur,(u"%s : %s"%(k,"; ".join([unicode(i) for i in self.play_status[k]]))).encode("utf8") )
         elif cmd=="say":
             if auteur in self.overops and len(message)>2:
                 serv.privmsg(message[1]," ".join(message[2:]))
         elif cmd=="say":
             if auteur in self.overops and len(message)>2:
                 serv.privmsg(message[1]," ".join(message[2:]))
@@ -340,7 +399,6 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
                 serv.privmsg(auteur,"Scores by score : "+" ; ".join(["%s %s"%(i[0],i[1]) for i in scores]))
                 # trie par pseudo
                 scores.sort(lambda x,y:cmp(x[0].lower(),y[0].lower()))
                 serv.privmsg(auteur,"Scores by score : "+" ; ".join(["%s %s"%(i[0],i[1]) for i in scores]))
                 # trie par pseudo
                 scores.sort(lambda x,y:cmp(x[0].lower(),y[0].lower()))
-                scores.reverse()
                 serv.privmsg(auteur,"Scores by pseudo : "+" ; ".join(["%s %s"%(i[0],i[1]) for i in scores]))
             elif auteur in self.overops:
                 souscmd=message[1].lower()
                 serv.privmsg(auteur,"Scores by pseudo : "+" ; ".join(["%s %s"%(i[0],i[1]) for i in scores]))
             elif auteur in self.overops:
                 souscmd=message[1].lower()
@@ -389,7 +447,7 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
             if not canal in self.quiet_channels:
                 serv.privmsg(canal,
                    "%s: Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…"%(auteur))
             if not canal in self.quiet_channels:
                 serv.privmsg(canal,
                    "%s: Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…"%(auteur))
-                return
+            return
         tryother=False
         pour_moi,message=self.pourmoi(serv,message)
         if pour_moi and message.split()!=[]:
         tryother=False
         pour_moi,message=self.pourmoi(serv,message)
         if pour_moi and message.split()!=[]:
@@ -405,8 +463,8 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
                 else:
                     serv.privmsg(canal,"%s: crève !"%(auteur))
                     log(canal,auteur,message+"[failed]")
                 else:
                     serv.privmsg(canal,"%s: crève !"%(auteur))
                     log(canal,auteur,message+"[failed]")
-            if cmd in ["meur", "meurt","meurre","meurres"]:
-                serv.privmsg(canal,'%s: Mourir, impératif, 2ème personne du pluriel : "meurs" (de rien)'%(auteur))
+            if cmd in ["meur", "meurt","meurre","meurres"] and not canal in self.quiet_channels:
+                serv.privmsg(canal,'%s: Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)'%(auteur))
             if cmd in ["part","leave","dégage"]:
                 if auteur in self.ops and (not (canal in self.stay_channels)
                                            or auteur in self.overops):
             if cmd in ["part","leave","dégage"]:
                 if auteur in self.ops and (not (canal in self.stay_channels)
                                            or auteur in self.overops):
@@ -422,10 +480,9 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
                     become=args
                     serv.nick(become)
                     log(canal,auteur,message+"[successful]")
                     become=args
                     serv.nick(become)
                     log(canal,auteur,message+"[successful]")
-    
-            if cmd in ["coucou"]:
+            if cmd in ["coucou"] and not canal in self.quiet_channels:
                 serv.privmsg(canal,"%s: coucou"%(auteur))
                 serv.privmsg(canal,"%s: coucou"%(auteur))
-            if cmd in ["ping"]:
+            if cmd in ["ping"] and not canal in self.quiet_channels:
                 serv.privmsg(canal,"%s: pong"%(auteur))
             if cmd in ["déconnaissance","deconnaissance","énigme","enigme","encore"]:
                 if canal in self.play_channels:
                 serv.privmsg(canal,"%s: pong"%(auteur))
             if cmd in ["déconnaissance","deconnaissance","énigme","enigme","encore"]:
                 if canal in self.play_channels:
@@ -435,11 +492,31 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
                         except RefuseError:
                             serv.privmsg(canal,"%s: Je peux souffler une minute ?"%(auteur))
                     else:
                         except RefuseError:
                             serv.privmsg(canal,"%s: Je peux souffler une minute ?"%(auteur))
                     else:
-                        serv.privmsg(canal,"%s: Rappel : %s"%(auteur,self.play_status[canal][1]))
+                        serv.privmsg(canal,("%s: Rappel : %s"%(auteur,self.play_status[canal][1])).encode("utf8") )
                 else:
                     serv.privmsg(canal,"%s: pas ici…"%(auteur))
                 else:
                     serv.privmsg(canal,"%s: pas ici…"%(auteur))
+            if cmd in ["score","!score"]:
+                serv.privmsg(auteur,"Votre score : %s"%(self.get_scores().get(auteur,0)) )
+            if cmd in ["scores","!scores"]:
+                scores=self.get_scores().items()
+                # trie par score
+                scores.sort(lambda x,y:cmp(x[1],y[1]))
+                scores.reverse()
+                serv.privmsg(auteur,"Scores by score : "+" ; ".join(["%s %s"%(i[0],i[1]) for i in scores]))
+                # trie par pseudo
+                scores.sort(lambda x,y:cmp(x[0].lower(),y[0].lower()))
+                serv.privmsg(auteur,"Scores by pseudo : "+" ; ".join(["%s %s"%(i[0],i[1]) for i in scores]))
             if cmd=="indice" and canal in self.play_channels:
                 self.give_indice(serv,canal,None)
             if cmd=="indice" and canal in self.play_channels:
                 self.give_indice(serv,canal,None)
+            if is_tag(message) and not canal in self.quiet_channels:
+                if auteur in self.ops:
+                    action=random.choice(config_tag_actions)
+                    serv.action(canal,action.encode("utf8"))
+                    self.quiet_channels.append(canal)
+                else:
+                    answer=random.choice(config_tag_answers)
+                    for ligne in answer.split("\n"):
+                        serv.privmsg(canal,"%s: %s"%(auteur,ligne.encode("utf8")))
             else:
                 tryother=True
         else:
             else:
                 tryother=True
         else:
@@ -447,9 +524,9 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
         if tryother:
             if self.play_status.get(canal,[-1])[0] in [1,2]:
                 answer_regexp=self.play_status[canal][3]
         if tryother:
             if self.play_status.get(canal,[-1])[0] in [1,2]:
                 answer_regexp=self.play_status[canal][3]
-                if re.match(tolere(answer_regexp),unicode(message,"utf8").lower()):
-                    answer=self.play_status[canal][4]
-                    serv.privmsg(canal,"%s: bravo ! (C'était %s)"%(auteur,answer))
+                answer=self.play_status[canal][4]
+                if reussi(message.decode("utf8"),answer,answer_regexp,auteur):
+                    serv.privmsg(canal,(u"%s: bravo ! (C'était %s)"%(auteur,answer)).encode("utf8"))
                     self.add_score(auteur,1)
                     token=time.time()
                     self.play_status[canal]=[0,token]
                     self.add_score(auteur,1)
                     token=time.time()
                     self.play_status[canal]=[0,token]