'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(); // msgId → callback const reqInfo = new Map(); // requestId → {url, status} const captured = []; // {url, status, body} 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; } function getBody(requestId, url, status) { send('Network.getResponseBody', { requestId }, res => { if (res.error) return; const raw = res.body || ''; const text = res.base64Encoded ? Buffer.from(raw, 'base64').toString('utf8') : raw; if (text.length < 20) return; const lower = text.toLowerCase(); const kws = ['descuento','promo','banco','tarjeta','reintegro','cuota','legal','bancari','oferta','medio']; const hits = kws.filter(w => lower.includes(w)).length; captured.push({ url, status, hits, len: text.length, text }); }); } ws.on('open', () => { console.log('Connected'); send('Target.getTargets', {}, res => { const pages = (res.targetInfos || []).filter(t => t.type === 'page'); console.log('Tabs:', pages.map(p => `[${p.targetId.slice(-6)}] ${p.url.slice(0,60)}`).join('\n ')); const target = pages[0]; if (!target) { console.error('No page target'); ws.close(); return; } send('Target.attachToTarget', { targetId: target.targetId, flatten: true }, res2 => { sessionId = res2.sessionId; console.log('Attached session:', sessionId); send('Network.enable'); send('Page.enable'); send('Page.navigate', { url: TARGET_URL }, nav => { console.log('Navigating... frameId:', nav.frameId); }); }); }); }); ws.on('message', raw => { const msg = JSON.parse(raw); // Route callbacks 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; reqInfo.set(requestId, { url: request.url, method: request.method }); } if (msg.method === 'Network.responseReceived') { const { requestId, response } = msg.params; const req = reqInfo.get(requestId); if (!req) return; const ct = response.headers?.['content-type'] || response.headers?.['Content-Type'] || ''; const url = req.url; // Skip noise const skip = ['analytics','gtm','hotjar','amplitude','segment','.css','.png','.jpg', '.svg','.woff','vtexassets','vteximg','cloudfront','newrelic']; if (skip.some(s => url.includes(s))) return; // Capture JSON, graphql, and /api/ responses if (ct.includes('json') || url.includes('graphql') || url.includes('/api/')) { getBody(requestId, url, response.status); } } if (msg.method === 'Page.loadEventFired') { console.log('Page loaded — waiting 8s for async data + modals...'); setTimeout(() => { // Click all "ver legales" / "ver más" buttons to trigger modal API calls send('Runtime.evaluate', { expression: `(function(){ const btns = [...document.querySelectorAll('button,a,span,[role="button"]')] .filter(el => /legal|ver m[aá]s|terminos|t[eé]rminos/i.test(el.textContent)); btns.slice(0,5).forEach(b => { try { b.click(); } catch(e){} }); return btns.length + ' buttons: ' + btns.slice(0,5).map(b=>b.textContent.trim().slice(0,40)).join(' || '); })()`, returnByValue: true }, res => console.log('[click result]', res?.result?.value)); setTimeout(dump, 5000); }, 8000); } }); function dump() { console.log('\n=== CAPTURED', captured.length, 'JSON responses ==='); const sorted = captured.sort((a,b) => b.hits - a.hits); sorted.slice(0, 15).forEach((c, i) => { console.log(`\n[${i+1}] hits=${c.hits} status=${c.status} len=${c.len}`); console.log(' URL:', c.url.slice(0, 120)); console.log(' BODY:', c.text.slice(0, 600)); }); // Also show any URLs with 'promo' or 'banco' or 'legal' in URL const byUrl = captured.filter(c => /promo|banco|legal|medio|descuento/i.test(c.url)); if (byUrl.length) { console.log('\n=== URLs with promo/banco/legal keywords ==='); byUrl.forEach(c => console.log(' ', c.url)); } ws.close(); } ws.on('error', e => console.error('WS error:', e.message)); ws.on('close', () => process.exit(0)); setTimeout(() => { console.log('Timeout — dumping'); dump(); }, 30000);