Skip to content

refactor: migrar comandos /ping, /github, /ayuda a GeneralCog - #8

Merged
Axel-DaMage merged 17 commits into
mainfrom
feat/general-cog
Aug 15, 2026
Merged

Axel-DaMage merged 17 commits into
mainfrom
feat/general-cog

Conversation

@ranto-dev05

Copy link
Copy Markdown
Collaborator

Closes #3

Resumen

Migra los comandos slash /ping, /github\ y /ayuda\ desde \main.py\ hacia un cog dedicado \�ot/cogs/general.py.

Cambios

  • \�ot/cogs/general.py\ (nuevo): clase \GeneralCog\ con los tres comandos (@app_commands.command\ + scoping por guild).
  • \�ot/cogs/events.py: se agrega entry point \setup\ para cargarse como extensión.
  • \main.py: se eliminan los @bot.tree.command, se cargan las extensiones en \setup_hook\ con \�ot.load_extension\ y se sincroniza el árbol de comandos ahí (en lugar de \on_ready).

Mejoras de diseño

  • /ayuda\ ahora se genera dinámicamente desde \�ot.tree.get_commands(guild=...), por lo que al añadir nuevos comandos al bot aparecerán automáticamente (lista ordenada alfabéticamente).
  • Carga de cogs unificada por extensiones, patrón escalable para añadir nuevos cogs.
  • Sync de cmd tree en \setup_hook\ (se ejecuta una sola vez tras el login), eliminando el sync condicional en \on_ready.

Validación

  • \python -m compileall: OK.
  • Script de sanity: los tres comandos se registran limitados al guild configurado; los handlers responden correctamente.

Nota: este PR depende de la estructura \�ot/\ de la rama
efactor/project-structure, por lo que incluye esos commits como base.

- Add bot/cogs/general.py with GeneralCog and the three slash commands
- Add setup entry point to EventsCog for extension loading
- Load cogs via bot.load_extension in setup_hook
- Sync command tree in setup_hook and remove on_ready sync logic
- Build /ayuda dynamically from the registered command tree
@ranto-dev05 ranto-dev05 added enhancement New feature or request Priority: Low Baja prioridad - consideracion futura Status: Pending Necesita revision inicial labels Aug 14, 2026
@ranto-dev05

Copy link
Copy Markdown
Collaborator Author

🔍 Revisión profunda y plan de mitigación — PR #8

Revisión detallada del PR para dejarlo estable y escalable antes de sacarlo de Draft. Se clasifica por severidad.


🔴 Bugs que rompen el arranque

1. logging.basicConfig(filename="logs/atlas.log") crashea en un clone fresco
logs/ está en .gitignore y no se commitea. En un entorno limpio (CI/deploy), la carpeta no existe y basicConfig lanza FileNotFoundError antes de conectar el bot (verificado en Python 3.13). main.py se modifica en este PR, así que conviene resolverlo aquí.

import os
os.makedirs("logs", exist_ok=True)  # antes de logging.basicConfig

2. int(settings.discord_guild_id) puede crashear con mensaje críptico
validate_settings() solo valida is None. Si DISCORD_GUILD_ID está definida pero vacía ("") o no es numérica, pasa la validación y int(...) lanza ValueError en el import de bot/cogs/general.py y en main.py, rompiendo el arranque con un error poco claro.

def validate_settings():
    if not discord_token:
        raise ValueError("Falta DISCORD_TOKEN en el archivo .env")
    if not discord_guild_id:
        raise ValueError("Falta DISCORD_GUILD_ID en el archivo .env")
    if not github_url:
        raise ValueError("Falta GITHUB_URL en el archivo .env")
    if not str(discord_guild_id).isdigit():
        raise ValueError("DISCORD_GUILD_ID debe ser el ID numérico del servidor")

3. load_extension y bot.tree.sync() sin manejo de errores
Si un cog falla o Discord devuelve un error transitorio en el sync, la excepción propaga a setup_hook y el bot nunca arranca. El sync de comandos no debería impedir la conexión.

@bot.event
async def setup_hook() -> None:
    for ext in ("bot.cogs.general", "bot.cogs.events"):
        try:
            await bot.load_extension(ext)
        except commands.ExtensionError as exc:
            logging.error("No se pudo cargar %s: %s", ext, exc)
            raise
    try:
        await bot.tree.sync(guild=guild)
    except discord.HTTPException as exc:
        logging.error("No se pudo sincronizar comandos: %s", exc)

🟠 Robustez y mantenibilidad

4. Sin manejador global de errores de comandos
Si un handler falla en runtime (p. ej. github_url vacío), la interacción queda colgada sin respuesta. Falta un error handler:

@bot.tree.error
async def on_app_error(interaction: discord.Interaction, error: Exception) -> None:
    if interaction.response.is_done():
        await interaction.followup.send("❌ Ocurrió un error al ejecutar el comando.")
    else:
        await interaction.response.send_message("❌ Ocurrió un error al ejecutar el comando.")
    logging.error("Error en %s: %s", interaction.command, error)

5. GUILD duplicado en main.py y bot/cogs/general.py
El mismo discord.Object(id=int(...)) se construye dos veces con riesgo de deriva. Centralizar el helper (p. ej. en settings.py) y derivar el objeto guild desde ahí.

# settings.py
def get_discord_guild_id() -> int:
    return int(discord_guild_id)

6. Evaluación eager de GUILD a nivel de módulo impide testear/importar el cog sin env
Cualquier import de bot.cogs.general (tests, CI, tools) crashea con int(None) si no hay .env. Mejor hacerlo perezoso:

def get_guild() -> discord.Object:
    return discord.Object(id=int(settings.discord_guild_id))

7. Scoping a un único guild no escala a comando global / multi-guild
@app_commands.guilds(GUILD) está bien hoy (comportamiento actual), pero hardcodear el guild en cada comando dificulta migrar a comandos globales. Sugerencia: dejar constancia en el código y centralizar en un único lugar (ver punto 5).

8. /ayuda no contempla comandos globales ni subcomandos
get_commands(guild=GUILD) omite comandos globales que se agreguen en el futuro, y no lista subcomandos de grupos. Ampliarlo:

comandos = [*self.bot.tree.get_commands(guild=GUILD), *self.bot.tree.get_commands()]

Documentar además que los emojis de COMANDO_EMOJIS deben actualizarse al añadir cogs.

9. print() vs logging mezclados
main.py mezcla print y logging; EventsCog usa print y GeneralCog usa logger. Unificar con el logger del módulo para centralizar salida (consola + archivo).

10. EventsCog.setup no registra nada (inconsistente con general.py)

logger = logging.getLogger(__name__)

async def setup(bot: commands.Bot) -> None:
    await bot.add_cog(EventsCog(bot))
    logger.info("EventsCog cargado correctamente.")

11. bot.tree.sync() en cada arranque
Sincronizar en cada setup_hook puede golpear rate limits de Discord en deploys frecuentes. Alternativa: rastrear si los comandos cambiaron o sincronizar de forma controlada (mejora a futuro).

12. save_event sobrescribe description con None al actualizar
Si Discord envía una actualización sin description, se pisa el valor previo (pérdida de datos). Considerar no sobreescribir con None en update → existing_event.description = description solo si description is not None.


🟡 Estilo y consistencia (PEP8)

  • Faltan 2 líneas en blanco entre funciones en bot/services/event_service.py (db.commit() → def update_event_status). (E305)
  • Falta newline al final de archivo en bot/cogs/general.py, bot/cogs/events.py y bot/services/event_service.py.
  • Espacio trailing en intents.guild_scheduled_events = True .
  • Parámetro before sin usar en on_scheduled_event_update → renombrar a _before.
  • @bot.event en setup_hook: funciona en discord.py 2.7.1 (event() hace setattr), pero es poco habitual y frágil ante cambios de versión. Alternativa más idiomática y testeable: subclase commands.Bot con async def setup_hook(self).
  • Integrar ruff o black como formatter + pre-commit para evitar regresiones.

🧪 Testing y CI

  • No hay tests automatizados. El PR debería incluir pytest que verifique: que GeneralCog registra los 3 comandos, que están scope-ados al guild (get_commands(guild=GUILD)), y que los handlers responden (base: el sanity/check que validé en local).
  • El paso "Verificar importación" del CI no cubre general.py: al intentarlo fallaría con int(None) por el punto 6. El fix de lazy GUILD + validate_settings() deja ambos consistentes.
  • CI: hacer el import del cog en el job para blindarlo.

✅ Lo que está bien del PR

  • Migración correcta de los 3 comandos a GeneralCog; main.py queda limpio.
  • Carga por extensiones (load_extension) y sync en setup_hook (deja de depender de on_ready, que puede dispararse varias veces).
  • /ayuda dinámico y ordenado — buen paso de escalabilidad.
  • setup async correcto para discord.py 2.7.1 (add_cog es coroutine y _load_from_module_spec hace await setup(bot)).
  • Los archivos del web dashboard (bot/web/, list_events, requirements.txt) quedaron correctamente fuera del PR.

🎯 Prioridad sugerida para mitigar

  1. Fijar 1, 2 y 3 (bloquean arranque en entornos limpios / configs inválidas).
  2. Aplicar 4 (error handler) y 5/6 (centralización + lazy guild).
  3. Estilo y tests antes de quitar el Draft.

Quedo disponible para implementar los fix cuando me lo indiques.

Comment thread bot/cogs/__init__.py Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cambios innecesarios, solo añadio lineas.

Comment thread bot/cogs/general.py Outdated


class GeneralCog(commands.Cog):
"""Comandos generales de ATLAS."""

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cadena de comillas triples (triple-quoted string) innecesario, ojo que son detalles no es necesario cambiarlo.

Comment thread bot/database/__init__.py Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ojo con estos cambios innecesarios, el modificar archivos y dejarlos vacios es ruido visual para el mantenedor (Mas archivos para analizar y menos enfoque en los necesarios)

@Axel-DaMage Axel-DaMage left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review hecha.

  • Axel-DaMage

@ranto-dev05
ranto-dev05 marked this pull request as ready for review August 15, 2026 18:14
Axel-DaMage
Axel-DaMage previously approved these changes Aug 15, 2026
@Axel-DaMage
Axel-DaMage merged commit ef2d5ac into main Aug 15, 2026
3 checks passed
@Axel-DaMage
Axel-DaMage deleted the feat/general-cog branch August 15, 2026 21:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request Priority: Low Baja prioridad - consideracion futura Status: Pending Necesita revision inicial

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor: migrar comandos /ping, /github, /ayuda a GeneralCog

4 participants