const { chromium } = require('/Users/jakeshore/ClawdBot/node_modules/playwright'); (async () => { const browser = await chromium.launch({ headless: false }); const context = await browser.newContext(); const page = await context.newPage(); console.log('Navigating to Reonomy...'); await page.goto('https://app.reonomy.com'); // Wait for login form await page.waitForSelector('input[placeholder="yours@example.com"]', { timeout: 10000 }); console.log('Filling in credentials...'); await page.fill('input[placeholder="yours@example.com"]', 'henry@realestateenhanced.com'); await page.fill('input[placeholder="your password"]', '9082166532'); console.log('Clicking login...'); await page.click('button:has-text("Log In")'); // Wait for navigation await page.waitForLoadState('networkidle', { timeout: 15000 }); console.log('Current URL:', page.url()); // Try to navigate to a property detail page directly const propertyIds = [ '710c31f7-5021-5494-b43e-92f03882759b', '89ad58c3-39c7-5ecb-8a30-58ec6c28fc1a' ]; for (const propId of propertyIds) { console.log(`\n\n=== Analyzing property: ${propId} ===`); const propertyUrl = `https://app.reonomy.com/#!/property/${propId}`; console.log(`Navigating to: ${propertyUrl}`); await page.goto(propertyUrl); await page.waitForLoadState('networkidle', { timeout: 15000 }); await page.waitForTimeout(3000); // Extra wait for dynamic content // Save screenshot const screenshotPath = `/Users/jakeshore/.clawdbot/workspace/property-${propId}.png`; await page.screenshot({ path: screenshotPath, fullPage: true }); console.log('Screenshot saved:', screenshotPath); // Extract page HTML structure for analysis console.log('\n=== SEARCHING FOR EMAIL/PHONE ELEMENTS ===\n'); // Search for specific patterns const patterns = await page.evaluate(() => { const results = []; // Look for elements with text matching email pattern const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/; const phoneRegex = /\(?(\d{3})\)?[-.\s]?(\d{3})[-.\s]?(\d{4})/; // Check all elements const allElements = document.querySelectorAll('*'); allElements.forEach(el => { const text = el.textContent?.trim() || ''; const href = el.getAttribute('href') || ''; // Check if this element contains an email if (emailRegex.test(text) || href.startsWith('mailto:')) { results.push({ type: 'email', tag: el.tagName, class: el.className, id: el.id, text: text.substring(0, 100), href: href.substring(0, 100), html: el.outerHTML.substring(0, 300), parentClass: el.parentElement?.className || '', parentTag: el.parentElement?.tagName || '', selectors: [ el.id ? `#${el.id}` : null, el.className ? `.${el.className.split(' ')[0]}` : null, `${el.tagName.toLowerCase()}[class*="${el.className.split(' ')[0] || ''}"]`, ].filter(Boolean) }); } // Check if this element contains a phone if (phoneRegex.test(text) || href.startsWith('tel:')) { results.push({ type: 'phone', tag: el.tagName, class: el.className, id: el.id, text: text.substring(0, 100), href: href.substring(0, 100), html: el.outerHTML.substring(0, 300), parentClass: el.parentElement?.className || '', parentTag: el.parentElement?.tagName || '', selectors: [ el.id ? `#${el.id}` : null, el.className ? `.${el.className.split(' ')[0]}` : null, `${el.tagName.toLowerCase()}[class*="${el.className.split(' ')[0] || ''}"]`, ].filter(Boolean) }); } }); return results; }); // Print results if (patterns.length === 0) { console.log('No email/phone elements found with regex pattern matching.'); console.log('\n=== LOOKING FOR "EMAIL" AND "PHONE" LABELS ===\n'); const labeledElements = await page.evaluate(() => { const results = []; const allElements = document.querySelectorAll('*'); allElements.forEach(el => { const text = el.textContent?.trim() || ''; const lowerText = text.toLowerCase(); // Look for elements that might be labels if (lowerText === 'email' || lowerText === 'e-mail' || lowerText === 'phone' || lowerText === 'telephone' || lowerText === 'tel') { // Check the next sibling or children for the actual value const nextSibling = el.nextElementSibling; const children = el.parentElement?.querySelectorAll(el.tagName === 'SPAN' ? '*' : `${el.tagName} + *`); results.push({ labelText: text, labelClass: el.className, labelId: el.id, nextSiblingText: nextSibling?.textContent?.trim()?.substring(0, 100) || '', nextSiblingClass: nextSibling?.className || '', nextSiblingTag: nextSibling?.tagName || '', parentHTML: el.parentElement?.outerHTML?.substring(0, 500) || '' }); } }); return results; }); console.log('Labeled elements:', JSON.stringify(labeledElements, null, 2)); } else { console.log(`Found ${patterns.length} potential email/phone elements:\n`); // Group by type const emails = patterns.filter(p => p.type === 'email'); const phones = patterns.filter(p => p.type === 'phone'); console.log('EMAIL ELEMENTS:'); emails.slice(0, 5).forEach((item, i) => { console.log(`\n${i + 1}. Tag: ${item.tag}`); console.log(` Class: ${item.class}`); console.log(` ID: ${item.id}`); console.log(` Text: ${item.text}`); console.log(` Parent Tag: ${item.parentTag}`); console.log(` Parent Class: ${item.parentClass}`); console.log(` Suggested Selectors:`); item.selectors.forEach(sel => console.log(` - ${sel}`)); }); console.log('\n\nPHONE ELEMENTS:'); phones.slice(0, 5).forEach((item, i) => { console.log(`\n${i + 1}. Tag: ${item.tag}`); console.log(` Class: ${item.class}`); console.log(` ID: ${item.id}`); console.log(` Text: ${item.text}`); console.log(` Parent Tag: ${item.parentTag}`); console.log(` Parent Class: ${item.parentClass}`); console.log(` Suggested Selectors:`); item.selectors.forEach(sel => console.log(` - ${sel}`)); }); } // Also check for data-* attributes console.log('\n\n=== CHECKING FOR DATA-* ATTRIBUTES ===\n'); const dataAttributes = await page.evaluate(() => { const results = []; const allElements = document.querySelectorAll('*'); allElements.forEach(el => { // Check all data attributes Array.from(el.attributes).forEach(attr => { if (attr.name.startsWith('data-')) { const name = attr.name.toLowerCase(); if (name.includes('email') || name.includes('phone') || name.includes('contact') || name.includes('mail') || name.includes('tel')) { results.push({ attribute: attr.name, value: attr.value, tag: el.tagName, class: el.className, text: el.textContent?.trim()?.substring(0, 50) || '' }); } } }); }); return results; }); if (dataAttributes.length > 0) { console.log(`Found ${dataAttributes.length} elements with relevant data attributes:\n`); dataAttributes.forEach((item, i) => { console.log(`${i + 1}. ${item.attribute}="${item.value}"`); console.log(` Tag: ${item.tag}, Class: ${item.class}`); console.log(` Text: ${item.text}\n`); }); } else { console.log('No data attributes found containing email/phone/contact keywords.'); } // Save detailed analysis to JSON const analysis = { propertyId: propId, url: propertyUrl, emailPhoneElements: patterns, labeledElements: [], dataAttributes: dataAttributes }; const fs = require('fs'); fs.writeFileSync( `/Users/jakeshore/.clawdbot/workspace/property-${propId}-analysis.json`, JSON.stringify(analysis, null, 2) ); console.log(`\nAnalysis saved to: property-${propId}-analysis.json`); } console.log('\n\n=== DONE ==='); console.log('Keeping browser open for 60 seconds for manual inspection...'); await page.waitForTimeout(60000); await browser.close(); console.log('Browser closed.'); })();