Actualizar server.js
This commit is contained in:
52
server.js
52
server.js
@@ -2981,59 +2981,77 @@ app.post("/services/:id/chat", authMiddleware, async (req, res) => {
|
|||||||
app.post("/webhook/evolution", async (req, res) => {
|
app.post("/webhook/evolution", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const data = req.body;
|
const data = req.body;
|
||||||
// Solo procesamos si es un mensaje de texto entrante
|
|
||||||
|
// 1. Filtrar solo mensajes de texto entrantes
|
||||||
if (data.event !== "messages.upsert" || data.data.key.fromMe) return res.sendStatus(200);
|
if (data.event !== "messages.upsert" || data.data.key.fromMe) return res.sendStatus(200);
|
||||||
|
|
||||||
const telefonoCliente = data.data.key.remoteJid.split("@")[0];
|
const remoteJid = data.data.key.remoteJid;
|
||||||
|
const telefonoCliente = remoteJid.split("@")[0]; // Ej: 34666777888
|
||||||
const mensajeTexto = data.data.message?.conversation || data.data.message?.extendedTextMessage?.text;
|
const mensajeTexto = data.data.message?.conversation || data.data.message?.extendedTextMessage?.text;
|
||||||
const instanceName = data.instance; // ej: cliente_1
|
const instanceName = data.instance; // Ej: cliente_1
|
||||||
|
|
||||||
if (!mensajeTexto) return res.sendStatus(200);
|
if (!mensajeTexto) return res.sendStatus(200);
|
||||||
|
|
||||||
// 1. Identificar al dueño de la instancia (owner_id)
|
console.log(`📩 [WEBHOOK] Mensaje de ${telefonoCliente}: "${mensajeTexto}" (Instancia: ${instanceName})`);
|
||||||
const ownerId = instanceName.split("_")[1];
|
|
||||||
|
|
||||||
// 2. Buscar si este teléfono tiene un servicio activo
|
// 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);
|
||||||
|
|
||||||
const svcQ = await pool.query(`
|
const svcQ = await pool.query(`
|
||||||
SELECT s.id, s.service_ref, s.assigned_to, u.full_name as worker_name,
|
SELECT s.id, s.service_ref, u.full_name as worker_name,
|
||||||
st.name as status_name, s.raw_data->>'scheduled_date' as cita
|
st.name as status_name, s.raw_data->>'scheduled_date' as cita
|
||||||
FROM scraped_services s
|
FROM scraped_services s
|
||||||
LEFT JOIN users u ON s.assigned_to = u.id
|
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
|
LEFT JOIN service_statuses st ON (s.raw_data->>'status_operativo')::text = st.id::text
|
||||||
WHERE s.owner_id = $1 AND s.raw_data->>'Teléfono' 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
|
ORDER BY s.created_at DESC LIMIT 1
|
||||||
`, [ownerId, `%${telefonoCliente.slice(-9)}%`]);
|
`, [ownerId, `%${cleanPhone}%`]);
|
||||||
|
|
||||||
if (svcQ.rowCount > 0) {
|
if (svcQ.rowCount > 0) {
|
||||||
const service = svcQ.rows[0];
|
const service = svcQ.rows[0];
|
||||||
|
console.log(`🔎 [IA] Siniestro localizado: #${service.service_ref}. Preparando respuesta...`);
|
||||||
|
|
||||||
// 3. Llamar a la IA
|
// 4. Llamar a la IA
|
||||||
const respuestaIA = await procesarConIA(ownerId, mensajeTexto, {
|
const respuestaIA = await procesarConIA(ownerId, mensajeTexto, {
|
||||||
ref: service.service_ref,
|
ref: service.service_ref,
|
||||||
estado: service.status_name,
|
estado: service.status_name || "En proceso",
|
||||||
operario: service.worker_name,
|
operario: service.worker_name,
|
||||||
cita: service.cita
|
cita: service.cita
|
||||||
});
|
});
|
||||||
|
|
||||||
if (respuestaIA) {
|
if (respuestaIA) {
|
||||||
// 4. Enviar respuesta por WhatsApp
|
console.log(`🤖 [IA] Respondiendo: "${respuestaIA}"`);
|
||||||
|
// 5. Enviar respuesta por WhatsApp
|
||||||
await sendWhatsAppAuto(telefonoCliente, respuestaIA, instanceName, true);
|
await sendWhatsAppAuto(telefonoCliente, respuestaIA, instanceName, true);
|
||||||
|
|
||||||
// 5. Registrar en el chat para que la oficina lo vea
|
// 6. Registrar en el chat y logs de trazabilidad
|
||||||
await pool.query(`
|
await pool.query(`
|
||||||
INSERT INTO service_communications (scraped_id, owner_id, sender_name, sender_role, message)
|
INSERT INTO service_communications (scraped_id, owner_id, sender_name, sender_role, message)
|
||||||
VALUES ($1, $2, $3, $4, $5)
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
`, [service.id, ownerId, "Asistente IA", "ia", respuestaIA]);
|
`, [service.id, ownerId, "Asistente IA", "ia", respuestaIA]);
|
||||||
|
|
||||||
// 6. Registrar en el historial
|
await registrarMovimiento(service.id, null, "Respuesta IA", `ChatGPT respondió automáticamente al cliente.`);
|
||||||
await registrarMovimiento(service.id, null, "Respuesta IA", `ChatGPT respondió: ${respuestaIA}`);
|
} else {
|
||||||
|
console.log("ℹ️ [IA] ChatGPT no generó respuesta (Botón OFF o error interno).");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
console.warn(`⚠️ [WEBHOOK] No hay siniestros activos para el teléfono ${cleanPhone} en la cuenta del admin ${ownerId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
res.sendStatus(200);
|
res.sendStatus(200);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Error Webhook IA:", e.message);
|
console.error("❌ [WEBHOOK ERROR]:", e.message);
|
||||||
res.sendStatus(500);
|
if (!res.headersSent) res.sendStatus(500);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user