Skip to content

Commit

Permalink
Pre 1.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
TheNetsky committed Nov 23, 2023
1 parent 1d6167a commit 28286ff
Show file tree
Hide file tree
Showing 14 changed files with 285 additions and 203 deletions.
20 changes: 0 additions & 20 deletions .vscode/launch.json

This file was deleted.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Under development, however mainly for personal use!
- [x] Completing Click Rewards
- [x] Completing Polls
- [x] Completing Punchcards
- [ ] Solving This Or That Quiz
- [x] Solving This Or That Quiz (Random)
- [x] Clicking Promotional Items
- [x] Solving ABC Quiz
- [ ] Completing Shopping Game
Expand Down
13 changes: 6 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,16 @@
"license": "ISC",
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^6.7.0",
"eslint": "^8.54.0",
"eslint-plugin-modules-newline": "^0.0.6",
"typescript": "^5.2.2"
},
"dependencies": {
"axios": "^1.5.1",
"axios": "^1.6.1",
"cheerio": "^1.0.0-rc.12",
"eslint": "^8.49.0",
"eslint-plugin-modules-newline": "^0.0.6",
"fingerprint-generator": "^2.1.42",
"fingerprint-injector": "^2.1.42",
"puppeteer": "^21.4.1",
"puppeteer-extra": "^3.3.6",
"fingerprint-generator": "^2.1.43",
"fingerprint-injector": "^2.1.43",
"puppeteer": "^21.2.1",
"ts-node": "^10.9.1"
}
}
15 changes: 8 additions & 7 deletions src/browser/Browser.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import puppeteer from 'puppeteer-extra'
import puppeteer from 'puppeteer'
import { FingerprintInjector } from 'fingerprint-injector'
import { FingerprintGenerator } from 'fingerprint-generator'

import { MicrosoftRewardsBot } from '../index'
import { loadSesion } from '../util/Load'

import { AccountProxy } from '../interface/Account'

Expand All @@ -20,12 +21,12 @@ class Browser {
this.bot = bot
}

async createBrowser(email: string, proxy: AccountProxy, isMobile: boolean) {
// const userAgent = await getUserAgent(isMobile)
async createBrowser(email: string, proxy: AccountProxy) {
// const userAgent = await getUserAgent(isMobile)

const browser = await puppeteer.launch({
headless: this.bot.config.headless,
userDataDir: await this.bot.browser.func.loadSesion(email),
headless: this.bot.config.headless ? 'new' : false,
userDataDir: await loadSesion(this.bot.config.sessionPath, email),
args: [
'--no-sandbox',
'--mute-audio',
Expand All @@ -38,8 +39,8 @@ class Browser {
})

const { fingerprint, headers } = new FingerprintGenerator().getFingerprint({
devices: isMobile ? ['mobile'] : ['desktop'],
operatingSystems: isMobile ? ['android'] : ['windows'],
devices: this.bot.isMobile ? ['mobile'] : ['desktop'],
operatingSystems: this.bot.isMobile ? ['android'] : ['windows'],
browsers: ['edge'],
browserListQuery: 'last 2 Edge versions'
})
Expand Down
132 changes: 68 additions & 64 deletions src/browser/BrowserFunc.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { Page } from 'puppeteer'
import { CheerioAPI, load } from 'cheerio'
import fs from 'fs'
import path from 'path'

import { MicrosoftRewardsBot } from '../index'

Expand All @@ -16,7 +14,12 @@ export default class BrowserFunc {
this.bot = bot
}

async goHome(page: Page): Promise<boolean> {

/**
* Navigate the provided page to rewards homepage
* @param {Page} page Puppeteer page
*/
async goHome(page: Page) {

try {
const dashboardURL = new URL(this.bot.config.baseURL)
Expand All @@ -39,47 +42,52 @@ export default class BrowserFunc {
try {
// If activities are found, exit the loop
await page.waitForSelector('#more-activities', { timeout: 1000 })
this.bot.log('GO-HOME', 'Visited homepage successfully')
break

} catch (error) {
// Continue if element is not found
}

// Below runs if the homepage was unable to be visited
const currentURL = new URL(page.url())

if (currentURL.hostname !== dashboardURL.hostname) {
await this.bot.browser.utils.tryDismissAllMessages(page)

await this.bot.utils.wait(2000)
await page.goto(this.bot.config.baseURL)
} else {
this.bot.log('GO-HOME', 'Visited homepage successfully')
break
}

await this.bot.utils.wait(5000)
this.bot.log('GO-HOME', 'Visited homepage successfully')
}

} catch (error) {
console.error('An error occurred:', error)
return false
throw this.bot.log('GO-HOME', 'An error occurred:' + error, 'error')
}

return true
}

async getDashboardData(page: Page): Promise<DashboardData> {
/**
* Fetch user dashboard data
* @returns {DashboardData} Object of user bing rewards dashboard data
*/
async getDashboardData(): Promise<DashboardData> {
const dashboardURL = new URL(this.bot.config.baseURL)
const currentURL = new URL(page.url())
const currentURL = new URL(this.bot.homePage.url())

// Should never happen since tasks are opened in a new tab!
if (currentURL.hostname !== dashboardURL.hostname) {
this.bot.log('DASHBOARD-DATA', 'Provided page did not equal dashboard page, redirecting to dashboard page')
await this.goHome(page)
await this.goHome(this.bot.homePage)
}

// Reload the page to get new data
await page.reload({ waitUntil: 'networkidle2' })
await this.bot.homePage.reload({ waitUntil: 'networkidle2' })

const scriptContent = await page.evaluate(() => {
const scriptContent = await this.bot.homePage.evaluate(() => {
const scripts = Array.from(document.querySelectorAll('script'))
const targetScript = scripts.find(script => script.innerText.includes('var dashboard'))

Expand All @@ -91,7 +99,7 @@ export default class BrowserFunc {
})

// Extract the dashboard object from the script content
const dashboardData = await page.evaluate(scriptContent => {
const dashboardData = await this.bot.homePage.evaluate(scriptContent => {
// Extract the dashboard object using regex
const regex = /var dashboard = (\{.*?\});/s
const match = regex.exec(scriptContent)
Expand All @@ -106,47 +114,23 @@ export default class BrowserFunc {
return dashboardData
}

async getQuizData(page: Page): Promise<QuizData> {
try {
const html = await page.content()
const $ = load(html)

const scriptContent = $('script').filter((index, element) => {
return $(element).text().includes('_w.rewardsQuizRenderInfo')
}).text()

if (scriptContent) {
const regex = /_w\.rewardsQuizRenderInfo\s*=\s*({.*?});/s
const match = regex.exec(scriptContent)

if (match && match[1]) {
const quizData = JSON.parse(match[1])
return quizData
} else {
throw this.bot.log('GET-QUIZ-DATA', 'Quiz data not found within script', 'error')
}
} else {
throw this.bot.log('GET-QUIZ-DATA', 'Script containing quiz data not found', 'error')
}

} catch (error) {
throw this.bot.log('GET-QUIZ-DATA', 'An error occurred:' + error, 'error')
}

}

async getSearchPoints(page: Page): Promise<Counters> {
const dashboardData = await this.getDashboardData(page) // Always fetch newest data
/**
* Get search point counters
* @returns {Counters} Object of search counter data
*/
async getSearchPoints(): Promise<Counters> {
const dashboardData = await this.getDashboardData() // Always fetch newest data

return dashboardData.userStatus.counters
}

async getEarnablePoints(data: DashboardData, page: null | Page = null): Promise<number> {
/**
* Get total earnable points
* @returns {number} Total earnable points
*/
async getEarnablePoints(): Promise<number> {
try {
// Fetch new data if page is provided
if (page) {
data = await this.getDashboardData(page)
}
const data = await this.getDashboardData()

// These only include the points from tasks that the script can complete!
let totalEarnablePoints = 0
Expand Down Expand Up @@ -176,37 +160,57 @@ export default class BrowserFunc {
}
}

async getCurrentPoints(data: DashboardData, page: null | Page = null): Promise<number> {
/**
* Get current point amount
* @returns {number} Current total point amount
*/
async getCurrentPoints(): Promise<number> {
try {
// Fetch new data if page is provided
if (page) {
data = await this.getDashboardData(page)
}
const data = await this.getDashboardData()

return data.userStatus.availablePoints
} catch (error) {
throw this.bot.log('GET-CURRENT-POINTS', 'An error occurred:' + error, 'error')
}
}

async loadSesion(email: string): Promise<string> {
const sessionDir = path.join(__dirname, this.bot.config.sessionPath, email)

/**
* Parse quiz data from provided page
* @param {Page} page Puppeteer page
* @returns {QuizData} Quiz data object
*/
async getQuizData(page: Page): Promise<QuizData> {
try {
// Create session dir
if (!fs.existsSync(sessionDir)) {
await fs.promises.mkdir(sessionDir, { recursive: true })
const html = await page.content()
const $ = load(html)

const scriptContent = $('script').filter((index, element) => {
return $(element).text().includes('_w.rewardsQuizRenderInfo')
}).text()

if (scriptContent) {
const regex = /_w\.rewardsQuizRenderInfo\s*=\s*({.*?});/s
const match = regex.exec(scriptContent)

if (match && match[1]) {
const quizData = JSON.parse(match[1])
return quizData
} else {
throw this.bot.log('GET-QUIZ-DATA', 'Quiz data not found within script', 'error')
}
} else {
throw this.bot.log('GET-QUIZ-DATA', 'Script containing quiz data not found', 'error')
}

return sessionDir
} catch (error) {
throw new Error(error as string)
throw this.bot.log('GET-QUIZ-DATA', 'An error occurred:' + error, 'error')
}

}

async waitForQuizRefresh(page: Page): Promise<boolean> {
try {
await page.waitForSelector('#rqHeaderCredits', { visible: true, timeout: 10_000 })
await page.waitForSelector('span.rqMCredits', { visible: true, timeout: 10_000 })
await this.bot.utils.wait(2000)

return true
Expand Down
34 changes: 34 additions & 0 deletions src/browser/BrowserUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,38 @@ export default class BrowserUtil {
}
}

async getTabs(page: Page) {
try {
const browser = page.browser()
const pages = await browser.pages()

const homeTab = pages[1]
let homeTabURL: URL

if (!homeTab) {
throw this.bot.log('GET-TABS', 'Home tab could not be found!', 'error')

} else {
homeTabURL = new URL(homeTab.url())

if (homeTabURL.hostname !== 'rewards.bing.com') {
throw this.bot.log('GET-TABS', 'Reward page hostname is invalid: ' + homeTabURL.host, 'error')
}
}

const workerTab = pages[2]
if (!workerTab) {
throw this.bot.log('GET-TABS', 'Worker tab could not be found!', 'error')
}

return {
homeTab: homeTab,
workerTab: workerTab
}

} catch (error) {
throw this.bot.log('GET-TABS', 'An error occurred:' + error, 'error')
}
}

}
4 changes: 2 additions & 2 deletions src/functions/Activities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ export default class Activities {
this.bot = bot
}

doSearch = async (page: Page, data: DashboardData, mobile: boolean): Promise<void> => {
doSearch = async (page: Page, data: DashboardData): Promise<void> => {
const search = new Search(this.bot)
await search.doSearch(page, data, mobile)
await search.doSearch(page, data)
}

doABC = async (page: Page): Promise<void> => {
Expand Down
Loading

0 comments on commit 28286ff

Please sign in to comment.