Files
Autoparts-DB/pos/whatsapp-bridge-server.js
consultoria-as e43894b7a4 feat: WhatsApp bridge con Baileys directo — QR funcional
Reemplaza Evolution API con bridge Node.js propio usando Baileys.
QR se genera en ~10 segundos. Auto-reply con chatbot IA.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 04:02:16 +00:00

75 lines
3.6 KiB
JavaScript

const { default: makeWASocket, useMultiFileAuthState, DisconnectReason, fetchLatestBaileysVersion } = require('@whiskeysockets/baileys');
const express = require('express');
const QRCode = require('qrcode');
const pino = require('pino');
const app = express();
app.use(express.json());
const PORT = 21465;
const API_KEY = 'nexus-wpp-secret-2026';
const WEBHOOK_URL = 'http://localhost:5001/pos/api/whatsapp/webhook';
let sock = null;
let qrCode = null;
let connectionState = 'disconnected';
const logger = pino({ level: 'warn' });
async function connectWhatsApp() {
const { state, saveCreds } = await useMultiFileAuthState('/opt/whatsapp-bridge/auth');
const { version } = await fetchLatestBaileysVersion();
console.log('Connecting with Baileys v' + version.join('.'));
connectionState = 'connecting';
sock = makeWASocket({ version, auth: state, logger, printQRInTerminal: true, browser: ['Nexus POS', 'Chrome', '120.0'] });
sock.ev.on('creds.update', saveCreds);
sock.ev.on('connection.update', async (update) => {
const { connection, lastDisconnect, qr } = update;
if (qr) {
qrCode = await QRCode.toDataURL(qr);
connectionState = 'qr';
console.log('QR code generated!');
}
if (connection === 'close') {
connectionState = 'disconnected';
qrCode = null;
const reason = lastDisconnect?.error?.output?.statusCode;
if (reason !== DisconnectReason.loggedOut) { setTimeout(connectWhatsApp, 5000); }
}
if (connection === 'open') { connectionState = 'open'; qrCode = null; console.log('Connected!'); }
});
sock.ev.on('messages.upsert', async ({ messages }) => {
for (const msg of messages) {
if (msg.key.fromMe) continue;
const phone = msg.key.remoteJid.replace('@s.whatsapp.net', '');
const text = msg.message?.conversation || msg.message?.extendedTextMessage?.text || '';
console.log('From ' + phone + ': ' + text);
try {
await fetch(WEBHOOK_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ event: 'messages.upsert', data: { key: msg.key, message: msg.message, messageTimestamp: msg.messageTimestamp } }) });
} catch (e) { console.log('Webhook failed:', e.message); }
}
});
}
app.get('/', (req, res) => res.json({ status: 'ok', service: 'Nexus WhatsApp Bridge', state: connectionState }));
app.get('/status', (req, res) => res.json({ state: connectionState, hasQr: !!qrCode }));
app.get('/qr', (req, res) => {
if (connectionState === 'open') return res.json({ state: 'open', message: 'Already connected' });
if (!qrCode) return res.json({ state: connectionState, qr: null, message: 'QR not ready' });
res.json({ state: 'qr', qr: qrCode });
});
app.post('/connect', async (req, res) => { if (!sock) connectWhatsApp(); res.json({ state: connectionState }); });
app.post('/send', async (req, res) => {
if (connectionState !== 'open') return res.status(400).json({ error: 'Not connected' });
const { phone, message } = req.body;
const jid = phone.includes('@') ? phone : phone + '@s.whatsapp.net';
try { const r = await sock.sendMessage(jid, { text: message }); res.json({ success: true, id: r.key.id }); }
catch (e) { res.status(500).json({ error: e.message }); }
});
app.post('/logout', async (req, res) => { if (sock) { await sock.logout(); sock = null; } qrCode = null; connectionState = 'disconnected'; res.json({ state: 'disconnected' }); });
app.listen(PORT, () => { console.log('WhatsApp Bridge on port ' + PORT); connectWhatsApp(); });