Automatiza bonk.io sin abrir un navegador.
bonktools es una biblioteca TypeScript que habla directamente el protocolo del juego. Crea salas, controla equipos, detecta jugadores AFK y mantén una sala funcionando las 24 horas.
npm install bonktoolsimport { createRoom } from 'bonktools';
const room = await createRoom({
auth: { type: 'registered', username, password },
desiredState: {
roomName: 'Mi Sala', password: '',
maxPlayers: 6, mode: 'b', rounds: 3,
},
});
room.lockTeams(); // solo el host mueve jugadores
room.enableAntiAfk(); // 12 s quieto = 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/123456abcdeCaracterísticas
- Conexión directa al protocolo. Socket.IO v2 y la cadena TLS de bonk.io ya están resueltos. Sin Puppeteer, sin pantalla virtual, sin automatización frágil de la interfaz. Protocolo →
- Salas 24/7 que se recuperan. BonkSession recrea las salas que caen, con backoff exponencial, throttle de creación y un reconcile cada 60 s. Sesiones 24/7 →
- Eventos tipados. Más de 30 eventos con payloads tipados y el estado de la sala siempre disponible en room.state. Eventos →
- Control de equipos. lockTeams() impide que los jugadores cambien de equipo por su cuenta: solo el host mueve jugadores. Quien entra después ya ve la sala bloqueada. Equipos y bloqueo →
- Anti-AFK. Detecta 12 s sin moverse y sin hablar, leyendo el movimiento de los frames de input por WebRTC. Anti-AFK →
- Los espectadores ven la partida. Quien entra mientras hay una partida en curso recibe el estado de la partida al instante, sin reiniciarla para todos. Partidas →
Cómo funciona
Tú eliges el nivel de abstracción: un socket crudo, una sala con estado y eventos, o un pool de salas que se mantiene vivo solo. Cada sala es una conexión ligera; no hace falta renderizar el juego para alojar una sala.
Tu código
│
BonkSession pool de salas · login compartido · throttle · reconcile de 60 s
BonkRoom estado · eventos tipados · equipos · bloqueo · anti-AFK · reconexión
BonkTransport Socket.IO v2 (EIO=3) · TLS · timesync
│
bonk.io + PeerJS/WebRTC para los frames de input de los jugadores- Fallos bajo control. Las caídas transitorias se recrean. Los baneos, salas llenas y reintentos agotados son terminales y te avisan.
- Protocolo documentado. La ingeniería inversa está registrada al detalle, con formatos de paquetes y trampas. Ver el protocolo →
Ejemplos
Crear y entrar en salas
import { createRoom, joinRoom } from 'bonktools';
// Crear una sala (el bot se convierte en 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 en una sala existente
const guest = await joinRoom('https://bonk.io/123456abcde', {
auth: { type: 'guest', guestName: 'BonkBot' },
role: 'spectator',
});Eventos y estado
room.on('player-join', (p) => room.chat(`Bienvenido, ${p.userName}!`));
room.on('team-change', (p) => console.log(`jugador ${p.id} → equipo ${p.team}`));
room.on('game-start', () => console.log('partida iniciada'));
room.on('game-end', () => console.log('partida terminada'));
room.on('room-dead', (reason) => console.error('la sala cayó:', reason.kind));
room.on('room-rebuilt', (link) => console.log('sala recreada:', link));
// el estado siempre a mano
room.state.players.forEach((p) => console.log(p.userName, p.team));Equipos y anti-AFK
room.lockTeams(); // nadie cambia de equipo por su cuenta
room.enableAntiAfk({ thresholdMs: 12_000 }); // 12 s sin moverse ni hablar
room.on('player-afk', (id) => {
room.chat(`${room.state.players.get(id)?.userName} está AFK!`);
room.kickPlayer(id);
});
room.on('player-back', () => room.chat('¡ha vuelto!'));
room.setTeam(id, 3); // el host sigue moviendo jugadores (3 = azul)
room.isAfk(id); // consulta puntualSesión 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 activa:', room.shareLink);
});
session.on('room-dead-terminal', ({ localId, reason }) => console.error(localId, reason));
// declarativo: recrea la sala solo si se cae
await session.startFromConfig({
rooms: [{ id: 'main', name: 'ATLAS', maxPlayers: 6, mode: 'b', rounds: 3 }],
throttle: { maxConcurrentRooms: 1, roomCreationDelayMs: 3000, roomCreationJitterMs: 2000 },
});Ejemplo: una sala de fútbol 24/7
El repositorio incluye un bot de referencia completo construido solo con la biblioteca. Monta los equipos, elige capitanes, rota al campeón y gestiona a los jugadores AFK. Úsalo como base para el tuyo.
- Equipos siempre iguales. Basado en
maxTeamSize: nunca 2v1, 3v1 ni 3v4. - Los capitanes eligen. Cuando los espectadores pueden completar los equipos, el capitán escribe el número del jugador que quiere; el último jugador entra solo.
- El ganador se queda en azul. El perdedor va al final de la cola y el primero de la cola se convierte en capitán del rojo.
- AFK sin complicaciones.
!afkalterna, los AFK nunca son elegidos, y quien está jugando no puede declararse AFK. - Equipos bloqueados. Solo el bot mueve jugadores.
Cómo funciona la elección
Azul
- Ana capitán
Rojo
vacío
Espectadores (cola)
vacío
El primer jugador va al azul y se convierte en capitán. La partida en solitario empieza al instante.
Comandos
| Comando | Quién lo usa | Qué hace |
|---|---|---|
!afk | cualquier jugador | Alterna AFK: pasa a espectador y no puede ser elegido. Durante una partida, quien juega no puede ponerse AFK. |
2 (solo el número) | capitán con el turno | Elige al jugador número 2 de la lista, sin comando (30 s; sin respuesta, se elige al primero). |
!win blue · !win red | jugador en el campo | Informa del ganador y dispara la rotación de equipos. |
!start · !stop | jugador en el campo | Inicia o detiene la partida (!stop retiene el reinicio hasta el siguiente !start). |
Calidad
Las salas de juego muestran errores que las pruebas unitarias no ven, así que cada función pasa por tres capas de validación:
- 123 pruebas en la biblioteca. Sala, equipos, bloqueo, anti-AFK, códec y reconexión.
- 32 pruebas en la sala 24/7, con fuzzing. Más de 600 secuencias aleatorias de entradas, salidas, AFK y elecciones, comprobando la proporción de equipos en cada partida.
- Jugadores reales. Navegadores reales jugando; incluso medimos si el disco realmente se mueve en pantalla.
Versiones
0.1.0Base: transporte, sala con estado y eventos, sesión 24/7.0.1.1Balance por jugador (BALANCE_SET) reflejado en el estado.0.1.2Un espectador que entra con una partida en curso ahora ve el juego.0.1.3Anti-AFK y el handshake WebRTC, con el eventopeer-input.0.1.4lockTeams()yunlockTeams(), además de las correcciones degs.tly de los colores de equipo.
Empieza en 3 pasos
Requiere Node.js 20.18 o superior y una cuenta de bonk.io.
- Instala.bash
npm install bonktools - Escribe el 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: '¡Hola, bonk!', password: '', maxPlayers: 6, mode: 'b', rounds: 3 }, }); console.log(room.shareLink); - Ejecútalo.bash
BONK_USER=tu_usuario BONK_PASS=tu_contraseña npx tsx bot.ts # → https://bonk.io/123456abcde