X-Git-Url: http://gitweb.pimeys.fr/?p=bots%2Fbbc.git;a=blobdiff_plain;f=bbc.py;fp=bbc.py;h=79d099c9c56bb495005da1fa77cc8f35de5f870c;hp=0000000000000000000000000000000000000000;hb=c890c4dd54382450abf0b17bf9333b308cecf574;hpb=6bcba1e8e4d35909a73791b23c3ec49734d06732 diff --git a/bbc.py b/bbc.py new file mode 100755 index 0000000..79d099c --- /dev/null +++ b/bbc.py @@ -0,0 +1,387 @@ +#!/usr/bin/python +# -*- encoding: utf-8 -*- + +""" Codé par 20-100 + +Un bot IRC qui ne fait rien. Base pour en coder un vrai. +""" + +import irclib +import ircbot +import random +import time +import re +from commands import getstatusoutput as ex + +# on récupère la config +import config + + +def get_config_logfile(serveur): + """Renvoie le nom du fichier de log en fonction du serveur.""" + serveurs = {"acoeur.crans.org" : "acoeur", "irc.crans.org" : "crans"} + return config.logfile_template % (serveurs[serveur]) + +def log(serveur, channel, auteur=None, message=None): + f = open(get_config_logfile(serveur), "a") + if auteur == message == None: + # alors c'est que c'est pas un channel mais juste une ligne de log + chain = "%s %s" % (time.strftime("%F %T"), channel) + else: + chain = "%s [%s:%s] %s" % (time.strftime("%F %T"), channel, auteur, message) + f.write(chain + "\n") + if config.debug_stdout: + print chain + f.close() + +class UnicodeBotError(Exception): + pass +def bot_unicode(chain): + try: + unicode(chain, "utf8") + except UnicodeDecodeError as exc: + raise UnicodeBotError + +class Skeleton(ircbot.SingleServerIRCBot): + def __init__(self, serveur, debug=False): + temporary_pseudo = config.irc_pseudo + str(random.randrange(10000, 100000)) + ircbot.SingleServerIRCBot.__init__(self, [(serveur, 6667)], + temporary_pseudo, config.ircname, 10) + self.debug = debug + self.serveur = serveur + self.overops = config.overops + self.ops = self.overops + config.ops + self.chanlist = config.chanlist + self.stay_channels = config.stay_channels + self.quiet_channels = config.quiet_channels + self.last_perdu = 0 + + def give_me_my_pseudo(self, serv): + serv.privmsg("NickServ", "RECOVER %s %s" % (config.irc_pseudo, config.irc_password)) + serv.privmsg("NickServ", "RELEASE %s %s" % (config.irc_pseudo, config.irc_password)) + time.sleep(0.3) + serv.nick(config.irc_pseudo) + + def on_welcome(self, serv, ev): + self.serv = serv # ça serv ira :) + self.give_me_my_pseudo(serv) + serv.privmsg("NickServ", "identify %s" % (config.irc_password)) + log(self.serveur, "Connected") + if self.debug: + self.chanlist = ["#bot"] + for c in self.chanlist: + log(self.serveur, "JOIN %s" % (c)) + serv.join(c) + + def pourmoi(self, serv, message): + """renvoie (False, lemessage) ou (True, le message amputé de "pseudo: ")""" + pseudo = self.nick + size = len(pseudo) + if message[:size] == pseudo and len(message) > size and message[size] == ":": + return (True, message[size + 1:].lstrip(" ")) + else: + return (False, message) + + def on_privmsg(self, serv, ev): + message = ev.arguments()[0] + auteur = irclib.nm_to_n(ev.source()) + try: + bot_unicode(message) + except UnicodeBotError: + if config.utf8_trigger: + serv.privmsg(auteur, random.choice(config.utf8_fail_answers).encode("utf8")) + return + message = message.split() + cmd = message[0].lower() + notunderstood = False + if cmd == "help": + helpdico = {"help" : ["""HELP + Affiche de l'aide sur la commande""", None, None], + "join" : [None, """JOIN + Me fait rejoindre le channel""", None], + "leave" : [None, """LEAVE + Me fait quitter le channel (sauf s'il est dans ma stay_list).""", None], + "quiet" : [None, """QUIET + Me rend silencieux sur le channel.""", None], + "noquiet" : [None, """NOQUIET + Me rend la parole sur le channel.""", None], + "say" : [None, None, """SAY + Me fait parler sur le channel."""], + "do" : [None, None, """DO + Me fait faitre une action (/me) sur le channel."""], + "stay" : [None, None, """STAY + Ajoute le channel à ma stay_list."""], + "nostay" : [None, None, """NOSTAY + Retire le channel de ma stay_list."""], + "ops" : [None, None, """OPS + Affiche la liste des ops."""], + "overops" : [None, None, """OVEROPS + Affiche la liste des overops."""], + "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."""] + } + helpmsg_default = "Liste des commandes disponibles :\nHELP" + helpmsg_ops = " JOIN LEAVE QUIET NOQUIET LOST RECONNECT" + helpmsg_overops = " SAY DO STAY NOSTAY OPS OVEROPS KICK DIE" + op, overop = auteur in self.ops, auteur in self.overops + if len(message) == 1: + helpmsg = helpmsg_default + if op: + helpmsg += helpmsg_ops + if overop: + helpmsg += helpmsg_overops + else: + helpmsgs = helpdico.get(message[1].lower(), ["Commande inconnue.", None, None]) + helpmsg = helpmsgs[0] + if op and helpmsgs[1]: + if helpmsg: + helpmsg += "\n" + helpmsgs[1] + else: + helpmsg = helpmsgs[1] + if overop and helpmsgs[2]: + if helpmsg: + helpmsg += "\n" + helpmsgs[2] + else: + helpmsg = helpmsgs[2] + for ligne in helpmsg.split("\n"): + serv.privmsg(auteur, ligne) + elif cmd == "join": + if auteur in self.ops: + if len(message) > 1: + if message[1] in self.chanlist: + serv.privmsg(auteur, "Je suis déjà sur %s" % (message[1])) + else: + serv.join(message[1]) + self.chanlist.append(message[1]) + serv.privmsg(auteur, "Channels : " + " ".join(self.chanlist)) + log(self.serveur, "priv", auteur, " ".join(message)) + else: + serv.privmsg(auteur, "Channels : " + " ".join(self.chanlist)) + else: + notunderstood = True + elif cmd == "leave": + if auteur in self.ops and len(message) > 1: + if message[1] in self.chanlist: + if not (message[1] in self.stay_channels) or auteur in self.overops: + self.quitter(message[1], " ".join(message[2:])) + self.chanlist.remove(message[1]) + log(self.serveur, "priv", auteur, " ".join(message) + "[successful]") + else: + serv.privmsg(auteur, "Non, je reste !") + log(self.serveur, "priv", auteur, " ".join(message) + "[failed]") + else: + serv.privmsg(auteur, "Je ne suis pas sur %s" % (message[1])) + else: + notunderstood = True + elif cmd == "stay": + if auteur in self.overops: + if len(message) > 1: + if message[1] in self.stay_channels: + log(self.serveur, "priv", auteur, " ".join(message) + "[failed]") + serv.privmsg(auteur, "Je stay déjà sur %s." % (message[1])) + else: + log(self.serveur, "priv", auteur, " ".join(message) + "[successful]") + self.stay_channels.append(message[1]) + serv.privmsg(auteur, "Stay channels : " + " ".join(self.stay_channels)) + else: + serv.privmsg(auteur, "Stay channels : " + " ".join(self.stay_channels)) + else: + notunderstood = True + elif cmd == "nostay": + if auteur in self.overops: + if len(message) > 1: + if message[1] in self.stay_channels: + log(self.serveur, "priv", auteur, " ".join(message) + "[successful]") + self.stay_channels.remove(message[1]) + serv.privmsg(auteur, "Stay channels : " + " ".join(self.stay_channels)) + else: + log(self.serveur, "priv", auteur, " ".join(message) + "[failed]") + serv.privmsg(auteur, "Je ne stay pas sur %s." % (message[1])) + + else: + notunderstood = True + elif cmd == "die": + if auteur in self.overops: + log(self.serveur, "priv", auteur, " ".join(message) + "[successful]") + self.mourir() + 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 == "say": + if auteur in self.overops and len(message) > 2: + serv.privmsg(message[1], " ".join(message[2:])) + log(self.serveur, "priv", auteur, " ".join(message)) + elif len(message) <= 2: + serv.privmsg(auteur, "Syntaxe : SAY ") + else: + notunderstood = True + elif cmd == "do": + if auteur in self.overops and len(message) > 2: + serv.action(message[1], " ".join(message[2:])) + log(self.serveur, "priv", auteur, " ".join(message)) + elif len(message) <= 2: + serv.privmsg(auteur, "Syntaxe : DO ") + else: + notunderstood = True + elif cmd == "kick": + if auteur in self.overops and len(message) > 2: + serv.kick(message[1], message[2], " ".join(message[3:])) + log(self.serveur, "priv", auteur, " ".join(message)) + elif len(message) <= 2: + serv.privmsg(auteur, "Syntaxe : KICK []") + else: + notunderstood = True + elif cmd == "ops": + if auteur in self.overops: + serv.privmsg(auteur, " ".join(self.ops)) + else: + notunderstood = True + elif cmd == "overops": + if auteur in self.overops: + serv.privmsg(auteur, " ".join(self.overops)) + else: + notunderstood = True + else: + notunderstood = True + if notunderstood: + serv.privmsg(auteur, "Je n'ai pas compris. Essayez HELP…") + + def on_pubmsg(self, serv, ev): + auteur = irclib.nm_to_n(ev.source()) + canal = ev.target() + message = ev.arguments()[0] + try: + bot_unicode(message) + except UnicodeBotError: + if config.utf8_trigger and not canal in self.quiet_channels: + serv.privmsg(canal, (u"%s: %s" % (auteur, random.choice(config.utf8_fail_answers))).encode("utf8")) + return + pour_moi, message = self.pourmoi(serv, message) + if pour_moi and message.split() != []: + cmd = message.split()[0].lower() + try: + args = " ".join(message.split()[1:]) + except: + args = "" + if cmd in ["meurs", "die", "crève"]: + if auteur in self.overops: + log(self.serveur, canal, auteur, message + "[successful]") + self.mourir() + else: + serv.privmsg(canal, ("%s: %s" % (auteur, random.choice(config.quit_fail_messages))).encode("utf8")) + log(self.serveur, canal, auteur, message + "[failed]") + + 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): + self.quitter(canal) + log(self.serveur, canal, auteur, message + "[successful]") + if canal in self.chanlist: + self.chanlist.remove(canal) + else: + serv.privmsg(canal, ("%s: %s" % (auteur, random.choice(config.leave_fail_messages))).encode("utf8")) + log(self.serveur, canal, auteur, message + "[failed]") + + elif cmd in ["deviens", "pseudo"]: + if auteur in self.ops: + become = args + serv.nick(become) + log(self.serveur, canal, auteur, message + "[successful]") + + elif cmd in ["ping"] and not canal in self.quiet_channels: + serv.privmsg(canal, "%s: pong" % (auteur)) + else: + if not canal in self.quiet_channels: + pass + + def on_action(self, serv, ev): + action = ev.arguments()[0] + auteur = irclib.nm_to_n(ev.source()) + channel = ev.target() + try: + bot_unicode(action) + except UnicodeBotError: + if config.utf8_trigger and not channel in self.quiet_channels: + serv.privmsg(channel, (u"%s: %s" % (auteur, random.choice(config.utf8_fail_answers))).encode("utf8")) + return + mypseudo = self.nick + + def on_kick(self, serv, ev): + auteur = irclib.nm_to_n(ev.source()) + channel = ev.target() + victime = ev.arguments()[0] + raison = ev.arguments()[1] + if victime == self.nick: + log(self.serveur, "%s kické de %s par %s (raison : %s)" % (victime, channel, auteur, raison)) + time.sleep(2) + serv.join(channel) + return + l1, l2 = config.kick_answers, config.kick_actions + n1, n2 = len(l1), len(l2) + i = random.randrange(n1 + n2) + if i >= n1: + serv.action(channel, l2[i - n1].format(auteur).encode("utf8")) + else: + serv.privmsg(channel, l1[i].format(auteur).encode("utf8")) + + def quitter(self, chan, leave_message=None): + if leave_message == None: + leave_message = random.choice(config.leave_messages) + self.serv.part(chan, message=leave_message.encode("utf8")) + + def mourir(self): + quit_message = random.choice(config.quit_messages) + self.die(msg=quit_message.encode("utf8")) + + def _getnick(self): + return self.serv.get_nickname() + nick = property(_getnick) + + +if __name__ == "__main__": + import sys + if len(sys.argv) == 1: + print "Usage : bbc.py [--debug]" + exit(1) + serveur = sys.argv[1] + if "debug" in sys.argv or "--debug" in sys.argv: + debug = True + else: + debug = False + if "--quiet" in sys.argv: + config.debug_stdout = False + serveurs = {"irc" : "irc.crans.org", "crans" : "irc.crans.org", "irc.crans.org" : "irc.crans.org"} + try: + serveur = serveurs[serveur] + except KeyError: + print "Server Unknown : %s" % (serveur) + exit(404) + bot = Skeleton(serveur, debug) + bot.start()