- Switched from Puppeteer to Playwright
- Fixed mobile searches not working
- Added fingerprint saving in config
- Added mobile search retry in config
This commit is contained in:
TheNetsky
2024-01-07 16:33:48 +01:00
parent f3fb641ecd
commit 9ea7f5c452
19 changed files with 199 additions and 142 deletions

View File

@@ -1,9 +1,11 @@
import puppeteer from 'puppeteer'
import { FingerprintInjector } from 'fingerprint-injector'
import playwright from 'playwright'
import { BrowserContext } from 'playwright'
import { newInjectedContext } from 'fingerprint-injector'
import { FingerprintGenerator } from 'fingerprint-generator'
import { MicrosoftRewardsBot } from '../index'
import { loadSesion } from '../util/Load'
import { loadSessionData, saveFingerprintData } from '../util/Load'
import { AccountProxy } from '../interface/Account'
@@ -13,63 +15,54 @@ https://botcheck.luminati.io/
http://f.vision/
*/
class Browser {
private bot: MicrosoftRewardsBot
private usedUserAgents: string[] = []
constructor(bot: MicrosoftRewardsBot) {
this.bot = bot
}
async createBrowser(email: string, proxy: AccountProxy) {
// const userAgent = await getUserAgent(isMobile)
const browser = await puppeteer.launch({
headless: this.bot.config.headless ? 'new' : false,
userDataDir: await loadSesion(this.bot.config.sessionPath, email),
async createBrowser(proxy: AccountProxy, email: string): Promise<BrowserContext> {
const browser = await playwright.chromium.launch({
//channel: 'msedge', // Uses Edge instead of chrome
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',
proxy.url ? `--proxy-server=${proxy.url}:${proxy.port}` : ''
'--ignore-ssl-errors'
]
})
let fingerPrintData = new FingerprintGenerator().getFingerprint({
const sessionData = await loadSessionData(this.bot.config.sessionPath, email, this.bot.isMobile, this.bot.config.saveFingerprint)
const fingerpint = sessionData.fingerprint ? sessionData.fingerprint : this.generateFingerprint()
const context = await newInjectedContext(browser, { fingerprint: fingerpint })
await context.addCookies(sessionData.cookies)
if (this.bot.config.saveFingerprint) {
await saveFingerprintData(this.bot.config.sessionPath, email, this.bot.isMobile, fingerpint)
}
this.bot.log('BROWSER', `Created browser with User-Agent: "${fingerpint.fingerprint.navigator.userAgent}"`)
return context
}
generateFingerprint() {
const fingerPrintData = new FingerprintGenerator().getFingerprint({
devices: this.bot.isMobile ? ['mobile'] : ['desktop'],
operatingSystems: this.bot.isMobile ? ['android'] : ['windows'],
browsers: ['edge']
})
if (this.usedUserAgents) {
while (this.usedUserAgents.includes(fingerPrintData.fingerprint.navigator.userAgent)) {
fingerPrintData = new FingerprintGenerator().getFingerprint({
devices: this.bot.isMobile ? ['mobile'] : ['desktop'],
operatingSystems: this.bot.isMobile ? ['android'] : ['windows'],
browsers: ['edge']
})
}
}
this.usedUserAgents.push(fingerPrintData.fingerprint.navigator.userAgent)
// Modify the newPage function to attach the fingerprint
const originalNewPage = browser.newPage
browser.newPage = async function () {
const page = await originalNewPage.apply(browser)
await new FingerprintInjector().attachFingerprintToPuppeteer(page, fingerPrintData)
return page
}
this.bot.log('BROWSER', `Created browser with User-Agent: "${fingerPrintData.fingerprint.navigator.userAgent}"`)
return browser
return fingerPrintData
}
}
export default Browser
export default Browser

View File

@@ -1,4 +1,4 @@
import { Page } from 'puppeteer'
import { Page } from 'playwright'
import { CheerioAPI, load } from 'cheerio'
import { MicrosoftRewardsBot } from '../index'
@@ -17,7 +17,7 @@ export default class BrowserFunc {
/**
* Navigate the provided page to rewards homepage
* @param {Page} page Puppeteer page
* @param {Page} page Playwright page
*/
async goHome(page: Page) {
@@ -37,7 +37,7 @@ export default class BrowserFunc {
await this.bot.browser.utils.tryDismissCookieBanner(page)
// Check if account is suspended
const isSuspended = await page.waitForSelector('#suspendedAccountHeader', { visible: true, timeout: 2000 }).then(() => true).catch(() => false)
const isSuspended = await page.waitForSelector('#suspendedAccountHeader', { state: 'visible', timeout: 2000 }).then(() => true).catch(() => false)
if (isSuspended) {
this.bot.log('GO-HOME', 'This account is suspended!', 'error')
throw new Error('Account has been suspended!')
@@ -89,7 +89,7 @@ export default class BrowserFunc {
}
// Reload the page to get new data
await this.bot.homePage.reload({ waitUntil: 'networkidle2' })
await this.bot.homePage.reload({ waitUntil: 'domcontentloaded' })
const scriptContent = await this.bot.homePage.evaluate(() => {
const scripts = Array.from(document.querySelectorAll('script'))
@@ -180,7 +180,7 @@ export default class BrowserFunc {
/**
* Parse quiz data from provided page
* @param {Page} page Puppeteer page
* @param {Page} page Playwright page
* @returns {QuizData} Quiz data object
*/
async getQuizData(page: Page): Promise<QuizData> {
@@ -214,7 +214,7 @@ export default class BrowserFunc {
async waitForQuizRefresh(page: Page): Promise<boolean> {
try {
await page.waitForSelector('span.rqMCredits', { visible: true, timeout: 10_000 })
await page.waitForSelector('span.rqMCredits', { state: 'visible', timeout: 10_000 })
await this.bot.utils.wait(2000)
return true
@@ -226,7 +226,7 @@ export default class BrowserFunc {
async checkQuizCompleted(page: Page): Promise<boolean> {
try {
await page.waitForSelector('#quizCompleteContainer', { visible: true, timeout: 2000 })
await page.waitForSelector('#quizCompleteContainer', { state: 'visible', timeout: 2000 })
await this.bot.utils.wait(2000)
return true

View File

@@ -1,4 +1,4 @@
import { Page } from 'puppeteer'
import { Page } from 'playwright'
import { MicrosoftRewardsBot } from '../index'
@@ -24,7 +24,7 @@ export default class BrowserUtil {
for (const button of buttons) {
try {
const element = await page.waitForSelector(button.selector, { visible: true, timeout: 1000 })
const element = await page.waitForSelector(button.selector, { state: 'visible', timeout: 1000 })
if (element) {
await element.click()
result = true
@@ -73,8 +73,8 @@ export default class BrowserUtil {
try {
await this.bot.utils.wait(500)
const browser = page.browser()
const pages = await browser.pages()
const browser = page.context()
const pages = browser.pages()
const newTab = pages[pages.length - 1]
if (newTab) {
@@ -89,8 +89,8 @@ export default class BrowserUtil {
async getTabs(page: Page) {
try {
const browser = page.browser()
const pages = await browser.pages()
const browser = page.context()
const pages = browser.pages()
const homeTab = pages[1]
let homeTabURL: URL