Bot: endpoint /debug para diagnosticar entrantes + estado de conexión

GET /debug (Basic auth, QR_TOKEN) devuelve el estado de la conexión de WhatsApp
y un anillo de los últimos mensajes entrantes (remoteJid real, fromMe, tipo) y
el resultado del matching lead↔teléfono. Para diagnosticar por qué el bot no
responde (conexión zombi vs formato de jid @lid vs no llega el mensaje).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Carlos Narro
2026-06-09 17:51:10 +02:00
parent a8b6d62dd6
commit 8d565e5fb0
2 changed files with 51 additions and 4 deletions

View File

@@ -196,6 +196,13 @@ export class WhatsappService implements OnModuleInit, OnModuleDestroy {
this.sock.ev.on('connection.update', (update) => {
const { connection, lastDisconnect, qr } = update;
this.webhookListener.setConnState({
connection: connection ?? null,
hasQr: !!qr,
lastDisconnect: (lastDisconnect?.error as Boom)?.output?.statusCode ?? null,
at: new Date().toISOString(),
});
if (qr) {
QRCode.generate(qr, { small: true });
console.log('\n📲 Escanea este QR con WhatsApp (o abre la página /qr, protegida con QR_TOKEN)\n');
@@ -218,6 +225,12 @@ export class WhatsappService implements OnModuleInit, OnModuleDestroy {
this.sock.ev.on('messages.upsert', async ({ messages, type }) => {
if (type !== 'notify') return;
for (const msg of messages) {
this.webhookListener.pushInbound({
remoteJid: msg.key.remoteJid ?? null,
fromMe: !!msg.key.fromMe,
msgType: msg.message ? Object.keys(msg.message)[0] : null,
at: new Date().toISOString(),
});
if (msg.key.fromMe) continue;
if (!msg.key.remoteJid) continue;
if (msg.key.remoteJid.includes('@g.us')) continue;
@@ -274,6 +287,7 @@ export class WhatsappService implements OnModuleInit, OnModuleDestroy {
}
}
this.webhookListener.pushInbound({ stage: 'match', telefono, leadId: leadId ?? null, at: new Date().toISOString() });
if (!leadId) {
this.logger.log(`Mensaje ignorado de ${telefono}: lead no registrado. Debe iniciarse desde la web.`);
return null;