'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; let sessionId = null; const callbacks = new Map(); const bodyWaiters = new Map(); // requestId → resolve const postRequests = {}; // requestId → { body, postBody } function send(method, params = {}, cb) { const id = _id++; const msg = { id, method, params }; if (sessionId) msg.sessionId = sessionId; if (cb) callbacks.set(id, cb); ws.send(JSON.stringify(msg)); return id; } ws.on('open', () => { send('Target.getTargets', {}, res => { const target = (res.targetInfos || []).filter(t => t.type === 'page')[0]; console.log('Tab:', target?.url); send('Target.attachToTarget', { targetId: target.targetId, flatten: true }, r2 => { sessionId = r2.sessionId; send('Network.enable', { maxPostDataSize: 65536 }); // capture POST bodies send('Page.enable'); send('Page.navigate', { url: TARGET_URL }, () => console.log('Navigating...')); }); }); }); ws.on('message', raw => { const msg = JSON.parse(raw); if (msg.id && callbacks.has(msg.id)) { const cb = callbacks.get(msg.id); callbacks.delete(msg.id); cb(msg.result || {}, msg.error); return; } if (!msg.method) return; if (msg.method === 'Network.requestWillBeSent') { const { requestId, request } = msg.params; const url = request.url; if (url.includes('graphql') && request.method === 'POST') { postRequests[requestId] = { url, postBody: request.postData || '' }; } } if (msg.method === 'Network.responseReceived') { const { requestId, response } = msg.params; if (postRequests[requestId]) { postRequests[requestId].status = response.status; // Schedule body fetch setTimeout(() => { send('Network.getResponseBody', { requestId }, res => { if (res.body) { const text = res.base64Encoded ? Buffer.from(res.body, 'base64').toString() : res.body; postRequests[requestId].responseBody = text; const r = postRequests[requestId]; console.log('\n[POST graphql] url:', r.url.slice(0,80)); console.log(' request body:', String(r.postBody).slice(0, 300)); console.log(' response:', text.slice(0, 500)); } }); }, 100); } } if (msg.method === 'Page.loadEventFired') { console.log('Page loaded — waiting 4s then clicking Ver Legales on each card...'); setTimeout(clickAllLegals, 4000); } }); function clickAllLegals() { // First extract full promo card data from DOM send('Runtime.evaluate', { expression: `(function() { // Get bank/card names from img alt text within each card const legalBtns = [...document.querySelectorAll('button,a,span,[role="button"]')] .filter(el => /ver legal/i.test(el.textContent)); const cards = legalBtns.map((btn, i) => { let container = btn; // Walk up to find the outermost card container (but stop before page) for (let j = 0; j < 10; j++) { const p = container.parentElement; if (!p || p.tagName === 'MAIN' || p.tagName === 'BODY') break; const t = p.innerText || ''; if (t.includes('Ver Legales') && t.length < 1500) { container = p; } else break; } // Get bank images const imgs = [...container.querySelectorAll('img')].map(img => ({ alt: img.alt, src: img.src.replace(/.*\//,'') })); // Get day filter tags const texto = container.innerText.replace(/\\s+/g,' ').trim(); return { idx: i, texto, imgs }; }); return { count: cards.length, cards }; })()`, returnByValue: true }, res => { const val = res?.result?.value; console.log('\n=== FULL PROMO CARDS:', val?.count, '==='); (val?.cards || []).forEach((c, i) => { console.log(`\n[${i+1}] ${c.texto}`); if (c.imgs?.length) console.log(' imgs:', c.imgs.map(img=>`${img.alt}(${img.src})`).join(', ')); }); // Now click them one by one to get legals console.log('\n--- Clicking each Ver Legales to capture legal text ---'); clickLegal(0, val?.count || 0); }); } function clickLegal(idx, total) { if (idx >= Math.min(total, 16)) { console.log('\nDone.'); ws.close(); return; } send('Runtime.evaluate', { expression: `(function() { const btns = [...document.querySelectorAll('button,a,span,[role="button"]')] .filter(el => /ver legal/i.test(el.textContent)); if (!btns[${idx}]) return 'no btn'; btns[${idx}].click(); return 'clicked btn ${idx}: ' + btns[${idx}].textContent.trim(); })()`, returnByValue: true }, res => { console.log(` [${idx}] click:`, res?.result?.value); // Wait for modal + network, then extract modal text setTimeout(() => { send('Runtime.evaluate', { expression: `(function() { const modal = document.querySelector('[role="dialog"],[class*="modal"],[class*="legal"],[class*="terms"],[class*="drawer"]'); if (modal && modal.offsetParent) { const closeBtn = modal.querySelector('button,[aria-label*="close"],[aria-label*="cerrar"]'); const text = modal.innerText.replace(/\\s+/g,' ').trim(); if (closeBtn) closeBtn.click(); return { found: true, text }; } return { found: false }; })()`, returnByValue: true }, mres => { const modal = mres?.result?.value; if (modal?.found) { console.log(` [${idx}] LEGAL TEXT: ${modal.text.slice(0,400)}`); } setTimeout(() => clickLegal(idx + 1, total), 800); }); }, 1500); }); } ws.on('error', e => console.error('WS error:', e.message)); ws.on('close', () => process.exit(0)); setTimeout(() => { console.log('Timeout'); ws.close(); }, 90000);