Pular para o conteúdo principal

Gateway

Todo o tempo real do Concord passa por um WebSocket:

wss://app.concord.win/ws

Não há sharding, não há intents, não há segundo socket para voz. Um bot e o aplicativo web falam exatamente o mesmo protocolo.

Entrar​

Duas regras e nada mais:

  1. a primeira mensagem precisa chegar em 10 segundos, senão a conexão é fechada sem aviso;
  2. ela é um JSON com o campo token.
{"type": "auth", "token": "Bot NDc.xxxxxxxx…"}
O type dessa primeira mensagem é decorativo

O servidor lê só o campo token. Mandar {"token": "..."} sozinho funciona igual. O "type": "auth" está aí porque o cliente web manda — não porque alguém o leia.

O prefixo Bot é o que diz ao servidor que isso é um token de aplicação e não um token de sessão de pessoa. Se o seu cliente consegue mandar cabeçalho no handshake (qualquer coisa fora do navegador consegue), prefira o cabeçalho e deixe o frame sem prefixo:

Authorization: Bot NDc.xxxxxxxx…

Deu certo, chega o welcome:

{"type": "welcome", "me": {"id": 47, "name": "Tocadiscos", "bot": true, …},
"ice": {…}, "room": null, "sfu": true}

Deu errado:

{"type": "error", "code": "auth", "message": "Sessão inválida, entre de novo"}

Depois do welcome vem um state, e aí a conexão está pronta.

Formato das mensagens​

Todas, nos dois sentidos, são JSON com um campo type em snake_case:

{"type": "chat", "channel": 12, "text": "oi"}

Mensagem maior que 256 KB derruba a conexão.

state é uma foto, não um delta​

{"type": "state", "servers": [...], "online": [...]}

O state chega no começo e de novo a cada mudança que afete o que você vê: alguém entrou na voz, um canal nasceu, um cargo mudou. Ele nunca é parcial — é sempre o retrato inteiro.

Então substitua o seu estado local por ele. Quem tenta mesclar state com o que já tinha acaba com canal fantasma e membro duplicado.

O que o bot normalmente escuta​

typeQuando chega
welcomelogo depois do login
stateno começo e a cada mudança estrutural
chatmensagem nova num canal de texto
chat_edited / chat_deletededição e remoção
dmmensagem direta
joined / leftvocê entrou ou saiu de um canal de voz
signalsinalização WebRTC entre pares
error / warn / inforecusas e avisos

O que o bot normalmente manda​

typePara quê
chat{"type":"chat","channel":12,"text":"oi"}
chat_reactreagir — o campo é e, não emoji
historypedir mensagens antigas de um canal
join / leaveentrar e sair de um canal de voz
mediao que está ligado na voz
presenceidle, dnd ou invisible
statuso recado ao lado do nome

As cinco armadilhas​

Estas não dá para adivinhar lendo o protocolo. Todas já custaram tempo.

1. Não existe evento de interação​

Não há interaction_create nem caixa de comandos no gateway. Comando de barra é texto. Seu bot lê o chat, vê que começa com o prefixo e despacha:

if (msg.text.startsWith('/')) despachar(msg);

É por isso que o nescord dispara @SlashCommand a partir do messageCreate.

2. Menção é texto puro​

Não existe <@47>. Menção é literalmente @usuario, @everyone, @todos, @aqui, @here.

Isso tem consequência de segurança: se o seu bot ecoa texto de alguém (nome de música, resultado de busca), ele pode ecoar um @everyone. Veja Boas práticas.

3. O envio não volta com id​

O servidor não confirma um chat com o id da mensagem. Ele reemite um chat para todo mundo do canal, inclusive para quem mandou. Quem precisa do id (para editar ou apagar depois) casa o eco pelo autor e pelo texto.

E sim: seu bot recebe de volta as próprias mensagens. Ignore msg.from === meuId ou você entra em laço.

4. presence só aceita três valores​

idle, dnd, invisible. Qualquer outra coisa vira string vazia, que é o mesmo que "online". Mandar "online" funciona por acidente, não por desenho.

5. media exige os quatro booleanos​

{"type": "media", "mic": true, "cam": false, "screen": false, "deaf": false}

Faltando um campo, a mensagem é descartada em silêncio. Não há valor padrão.

Reconexão​

A conexão cai: internet, deploy, reinício. O Concord guarda a vaga na voz por 20 segundos. Se você voltar dentro disso, o welcome vem com room preenchido e o bot continua na sala.

Fora desses 20 segundos, a vaga é liberada e é preciso mandar join de novo.

O token do bot não vence por tempo. O que o derruba é alguém gerar outro no portal — aí a conexão cai e reconectar não adianta: o token antigo não existe mais.