]> gitweb.pimeys.fr Git - bots/historien.git/blobdiff - historien.py
16:11:00 < quelu> [20-100]: pas d'article devant Israël
[bots/historien.git] / historien.py
index 005bfb9f28f2e3ab0bc447d9dd10bbcbced07c7b..a67ed1ab1fde14e2ba7bec125ce2b9dcde397736 100755 (executable)
@@ -1,9 +1,9 @@
 #!/usr/bin/python
 # -*- coding:utf8 -*-
 
-# Codé par 20-100 le 23/04/12
+# Codé par 20-100 le 25/05/12
 
-# Un bot IRC qui sort des déconnaissances
+# Un bot IRC qui pose des questions d'histoire
 
 import irclib
 import ircbot
@@ -12,17 +12,17 @@ import random
 import time
 import pickle
 import re
-from remplace_accents import remplace_accents
+from cast_as_date import *
 
-config_password="PatrickSébastien"
-config_pseudo="deconnaisseur"
+config_password="EtTaMère,ElleEstNéeQuand?"
+config_pseudo="historien"
 config_chanlist=["#bot","#flood"]
 config_play_channels=["#flood"]
 config_stay_channels=["#flood","#bot"]
-config_overops=["[20-100]","[20-100]_","PEB"]
-config_ops=["Nit","Eguel","Harry"]
+config_overops=["[20-100]","[20-100]_"]
+config_ops=["PEB","Petite-Peste"]
 
-config_source_file="deconnaissances.txt"
+config_source_file="dates.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"}
@@ -43,17 +43,23 @@ 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"]
+config_level3=[]
 
 config_debug_stdout = True
-config_logfile_template="deconnaisseur.%s.log"
+config_logfile_template="historien.%s.log"
 def get_config_logfile(serveur):
     serveurs={"acoeur.crans.org":"acoeur","irc.crans.org":"crans"}
     return config_logfile_template%(serveurs[serveur])
 
-config_quit_messages=[u"Se décrocher la mâchoire, pas cuit bras d'oiseau ou métalld précieuxld"]
+config_quit_messages=[u"%s : %s quitte le serveur IRC"]
 
-config_leave_messages=[u"On continuera à jouer plus tard ;)"]
+config_leave_messages=[u"%s : %s quitte le channel"]
+
+# Quand personne ne cause, on finit par se taire
+# temps au bout duquel, si personne n'a parlé, on se tait
+config_idle_time=20*60
+# liste des bots, qui ne sont pas considérés comme de l'activité
+config_idle_bots=["deconnaisseur","Basile","historien","hung","salesman","Shadobot","Wen","___"]
 
 class UnicodeBotError(Exception):
     pass
@@ -76,14 +82,42 @@ def log(serveur,channel,auteur=None,message=None):
     f.close()
 
 
-def reussi(message,answer,answer_regexp,auteur):
+config_score_annee=1
+config_score_mois=3
+config_score_jour=4
+
+config_noscore=["[20-100]","[20-100]_"] # parce que 20-100 est nul en histoire
+
+class GoodCentury(Exception):
+    pass
+
+class GoodDeceny(Exception):
+    pass
+
+def reussi(message,answer,auteur):
     if auteur in config_level3:
         return answer in message
     if auteur in config_level2:
-        return remplace_accents(answer) in message
+        return answer in message
     else:
-        if re.match(remplace_accents(answer_regexp).lower(),remplace_accents(message).lower()):
-            return True
+        try:
+            date=cast_as_date(message.lower().strip())
+        except ThisIsNotADate:
+            return False
+        realdate=map(lambda x:int(x), answer.split('/'))
+        realdate.reverse()
+        score=0
+        if date[0]==realdate[0]:
+            score=config_score_annee
+            if date[1]==realdate[1]:
+                score+=config_score_mois
+                if date[2]==realdate[2]:
+                    score+=config_score_jour
+        elif date[0]/10 == realdate[0]/10:
+            raise GoodDeceny
+        elif date[0]/100 == realdate[0]/100:
+            raise GoodCentury
+        return score
 
 def is_something(chain,matches,avant=u".*(?:^| )",apres=u"(?:$|\.| |,|;).*",case_sensitive=False,debug=False):
     if case_sensitive:
@@ -101,11 +135,11 @@ def is_tag(chain):
 class RefuseError(Exception):
     pass
 
-class Deconnaisseur(ircbot.SingleServerIRCBot):
+class Historien(ircbot.SingleServerIRCBot):
     def __init__(self,serveur,debug=False):
         temporary_pseudo=config_pseudo+str(random.randrange(10000,100000))
         ircbot.SingleServerIRCBot.__init__(self, [(serveur, 6667)],
-                                      temporary_pseudo,"Un bot irc.[flagellez 20-100, il le mérite]", 10)
+                                      temporary_pseudo,"Un bot irc qui a au moins l'agreg d'histoire", 10)
         self.debug=debug
         self.serveur=serveur
         self.overops=config_overops
@@ -114,6 +148,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.last_activity={}
         self.quiet_channels=[]
 
     def give_me_my_pseudo(self,serv):
@@ -133,12 +168,17 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
         for c in self.chanlist:
             log(self.serveur,"JOIN %s"%(c))
             serv.join(c)
+            self.update_activity(c,"") # la chaîne vide ne sera jamais un nom de bot et donc marchera toujours
         for c in self.play_channels:
             token=time.time()-3600
             self.play_status[c]=[0,token]
             serv.execute_delayed(random.randrange(ttrig),self.start_enigme,(serv,c,token))
 
     def start_enigme(self,serv,channel,token=None):
+        # On reste silencieux si lechan n'est pas actif
+        if not self.is_active(channel):
+            serv.execute_delayed(ttrig*5,self.start_enigme,(serv,channel,token))
+            return
         if self.play_status[channel][0]==0 and channel in self.play_channels:
             ok="skip"
             if token==self.play_status[channel][-1]:
@@ -149,11 +189,12 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
                 else:
                     ok="refuse"
             if ok=="do_it":
-                enigme,indice,answer_reg,answer=self.get_enigme()
-                log(self.serveur,channel,u"$Énigme$".encode("utf8"),("%s; %s; %s; %s"%(enigme, indice, answer_reg, answer)).encode("utf8"))
-                serv.privmsg(channel,enigme.encode("utf8"))
+                date,evenement=self.get_enigme()
+                log(self.serveur,channel,u"$Date$".encode("utf8"),("%s : %s"%(date, evenement)).encode("utf8"))
+                serv.privmsg(channel,evenement.encode("utf8"))
                 token=time.time()
-                self.play_status[channel]=[1,enigme,indice,answer_reg,answer,token]
+                # le 0 est le flag "bon siècle" n'a pas encore été dit
+                self.play_status[channel]=[1,date,evenement,0,token]
                 serv.execute_delayed(random.randrange(ttrig*3,ttrig*5),self.give_indice,(serv,channel,token))
             elif ok=="refuse":
                 raise RefuseError
@@ -164,25 +205,26 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
                 if self.play_status[channel][-1]+config_time_incompressible_clue<time.time():
                     token=self.play_status[channel][-1]
             if self.play_status[channel][-1]==token:
-                indice=self.play_status[channel][2]
+                date=self.play_status[channel][1]
+                indice=date[:5]
                 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]
-            serv.privmsg(channel,"C'était : %s"%(answer).encode("utf8"))
+            date=self.play_status[channel][1]
+            serv.privmsg(channel,"C'était le %s"%(date).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):
-        # on récupère les déconnaissances
+        # on récupère les dates
         f=open(config_source_file)
-        t=f.read()
+        l=f.readlines()
         f.close()
-        l=re.findall("%\n(.*)\n(.*)\n(.*)\n(.*)\n(.*)\n",t)
-        dec={int(i[0]):list(i[1:]) for i in l if len(i)==5}
+        l=[i.split(" : ",2) for i in l]
+        dates={int(i[0]):i[1:] for i in l}
         # on va chercher combien de fois elles ont été jouées
         played_file=get_config_played_file(self.serveur)
         f=open(played_file)
@@ -194,14 +236,15 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
         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]
+        date,evenement=dates[id_choisi]
+        evenement=evenement.replace("\n","")
         # 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.write("\n".join(["%-4s : %s"%(k,v) for k,v in played.items()]))
         f.close()
-        return enigme.decode("utf8"),indice.decode("utf8"),answer_reg.decode("utf8"),answer.decode("utf8")
+        return map(lambda x:x.decode("utf8"), [date,evenement])
 
     def pourmoi(self, serv, message):
         pseudo=self.nick
@@ -359,7 +402,7 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
         elif cmd in ["states","status"]:
             if auteur in self.overops:
                 for k in self.play_status.keys():
-                    serv.privmsg(auteur,(u"%s : %s"%(k,"; ".join([unicode(i) for i in self.play_status[k]]))).encode("utf8") )
+                    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:]))
@@ -454,6 +497,7 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
         auteur = irclib.nm_to_n(ev.source())
         canal = ev.target()
         message = ev.arguments()[0]
+        self.update_activity(canal,auteur)
         try:
             test=bot_unicode(message)
         except UnicodeBotError:
@@ -497,7 +541,7 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
                 serv.privmsg(canal,"%s: coucou"%(auteur))
             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 cmd in ["date","dates","histoire","énigme","enigme","encore"]:
                 if canal in self.play_channels:
                     if self.play_status.get(canal,[-1])[0]==0:
                         try:
@@ -505,7 +549,7 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
                         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])).encode("utf8") )
+                        serv.privmsg(canal,("%s: Rappel : %s"%(auteur,self.play_status[canal][2])).encode("utf8") )
                 else:
                     serv.privmsg(canal,"%s: pas ici…"%(auteur))
             if cmd in ["score","!score"]:
@@ -536,12 +580,33 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
             tryother=True
         if tryother:
             if self.play_status.get(canal,[-1])[0] in [1,2]:
-                answer_regexp=self.play_status[canal][3]
-                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"))
+                answer=self.play_status[canal][1]
+                flag_century=self.play_status[canal][3]
+                try:
+                    score_obtenu=reussi(message.decode("utf8"),answer,auteur)
+                except GoodCentury:
+                    if not flag_century:
+                        serv.privmsg(canal,"%s: C'est le bon siècle, mais pas la bonne année, cherche encore ;)"%(auteur))
+                        self.play_status[canal][3]=1
+                    return
+                except GoodDeceny:
+                    if flag_century in [0,1]:
+                        serv.privmsg(canal,"%s: C'est la bonne décennie, mais pas la bonne année, encore un effort ;)"%(auteur))
+                        self.play_status[canal][3]=2
+                    return
+                if score_obtenu:
+                    if self.play_status[canal][0]==1:
+                        bonusmsg=u" [+bonus_mois"*(score_obtenu>config_score_annee)+u"+bonus_jour"*(score_obtenu>config_score_annee+config_score_mois)
+                    else:
+                        bonusmsg=""
+                        score_obtenu=1
+                    if bonusmsg:
+                        bonusmsg+=u"]"
+                    serv.privmsg(canal,(u"%s: bravo ! (C'était le %s)%s"%(auteur,answer,bonusmsg)).encode("utf8"))
                     log(self.serveur,canal,auteur+"$win",message)
-                    self.add_score(auteur,1)
+                    if auteur in config_noscore:
+                        score_obtenu=0
+                    self.add_score(auteur,score_obtenu)
                     token=time.time()
                     self.play_status[canal]=[0,token]
                     serv.execute_delayed(random.randrange(Ttrig*5,Ttrig*10),self.start_enigme,(serv,canal,token))
@@ -552,9 +617,10 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
         victime = ev.arguments()[0]
         raison = ev.arguments()[1]
         if victime==self.nick:
-            log(self.serveur,"%s kické par %s (raison : %s)" %(victime,auteur,raison))
+            log(self.serveur,"%s kické de %s par %s (raison : %s)" %(victime,channel,auteur,raison))
             time.sleep(5)
             serv.join(channel)
+            self.update_activity(channel,"")
             # on ne dit rien au rejoin
             #l1,l2=config_kick_answers,config_kick_actions
             #n1,n2=len(l1),len(l2)
@@ -567,10 +633,18 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
     def quitter(self,chan,leave_message=None):
         if leave_message==None:
             leave_message=random.choice(config_leave_messages)
+        try:
+            leave_message=leave_message%(time.strftime("le %d/%m/%Y à %T").decode("utf8"),self.nick)
+        except:
+            pass
         self.serv.part(chan,message=leave_message.encode("utf8"))
     
     def mourir(self):
         quit_message=random.choice(config_quit_messages)
+        try:
+            quit_message=quit_message%(time.strftime("le %d/%m/%Y à %T").decode("utf8"),self.nick)
+        except:
+            pass
         self.die(msg=quit_message.encode("utf8"))
     
     def get_scores(self):
@@ -595,11 +669,17 @@ class Deconnaisseur(ircbot.SingleServerIRCBot):
     def _getnick(self):
         return self.serv.get_nickname()
     nick = property(_getnick)
+    
+    def update_activity(self,canal,pseudo):
+        if not pseudo in config_idle_bots:
+            self.last_activity[canal]=time.time()
+    def is_active(self,canal):
+        return time.time()-self.last_activity[canal]<config_idle_time
 
 if __name__=="__main__":
     import sys
     if len(sys.argv)==1:
-        print "Usage : deconnaisseur.py <serveur> [--debug]"
+        print "Usage : historien.py <serveur> [--debug]"
         exit(1)
     serveur=sys.argv[1]
     if "debug" in sys.argv or "--debug" in sys.argv:
@@ -613,5 +693,5 @@ if __name__=="__main__":
     except KeyError:
         print "Server Unknown : %s"%(serveur)
         exit(404)
-    deco=Deconnaisseur(serveur,debug)
-    deco.start()
+    historien=Historien(serveur,debug)
+    historien.start()