Saltar al contenido principal

Cómo Reemplazar Baileys con whatsmeow-node Cómo Reemplazar Baileys con whatsmeow-node

Cómo Reemplazar Baileys con whatsmeow-node

Si estás usando Baileys y te topas con problemas de mantenimiento, inestabilidad de forks, o quieres un upstream más confiable, whatsmeow-node es una alternativa directa con una superficie de API similar. Esta guía mapea los conceptos clave y te muestra cómo migrar.

¿Por Qué Migrar?

  • Upstream estable — whatsmeow es mantenido por el equipo de Mautrix y usado en producción por miles de puentes Matrix 24/7. Cuando WhatsApp cambia su protocolo, los arreglos llegan rápido.
  • Sin ruleta de forks — Baileys ha pasado por múltiples forks (adiwajshing → WhiskeySockets → otros). whatsmeow-node envuelve una sola biblioteca Go estable.
  • Menor consumo de memoria — ~10-20 MB vs ~50 MB típico de Baileys.
  • API tipada — Más de 100 métodos async tipados con diseño TypeScript-first.

Consulta la Comparación con Alternativas para más detalles.

Paso 1: Instalar

# Remove Baileys
npm uninstall @whiskeysockets/baileys

# Install whatsmeow-node
npm install @whatsmeow-node/whatsmeow-node

Paso 2: Actualizar la Inicialización del Cliente

Baileys

import makeWASocket, { useMultiFileAuthState } from "@whiskeysockets/baileys";

const { state, saveCreds } = await useMultiFileAuthState("auth_info");
const sock = makeWASocket({ auth: state });
sock.ev.on("creds.update", saveCreds);

whatsmeow-node

import { createClient } from "@whatsmeow-node/whatsmeow-node";

const client = createClient({ store: "session.db" });
const { jid } = await client.init();
await client.connect();

La persistencia de sesión es automática — no se necesita callback saveCreds. La opción store acepta una ruta de archivo (SQLite) o una cadena de conexión de PostgreSQL.

info

Necesitarás vincular de nuevo (escanear QR code) después del cambio. El estado de autenticación de Baileys no es compatible con las sesiones de whatsmeow.

Paso 3: Actualizar los Listeners de Eventos

Mensajes

Baileys:

sock.ev.on("messages.upsert", ({ messages }) => {
for (const msg of messages) {
if (msg.key.fromMe) continue;
const text = msg.message?.conversation
?? msg.message?.extendedTextMessage?.text;
console.log(`${msg.pushName}: ${text}`);
}
});

whatsmeow-node:

client.on("message", ({ info, message }) => {
if (info.isFromMe) return;
const text =
(message.conversation as string) ??
(message.extendedTextMessage as { text?: string } | undefined)?.text;
console.log(`${info.pushName}: ${text}`);
});

Diferencias clave:

  • Un solo mensaje por evento (no en lote)
  • Los metadatos del mensaje están en info, el contenido protobuf en message
  • info.isFromMe reemplaza a msg.key.fromMe
  • info.chat reemplaza a msg.key.remoteJid
  • info.sender reemplaza a msg.key.participant (en grupos)

Conexión

Baileys:

sock.ev.on("connection.update", ({ connection, lastDisconnect }) => {
if (connection === "open") console.log("Connected!");
if (connection === "close") { /* handle reconnection */ }
});

whatsmeow-node:

client.on("connected", ({ jid }) => console.log(`Connected as ${jid}`));
client.on("disconnected", () => console.log("Disconnected"));
client.on("logged_out", ({ reason }) => console.error(`Logged out: ${reason}`));

No necesitas lógica de reconexión manual — whatsmeow la maneja automáticamente.

Paso 4: Actualizar el Envío de Mensajes

Mensaje de texto

Baileys:

await sock.sendMessage(jid, { text: "Hello!" });

whatsmeow-node:

await client.sendMessage(jid, { conversation: "Hello!" });

Respuesta con cita

Baileys:

await sock.sendMessage(jid, { text: "Reply!" }, { quoted: msg });

whatsmeow-node:

await client.sendRawMessage(jid, {
extendedTextMessage: {
text: "Reply!",
contextInfo: {
stanzaId: info.id,
participant: info.sender,
quotedMessage: { conversation: originalText },
},
},
});

Multimedia

Baileys:

await sock.sendMessage(jid, {
image: { url: "/path/to/photo.jpg" },
caption: "Check this out",
});

whatsmeow-node:

const media = await client.uploadMedia("/path/to/photo.jpg", "image");
await client.sendRawMessage(jid, {
imageMessage: {
URL: media.URL,
directPath: media.directPath,
mediaKey: media.mediaKey,
fileEncSHA256: media.fileEncSHA256,
fileSHA256: media.fileSHA256,
fileLength: String(media.fileLength),
mimetype: "image/jpeg",
caption: "Check this out",
},
});

La subida y el envío de multimedia son pasos separados en whatsmeow-node. Esto te da más control (por ejemplo, subir una vez y enviar a múltiples chats).

Reacciones

Baileys:

await sock.sendMessage(jid, { react: { text: "👍", key: msg.key } });

whatsmeow-node:

await client.sendReaction(jid, senderJid, messageId, "👍");

Paso 5: Actualizar Operaciones de Grupo

Baileyswhatsmeow-node
sock.groupCreate(name, members)client.createGroup(name, members)
sock.groupMetadata(jid)client.getGroupInfo(jid)
sock.groupFetchAllParticipating()client.getJoinedGroups()
sock.groupUpdateSubject(jid, name)client.setGroupName(jid, name)
sock.groupUpdateDescription(jid, desc)client.setGroupDescription(jid, desc)
sock.groupSettingUpdate(jid, "announcement")client.setGroupAnnounce(jid, true)
sock.groupParticipantsUpdate(jid, [jid], "add")client.updateGroupParticipants(jid, [jid], "add")
sock.groupInviteCode(jid)client.getGroupInviteLink(jid)
sock.groupLeave(jid)client.leaveGroup(jid)

Referencia Rápida de la API

Baileyswhatsmeow-node
makeWASocket()createClient()
sock.sendMessage(jid, content)client.sendMessage(jid, content)
sock.readMessages([key])client.markRead([id], chat, sender)
sock.sendPresenceUpdate("available")client.sendPresence("available")
sock.presenceSubscribe(jid)client.subscribePresence(jid)
sock.profilePictureUrl(jid)client.getProfilePicture(jid)
sock.updateBlockStatus(jid, "block")client.updateBlocklist(jid, "block")
sock.logout()client.logout()

Lista de Verificación de Migración

  • Instalar @whatsmeow-node/whatsmeow-node, eliminar @whiskeysockets/baileys
  • Reemplazar makeWASocketcreateClient
  • Eliminar useMultiFileAuthState — la sesión se maneja automáticamente
  • Actualizar listeners de eventos (ev.onclient.on, nombres de eventos diferentes)
  • Actualizar llamadas a sendMessage (textconversation)
  • Actualizar envío de multimedia (pasos separados de upload + envío)
  • Actualizar operaciones de grupo (los nombres de métodos difieren ligeramente)
  • Eliminar lógica de reconexión manual — whatsmeow se reconecta automáticamente
  • Vincular de nuevo vía QR code (se requiere nueva sesión)
  • Probar todos los tipos de mensaje de extremo a extremo

Errores Comunes

Se requiere nueva sesión

El estado de autenticación de Baileys no se puede migrar. Debes vincular una nueva sesión escaneando el QR code. Tu historial de chat y contactos de WhatsApp no se ven afectados — solo el enlace del dispositivo es nuevo.

text vs conversation

Baileys usa { text: "..." } para mensajes. whatsmeow-node usa { conversation: "..." } — coincidiendo con el nombre del campo protobuf de WhatsApp.

Casing de campos proto

Los campos de respuesta de upload usan el casing exacto de protobuf: URL, fileSHA256, fileEncSHA256no camelCase. Usar el casing incorrecto falla silenciosamente.