Aparência
Seu primeiro bot
Vamos fazer o "olá mundo" dos bots: quando alguém escrever !ping numa sala, o bot responde Pong! 🏓.
1. Prepare a pasta
bash
mkdir meu-bot
cd meu-bot
npm init -y
npm install wsA biblioteca ws cuida do WebSocket. Para as requisições HTTP usamos o fetch, que já vem no Node.
No package.json, adicione "type": "module" para poder usar import:
json
{
"name": "meu-bot",
"type": "module",
"dependencies": {
"ws": "^8.18.0"
}
}Crie o arquivo .env com o token do bot (veja como pegar):
ini
GOLIVE_TOKEN=Bot cole-o-token-aqui2. O código
Crie index.js:
js
// O menor bot possível: responde "!ping" com "Pong!".
//
// npm install ws
// GOLIVE_TOKEN="Bot seu-token" node index.js
import WebSocket from "ws";
const API = process.env.GOLIVE_API_URL ?? "https://apigolive.nemtudo.me";
const GATEWAY = process.env.GOLIVE_GATEWAY_URL ?? "wss://apigolive.nemtudo.me/ws";
const TOKEN = process.env.GOLIVE_TOKEN?.startsWith("Bot ")
? process.env.GOLIVE_TOKEN
: `Bot ${process.env.GOLIVE_TOKEN}`;
// 1. Descobre quem é o bot (e confere se o token funciona).
const meResponse = await fetch(`${API}/auth/me`, { headers: { Authorization: TOKEN } });
if (!meResponse.ok) throw new Error(`Token inválido (HTTP ${meResponse.status})`);
const { account: me } = await meResponse.json();
// 2. Abre a conexão em tempo real e se registra com o token.
const ws = new WebSocket(GATEWAY);
ws.on("open", () => {
ws.send(JSON.stringify({ type: "register", token: TOKEN }));
});
ws.on("message", async (data) => {
const event = JSON.parse(data.toString());
if (event.type === "registered") {
console.log(`Conectado como ${me.displayName} (@${me.username})`);
}
// 3. Uma mensagem nova numa sala de texto de algum grupo do bot.
if (event.type === "group-message") {
const { message, author } = event;
if (author.bot) return; // ignora outros bots e a si mesmo
if (message.text.trim() !== "!ping") return;
// 4. Responde pela API HTTP.
await fetch(`${API}/groups/${message.groupId}/channels/${message.channelId}/messages`, {
method: "POST",
headers: { Authorization: TOKEN, "Content-Type": "application/json" },
body: JSON.stringify({
text: "Pong! 🏓",
replyTo: { id: message.id, name: author.name, text: message.text, userId: author.id },
}),
});
}
});
ws.on("close", (code) => {
console.log(`Conexão fechada (${code}). Num bot de verdade, reconecte aqui.`);
});3. Rode
bash
node --env-file=.env index.jsDeve aparecer:
Conectado como Meu Bot (@meu_bot)4. Teste
O bot só vê as salas dos grupos em que está. Se ele ainda não está em nenhum, coloque-o num grupo — leva um minuto.
Depois, escreva !ping numa sala de texto do grupo. O bot responde citando a sua mensagem. 🎉
O que aconteceu, passo a passo
1. GET /auth/me — confere o token e descobre o nome do bot. Se o token estiver errado, o programa para aqui com uma mensagem clara, em vez de falhar misteriosamente depois.
2. new WebSocket(GATEWAY) + register — abre a conexão em tempo real e se identifica. A partir da resposta registered, o Go Live começa a mandar eventos.
3. group-message — é o evento de "chegou mensagem numa sala de texto". Ele traz:
js
{
type: "group-message",
message: {
id: "8c1f...", // id da mensagem
groupId: "k2x9d0a1b3", // em qual grupo
channelId: "q7w3e5r9t1y2", // em qual sala
from: "a41c...", // id de quem escreveu
text: "!ping",
ts: 1757700000000 // quando (milissegundos)
},
author: { id: "a41c...", name: "Maria", bot: false, /* ... */ }
}4. if (author.bot) return — o bot recebe as próprias mensagens também (e as de outros bots). Sem essa linha, dois bots podem ficar se respondendo para sempre.
5. POST /groups/:id/channels/:cid/messages — responde. O replyTo faz a resposta aparecer citando a mensagem original, e o userId dentro dele notifica quem perguntou.
O que falta para um bot "de verdade"
Este exemplo é propositalmente mínimo. Um bot que fica ligado dias precisa de:
- Reconexão quando a internet ou o servidor cair → Conexão em tempo real.
- Tratamento de erros e de limite de requisições (
429) → Limites e boas práticas. - Um sistema de comandos em vez de
ifs → Criando comandos.
Tudo isso já está pronto no bot completo.