v3.1.0 initial

This commit is contained in:
TheNetsky
2026-01-05 16:26:47 +01:00
parent a8ddb65b21
commit 576899f39d
37 changed files with 3391 additions and 865 deletions

View File

@@ -1,5 +1,4 @@
import rebrowser, { BrowserContext } from 'patchright'
import { newInjectedContext } from 'fingerprint-injector'
import { BrowserFingerprintWithHeaders, FingerprintGenerator } from 'fingerprint-generator'
@@ -7,7 +6,7 @@ import type { MicrosoftRewardsBot } from '../index'
import { loadSessionData, saveFingerprintData } from '../util/Load'
import { UserAgentManager } from './UserAgent'
import type { AccountProxy } from '../interface/Account'
import type { Account, AccountProxy } from '../interface/Account'
/* Test Stuff
https://abrahamjuliot.github.io/creepjs/
@@ -17,92 +16,110 @@ https://pixelscan.net/
https://www.browserscan.net/
*/
interface BrowserCreationResult {
context: BrowserContext
fingerprint: BrowserFingerprintWithHeaders
}
class Browser {
private bot: MicrosoftRewardsBot
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(
proxy: AccountProxy,
email: string
): Promise<{
context: BrowserContext
fingerprint: BrowserFingerprintWithHeaders
}> {
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,
...(proxy.url && {
proxy: { username: proxy.username, password: proxy.password, server: `${proxy.url}:${proxy.port}` }
}),
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'
]
...(proxyConfig && { proxy: proxyConfig }),
args: [...Browser.BROWSER_ARGS]
})
} catch (error) {
this.bot.logger.error(
this.bot.isMobile,
'BROWSER',
`Launch failed: ${error instanceof Error ? error.message : String(error)}`
)
const errorMessage = error instanceof Error ? error.message : String(error)
this.bot.logger.error(this.bot.isMobile, 'BROWSER', `Launch failed: ${errorMessage}`)
throw error
}
const sessionData = await loadSessionData(
this.bot.config.sessionPath,
email,
this.bot.config.saveFingerprint,
this.bot.isMobile
)
try {
const sessionData = await loadSessionData(
this.bot.config.sessionPath,
account.email,
account.saveFingerprint,
this.bot.isMobile
)
const fingerprint = sessionData.fingerprint
? sessionData.fingerprint
: await this.generateFingerprint(this.bot.isMobile)
const fingerprint = sessionData.fingerprint ?? (await this.generateFingerprint(this.bot.isMobile))
const context = await newInjectedContext(browser as any, { fingerprint: fingerprint })
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'))
}
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))
context.setDefaultTimeout(this.bot.utils.stringToNumber(this.bot.config?.globalTimeout ?? 30000))
await context.addCookies(sessionData.cookies)
await context.addCookies(sessionData.cookies)
if (this.bot.config.saveFingerprint) {
await saveFingerprintData(this.bot.config.sessionPath, email, this.bot.isMobile, fingerprint)
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
}
}
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: fingerprint
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}`
}
}