// const puppeteer = require("puppeteer-core"); // Uncomment if using puppeteer-core const { connect } = require("puppeteer-real-browser"); async function createBrowser(retry = 0) { try { // If a browser instance already exists, or if we're finished, return. // global.finished should be set to true when the application is shutting down. if (global.finished) return; // If global.browser is not null, it means we already have a connected browser. // This prevents launching multiple browsers if one is already active. if (global.browser) { console.log("Browser is already connected."); return; } console.log("Launching new browser instance..."); /* If using puppeteer-core: const browser = await puppeteer.launch({ headless: false, args: ["--no-sandbox", "--disable-gpu"], }); */ const { browser: _browser } = await connect({ headless: false, turnstile: true, connectOption: { defaultViewport: null }, disableXvfb: false, }); // Store the new browser instance globally global.browser = _browser; // Set up a listener for when the browser disconnects browser.on("disconnected", async () => { if (global.finished) return; // If the app is shutting down, don't try to restart console.log("Browser disconnected. Attempting to restart browser..."); global.browser = null; // Clear the disconnected instance // Recursively call createBrowser to launch a new instance await createBrowser(); }); console.log("Browser launched successfully and ready for use."); } catch (e) { console.error("Error launching browser:", e.stack); // Only retry if the application is not finished and retry attempts are within limit if (global.finished || retry >= 5) { console.error("Max retries reached or application is shutting down. Could not launch browser."); global.browser = null; // Ensure the instance is null if launch failed return; } console.log(`Retrying browser launch (${retry + 1}/5)...`); await new Promise((resolve) => setTimeout(resolve, 3000)); await createBrowser(retry + 1); } } // Immediately call createBrowser when this module is required to ensure a browser is available from start createBrowser(); // Optionally, export the createBrowser function if you need to manually trigger it from elsewhere module.exports = createBrowser; // Add a graceful shutdown handler process.on('SIGINT', async () => { console.log('SIGINT signal received. Shutting down...'); global.finished = true; // Signal that the application is shutting down if (global.browser) { console.log('Closing browser...'); await global.browser.close().catch(e => console.error("Error closing browser:", e)); } process.exit(0); }); process.on('SIGTERM', async () => { console.log('SIGTERM signal received. Shutting down...'); global.finished = true; // Signal that the application is shutting down if (global.browser) { console.log('Closing browser...'); await global.browser.close().catch(e => console.error("Error closing browser:", e)); } process.exit(0); });