import os import json # Ajusta la ruta donde quieras guardar los aliases ALIAS_FILE = os.path.expanduser("/var/lib/bot/aliases.json") os.makedirs(os.path.dirname(ALIAS_FILE), exist_ok=True) class AliasPlugin: """ Gestor de alias con soporte para variables posicionales ($1, $2, $*). Cada alias se convierte en un comando independiente que el usuario puede invocar con .. """ def __init__(self, send_raw, bot=None): # Esta función se llama al instanciar el plugin en load_plugins(). self.send_raw = send_raw self.bot = bot self.aliases = self.load_aliases() def load_aliases(self): """Carga los alias desde un archivo JSON.""" if os.path.exists(ALIAS_FILE): try: with open(ALIAS_FILE, "r", encoding="utf-8") as f: return json.load(f) except json.JSONDecodeError: return {} return {} def save_aliases(self): """Guarda los alias en un archivo JSON.""" with open(ALIAS_FILE, "w", encoding="utf-8") as f: json.dump(self.aliases, f, indent=4, ensure_ascii=False) def add_alias(self, name, command): """Añade un alias, lo guarda y recarga los plugins.""" if name in self.aliases: return f"️ El alias '{name}' ya existe. Usa `.alias del {name}` para eliminarlo primero." # Eliminar comillas dobles extra if command.startswith('"') and command.endswith('"'): command = command[1:-1] # Elimina la primera y última comilla self.aliases[name] = command self.save_aliases() # Recargar plugins tras añadir un alias if self.bot: self.bot.load_plugins() return f" Alias '{name}' creado para ejecutar: `{command}`" def remove_alias(self, name): """Elimina un alias por su nombre.""" if name not in self.aliases: return f"️ El alias '{name}' no existe." del self.aliases[name] self.save_aliases() return f" Alias '{name}' eliminado." def list_aliases(self): """Retorna una lista de todos los alias registrados.""" if not self.aliases: return " No hay alias registrados." lines = [f"`{name}` → `{cmd}`" for name, cmd in self.aliases.items()] return " **Alias disponibles:**\n" + "\n".join(lines) def execute_alias(self, sender, alias, *args): if alias not in self.aliases: return f" El alias '{alias}' no está registrado." command = self.aliases[alias] # Ej: "echo Hola $1" # Reemplazo de variables especiales command = command.replace("$nick", sender) # Reemplaza $nick por el nombre del usuario # Reemplazo de $1, $2, ..., $* for i, arg in enumerate(args, start=1): command = command.replace(f"${i}", arg) command = command.replace("$*", " ".join(args[1:])) # Ejecutar el comando procesado como si fuera un plugin del bot tokens = command.split() if not tokens: return " Error: Alias vacío tras el procesamiento." cmd = tokens[0] # Primer token es el comando (Ej: "echo") cmd_args = tokens[1:] # El resto son argumentos # Verificar si el comando existe en los plugins del bot if cmd in self.bot.plugins: plugin_or_func = self.bot.plugins[cmd] try: # Si es una función (alias dinámico), la llamamos if callable(plugin_or_func): response = plugin_or_func(sender, *cmd_args) else: # Si es un objeto plugin con método `.run()`, ejecutamos `.run(...)` response = plugin_or_func.run(*cmd_args) return response except Exception as e: return f" Error al ejecutar alias '{alias}': {str(e)}" return f" El comando '{cmd}' no existe." def get_help(self, alias_name): """Devuelve un texto con la ayuda de un alias concreto.""" if alias_name in self.aliases: command = self.aliases[alias_name] min_args = max(command.count("$1"), 1) # Asume al menos 1 return f"({alias_name} ) -- Alias for `{command}`." return f" No hay ayuda disponible para '{alias_name}'." def get_dynamic_commands(self): """ Retorna un dict con { alias: function } para registrarlos como comandos. Cada alias quedará accesible con .. """ commands = {} for alias_name in self.aliases: # Creamos una función que llame a self.execute_alias def alias_func(sender, *args, _alias=alias_name): return self.execute_alias(sender, _alias, *args) commands[alias_name] = alias_func return commands def run(self, sender, *args): """ Maneja el uso de `.alias `: - .alias add - .alias del - .alias list - .alias help """ if not args: return " Uso: `.alias list` | `.alias add ` | `.alias del `" action = args[0].lower() if action == "add" and len(args) > 2: name = args[1] command = " ".join(args[2:]) return self.add_alias(name, command) elif action == "del" and len(args) > 1: return self.remove_alias(args[1]) elif action == "list": return self.list_aliases() elif action == "help" and len(args) > 1: return self.get_help(args[1]) else: return " Comando no reconocido. Usa `.alias list`." # # Función 'run' global para cuando el bot llama a 'alias' como plugin. # def run(sender, *args): """ Función que se invoca cuando el usuario hace .alias ... Recuerda que en el bot, normalmente le pasamos: plugin.run(sender, *args) """ # Como no necesitamos send_raw aquí, podemos instanciar con None alias_plugin = AliasPlugin(None) # Simplemente delegamos la lógica de los comandos a alias_plugin.run # Como no sabemos si lo primero que llega es 'sender' o no, ajusta según tu bot: if len(args) == 0: return alias_plugin.run("", *args) # Asumiendo que 'sender' es el primer argumento: sender = args[0] more_args = args[1:] return alias_plugin.run(sender, *more_args) def help(): """Texto de ayuda para .help alias""" return ( "Usa `.alias add ` para crear un alias.\n" "Usa `.alias del ` para eliminarlo.\n" "Usa `.alias list` para ver todos los alias.\n" "Usa `.alias help ` para ver la definición de un alias.\n" "Los alias pueden usar `$1`, `$2`, `$*` para insertar argumentos." )