196 lines
6.8 KiB
Python
196 lines
6.8 KiB
Python
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 .<alias>.
|
||
"""
|
||
|
||
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} <al menos {min_args} argumento/s>) -- 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 .<alias>.
|
||
"""
|
||
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 <acción>`:
|
||
- .alias add <nombre> <comando>
|
||
- .alias del <nombre>
|
||
- .alias list
|
||
- .alias help <alias>
|
||
"""
|
||
if not args:
|
||
return " Uso: `.alias list` | `.alias add <nombre> <cmd>` | `.alias del <nombre>`"
|
||
|
||
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 <nombre> <comando>` para crear un alias.\n"
|
||
"Usa `.alias del <nombre>` para eliminarlo.\n"
|
||
"Usa `.alias list` para ver todos los alias.\n"
|
||
"Usa `.alias help <nombre>` para ver la definición de un alias.\n"
|
||
"Los alias pueden usar `$1`, `$2`, `$*` para insertar argumentos."
|
||
)
|
||
|