141 lines
5.1 KiB
JavaScript
141 lines
5.1 KiB
JavaScript
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`);
|
|
|
|
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);
|
|
|
|
if (result.siteFailed) {
|
|
failedSites.push({
|
|
name: site.name,
|
|
url: site.url,
|
|
reason: result.failureReason,
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
processedCount.failed++;
|
|
} else {
|
|
processedCount.success++;
|
|
}
|
|
|
|
await new Promise(r => setTimeout(r, 1000));
|
|
}
|
|
|
|
console.log(`\n${'='.repeat(70)}`);
|
|
console.log(`Done: ${processedCount.success} success, ${processedCount.failed} failed`);
|
|
|
|
} 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();
|
|
}
|
|
|
|
if (failedSites.length > 0) {
|
|
const reportPath = path.join(__dirname, 'failed_sites.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 | WEBSITE | REASON\n';
|
|
reportContent += '-'.repeat(100) + '\n';
|
|
}
|
|
|
|
for (const site of failedSites) {
|
|
const website = `${site.name} (${site.url})`.substring(0, 32).padEnd(32);
|
|
reportContent += `${dateStr} | ${timeStr} | ${website} | ${site.reason}\n`;
|
|
}
|
|
|
|
fs.appendFileSync(reportPath, reportContent);
|
|
console.log(`${failedSites.length} failed. See: failed_sites.txt`);
|
|
}
|
|
}
|
|
}
|
|
|
|
main();
|