const fs = require('fs'); const path = require('path'); const puppeteer = require('puppeteer-extra'); const StealthPlugin = require('puppeteer-extra-plugin-stealth'); puppeteer.use(StealthPlugin()); const { loadConfig, loadSitesFromFile } = require('./src/config'); const { processSite } = require('./src/processor'); const { createCLI, parseCLI } = require('./src/cli'); async function main() { const cliOptions = parseCLI(); if (cliOptions.help) { createCLI().help(); return; } const config = loadConfig(); let sitesToProcess = config.sites || []; if (cliOptions.file) { console.log(`Loading sites from: ${cliOptions.file}`); sitesToProcess = loadSitesFromFile(cliOptions.file); console.log(`Loaded ${sitesToProcess.length} sites from file`); } const logFile = cliOptions.log ? path.join(__dirname, `run_${new Date().toISOString().replace(/[:.]/g, '-')}.log`) : null; if (cliOptions.target) { sitesToProcess = sitesToProcess.filter(site => site.name.toLowerCase().includes(cliOptions.target.toLowerCase()) || site.url.toLowerCase().includes(cliOptions.target.toLowerCase()) ); if (sitesToProcess.length === 0) { console.error(`No site found matching "${cliOptions.target}"`); return; } console.log(`Targeting ${sitesToProcess.length} site(s)`); } if (cliOptions.keepOpen) { console.log('Keep-open mode: Tabs will stay open for verification'); } const browserConfig = config.browser || {}; const globalCreds = config.global_credentials || {}; const userDataDir = browserConfig.userDataDir; if (!userDataDir) { console.error('userDataDir not set in config.toml'); return; } if (cliOptions.log && logFile) { const originalLog = console.log; const originalError = console.error; const originalWarn = console.warn; const writeToLog = (type, args) => { const message = args.map(arg => typeof arg === 'string' ? arg : JSON.stringify(arg)).join(' '); fs.appendFileSync(logFile, `[${new Date().toISOString()}] [${type}] ${message}\n`); }; console.log = (...args) => { writeToLog('LOG', args); originalLog.apply(console, args); }; console.error = (...args) => { writeToLog('ERROR', args); originalError.apply(console, args); }; console.warn = (...args) => { writeToLog('WARN', args); originalWarn.apply(console, args); }; console.log(`Logging to: ${logFile}`); } const failedSites = []; const processedCount = { success: 0, failed: 0 }; const browser = await puppeteer.launch({ headless: false, userDataDir: userDataDir, args: ['--start-maximized', '--no-sandbox', '--disable-setuid-sandbox'] }); try { console.log(`\nProcessing ${sitesToProcess.length} sites...\n`); const allResults = []; for (let i = 0; i < sitesToProcess.length; i++) { const site = sitesToProcess[i]; console.log(`[${i + 1}/${sitesToProcess.length}]`); const result = await processSite(browser, site, globalCreds, browserConfig, cliOptions.keepOpen, cliOptions.dryRun); const siteResult = { name: site.name, url: site.url, success: !result.siteFailed, reason: result.failureReason || 'Success', timestamp: new Date().toISOString() }; allResults.push(siteResult); if (result.siteFailed) { failedSites.push(siteResult); processedCount.failed++; } else { processedCount.success++; } // Write results after each site const reportPath = path.join(__dirname, 'site_results.txt'); const now = new Date(); const dateStr = now.toLocaleDateString('en-GB'); const timeStr = now.toLocaleTimeString('en-GB'); let reportContent = ''; if (!fs.existsSync(reportPath)) { reportContent = 'DATE | TIME | STATUS | WEBSITE | RESULT\n'; reportContent += '-'.repeat(110) + '\n'; } const website = `${site.name} (${site.url})`.substring(0, 32).padEnd(32); const status = siteResult.success ? 'SUCCESS' : 'FAILED'; reportContent += `${dateStr} | ${timeStr} | ${status} | ${website} | ${siteResult.reason}\n`; fs.appendFileSync(reportPath, reportContent); console.log(` -> Result written to site_results.txt`); await new Promise(r => setTimeout(r, 1000)); } console.log(`\n${'='.repeat(70)}`); console.log(`Done: ${processedCount.success} success, ${processedCount.failed} failed`); console.log(`Full results: site_results.txt`); } catch(error) { console.error('Fatal error:', error.message); } finally { if (cliOptions.keepOpen) { console.log(`\nBrowser kept open for verification`); console.log(` Close browser manually when done`); } else { await browser.close(); } } } main();