'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(); // Also capture network requests triggered by modal clicks const newRequests = []; let modalPhase = false; 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)); } ws.on('open', () => { send('Target.getTargets', {}, res => { const pages = (res.targetInfos || []).filter(t => t.type === 'page'); const target = pages[0]; console.log('Tab:', target?.url); send('Target.attachToTarget', { targetId: target.targetId, flatten: true }, r2 => { sessionId = r2.sessionId; send('Network.enable'); send('Page.enable'); send('Page.navigate', { url: TARGET_URL }, () => console.log('Navigating to DIA promos...')); }); }); }); 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; // Capture network requests during modal phase if (modalPhase && msg.method === 'Network.requestWillBeSent') { const url = msg.params.request.url; if (!url.includes('analytics') && !url.includes('gtm')) { newRequests.push({ url, method: msg.params.request.method }); console.log('[modal network]', msg.params.request.method, url.slice(0,100)); } } if (msg.method === 'Page.loadEventFired') { console.log('Page loaded — extracting DOM in 4s...'); setTimeout(extractPromos, 4000); } }); function extractPromos() { // Step 1: Extract all visible promo card content send('Runtime.evaluate', { expression: `(function() { // Try multiple selectors for promo cards const results = []; // Strategy 1: find elements containing % discount text const discountEls = [...document.querySelectorAll('*')] .filter(el => el.children.length === 0 && /\\d+%/.test(el.textContent) && el.textContent.length < 200); // Strategy 2: find section/article/div with promo structure const cards = [...document.querySelectorAll('[class*="promo"],[class*="card"],[class*="benefit"],[class*="bank"],[class*="descuento"],[class*="medio"],[class*="payment"]')] .filter(el => el.offsetParent !== null); // visible only // Strategy 3: find "Ver Legales" buttons and their parent containers const legalBtns = [...document.querySelectorAll('button,a,span')] .filter(el => /ver legal|ver m[aá]s|t[eé]rminos/i.test(el.textContent)); const cardData = []; legalBtns.forEach((btn, i) => { // Walk up to find the card container let container = btn.parentElement; for (let j = 0; j < 8 && container; j++) { const t = container.innerText || ''; if (t.length > 50 && t.length < 2000) { break; } container = container.parentElement; } if (container) { cardData.push({ idx: i, text: (container.innerText || '').replace(/\\s+/g, ' ').trim().slice(0, 500) }); } }); return { legalBtnCount: legalBtns.length, discountCount: discountEls.length, cardCount: cards.length, cardData: cardData.slice(0, 20), pageTitle: document.title, bodySnippet: document.body.innerText.slice(0, 3000) }; })()`, returnByValue: true }, res => { const val = res?.result?.value; if (!val) { console.log('No DOM data:', JSON.stringify(res).slice(0,200)); } else { console.log('\n=== DIA Promo DOM ==='); console.log('Page title:', val.pageTitle); console.log('Legal buttons found:', val.legalBtnCount); console.log('Discount elements:', val.discountCount); console.log('\n--- Card data (via legal button parents) ---'); val.cardData.forEach((c,i) => console.log(`[${i+1}] ${c.text}\n`)); console.log('\n--- Body text snippet ---'); console.log(val.bodySnippet); } // Step 2: click first legal button and capture modal clickFirstLegal(); }); } function clickFirstLegal() { console.log('\n--- Clicking first "Ver Legales" button ---'); modalPhase = true; send('Runtime.evaluate', { expression: `(function() { const btn = [...document.querySelectorAll('button,a,span,[role="button"]')] .find(el => /ver legal|ver m[aá]s|t[eé]rminos/i.test(el.textContent)); if (!btn) return 'no button found'; btn.click(); return 'clicked: ' + btn.textContent.trim().slice(0,40); })()`, returnByValue: true }, res => { console.log('Click result:', res?.result?.value); // Wait 2s for modal to open, then extract setTimeout(extractModal, 2000); }); } function extractModal() { send('Runtime.evaluate', { expression: `(function() { // Find modal/dialog/overlay const modal = document.querySelector('[role="dialog"],[class*="modal"],[class*="overlay"],[class*="drawer"],[class*="popup"],[class*="legal"],[class*="terms"]'); if (modal) return { found: true, text: modal.innerText.replace(/\\s+/g,' ').trim().slice(0,2000) }; // Fallback: find newly visible text blocks const visible = [...document.querySelectorAll('*')] .filter(el => el.children.length === 0 && el.offsetParent && el.textContent.trim().length > 100 && el.textContent.trim().length < 3000); const legalLike = visible.filter(el => /legal|t[eé]rmino|vigente|exclu|reint|cuota|pago/i.test(el.textContent)); return { found: false, legalLike: legalLike.slice(0,5).map(el => el.textContent.trim().slice(0,300)) }; })()`, returnByValue: true }, res => { const val = res?.result?.value; console.log('\n=== Modal content ==='); if (val?.found) { console.log(val.text); } else { console.log('No modal found. Legal-like text blocks:'); (val?.legalLike || []).forEach((t,i) => console.log(`[${i+1}] ${t}\n`)); } ws.close(); }); } ws.on('error', e => console.error('WS error:', e.message)); ws.on('close', () => process.exit(0)); setTimeout(() => { console.log('Timeout'); ws.close(); }, 45000);