diff --git a/mvp/Whatsapp-bot/src/webhook/webhook-listener.ts b/mvp/Whatsapp-bot/src/webhook/webhook-listener.ts index 57f74de..1f0855d 100644 --- a/mvp/Whatsapp-bot/src/webhook/webhook-listener.ts +++ b/mvp/Whatsapp-bot/src/webhook/webhook-listener.ts @@ -143,20 +143,29 @@ export class WebhookListener implements OnApplicationBootstrap { // eslint-disable-next-line @typescript-eslint/no-unused-vars private leadSessions = new Map(); + private normTel(t: string): string { + return (t || '').replace(/\D/g, ''); + } + private async handleWhatsappStart(payload: { leadId: string; telefono: string; nombre: string; empresa: string }) { - const { leadId, telefono, nombre } = payload; + const { leadId, nombre, empresa } = payload; + const telefono = this.normTel(payload.telefono); this.logger.log(`[START] leadId=${leadId}, telefono=${telefono}, nombre=${nombre}`); this.leadSessions.set(telefono, { leadId, telefono, nombre, jid: null }); - this.logger.log(`Lead ${leadId} registrado en sesiones.`); + + // Dispara la apertura proactiva (la envía WhatsappService, evitando dependencia circular). + const { startEmitter } = await import('../whatsapp/whatsapp.service'); + startEmitter.emit('start', { leadId, telefono, nombre, empresa }); + this.logger.log(`Lead ${leadId} registrado; apertura disparada.`); } getLeadIdByTelefono(telefono: string): string | null { - return this.leadSessions.get(telefono)?.leadId ?? null; + return this.leadSessions.get(this.normTel(telefono))?.leadId ?? null; } registerJid(telefono: string, jid: string) { - const session = this.leadSessions.get(telefono); + const session = this.leadSessions.get(this.normTel(telefono)); if (session) { session.jid = jid; } diff --git a/mvp/Whatsapp-bot/src/whatsapp/whatsapp.service.ts b/mvp/Whatsapp-bot/src/whatsapp/whatsapp.service.ts index 48e2037..5e14ccc 100644 --- a/mvp/Whatsapp-bot/src/whatsapp/whatsapp.service.ts +++ b/mvp/Whatsapp-bot/src/whatsapp/whatsapp.service.ts @@ -27,6 +27,7 @@ import { ApiClient } from '../api/api-client.service'; import { wrapSocket } from 'baileys-antiban'; export const pdfEmitter = new EventEmitter(); +export const startEmitter = new EventEmitter(); interface LeadContext { leadId: string; @@ -62,6 +63,7 @@ export class WhatsappService implements OnModuleInit, OnModuleDestroy { async onModuleInit() { await this.conectar(); this.escucharPdf(); + this.escucharStart(); } async onModuleDestroy() { @@ -98,6 +100,66 @@ export class WhatsappService implements OnModuleInit, OnModuleDestroy { }); } + // Apertura proactiva: cuando el funnel dispara /whatsapp-start, Luisa escribe ella el primer + // mensaje (el bot ya no es solo reactivo). + private escucharStart() { + startEmitter.on( + 'start', + async (p: { leadId: string; telefono: string; nombre: string; empresa: string }) => { + try { + await this.enviarApertura(p); + } catch (err: any) { + this.logger.error(`[APERTURA] Error: ${err.message}`); + } + }, + ); + } + + private async enviarApertura(p: { leadId: string; telefono: string; nombre: string; empresa: string }) { + if (!this.sock) { + this.logger.warn(`[APERTURA] WhatsApp no conectado; no se envía a ${p.telefono}`); + return; + } + const tel = (p.telefono || '').replace(/\D/g, ''); + let jid = `${tel}@s.whatsapp.net`; + try { + const res = await this.sock.onWhatsApp(tel); + if (res && res[0]?.exists && res[0]?.jid) jid = res[0].jid; + else if (!res || !res[0]?.exists) this.logger.warn(`[APERTURA] ${tel} no parece estar en WhatsApp`); + } catch { + /* seguimos con el jid por defecto */ + } + + const primerNombre = (p.nombre || '').trim().split(' ')[0] || 'hola'; + const empresa = p.empresa || 'Reformix'; + const apertura = + `¡Hola ${primerNombre}! Soy Luisa, del equipo de ${empresa}. 😊\n\n` + + `Acabas de pedir presupuesto para tu reforma y te ayudo a prepararlo (con un render de cómo ` + + `quedaría incluido). Para empezar, cuéntame: ¿qué espacio quieres reformar? (cocina, baño, salón…)`; + + // Contexto para los siguientes mensajes del cliente. + this.jidToLeadId.set(jid, p.leadId); + this.webhookListener.registerJid(tel, jid); + this.leadCache.set(p.leadId, { + leadId: p.leadId, + telefono: tel, + nombre: p.nombre || '', + botStep: 'apertura', + viable: null, + }); + + await this.enviarMensaje(jid, apertura); + this.logger.log(`[APERTURA] Enviada a ${jid} (lead ${p.leadId})`); + + try { + await this.api.actualizarPerfil(p.leadId, { estadoWa: 'enviado', botStep: 'apertura', canalOrigen: 'whatsapp' }); + await this.conversacionService.guardarMensaje(p.leadId, 'assistant', apertura, { botStep: 'apertura' }); + await this.api.registrarIntento(p.leadId, 'whatsapp', 1, 'exitoso', true); + } catch (err: any) { + this.logger.warn(`[APERTURA] No se pudo persistir en la app: ${err.message}`); + } + } + private normalizarTelefono(jid: string): string { return jid.split('@')[0].replace(/\D/g, ''); }