From 9ab3568e6ad1ffebf804a2c3c5f40af73f9ec02d Mon Sep 17 00:00:00 2001 From: Shadow15510 Date: Mon, 12 Jun 2023 15:52:51 +0200 Subject: [PATCH] Auto detection of the arguments of commands --- glados_cmnds.py | 76 +++++++++++++++++++++++++++------------ irc_api/api.py | 94 ++++++++++++++++++++++++++++++++++++++++--------- irc_api/test.py | 49 ++++++++++++++++++++++++++ main.py | 6 ++-- 4 files changed, 183 insertions(+), 42 deletions(-) create mode 100644 irc_api/test.py diff --git a/glados_cmnds.py b/glados_cmnds.py index 94ce0b3..6d35626 100644 --- a/glados_cmnds.py +++ b/glados_cmnds.py @@ -1,32 +1,64 @@ +from random import choice +import re +import requests +import time + from irc_api import api from irc_api.api import auto_help -@api.on(lambda m: "au revoir glados" in m.text.lower()) -def greetings_bye(bot, msg, *args): - bot.send(msg.to, f"Au revoir {msg.author}") +@api.on(lambda m: isinstance(re.match(r"(.*)(bonjour|coucou|salut|hey|hello|hi|yo) glados(.*)", m.text, re.IGNORECASE), re.Match)) +def greetings_hello(bot, msg): + """Dit bonjour à l'utilisateur""" + greetings = ("Bonjour", "Coucou", "Salut", "Hey", "Hello", "Hi", "Yo") + bot.send(msg.to, f"{choice(greetings)} {msg.author}.") + + +@api.on(lambda m: isinstance(re.match(r"(.*)(au revoir|à plus|a\+|à toute|bye|see you|see you soon) glados(.*)", m.text, re.IGNORECASE), re.Match)) +def greetings_bye(bot, msg): + """Dit au revoir à l'utilisateur.""" + greetings = ("Au revoir", "À plus", "À toute", "Bye bye", "See you soon") + bot.send(msg.to, f"{choice(greetings)} {msg.author}.") + + +@api.on(lambda m: isinstance(re.match(r"(.*)(merci|merci beaucoup|thx|thanks|thank you) glados(.*)", m.text, re.IGNORECASE), re.Match)) +def thanks(bot, msg): + """Répond aux remerciements de l'utilisateur.""" + thanks_choice = ("Mais je vous en prie", "Tout le plaisir est pour moi", "C'est tout naturel", "Je n'en ferais rien") + bot.send(msg.to, f"{choice(thanks_choice)}, {msg.author}") + + +@api.on(lambda m: isinstance(re.match(r"(.*)quelle heure(.*)?", m.text, re.IGNORECASE), re.Match)) +def hour(bot, msg): + """Donne l'heure actuelle""" + now = time.strftime("%Hh%M", time.localtime()) + bot.send(msg.to, f"Il est très exactement {now}.") + + +@api.command("wiki", desc="wiki [limite=1]\nFait une recherche wikipedia.") +def wiki(bot, msg, text: str, limit: int=1): + session = requests.Session() + params = { + 'action': 'opensearch', + 'search': text, + 'limit': limit, + 'namespace': 0, + 'redirects': 'resolve', + 'format': 'json' + } + response = session.get(url="https://fr.wikipedia.org/w/api.php", params=params, timeout=(4, 12)).json() + if len(response[1]) == 0: + bot.send(msg.to, f"Aucun résultat trouvé pour la recherche : {text}.") + else: + bot.send(msg.to, f"{len(response[1])} résultat{('', 's')[limit > 1]} pour la recherche : '{text}'.") + for name, link in zip(response[1], response[3]): + bot.send(msg.to, f" {name} : {link}") @api.channel("#glados") -@api.on( - event=lambda m: "bonjour glados" in m.text.lower(), - desc="Réagis au 'bonjour glados' uniquement si le message est envoyé depuis le channel "\ - "#glados." - ) -def greetings_hello(bot, msg, *args): - bot.send(msg.to, f"Bonjour à toi") - - -@api.command("test") -def test(bot, msg, *args): - """Test de module de fonction.""" - bot.send(msg.to, f"arguments : {args}") - - -@api.channel("#glados") -def react_on_glados(bot, msg, *args): - """Répète le dernier message envoyé sur #glados.""" - if bot.history.get()[-1].author == msg.author: +def spam_on_glados(bot, msg): + """Détecte les monologues sur #glados.""" + if len(bot.history) > 2 and bot.history.get()[-2].author == msg.author: bot.counter += 1 else: bot.counter = 1 diff --git a/irc_api/api.py b/irc_api/api.py index 0665adb..0408230 100644 --- a/irc_api/api.py +++ b/irc_api/api.py @@ -19,14 +19,18 @@ def command(name, desc=""): def on(event, desc=""): - def decorator(func): - return Command( - name=func.__name__, - func=func, - events=[event], - desc=desc, - cmnd_type=0 - ) + def decorator(func_or_cmnd): + if isinstance(func_or_cmnd, Command): + func_or_cmnd.events.append(event) + return func_or_cmnd + else: + return Command( + name=func_or_cmnd.__name__, + func=func_or_cmnd, + events=[event], + desc=desc, + cmnd_type=0 + ) return decorator @@ -151,7 +155,21 @@ class Bot: for callback in self.callbacks.values(): if not False in [event(message) for event in callback.events]: logging.info("matched %s", callback.name) - callback(message, *parse(message.text)[callback.cmnd_type:]) + + # @api.on + if callback.cmnd_type == 0: + callback(message) + # @api.command + if callback.cmnd_type == 1: + args = check_args(callback.func, *parse(message.text)[1:]) + if isinstance(args, list): + callback(message, *args) + else: + self.send( + message.to, + "Erreur : les arguments donnés ne correspondent pas." + ) + def send(self, target: str, message: str): """Send a message to the specified target (channel or user). @@ -163,7 +181,8 @@ class Bot: message : str The content of the message to send. """ - self.irc.send(f"PRIVMSG {target} :{message}") + for line in message.splitlines(): + self.irc.send(f"PRIVMSG {target} :{line}") def add_command(self, command, add_to_help=False): command.bot = self @@ -197,20 +216,21 @@ class Bot: @command("aide") -def auto_help(bot, msg, *args): +def auto_help(bot, msg, fct_name: str=""): """Aide des commandes disponibles.""" - if args and args[0] in bot.commands_help.keys(): - cmnd = bot.commands_help[args[0]] + if fct_name and fct_name in bot.commands_help.keys(): + cmnd = bot.commands_help[fct_name] if cmnd.cmnd_type == 1: - bot.send(msg.to, f"Aide sur la commande : {bot.prefix}{args[0]}") + bot.send(msg.to, f"Aide sur la commande : {bot.prefix}{fct_name}") else: - bot.send(msg.to, f"Aide sur la commande : {args[0]}") + bot.send(msg.to, f"Aide sur la commande : {fct_name}") - bot.send(msg.to, f" {bot.commands_help[args[0]].desc}") + for line in bot.commands_help[fct_name].desc.splitlines(): + bot.send(msg.to, f" {line}") else: bot.send(msg.to, f"Liste des commandes ({PREFIX}aide pour plus d'info)") for cmnd_name in bot.commands_help.keys(): - bot.send(msg.to, f" - {cmnd.name}") + bot.send(msg.to, f" - {cmnd_name}") def parse(message): @@ -224,3 +244,43 @@ def parse(message): else: args_to_return.append(match) return args_to_return + + +def convert(data, new_type, default=None): + try: + return new_type(data) + except: + return default + + +def check_args(func, *input_args): + # args[0] = (type, is_optionnal) + defaults = getattr(func, "__defaults__") + if not defaults: + defaults = [] + + annotations = getattr(func, "__annotations__") + if not annotations: + return [] + + required_args = len(annotations) - len(defaults) + + check_args = [] + for index, arg_type in enumerate(annotations.values()): + if index + 1 > required_args: + check_args.append((arg_type, defaults[index - required_args])) + else: + check_args.append((arg_type, None)) + + if len(input_args) < required_args: + return None + + converted_args = [] + for index, arg in enumerate(check_args): + if len(input_args) > index: + converted_args.append(convert(input_args[index], *check_args[index])) + else: + converted_args.append(check_args[index][1]) + + return converted_args + diff --git a/irc_api/test.py b/irc_api/test.py new file mode 100644 index 0000000..22a6ce4 --- /dev/null +++ b/irc_api/test.py @@ -0,0 +1,49 @@ +def convert(data, new_type, default=None): + try: + return new_type(data) + except: + return default + + +def check_args(bot, func, *input_args): + # args[0] = (type, is_optionnal) + defaults = getattr(func, "__defaults__") + if not defaults: + defaults = [] + + annotations = getattr(func, "__annotations__") + if not annotations: + return [] + + required_args = len(annotations) - len(defaults) + + check_args = [] + for index, arg_type in enumerate(annotations.values()): + if index + 1 > required_args: + check_args.append((arg_type, defaults[index - required_args])) + else: + check_args.append((arg_type, None)) + + if len(input_args) < required_args: + # bot.send("Erreur : argument manquant") + return + + converted_args = [] + for index, arg in enumerate(check_args): + if len(input_args) > index: + converted_args.append(convert(input_args[index], *check_args[index])) + else: + converted_args.append(check_args[index][1]) + + return converted_args + + +def foo(bot, msg, a: str, b: int=1): + return None + + +print(check_args(None, foo, "3")) +print(check_args(None, foo, "3", "5")) +print(check_args(None, foo, "3", "test")) +print(check_args(None, foo, "3", "5", "2", "5")) + diff --git a/main.py b/main.py index 7117e20..a6d885a 100755 --- a/main.py +++ b/main.py @@ -13,7 +13,7 @@ import re from irc_api import api -import glados_cmnds as gcmnds +import glados_cmnds as gv4_cmnds import fun_cmnds as fcmnds from secrets import USER, PASSWORD @@ -28,8 +28,8 @@ class MyBot(api.Bot): glados = MyBot( (USER, PASSWORD), ('irc.planet-casio.com', 6697), - ["#general", "#glados"], - gcmnds, fcmnds, + ["#glados"], + gv4_cmnds, prefix="!", )