'use strict'; const WS_URL = 'ws://127.0.0.1:18792/cdp'; const TOKEN = '0537d84a67f2e43b525964bb43d93f6dfae1ec1b50946455'; const TARGET_URL = 'https://diaonline.supermercadosdia.com.ar/medios-de-pago-y-promociones'; const WS = require('/usr/lib/node_modules/openclaw/node_modules/ws').WebSocket || require('/usr/lib/node_modules/openclaw/node_modules/ws'); const ws = new WS(WS_URL, { headers: { 'x-openclaw-relay-token': TOKEN } }); let _id = 1, sessionId = null, started = false; const cbs = new Map(); function send(method, params, cb) { const id = _id++; const m = { id, method, params: params || {} }; if (sessionId) m.sessionId = sessionId; if (cb) cbs.set(id, cb); ws.send(JSON.stringify(m)); } function evalJ(expr, cb) { send('Runtime.evaluate', { expression: '(function(){try{return JSON.stringify('+expr+');}catch(e){return "ERR:"+e.message;}})()' }, r => { if (!r || !r.result) { cb(null); return; } const raw = r.result.value; if (!raw || raw.startsWith('ERR:')) { console.error('evalJ err:', raw); cb(null); return; } try { cb(JSON.parse(raw)); } catch(e) { cb(raw); } }); } function evalS(expr, cb) { send('Runtime.evaluate', { expression: expr, returnByValue: true }, r => { cb(r && r.result && r.result.value); }); } ws.on('open', () => { send('Target.getTargets', {}, res => { const target = (res.targetInfos||[]).filter(t=>t.type==='page')[0]; console.log('Tab:', target&&target.url.slice(0,60)); send('Target.attachToTarget', { targetId: target.targetId, flatten: true }, r2 => { sessionId = r2.sessionId; send('Page.enable'); send('Page.navigate', { url: TARGET_URL }); }); }); }); ws.on('message', raw => { const msg = JSON.parse(raw); if (msg.id && cbs.has(msg.id)) { const cb=cbs.get(msg.id); cbs.delete(msg.id); cb(msg.result||{}); return; } if (!msg.method) return; if (msg.method === 'Page.frameNavigated') { const url = msg.params&&msg.params.frame&&msg.params.frame.url; if (url && url.includes('medios-de-pago') && !started) { started = true; console.log('Navigated to:', url); console.log('Waiting 7s for React render...'); setTimeout(phase1_extract, 7000); } } }); // ── Phase 1: extract card texts ──────────────────────────────────────────────── function phase1_extract() { evalJ(`(function(){ // Find Ver Legales buttons var btns = [].filter.call(document.querySelectorAll('*'), function(el){ return el.childElementCount===0 && /^ver legales$/i.test((el.textContent||'').trim()); }); // Walk up to find card container (first parent with >60 chars of text) function getCard(btn) { var node = btn.parentElement; for(var j=0;j<15&&node;j++){ var t=(node.innerText||'').trim(); if(t.length>60) return node; node=node.parentElement; } return btn.parentElement; } var cards = [].map.call(btns, function(btn,i){ var card = getCard(btn); var imgs = [].map.call(card.querySelectorAll('img'), function(img){ return {alt:img.alt, file:img.src.split('/').pop()}; }); return { i: i, text: (card.innerText||'').replace(/\s+/g,' ').trim().slice(0,400), imgs: imgs }; }); return {count:btns.length, cards:cards}; })`, data => { if (!data) { console.log('No data'); ws.close(); return; } console.log('\n=== DIA PROMOS:', data.count, '===\n'); (data.cards||[]).forEach(c => { console.log('['+c.i+'] '+c.text); if(c.imgs&&c.imgs.length) console.log(' imgs:', c.imgs.map(function(img){return img.alt+'('+img.file+')'}).join(', ')); console.log(); }); // Phase 2: get legal text for each card phase2_legals(0, data.count||0); }); } // ── Phase 2: click each Ver Legales and capture modal ───────────────────────── function phase2_legals(idx, total) { if (idx >= Math.min(total, 20)) { console.log('\nDone — all legals captured above.'); ws.close(); return; } // Snapshot body text BEFORE click evalS('document.body.innerText.length', beforeLen => { // Click button idx evalS(`(function(){ var btns=[].filter.call(document.querySelectorAll('*'),function(el){ return el.childElementCount===0&&/^ver legales$/i.test((el.textContent||'').trim()); }); if(!btns[${idx}]) return 'missing'; btns[${idx}].scrollIntoView({behavior:'instant',block:'center'}); btns[${idx}].click(); return 'ok'; })()`, clickRes => { console.log('['+idx+'] click:', clickRes); if (clickRes === 'missing') { phase2_legals(idx+1, total); return; } setTimeout(() => { // Look for modal: any fixed/absolute element that's visible and has legal-ish text evalJ(`(function(){ var all = document.querySelectorAll('*'); var modals = []; for(var i=0;i10 && t.length>50 && t.length<5000){ modals.push({tag:el.tagName, cls:el.className.toString().slice(0,60), z:z, text:t.slice(0,600)}); } } } modals.sort(function(a,b){return b.z-a.z;}); return modals.slice(0,3); })`, modals => { if (modals && modals.length) { console.log('['+idx+'] MODAL (z-index approach):'); modals.forEach(function(m){ console.log(' [z='+m.z+'] '+m.cls+': '+m.text.slice(0,300)); }); } else { // Fallback: look for any element with 'legal' anywhere in it evalJ(`(function(){ var bodyAfter=(document.body.innerText||'').length; // Find elements that might be the modal var els=[].filter.call(document.querySelectorAll('*'),function(el){ var t=(el.innerText||'').trim(); var cls=(el.className||'').toString().toLowerCase(); return el.offsetParent && t.length>80 && t.length<4000 && (cls.indexOf('legal')>=0||cls.indexOf('modal')>=0||cls.indexOf('dialog')>=0|| cls.indexOf('terms')>=0||cls.indexOf('bottom')>=0||cls.indexOf('sheet')>=0|| el.getAttribute('role')==='dialog'); }); return [].map.call(els.slice(0,3), function(el){ return {cls:(el.className||'').toString().slice(0,80), text:(el.innerText||'').replace(/\s+/g,' ').trim().slice(0,400)}; }); })`, fallback => { if (fallback && fallback.length) { console.log('['+idx+'] MODAL (class approach):'); fallback.forEach(function(f){ console.log(' '+f.cls+': '+f.text.slice(0,250)); }); } else { console.log('['+idx+'] no modal found'); } }); } // Close modal via Escape and continue evalS('document.dispatchEvent(new KeyboardEvent("keydown",{key:"Escape",bubbles:true,cancelable:true})); "esc"', () => { setTimeout(() => phase2_legals(idx+1, total), 800); }); }); }, 2200); }); }); } ws.on('error', e => console.error('WS error:', e.message)); ws.on('close', () => process.exit(0)); setTimeout(() => { console.log('TIMEOUT'); ws.close(); }, 150000);