From 0c803c2fe1eb01d7805a527588372467b0d8a6ca Mon Sep 17 00:00:00 2001 From: marsalva Date: Sat, 7 Mar 2026 20:58:20 +0000 Subject: [PATCH] Actualizar server.js --- server.js | 66 +++++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/server.js b/server.js index ee0dcb0..7daba77 100644 --- a/server.js +++ b/server.js @@ -2968,51 +2968,57 @@ app.post("/services/:id/chat", authMiddleware, async (req, res) => { } }); -// 🤖 WEBHOOK PARA RECIBIR MENSAJES DE WHATSAPP Y RESPONDER CON IA +// 🤖 WEBHOOK CON ESCUDO DE INTERVENCIÓN HUMANA app.post("/webhook/evolution", async (req, res) => { try { const data = req.body; - - // 1. Filtrar solo mensajes de texto entrantes if (data.event !== "messages.upsert" || data.data.key.fromMe) return res.sendStatus(200); const remoteJid = data.data.key.remoteJid; - const telefonoCliente = remoteJid.split("@")[0]; // Ej: 34666777888 + const telefonoCliente = remoteJid.split("@")[0]; const mensajeTexto = data.data.message?.conversation || data.data.message?.extendedTextMessage?.text; - const instanceName = data.instance; // Ej: cliente_1 + const instanceName = data.instance; if (!mensajeTexto) return res.sendStatus(200); - console.log(`📩 [WEBHOOK] Mensaje de ${telefonoCliente}: "${mensajeTexto}" (Instancia: ${instanceName})`); - - // 2. Identificar al dueño (owner_id) const ownerId = instanceName.split("_")[1]; - if (!ownerId) { - console.error("❌ [WEBHOOK] No se pudo determinar el ownerId de la instancia:", instanceName); - return res.sendStatus(200); - } - - // 3. Buscar siniestro por teléfono (Búsqueda ULTRA-FLEXIBLE en todo el JSON) - // Buscamos los últimos 9 dígitos para ignorar el +34 o 34 const cleanPhone = telefonoCliente.slice(-9); + // 1. BUSCAMOS EL SINIESTRO const svcQ = await pool.query(` SELECT s.id, s.service_ref, u.full_name as worker_name, st.name as status_name, s.raw_data->>'scheduled_date' as cita FROM scraped_services s LEFT JOIN users u ON s.assigned_to = u.id LEFT JOIN service_statuses st ON (s.raw_data->>'status_operativo')::text = st.id::text - WHERE s.owner_id = $1 - AND s.status != 'archived' - AND s.raw_data::text ILIKE $2 + WHERE s.owner_id = $1 AND s.status != 'archived' AND s.raw_data::text ILIKE $2 ORDER BY s.created_at DESC LIMIT 1 `, [ownerId, `%${cleanPhone}%`]); if (svcQ.rowCount > 0) { const service = svcQ.rows[0]; - console.log(`🔎 [IA] Siniestro localizado: #${service.service_ref}. Preparando respuesta...`); - - // 4. Llamar a la IA + + // 🛡️ 2. VERIFICAR INTERVENCIÓN HUMANA (NUEVO) + // Miramos si el último mensaje fue de un humano en las últimas 2 horas + const checkHumanQ = await pool.query(` + SELECT sender_role, created_at + FROM service_communications + WHERE scraped_id = $1 + ORDER BY created_at DESC LIMIT 1 + `, [service.id]); + + if (checkHumanQ.rowCount > 0) { + const lastMsg = checkHumanQ.rows[0]; + const diffMinutos = (new Date() - new Date(lastMsg.created_at)) / (1000 * 60); + + // Si el último que habló fue admin/operario y hace menos de 120 min, la IA no responde + if (['admin', 'superadmin', 'operario'].includes(lastMsg.sender_role) && diffMinutos < 120) { + console.log(`🤫 [IA Silenciada] Un humano ha intervenido hace ${Math.round(diffMinutos)} min en el exp #${service.service_ref}`); + return res.sendStatus(200); + } + } + + // 3. SI NO HAY HUMANO RECIENTE, LLAMAMOS A LA IA const respuestaIA = await procesarConIA(ownerId, mensajeTexto, { ref: service.service_ref, estado: service.status_name || "En proceso", @@ -3021,24 +3027,12 @@ app.post("/webhook/evolution", async (req, res) => { }); if (respuestaIA) { - console.log(`🤖 [IA] Respondiendo: "${respuestaIA}"`); - // 5. Enviar respuesta por WhatsApp await sendWhatsAppAuto(telefonoCliente, respuestaIA, instanceName, true); - - // 6. Registrar en el chat y logs de trazabilidad - await pool.query(` - INSERT INTO service_communications (scraped_id, owner_id, sender_name, sender_role, message) - VALUES ($1, $2, $3, $4, $5) - `, [service.id, ownerId, "Asistente IA", "ia", respuestaIA]); - - await registrarMovimiento(service.id, null, "Respuesta IA", `ChatGPT respondió automáticamente al cliente.`); - } else { - console.log("ℹ️ [IA] ChatGPT no generó respuesta (Botón OFF o error interno)."); + await pool.query(`INSERT INTO service_communications (scraped_id, owner_id, sender_name, sender_role, message) VALUES ($1, $2, $3, $4, $5)`, + [service.id, ownerId, "Asistente IA", "ia", respuestaIA]); + await registrarMovimiento(service.id, null, "Respuesta IA", `ChatGPT respondió automáticamente.`); } - } else { - console.warn(`⚠️ [WEBHOOK] No hay siniestros activos para el teléfono ${cleanPhone} en la cuenta del admin ${ownerId}`); } - res.sendStatus(200); } catch (e) { console.error("❌ [WEBHOOK ERROR]:", e.message);