Ir al contenido

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 para un grupo de amigos. El módulo central es el ranking de League of Legends: vincular cuenta de Riot → ingerir partidas desde la Riot API → calcular un puntaje configurable por jugador → publicar rankings en Discord. Alrededor de eso hay un detector de trolls que juzga cada partida, avisos en vivo, sonidos en los canales de voz y un sistema de puntos canjeables.

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), cada módulo es un cog autocontenido y tanto la fórmula del ranking como el detector de trolls son archivos YAML editables sin tocar código.

Python · discord.py[voice] · aiohttpLAS (la2 / americas) por defecto, configurable por regiónUso libre — clonás el repo y lo levantás en tu server

Para jugadores

Si el bot ya está en tu server, lo único que tenés que hacer es vincularte:

  1. Corré /link Nombre#TAG con tu Riot ID completo (el nombre y el tag que ves en el cliente de LoL, ej. Faker#KR1).
  2. El bot valida la cuenta contra la Riot API. Si existe, queda vinculada y tus partidas de esta semana empiezan a contar.
  3. Usá /ranking cuando quieras ver la tabla, o esperá el posteo automático de cada noche.
Una partida solo cuenta si la jugaste con al menos otro miembro vinculado del grupo, y para el ranking solo cuenta Ranked (Flex o Solo/Duo). Las que jugás sin nadie conocido se descartan.

Además

  • /trolls muestra quién viene trolleando más; /troll-analizar te dice por qué tu última partida sumó (o no) puntos troll.
  • /sonido hace que el bot entre a tu canal de voz y tire un audio.
  • Si tenés el rol de puntos, sumás estando en voz con amigos y jugando LoL. Mirá cuántos tenés con /puntos y canjealos por un sonido propio con /canjear-sonido.
  • Si el server configuró un canal de comandos, usalos ahí. Los que tienen 🔒 en /help te responden solo a vos.

Requisitos

RuntimePython 3.12+ · discord.py[voice] · aiohttp
ffmpegEn el PATH, para reproducir y medir los sonidos (sin él, todo lo demás anda)
Cuenta de DiscordCon permiso para crear una Application y un bot
Riot API keyPersonal API Key (no vence) o Development (vence cada 24 h)
Server de DiscordDonde invitás el bot, con canales y roles propios
HostingLocal (python run.py) o un server Linux con systemd

Setup en Windows / PowerShell: python -m venv venv → venv\Scripts\activate → pip install -r requirements.txt. En Linux: sudo apt install ffmpeg para los sonidos.

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: View Channel, Send Messages, Read Message History y Embed Links; Connect y Speak para los sonidos; Manage Roles 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.

Paso 4

Crear canales y roles

Como mínimo un canal privado de storage, uno público de rankings, el general y un rol de administración. El resto es opcional (ver la tabla completa en la wiki).

Paso 5

Conseguir la Riot API key

En developer.riotgames.com → Register Product → Personal API Key: gratis y no vence (Riot la aprueba a mano). Mientras tanto sirve la Development Key, que vence cada 24 h y se renueva con /riot-key sin reiniciar.

Paso 6

Completar el .env y correr

Con todos los IDs y tokens, completás .env.staging (o .env.production) y corrés python run.py. En el primer arranque registra los slash commands. Para los sonidos, ffmpeg tiene que estar instalado.

Permisos al invitarlo

En OAuth2 → URL Generator, scopes bot y applications.commands. Bot permissions:

  • View Channel, Send Messages, Read Message History y Embed Links en los canales de storage, rankings, general, trolls y avisos.
  • Connect y Speak para los sonidos en los canales de voz.
  • 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á estoTipoVariablePara qué
Canal de texto privado (solo lo ve el bot)canalSTORAGE_CHANNEL_IDEl 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 rankingscanalRANKING_CHANNEL_IDRanking diario, recap semanal "Trolls y Pros" y, si no hay canal de trolls, las alertas troll.
Canal general del servercanalGENERAL_CHANNEL_IDSolo le llega una línea corta por cada papelón histórico (15+ puntos troll). Nada más.
Canal de alertas troll · opcionalcanalTROLL_CHANNEL_IDTrolleadas con su anécdota y el detalle, y el ranking troll diario. Si falta, va al de rankings.
Canal de avisos de partida terminada · opcionalcanalMATCH_NOTIFY_CHANNEL_IDAviso en vivo por cada partida del grupo: los 10 jugadores y el troll-o-metro.
Canal de comandos del bot · opcionalcanalBOT_CHANNEL_IDSi lo seteás, los miembros comunes solo pueden usar comandos ahí (o en el de admin). Los devs, en cualquier lado.
Canal para comandos de admin · opcionalcanalADMIN_CHANNEL_IDLos comandos de administración solo se pueden correr ahí, y ahí llegan los avisos de vencimiento de la Riot key.
Canal de logs del bot · opcionalcanalLOG_CHANNEL_IDEl bot reenvía acá sus logs WARNING+ (Riot caído, key vencida, etc.) además de la consola.
Rol de quien administra el botrolDEV_ROLE_IDHabilita los comandos de administración, de sonidos y de puntos marcados como dev.
Rol de jugador / miembro del grupo · opcionalrolPLAYER_ROLE_IDSolo afecta qué secciones muestran /help y /ayuda.
Rol que junta puntos ("Boguero") · opcionalrolPOINTS_ROLE_IDQuien lo tiene gana puntos en voz y jugando, y puede canjearlos. Sin este rol, el módulo de puntos no se carga.
Rol que se asigna solo al vincularse · opcionalrolLOL_ROLE_IDAl hacer /link, el bot te da este rol (necesita permiso Manage Roles).
El canal de 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 keyDuraciónCuándo
Personal API KeyNo vence. Se pide en Register Product; Riot la aprueba a mano (puede tardar unos días)El bot corriendo en serio. Poné RIOT_KEY_TTL_HOURS=0
DevelopmentVence cada 24 hPara probar mientras llega la otra. Se renueva con /riot-key

/riot-key <key> (rol dev, en el canal de admin) valida la key nueva contra Riot, la aplica sin reiniciar y la guarda en RIOT_KEY_FILE para que sobreviva reinicios. Sin argumento, muestra cuándo vence la actual. Con RIOT_KEY_TTL_HOURS mayor a 0, el bot avisa en el canal de admin (etiquetando al rol dev) RIOT_KEY_WARN_MINUTES antes de que venza y cuando vence.

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).

Si la key vence mientras el bot corre, la ingesta se corta y el bot loguea un CRITICAL (con cooldown de 3 h) que llega al canal de logs. Si cambiás a una key de otra app de Riot, los puuid cambian (vienen encriptados por app): el bot los re-resuelve solo por Riot ID.

Variables de entorno

Todo sale de un archivo .env — el código nunca hardcodea secretos ni IDs, y si falta una variable requerida el bot no arranca y dice cuál. Ninguno de los .env.* reales se commitea.

Discord: token, canales y roles

VariableDescripción
DISCORD_TOKENToken del bot (pestaña Bot → Reset Token). Discord no lo vuelve a mostrar.
DISCORD_GUILD_IDID del server. Opcional, pero registra los slash commands al instante.
STORAGE_CHANNEL_IDCanal privado que el bot usa como base de datos.
RANKING_CHANNEL_IDCanal donde publica los rankings.
GENERAL_CHANNEL_IDCanal general: ahí van solo los papelones históricos.
TROLL_CHANNEL_IDCanal de alertas y ranking troll (opcional; default RANKING_CHANNEL_ID).
MATCH_NOTIFY_CHANNEL_IDCanal de avisos de partida terminada (opcional).
MATCH_POLL_INTERVAL_MINUTESCada cuántos minutos se chequean partidas nuevas, para los avisos y las alertas troll (default 5).
BOT_CHANNEL_IDCanal donde los miembros comunes pueden usar comandos (opcional).
ADMIN_CHANNEL_IDCanal donde se corren los comandos de administración (opcional).
DEV_ROLE_IDRol habilitado para los comandos de administración.
PLAYER_ROLE_IDRol de jugador; define qué ven /help y /ayuda.
LOL_ROLE_IDRol que el bot asigna al vincular una cuenta (opcional).

Riot API

VariableDescripción
RIOT_API_KEYAPI key de Riot. En producción, la Personal API Key (no vence). Se rota en caliente con /riot-key.
RIOT_PLATFORMPlataforma de la región (LAS → la2).
RIOT_REGIONRouting regional (LAS/LAN/NA → americas).
RIOT_KEY_FILEDónde se guarda la key cargada con /riot-key (default data/riot_key.json, permisos 600).
RIOT_KEY_TTL_HOURSHoras de vida de la key para el recordatorio (default 24, la dev key). Con la Personal API Key: 0 = no vence.
RIOT_KEY_WARN_MINUTESCuántos minutos antes de vencer se avisa en el canal de admin (default 120).

Horarios

VariableDescripción
TIMEZONEZona horaria para los cortes de día/semana (default America/Argentina/Buenos_Aires).
DAILY_POST_HOUR / DAILY_POST_MINUTEHora local del job diario (default 10:00). Recomendado 23:55, para que el ranking de hoy no salga vacío.

Archivos de configuración y estado

VariableDescripción
SCORING_CONFIG_PATHFórmula del ranking (default config/scoring.yaml).
TROLLS_CONFIG_PATHUmbrales y puntos del detector de trolls (default config/trolls.yaml).
TROLLS_STATE_FILEDesde cuándo cuenta el ranking troll; lo escribe /trolls-reiniciar (default data/trolls_state.json).

Logs

VariableDescripción
LOG_LEVELNivel de log de la consola (default INFO).
LOG_CHANNEL_IDCanal donde el bot manda sus propios logs (opcional).
LOG_CHANNEL_LEVELNivel mínimo que se reenvía a ese canal (default WARNING).

Sonidos

VariableDescripción
SOUNDS_ENABLEDSonidos al azar en los canales de voz (default true). /sonido anda igual aunque esté apagado.
SOUNDS_DIRCarpeta de los audios, fuera de git (default sounds/).
SOUNDS_CHANCEProbabilidad de que suene uno en cada chequeo, de 0 a 1 (default 0.15).
SOUNDS_CHECK_INTERVAL_MINUTESCada cuánto se tira el dado (default 5).
SOUNDS_COOLDOWN_MINUTESMínimo entre dos sonidos al azar (default 45).
SOUNDS_ACTIVE_FROM / SOUNDS_ACTIVE_TOHorario en que suenan (0-23; puede cruzar la medianoche). 0 y 0 = todo el día.

Puntos y canjes

VariableDescripción
POINTS_ROLE_IDRol que junta y canjea puntos. Sin él, el módulo de puntos no se carga.
POINTS_FILEDónde se guardan los puntos (default data/points.json).
POINTS_VOICE_INTERVAL_MINUTES / POINTS_VOICE_AMOUNTPuntos por estar en voz: cuántos y cada cuánto (default 1 cada 5 min).
POINTS_VOICE_DAILY_CAPTope diario de puntos por voz (default 60).
POINTS_LOL_GAME / POINTS_LOL_WINPuntos por partida de LoL guardada y extra si la ganaste (default 5 y 5).
SOUND_REDEEM_COSTLo que cuesta canjear un sonido (default 100).
SOUND_REDEEM_DAYSDías que dura un sonido canjeado (default 7).
SOUND_REDEEM_MAX_SECONDSDuración máxima del audio canjeado (default 8 s).
SOUND_REDEEM_MAX_ACTIVESonidos canjeados activos por persona (default 1).

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_ENVCargaUso
sin setear o staging.env.stagingDefault. Desarrollo y pruebas.
production.env.productionEl 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

Si hay BOT_CHANNEL_ID, los miembros comunes solo pueden usar comandos en ese canal (o en el de admin); los devs, en cualquier lado. Los comandos de administración (/link-admin, /unlink-admin, /ingest-now, /riot-key, /trolls-reiniciar, /trolls-recalcular) además exigen el canal de admin.

🎮 Ranking LoL

ComandoQué haceQuié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
/unlinkDesvincula 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. Solo cuentan partidas Ranked (Flex y Solo/Duo).todos
/link-admin <usuario> <Nombre#TAG>Vincula la cuenta de Riot de otro usuario del server.rol dev
/unlink-admin <usuario>Desvincula la cuenta de otro usuario del server.rol dev
/ingest-nowFuerza una ingesta de partidas. Es idempotente: el dedup por (match_id, discord_id) saltea lo que ya está guardado.rol dev
/riot-key [key]Carga una RIOT_API_KEY nueva sin reiniciar el bot (la valida y la guarda). Sin key, muestra cuándo vence la actual. La respuesta es efímera: la key no queda visible.rol dev

🤡 Trolls

ComandoQué haceQuién
/trolls [Semana | Semana pasada | Mes | Histórico]Ranking troll por índice (puntos troll promedio por partida): categoría, especialidad, peor partida y tendencia contra el período anterior.todos
/troll-analizar [usuario] [partida]Juzga una partida (por defecto la última guardada): qué cargos troll tiene, cuántos puntos suma cada uno y por qué.todos
/trolls-reglasQué detecta el bot y cuántos puntos suma cada cosa, con la config que está activa.todos
/trolls-reiniciarEl ranking troll arranca de cero desde ahora. Las partidas viejas quedan guardadas.rol dev
/trolls-recalcularVuelve a pedirle a Riot las partidas guardadas con un análisis viejo para completarles stats y timeline. Corre solo al arrancar; esto lo fuerza a mano, en silencio.rol dev

🔊 Sonidos

ComandoQué haceQuién
/sonido [nombre]El bot entra a tu canal de voz, tira el sonido (o uno al azar) y se va.todos
/sonidosLista los sonidos cargados.todos
/canjear-sonido <nombre> <audio>Cambiás puntos por subir un sonido tuyo temporal (por defecto 100 puntos, hasta 8 s, dura 7 días).rol puntos
/sonido-del <nombre>Borra un sonido. El dueño puede borrar el que canjeó; un dev, cualquiera.rol puntos
/sonido-add <nombre> <audio>Sube un sonido permanente (mp3, ogg o wav, hasta 2 MB).rol dev
/sonido-forzar [nombre] [canal]El bot entra a un canal de voz y tira ese sonido. Si hay otro sonando, espera su turno.rol dev

💰 Puntos

ComandoQué haceQuién
/puntos [usuario]Cuántos puntos tenés (o los de otro) y cómo se ganan.todos
/puntos-topRanking de puntos del server.todos
/puntos-dar <usuario> <cantidad>Suma o resta puntos a alguien (cantidad negativa para restar).rol dev

ℹ️ Ayuda

ComandoQué haceQuién
/help · /ayudaListan los comandos que podés usar según tus roles. Son dos nombres para lo mismo y la respuesta la ves solo vos.todos

Cómo se calcula el ranking

  1. 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.participants del JSON de match-v5).
  2. Se excluyen los remakes (menos de 5 min o early surrender).
  3. El ranking diario y el semanal cuentan solo Ranked (Solo/Duo y Flex). Normales, ARAM y rotativos se guardan igual (sirven para el detector de trolls y los puntos), pero no suman al ranking.
  4. Las ventanas son día y semana desde el lunes 00:00 hora local (TIMEZONE, default Buenos Aires).
  5. En cada ventana se agregan las stats por jugador y el motor de scoring aplica la fórmula de config/scoring.yaml.
  6. El job diario corre a DAILY_POST_HOUR:DAILY_POST_MINUTE (recomendado 23:55): ingesta → ranking del día → si hubo trolleadas, cómo va el ranking troll de la semana. 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 — y la corona del Troll de la semana.
  7. Dedup por (match_id, discord_id) sin cursor: cada corrida pide “desde el lunes” (con un día de margen, por las partidas que cruzan la medianoche) 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.

aggregationper_game_average — promedio por partida — calidad sobre cantidad: jugar muchas partidas mediocres no te sube
normalizationzscore — (valor − promedio) / desvío, para que ninguna métrica domine por tener números más grandes

normalization acepta zscore (recomendado), minmax (escala 0..1 entre el peor y el mejor) o none (valor crudo; los pesos se calibran a mano).

Métricas activas por defecto

MétricaPesoQué mide
carry_rate5.0% de partidas carreadas (victoria + KDA ≥ 5)
troll_rate4.0 ↓% de partidas troleadas (KDA < 0.5)
kda3.0(kills + assists) / muertes
win_rate2.0% de victorias
avg_deaths1.5 ↓muertes promedio por partida
damage_per_min1.0daño a campeones por minuto
avg_vision0.5vision score promedio

↓ = menos es mejor (el valor normalizado se invierte). Una partida es carreada si la ganaste con KDA ≥ 5 y troleada si terminaste con KDA < 0,5. El motor soporta además estas métricas, desactivadas por defecto — se activan agregándolas al YAML: avg_kills, avg_assists, cs_per_min, games_played.

Detector de trolls

Después de cada partida, cada jugador del grupo se juzga con las reglas de abajo. Las que dicen timeline usan una consulta más a Riot (qué pasó y cuándo); el resto sale de las stats de la partida. Todo se ajusta en config/trolls.yaml sin tocar código (reiniciando el bot), y como el ranking troll se calcula al vuelo, un cambio ahí recalcula también el historial.

Cómo se suman los puntos

  • Cada regla que se cumple es un cargo con sus puntos troll.
  • En ranked (Solo/Duo o Flex) los puntos se multiplican por ×1,25; si igual ganaron, por ×0,5 (lo llevaron de mochila).
  • Los cargos menores (🔸 en la tabla: mal rendimiento, poca KP, poco daño, línea perdida, visión, farm, primera sangre, FF…) suman entre todos como mucho 4. Para ser trolleada hace falta una señal fuerte: AFK, 0 kills y 0 asistencias, items vendidos, dejar caer la base, feeder, throw o ancla del equipo.
  • Los umbrales cambian según el modo: ARAM y los modos caóticos (URF, One for All…) toleran más muertes, y las reglas de línea y de base son solo de la Grieta.
  • Reglas que miden lo mismo no se suman: feeder reemplaza a KDA de la vergüenza y a tiempo muerto; ciego reemplaza a sin control wards.

Qué pasa según los puntos de la partida

PuntosQué pasa
menos de 8Nada aparte: suma al ranking troll y se ve en el troll-o-metro del aviso de partida.
8 o más🤡 Trolleada: en TROLL_CHANNEL_ID (o el de rankings), una línea con la anécdota etiquetando al jugador, más el detalle compacto.
15 o más💀 Papelón: además, una línea corta en `GENERAL_CHANNEL_ID`. Es lo único que llega a #general.

Solo se avisan partidas de las últimas 36 h (alert_max_age_hours): si el bot estuvo caído o alguien se acaba de vincular, lo viejo no se anuncia.

Ranking troll (/trolls)

Ordena por índice troll — puntos por partida —, no por el total, así que jugar más no suma: el que la trollea fuerte en 2 partidas queda arriba del que jugó 18 y trolleó 2. Para que una partida suelta no decida por azar, cada jugador arranca con 2 partidas “fantasma” que valen el promedio del grupo (index.prior_games) y una sola partida cuenta como mucho 30 puntos (index.max_game_points). Muestra la categoría, el % de partidas trolleadas y la tendencia contra el período anterior (📈 / 📉 / ➡️ / 🆕). /trolls-reiniciar lo pone en cero desde ese momento.

Categorías (según el índice)

😇 Santo · < 8/12 ≈ 0,7🙂 Tranqui · < 8/4 = 2😬 Sospechoso · < 8/2 = 4🤡 Troll · < 8💀 Leyenda troll · ≥ 8

Las reglas

ReglaPtsCuándo
💤 AFK timeline8Minutos seguidos quieto, vivo y sin ganar experiencia.
👻 ¿Estaba AFK?50 kills y 0 asistencias en una partida donde su equipo sí mató.
💸 Liquidación total timeline5Vendió 6 items o más en la partida (inteo).
🏚️ Nos tiraban la base timeline5Cayeron inhibidores o torres del nexo mientras estaba vivo y lejos, sin estar haciendo split push. +3 si estaba farmeando.
🍽️ Feeder profesional3Muertes según lo que duró la partida (≈3,3 cada 10 min, mínimo 8) con KDA < 1. Suma extra por cada 2 muertes de más.
💥 Throw timeline3Lo agarraron solo, sin pelea alrededor, y en menos de un minuto perdieron Barón, Ancestral o el nexo.
⚓ Ancla del equipo2Murió más que los otros cuatro de su equipo juntos (con al menos 7 muertes).
📉 KDA de la vergüenza2KDA menor a 0,5 con al menos 5 muertes (no se suma si ya es feeder).
⚰️ Veraneando en la fuente2Pasó muerto un cuarto de la partida o más.
⏰ Speedrun de muertes timeline23 muertes o más antes del minuto 10.
🚜 Le pasaron el trapo en línea timeline22.500 de oro abajo contra su rival de línea al minuto 15 (1.500 si es support).
🎁 Delivery a domicilio timeline24 muertes o más contra su rival de línea, y que sean buena parte (40%+) de todas sus muertes.
🪶 Daño de cotillón2Menos del 10% del daño de su equipo, salvo que haya tanqueado.
🏝️ Jugando otra partida2Participó en menos del 20% de las kills de su equipo.
🩸 Regaló la primera sangre timeline1Primera muerte de la partida antes del minuto 5 (+1 antes del 3).
🕊️ Pacifista10 kills en 20 minutos o más, con poco daño (no aplica a supports).
🙈 Ciego voluntario1Vision score por minuto muy bajo (a los supports se les exige más).
🧿 Ni un control ward1Cero control wards en 25 minutos, y además visión floja.
🌾 Alérgico al farm1Farm por minuto bajo para su rol, salvo que carree con daño.
🤖 Ejecutado timeline12 muertes o más por torres, minions o monstruos.
💰 Ahorrista timeline1Murió con más de 3.000 de oro encima, antes del minuto 25.
🏳️ FF al 152Derrota por rendición antes del 20. Agravante: solo suma si ya tiene un cargo propio.
🧹 Barrida histórica1Derrota por 20 kills o más de diferencia. Agravante, como el FF.
❓ Tóxico del '?'115 pings de "?" o más.
🥄 Cuchara de madera2Último puesto en Arena.
Las partidas guardadas antes de una versión nueva del análisis se recalculan solas y en silencio al arrancar el bot: sin mensajes, sin logs visibles y sin avisos; lo único que cambia es la tabla troll. /trolls-recalcular fuerza lo mismo a mano.

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 que cuente, postea un cuadro con las 10 posiciones, etiquetando a los jugadores del grupo que la jugaron (con el resultado de cada uno, por si quedaron en equipos contrarios) y un troll-o-metro con los puntos troll de cada uno.

Los avisos salen de cualquier ingesta — el chequeo periódico, el job diario o /ingest-now — y una sola vez por partida: la ingesta tiene un lock y el dedup hace que correr todo junto no duplique nada.

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. Los errores de red contra Riot se reintentan con backoff antes de avisar.

Sonidos

El bot entra a un canal de voz, tira un audio corto y se va. Una sola reproducción a la vez en todo el bot, y cualquier audio se corta a los 20 s por las dudas. Necesita ffmpeg instalado y los permisos Connect y Speak.

Tres formas de que suene

  • A pedido: /sonido [nombre] en tu canal de voz (vacío = uno al azar).
  • Forzado (dev): /sonido-forzar [nombre] [canal] — en el canal que elijas, en el tuyo o en uno con gente al azar. Si hay otro sonando, espera su turno.
  • Al azar: cada SOUNDS_CHECK_INTERVAL_MINUTES (5) el bot tira un dado con SOUNDS_CHANCE (15%). Si sale, dentro del horario activo y pasado el cooldown (SOUNDS_COOLDOWN_MINUTES, 45), elige un canal con al menos una persona (no cuenta el AFK) y un audio al azar. Se apaga con SOUNDS_ENABLED=false.

Cómo se cargan

  • /sonido-add (dev): permanente. mp3, ogg o wav, hasta 2 MB.
  • /canjear-sonido (rol puntos): temporal, pagado con puntos. Ver abajo.
  • Los audios viven en SOUNDS_DIR, fuera de git. Dueño y vencimiento de los canjeados quedan en SOUNDS_DIR/_meta.json; un sonido sin entrada ahí es permanente.

ffmpeg.org ↗

Puntos

Los miembros con POINTS_ROLE_ID juntan puntos y los canjean. Sin ese rol configurado, el módulo no se carga.

Cómo se ganan

  • Voz: 1 punto cada 5 minutos a cada miembro con el rol que esté en un canal de voz con al menos otro humano (no cuenta el canal AFK ni estar ensordecido). Tope: 60 por día.
  • LoL: 5 por cada partida nueva que se guarda y 5 más si la ganaste. El dedup de la ingesta garantiza que cada partida se paga una sola vez.
  • A mano: un dev puede sumar o restar con /puntos-dar.

Canje: un sonido propio

/canjear-sonido <nombre> <audio> cuesta 100 puntos: el audio puede durar hasta 8 s, queda cargado 7 días y se borra solo al vencer. Máximo 1 activo por persona (lo podés borrar antes con /sonido-del). El bot mide la duración con ffprobe y recién cobra si el audio pasa el chequeo, y avisa en el canal que canjeaste. Todos los números se cambian por variables de entorno.

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.

Server Linux (systemd)

El repo trae deploy/bogabot.service. El setup es una vez: clonar, venv + pip install -r requirements.txt, instalar ffmpeg, copiar el .env.production por scp (con permisos 600), instalar el service y systemctl enable --now bogabot. El estado (puntos, key de Riot, reinicio del ranking troll) vive en data/, fuera de git.

sudo apt install ffmpeg
sudo cp deploy/bogabot.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now bogabot
sudo journalctl -u bogabot -f # logs en vivo

Para actualizar: git pull + pip install si cambió requirements.txt + systemctl restart bogabot. Cambiar la key de Riot no requiere deploy: /riot-key desde Discord. El repo trae además un workflow de GitHub Actions que despliega cada push a main que pasa los tests, pensado para cuando haya VPS.

Estado y límites

  • Alcance: beta con el grupo. Módulos de LoL (ranking y trolls), sonidos, puntos y ayuda. 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 en bot.py. Puntos y sonidos canjeados van a archivos JSON en data/ y sounds/.
  • Colas: el ranking diario y semanal cuenta solo Ranked (Solo/Duo y Flex); el recap “Trolls y Pros”, solo Flex. El detector de trolls y los puntos miran todas las colas.
  • Región: decisión tomada para LAS (la2 / americas); configurable para otras.
  • Tests: python -m pytest — scoring, dedup, mapper de match-v5 con timeline, reglas troll, config, ranking troll, ingesta y ruteo de avisos.

Bugs, ideas y pedidos → issues del repo.