El mayor portal de MU Online de Brasil — desde 2003
Tutorial Intermedio Eventos

Cómo automatizar el anuncio de eventos multiplataforma en tu servidor de MU Online

Configura un pipeline que lee los eventos del GameServer (Blood Castle, Devil Square, Chaos Castle, Invasiones) y publica el aviso automáticamente en Discord, Telegram y el sitio web, sin depender de un admin conectado.

GA Gabriel · Actualizado el 5 may 2026 · ⏱ 14 min de lectura
Respuesta rápida

Anunciar eventos como Blood Castle, Devil Square, Chaos Castle e Invasiones manualmente es una de las tareas más repetitivas — y más fáciles de olvidar — en la administración de un servidor de MU Online. Un admin que tiene que estar pendiente del reloj para publicar "¡Devil Square en 5 minutos!" en

Anunciar eventos como Blood Castle, Devil Square, Chaos Castle e Invasiones manualmente es una de las tareas más repetitivas — y más fáciles de olvidar — en la administración de un servidor de MU Online. Un admin que tiene que estar pendiente del reloj para publicar "¡Devil Square en 5 minutos!" en Discord, Telegram y el sitio pierde tiempo y, inevitablemente, falla en los horarios pico. Este tutorial muestra cómo armar un pipeline simple que lee el estado de los eventos directamente de la base de datos o de los logs del GameServer y publica el aviso automáticamente en los tres canales, con la infraestructura mínima. Vas a aprender la estructura del script, los webhooks de cada plataforma, el cálculo del "T-minus" antes del evento y cómo evitar mensajes duplicados.

Por qué automatizar el anuncio de eventos

Los eventos con cronograma fijo (Devil Square cada hora, Blood Castle en horarios específicos) y los eventos dinámicos (Invasión de Kundun, Red Dragon) tienen un patrón en común: el jugador solo participa si sabe que está pasando. Las comunidades que anuncian manualmente tienen una tasa de participación inconsistente — cae mucho de noche, de madrugada, o cuando el admin está ausente. Un pipeline automatizado garantiza consistencia 24/7, reduce la carga operativa del equipo y profesionaliza la percepción del servidor ante los jugadores.

Arquitectura de la solución

El diseño más simple y robusto tiene tres componentes: un colector (script que lee el estado de los eventos), un normalizador (transforma el dato crudo en un mensaje estándar) y publicadores (uno por plataforma: Discord, Telegram, sitio web). Ejecutar el colector cada 30-60 segundos vía cron es suficiente para la mayoría de los servidores — no hace falta que sea en tiempo real.

ComponenteFunciónTecnología sugerida
ColectorLee la tabla de eventos de MySQL/MSSQL o parsea el log del GameServerPHP, Python o Node.js
NormalizadorConvierte en {evento, mapa, horario, estado}Función pura, sin I/O
Publicador DiscordEnvía embed vía Webhookcurl o librería HTTP
Publicador TelegramEnvía mensaje vía Bot APIcurl o librería HTTP
Publicador WebEscribe en la tabla eventos_ativos leída por el sitioConsulta SQL directa

Identificando la fuente de datos del evento

Cada emulador guarda el estado del evento de una manera distinta. En IGCN, muchos eventos registran el horario en la tabla EVENT_LOG o en columnas de GameServerInfo; en MuEMU, es común que exista una tabla adyacente a MEMB_STAT o un archivo de log rutinario (Event.log) que registra el inicio/fin. Antes de escribir cualquier script, hacé una consulta exploratoria:

SELECT TOP 20 * FROM EVENT_LOG ORDER BY dtCreate DESC;

Si tu emulador no expone esto en una tabla, la alternativa es leer el archivo de log del GameServer con un tail -f equivalente, filtrando por palabras clave como BloodCastle, DevilSquare, ChaosCastle, Invasion.

Calculando el aviso anticipado (T-minus)

Anunciar solo cuando el evento ya empezó tiene un valor limitado — el jugador necesita tiempo para trasladarse y entrar. Lo ideal es calcular el horario programado y disparar avisos en T-5min y T-1min, además de la apertura del evento. Si tus eventos son cíclicos (por ejemplo, Devil Square cada 60 minutos, en punto :00), el cálculo es directo:

from datetime import datetime, timedelta

def proximo_ciclo(intervalo_minutos=60):
    agora = datetime.now()
    minuto_atual = agora.minute
    proximo = agora.replace(second=0, microsecond=0) + timedelta(minutes=(intervalo_minutos - minuto_atual % intervalo_minutos))
    return proximo

Para eventos dinámicos (Invasiones disparadas por un script del servidor), el T-minus no existe de antemano — en ese caso, el anuncio siempre es "evento iniciado ahora", disparado en el instante en que el colector detecta el cambio de estado.

Publicando en Discord vía Webhook

El Discord Webhook es la forma más simple de publicar sin mantener un bot corriendo. Creá el webhook en Configuración del canal → Integraciones → Webhooks y usá la URL generada:

curl -X POST "$DISCORD_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{
    "embeds": [{
      "title": "⚔️ ¡Devil Square empieza en 5 minutos!",
      "description": "Nivel recomendado: 380+\nLugar: Devias 2\nEntrada: NPC Devil Messenger",
      "color": 15158332
    }]
  }'

Usá embeds en vez de texto plano — quedan visualmente destacados y permiten color, título y descripción por separado, lo que ayuda al jugador a identificar rápidamente qué evento está por empezar.

Publicando en Telegram vía Bot API

Creá un bot con @BotFather, obtené el token y el chat_id del canal/grupo, y publicá con una llamada HTTP simple:

curl -X POST "https://api.telegram.org/bot$TELEGRAM_TOKEN/sendMessage" \
  -d chat_id="$TELEGRAM_CHAT_ID" \
  -d parse_mode="Markdown" \
  -d text="*Chaos Castle* empieza en 5 minutos! Nivel recomendado: 400+."

A diferencia de Discord, Telegram no exige crear un "webhook de canal" — el bot solo necesita ser administrador del canal/grupo de destino para poder publicar.

Sincronizando con el sitio (banner de "evento en vivo")

Además de las redes sociales, conviene registrar el estado actual en una tabla simple leída por el front-end del sitio, para mostrar un banner "¡Devil Square en vivo ahora!" en la home:

INSERT INTO eventos_ativos (evento, mapa, inicio, fim)
VALUES ('Devil Square', 'Devias 2', NOW(), DATE_ADD(NOW(), INTERVAL 15 MINUTE));

El front-end consulta esa tabla vía API cada pocos segundos (o usa websocket, si la stack ya lo soporta) y muestra/oculta el banner a medida que el fim expira.

Evitando anuncios duplicados

El mayor riesgo de un script corriendo en un intervalo corto es publicar el mismo aviso varias veces. Resolvelo con una tabla o archivo de control que guarda el último "hash de evento" ya anunciado (por ejemplo, evento + horario_programado), y el colector solo publica si el hash es nuevo:

CREATE TABLE eventos_anunciados (
  hash_evento VARCHAR(64) PRIMARY KEY,
  anunciado_em DATETIME DEFAULT NOW()
);

Antes de publicar, intentá insertar el hash; si da error de clave duplicada, el script simplemente lo ignora y continúa — es una forma barata y confiable de idempotencia.

Programando la ejecución (cron)

En Linux, un cron cada minuto es suficiente:

* * * * * /usr/bin/php /var/www/scripts/anunciar_eventos.php >> /var/log/mu/anuncios.log 2>&1

En Windows, usá el Programador de Tareas con un disparador "repetir cada 1 minuto" que llame al script PHP/Python vía línea de comandos. Asegurate de que el log se rote (mirá el tutorial de limpieza de logs) para no acumular gigabytes de ejecuciones repetidas.

Manejando fallas de red y reintentos

Las llamadas a APIs externas fallan eventualmente — Discord y Telegram tienen límites de tasa e inestabilidades puntuales. Implementá un reintento simple con backoff exponencial (1s, 2s, 4s) y un límite de intentos (por ejemplo, 3), registrando la falla definitiva en un log sin trabar el resto del flujo:

IntentoEspera antesAcción si falla
10sReintenta
21sReintenta
32sReintenta
4 (final)4sRegistra en log de falla y continúa

Personalizando el mensaje por tipo de evento

Cada evento tiene un público y una urgencia diferentes — conviene tener una plantilla por tipo, con nivel recomendado, lugar y recompensa esperada, para que el jugador decida rápidamente si vale la pena participar:

EventoNivel recomendadoRecompensa típica
Blood CastleVaría según el nivel de la BCBox of Luck, Jewels
Devil Square380+Jewels, ítems raros
Chaos Castle400+Combinación de Chaos, PK reset
Invasión de KundunTodosDrop de ítems de boss
Red Dragon InvasionTodosBoxes exclusivas de evento

Errores comunes y soluciones

SíntomaCausa probableSolución
Anuncio duplicado en DiscordFalta de control de idempotenciaImplementá una tabla de hash de evento anunciado
No se publica ningún anuncioLa consulta apunta a la tabla/columna equivocada del emuladorConfirmá el schema real con una consulta exploratoria
El webhook devuelve 401/404URL del webhook vencida o canal eliminadoGenerá un nuevo webhook y actualizá la variable de entorno
El mensaje llega tardeCron corriendo en un intervalo muy largoReducí el intervalo a 30-60s
El bot de Telegram no publicaEl bot no es admin del canalAgregá el bot como administrador del canal/grupo
El script traba el servidorLlamada de red sin timeoutDefiní un timeout de pocos segundos en toda llamada HTTP

Lista de verificación de automatización de eventos

  • Fuente de datos del evento identificada y probada (tabla SQL o log).
  • Script colector corriendo vía cron/Programador en un intervalo de 30-60s.
  • Webhook de Discord configurado y probado con un mensaje real.
  • Bot de Telegram creado, agregado como admin y probado.
  • Tabla de idempotencia (eventos_anunciados) creada y funcionando.
  • Banner del sitio sincronizado con la tabla eventos_ativos.
  • Reintentos con backoff implementados para fallas de red.
  • Logs de ejecución con rotación configurada.

Con el anuncio de eventos corriendo solo, tu equipo libera tiempo para enfocarse en contenido y soporte en lugar de estar pendiente del reloj. Si todavía estás armando la base del servidor antes de automatizar este flujo, empezá por el tutorial de creación de servidor de MU Online.

Preguntas frecuentes

¿Necesito un bot propio o alcanza con webhooks?

Para la mayoría de los casos, los webhooks (Discord Webhook y Telegram Bot API) resuelven el problema sin necesidad de alojar un bot completo. Un bot dedicado solo vale la pena si querés comandos interactivos, como '/proximoevento', además del anuncio automático.

¿El anuncio puede avisar con anticipación (por ejemplo, 5 minutos antes)?

Sí, siempre que tu script lea el horario programado del evento (mediante una tabla de la base de datos o la configuración del GameServer) y no solo el evento en curso. El tutorial muestra cómo calcular el T-5min a partir del ciclo configurado.

¿Esto funciona con cualquier emulador (IGCN, MuEMU, X-Team)?

La lógica es la misma, pero el nombre de las tablas/columnas de evento cambia entre emuladores. Vas a necesitar identificar dónde tu emulador guarda el estado del evento (tabla SQL, archivo de log o memoria compartida) y ajustar la consulta.

¿Se puede anunciar en más de un servidor (idiomas diferentes) con el mismo script?

Sí. Basta con parametrizar el script por servidor/idioma y ejecutar una instancia (o un bucle) para cada configuración, apuntando al webhook correspondiente de cada comunidad.

¿Qué pasa si Discord o Telegram están caídos en el momento del evento?

Lo ideal es implementar reintentos con backoff y registro de fallas. Si la llamada falla, registrala en un archivo de log y volvé a intentar en pocos segundos — nunca dejes que el script se trabe por una falla de red.

GA
Editor de guías y builds

Gabriel cubre gameplay, builds de clases, PvP y progresión. Prueba cada estrategia en un servidor antes de publicar.

Sigue leyendo

Artículos relacionados