X-Git-Url: http://gitweb.pimeys.fr/?a=blobdiff_plain;f=basile.py;h=610a34609e65d374d875e1a315a1ef8a97965e4b;hb=9fd92669fd83e2ac4c57874aad0996ea2d0964f9;hp=011dc56a18699f04d7eee861cfb2c73b189c0bd5;hpb=7ce8b7c5ed4cec336c94e9c5d4f358cd5917fa65;p=bots%2Fbasile.git diff --git a/basile.py b/basile.py index 011dc56..610a346 100755 --- a/basile.py +++ b/basile.py @@ -5,8 +5,6 @@ # Un bot IRC qui, un jour, s'interfacera avec la Note Kfet 2015 -import irclib -import ircbot import threading import random import time @@ -14,10 +12,18 @@ import socket, ssl, json import pickle import re import os +import signal +import sys + +# Oui, j'ai recodé ma version d'irclib pour pouvoir rattrapper les SIGHUP +sys.path.insert(0, "/home/vincent/scripts/python-myirclib") +import irclib +import ircbot + from commands import getstatusoutput as ex # on récupère la config -import config_basile as config +import config # la partie qui réfère au fichier lui-même est mieux ici # sinon on réfère la config et pas le fichier lui-même @@ -86,9 +92,9 @@ def connect_NK(): def login_NK(username,password,typ="bdd"): sock=connect_NK() if typ=="special": # ça c'est pour Basile lui-même - masque='["note"]' + masque='[]' elif typ=="bdd": - masque='[["all"],["all"],false]' + masque='[[], [], true]' try: # Basile a un compte special user commande='login [%s,%s,"%s",%s]'%(json.dumps(username),json.dumps(password),typ,masque) @@ -160,12 +166,18 @@ def is_night(): class UnicodeBotError(Exception): pass + +class CrashError(Exception): + """Pour pouvoir faire crasher Basile, parce que ça a l'air drôle""" + pass + def bot_unicode(chain): try: unicode(chain,"utf8") except UnicodeDecodeError as exc: raise UnicodeBotError + class Basile(ircbot.SingleServerIRCBot): def __init__(self,serveur,debug=False): temporary_pseudo=config.irc_pseudo+str(random.randrange(10000,100000)) @@ -225,8 +237,6 @@ class Basile(ircbot.SingleServerIRCBot): log(self.serveur,"Connected") if self.debug: self.chanlist=["#bot"] - else: - serv.privmsg("ChanServ", "INVITE #note-dev") for c in self.chanlist: log(self.serveur,"JOIN %s"%(c)) serv.join(c) @@ -290,6 +300,8 @@ class Basile(ircbot.SingleServerIRCBot): Me fait perdre sur le channel.""",None], "reconnect": [None,"""RECONNECT Établit à nouveau la connexion avec le serveur NK2015""",None], + "reload": [None,"""RELOAD + Recharge la configuration.""",None], "say": [None,None,"""SAY Me fait parler sur le channel."""], "do": [None,None,"""DO @@ -305,11 +317,13 @@ class Basile(ircbot.SingleServerIRCBot): "kick": [None,None,"""KICK [] Kicke du channel (Il faut bien entendu que j'y sois op)."""], "die": [None,None,"""DIE - Me déconnecte du serveur IRC."""] + Me déconnecte du serveur IRC."""], + "crash": [None,None,"""CRASH + Me fait crasher"""] } helpmsg_default="Liste des commandes disponibles :\nHELP IDENTIFY DROP SOLDE" - helpmsg_ops=" JOIN LEAVE QUIET NOQUIET LOST RECONNECT" - helpmsg_overops=" SAY DO STAY NOSTAY OPS OVEROPS KICK DIE" + helpmsg_ops=" JOIN LEAVE QUIET NOQUIET LOST RECONNECT RELOAD" + helpmsg_overops=" SAY DO STAY NOSTAY OPS OVEROPS KICK DIE CRASH" op,overop=auteur in self.ops, auteur in self.overops if len(message)==1: helpmsg=helpmsg_default @@ -430,6 +444,18 @@ class Basile(ircbot.SingleServerIRCBot): self.mourir() else: notunderstood=True + elif cmd=="crash": + if auteur in self.overops: + log(self.serveur,"priv",auteur," ".join(message)+"[successful]") + self.crash() + else: + notunderstood=True + elif cmd=="reload": + if auteur in self.ops: + self.reload(auteur) + log(self.serveur,"priv",auteur," ".join(message)+"[successful]") + else: + notunderstood=True elif cmd=="reconnect": if auteur in self.ops: try: @@ -573,7 +599,13 @@ class Basile(ircbot.SingleServerIRCBot): else: serv.privmsg(canal,("%s: %s"%(auteur,random.choice(config.quit_fail_messages))).encode("utf8")) log(self.serveur,canal,auteur,message+"[failed]") - + elif cmd == "reload": + if auteur in self.ops: + log(self.serveur, canal, auteur, message+"[successful]") + self.reload(canal) + elif cmd == "crash": + if auteur in self.overops: + self.crash() elif cmd in ["part","leave","dégage","va-t-en","tut'tiresailleurs,c'estmesgalets"]: if auteur in self.ops and (not (canal in self.stay_channels) or auteur in self.overops): @@ -820,13 +852,47 @@ class Basile(ircbot.SingleServerIRCBot): return self.serv.get_nickname() nick=property(_getnick) + def reload(self, auteur=None): + reload(config) + if auteur in [None, "SIGHUP"]: + towrite = "Config reloaded" + " (SIGHUP received)"*(auteur == "SIGHUP") + for to in config.report_bugs_to: + self.serv.privmsg(to, towrite) + log(self.serveur, towrite) + else: + self.serv.privmsg(auteur,"Config reloaded") + + def crash(self): + raise CrashError + + def start_as_daemon(self, outfile): + sys.stderr = Logger(outfile) + self.start() + + +class Logger(object): + """Pour écrire ailleurs que sur stdout""" + def __init__(self, filename="basile.full.log"): + self.filename = filename + + def write(self, message): + f = open(self.filename, "a") + f.write(message) + f.close() -if __name__=="__main__": - import sys +def main(): if len(sys.argv)==1: - print "Usage : basile.py [--debug]" + print "Usage : basile.py [--debug] [--no-output] [--daemon [--pidfile]] [--outfile]" + print " --outfile sans --no-output ni --daemon n'a aucun effet" exit(1) serveur=sys.argv[1] + if "--daemon" in sys.argv: + thisfile = os.path.realpath(__file__) + thisdirectory = thisfile.rsplit("/", 1)[0] + os.chdir(thisdirectory) + daemon = True + else: + daemon = False if "debug" in sys.argv or "--debug" in sys.argv: debug=True else: @@ -835,10 +901,40 @@ if __name__=="__main__": config.debug_stdout=False serveurs={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org", "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"} + if "--no-output" in sys.argv or "--daemon" in sys.argv: + outfile = "/var/log/bots/basile.full.log" + for arg in sys.argv: + arg = arg.split("=") + if arg[0].strip('-') in ["out", "outfile", "logfile"]: + outfile = arg[1] + sys.stdout = Logger(outfile) try: serveur=serveurs[serveur] except KeyError: print "Server Unknown : %s"%(serveur) exit(404) basile=Basile(serveur,debug) - basile.start() + # Si on reçoit un SIGHUP, on reload la config + def sighup_handler(signum, frame): + basile.reload("SIGHUP") + signal.signal(signal.SIGHUP, sighup_handler) + if daemon: + child_pid = os.fork() + if child_pid == 0: + os.setsid() + basile.start_as_daemon(outfile) + else: + # on enregistre le pid de basile + pidfile = "/var/run/bots/basile.pid" + for arg in sys.argv: + arg = arg.split("=") + if arg[0].strip('-') in ["pidfile"]: + pidfile = arg[1] + f = open(pidfile, "w") + f.write("%s\n" % child_pid) + f.close() + else: + basile.start() + +if __name__ == "__main__": + main()