agentic-os/utility-agent/scraper.js

109 lines
5.5 KiB
JavaScript

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
const WHATSAPP_GATEWAY_URL = process.env.WHATSAPP_GATEWAY_URL || 'http://whatsapp-gateway.ai-agents.svc.cluster.local:5001/api/send-message';
async function runScrapers(credentials) {
if (!credentials.firstEnergy && !credentials.peoplesGas) {
console.log('[Scraper] No credentials configured. Skipping run.');
return;
}
let report = "⚡ *Daily Utility Usage Report*\n\n";
const browser = await puppeteer.launch({
headless: 'new',
executablePath: '/home/pptruser/.cache/puppeteer/chrome/linux-150.0.7871.24/chrome-linux64/chrome',
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-blink-features=AutomationControlled']
});
if (credentials.firstEnergy?.username && credentials.firstEnergy?.password) {
console.log('[Scraper] Scraping FirstEnergy...');
const page = await browser.newPage();
try {
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36');
// Use networkidle2 so we wait for any Javascript redirects or B2C login loads
await page.goto('https://www.firstenergycorp.com/content/customer/log_in.html', { waitUntil: 'networkidle2', timeout: 60000 });
// Try to extract the direct URL instead of clicking, which is much more reliable
await page.waitForSelector('a[href*="b2clogin.firstenergycorp.com"]', { timeout: 10000 }).catch(()=>null);
const b2cUrl = await page.evaluate(() => {
const loginBtn = document.querySelector('a[href*="b2clogin"]');
return loginBtn ? loginBtn.href : null;
});
if (b2cUrl) {
await page.goto(b2cUrl, { waitUntil: 'networkidle2', timeout: 60000 });
}
await page.waitForSelector('#signInName, input[name="signInName"], #username, input[name="username"]', { timeout: 30000 });
await page.type('#signInName, input[name="signInName"], #username, input[name="username"]', credentials.firstEnergy.username);
await page.type('#password, input[name="password"]', credentials.firstEnergy.password);
await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 60000 }).catch(()=>null),
page.click('#next, button[type="submit"]')
]);
console.log('[Scraper] Logged into FirstEnergy. Extracting usage...');
await page.waitForSelector('.usage-summary, .kwh-value', { timeout: 10000 });
const usage = await page.$eval('.kwh-value', el => el.innerText);
const cost = await page.$eval('.cost-value', el => el.innerText).catch(() => 'N/A');
report += `💡 *FirstEnergy*: ${usage.trim()} kWh used today (~${cost.trim()})\n`;
} catch (err) {
console.warn('[Scraper] FirstEnergy scraping failed:', err.message);
report += `💡 *FirstEnergy*: ❌ Error scraping data (${err.message})\n`;
} finally {
await page.close().catch(()=>null);
}
}
if (credentials.peoplesGas?.username && credentials.peoplesGas?.password) {
console.log('[Scraper] Scraping Peoples Gas...');
const page = await browser.newPage();
try {
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36');
await page.goto('https://peopleseaccount.com/Portal/default.aspx', { waitUntil: 'domcontentloaded', timeout: 60000 });
await page.waitForSelector('#txtLogin, input[name="txtLogin"]', { timeout: 30000 });
await page.type('#txtLogin, input[name="txtLogin"]', credentials.peoplesGas.username);
await page.type('#txtpwd, input[name="txtpwd"]', credentials.peoplesGas.password);
await Promise.all([
page.waitForNavigation({ waitUntil: 'domcontentloaded', timeout: 60000 }),
page.click('#btnlogin')
]);
console.log('[Scraper] Logged into Peoples Gas. Extracting usage...');
await page.waitForSelector('.ccf-usage', { timeout: 10000 });
const usage = await page.$eval('.ccf-usage', el => el.innerText);
const cost = await page.$eval('.ccf-cost', el => el.innerText).catch(() => 'N/A');
report += `🔥 *Peoples Gas*: ${usage.trim()} CCF used today (~${cost.trim()})\n`;
} catch (err) {
console.warn('[Scraper] Peoples Gas scraping failed:', err.message);
report += `🔥 *Peoples Gas*: ❌ Error scraping data (${err.message})\n`;
} finally {
await page.close().catch(()=>null);
}
}
report += `\n_Stats pulled automatically by Utility Agent_`;
console.log('[Scraper] Report generated, sending to WhatsApp...');
try {
await fetch(WHATSAPP_GATEWAY_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ to: 'default', message: report })
});
console.log('[Scraper] Report sent successfully.');
} catch (err) {
console.error('[Scraper] Failed to send WhatsApp message:', err);
}
await browser.close();
}
module.exports = { runScrapers };