From 4c3a57a508cb54baf9a4aafa057612c244477837 Mon Sep 17 00:00:00 2001 From: LightZirconite Date: Tue, 4 Nov 2025 22:43:09 +0100 Subject: [PATCH] feat: refactor browser configuration handling and update validation logic --- src/browser/Browser.ts | 15 +++++---------- src/interface/Config.ts | 1 - src/util/Load.ts | 25 ++++++++++++++++++++----- src/util/StartupValidator.ts | 8 ++++---- 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/browser/Browser.ts b/src/browser/Browser.ts index 2109ec8..47f9233 100644 --- a/src/browser/Browser.ts +++ b/src/browser/Browser.ts @@ -27,19 +27,16 @@ class Browser { let browser: import('rebrowser-playwright').Browser try { const envForceHeadless = process.env.FORCE_HEADLESS === '1' - const legacyHeadless = (this.bot.config as { headless?: boolean }).headless - const nestedHeadless = (this.bot.config.browser as { headless?: boolean } | undefined)?.headless - let headlessValue = envForceHeadless ? true : (legacyHeadless ?? nestedHeadless ?? false) + let headless = envForceHeadless ? true : (this.bot.config.browser?.headless ?? false) if (this.bot.isBuyModeEnabled() && !envForceHeadless) { - if (headlessValue !== false) { + if (headless !== false) { const target = this.bot.getBuyModeTarget() this.bot.log(this.bot.isMobile, 'BROWSER', `Buy mode: forcing headless=false${target ? ` for ${target}` : ''}`, 'warn') } - headlessValue = false + headless = false } - const headless: boolean = Boolean(headlessValue) const engineName = 'chromium' this.bot.log(this.bot.isMobile, 'BROWSER', `Launching ${engineName} (headless=${headless})`) const proxyConfig = this.buildPlaywrightProxy(proxy) @@ -89,10 +86,8 @@ class Browser { const fingerprint = sessionData.fingerprint ? sessionData.fingerprint : await this.generateFingerprint() const context = await newInjectedContext(browser as unknown as import('playwright').Browser, { fingerprint: fingerprint }) - const legacyTimeout = (this.bot.config as { globalTimeout?: number | string }).globalTimeout - const nestedTimeout = (this.bot.config.browser as { globalTimeout?: number | string } | undefined)?.globalTimeout - const globalTimeout = legacyTimeout ?? nestedTimeout ?? 30000 - context.setDefaultTimeout(this.bot.utils.stringToMs(globalTimeout)) + const globalTimeout = this.bot.config.browser?.globalTimeout ?? 30000 + context.setDefaultTimeout(typeof globalTimeout === 'number' ? globalTimeout : this.bot.utils.stringToMs(globalTimeout)) try { context.on('page', async (page) => { diff --git a/src/interface/Config.ts b/src/interface/Config.ts index 903d86b..ceb3f26 100644 --- a/src/interface/Config.ts +++ b/src/interface/Config.ts @@ -1,7 +1,6 @@ export interface Config { baseURL: string; sessionPath: string; - headless: boolean; browser?: ConfigBrowser; // Optional nested browser config fingerprinting?: ConfigFingerprinting; // Optional nested fingerprinting config parallel: boolean; diff --git a/src/util/Load.ts b/src/util/Load.ts index 6303d5e..1ab9cb9 100644 --- a/src/util/Load.ts +++ b/src/util/Load.ts @@ -4,7 +4,10 @@ import fs from 'fs' import path from 'path' import { Account } from '../interface/Account' -import { Config, ConfigSaveFingerprint } from '../interface/Config' +import { Config, ConfigSaveFingerprint, ConfigBrowser } from '../interface/Config' +import { Util } from './Utils' + +const utils = new Util() let configCache: Config let configSourcePath = '' @@ -72,9 +75,21 @@ function normalizeConfig(raw: unknown): Config { // eslint-disable-next-line @typescript-eslint/no-explicit-any const n = (raw || {}) as any - // Browser / execution - const headless = n.browser?.headless ?? n.headless ?? false - const globalTimeout = n.browser?.globalTimeout ?? n.globalTimeout ?? '30s' + // Browser settings + const browserConfig = n.browser ?? {} + const headless = process.env.FORCE_HEADLESS === '1' + ? true + : (typeof browserConfig.headless === 'boolean' + ? browserConfig.headless + : (typeof n.headless === 'boolean' ? n.headless : false)) // Legacy fallback + + const globalTimeout = browserConfig.globalTimeout ?? n.globalTimeout ?? '30s' + const browser: ConfigBrowser = { + headless, + globalTimeout: utils.stringToMs(globalTimeout) + } + + // Execution const parallel = n.execution?.parallel ?? n.parallel ?? false const runOnZeroPoints = n.execution?.runOnZeroPoints ?? n.runOnZeroPoints ?? false const clusters = n.execution?.clusters ?? n.clusters ?? 1 @@ -197,7 +212,7 @@ function normalizeConfig(raw: unknown): Config { const cfg: Config = { baseURL: n.baseURL ?? 'https://rewards.bing.com', sessionPath: n.sessionPath ?? 'sessions', - headless, + browser, parallel, runOnZeroPoints, clusters, diff --git a/src/util/StartupValidator.ts b/src/util/StartupValidator.ts index d77842e..72471ef 100644 --- a/src/util/StartupValidator.ts +++ b/src/util/StartupValidator.ts @@ -197,10 +197,10 @@ export class StartupValidator { } // Headless mode in Docker - if (process.env.FORCE_HEADLESS === '1' && config.headless === false) { + if (process.env.FORCE_HEADLESS === '1' && config.browser?.headless === false) { this.addWarning( 'config', - 'FORCE_HEADLESS=1 but config.headless is false', + 'FORCE_HEADLESS=1 but config.browser.headless is false', 'Docker environment forces headless mode. Your config setting will be overridden.' ) } @@ -358,10 +358,10 @@ export class StartupValidator { private validateBrowserSettings(config: Config): void { // Headless validation - only warn in Docker/containerized environments - if (!config.headless && process.env.FORCE_HEADLESS === '1') { + if (!config.browser?.headless && process.env.FORCE_HEADLESS === '1') { this.addWarning( 'browser', - 'FORCE_HEADLESS=1 but config.headless is false', + 'FORCE_HEADLESS=1 but config.browser.headless is false', 'Docker environment forces headless mode. Your config setting will be overridden.', 'docs/docker.md' )