O maior portal de MU Online do Brasil — desde 2003
Tutorial Intermediário Eventos

Como automatizar o anúncio de eventos multiplataforma no seu servidor de MU Online

Configure um pipeline que lê os eventos do GameServer (Blood Castle, Devil Square, Chaos Castle, Invasões) e publica o aviso automaticamente no Discord, Telegram e site, sem depender de um admin logado.

GA Gabriel · Atualizado em 5 mai 2026 · ⏱ 14 min de leitura
Resposta rápida

Anunciar eventos como Blood Castle, Devil Square, Chaos Castle e Invasões manualmente é uma das tarefas mais repetitivas — e mais fáceis de esquecer — na administração de um servidor de MU Online. Um admin que precisa ficar de olho no relógio para postar "Devil Square em 5 minutos!" no Discord, no T

Anunciar eventos como Blood Castle, Devil Square, Chaos Castle e Invasões manualmente é uma das tarefas mais repetitivas — e mais fáceis de esquecer — na administração de um servidor de MU Online. Um admin que precisa ficar de olho no relógio para postar "Devil Square em 5 minutos!" no Discord, no Telegram e no site perde tempo e, inevitavelmente, falha em horários de pico. Este tutorial mostra como montar um pipeline simples que lê o estado dos eventos diretamente do banco de dados ou dos logs do GameServer e publica o aviso automaticamente nos três canais, com o mínimo de infraestrutura. Você vai aprender a estrutura do script, os webhooks de cada plataforma, o cálculo do "T-minus" antes do evento e como evitar mensagens duplicadas.

Por que automatizar o anúncio de eventos

Eventos com cronograma fixo (Devil Square a cada hora, Blood Castle em horários específicos) e eventos dinâmicos (Invasão de Kundun, Red Dragon) têm um padrão em comum: o jogador só participa se souber que está acontecendo. Comunidades que anunciam manualmente têm taxa de participação inconsistente — cai muito à noite, de madrugada, ou quando o admin está ausente. Um pipeline automatizado garante consistência 24/7, reduz carga operacional da equipe e profissionaliza a percepção do servidor perante os jogadores.

Arquitetura da solução

O desenho mais simples e robusto tem três componentes: um coletor (script que lê o estado dos eventos), um normalizador (transforma o dado bruto em uma mensagem padrão) e publicadores (um por plataforma: Discord, Telegram, site). Rodar o coletor a cada 30–60 segundos via cron é suficiente para a maioria dos servidores — não precisa ser em tempo real.

ComponenteFunçãoTecnologia sugerida
ColetorLê tabela de eventos do MySQL/MSSQL ou parseia log do GameServerPHP, Python ou Node.js
NormalizadorConverte em {evento, mapa, horario, status}Função pura, sem I/O
Publicador DiscordEnvia embed via Webhookcurl ou lib HTTP
Publicador TelegramEnvia mensagem via Bot APIcurl ou lib HTTP
Publicador WebGrava em tabela eventos_ativos lida pelo siteQuery SQL direta

Identificando a fonte de dados do evento

Cada emulador guarda o estado do evento de um jeito. No IGCN, muitos eventos gravam o horário na tabela EVENT_LOG ou em colunas de GameServerInfo; no MuEMU, é comum existir uma tabela MEMB_STAT-adjacente ou um arquivo de log rotineiro (Event.log) que registra início/fim. Antes de escrever qualquer script, rode uma consulta exploratória:

SELECT TOP 20 * FROM EVENT_LOG ORDER BY dtCreate DESC;

Se seu emulador não expõe isso em tabela, a alternativa é ler o arquivo de log do GameServer com um tail -f equivalente, filtrando por palavras-chave como BloodCastle, DevilSquare, ChaosCastle, Invasion.

Calculando o aviso antecipado (T-minus)

Anunciar só quando o evento já começou tem valor limitado — o jogador precisa de tempo para se deslocar e entrar. O ideal é calcular o horário programado e disparar avisos em T-5min e T-1min, além da abertura do evento. Se seus eventos são cíclicos (ex.: Devil Square a cada 60 minutos, cheio em :00), o cálculo é direto:

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 (Invasões disparadas por script do servidor), o T-minus não existe de antemão — nesse caso, o anúncio é sempre "evento iniciado agora", disparado no instante em que o coletor detecta a mudança de estado.

Publicando no Discord via Webhook

O Discord Webhook é a forma mais simples de publicar sem manter um bot rodando. Crie o webhook em Configurações do Canal → Integrações → Webhooks e use a URL gerada:

curl -X POST "$DISCORD_WEBHOOK_URL" \
  -H "Content-Type: application/json" \
  -d '{
    "embeds": [{
      "title": "⚔️ Devil Square começa em 5 minutos!",
      "description": "Nível recomendado: 380+\nLocal: Devias 2\nEntrada: NPC Devil Messenger",
      "color": 15158332
    }]
  }'

Use embeds em vez de texto puro — eles ficam visualmente destacados e permitem cor, título e descrição separados, o que ajuda o jogador a identificar rapidamente qual evento está começando.

Publicando no Telegram via Bot API

Crie um bot com o @BotFather, pegue o token e o chat_id do canal/grupo, e publique com uma chamada HTTP simples:

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* começa em 5 minutos! Nível recomendado: 400+."

Diferente do Discord, o Telegram não exige criar "webhook de canal" — o próprio bot precisa apenas ser administrador do canal/grupo de destino para poder postar.

Sincronizando com o site (banner de "evento ao vivo")

Além das redes sociais, vale gravar o estado atual em uma tabela simples lida pelo front-end do site, para exibir um banner "Devil Square ao vivo agora!" na home:

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

O front-end consulta essa tabela via API a cada poucos segundos (ou usa websocket, se a stack já suportar) e exibe/oculta o banner conforme o fim expira.

Evitando anúncios duplicados

O maior risco de um script rodando em intervalo curto é publicar o mesmo aviso várias vezes. Resolva com uma tabela ou arquivo de controle que grava o último "hash de evento" já anunciado (ex.: evento + horario_programado), e o coletor só publica se o hash for novo:

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

Antes de publicar, tente inserir o hash; se der erro de chave duplicada, o script simplesmente ignora e segue — é uma forma barata e confiável de idempotência.

Agendando a execução (cron)

No Linux, um cron a cada minuto é suficiente:

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

No Windows, use o Agendador de Tarefas com um gatilho "repetir a cada 1 minuto" chamando o script PHP/Python via linha de comando. Garanta que o log seja rotacionado (veja o tutorial de limpeza de logs) para não acumular gigabytes de execuções repetidas.

Tratando falhas de rede e retry

Chamadas a APIs externas falham eventualmente — Discord e Telegram têm rate limit e instabilidades pontuais. Implemente um retry simples com backoff exponencial (1s, 2s, 4s) e um limite de tentativas (ex.: 3), registrando falha definitiva em log sem travar o restante do fluxo:

TentativaEspera antesAção se falhar
10sTenta novamente
21sTenta novamente
32sTenta novamente
4 (final)4sGrava em log de falha e segue

Personalizando a mensagem por tipo de evento

Cada evento tem público e urgência diferentes — vale ter um template por tipo, com nível recomendado, local e recompensa esperada, para o jogador decidir rapidamente se vale participar:

EventoNível recomendadoRecompensa típica
Blood CastleVaria por nível da BCBox of Luck, Jewels
Devil Square380+Jewels, itens raros
Chaos Castle400+Combinação de Chaos, PK reset
Invasão de KundunTodosDrop de itens de boss
Red Dragon InvasionTodosBoxes exclusivas de evento

Erros comuns e soluções

SintomaCausa provávelSolução
Anúncio duplicado no DiscordFalta de controle de idempotênciaImplemente tabela de hash de evento anunciado
Nenhum anúncio é publicadoQuery aponta para tabela/coluna errada do emuladorConfirme o schema real com uma consulta exploratória
Webhook retorna 401/404URL do webhook expirada ou canal deletadoGere um novo webhook e atualize a variável de ambiente
Mensagem chega atrasadaCron rodando em intervalo muito longoReduza o intervalo para 30–60s
Bot do Telegram não postaBot não é admin do canalAdicione o bot como administrador do canal/grupo
Script trava o servidorChamada de rede sem timeoutDefina timeout de poucos segundos em toda chamada HTTP

Checklist de automação de eventos

  • Fonte de dados do evento identificada e testada (tabela SQL ou log).
  • Script coletor rodando via cron/Agendador em intervalo de 30–60s.
  • Webhook do Discord configurado e testado com mensagem real.
  • Bot do Telegram criado, adicionado como admin e testado.
  • Tabela de idempotência (eventos_anunciados) criada e funcionando.
  • Banner do site sincronizado com a tabela eventos_ativos.
  • Retry com backoff implementado para falhas de rede.
  • Logs de execução com rotação configurada.

Com o anúncio de eventos rodando sozinho, sua equipe libera tempo para focar em conteúdo e suporte em vez de ficar de olho no relógio. Se você ainda está estruturando a base do servidor antes de automatizar esse fluxo, comece pelo tutorial de criação de servidor de MU Online.

Perguntas frequentes

Preciso de um bot próprio ou dá para usar só webhooks?

Para a maioria dos casos, webhooks (Discord Webhook e Telegram Bot API) resolvem sem precisar hospedar um bot completo. Um bot dedicado só vale a pena se você quiser comandos interativos, como '/proximoevento', além do anúncio automático.

O anúncio consegue avisar com antecedência (ex.: 5 minutos antes)?

Sim, desde que seu script leia o horário programado do evento (via tabela do banco ou config do GameServer) e não apenas o evento em andamento. O tutorial mostra como calcular o T-5min a partir do ciclo configurado.

Isso funciona com qualquer emulador (IGCN, MuEMU, X-Team)?

A lógica é a mesma, mas o nome das tabelas/colunas de evento muda entre emuladores. Você vai precisar identificar onde o seu emulador grava o estado do evento (tabela SQL, arquivo de log ou memória compartilhada) e ajustar a query.

Dá para anunciar em mais de um servidor (idiomas diferentes) com o mesmo script?

Sim. Basta parametrizar o script por servidor/idioma e rodar uma instância (ou um loop) para cada configuração, apontando para o webhook correspondente de cada comunidade.

O que acontece se o Discord ou Telegram estiver fora do ar no momento do evento?

O ideal é implementar retry com backoff e log de falha. Se a chamada falhar, registre em um arquivo de log e tente novamente em poucos segundos — nunca deixe o script travar o restante do pipeline por causa de uma falha de rede.

GA
Editor de guias e builds

Gabriel cobre gameplay, builds de classes, PvP e progressão. Testa cada estratégia em servidor antes de publicar.

Continue lendo

Artigos relacionados