
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@soblend/baileys
Advanced tools
Enhanced Baileys fork with interactive buttons, encrypted database (BSONLite), microservices orchestration (MykloreJS), advanced group management, and optimized performance
_____ ____ ____ _ ______ _ _ _____
/ ____/ __ \| _ \| | | ____| \ | | __ \
| (___| | | | |_) | | | |__ | \| | | | |
\___ \| | | | _ <| | | __| | . ` | | | |
____) | |__| | |_) | |___| |____| |\ | |__| |
|_____/ \____/|____/|_____|______|_| \_|_____/
____ _____ _ ________ _______
| _ \ /\ |_ _| | | ____\ \ / / ____|
| |_) | / \ | | | | | |__ \ \_/ / (___
| _ < / /\ \ | | | | | __| \ / \___ \
| |_) / ____ \ _| |_| |____| |____ | | ____) |
|____/_/ \_\_____|______|______| |_| |_____/
La biblioteca de WhatsApp más completa, rápida y avanzada del ecosistema
📚 Documentación • ⚡ Instalación • 🎯 Características • 💡 Ejemplos
@soblend/baileys es una versión mejorada y optimizada de la biblioteca Baileys para WhatsApp Web. No es solo un fork, es una evolución completa que agrega:
| Característica | Baileys Original | @soblend/baileys |
|---|---|---|
| Botones Interactivos | ❌ No funcionan | ✅ Funcionan perfectamente |
| Carouseles Interactivos | ❌ No disponible | ✅ Soporte completo con botones |
| Reconexión | ⚠️ Lenta (~10s) | ⚡ Ultra-rápida (1.5s) |
| Memoria RAM | ~150MB | 💚 ~80MB (50% menos) |
| Sistema de Caché | ❌ Básico | ✅ LRU inteligente con 95%+ hit rate |
| Admin de Grupos | ⚠️ Manual | ✅ Sistema completo automatizado |
| Anti-Spam | ❌ No disponible | ✅ Detección inteligente |
| Auto-Update | ❌ No disponible | ✅ Notificaciones automáticas |
| Dashboard | ❌ No disponible | ✅ Panel web en tiempo real |
| Base de Datos | ❌ No incluida | ✅ BSONLite cifrado integrado |
| Sistema de Logs | ⚠️ Básico | ✅ Colorette con niveles y colores |
| Backups de Sesión | ❌ No disponible | ✅ Cifrado AES-256-GCM automático |
| Códigos de Emparejamiento | ❌ No disponible | ✅ 8 dígitos formateados |
| Documentación | ⚠️ Limitada | ✅ Completa con ejemplos |
El núcleo de @soblend/baileys ha sido completamente reescrito para máximo rendimiento:
// Gestión de memoria automática con límites configurables
// Caché LRU con eviction policy inteligente
// Buffer de mensajes para procesamiento paralelo
// Queue system con 5 workers concurrentes
// Keep-alive cada 25s con monitoreo de calidad
Beneficios reales:
Soporte completo para mensajes interactivos de WhatsApp, incluyendo carouseles con múltiples tarjetas:
Funcionalidades:
Casos de uso:
Un sistema completo para gestionar grupos de WhatsApp de forma profesional:
Funcionalidades:
Sistema que verifica automáticamente nuevas versiones desde NPM:
// Verifica cada 24 horas (configurable)
// Notifica con botones interactivos
// Muestra changelog desde GitHub
// Actualiza con un solo click
Panel de control completo accesible desde el navegador:
# Opción 1: NPM
npm install @soblend/baileys
# Opción 2: Yarn
yarn add @soblend/baileys
# Opción 3: PNPM
pnpm add @soblend/baileys
# Crear directorio del proyecto
mkdir mi-bot-whatsapp
cd mi-bot-whatsapp
# Inicializar proyecto
npm init -y
# Instalar @soblend/baileys
npm install @soblend/baileys
# Crear archivo principal
touch index.js
import { SoblendBaileys } from '@soblend/baileys';
async function main() {
// Crear instancia con configuración básica
const soblend = new SoblendBaileys({
printQRInTerminal: true, // Mostrar QR en consola
enableCache: true, // Activar caché inteligente
logLevel: 'info', // Nivel de logs
});
// Conectar
const socket = await soblend.connect('auth_session');
console.log('✅ ¡Conectado a WhatsApp!');
// Escuchar mensajes
socket.ev.on('messages.upsert', async ({ messages }) => {
const msg = messages[0];
if (!msg.message || msg.key.fromMe) return;
const text = msg.message.conversation || '';
const from = msg.key.remoteJid;
// Responder a "hola"
if (text.toLowerCase() === 'hola') {
await socket.sendMessage(from, { text: '¡Hola! 👋' });
}
});
}
main();
Explicación paso a paso:
SoblendBaileysconnect() con un nombre de sesiónmessages.upsert para recibir mensajessendMessage() para enviar respuestasinterface SoblendConfig {
// Autenticación
printQRInTerminal?: boolean; // Mostrar QR en consola (default: true)
// Rendimiento
enableCache?: boolean; // Activar caché LRU (default: true)
cacheMaxSize?: number; // Tamaño máximo del caché (default: 10000)
// Reconexión
autoReconnect?: boolean; // Reconexión automática (default: true)
maxReconnectAttempts?: number; // Intentos máximos (default: 20)
reconnectDelay?: number; // Delay inicial en ms (default: 1500)
// Seguridad
enableAntiSpam?: boolean; // Anti-spam (default: false)
enableRateLimit?: boolean; // Rate limiting (default: false)
// Logs
logLevel?: 'trace' | 'debug' | 'info' | 'warn' | 'error';
// Plugins
enablePlugins?: boolean; // Sistema de plugins (default: false)
}
// Conectar a WhatsApp
const socket = await soblend.connect(sessionId: string);
// Obtener calidad de conexión (0-100%)
const quality = soblend.getConnectionQuality();
// Obtener último ping
const ping = soblend.getLastPingTime();
// Limpiar recursos
await soblend.cleanup();
// Obtener estadísticas del caché
const stats = soblend.getCache().getStats();
@soblend/baileys incluye soporte completo para mensajes carousel (carruseles) de WhatsApp, permitiéndote enviar galerías interactivas con múltiples tarjetas deslizables, cada una con su propio contenido y botones.
Un carousel es un mensaje interactivo que contiene múltiples tarjetas (hasta 10) que el usuario puede deslizar horizontalmente. Cada tarjeta puede incluir:
import { sendCarousel } from '@soblend/baileys/core/connection';
// Definir las tarjetas del carousel
const cards = [
{
header: {
title: 'Producto 1',
hasMediaAttachment: true,
imageMessage: await prepareWAMessageMedia(
{ image: { url: 'https://ejemplo.com/imagen1.jpg' } },
{ upload: socket.waUploadToServer }
).then(m => m.imageMessage)
},
body: '📱 iPhone 15 Pro Max\nPrecio: $1,199 USD',
footer: 'Stock disponible',
nativeFlowMessage: {
buttons: [
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: '🛒 Comprar',
id: 'buy_iphone15'
})
},
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: 'ℹ️ Más Info',
id: 'info_iphone15'
})
}
]
}
},
{
header: {
title: 'Producto 2',
hasMediaAttachment: true,
imageMessage: await prepareWAMessageMedia(
{ image: { url: 'https://ejemplo.com/imagen2.jpg' } },
{ upload: socket.waUploadToServer }
).then(m => m.imageMessage)
},
body: '⌚ Apple Watch Series 9\nPrecio: $399 USD',
footer: 'Stock limitado',
nativeFlowMessage: {
buttons: [
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: '🛒 Comprar',
id: 'buy_watch'
})
}
]
}
}
];
// Enviar el carousel
await socket.sendCarousel(
'NUMERO@s.whatsapp.net',
cards,
'Nuestros Productos Destacados 🌟'
);
import { sendCarousel, prepareWAMessageMedia } from '@soblend/baileys';
async function sendTikTokCarousel(socket, jid, videos) {
const cards = [];
for (const video of videos.slice(0, 10)) { // Max 10 tarjetas
// Preparar el video como header
const videoMessage = await prepareWAMessageMedia(
{
video: { url: video.videoUrl },
gifPlayback: false
},
{ upload: socket.waUploadToServer }
);
cards.push({
header: {
title: video.title,
hasMediaAttachment: true,
videoMessage: videoMessage.videoMessage
},
body: `👤 @${video.author}\n❤️ ${video.likes} likes\n💬 ${video.comments} comentarios`,
footer: `📺 TikTok • ${video.duration}`,
nativeFlowMessage: {
buttons: [
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: '📥 Descargar',
id: `download_${video.id}`
})
},
{
name: 'cta_url',
buttonParamsJson: JSON.stringify({
display_text: '🔗 Ver en TikTok',
url: video.shareUrl,
merchant_url: video.shareUrl
})
}
]
}
});
}
await socket.sendCarousel(
jid,
cards,
`🎬 Videos de TikTok - ${videos.length} resultados`
);
}
async function sendProductCatalog(socket, jid, products) {
const cards = await Promise.all(products.map(async (product) => {
// Preparar imagen del producto
const imageMessage = await prepareWAMessageMedia(
{ image: { url: product.imageUrl } },
{ upload: socket.waUploadToServer }
);
return {
header: {
title: product.name,
hasMediaAttachment: true,
imageMessage: imageMessage.imageMessage
},
body: `${product.description}\n\n💰 Precio: $${product.price}\n⭐ Rating: ${product.rating}/5`,
footer: product.inStock ? '✅ En stock' : '❌ Agotado',
nativeFlowMessage: {
buttons: [
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: '🛒 Agregar al carrito',
id: `add_cart_${product.id}`
})
},
{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: 'ℹ️ Ver detalles',
id: `details_${product.id}`
})
}
]
}
};
}));
await socket.sendCarousel(jid, cards, '🛍️ Catálogo de Productos');
}
async function sendMenuCarousel(socket, jid) {
const cards = [
{
header: { title: '📊 Estadísticas' },
body: 'Ver estadísticas del bot\n• Usuarios activos\n• Mensajes procesados\n• Comandos más usados',
footer: 'Datos en tiempo real',
nativeFlowMessage: {
buttons: [{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: '📈 Ver Stats',
id: 'view_stats'
})
}]
}
},
{
header: { title: '⚙️ Configuración' },
body: 'Ajustes del bot\n• Cambiar idioma\n• Activar/desactivar módulos\n• Personalizar respuestas',
footer: 'Personaliza tu experiencia',
nativeFlowMessage: {
buttons: [{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: '🔧 Configurar',
id: 'settings'
})
}]
}
},
{
header: { title: '❓ Ayuda' },
body: 'Centro de ayuda\n• Comandos disponibles\n• Guías de uso\n• FAQ\n• Contactar soporte',
footer: 'Estamos aquí para ayudarte',
nativeFlowMessage: {
buttons: [{
name: 'quick_reply',
buttonParamsJson: JSON.stringify({
display_text: '📚 Ver Ayuda',
id: 'help'
})
}]
}
}
];
await socket.sendCarousel(jid, cards, '🤖 Menú Principal del Bot');
}
interface CarouselCard {
header: {
title: string;
hasMediaAttachment?: boolean;
imageMessage?: proto.Message.IImageMessage;
videoMessage?: proto.Message.IVideoMessage;
documentMessage?: proto.Message.IDocumentMessage;
};
body: string;
footer?: string;
nativeFlowMessage?: {
buttons: Array<{
name: string;
buttonParamsJson: string;
}>;
};
}
interface CarouselMessage {
cards: CarouselCard[];
messageVersion: number;
}
// Preparar media para WhatsApp
import { prepareWAMessageMedia } from '@soblend/baileys';
const media = await prepareWAMessageMedia(
{ image: { url: 'https://...' } },
{ upload: socket.waUploadToServer }
);
// Generar mensaje desde contenido
import { generateWAMessageFromContent } from '@soblend/baileys';
const msg = generateWAMessageFromContent(
jid,
messageContent,
{ userJid: socket.user.id }
);
Limitaciones de WhatsApp:
Mejores Prácticas:
Promise.all()socket.ev.on('messages.upsert', async ({ messages }) => {
const msg = messages[0];
if (!msg.message) return;
// Detectar respuesta de botón de carousel
const buttonResponse = msg.message.buttonsResponseMessage;
if (buttonResponse) {
const buttonId = buttonResponse.selectedButtonId;
// Procesar según el ID del botón
if (buttonId.startsWith('download_')) {
const videoId = buttonId.replace('download_', '');
await downloadVideo(videoId);
} else if (buttonId.startsWith('buy_')) {
const productId = buttonId.replace('buy_', '');
await processOrder(productId);
}
}
});
Ver el archivo src/example-carousel.ts para un ejemplo completo de integración con TikTok que incluye:
import { GroupAdminManager } from '@soblend/baileys';
const groupManager = new GroupAdminManager(socket);
// Crear grupo
const result = await groupManager.createGroup(
'Mi Grupo Genial',
['1234567890@s.whatsapp.net', '0987654321@s.whatsapp.net']
);
// Añadir participantes (en lotes de 10)
const results = await groupManager.addParticipants(
'GROUP_ID@g.us',
['user1@s.whatsapp.net', 'user2@s.whatsapp.net'],
true // Enviar mensaje de bienvenida
);
// Eliminar participantes
await groupManager.removeParticipants(
'GROUP_ID@g.us',
['user1@s.whatsapp.net']
);
// Promover a admin
await groupManager.promoteParticipants(
'GROUP_ID@g.us',
['user1@s.whatsapp.net']
);
// Degradar de admin
await groupManager.demoteParticipants(
'GROUP_ID@g.us',
['user1@s.whatsapp.net']
);
// Silenciar usuario por 1 hora (3600000 ms)
groupManager.muteUser(
'GROUP_ID@g.us',
'user@s.whatsapp.net',
3600000,
'Spam'
);
// Silenciar permanentemente
groupManager.muteUser(
'GROUP_ID@g.us',
'user@s.whatsapp.net',
undefined, // Sin duración = permanente
'Violó reglas'
);
// Quitar silencio
groupManager.unmuteUser('GROUP_ID@g.us', 'user@s.whatsapp.net');
// Verificar si está silenciado
const isMuted = groupManager.isUserMuted('GROUP_ID@g.us', 'user@s.whatsapp.net');
// Obtener lista de silenciados
const mutedList = groupManager.getMutedUsers('GROUP_ID@g.us');
// Añadir regla anti-link
groupManager.addRule('GROUP_ID@g.us', {
id: 'no-links',
type: 'anti-link',
enabled: true,
action: 'kick', // 'warn', 'mute', o 'kick'
message: '❌ No se permiten enlaces en este grupo'
});
// Añadir regla anti-spam
groupManager.addRule('GROUP_ID@g.us', {
id: 'no-spam',
type: 'anti-spam',
enabled: true,
action: 'mute',
message: '⚠️ Detectado spam, serás silenciado'
});
// Regla personalizada con expresiones regulares
groupManager.addRule('GROUP_ID@g.us', {
id: 'no-bad-words',
type: 'custom',
enabled: true,
action: 'warn',
patterns: [/palabra1/i, /palabra2/i],
message: '⚠️ Lenguaje inapropiado'
});
// Activar/desactivar regla
groupManager.toggleRule('GROUP_ID@g.us', 'no-links', false);
// Eliminar regla
groupManager.removeRule('GROUP_ID@g.us', 'no-links');
// Configurar mensaje de bienvenida
groupManager.setWelcomeMessage('GROUP_ID@g.us', {
enabled: true,
text: '¡Bienvenido {user} a {group}! 🎉\nLee las reglas en la descripción.',
buttons: true // Incluir botones de "Ver Reglas" y "Ayuda"
});
// Configurar mensaje de despedida
groupManager.setGoodbyeMessage('GROUP_ID@g.us', {
enabled: true,
text: 'Adiós {user}, esperamos verte pronto. 👋'
});
// Cambiar nombre
await groupManager.updateGroupName('GROUP_ID@g.us', 'Nuevo Nombre');
// Cambiar descripción
await groupManager.updateGroupDescription('GROUP_ID@g.us', 'Nueva descripción');
// Configuraciones avanzadas
await groupManager.updateGroupSettings('GROUP_ID@g.us', {
announceOnly: true, // Solo admins pueden enviar mensajes
locked: true, // Solo admins pueden cambiar info del grupo
});
// Obtener código de invitación
const inviteCode = await groupManager.getGroupInviteCode('GROUP_ID@g.us');
console.log(`https://chat.whatsapp.com/${inviteCode}`);
// Revocar enlace de invitación (generar uno nuevo)
const newCode = await groupManager.revokeGroupInviteCode('GROUP_ID@g.us');
// Obtener metadata del grupo
const metadata = await groupManager.getGroupMetadata('GROUP_ID@g.us');
console.log(metadata.data.subject); // Nombre del grupo
console.log(metadata.data.participants); // Lista de participantes
// Obtener solo participantes
const participants = await groupManager.getParticipants('GROUP_ID@g.us');
// Obtener solo administradores
const admins = await groupManager.getAdmins('GROUP_ID@g.us');
// Verificar si un usuario es admin
const isAdmin = await groupManager.isAdmin('GROUP_ID@g.us', 'user@s.whatsapp.net');
// Verificar si el bot es admin
const botIsAdmin = await groupManager.isBotAdmin('GROUP_ID@g.us');
// Estadísticas del sistema
const stats = groupManager.getStats();
console.log('Grupos en caché:', stats.cachedGroups);
console.log('Usuarios silenciados:', stats.mutedUsers);
console.log('Reglas activas:', stats.activeRules);
// Enviar panel de administración con botones
await groupManager.sendAdminPanel('GROUP_ID@g.us', 'admin@s.whatsapp.net');
// El panel incluye opciones para:
// - Ver lista de miembros
// - Ver administradores
// - Ver usuarios silenciados
// - Configurar el grupo
// - Gestionar reglas
// - Configurar bienvenida
// - Activar/desactivar anti-link
// - Activar/desactivar anti-spam
// - Revocar enlace de invitación
// Registrar listeners para eventos del grupo
groupManager.registerEventListener('GROUP_ID@g.us', {
// Cuando un usuario se une
onMemberJoin: async (groupId, members) => {
console.log(`${members.length} usuarios se unieron a ${groupId}`);
},
// Cuando un usuario sale
onMemberLeave: async (groupId, members) => {
console.log(`${members.length} usuarios salieron de ${groupId}`);
},
// Cuando se promociona a admin
onMemberPromote: async (groupId, members) => {
console.log(`${members.length} usuarios promovidos en ${groupId}`);
},
// Cuando se degrada de admin
onMemberDemote: async (groupId, members) => {
console.log(`${members.length} usuarios degradados en ${groupId}`);
},
// Cuando cambia el nombre del grupo
onGroupNameChange: async (groupId, oldName, newName) => {
console.log(`Grupo ${groupId} renombrado: ${oldName} → ${newName}`);
},
// Cuando cambia la descripción
onGroupDescriptionChange: async (groupId, newDesc) => {
console.log(`Nueva descripción en ${groupId}`);
},
// Cuando cambia la configuración
onGroupSettingsChange: async (groupId, settings) => {
console.log(`Configuración actualizada en ${groupId}`, settings);
}
});
import { AutoUpdater } from '@soblend/baileys';
const updater = new AutoUpdater();
// Verificar manualmente
const updateInfo = await updater.checkForUpdates();
console.log('Versión actual:', updateInfo.currentVersion);
console.log('Última versión:', updateInfo.latestVersion);
console.log('Hay actualización:', updateInfo.hasUpdate);
console.log('Notas:', updateInfo.releaseNotes);
// Enviar notificación con botones
await updater.sendUpdateNotification(
socket,
'YOUR_NUMBER@s.whatsapp.net',
updateInfo
);
// Verificación automática cada 24 horas
updater.startAutoCheck(
socket,
'YOUR_NUMBER@s.whatsapp.net',
24 // horas
);
// Detener verificación automática
updater.stopAutoCheck();
// Actualizar (ejecuta npm update @soblend/baileys)
const result = await updater.performUpdate();
console.log(result.message);
import { SoblendStorage } from '@soblend/baileys';
// Inicializar con cifrado
const storage = new SoblendStorage(
'./bot_database', // Ruta
true, // Cifrado activado
'MiPassword123!' // Contraseña
);
await storage.initialize();
// Guardar usuario
await storage.saveUser({
jid: 'user@s.whatsapp.net',
name: 'Juan',
messageCount: 10,
firstSeen: Date.now(),
lastSeen: Date.now(),
isBlocked: false,
isBanned: false,
level: 5,
points: 500
});
// Obtener usuario
const user = storage.getUser('user@s.whatsapp.net');
// Actualizar usuario
await storage.updateUser('user@s.whatsapp.net', {
points: 600,
level: 6
});
// Incrementar nivel automáticamente
await storage.incrementUserLevel('user@s.whatsapp.net', 50); // +50 puntos
// Top usuarios
const topUsers = await storage.getTopUsers(10);
// Banear/desbanear
await storage.banUser('user@s.whatsapp.net');
await storage.unbanUser('user@s.whatsapp.net');
// Guardar grupo
await storage.saveGroup({
jid: 'GROUP_ID@g.us',
name: 'Mi Grupo',
description: 'Descripción',
participants: ['user1@s.whatsapp.net'],
admins: ['admin@s.whatsapp.net'],
settings: {
locked: false,
announceOnly: false,
allowMemberAdd: true
}
});
// Configuración del bot
const config = storage.getConfig();
await storage.updateConfig({
botName: 'Mi Bot',
prefix: '!',
antiSpam: true
});
// Backup de datos
await storage.backup('./backup_folder');
import { DashboardServer } from '@soblend/baileys';
const dashboard = new DashboardServer({
port: 5000,
host: '0.0.0.0',
secret: 'your-secret-token',
storage: storage,
taskQueue: soblend.getTaskQueue(),
cache: soblend.getCache(),
antiSpam: soblend.getAntiSpam(),
rateLimiter: soblend.getRateLimiter()
});
dashboard.start();
// Accede a http://localhost:5000
@soblend/baileys incluye un sistema de logging profesional con colores usando colorette:
import { logger } from '@soblend/baileys';
// Configurar nivel de log
logger.setLogLevel('debug'); // 'trace' | 'debug' | 'info' | 'warn' | 'error'
// Mostrar banner de inicio
logger.printBanner();
logger.printFeatures();
// Logs por nivel
logger.trace('Mensaje de trazabilidad detallada');
logger.debug('Información de depuración');
logger.info('Información general');
logger.success('Operación exitosa');
logger.warning('Advertencia importante');
logger.error('Error crítico', new Error('Detalles del error'));
// Logs de conexión con iconos
logger.connection('connected', 'WhatsApp Web conectado');
logger.connection('disconnected', 'Pérdida de conexión');
logger.connection('connecting', 'Estableciendo conexión...');
logger.connection('error', 'Error en la autenticación');
// Logs de sesión
logger.session('session_001', 'Sesión iniciada', 'success');
logger.session('session_002', 'Error al cargar credenciales', 'error');
// Logs de mensajes
logger.message('user@s.whatsapp.net', '¡Hola! ¿Cómo estás?', 'incoming');
logger.message('group@g.us', 'Mensaje enviado al grupo', 'outgoing');
// Estadísticas del sistema
const stats = socket.getAdminStats();
logger.stats(stats);
// Tablas de datos
logger.table('Configuración del Bot', [
{ label: 'Nombre', value: 'Mi Bot Genial' },
{ label: 'Prefijo', value: '!' },
{ label: 'Anti-Spam', value: 'Activo' },
{ label: 'Caché', value: '95% hit rate' }
]);
// Separadores visuales
logger.separator();
// Animación de carga
logger.loading('Procesando solicitud');
// ... operación en progreso ...
logger.clearLoading();
logger.success('Operación completada');
// Footer con información del proyecto
logger.footer();
Características del Logger:
Sistema completo de respaldo automático de sesiones con cifrado AES-256-GCM:
import { SoblendBaileys } from '@soblend/baileys';
const soblend = new SoblendBaileys({
printQRInTerminal: true,
// Configuración de backups de sesión
enableSessionBackup: true, // Activar backups automáticos
sessionBackupInterval: 30, // Backup cada 30 minutos
sessionEncryptionKey: 'mi-clave-secura-2025!', // Clave de cifrado
});
const socket = await soblend.connect('auth_info');
// Acceder al gestor de sesiones
const sessionManager = soblend.getSessionManager();
// Crear backup manual
await sessionManager.createBackup('auth_info');
// Listar backups disponibles
const backups = await sessionManager.listBackups();
console.log('Backups disponibles:', backups);
// Obtener el último backup
const latestBackup = await sessionManager.getLatestBackup();
console.log('Último backup:', latestBackup);
// Restaurar sesión desde backup
await sessionManager.restoreBackup('session_backup_2025-11-08T15-30-00.enc', 'auth_info');
// Detener backups automáticos
sessionManager.stopAutoBackup();
Opciones de SessionManager:
interface SessionBackupOptions {
enableAutoBackup?: boolean; // Activar backups automáticos (default: true)
backupInterval?: number; // Intervalo en minutos (default: 30)
maxBackups?: number; // Máximo de backups a mantener (default: 5)
encryptionKey?: string; // Clave de cifrado personalizada
backupPath?: string; // Ruta de almacenamiento (default: './session_backups')
}
Características de Backups:
Vincula dispositivos usando códigos de 8 dígitos en lugar de escanear QR:
import { SoblendBaileys } from '@soblend/baileys';
const soblend = new SoblendBaileys({
printQRInTerminal: false, // Desactivar QR
});
const socket = await soblend.connect('auth_info');
// Solicitar código de emparejamiento
const pairingCode = await soblend.requestPairingCode({
phoneNumber: '5491112345678', // Número con código de país (sin +)
displayInConsole: true, // Mostrar en consola
sendToNumber: false, // No enviar automáticamente
});
console.log('Código de emparejamiento:', pairingCode);
// Output: "1234-5678" (formato formateado)
// Enviar código por WhatsApp al usuario
await socket.sendMessage('5491112345678@s.whatsapp.net', {
text: `🔐 Tu código de emparejamiento es:\n\n*${pairingCode}*\n\nÚsalo en WhatsApp > Dispositivos vinculados > Vincular un dispositivo`
});
Opciones de PairingCode:
interface PairingCodeOptions {
phoneNumber: string; // Número de teléfono (con código de país, sin +)
displayInConsole?: boolean; // Mostrar código en consola (default: true)
sendToNumber?: boolean; // Enviar automáticamente al número (default: false)
}
Ejemplo avanzado con validación:
const pairingCodeManager = soblend.getPairingCodeManager();
// Validar número antes de generar código
const phoneNumber = '5491112345678';
if (!/^\d{10,15}$/.test(phoneNumber)) {
throw new Error('Número de teléfono inválido');
}
const code = await soblend.requestPairingCode({
phoneNumber,
displayInConsole: true,
sendToNumber: true, // Enviar código automáticamente
});
console.log(`✅ Código enviado a +${phoneNumber}: ${code}`);
Ventajas del código de emparejamiento:
Reconexión ultra-rápida e inteligente sin pérdida de mensajes:
Características de la Reconexión:
Reconexión Instantánea (1.5-3s vs 5-10s del original):
const soblend = new SoblendBaileys({
autoReconnect: true,
maxReconnectAttempts: 20,
reconnectDelay: 1500, // Delay inicial de 1.5s
});
Estrategias Diferenciadas por Error:
Keep-Alive Inteligente:
Gestión de Memoria Optimizada:
Ejemplo de uso con logs detallados:
import { SoblendBaileys, logger } from '@soblend/baileys';
logger.setLogLevel('debug');
const soblend = new SoblendBaileys({
autoReconnect: true,
maxReconnectAttempts: 20,
reconnectDelay: 1500,
logLevel: 'debug',
});
const socket = await soblend.connect('auth_info');
// Monitorear calidad de conexión
setInterval(() => {
const quality = soblend.getConnectionQuality();
const ping = soblend.getLastPingTime();
logger.debug(`Calidad: ${quality}% | Ping: ${Date.now() - ping}ms`);
if (quality < 50) {
logger.warning('Calidad de conexión baja');
}
}, 30000);
// Manejar eventos de conexión
socket.ev.on('connection.update', (update) => {
const { connection } = update;
if (connection === 'open') {
logger.success('Conexión establecida exitosamente');
} else if (connection === 'close') {
logger.warning('Conexión cerrada - reconectando...');
} else if (connection === 'connecting') {
logger.info('Estableciendo conexión...');
}
});
Beneficios del Sistema de Reconexión:
import { SoblendBaileys } from '@soblend/baileys';
async function main() {
const soblend = new SoblendBaileys({
printQRInTerminal: true,
enableCache: true,
});
const socket = await soblend.connect('session');
socket.ev.on('messages.upsert', async ({ messages }) => {
const msg = messages[0];
if (!msg.message || msg.key.fromMe) return;
const text = msg.message.conversation || '';
const from = msg.key.remoteJid;
// Comando: !ping
if (text === '!ping') {
await socket.sendMessage(from, { text: '🏓 Pong!' });
}
// Comando: !info
if (text === '!info') {
const quality = soblend.getConnectionQuality();
await socket.sendMessage(from, {
text: `📊 Bot Info:\n` +
`Calidad: ${quality}%\n` +
`Ping: ${soblend.getLastPingTime()}ms`
});
}
});
}
main();
import { SoblendBaileys, GroupAdminManager } from '@soblend/baileys';
async function main() {
const soblend = new SoblendBaileys({ printQRInTerminal: true });
const socket = await soblend.connect('session');
const groupManager = new GroupAdminManager(socket);
// Configurar reglas anti-spam y anti-link
const GROUP_ID = 'GROUP_ID@g.us';
groupManager.addRule(GROUP_ID, {
id: 'no-links',
type: 'anti-link',
enabled: true,
action: 'kick',
message: '❌ Enlaces prohibidos'
});
groupManager.addRule(GROUP_ID, {
id: 'no-spam',
type: 'anti-spam',
enabled: true,
action: 'mute'
});
// Mensaje de bienvenida personalizado
groupManager.setWelcomeMessage(GROUP_ID, {
enabled: true,
text: '¡Hola {user}! 👋\nBienvenido a {group}\n\n📋 Reglas:\n1. No spam\n2. No enlaces\n3. Respeto mutuo',
buttons: true
});
socket.ev.on('messages.upsert', async ({ messages }) => {
const msg = messages[0];
if (!msg.message || msg.key.fromMe) return;
const text = msg.message.conversation || '';
const from = msg.key.remoteJid;
const sender = msg.key.participant || msg.key.remoteJid;
// Verificar reglas
if (from.endsWith('@g.us')) {
const allowed = await groupManager.checkRules(from, sender, text);
if (!allowed) return; // Mensaje bloqueado por reglas
}
// Comando: !admin (mostrar panel)
if (text === '!admin' && from.endsWith('@g.us')) {
const isAdmin = await groupManager.isAdmin(from, sender);
if (isAdmin) {
await groupManager.sendAdminPanel(from, sender);
}
}
// Comando: !kick @usuario
if (text.startsWith('!kick') && from.endsWith('@g.us')) {
const isAdmin = await groupManager.isAdmin(from, sender);
if (!isAdmin) return;
const mentioned = msg.message.extendedTextMessage?.contextInfo?.mentionedJid;
if (mentioned && mentioned.length > 0) {
await groupManager.removeParticipants(from, mentioned);
await socket.sendMessage(from, { text: '✅ Usuarios eliminados' });
}
}
});
}
main();
import { SoblendBaileys, logger } from '@soblend/baileys';
async function main() {
logger.printBanner();
logger.printFeatures();
const soblend = new SoblendBaileys({
printQRInTerminal: false, // No usar QR
logLevel: 'debug',
});
const socket = await soblend.connect('auth_pairing');
// Solicitar código de emparejamiento
const phoneNumber = '5491112345678'; // Tu número con código de país
logger.info(`Solicitando código para ${phoneNumber}...`);
const pairingCode = await soblend.requestPairingCode({
phoneNumber,
displayInConsole: true,
sendToNumber: false,
});
logger.success(`Código de emparejamiento: ${pairingCode}`);
logger.info('Ingresa este código en WhatsApp > Dispositivos vinculados');
socket.ev.on('connection.update', (update) => {
const { connection } = update;
if (connection === 'open') {
logger.success('¡Conectado con código de emparejamiento!');
// Enviar mensaje de confirmación
socket.sendMessage(`${phoneNumber}@s.whatsapp.net`, {
text: '✅ ¡Vinculación exitosa! Tu bot está listo.'
});
}
});
}
main();
import { SoblendBaileys, SoblendStorage } from '@soblend/baileys';
async function main() {
const storage = new SoblendStorage('./database', true, 'password');
await storage.initialize();
const soblend = new SoblendBaileys({ printQRInTerminal: true });
const socket = await soblend.connect('session');
socket.ev.on('messages.upsert', async ({ messages }) => {
const msg = messages[0];
if (!msg.message || msg.key.fromMe) return;
const sender = msg.key.participant || msg.key.remoteJid;
const from = msg.key.remoteJid;
// Registrar usuario si no existe
let user = storage.getUser(sender);
if (!user) {
await storage.saveUser({
jid: sender,
name: msg.pushName || 'Usuario',
messageCount: 0,
firstSeen: Date.now(),
lastSeen: Date.now(),
isBlocked: false,
isBanned: false,
level: 1,
points: 0
});
user = storage.getUser(sender);
}
// Incrementar contador y puntos
await storage.updateUser(sender, {
messageCount: user.messageCount + 1,
lastSeen: Date.now()
});
await storage.incrementUserLevel(sender, 10); // +10 puntos por mensaje
const text = msg.message.conversation || '';
// Comando: !level
if (text === '!level') {
const updatedUser = storage.getUser(sender);
await socket.sendMessage(from, {
text: `👤 Tu Perfil:\n` +
`Nivel: ${updatedUser.level}\n` +
`Puntos: ${updatedUser.points}\n` +
`Mensajes: ${updatedUser.messageCount}`
});
}
// Comando: !top
if (text === '!top') {
const topUsers = await storage.getTopUsers(5);
let leaderboard = '🏆 Top 5 Usuarios:\n\n';
topUsers.forEach((u, i) => {
leaderboard += `${i + 1}. ${u.name}\n`;
leaderboard += ` Nivel ${u.level} - ${u.points} puntos\n\n`;
});
await socket.sendMessage(from, { text: leaderboard });
}
});
}
main();
class SoblendBaileys {
constructor(config: SoblendConfig)
connect(sessionId: string): Promise<SoblendSocket>
getConnectionQuality(): number
getLastPingTime(): number
getCache(): SmartCache
getTaskQueue(): TaskQueue
cleanup(): Promise<void>
}
class GroupAdminManager {
constructor(socket: SoblendSocket)
// Grupos
createGroup(name: string, participants: string[]): Promise<any>
updateGroupName(groupId: string, name: string): Promise<boolean>
updateGroupDescription(groupId: string, desc: string): Promise<boolean>
updateGroupSettings(groupId: string, settings: GroupSettings): Promise<boolean>
// Participantes
addParticipants(groupId: string, participants: string[], sendWelcome?: boolean): Promise<ParticipantAction[]>
removeParticipants(groupId: string, participants: string[], reason?: string): Promise<ParticipantAction[]>
promoteParticipants(groupId: string, participants: string[]): Promise<ParticipantAction[]>
demoteParticipants(groupId: string, participants: string[]): Promise<ParticipantAction[]>
// Silenciamiento
muteUser(groupId: string, jid: string, duration?: number, reason?: string): void
unmuteUser(groupId: string, jid: string): void
isUserMuted(groupId: string, jid: string): boolean
// Reglas
addRule(groupId: string, rule: GroupRule): void
removeRule(groupId: string, ruleId: string): void
toggleRule(groupId: string, ruleId: string, enabled: boolean): void
checkRules(groupId: string, userId: string, message: string): Promise<boolean>
// Eventos
registerEventListener(groupId: string, listeners: GroupEventListener): void
sendAdminPanel(groupId: string, userId: string): Promise<void>
}
Solución:
const soblend = new SoblendBaileys({
printQRInTerminal: true, // Asegúrate de que esté en true
logLevel: 'debug' // Activa logs detallados
});
Solución:
const soblend = new SoblendBaileys({
autoReconnect: true,
reconnectDelay: 1500, // Reducir delay inicial
maxReconnectAttempts: 20 // Aumentar intentos
});
Solución:
const soblend = new SoblendBaileys({
enableCache: true,
cacheMaxSize: 5000, // Reducir tamaño del caché
});
// Limpiar caché periódicamente
setInterval(() => {
soblend.getCache().clear();
}, 3600000); // Cada hora
Solución: Los botones en @soblend/baileys usan la implementación de GataBot-MD que SÍ funciona:
await socket.sendInteractiveButtons(jid, {
text: 'Elige una opción',
footer: 'Powered by Soblend',
buttons: [
{
buttonId: 'id1',
buttonText: { displayText: 'Opción 1' },
type: 1
}
]
});
| Métrica | Baileys Original | @soblend/baileys | Mejora |
|---|---|---|---|
| Reconexión | ~5-10s | ⚡ 1.5-3s | 70% más rápido |
| Uso de RAM | ~150MB | 💚 ~80MB | 47% menos |
| CPU en idle | ~5% | 💚 ~1% | 80% menos |
| Cache hit rate | N/A | 📈 95%+ | Nuevo |
| Mensajes/seg | ~10 | 🚀 ~50+ | 5x más |
¿Quieres contribuir? ¡Genial! Abre un issue o pull request en GitHub.
MIT License - ver archivo LICENSE
FAQs
Enhanced Baileys fork with interactive buttons, encrypted database (BSONLite), microservices orchestration (MykloreJS), advanced group management, and optimized performance
We found that @soblend/baileys demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.