Skip to content

Fer2809fl/Baileys

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

97 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Baileys

@fer2809fl/baileys

API de WhatsApp Web para Node.js

npm version License Node.js TypeScript

Conéctate a WhatsApp Web directamente desde Node.js sin navegadores ni Selenium


🆕 Novedades — v1.8.9

✅ Nuevas funciones añadidas

  • Botones interactivos — Se agregaron funciones nativas para enviar botones de WhatsApp:
    • sendCopyButton — Botón que copia texto al portapapeles
    • sendUrlButton — Botón que abre un enlace en el navegador
    • sendQuickReplyButtons — Botones de respuesta rápida
    • sendCallButton — Botón para iniciar una llamada telefónica
    • sendListMenu — Menú desplegable con secciones y filas
    • sendInteractiveMessage — Combinación de botones mixtos (URL + Copiar + Rápido)
  • resolveJid — Nueva función para resolver automáticamente el JID objetivo de un comando (citado → mención → argumento → sender)

🐛 Correcciones

  • Error en macOS — Se reparó un bug crítico que impedía iniciar sesión correctamente en dispositivos Mac. El proceso de pairing/QR ahora funciona de forma estable en macOS.

⚠️ Nota Importante

ꕤ Esta librería está basada en Baileys. No está afiliada ni aprobada oficialmente por WhatsApp.

@fer2809fl/baileys y su desarrollador no se hacen responsables por el mal uso de esta librería. Úsala de forma responsable — nada de spam ni actividades maliciosas.


📦 Instalación

Puedes instalarla de varias formas, todas funcionan igual:

Opción 1 — Desde npm (recomendado)

npm install @fer2809fl/baileys
yarn add @fer2809fl/baileys

Opción 2 — Desde GitHub directamente

npm install github:Fer2809fl/Baileys
yarn add github:Fer2809fl/Baileys

Opción 3 — También funciona con el paquete original

npm install @whiskeysockets/baileys
yarn add @whiskeysockets/baileys

Opción — En tu package.json (elige una de estas formas):

{
  "dependencies": {
    "@fer2809fl/baileys": "^1.8.9"
  }
}
{
  "dependencies": {
    "@whiskeysockets/baileys": "github:Fer2809fl/Baileys"
  }
}

⚡ Inicio Rápido

JavaScript

const { makeWASocket, useMultiFileAuthState } = require('@fer2809fl/baileys')

async function startBot() {
    const { state, saveCreds } = await useMultiFileAuthState('session-mymelody')
    
    const melody = makeWASocket({
        auth: state,
        printQRInTerminal: true
    })

    melody.ev.on('connection.update', ({ connection }) => {
        if (connection === 'open') console.log('✅ ¡Conectado con éxito!')
        if (connection === 'close') console.log('❌ Conexión cerrada, reconectando...')
    })

    melody.ev.on('messages.upsert', async ({ messages }) => {
        const m = messages[0]
        if (!m.message) return

        await melody.sendMessage(m.key.remoteJid, { 
            text: '¡Hola! Soy un bot de Delta!' 
        })
    })

    melody.ev.on('creds.update', saveCreds)
}

startBot()

TypeScript

import makeWASocket, { useMultiFileAuthState, DisconnectReason } from '@fer2809fl/baileys'
import { Boom } from '@hapi/boom'

async function startBot(): Promise<void> {
    const { state, saveCreds } = await useMultiFileAuthState('session-mymelody')
    
    const melody = makeWASocket({
        auth: state,
        printQRInTerminal: true
    })

    melody.ev.on('connection.update', ({ connection, lastDisconnect }) => {
        if (connection === 'close') {
            const shouldReconnect = (lastDisconnect?.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
            if (shouldReconnect) startBot()
        }
        if (connection === 'open') console.log('✅ ¡Conectado!')
    })

    melody.ev.on('messages.upsert', async ({ messages }) => {
        const m = messages[0]
        if (!m.message) return

        await melody.sendMessage(m.key.remoteJid!, { 
            text: '¡Hola! Soy un bot de Delta!' 
        })
    })

    melody.ev.on('creds.update', saveCreds)
}

startBot()

✨ Características

General

  • 🚀 Optimizado para mayor velocidad y estabilidad
  • 📸 Mensajes multimedia (imágenes, video, audio, documentos)
  • 🤖 Comandos personalizados fáciles de implementar
  • 👥 Soporte para grupos y chats privados
  • 🔘 Mensajes interactivos con botones, listas y más (nuevo en v1.8.9)
  • 🎯 Resolución automática de JID objetivo en comandos (nuevo en v1.8.9)

Técnicas

  • ⚡ Sin Selenium — Conexión directa vía WebSocket
  • 💾 Super eficiente — Bajo consumo de RAM
  • 📱 Soporte multi-dispositivo — Compatible con WhatsApp Web
  • 🔷 Totalmente tipado — TypeScript y JavaScript
  • 🔄 Reconexión automática ante desconexiones
  • 🔐 Sesiones persistentes guardadas localmente
  • 🌐 API completa de WhatsApp Web
  • 🍎 Compatible con macOS — Error de pairing reparado (fix en v1.8.9)

🎯 resolveJid — Resolver JID objetivo (nuevo en v1.8.9)

resolveJid resuelve automáticamente el JID del usuario objetivo en un comando, siguiendo esta prioridad:

  1. Mensaje citado — si el comando va en respuesta a otro mensaje
  2. Mención — si se menciona a alguien con @
  3. Argumento — si se escribe un número directamente
  4. Sender — fallback al propio usuario que ejecutó el comando

Importar

// JavaScript (CommonJS)
const { resolveJid } = require('@fer2809fl/baileys')
// TypeScript / ESM
import { resolveJid } from '@fer2809fl/baileys'

Uso básico

// resolveJid(m, arg?)
// m   = objeto del mensaje
// arg = argumento de texto del comando (opcional)

const target = resolveJid(m, args[0])
// target → '521234567890@s.whatsapp.net'

Ejemplo en un plugin

// plugins/kick.js
import { resolveJid } from '@fer2809fl/baileys'

let handler = async (m, { conn, args, isAdmin, isBotAdmin }) => {
    if (!isAdmin)   return conn.sendMessage(m.chat, { text: '❌ Solo admins.' })
    if (!isBotAdmin) return conn.sendMessage(m.chat, { text: '❌ El bot necesita ser admin.' })

    // Resuelve automáticamente: citado / mención / número / sender
    const target = resolveJid(m, args[0])

    await conn.groupParticipantsUpdate(m.chat, [target], 'remove')
    await conn.sendMessage(m.chat, {
        text: `✅ Usuario expulsado: @${target.split('@')[0]}`,
        mentions: [target]
    })
}

handler.command = /^(kick|expulsar)$/i
handler.group   = true
handler.admin   = true
handler.botAdmin = true
export default handler

Casos que resuelve automáticamente

Caso Ejemplo Resultado
Mensaje citado Responder a un mensaje con .kick JID del autor del mensaje citado
Mención .kick @usuario JID del usuario mencionado
Número .kick 521234567890 521234567890@s.whatsapp.net
Sin argumento .kick JID del sender (quien ejecutó el comando)

🔘 Botones Interactivos (nuevo en v1.8.9)

Desde la versión 1.8.9 puedes importar y usar funciones nativas para enviar botones interactivos de WhatsApp.

Importar las funciones

// JavaScript (CommonJS)
const {
    sendCopyButton,
    sendUrlButton,
    sendQuickReplyButtons,
    sendCallButton,
    sendListMenu,
    sendInteractiveMessage
} = require('@fer2809fl/baileys')
// TypeScript / ESM
import {
    sendCopyButton,
    sendUrlButton,
    sendQuickReplyButtons,
    sendCallButton,
    sendListMenu,
    sendInteractiveMessage
} from '@fer2809fl/baileys'

📋 sendCopyButton — Botón Copiar

Muestra un botón que al tocarlo copia un texto al portapapeles del usuario.

await sendCopyButton(
    conn,
    jid,
    '📋 *CÓDIGO DE INSTALACIÓN*\n\nEjecuta este comando en tu terminal:',
    'npm install asta-bot',   // texto que se copiará
    '📋 Copiar Comando'       // etiqueta del botón
)

🔗 sendUrlButton — Botón URL

Abre un enlace en el navegador al tocar el botón.

await sendUrlButton(
    conn,
    jid,
    '🔗 *ENLACES IMPORTANTES*\n\nVisita nuestro repositorio oficial:',
    'https://github.com/Fer2809fl/Asta_bot',  // URL de destino
    '🌐 Ver GitHub'                            // etiqueta del botón
)

sendQuickReplyButtons — Botones de Respuesta Rápida

Muestra varios botones de respuesta rápida debajo del mensaje.

await sendQuickReplyButtons(
    conn,
    jid,
    '🎮 *MENÚ DE OPCIONES*\n\n¿Qué deseas hacer?',
    [
        { id: 'menu',  text: '📋 Ver Menú'    },
        { id: 'info',  text: 'ℹ️ Información' },
        { id: 'owner', text: '👑 Owner'       }
    ]
)

📞 sendCallButton — Botón de Llamada

Inicia una llamada al número indicado al tocar el botón.

await sendCallButton(
    conn,
    jid,
    '📞 *SOPORTE TÉCNICO*\n\n¿Necesitas ayuda? Llámanos:',
    '+5214183357841',  // número de teléfono
    '📞 Llamar Ahora'  // etiqueta del botón
)

📋 sendListMenu — Menú Desplegable (Lista)

Muestra un menú con secciones y opciones seleccionables.

await sendListMenu(
    conn,
    jid,
    '📋 *SELECCIONA UNA OPCIÓN*',
    'Menú Principal',  // título del botón que abre la lista
    [
        {
            title: '📱 COMANDOS BÁSICOS',
            rows: [
                { id: '#menu',  title: '📋 Menú',  description: 'Ver todos los comandos' },
                { id: '#ping',  title: '🏓 Ping',  description: 'Ver latencia del bot'   },
                { id: '#owner', title: '👑 Owner', description: 'Info del creador'       }
            ]
        },
        {
            title: '🎮 COMANDOS DE GRUPO',
            rows: [
                { id: '#add',     title: '➕ Agregar', description: 'Agregar usuario al grupo'  },
                { id: '#kick',    title: '👢 Expulsar', description: 'Expulsar usuario del grupo' },
                { id: '#promote', title: '⭐ Promover', description: 'Dar admin a un usuario'   }
            ]
        },
        {
            title: '🔧 CONFIGURACIÓN',
            rows: [
                { id: '#sinprefix', title: '⚙️ Sin Prefijo', description: 'Activar/desactivar prefijo' },
                { id: '#antilink', title: '🔗 Anti Link',    description: 'Bloquear enlaces'           }
            ]
        }
    ]
)

🎯 sendInteractiveMessage — Múltiples Botones Mixtos

Combina distintos tipos de botones en un solo mensaje.

await sendInteractiveMessage(
    conn,
    jid,
    '🎯 *PANEL DE CONTROL*\n\nSelecciona una acción rápida:',
    [
        { type: 'url',   text: '🌐 GitHub',        value: 'https://github.com/Fer2809fl/Asta_bot' },
        { type: 'copy',  text: '📋 Comando Inicio', value: 'npm start'                             },
        { type: 'quick', text: '📋 Ver Menú',       value: 'menu'                                  }
    ]
)

Plugin de ejemplo completo

Aquí un plugin listo para usar en tu bot con todos los tipos de botones:

// plugins/botones.js
import { 
    sendCopyButton,
    sendUrlButton,
    sendQuickReplyButtons,
    sendCallButton,
    sendListMenu,
    sendInteractiveMessage
} from '@fer2809fl/baileys'

let handler = async (m, { conn, usedPrefix }) => {

    // #boton1 — Botón Copiar
    if (m.text === `${usedPrefix}boton1`) {
        await sendCopyButton(conn, m.chat,
            '📋 *CÓDIGO DE INSTALACIÓN*\n\nEjecuta este comando en tu terminal:',
            'npm install asta-bot',
            '📋 Copiar Comando'
        )
    }

    // #boton2 — Botón URL
    else if (m.text === `${usedPrefix}boton2`) {
        await sendUrlButton(conn, m.chat,
            '🔗 *ENLACES IMPORTANTES*\n\nVisita nuestro repositorio oficial:',
            'https://github.com/Fer2809fl/Asta_bot',
            '🌐 Ver GitHub'
        )
    }

    // #boton3 — Botones de Respuesta Rápida
    else if (m.text === `${usedPrefix}boton3`) {
        await sendQuickReplyButtons(conn, m.chat,
            '🎮 *MENÚ DE OPCIONES*\n\n¿Qué deseas hacer?',
            [
                { id: 'menu',  text: '📋 Ver Menú'    },
                { id: 'info',  text: 'ℹ️ Información' },
                { id: 'owner', text: '👑 Owner'       }
            ]
        )
    }

    // #boton4 — Botón de Llamada
    else if (m.text === `${usedPrefix}boton4`) {
        await sendCallButton(conn, m.chat,
            '📞 *SOPORTE TÉCNICO*\n\n¿Necesitas ayuda? Llámanos:',
            '+5214183357841',
            '📞 Llamar Ahora'
        )
    }

    // #boton5 — Lista Desplegable
    else if (m.text === `${usedPrefix}boton5`) {
        await sendListMenu(conn, m.chat,
            '📋 *SELECCIONA UNA OPCIÓN*',
            'Menú Principal',
            [
                {
                    title: '📱 COMANDOS BÁSICOS',
                    rows: [
                        { id: '#menu',  title: '📋 Menú',  description: 'Ver todos los comandos' },
                        { id: '#ping',  title: '🏓 Ping',  description: 'Ver latencia del bot'   },
                        { id: '#owner', title: '👑 Owner', description: 'Info del creador'       }
                    ]
                },
                {
                    title: '🎮 COMANDOS DE GRUPO',
                    rows: [
                        { id: '#add',     title: '➕ Agregar', description: 'Agregar usuario al grupo'    },
                        { id: '#kick',    title: '👢 Expulsar', description: 'Expulsar usuario del grupo' },
                        { id: '#promote', title: '⭐ Promover', description: 'Dar admin a un usuario'    }
                    ]
                },
                {
                    title: '🔧 CONFIGURACIÓN',
                    rows: [
                        { id: '#sinprefix', title: '⚙️ Sin Prefijo', description: 'Activar/desactivar prefijo' },
                        { id: '#antilink',  title: '🔗 Anti Link',   description: 'Bloquear enlaces'           }
                    ]
                }
            ]
        )
    }

    // #boton6 — Botones Mixtos
    else if (m.text === `${usedPrefix}boton6`) {
        await sendInteractiveMessage(conn, m.chat,
            '🎯 *PANEL DE CONTROL*\n\nSelecciona una acción rápida:',
            [
                { type: 'url',   text: '🌐 GitHub',        value: 'https://github.com/Fer2809fl/Asta_bot' },
                { type: 'copy',  text: '📋 Comando Inicio', value: 'npm start'                             },
                { type: 'quick', text: '📋 Ver Menú',       value: 'menu'                                  }
            ]
        )
    }

    // #botones — Ayuda
    else if (m.text === `${usedPrefix}botones`) {
        await conn.reply(m.chat,
            `🧪 *COMANDOS DE PRUEBA - BOTONES INTERACTIVOS*\n\n` +
            `┌✦ *BOTÓN COPIAR*\n` +
            `│ ${usedPrefix}boton1 - Botón que copia texto\n│\n` +
            `├✦ *BOTÓN URL*\n` +
            `│ ${usedPrefix}boton2 - Botón que abre enlace\n│\n` +
            `├✦ *BOTONES RÁPIDOS*\n` +
            `│ ${usedPrefix}boton3 - Botones de respuesta\n│\n` +
            `├✦ *BOTÓN LLAMADA*\n` +
            `│ ${usedPrefix}boton4 - Botón para llamar\n│\n` +
            `├✦ *LISTA DESPLEGABLE*\n` +
            `│ ${usedPrefix}boton5 - Menú con opciones\n│\n` +
            `└✦ *MÚLTIPLES BOTONES*\n` +
            `  ${usedPrefix}boton6 - Combinación de botones\n\n` +
            `✨ *Prueba cada uno y mira cómo funcionan!*`, m)
    }
}

handler.command = ['boton1', 'boton2', 'boton3', 'boton4', 'boton5', 'boton6', 'botones']
handler.help    = ['boton1', 'boton2', 'boton3', 'boton4', 'boton5', 'boton6', 'botones']
handler.tags    = ['test']

export default handler

📖 Uso Básico

Inicializar el bot

// JavaScript
const { makeWASocket, useMultiFileAuthState } = require('@fer2809fl/baileys')

const { state, saveCreds } = await useMultiFileAuthState('session-mymelody')
const melody = makeWASocket({ auth: state, printQRInTerminal: true })
melody.ev.on('creds.update', saveCreds)
// TypeScript
import makeWASocket, { useMultiFileAuthState } from '@fer2809fl/baileys'

const { state, saveCreds } = await useMultiFileAuthState('session-mymelody')
const melody = makeWASocket({ auth: state, printQRInTerminal: true })
melody.ev.on('creds.update', saveCreds)

Enviar mensajes

// Texto simple
await melody.sendMessage(jid, { text: '¡Hola mundo!' })

// Imagen con caption
await melody.sendMessage(jid, {
    image: { url: './images/mymelody.jpg' },
    caption: '¡Mira mi nueva foto!'
})

// Video con caption
await melody.sendMessage(jid, {
    video: { url: './videos/clip.mp4' },
    caption: '¡Nuevo video!'
})

// Audio (PTT = nota de voz)
await melody.sendMessage(jid, {
    audio: { url: './audio/nota.mp3' },
    mimetype: 'audio/mp4',
    ptt: true
})

// Sticker
await melody.sendMessage(jid, {
    sticker: { url: './stickers/melody.webp' }
})

// Documento
await melody.sendMessage(jid, {
    document: { url: './archivo.pdf' },
    mimetype: 'application/pdf',
    fileName: 'archivo.pdf'
})

// Reaccionar a un mensaje
await melody.sendMessage(jid, {
    react: { text: '💖', key: m.key }
})

🤖 Comandos Personalizados

JavaScript

melody.ev.on('messages.upsert', async ({ messages }) => {
    const m = messages[0]
    const body = m.message?.conversation
        || m.message?.extendedTextMessage?.text
        || ''

    const prefix = '!'
    if (!body.startsWith(prefix)) return

    const [cmd, ...args] = body.slice(prefix.length).trim().split(' ')

    switch (cmd.toLowerCase()) {
        case 'hola':
            await melody.sendMessage(m.key.remoteJid, {
                text: '¡Hola! Soy Delta, ¿en qué puedo ayudarte?'
            })
            break
        case 'ping':
            await melody.sendMessage(m.key.remoteJid, { text: '🏓 Pong!' })
            break
        default:
            await melody.sendMessage(m.key.remoteJid, {
                text: `Comando desconocido: ${cmd}`
            })
    }
})

⚙️ Configuración Avanzada

const melody = makeWASocket({
    auth: state,
    printQRInTerminal: true,
    markOnlineOnConnect: false,
    browser: ["Delta", "Chrome", "1.0.0"],
    logger: require('pino')({ level: 'silent' }),
    syncFullHistory: false,
    generateHighQualityLinkPreview: true
})

🛠️ Funciones Útiles

Broadcast a múltiples chats

async function broadcastMessage(jids, message) {
    for (const jid of jids) {
        await melody.sendMessage(jid, { text: message })
        await new Promise(r => setTimeout(r, 1000)) // delay para evitar ban
    }
}

Descargar medios recibidos

const { downloadMediaMessage } = require('@fer2809fl/baileys')

melody.ev.on('messages.upsert', async ({ messages }) => {
    const m = messages[0]
    if (!m.message?.imageMessage) return

    const buffer = await downloadMediaMessage(m, 'buffer', {})
    require('fs').writeFileSync('./imagen_recibida.jpg', buffer)
    console.log('✅ Imagen guardada')
})

Obtener info de un grupo

const metadata = await melody.groupMetadata(jid)
console.log('Nombre:', metadata.subject)
console.log('Participantes:', metadata.participants.length)

Mencionar usuarios en un grupo

await melody.sendMessage(jid, {
    text: '@1234567890 ¡Hola!',
    mentions: ['1234567890@s.whatsapp.net']
})

📁 Estructura Recomendada del Proyecto

mi-bot/
├── index.js          # Entrada principal
├── config.js         # Configuración general
├── commands/
│   ├── hola.js
│   ├── ping.js
│   ├── stickers.js
│   └── botones.js    
├── events/
│   ├── messages.js
│   └── connection.js
├── utils/
│   └── helpers.js
└── session-mymelody/ # Sesión guardada automáticamente

📝 Historial de Versiones

Versión Cambios
1.8.9 ✅ Botones interactivos (sendCopyButton, sendUrlButton, sendQuickReplyButtons, sendCallButton, sendListMenu, sendInteractiveMessage) — 🎯 Nueva función resolveJid para resolver JID objetivo — 🐛 Fix error de pairing en macOS
1.4.5 Versión estable anterior

🔗 Links


Desarrollado con 🤍 por Fer2809fl

About

No description, website, or topics provided.

Resources

License

Stars

2 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors