Documentación
Wiki
Cómo se usa BogaBot y cómo levantar tu propia instancia en tu server. El bot es de uso libre: clonás el repo y lo corrés con tu propio bot y tus propios tokens.
Qué es
BogaBot es un bot de Discord modular. El módulo 1 (el MVP actual) es el ranking de League of Legends de un grupo de amigos: vincular cuenta de Riot → ingerir partidas desde la Riot API 1×/día → calcular un puntaje configurable por jugador → publicar rankings en Discord.
Está armado por capas reemplazables: el storage vive detrás de una interfaz (hoy es “Discord como base de datos”, migrar a SQLite o Postgres es una clase nueva), los módulos son cogs autocontenidos y la fórmula del ranking es un archivo YAML editable sin tocar código.
Para jugadores
Si el bot ya está en tu server, lo único que tenés que hacer es vincularte:
- Corré
/link Nombre#TAGcon tu Riot ID completo (el nombre y el tag que ves en el cliente de LoL, ej.Faker#KR1). - El bot valida la cuenta contra la Riot API. Si existe, queda vinculada y tus partidas de esta semana empiezan a contar.
- Usá
/rankingcuando quieras ver la tabla, o esperá el posteo automático de cada noche.
Requisitos
Runtime | Python · discord.py · aiohttp |
|---|---|
Cuenta de Discord | Con permiso para crear una Application y un bot |
Riot API key | Development (vence cada 24 h) o Production |
Server de Discord | Donde invitás el bot, con canales y roles propios |
Hosting | Local (python run.py) o una VPS con systemd |
Setup en Windows / PowerShell: python -m venv venv → venv\Scripts\activate → pip install -r requirements.txt.
Crear el bot en Discord
Paso 1
Crear el bot en Discord
En el Developer Portal: New Application → pestaña Bot → Reset Token. Ese valor va en DISCORD_TOKEN. Dejá los Privileged Gateway Intents apagados, el bot no los necesita.
Paso 2
Invitarlo a tu server
OAuth2 → URL Generator. Scopes: bot y applications.commands. Permisos: Send Messages, Read Message History, Embed Links, View Channel y Manage Roles (esta última solo si vas a usar LOL_ROLE_ID).
Paso 3
Activar el modo desarrollador
Ajustes de usuario → Avanzado → Modo de desarrollador. Con eso, click derecho sobre cualquier canal, rol o server te deja copiar su ID.
Permisos al invitarlo
En OAuth2 → URL Generator, scopes bot y applications.commands. Bot permissions:
- Send Messages, Embed Links, View Channel y Read Message History en los canales de storage y de rankings.
- Manage Roles solo si vas a usar
LOL_ROLE_ID(para que el bot asigne ese rol al vincular). - No requiere intents privilegiados: dejalos apagados.
Canales y roles
Con el modo desarrollador activado (Ajustes → Avanzado), click derecho sobre cada canal o rol te deja copiar su ID. Necesitás también el ID del server para DISCORD_GUILD_ID.
| Creá esto | Tipo | Variable | Para qué |
|---|---|---|---|
| Canal de texto privado (solo lo ve el bot) | canal | STORAGE_CHANNEL_ID | El bot lo usa como base de datos: guarda mensajes JSON acá. Nadie más debería verlo ni escribir en él. |
| Canal público para los rankings | canal | RANKING_CHANNEL_ID | Donde se postean el ranking diario y el recap semanal. |
| Canal de avisos de partida terminada · opcional | canal | MATCH_NOTIFY_CHANNEL_ID | Si lo seteás, el bot avisa en vivo cuando termina una partida jugada por el grupo. |
| Canal general (papelones) · opcional | canal | GENERAL_CHANNEL_ID | Donde caen los avisos de papelón (derrota antes de los 25 min). |
| Canal de logs del bot · opcional | canal | LOG_CHANNEL_ID | El bot reenvía acá sus logs WARNING+ (Riot caído, key vencida, etc.) además de la consola. |
| Canal para comandos de admin · opcional | canal | ADMIN_CHANNEL_ID | Si lo seteás, /link-admin e /ingest-now solo se pueden correr ahí. |
| Rol de quien administra el bot | rol | DEV_ROLE_ID | Habilita /link-admin, /unlink-admin e /ingest-now. |
| Rol de jugador / miembro del grupo · opcional | rol | PLAYER_ROLE_ID | Solo afecta qué comandos muestran /help y /ayuda. |
| Rol que se asigna solo al vincularse · opcional | rol | LOL_ROLE_ID | Al hacer /link, el bot te da este rol (necesita permiso Manage Roles). |
STORAGE_CHANNEL_ID es la base de datos del bot (mensajes JSON). No debería verlo ni escribir en él nadie más que el bot.Riot API key
En developer.riotgames.com generás la key. Va en RIOT_API_KEY.
| Tipo de key | Duración | Cuándo |
|---|---|---|
| Development | Vence cada 24 h — hay que regenerarla a mano | Pruebas, desarrollo |
| Production | Estable | El bot corriendo en serio |
Ajustá también RIOT_PLATFORM y RIOT_REGION a tu región. Por defecto está en LAS: RIOT_PLATFORM=la2, RIOT_REGION=americas (LAS, LAN y NA rutean a americas).
CRITICAL (con cooldown de 3 h) que llega a LOG_CHANNEL_ID si lo configuraste.Variables de entorno
Todo sale de un archivo .env — el código nunca hardcodea secretos ni IDs. Ninguno de los .env.* reales se commitea.
| Variable | Descripción |
|---|---|
DISCORD_TOKEN | Token del bot (pestaña Bot → Reset Token). Discord no lo vuelve a mostrar. |
DISCORD_GUILD_ID | ID del server. Opcional, pero registra los slash commands al instante. |
STORAGE_CHANNEL_ID | Canal privado que el bot usa como base de datos. |
RANKING_CHANNEL_ID | Canal donde publica los rankings. |
DEV_ROLE_ID | Rol habilitado para los comandos de administración. |
ADMIN_CHANNEL_ID | Canal donde se pueden correr esos comandos (opcional). |
PLAYER_ROLE_ID | Rol de jugador; define qué ve /help y /ayuda. |
LOL_ROLE_ID | Rol que el bot asigna al vincular una cuenta (opcional). |
MATCH_NOTIFY_CHANNEL_ID | Canal de avisos de partida terminada (opcional). |
GENERAL_CHANNEL_ID | Canal donde se avisan los papelones (opcional). |
MATCH_POLL_INTERVAL_MINUTES | Cada cuántos minutos se chequean partidas nuevas para el aviso en vivo (default 5). |
RIOT_API_KEY | API key de Riot. La development key vence cada 24 h. |
RIOT_PLATFORM | Plataforma de la región (LAS → la2). |
RIOT_REGION | Routing regional (LAS/LAN/NA → americas). |
TIMEZONE | Zona horaria para los cortes de día/semana (default America/Argentina/Buenos_Aires). |
DAILY_POST_HOUR / DAILY_POST_MINUTE | Hora local del job diario. Recomendado 23:55, para que el ranking de hoy no salga vacío. |
LOG_CHANNEL_ID | Canal donde el bot manda sus propios logs (opcional). |
LOG_CHANNEL_LEVEL | Nivel mínimo que se reenvía a ese canal (default WARNING). |
Staging vs. producción
El ambiente lo elige la variable de shell BOGABOT_ENV (se setea en la terminal antes de correr, no dentro del .env):
| BOGABOT_ENV | Carga | Uso |
|---|---|---|
sin setear o staging | .env.staging | Default. Desarrollo y pruebas. |
production | .env.production | El bot real, en el server real. |
# local, default staging python run.py # explícito $env:BOGABOT_ENV = "production" python run.py # con el script (consola + log en logs\) .\scripts\run_bot.ps1 -Environment production
El default es staging a propósito: si te olvidás de setear la variable, nunca corrés contra producción por accidente. Recomendado: staging apunta a otro bot y otro server, no al mismo, porque el storage vive en canales de Discord y mezclarías datos de prueba con datos reales.
Comandos
| Comando | Qué hace | Quién |
|---|---|---|
/link <Nombre#TAG> | Vincula tu cuenta de Riot con tu Discord. Se valida contra la Riot API; si el Riot ID no existe, no guarda nada. | todos |
/unlink | Desvincula tu cuenta. Tus partidas dejan de contar para el ranking. | todos |
/ranking [Hoy | Semana] | Muestra el ranking del grupo on-demand, sin esperar al posteo automático. | todos |
/help · /ayuda | Listan los comandos disponibles según tu rol. Son dos nombres para lo mismo. | todos |
/link-admin <usuario> <Nombre#TAG> | Vincula la cuenta de Riot de otro usuario del server. Requiere el rol dev y, si está configurado, correrse en el canal de administración. | rol dev |
/unlink-admin <usuario> | Desvincula la cuenta de otro usuario del server. | rol dev |
/ingest-now | Fuerza una ingesta de partidas manual. Es idempotente: el dedup por (match_id, puuid) saltea lo que ya está guardado, así que correrlo de más no duplica nada. | rol dev |
/ingest-now es idempotente: el dedup por (match_id, puuid) saltea lo que ya está guardado, así que correrlo de más no duplica nada.
Cómo se calcula el ranking
- Cada partida se guarda como un registro por jugador, pero solo si la jugaste acompañado de al menos otro vinculado del grupo. Las solitarias se descartan en la ingesta (se chequea
metadata.participantsdel JSON de match-v5). - Se excluyen los remakes (menos de 5 min o early surrender).
- Las ventanas son día y semana desde el lunes 00:00 hora local (
TIMEZONE, default Buenos Aires). - En cada ventana se agregan las stats por jugador y el motor de scoring aplica la fórmula de
config/scoring.yaml. - El job diario corre a
DAILY_POST_HOUR:DAILY_POST_MINUTE(recomendado 23:55): ingesta → ranking del día. Los lunes, además, el recap semanal “Trolls y Pros” de la semana que cerró — contando solo Ranked Flex (queue 440), para medir el juego serio del grupo. - Dedup por
(match_id, puuid)sin cursor: cada corrida pide “desde el lunes” y saltea lo ya guardado.
Motor de scoring
La fórmula vive en config/scoring.yaml y se edita sin tocar código. Para cada jugador se calcula cada métrica (promediada por partida), se normaliza entre todos los jugadores y el puntaje final es la suma de peso × valor_normalizado.
aggregation | per_game_average — promedio por partida — justo para quien juega poco vs. mucho |
|---|---|
normalization | zscore — (valor − promedio) / desvío, para que ninguna métrica domine por tener números más grandes |
Métricas activas por defecto
| Métrica | Peso | Qué mide |
|---|---|---|
win_rate | 5.0 | % de victorias |
kda | 3.0 | (kills + assists) / muertes |
avg_deaths | 2.0 ↓ | muertes promedio por partida |
damage_per_min | 1.5 | daño a campeones por minuto |
avg_vision | 1.0 | vision score promedio |
games_played | 0.5 | partidas jugadas (premia participación) |
↓ = menos es mejor (el valor normalizado se invierte). El motor soporta además avg_kills, avg_assists, cs_per_min, desactivadas por defecto — se activan agregándolas al YAML.
Avisos en vivo y logs
Partida terminada
Si MATCH_NOTIFY_CHANNEL_ID está seteado, cada MATCH_POLL_INTERVAL_MINUTES (5 por defecto) el bot chequea partidas nuevas y, por cada una jugada con otro vinculado, postea un mensaje etiquetando a los jugadores del grupo que la jugaron — con el resultado de cada uno, por si terminaron en equipos contrarios.
Trolleadas y papelones
Cada corrida del scheduler detecta, entre las últimas 48 h, partidas trolleadas (KDA < 0.5 y FF antes de los 20 min) y papelones (derrota antes de los 25 min). Las trolls avisan en RANKING_CHANNEL_ID; los papelones en GENERAL_CHANNEL_ID. Hay un ranking histórico de trolls, y el aviso consulta el timeline de la partida para mostrar en qué minuto moriste por primera vez.
Logs a Discord
Si LOG_CHANNEL_ID está seteado, los logs de nivel LOG_CHANNEL_LEVEL (WARNING por defecto) o superior se reenvían también a ese canal, además de la consola. Pensado para enterarte de errores (Riot caído, key vencida) sin mirar la terminal.
Deploy
Local
python run.py directo, o .\scripts\run_bot.ps1 [-Environment production], que abre consola visible y espeja todo a logs\<ambiente>\. No levantes dos instancias contra el mismo ambiente/server: te responderían los comandos dos veces.
VPS (systemd)
El repo trae deploy/bogabot.service. El setup es una vez: clonar, venv + pip install, copiar el .env por scp, instalar el service y systemctl enable --now bogabot. Después, cada push a main que pase los tests se despliega solo por GitHub Actions (git pull + pip install + systemctl restart).
sudo cp deploy/bogabot.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now bogabot
sudo journalctl -u bogabot -f # logs en vivoEstado y límites
- Alcance: módulo 1 (ranking de LoL). Sin funciones de IA todavía — están en el backlog como cog aparte.
- Storage: hoy es Discord (mensajes JSON en un canal privado + índice en memoria). Es O(n) mensajes; migrar a una DB real es una clase nueva en
storage/y una línea enbot.py. - Colas:el ranking diario/semanal cuenta todas las colas (incluye ARAM y rotativos); el recap “Trolls y Pros” solo Ranked Flex.
- Región: decisión tomada para LAS (
la2/americas); configurable para otras.
Bugs, ideas y pedidos → issues del repo.