feat: refactor browser configuration handling and update validation logic

This commit is contained in:
2025-11-04 22:43:09 +01:00
parent 2255845dbe
commit 4c3a57a508
4 changed files with 29 additions and 20 deletions

View File

@@ -27,19 +27,16 @@ class Browser {
let browser: import('rebrowser-playwright').Browser let browser: import('rebrowser-playwright').Browser
try { try {
const envForceHeadless = process.env.FORCE_HEADLESS === '1' const envForceHeadless = process.env.FORCE_HEADLESS === '1'
const legacyHeadless = (this.bot.config as { headless?: boolean }).headless let headless = envForceHeadless ? true : (this.bot.config.browser?.headless ?? false)
const nestedHeadless = (this.bot.config.browser as { headless?: boolean } | undefined)?.headless
let headlessValue = envForceHeadless ? true : (legacyHeadless ?? nestedHeadless ?? false)
if (this.bot.isBuyModeEnabled() && !envForceHeadless) { if (this.bot.isBuyModeEnabled() && !envForceHeadless) {
if (headlessValue !== false) { if (headless !== false) {
const target = this.bot.getBuyModeTarget() const target = this.bot.getBuyModeTarget()
this.bot.log(this.bot.isMobile, 'BROWSER', `Buy mode: forcing headless=false${target ? ` for ${target}` : ''}`, 'warn') 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' const engineName = 'chromium'
this.bot.log(this.bot.isMobile, 'BROWSER', `Launching ${engineName} (headless=${headless})`) this.bot.log(this.bot.isMobile, 'BROWSER', `Launching ${engineName} (headless=${headless})`)
const proxyConfig = this.buildPlaywrightProxy(proxy) const proxyConfig = this.buildPlaywrightProxy(proxy)
@@ -89,10 +86,8 @@ class Browser {
const fingerprint = sessionData.fingerprint ? sessionData.fingerprint : await this.generateFingerprint() const fingerprint = sessionData.fingerprint ? sessionData.fingerprint : await this.generateFingerprint()
const context = await newInjectedContext(browser as unknown as import('playwright').Browser, { fingerprint: fingerprint }) const context = await newInjectedContext(browser as unknown as import('playwright').Browser, { fingerprint: fingerprint })
const legacyTimeout = (this.bot.config as { globalTimeout?: number | string }).globalTimeout const globalTimeout = this.bot.config.browser?.globalTimeout ?? 30000
const nestedTimeout = (this.bot.config.browser as { globalTimeout?: number | string } | undefined)?.globalTimeout context.setDefaultTimeout(typeof globalTimeout === 'number' ? globalTimeout : this.bot.utils.stringToMs(globalTimeout))
const globalTimeout = legacyTimeout ?? nestedTimeout ?? 30000
context.setDefaultTimeout(this.bot.utils.stringToMs(globalTimeout))
try { try {
context.on('page', async (page) => { context.on('page', async (page) => {

View File

@@ -1,7 +1,6 @@
export interface Config { export interface Config {
baseURL: string; baseURL: string;
sessionPath: string; sessionPath: string;
headless: boolean;
browser?: ConfigBrowser; // Optional nested browser config browser?: ConfigBrowser; // Optional nested browser config
fingerprinting?: ConfigFingerprinting; // Optional nested fingerprinting config fingerprinting?: ConfigFingerprinting; // Optional nested fingerprinting config
parallel: boolean; parallel: boolean;

View File

@@ -4,7 +4,10 @@ import fs from 'fs'
import path from 'path' import path from 'path'
import { Account } from '../interface/Account' 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 configCache: Config
let configSourcePath = '' let configSourcePath = ''
@@ -72,9 +75,21 @@ function normalizeConfig(raw: unknown): Config {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const n = (raw || {}) as any const n = (raw || {}) as any
// Browser / execution // Browser settings
const headless = n.browser?.headless ?? n.headless ?? false const browserConfig = n.browser ?? {}
const globalTimeout = n.browser?.globalTimeout ?? n.globalTimeout ?? '30s' 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 parallel = n.execution?.parallel ?? n.parallel ?? false
const runOnZeroPoints = n.execution?.runOnZeroPoints ?? n.runOnZeroPoints ?? false const runOnZeroPoints = n.execution?.runOnZeroPoints ?? n.runOnZeroPoints ?? false
const clusters = n.execution?.clusters ?? n.clusters ?? 1 const clusters = n.execution?.clusters ?? n.clusters ?? 1
@@ -197,7 +212,7 @@ function normalizeConfig(raw: unknown): Config {
const cfg: Config = { const cfg: Config = {
baseURL: n.baseURL ?? 'https://rewards.bing.com', baseURL: n.baseURL ?? 'https://rewards.bing.com',
sessionPath: n.sessionPath ?? 'sessions', sessionPath: n.sessionPath ?? 'sessions',
headless, browser,
parallel, parallel,
runOnZeroPoints, runOnZeroPoints,
clusters, clusters,

View File

@@ -197,10 +197,10 @@ export class StartupValidator {
} }
// Headless mode in Docker // 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( this.addWarning(
'config', '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.' 'Docker environment forces headless mode. Your config setting will be overridden.'
) )
} }
@@ -358,10 +358,10 @@ export class StartupValidator {
private validateBrowserSettings(config: Config): void { private validateBrowserSettings(config: Config): void {
// Headless validation - only warn in Docker/containerized environments // 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( this.addWarning(
'browser', '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.', 'Docker environment forces headless mode. Your config setting will be overridden.',
'docs/docker.md' 'docs/docker.md'
) )