diff --git a/robot.js b/robot.js index da5f2dd..d721c01 100644 --- a/robot.js +++ b/robot.js @@ -90,6 +90,15 @@ async function main() { const gremiosRes = await client.query("SELECT id, name FROM guilds"); const gremiosDB = gremiosRes.rows; + // ACTUALIZACIƓN DE ESTRUCTURA: Aseguramos que exista is_urgent + await client.query(` + DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='scraped_services' AND column_name='is_urgent') THEN + ALTER TABLE scraped_services ADD COLUMN is_urgent BOOLEAN DEFAULT FALSE; + END IF; + END $$; + `); + const res = await client.query("SELECT * FROM provider_credentials WHERE status = 'active'"); for (const cred of res.rows) { let password = Buffer.from(cred.password_hash, 'base64').toString('utf-8'); @@ -113,7 +122,7 @@ async function main() { } // ========================================== -// šŸ„ MULTIASISTENCIA (CON INTELIGENCIA) +// šŸ„ MULTIASISTENCIA (CON INTELIGENCIA Y PAGINACIƓN) // ========================================== async function runMultiasistencia(ownerId, user, pass, gremiosDB) { const browser = await chromium.launch({ headless: HEADLESS, args: ['--no-sandbox'] }); @@ -127,10 +136,48 @@ async function runMultiasistencia(ownerId, user, pass, gremiosDB) { await page.waitForTimeout(4000); await page.goto('https://web.multiasistencia.com/w3multi/frepasos_new.php?refresh=1'); await page.waitForTimeout(2000); - const expedientes = await page.evaluate(() => { - const links = Array.from(document.querySelectorAll('a[href*="reparacion="]')); - return Array.from(new Set(links.map(a => a.href.match(/reparacion=(\d+)/)?.[1]).filter(Boolean))); - }); + + // --- BUCLE DE PAGINACIƓN INTELIGENTE --- + let todosExpedientes = new Set(); + let paginaActual = 1; + + while (true) { + console.log(`šŸ“„ [Multi] Escaneando pĆ”gina ${paginaActual}...`); + + // Extraer expedientes de esta pĆ”gina + const expedientesPagina = await page.evaluate(() => { + const links = Array.from(document.querySelectorAll('a[href*="reparacion="]')); + return links.map(a => a.href.match(/reparacion=(\d+)/)?.[1]).filter(Boolean); + }); + + expedientesPagina.forEach(ref => todosExpedientes.add(ref)); + + // Buscar botón de siguiente pĆ”gina y hacer clic si existe + const clickedNext = await page.evaluate(() => { + const links = Array.from(document.querySelectorAll('a')); + const nextBtn = links.find(a => { + const txt = a.innerText.trim(); + const title = (a.title || "").toLowerCase(); + return txt === '>' || txt.toLowerCase() === 'siguiente' || title.includes('siguient') || a.querySelector('img[alt*="iguient"]'); + }); + + if (nextBtn) { + nextBtn.click(); + return true; + } + return false; + }); + + if (clickedNext) { + await page.waitForTimeout(3000); // Dar tiempo a que cargue la siguiente pĆ”gina + paginaActual++; + } else { + break; // Se acabaron las pĆ”ginas + } + } + + const expedientes = Array.from(todosExpedientes); + console.log(`āœ… [Multi] Total expedientes detectados: ${expedientes.length}`); // --- MEJORA: ARCHIVADO --- if (expedientes.length > 0) { @@ -310,24 +357,23 @@ async function syncAndArchive(ownerId, provider, currentWebRefs) { async function saveServiceToDB(ownerId, provider, ref, data) { console.log(`šŸ’¾ Guardando/Actualizando ${provider.toUpperCase()} ${ref}...`); - // Utilizamos el operador || de JSONB en Postgres para fusionar los datos. - // EXCLUDED.raw_data contiene lo nuevo del scraper. - // scraped_services.raw_data contiene lo que ya estaba (incluyendo assigned_to, etc). - // Al poner EXCLUDED primero y concatenar lo existente despuĆ©s, preservamos los campos internos - // que el scraper no conoce, y solo actualizamos lo que viene de fuera. + // CORRECCIƓN URGENCIA: Miramos en el JSON y convertimos a booleano real + const isUrgent = (data['Urgente'] && data['Urgente'].toLowerCase() === 'sĆ­') ? true : false; + // Al aƱadir is_urgent en la consulta, sincronizamos la columna fĆ­sica de la base de datos await pool.query(` - INSERT INTO scraped_services (owner_id, provider, service_ref, raw_data, status) - VALUES ($1, $2, $3, $4, 'pending') + INSERT INTO scraped_services (owner_id, provider, service_ref, raw_data, status, is_urgent) + VALUES ($1, $2, $3, $4, 'pending', $5) ON CONFLICT (owner_id, provider, service_ref) DO UPDATE SET raw_data = EXCLUDED.raw_data || scraped_services.raw_data, + is_urgent = EXCLUDED.is_urgent, status = CASE WHEN scraped_services.status = 'archived' THEN 'archived' WHEN scraped_services.status = 'imported' THEN 'imported' ELSE 'pending' END - `, [ownerId, provider, ref, JSON.stringify(data)]); + `, [ownerId, provider, ref, JSON.stringify(data), isUrgent]); } main(); \ No newline at end of file