@hectorg321/hbot-whatsapp
v1.3.4
Published
Bot de WhatsApp con sistema de comandos addKeyword, interfaz web y reconexión automática
Maintainers
Readme
HBot - WhatsApp Bot
Bot de WhatsApp desarrollado con Baileys que incluye una interfaz web en tiempo real para escanear códigos QR y gestionar la conexión.
🚀 Características
- ✅ Conexión a WhatsApp mediante QR Code
- 🌐 Interfaz web moderna para escanear QR
- ⚡ Actualizaciones en tiempo real con Socket.IO
- 🔄 Reconexión automática
- 📱 Responsive design
- 🎯 Respuestas automáticas configurables
- 🔧 Variables de entorno configurables
📋 Requisitos
- Node.js >= 16.0.0
- npm >= 7.0.0
- WhatsApp en dispositivo móvil
🛠️ Instalación
- Clonar o descargar el proyecto
git clone <url-del-repositorio>
cd HBot- Instalar dependencias
npm install- Configurar variables de entorno (opcional)
# Crear archivo .env
echo "PORT=3000" > .env🏃♂️ Uso
Iniciar el bot
node bot.jsAcceder a la interfaz web
- Abrir navegador en:
http://localhost:3000 - Esperar a que aparezca el código QR
- Abrir WhatsApp → Configuración → Dispositivos vinculados
- Tocar "Vincular un dispositivo"
- Escanear el código QR mostrado en la página web
Estados de conexión
- ⏳ Esperando conexión... - Bot iniciándose
- 📱 Escanea el código QR - QR disponible para escanear
- ✅ ¡Conectado exitosamente! - Bot conectado y funcionando
- ❌ Desconectado - Reconectando... - Conexión perdida, reintentando
🔧 Configuración
Variables de entorno
Crear archivo .env en la raíz del proyecto:
# Puerto del servidor web (default: 3000)
PORT=3000
# Otros configuraciones futuras...Puerto personalizado
# Opción 1: Variable de entorno temporal
PORT=8080 node bot.js
# Opción 2: Modificar .env
echo "PORT=8080" > .env
node bot.js📁 Estructura del proyecto
HBot/
├── src/
│ ├── index.js # Clase WhatsAppBot principal
│ └── commandHandler.js # Sistema de comandos addKeyword
├── public/
│ └── index.html # Interfaz web
├── bot_sessions/ # Sesiones de autenticación (auto-generado)
├── bot.js # Servidor principal y configuración de comandos
├── package.json # Dependencias
├── .env # Variables de entorno
└── README.md # Esta documentación🔌 API Endpoints
HTTP Endpoints
GET /- Interfaz web principalGET /status- Estado actual del bot (JSON)GET /qr- Imagen PNG del código QR
Socket.IO Events
Eventos del servidor:
status- Cambio de estado del botqr_updated- Nuevo código QR generado
Estados posibles:
starting- Bot iniciándosewaiting_qr- Esperando escaneo de QRconnected- Bot conectadodisconnected- Bot desconectado
🤖 Sistema de Comandos
Comandos configurados por defecto
- "hola", "hello", "hi" → Saludo personalizado con nombre del usuario
- "ping" → "pong! 🏓"
- "menu", "menú" → Menú de comandos disponibles
- "info" → Información del bot con respuestas secuenciales
📋 Usar el sistema addKeyword
El bot incluye un sistema avanzado de comandos que funciona similar a otros frameworks de bots:
// Comando simple
bot.addKeyword('ping').addAction(
async (ctx, ctxFn) => {
await ctxFn.reply('pong! 🏓')
}
)
// Múltiples palabras clave
bot.addKeyword(['hola', 'hello', 'hi']).addAction(
async (ctx, ctxFn) => {
await ctxFn.reply(`¡Hola ${ctx.pushName}! 👋`)
}
)
// Respuestas múltiples secuenciales
bot.addKeyword('info').addAction(
async (ctx, ctxFn) => {
await ctxFn.flowDynamic([
'🤖 *Información del Bot*',
'Soy un bot de WhatsApp creado con Node.js',
'Puedo responder a diferentes comandos.',
'Escribe "menu" para ver los comandos disponibles.'
])
}
)📝 Objeto ctx (Contexto del mensaje)
El primer parámetro ctx contiene información del mensaje:
{
from: '[email protected]', // ID del remitente
message: 'Hola bot', // Texto del mensaje
body: 'Hola bot', // Alias de message
pushName: 'Juan Pérez', // Nombre del usuario
key: { ... }, // Información de la clave
originalMessage: { ... } // Mensaje completo de Baileys
}🔧 Objeto ctxFn (Funciones de respuesta)
El segundo parámetro ctxFn contiene métodos para enviar respuestas:
ctxFn.reply(texto)
Envía una respuesta simple:
await ctxFn.reply('¡Hola! ¿Cómo estás?')ctxFn.send(texto)
Alias de reply, envía un mensaje:
await ctxFn.send('Mensaje enviado')ctxFn.flowDynamic(array)
Envía múltiples mensajes secuenciales con delay automático:
await ctxFn.flowDynamic([
'Primera línea',
'Segunda línea',
'Tercera línea'
])
// También acepta objetos con propiedades
await ctxFn.flowDynamic([
{ body: 'Mensaje 1' },
{ body: 'Mensaje 2' }
])⚙️ Tipos de coincidencias de palabras clave
// Coincidencia exacta
bot.addKeyword('ping') // Solo responde a "ping"
// Múltiples palabras clave
bot.addKeyword(['hola', 'hello', 'hi']) // Cualquiera de las tres
// Coincidencia que empiece con la palabra
bot.addKeyword('help') // Responde a "help", "help me", etc.
// Para coincidencias que contengan la palabra (usar asteriscos)
bot.addKeyword('*ayuda*') // Responde si el mensaje contiene "ayuda"💡 Ejemplos avanzados
// Comando con validaciones
bot.addKeyword('edad').addAction(
async (ctx, ctxFn) => {
const edad = ctx.body.split(' ')[1]
if (!edad || isNaN(edad)) {
await ctxFn.reply('Por favor, envía tu edad así: "edad 25"')
return
}
await ctxFn.reply(`Tu edad es ${edad} años`)
}
)
// Comando con respuesta personalizada según el usuario
bot.addKeyword('perfil').addAction(
async (ctx, ctxFn) => {
await ctxFn.flowDynamic([
`👤 *Perfil de ${ctx.pushName}*`,
`📱 Número: ${ctx.from}`,
`💬 Último mensaje: "${ctx.body}"`,
'Gracias por usar el bot!'
])
}
)
// Comando con respuesta condicional
bot.addKeyword('tiempo').addAction(
async (ctx, ctxFn) => {
const hora = new Date().getHours()
let saludo
if (hora < 12) saludo = 'Buenos días'
else if (hora < 18) saludo = 'Buenas tardes'
else saludo = 'Buenas noches'
await ctxFn.reply(`${saludo}, ${ctx.pushName}! Son las ${new Date().toLocaleTimeString()}`)
}
)🔄 Migración desde el sistema anterior
Si tenías respuestas en el listener de eventos:
// ❌ Sistema anterior
bot.on('message', async (msg) => {
if (mensaje?.toLowerCase() === 'hola') {
await bot.enviarMensaje(from, '¡Hola!')
}
})
// ✅ Nuevo sistema
bot.addKeyword('hola').addAction(
async (ctx, ctxFn) => {
await ctxFn.reply('¡Hola!')
}
)🏗️ Arquitectura técnica
Tecnologías utilizadas
- Baileys v6.7.18 - Biblioteca para WhatsApp Web API
- Express.js v5.1.0 - Servidor web
- Socket.IO v4.8.1 - Comunicación en tiempo real
- QRCode v1.5.4 - Generación de códigos QR
- dotenv v17.2.1 - Variables de entorno
Clase WhatsAppBot
const { WhatsAppBot } = require('./src/index.js')
const bot = new WhatsAppBot()
// Eventos disponibles
bot.on('qr', (qr) => { /* QR generado */ })
bot.on('connected', () => { /* Bot conectado */ })
bot.on('disconnected', (error) => { /* Bot desconectado */ })
bot.on('message', (msg) => { /* Mensaje recibido */ })
// Métodos disponibles
await bot.conectar()
await bot.enviarMensaje(jid, mensaje)
const socket = bot.getSocket()
// Sistema de comandos
bot.addKeyword(['palabra1', 'palabra2']).addAction(async (ctx, ctxFn) => {
await ctxFn.reply('Respuesta')
})Clase CommandHandler
const { CommandHandler } = require('./src/commandHandler.js')
// Se instancia automáticamente dentro de WhatsAppBot
// Maneja el procesamiento de mensajes y coincidencias de palabras clave
// Proporciona ctx (contexto) y ctxFn (funciones de respuesta)Flujo de conexión
- Bot se inicia y carga sesión guardada
- Si no hay sesión, genera nuevo QR
- QR se emite vía Socket.IO a clientes web
- Usuario escanea QR desde interfaz web
- WhatsApp valida y establece conexión
- Bot queda listo para recibir/enviar mensajes
🚨 Resolución de problemas
El bot no se conecta
- Verificar QR actualizado: El QR expira cada ~30 segundos
- Limpiar sesión: Eliminar carpeta
bot_sessions/ - Verificar WhatsApp: Asegurar que WhatsApp esté actualizado
Error de puerto ocupado
# Cambiar puerto
PORT=3001 node bot.js
# O verificar procesos usando el puerto
netstat -ano | findstr :3000Página web no carga
- Verificar URL:
http://localhost:3000(no HTTPS) - Firewall: Permitir conexiones en el puerto configurado
- Logs del servidor: Revisar mensajes en consola
Socket.IO no conecta
- Verificar JavaScript habilitado en navegador
- Limpiar caché del navegador
- Verificar consola del navegador (F12)
📊 Logs y monitoreo
Mensajes de log importantes
🌐 Servidor web iniciado en http://localhost:3000 # Servidor listo
🔗 Cliente conectado: <socket-id> # Cliente web conectado
📱 QR generado para escanear # Nuevo QR disponible
🚀 Bot conectado y listo! # WhatsApp conectado
📨 Mensaje de <número>: <texto> # Mensaje recibido
❌ Bot desconectado: <error> # Error de conexiónMonitoreo en producción
Para uso en producción, considerar:
- PM2 para gestión de procesos
- Log rotation para archivos de log
- Health checks para verificar estado
- Reverse proxy (nginx) para HTTPS
# Instalar PM2
npm install -g pm2
# Iniciar con PM2
pm2 start bot.js --name "hbot"
# Monitorear
pm2 monit🔒 Seguridad
Datos sensibles
- Sesiones: Carpeta
bot_sessions/contiene tokens de autenticación - Números: Los mensajes incluyen números de teléfono
- QR Codes: No compartir códigos QR públicamente
Recomendaciones
- No commitear
bot_sessions/al repositorio - Usar HTTPS en producción
- Validar mensajes antes de procesar
- Rate limiting para evitar spam
📝 Desarrollo
Agregar nuevos comandos
// Agregar comandos con el sistema addKeyword
bot.addKeyword('/comando').addAction(
async (ctx, ctxFn) => {
await ctxFn.reply('Respuesta del comando')
}
)
// Comando con múltiples acciones
bot.addKeyword('ayuda')
.addAction(async (ctx, ctxFn) => {
await ctxFn.reply('¡Hola! Te ayudo')
})
.addAction(async (ctx, ctxFn) => {
await ctxFn.flowDynamic([
'Comandos disponibles:',
'• ping - Prueba de conexión',
'• menu - Ver menú principal'
])
})
// Comando con lógica compleja
bot.addKeyword('calcular').addAction(
async (ctx, ctxFn) => {
const partes = ctx.body.split(' ')
if (partes.length < 4) {
await ctxFn.reply('Uso: calcular [número] [operador] [número]')
return
}
const [, num1, operador, num2] = partes
const resultado = eval(`${num1} ${operador} ${num2}`)
await ctxFn.reply(`Resultado: ${resultado}`)
}
)Variables útiles del contexto (ctx)
// Información disponible en ctx dentro de addAction
ctx.from // Número/ID del remitente (ej: '[email protected]')
ctx.message || ctx.body // Texto completo del mensaje
ctx.pushName // Nombre del usuario en WhatsApp
ctx.key // Información de la clave del mensaje
ctx.originalMessage // Objeto mensaje completo de Baileys
// Tipos de chat (usando ctx.from)
ctx.from.endsWith('@s.whatsapp.net') // Chat individual
ctx.from.endsWith('@g.us') // Grupo
// Ejemplo de uso
bot.addKeyword('whoami').addAction(
async (ctx, ctxFn) => {
const tipoChat = ctx.from.endsWith('@g.us') ? 'grupo' : 'chat individual'
await ctxFn.reply(`Eres ${ctx.pushName} en un ${tipoChat}`)
}
)📚 Referencias
Versión: 1.0.0 - Con sistema de comandos addKeyword
Autor: HBot Team
Licencia: ISC
🆕 Changelog
v1.0.0
- ✅ Agregado sistema de comandos
addKeyword()yaddAction() - ✅ Soporte para múltiples palabras clave por comando
- ✅ Objeto
ctxcon contexto completo del mensaje - ✅ Objeto
ctxFncon métodosreply(),send()yflowDynamic() - ✅ Coincidencias exactas y por contenido con asteriscos
- ✅ Respuestas secuenciales con delay automático
- ✅ Compatibilidad con el sistema anterior de eventos
