diff --git a/robot.js b/robot.js index 56a7857..e36a340 100644 --- a/robot.js +++ b/robot.js @@ -111,10 +111,10 @@ async function main() { } // ========================================== -// 🏥 MULTIASISTENCIA (PAGINACIÓN ANTIBALAS Y DOBLE RECARGA) +// 🏥 MULTIASISTENCIA (PAGINACIÓN Y DOBLE RECARGA) // ========================================== async function runMultiasistencia(ownerId, user, pass, gremiosDB) { - const browser = await chromium.launch({ headless: HEADLESS, args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-gpu'] }); + const browser = await chromium.launch({ headless: HEADLESS, args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-gpu'] }); const context = await browser.newContext(); const page = await context.newPage(); try { @@ -126,19 +126,21 @@ async function runMultiasistencia(ownerId, user, pass, gremiosDB) { await page.waitForTimeout(4000); await gotoWithRetry(page, 'https://web.multiasistencia.com/w3multi/frepasos_new.php?refresh=1'); - console.log("🔄 [Multi] Doble recarga manual..."); + // 🔄 TU TRUCO MANUAL: Recarga -> Espera 3s -> Recarga -> Espera 5s + console.log("🔄 [Multi] Aplicando tu doble recarga manual..."); await page.evaluate(() => { if (typeof refrescar === 'function') refrescar(); }); - await page.waitForTimeout(3000); // Espera de 3 segundos + await page.waitForTimeout(3000); // Primera espera de 3 seg. await page.evaluate(() => { if (typeof refrescar === 'function') refrescar(); }); - await page.waitForTimeout(5000); // Espera de 5 segundos + await page.waitForTimeout(5000); // Segunda espera de 5 seg. para ver la tabla - // --- BUCLE DE PAGINACIÓN INFALIBLE --- let todosExpedientes = new Set(); let paginaActual = 1; + console.log(`📄 [Multi] Iniciando lectura por páginas...`); while (true) { - console.log(`📄 [Multi] Escaneando página ${paginaActual}...`); + console.log(`\n📄 [Multi] Escaneando página ${paginaActual}...`); await page.waitForSelector('a[href*="reparacion="]', { timeout: 8000 }).catch(() => {}); + await page.waitForTimeout(1000); const refs = await page.evaluate(() => { const links = Array.from(document.querySelectorAll('a[href*="reparacion="]')); @@ -146,126 +148,67 @@ async function runMultiasistencia(ownerId, user, pass, gremiosDB) { }); const unicos = [...new Set(refs)]; - console.log(` 👉 Encontrados ${unicos.length} únicos.`); + console.log(` 👉 Encontrados ${unicos.length} expedientes únicos.`); unicos.forEach(r => todosExpedientes.add(r)); + // CLICK EN SIGUIENTE const hasNext = await page.evaluate(() => { - const btn = Array.from(document.querySelectorAll('a.lnkheader')).find(a => a.innerText.includes('siguiente') || a.innerText.includes('>>')); + const btn = Array.from(document.querySelectorAll('a.lnkheader')).find(a => a.innerText.toLowerCase().includes('siguiente')); if (btn) { btn.click(); return true; } return false; }); - if (hasNext && unicos.length === 15) { + if (hasNext && unicos.length > 0) { console.log(" ➡️ Pulsado 'Siguiente'. Esperando 6 segundos a que cargue..."); - await page.waitForTimeout(6000); // Freno de 6 segundos + await page.waitForTimeout(6000); paginaActual++; + if(paginaActual > 20) break; } else { + console.log("🛑 [Multi] Fin de lista."); break; } } - unicosPagina.forEach(ref => todosExpedientes.add(ref)); + const listaFinal = Array.from(todosExpedientes); + console.log(`✅ [Multi] TOTAL: ${listaFinal.length}`); - // 2. BUSCAMOS Y PULSAMOS EL BOTÓN "SIGUIENTE" - const clicked = await page.evaluate(() => { - const links = Array.from(document.querySelectorAll('a.lnkheader')); - const btn = links.find(a => a.innerText.toLowerCase().includes('siguiente')); - if (btn) { - btn.click(); - return true; - } - return false; - }); - - if (clicked) { - console.log(` ➡️ Botón 'Siguiente' detectado. Pulsando y esperando a que cargue...`); - // 🛑 EL FRENO: Congelamos el robot 5 segundos fijos para que el servidor responda - await page.waitForTimeout(5000); - paginaActual++; - - if(paginaActual > 20) { - console.log("⚠️ [Multi] Límite de 20 páginas alcanzado por seguridad."); - break; - } - } else { - console.log("🛑 [Multi] Fin de la lista. No hay enlace a página siguiente."); - break; - } + if (listaFinal.length > 5 || paginaActual === 1) { + await syncAndArchive(ownerId, 'multiasistencia', listaFinal); } - const expedientesUnicos = Array.from(todosExpedientes); - console.log(`\n✅ [Multi] TOTAL EXPEDIENTES LEÍDOS EN WEB: ${expedientesUnicos.length}`); - - // SEGURO DE VIDA PARA MULTIASISTENCIA - if (expedientesUnicos.length > 5 || paginaActual === 1) { - console.log(`🧹 [Multi] Llamando a la escoba con ${expedientesUnicos.length} refs...`); - await syncAndArchive(ownerId, 'multiasistencia', expedientesUnicos); - } else { - console.log("⚠️ [Multi] Menos de 5 expedientes detectados. ABORTANDO ARCHIVADO DE SEGURIDAD."); - } - - // BUCLE DE GUARDADO - for (const ref of expedientesUnicos) { + for (const ref of listaFinal) { await gotoWithRetry(page, `https://web.multiasistencia.com/w3multi/repasos1.php?reparacion=${ref}`); await page.waitForTimeout(1500); let scrapData = null; - for (const frame of page.frames()) { try { scrapData = await frame.evaluate(() => { const clean = (t) => t ? t.replace(/\s+/g, ' ').trim() : ""; - const body = document.body?.innerText || ""; - if (!body.includes("Nombre Cliente") && !body.includes("Asegurado")) return null; - - const cabeceras = Array.from(document.querySelectorAll('.tcab')); - const detalles = Array.from(document.querySelectorAll('.tdet')); - const findByCab = (texto) => { - const idx = cabeceras.findIndex(el => el.innerText.includes(texto)); - return idx !== -1 && detalles[idx] ? clean(detalles[idx].innerText) : null; + const findByCab = (t) => { + const tds = Array.from(document.querySelectorAll('.tcab')); + const idx = tds.findIndex(el => el.innerText.includes(t)); + return idx !== -1 ? clean(tds[idx].nextElementSibling.innerText) : null; }; - - let rawDesc = ""; - const descHeader = Array.from(document.querySelectorAll('td.tcab')).find(td => td.innerText.includes("Descripción de la Reparación")); - if (descHeader && descHeader.nextElementSibling) rawDesc = clean(descHeader.nextElementSibling.innerText); - - const rawCPField = findByCab("Distrito Postal") || ""; - const cpMatch = rawCPField.match(/\b\d{5}\b/); - const cpOnly = cpMatch ? cpMatch[0] : ""; - const popOnly = rawCPField.replace(cpOnly, '').replace('-', '').trim(); - - let telefonoReal = ""; - const titulosDiv = Array.from(document.querySelectorAll('.subtitulo')); - const divTelefono = titulosDiv.find(div => div.innerText && div.innerText.includes('Teléfono')); - if (divTelefono && divTelefono.nextElementSibling) { - const celdaNum = divTelefono.nextElementSibling.querySelector('.tdet'); - if (celdaNum) telefonoReal = celdaNum.innerText.replace(/[^0-9]/g, ''); - } - if (!telefonoReal || telefonoReal.length < 9) { - telefonoReal = (document.body.innerText.match(/[6789]\d{8}/) || [])[0] || ""; - } - + const desc = Array.from(document.querySelectorAll('td.tcab')).find(td => td.innerText.includes("Descripción de la Reparación")); + if (!document.body.innerText.includes("Nombre Cliente")) return null; return { "Expediente": findByCab("Número Reparación") || "", "Nombre Cliente": findByCab("Nombre Cliente") || "", "Dirección": findByCab("Dirección") || "", - "Población": popOnly, - "Código Postal": cpOnly, + "Población": (findByCab("Distrito Postal") || "").replace(/\d{5}/, '').trim(), + "Código Postal": (findByCab("Distrito Postal") || "").match(/\d{5}/)?.[0] || "", "Compañía": "MULTI - " + (findByCab("Procedencia") || "MULTIASISTENCIA"), - "Descripción": rawDesc, - "Teléfono": telefonoReal, + "Descripción": desc ? clean(desc.nextElementSibling.innerText) : "", + "Teléfono": (document.body.innerText.match(/[6789]\d{8}/) || [])[0] || "", "Estado": findByCab("Estado") || "", "Urgente": findByCab("Urgente") || "No" - }; + }; }); if (scrapData && scrapData['Nombre Cliente']) break; } catch(e) {} } - // ESTO ES LO QUE TÚ ME HAS PASADO: if (scrapData && scrapData['Nombre Cliente']) { - const idGremioDetectado = clasificarGremio(scrapData['Descripción'], gremiosDB); - if (idGremioDetectado) { - scrapData['guild_id'] = idGremioDetectado; - } + scrapData['guild_id'] = clasificarGremio(scrapData['Descripción'], gremiosDB); await saveServiceToDB(ownerId, 'multiasistencia', ref, scrapData); } }