Automatize o bonk.io sem abrir um navegador.
O bonktools é uma biblioteca TypeScript que fala direto o protocolo do jogo. Crie salas, controle equipas, Detete jogadores AFK e mantenha uma sala a funcionar 24 horas por dia.
npm install bonktoolsimport { createRoom } from 'bonktools';
const room = await createRoom({
auth: { type: 'registered', username, password },
desiredState: {
roomName: 'Minha Sala', password: '',
maxPlayers: 6, mode: 'b', rounds: 3,
},
});
room.lockTeams(); // só o host move jogadores
room.enableAntiAfk(); // 12 s parado = AFK
room.on('player-afk', (id) => room.kickPlayer(id));
room.on('chat-message', ({ message }) => {
if (message === '!ping') room.chat('Pong!');
});
console.log(room.shareLink); // https://bonk.io/123456abcdeRecursos
- Conexão direta pelo protocolo. Socket.IO v2 e a cadeia TLS do bonk.io já resolvidos. Sem Puppeteer, sem ecrã virtual, sem automação de interface frágil. Protocolo →
- Salas 24/7 que se recuperam. BonkSession recria salas que caem, com backoff exponencial, throttle de criação e um reconcile a cada 60 s. Sessões 24/7 →
- Eventos tipados. Mais de 30 eventos com payloads tipados, e o estado da sala sempre disponível em room.state. Eventos →
- Controle das equipas. lockTeams() impede trocas por conta própria: só o host move jogadores. Quem entra depois já vê a sala bloqueada. Equipas e lock →
- Anti-AFK. Deteta 12 s sem se mexer e sem falar no chat, lendo o movimento pelos frames de input do WebRTC. Anti-AFK →
- Espectadores veem a partida. Quem entra com o jogo em curso recebe o estado da partida de imediato, sem reiniciar para toda a gente. Partidas →
Como funciona
Você escolhe o nível de abstração: um socket cru, uma sala com estado e eventos, ou um pool de salas que se mantém sozinho. Cada sala é uma conexão leve; nada de renderizar o jogo só para hospedar uma sala.
Seu código
│
BonkSession pool de salas · login compartilhado · throttle · reconcile de 60 s
BonkRoom estado · eventos tipados · equipas · lock · anti-AFK · reconexão
BonkTransport Socket.IO v2 (EIO=3) · TLS · timesync
│
bonk.io + PeerJS/WebRTC para os frames de input dos jogadores- Falhas sob controle. Quedas transitórias são recriadas. Ban, sala cheia e tentativas esgotadas são terminais e avisam você.
- Protocolo documentado. A engenharia reversa está registada em detalhe, com formatos de pacote e armadilhas. Ver protocolo →
Exemplos
Criar e entrar em salas
import { createRoom, joinRoom } from 'bonktools';
// Criar uma sala (o bot vira o host)
const room = await createRoom({
auth: { type: 'registered', username, password },
desiredState: { roomName: 'HERMES', password: '', maxPlayers: 6, mode: 'b', rounds: 3 },
hidden: false,
});
console.log('Link:', room.shareLink);
// Entrar numa sala que já existe
const guest = await joinRoom('https://bonk.io/123456abcde', {
auth: { type: 'guest', guestName: 'BonkBot' },
role: 'spectator',
});Eventos e estado
room.on('player-join', (p) => room.chat(`Bem-vindo, ${p.userName}!`));
room.on('team-change', (p) => console.log(`jogador ${p.id} → equipa ${p.team}`));
room.on('game-start', () => console.log('partida iniciada'));
room.on('game-end', () => console.log('partida encerrada'));
room.on('room-dead', (reason) => console.error('sala caiu:', reason.kind));
room.on('room-rebuilt', (link) => console.log('sala recriada:', link));
// estado sempre à mão
room.state.players.forEach((p) => console.log(p.userName, p.team));Equipas e anti-AFK
room.lockTeams(); // ninguém troca de equipa sozinho
room.enableAntiAfk({ thresholdMs: 12_000 }); // 12 s sem mexer nem falar
room.on('player-afk', (id) => {
room.chat(`${room.state.players.get(id)?.userName} está AFK!`);
room.kickPlayer(id);
});
room.on('player-back', () => room.chat('voltou!'));
room.setTeam(id, 3); // o host continua movendo jogadores (3 = azul)
room.isAfk(id); // consulta pontualSessão 24/7
import { BonkSession } from 'bonktools';
const session = new BonkSession({
auth: { type: 'registered', username, password },
throttle: { capacity: 1, refillPerSec: 0.3 },
});
await session.getToken();
session.on('room-added', (localId) => {
const { room } = session.rooms.get(localId)!;
console.log('sala ativa:', room.shareLink);
});
session.on('room-dead-terminal', ({ localId, reason }) => console.error(localId, reason));
// declarativo: recria a sala sozinho se ela cair
await session.startFromConfig({
rooms: [{ id: 'main', name: 'ATLAS', maxPlayers: 6, mode: 'b', rounds: 3 }],
throttle: { maxConcurrentRooms: 1, roomCreationDelayMs: 3000, roomCreationJitterMs: 2000 },
});Exemplo: uma sala de football 24/7
O repositório inclui um bot de referência completo, construído só com a biblioteca. Ele monta as equipas, escolhe capitães, rotaciona o campeão e cuida de quem fica AFK. Use como base para o seu.
- Equipas sempre iguais. Baseado em
maxTeamSize: nunca 2v1, 3v1 ou 3v4. - Capitães escolhem. Quando o spec completa as equipas, o capitão digita o número do jogador que quer; o último jogador entra sozinho.
- Quem vence fica no azul. O perdedor vai para o fim da fila e o primeiro da fila vira capitão do vermelho.
- AFK sem confusão.
!afkalterna, AFK nunca é escolhido e quem está a jogar não pode se declarar AFK. - Equipas bloqueadas. Só o bot move jogadores.
Como o pick funciona
Azul
- Ana capitão
Vermelho
vazio
Espectadores (fila)
vazio
O primeiro jogador vai para o azul e vira capitão. A partida solo já começa.
Comandos
| Comando | Quem usa | O que faz |
|---|---|---|
!afk | qualquer jogador | Alterna AFK: vai para o spec e não pode ser escolhido. Em partida, quem joga não pode ficar AFK. |
2 (só o número) | capitão da vez | Escolhe o jogador nº 2 da lista, sem nenhum comando (30 s; sem resposta, escolhe o primeiro). |
!win blue · !win red | jogador em campo | Informa o vencedor e dispara a rotação das equipas. |
!start · !stop | jogador em campo | Inicia ou pára a partida (o !stop segura o reinício até o próximo !start). |
Qualidade
Salas de jogo mostram bugs que testes unitários não pegam, então cada recurso passa por três camadas de validação:
- 123 testes na biblioteca. Sala, equipas, lock, anti-AFK, codec e reconexão.
- 32 testes na sala 24/7, com fuzz. Mais de 600 sequências aleatórias de entradas, saídas, AFK e escolhas, verificando a proporção das equipas a cada partida.
- Jogadores reais. Navegadores reais a jogar; medimos até se o disco realmente se move na ecrã.
Versões
0.1.0Base: transporte, sala com estado e eventos, sessão 24/7.0.1.1Balance por jogador (BALANCE_SET) refletido no estado.0.1.2Espectador que entra com a partida em curso passa a ver o jogo.0.1.3Anti-AFK e handshake WebRTC, com o eventopeer-input.0.1.4lockTeams()eunlockTeams(), correção dogs.tle das cores de equipa.
Comece em 3 passos
Requer Node.js 20.18 ou superior e uma conta do bonk.io.
- Instale.bash
npm install bonktools - Escreva o bot.bot.ts
import { createRoom } from 'bonktools'; const room = await createRoom({ auth: { type: 'registered', username: process.env.BONK_USER!, password: process.env.BONK_PASS! }, desiredState: { roomName: 'Olá, bonk!', password: '', maxPlayers: 6, mode: 'b', rounds: 3 }, }); console.log(room.shareLink); - Execute.bash
BONK_USER=seu_usuario BONK_PASS=sua_senha npx tsx bot.ts # → https://bonk.io/123456abcde