Objetivos de aprendizado
Depois de ler este artigo, você vai conseguir:
- Separar bot de prefixo (mensagens) de bot de slash commands (interações)
- Diagnosticar intent, registro de comandos, permissões e o prazo de 3 segundos
- Corrigir cada causa com código atual do discord.js v14
Nesta página
- Como saber se o bot recebe o evento?
- Por que o bot de prefixo ignora as mensagens?
- Por que o slash command não aparece ou não faz nada?
- Por que aparece "O aplicativo não respondeu"?
- O bot tem permissão para responder naquele canal?
- E se o handler falhar em silêncio?
- Como fazer isso na Square Cloud
- Perguntas frequentes
O bot está com a bolinha verde, mas você digita o comando e nada acontece. Isso é diferente de um bot offline: aqui a conexão com o Gateway existe, e o problema está no que o bot recebe, no que ele pode fazer ou no tempo que leva para responder.
A primeira pergunta decide todo o diagnóstico: o seu comando é uma mensagem com prefixo (!ping) ou um slash command (/ping)? Os dois caminhos usam eventos diferentes e quebram por motivos diferentes.
Como saber se o bot recebe o evento?#
Antes de suspeitar de intent ou permissão, prove que o evento chega. Um console.log na primeira linha do handler separa "o bot nem recebe" de "recebe e falha depois".
import { Client, Events, GatewayIntentBits } from "discord.js";
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
});
client.on(Events.MessageCreate, (m) => console.log("msg:", JSON.stringify(m.content)));
client.on(Events.InteractionCreate, (i) => console.log("interaction:", i.type, i.commandName));
client.login(process.env.DISCORD_TOKEN);Se msg: aparece com "" (vazio) para mensagens que têm texto, a causa é a intent de conteúdo. Se nada aparece para o slash command, o problema é registro ou escopo. Se aparece e o usuário não vê resposta, o problema é permissão, erro no handler ou tempo.
Por que o bot de prefixo ignora as mensagens?#
É a causa mais comum. Sem a intent privilegiada Message Content (valor 1 << 15, 32768), o Discord entrega os campos content, embeds, attachments, components e poll vazios. As exceções são mensagens do próprio bot, DMs com o bot, mensagens que mencionam o bot e a mensagem alvo de um comando de menu de contexto.
Por isso message.content.startsWith("!") nunca é verdadeiro: o bot recebe o evento, mas o texto não vem. Corrija em dois lugares:
- No Developer Portal, página Bot, ligue Message Content Intent. Apps não verificados ligam direto. A verificação é obrigatória a partir de 100 servidores, e aí a intent também precisa ser aprovada.
- No código, declare a intent:
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
],
});Se você declara a intent no código sem ligá-la no portal, o Gateway fecha a conexão com o código 4014 (o bot fica offline, não mudo). Mais detalhes em erro de intents no bot do Discord. Se o bot só precisa de comandos, migrar para slash commands elimina a dependência dessa intent.
Por que o slash command não aparece ou não faz nada?#
Um slash command não passa a existir só porque o bot está rodando. Ele precisa ser registrado pela API HTTP: PUT /applications/{id}/commands para global, PUT /applications/{id}/guilds/{guild_id}/commands para um servidor. Se você só escreveu o handler, o Discord não conhece o comando.
Confira:
- Registrou? Comandos de servidor atualizam na hora, então use-os para testar. Comandos globais servem para produção.
- Convidou com o escopo certo? Criar comandos em um servidor exige o escopo
applications.commands. O escopobotjá o inclui, mas um convite feito só com outros escopos não. - É o servidor certo? Um comando registrado em um servidor não existe nos outros nem em DMs.
- Limites: são 100 comandos
CHAT_INPUTglobais e 200 criações de comando por dia, por servidor. Em vez de recriar um a um, use o bulk overwrite (PUT), que substitui a lista inteira (comandos omitidos são removidos).
Por que aparece "O aplicativo não respondeu"?#
O Discord exige uma resposta inicial à interação em até 3 segundos. Passou disso, o token é invalidado e o usuário vê a falha. O mesmo acontece se o handler lança uma exceção antes de responder. Consultar banco, chamar API externa ou gerar imagem costuma estourar esse prazo.
A solução é reconhecer a interação primeiro e responder depois:
import { MessageFlags } from "discord.js";
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName !== "relatorio") return;
try {
await interaction.deferReply(); // responde em menos de 3 s, usuário vê "pensando..."
const texto = await gerarRelatorio(); // pode demorar
await interaction.editReply(texto); // o token vale por 15 minutos
} catch (err) {
console.error(err);
if (interaction.deferred || interaction.replied) {
await interaction.editReply("Algo deu errado.");
} else {
await interaction.reply({ content: "Algo deu errado.", flags: MessageFlags.Ephemeral });
}
}
});O token da interação vale 15 minutos para editReply e followUp. Dois erros relacionados aparecem no log: 10062 Unknown interaction (a interação expirou) e 40060 Interaction has already been acknowledged (você respondeu duas vezes; troque o segundo reply por followUp ou editReply).
O bot tem permissão para responder naquele canal?#
Se o evento chega e o código roda sem erro, mas nada aparece, o bot pode não ter permissão de enviar. No log você vê:
DiscordAPIError[50013]: Missing Permissions
DiscordAPIError[50001]: Missing Access50013 é falta de permissão para a ação (por exemplo, Send Messages ou Embed Links) e 50001 é falta de acesso ao canal (View Channel). A causa costuma ser um override de permissão no canal ou na categoria que sobrepõe o cargo do bot. Teste com o cargo do bot em Administrador num servidor de teste: se passar a funcionar, o problema é permissão, e você ajusta o mínimo necessário. Não deixe Administrador em produção.
E se o handler falhar em silêncio?#
Em código async, uma exceção sem try/catch vira uma promessa rejeitada sem tratamento. Nas versões atuais do Node.js isso derruba o processo por padrão, e se algum wrapper engolir a rejeição, o erro nem aparece. Adicione process.on("unhandledRejection", console.error) e trate erros no handler, como no exemplo acima. Confira também o rate limit: um loop que envia mensagens demais recebe 429 e fica mudo por alguns segundos, caso explicado em erro 429 no Discord.
Por fim, mudanças de código só valem depois de reiniciar o processo. Se você editou o handler e nada mudou, confirme que a versão nova é a que está rodando.
Como fazer isso na Square Cloud#
Para diagnosticar um bot mudo, o que você mais precisa é do log em tempo real. Na Square Cloud ele aparece no painel, na CLI, na extensão do VS Code e no app de celular, então dá para colocar os console.log acima, reiniciar e ver o resultado na hora.
O token fica nas variáveis de ambiente da aplicação (painel, API, CLI ou VS Code), e a mudança vale no próximo restart, sem rebuild. A hospedagem aceita discord.js, discord.py, JDA, Discord.Net ou qualquer biblioteca de Gateway. Cada aplicação de fundo, como um bot, reserva no mínimo 256 MB do pool de RAM do plano.
Veja a página de hospedagem de bots do Discord para os detalhes e os planos.
Hospedagem de bots
Seu bot online 24/7, com reinício automático
Perguntas frequentes
Por que meu bot aparece online mas não responde a !comandos?
O conteúdo das mensagens é uma intent privilegiada. Sem a Message Content ligada no Developer Portal e declarada no código, o campo content chega vazio e o seu prefixo nunca casa.
O que significa 'O aplicativo não respondeu' num slash command?
O Discord exige uma resposta inicial em até 3 segundos. Se o handler demora mais, ou lança erro antes de responder, o usuário vê essa falha. Use deferReply() para ganhar tempo.
Meu slash command novo não aparece na lista. O que fazer?
Comandos só existem depois de registrados pela API (PUT em /applications/{id}/commands). Registre como comando de servidor para testar, porque eles atualizam na hora, e confirme que o bot foi convidado com o escopo applications.commands.
O bot responde no meu servidor de teste mas não em outros. Por quê?
Normalmente é permissão: o bot precisa de View Channel e Send Messages no canal, e um cargo ou override pode negar isso. Também vale checar se o comando foi registrado só nesse servidor.
Mais em Bots
Ver todos os 33 artigos- Quanto custa hospedar um bot do Discord?O custo de hospedar um bot do Discord depende de RAM, tempo online, banco de dados e serviços externos. Veja como estimar o seu e onde o gasto aparece.
- Rodar bot no celular (Termux) ou no PC vs hospedar: o que mudaUm bot no PC ou no celular (Termux) fica offline quando o aparelho desliga, dorme ou perde a rede. Compare as três opções e veja quando cada uma serve.
- Como deixar um bot do Discord online 24/7Para deixar um bot do Discord online 24/7, rode o processo numa máquina sempre ligada com reinício automático. Veja PC, VPS com pm2 ou systemd e hospedagem.
- Por que meu bot do Discord fica offline (e como resolver)Bot do Discord offline quase sempre é processo caído, token inválido, intent não habilitada ou falta de memória. Veja como diagnosticar cada causa e corrigir.