mirror of
https://github.com/TheNetsky/Microsoft-Rewards-Script.git
synced 2026-01-11 19:06:18 +00:00
168 lines
5.6 KiB
JavaScript
168 lines
5.6 KiB
JavaScript
import fs from 'fs'
|
|
import { chromium } from 'patchright'
|
|
import { newInjectedContext } from 'fingerprint-injector'
|
|
import {
|
|
getDirname,
|
|
getProjectRoot,
|
|
log,
|
|
parseArgs,
|
|
validateEmail,
|
|
loadConfig,
|
|
loadAccounts,
|
|
findAccountByEmail,
|
|
getRuntimeBase,
|
|
getSessionPath,
|
|
loadCookies,
|
|
loadFingerprint,
|
|
buildProxyConfig,
|
|
setupCleanupHandlers
|
|
} from '../utils.js'
|
|
|
|
const __dirname = getDirname(import.meta.url)
|
|
const projectRoot = getProjectRoot(__dirname)
|
|
|
|
const args = parseArgs()
|
|
args.dev = args.dev || false
|
|
|
|
validateEmail(args.email)
|
|
|
|
const { data: config } = loadConfig(projectRoot, args.dev)
|
|
const { data: accounts } = loadAccounts(projectRoot, args.dev)
|
|
|
|
const account = findAccountByEmail(accounts, args.email)
|
|
if (!account) {
|
|
log('ERROR', `Account not found: ${args.email}`)
|
|
log('ERROR', 'Available accounts:')
|
|
accounts.forEach(acc => {
|
|
if (acc?.email) log('ERROR', ` - ${acc.email}`)
|
|
})
|
|
process.exit(1)
|
|
}
|
|
|
|
async function main() {
|
|
const runtimeBase = getRuntimeBase(projectRoot, args.dev)
|
|
const sessionBase = getSessionPath(runtimeBase, config.sessionPath, args.email)
|
|
|
|
log('INFO', 'Validating session data...')
|
|
|
|
if (!fs.existsSync(sessionBase)) {
|
|
log('ERROR', `Session directory does not exist: ${sessionBase}`)
|
|
log('ERROR', 'Please ensure the session has been created for this account')
|
|
process.exit(1)
|
|
}
|
|
|
|
if (!config.baseURL) {
|
|
log('ERROR', 'baseURL is not set in config.json')
|
|
process.exit(1)
|
|
}
|
|
|
|
let cookies = await loadCookies(sessionBase, 'desktop')
|
|
let sessionType = 'desktop'
|
|
|
|
if (cookies.length === 0) {
|
|
log('WARN', 'No desktop session cookies found, trying mobile session...')
|
|
cookies = await loadCookies(sessionBase, 'mobile')
|
|
sessionType = 'mobile'
|
|
|
|
if (cookies.length === 0) {
|
|
log('ERROR', 'No cookies found in desktop or mobile session')
|
|
log('ERROR', `Session directory: ${sessionBase}`)
|
|
log('ERROR', 'Please ensure a valid session exists for this account')
|
|
process.exit(1)
|
|
}
|
|
|
|
log('INFO', `Using mobile session (${cookies.length} cookies)`)
|
|
}
|
|
|
|
const isMobile = sessionType === 'mobile'
|
|
const fingerprintEnabled = isMobile ? account.saveFingerprint?.mobile : account.saveFingerprint?.desktop
|
|
|
|
let fingerprint = null
|
|
if (fingerprintEnabled) {
|
|
fingerprint = await loadFingerprint(sessionBase, sessionType)
|
|
if (!fingerprint) {
|
|
log('ERROR', `Fingerprint is enabled for ${sessionType} but fingerprint file not found`)
|
|
log('ERROR', `Expected file: ${sessionBase}/session_fingerprint_${sessionType}.json`)
|
|
log('ERROR', 'Cannot start browser without fingerprint when it is explicitly enabled')
|
|
process.exit(1)
|
|
}
|
|
log('INFO', `Loaded ${sessionType} fingerprint`)
|
|
}
|
|
|
|
const proxy = buildProxyConfig(account)
|
|
|
|
if (account.proxy && account.proxy.url && (!proxy || !proxy.server)) {
|
|
log('ERROR', 'Proxy is configured in account but proxy data is invalid or incomplete')
|
|
log('ERROR', 'Account proxy config:', JSON.stringify(account.proxy, null, 2))
|
|
log('ERROR', 'Required fields: proxy.url, proxy.port')
|
|
log('ERROR', 'Cannot start browser without proxy when it is explicitly configured')
|
|
process.exit(1)
|
|
}
|
|
|
|
const userAgent = fingerprint?.fingerprint?.navigator?.userAgent || fingerprint?.fingerprint?.userAgent || null
|
|
|
|
log('INFO', `Session: ${args.email} (${sessionType})`)
|
|
log('INFO', ` Cookies: ${cookies.length}`)
|
|
log('INFO', ` Fingerprint: ${fingerprint ? 'Yes' : 'No'}`)
|
|
log('INFO', ` User-Agent: ${userAgent || 'Default'}`)
|
|
log('INFO', ` Proxy: ${proxy ? 'Yes' : 'No'}`)
|
|
log('INFO', 'Launching browser...')
|
|
|
|
const browser = await chromium.launch({
|
|
headless: false,
|
|
...(proxy ? { proxy } : {}),
|
|
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'
|
|
]
|
|
})
|
|
|
|
let context
|
|
if (fingerprint) {
|
|
context = await newInjectedContext(browser, { fingerprint })
|
|
|
|
await context.addInitScript(() => {
|
|
Object.defineProperty(navigator, 'credentials', {
|
|
value: {
|
|
create: () => Promise.reject(new Error('WebAuthn disabled')),
|
|
get: () => Promise.reject(new Error('WebAuthn disabled'))
|
|
}
|
|
})
|
|
})
|
|
|
|
log('SUCCESS', 'Fingerprint injected into browser context')
|
|
} else {
|
|
context = await browser.newContext({
|
|
viewport: isMobile ? { width: 375, height: 667 } : { width: 1366, height: 768 }
|
|
})
|
|
}
|
|
|
|
if (cookies.length) {
|
|
await context.addCookies(cookies)
|
|
log('INFO', `Added ${cookies.length} cookies to context`)
|
|
}
|
|
|
|
const page = await context.newPage()
|
|
await page.goto(config.baseURL, { waitUntil: 'domcontentloaded' })
|
|
|
|
log('SUCCESS', 'Browser opened with session loaded')
|
|
log('INFO', `Navigated to: ${config.baseURL}`)
|
|
|
|
setupCleanupHandlers(async () => {
|
|
if (browser?.isConnected?.()) {
|
|
await browser.close()
|
|
}
|
|
})
|
|
}
|
|
|
|
main() |