From f629e676dae59eb1dd08fce6466d3dda52783fb1 Mon Sep 17 00:00:00 2001 From: Luis Antonio Date: Mon, 22 Dec 2025 14:18:00 +0000 Subject: [PATCH 1/4] Playwright headless_shell error fix [discord](https://ptb.discord.com/channels/1418201715009912866/1452445559897194639) --- src/flows/DesktopFlow.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/flows/DesktopFlow.ts b/src/flows/DesktopFlow.ts index e5b7ee0..b920920 100644 --- a/src/flows/DesktopFlow.ts +++ b/src/flows/DesktopFlow.ts @@ -53,7 +53,7 @@ export class DesktopFlow { this.bot.log(false, 'DESKTOP-FLOW', 'Starting desktop automation flow') // IMPROVED: Use centralized browser factory to eliminate duplication - const browser = await createBrowserInstance(this.bot, account.proxy, account.email) + let browser = await createBrowserInstance(this.bot, account.proxy, account.email) let keepBrowserOpen = false @@ -63,7 +63,23 @@ export class DesktopFlow { this.bot.log(false, 'DESKTOP-FLOW', 'Browser started successfully') // Login into MS Rewards, then optionally stop if compromised - await this.bot.login.login(this.bot.homePage, account.email, account.password, account.totp) + try { + await this.bot.login.login(this.bot.homePage, account.email, account.password, account.totp) + } catch (loginErr) { + const msg = loginErr instanceof Error ? loginErr.message : String(loginErr) + if (msg.includes('Target page, context or browser has been closed')) { + this.bot.log(false, 'DESKTOP-FLOW', 'Browser/context closed during login. Attempting one retry with a fresh browser context', 'warn') + // Ensure previous browser/context is closed gracefully + await closeBrowserSafely(this.bot, browser, account.email, false) + + // Create a fresh browser context and retry login once + browser = await createBrowserInstance(this.bot, account.proxy, account.email) + this.bot.homePage = await browser.newPage() + await this.bot.login.login(this.bot.homePage, account.email, account.password, account.totp) + } else { + throw loginErr + } + } if (this.bot.compromisedModeActive) { const reason = this.bot.compromisedReason || 'security-issue' From ef72ae23bd6d50ac0e857f6c9c4a6fe62eba0184 Mon Sep 17 00:00:00 2001 From: Luis Antonio Date: Mon, 22 Dec 2025 14:34:40 +0000 Subject: [PATCH 2/4] fixed mobile and desktop flows --- src/flows/MobileFlow.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/flows/MobileFlow.ts b/src/flows/MobileFlow.ts index d935aa9..b388a64 100644 --- a/src/flows/MobileFlow.ts +++ b/src/flows/MobileFlow.ts @@ -59,7 +59,7 @@ export class MobileFlow { this.bot.log(true, 'MOBILE-FLOW', 'Starting mobile automation flow') // IMPROVED: Use centralized browser factory to eliminate duplication - const browser = await createBrowserInstance(this.bot, account.proxy, account.email) + let browser = await createBrowserInstance(this.bot, account.proxy, account.email) let keepBrowserOpen = false let browserClosed = false @@ -70,7 +70,23 @@ export class MobileFlow { this.bot.log(true, 'MOBILE-FLOW', 'Browser started successfully') // Login into MS Rewards, then respect compromised mode - await this.bot.login.login(this.bot.homePage, account.email, account.password, account.totp) + try { + await this.bot.login.login(this.bot.homePage, account.email, account.password, account.totp) + } catch (loginErr) { + const msg = loginErr instanceof Error ? loginErr.message : String(loginErr) + if (msg.includes('Target page, context or browser has been closed')) { + this.bot.log(true, 'MOBILE-FLOW', 'Browser/context closed during login. Attempting one retry with a fresh browser context', 'warn') + // Ensure previous browser/context is closed gracefully + await closeBrowserSafely(this.bot, browser, account.email, true) + + // Create a fresh browser context and retry login once + browser = await createBrowserInstance(this.bot, account.proxy, account.email) + this.bot.homePage = await browser.newPage() + await this.bot.login.login(this.bot.homePage, account.email, account.password, account.totp) + } else { + throw loginErr + } + } if (this.bot.compromisedModeActive) { const reason = this.bot.compromisedReason || 'security-issue' From c80ea13877d9680c64dd53422a043ad566955da8 Mon Sep 17 00:00:00 2001 From: Luis Antonio Date: Mon, 22 Dec 2025 14:54:42 +0000 Subject: [PATCH 3/4] Added specific arguments for Linux and Windows machines --- .gitignore | 1 + src/browser/Browser.ts | 27 +++++++++++++++++++++------ src/config.jsonc | 2 +- src/functions/Login.ts | 7 ++++++- 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index ef0935e..e08d662 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ accounts.main.jsonc .update-extract/ .update-happened .update-restart-count +src/config.jsonc diff --git a/src/browser/Browser.ts b/src/browser/Browser.ts index 59ae042..0d281a7 100644 --- a/src/browser/Browser.ts +++ b/src/browser/Browser.ts @@ -94,24 +94,39 @@ class Browser { '--no-first-run', '--no-default-browser-check', '--no-zygote', - '--single-process', // ANTI-DETECTION: Make WebDriver undetectable '--enable-features=NetworkService,NetworkServiceInProcess' ] - // Linux stability fixes - const linuxStabilityArgs = isLinux ? [ + // Platform-specific stability fixes + // CRITICAL: --single-process is unstable on Windows and causes context closure + const platformStabilityArgs = isLinux ? [ + '--single-process', // Safe on Linux with proper memory management '--disable-dev-shm-usage', '--disable-software-rasterizer', '--disable-http-cache', '--disk-cache-size=1' - ] : [] + ] : [ + // Windows-specific stability (avoid --single-process which crashes Chromium context) + '--disable-background-networking', + '--disable-preconnect', + '--disable-web-resources', + '--disable-component-extensions-with-background-pages', + '--disable-translate', + '--disable-sync-on-cellular', + '--disable-device-discovery-notifications', + '--disable-default-language', + '--disable-print-preview' + ] + + // CRITICAL: Windows needs longer timeout (120s) due to slower context initialization + const launchTimeout = isLinux ? 90000 : 120000 browser = await playwright.chromium.launch({ headless, ...(proxyConfig && { proxy: proxyConfig }), - args: [...baseArgs, ...linuxStabilityArgs], - timeout: isLinux ? 90000 : 60000 + args: [...baseArgs, ...platformStabilityArgs], + timeout: launchTimeout }) } catch (e: unknown) { const msg = (e instanceof Error ? e.message : String(e)) diff --git a/src/config.jsonc b/src/config.jsonc index 948c125..a626620 100644 --- a/src/config.jsonc +++ b/src/config.jsonc @@ -88,7 +88,7 @@ }, // === BROWSER === "browser": { - "headless": false, + "headless": true, "globalTimeout": "30s" }, "fingerprinting": { diff --git a/src/functions/Login.ts b/src/functions/Login.ts index ed7babc..a6c4130 100644 --- a/src/functions/Login.ts +++ b/src/functions/Login.ts @@ -46,6 +46,7 @@ const DEFAULT_TIMEOUTS = { rewardsPortalCheck: 8000, navigationTimeout: 30000, navigationTimeoutLinux: 60000, + navigationTimeoutWindows: 90000, // Windows is slower at initializing contexts (issue: context closure) bingVerificationMaxIterations: 10, bingVerificationMaxIterationsMobile: 8 } as const @@ -121,7 +122,11 @@ export class Login { maxAttempts = 3 ): Promise<{ success: boolean; recoveryUsed: boolean }> { const isLinux = process.platform === 'linux' - const navigationTimeout = isLinux ? DEFAULT_TIMEOUTS.navigationTimeoutLinux : DEFAULT_TIMEOUTS.navigationTimeout + const isWindows = process.platform === 'win32' + // CRITICAL FIX: Windows needs 90s timeout to avoid "Target page, context or browser has been closed" + const navigationTimeout = isWindows ? DEFAULT_TIMEOUTS.navigationTimeoutWindows : + isLinux ? DEFAULT_TIMEOUTS.navigationTimeoutLinux : + DEFAULT_TIMEOUTS.navigationTimeout let navigationSucceeded = false let recoveryUsed = false From 3d973f2e3b6ab2df821437c7e9549d882222c42f Mon Sep 17 00:00:00 2001 From: Luis Antonio Date: Mon, 22 Dec 2025 12:02:59 -0300 Subject: [PATCH 4/4] Remove src/config.jsonc from .gitignore That was an specific config leftover from testings Signed-off-by: Luis Antonio --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index e08d662..ef0935e 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,3 @@ accounts.main.jsonc .update-extract/ .update-happened .update-restart-count -src/config.jsonc