#!/usr/bin/env node /** * Reonomy UI Explorer * * This script explores the Reonomy UI to understand: * - Login process * - Navigation structure * - Where lead data is located * - How to access property/owner information */ const puppeteer = require('puppeteer'); const { execSync } = require('child_process'); // Configuration - Use environment variables for credentials const REONOMY_EMAIL = process.env.REONOMY_EMAIL || 'henry@realestateenhanced.com'; const REONOMY_PASSWORD = process.env.REONOMY_PASSWORD || '9082166532'; // Google Sheets configuration const SHEET_TITLE = process.env.REONOMY_SHEET_TITLE || 'Reonomy Leads'; async function explore() { console.log('šŸ” Starting Reonomy UI exploration...'); const browser = await puppeteer.launch({ headless: process.env.HEADLESS === 'true' ? 'new' : false, // Show browser for debugging unless HEADLESS=true args: [ '--no-sandbox', '--disable-setuid-sandbox', '--window-size=1920,1080' ] }); const page = await browser.newPage(); // Set viewport await page.setViewport({ width: 1920, height: 1080 }); try { // Navigate to login page console.log('šŸ“ Navigating to login page...'); await page.goto('https://app.reonomy.com/#!/account', { waitUntil: 'networkidle2', timeout: 60000 }); // Wait for email input await page.waitForSelector('input[type="email"], input[placeholder*="example"]', { timeout: 10000 }); console.log('āœ… Login page loaded'); // Take screenshot await page.screenshot({ path: '/tmp/reonomy-01-login.png' }); // Fill email console.log('šŸ”‘ Entering credentials...'); await page.type('input[type="email"], input[placeholder*="example"]', REONOMY_EMAIL, { delay: 100 }); await page.type('input[type="password"], input[placeholder*="password"]', REONOMY_PASSWORD, { delay: 100 }); // Click login button - try multiple methods console.log('šŸ”˜ Looking for login button...'); // Method 1: Try type="submit" let loginButton = await page.$('button[type="submit"]'); if (loginButton) { await loginButton.click(); } else { // Method 2: Look for button with text "Log In" const buttons = await page.$$('button'); for (const btn of buttons) { const text = await btn.evaluate(e => e.innerText || e.textContent); if (text && text.includes('Log In')) { await btn.click(); break; } } } console.log('ā³ Waiting for login to complete...'); // Wait for navigation - check for dashboard await page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 30000 }).catch(() => { console.log('āš ļø No automatic navigation detected, checking current state...'); }); // Take screenshot after login await page.screenshot({ path: '/tmp/reonomy-02-after-login.png' }); // Check URL to see where we are const currentUrl = page.url(); console.log(`šŸ“ Current URL: ${currentUrl}`); // Wait a bit for any dynamic content await new Promise(resolve => setTimeout(resolve, 5000)); // Get page title const title = await page.title(); console.log(`šŸ“„ Page title: ${title}`); // Look for navigation elements console.log('\nšŸ”Ž Looking for navigation elements...'); // Common selectors for navigation const navSelectors = [ 'nav', '[role="navigation"]', '.navbar', '.nav', 'header nav', '.sidebar', '.menu', 'ul.menu', '[data-test="navigation"]', '[data-testid="navigation"]' ]; for (const selector of navSelectors) { const elements = await page.$$(selector); if (elements.length > 0) { console.log(` āœ… Found ${elements.length} elements with selector: ${selector}`); // Try to extract navigation text for (const el of elements) { try { const text = await el.evaluate(e => e.innerText); if (text && text.length < 500) { console.log(` Content: ${text.substring(0, 200)}...`); } } catch (err) { // Ignore errors } } } } // Look for common lead-related keywords in the page console.log('\nšŸ”Ž Scanning for lead-related content...'); const keywords = ['search', 'property', 'owner', 'leads', 'listings', 'buildings', 'properties']; const pageContent = await page.content(); for (const keyword of keywords) { const regex = new RegExp(keyword, 'gi'); const matches = pageContent.match(regex); if (matches && matches.length > 0) { console.log(` āœ… Found "${keyword}" (${matches.length} occurrences)`); } } // Look for data tables or lists console.log('\nšŸ”Ž Looking for data tables/lists...'); const tableSelectors = ['table', '[role="grid"]', '.table', '.data-table', '.list', '.results']; for (const selector of tableSelectors) { const elements = await page.$$(selector); if (elements.length > 0) { console.log(` āœ… Found ${elements.length} elements with selector: ${selector}`); } } // Try to find search functionality console.log('\nšŸ”Ž Looking for search functionality...'); const searchSelectors = [ 'input[type="search"]', 'input[placeholder*="search"]', 'input[placeholder*="Search"]', '.search-input', '[data-test="search"]', '[data-testid="search"]' ]; for (const selector of searchSelectors) { const elements = await page.$$(selector); if (elements.length > 0) { console.log(` āœ… Found ${elements.length} search inputs with selector: ${selector}`); } } // Save a screenshot of the final state await page.screenshot({ path: '/tmp/reonomy-03-exploration.png', fullPage: true }); console.log('\nāœ… Exploration complete!'); console.log('šŸ“ø Screenshots saved to /tmp/reonomy-*.png'); } catch (error) { console.error('āŒ Error during exploration:', error.message); await page.screenshot({ path: '/tmp/reonomy-error.png' }); } finally { console.log('\nšŸ”š Closing browser...'); await browser.close(); } } // Run exploration explore().catch(error => { console.error('Fatal error:', error); process.exit(1); });