Files
Microsoft-Rewards-Script/src/browser/Browser.ts
2026-01-05 16:26:47 +01:00

141 lines
5.1 KiB
TypeScript

import rebrowser, { BrowserContext } from 'patchright'
import { newInjectedContext } from 'fingerprint-injector'
import { BrowserFingerprintWithHeaders, FingerprintGenerator } from 'fingerprint-generator'
import type { MicrosoftRewardsBot } from '../index'
import { loadSessionData, saveFingerprintData } from '../util/Load'
import { UserAgentManager } from './UserAgent'
import type { Account, AccountProxy } from '../interface/Account'
/* Test Stuff
https://abrahamjuliot.github.io/creepjs/
https://botcheck.luminati.io/
https://fv.pro/
https://pixelscan.net/
https://www.browserscan.net/
*/
interface BrowserCreationResult {
context: BrowserContext
fingerprint: BrowserFingerprintWithHeaders
}
class Browser {
private readonly bot: MicrosoftRewardsBot
private static readonly BROWSER_ARGS = [
'--no-sandbox',
'--mute-audio',
'--disable-setuid-sandbox',
'--ignore-certificate-errors',
'--ignore-certificate-errors-spki-list',
'--ignore-ssl-errors',
'--no-first-run',
'--no-default-browser-check',
'--disable-user-media-security=true',
'--disable-blink-features=Attestation',
'--disable-features=WebAuthentication,PasswordManagerOnboarding,PasswordManager,EnablePasswordsAccountStorage,Passkeys',
'--disable-save-password-bubble'
] as const
constructor(bot: MicrosoftRewardsBot) {
this.bot = bot
}
async createBrowser(account: Account): Promise<BrowserCreationResult> {
let browser: rebrowser.Browser
try {
const proxyConfig = account.proxy.url
? {
server: this.formatProxyServer(account.proxy),
...(account.proxy.username &&
account.proxy.password && {
username: account.proxy.username,
password: account.proxy.password
})
}
: undefined
browser = await rebrowser.chromium.launch({
headless: this.bot.config.headless,
...(proxyConfig && { proxy: proxyConfig }),
args: [...Browser.BROWSER_ARGS]
})
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error)
this.bot.logger.error(this.bot.isMobile, 'BROWSER', `Launch failed: ${errorMessage}`)
throw error
}
try {
const sessionData = await loadSessionData(
this.bot.config.sessionPath,
account.email,
account.saveFingerprint,
this.bot.isMobile
)
const fingerprint = sessionData.fingerprint ?? (await this.generateFingerprint(this.bot.isMobile))
const context = await newInjectedContext(browser as any, { fingerprint })
await context.addInitScript(() => {
Object.defineProperty(navigator, 'credentials', {
value: {
create: () => Promise.reject(new Error('WebAuthn disabled')),
get: () => Promise.reject(new Error('WebAuthn disabled'))
}
})
})
context.setDefaultTimeout(this.bot.utils.stringToNumber(this.bot.config?.globalTimeout ?? 30000))
await context.addCookies(sessionData.cookies)
if (
(account.saveFingerprint.mobile && this.bot.isMobile) ||
(account.saveFingerprint.desktop && !this.bot.isMobile)
) {
await saveFingerprintData(this.bot.config.sessionPath, account.email, this.bot.isMobile, fingerprint)
}
this.bot.logger.info(
this.bot.isMobile,
'BROWSER',
`Created browser with User-Agent: "${fingerprint.fingerprint.navigator.userAgent}"`
)
this.bot.logger.debug(this.bot.isMobile, 'BROWSER-FINGERPRINT', JSON.stringify(fingerprint))
return { context: context as unknown as BrowserContext, fingerprint }
} catch (error) {
await browser.close().catch(() => {})
throw error
}
}
private formatProxyServer(proxy: AccountProxy): string {
try {
const urlObj = new URL(proxy.url)
const protocol = urlObj.protocol.replace(':', '')
return `${protocol}://${urlObj.hostname}:${proxy.port}`
} catch {
return `${proxy.url}:${proxy.port}`
}
}
async generateFingerprint(isMobile: boolean) {
const fingerPrintData = new FingerprintGenerator().getFingerprint({
devices: isMobile ? ['mobile'] : ['desktop'],
operatingSystems: isMobile ? ['android', 'ios'] : ['windows', 'linux'],
browsers: [{ name: 'edge' }]
})
const userAgentManager = new UserAgentManager(this.bot)
const updatedFingerPrintData = await userAgentManager.updateFingerprintUserAgent(fingerPrintData, isMobile)
return updatedFingerPrintData
}
}
export default Browser