mirror of
https://github.com/TheNetsky/Microsoft-Rewards-Script.git
synced 2026-01-11 02:46:17 +00:00
Pre 1.3.0
This commit is contained in:
20
.vscode/launch.json
vendored
20
.vscode/launch.json
vendored
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
// Use IntelliSense to learn about possible attributes.
|
|
||||||
// Hover to view descriptions of existing attributes.
|
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"type": "node",
|
|
||||||
"request": "launch",
|
|
||||||
"name": "Launch Program",
|
|
||||||
"skipFiles": [
|
|
||||||
"<node_internals>/**"
|
|
||||||
],
|
|
||||||
"program": "${file}",
|
|
||||||
"outFiles": [
|
|
||||||
"${workspaceFolder}/**/*.js"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -31,7 +31,7 @@ Under development, however mainly for personal use!
|
|||||||
- [x] Completing Click Rewards
|
- [x] Completing Click Rewards
|
||||||
- [x] Completing Polls
|
- [x] Completing Polls
|
||||||
- [x] Completing Punchcards
|
- [x] Completing Punchcards
|
||||||
- [ ] Solving This Or That Quiz
|
- [x] Solving This Or That Quiz (Random)
|
||||||
- [x] Clicking Promotional Items
|
- [x] Clicking Promotional Items
|
||||||
- [x] Solving ABC Quiz
|
- [x] Solving ABC Quiz
|
||||||
- [ ] Completing Shopping Game
|
- [ ] Completing Shopping Game
|
||||||
|
|||||||
13
package.json
13
package.json
@@ -25,17 +25,16 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "^6.7.0",
|
"@typescript-eslint/eslint-plugin": "^6.7.0",
|
||||||
|
"eslint": "^8.54.0",
|
||||||
|
"eslint-plugin-modules-newline": "^0.0.6",
|
||||||
"typescript": "^5.2.2"
|
"typescript": "^5.2.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.5.1",
|
"axios": "^1.6.1",
|
||||||
"cheerio": "^1.0.0-rc.12",
|
"cheerio": "^1.0.0-rc.12",
|
||||||
"eslint": "^8.49.0",
|
"fingerprint-generator": "^2.1.43",
|
||||||
"eslint-plugin-modules-newline": "^0.0.6",
|
"fingerprint-injector": "^2.1.43",
|
||||||
"fingerprint-generator": "^2.1.42",
|
"puppeteer": "^21.2.1",
|
||||||
"fingerprint-injector": "^2.1.42",
|
|
||||||
"puppeteer": "^21.4.1",
|
|
||||||
"puppeteer-extra": "^3.3.6",
|
|
||||||
"ts-node": "^10.9.1"
|
"ts-node": "^10.9.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import puppeteer from 'puppeteer-extra'
|
import puppeteer from 'puppeteer'
|
||||||
import { FingerprintInjector } from 'fingerprint-injector'
|
import { FingerprintInjector } from 'fingerprint-injector'
|
||||||
import { FingerprintGenerator } from 'fingerprint-generator'
|
import { FingerprintGenerator } from 'fingerprint-generator'
|
||||||
|
|
||||||
import { MicrosoftRewardsBot } from '../index'
|
import { MicrosoftRewardsBot } from '../index'
|
||||||
|
import { loadSesion } from '../util/Load'
|
||||||
|
|
||||||
import { AccountProxy } from '../interface/Account'
|
import { AccountProxy } from '../interface/Account'
|
||||||
|
|
||||||
@@ -20,12 +21,12 @@ class Browser {
|
|||||||
this.bot = bot
|
this.bot = bot
|
||||||
}
|
}
|
||||||
|
|
||||||
async createBrowser(email: string, proxy: AccountProxy, isMobile: boolean) {
|
async createBrowser(email: string, proxy: AccountProxy) {
|
||||||
// const userAgent = await getUserAgent(isMobile)
|
// const userAgent = await getUserAgent(isMobile)
|
||||||
|
|
||||||
const browser = await puppeteer.launch({
|
const browser = await puppeteer.launch({
|
||||||
headless: this.bot.config.headless,
|
headless: this.bot.config.headless ? 'new' : false,
|
||||||
userDataDir: await this.bot.browser.func.loadSesion(email),
|
userDataDir: await loadSesion(this.bot.config.sessionPath, email),
|
||||||
args: [
|
args: [
|
||||||
'--no-sandbox',
|
'--no-sandbox',
|
||||||
'--mute-audio',
|
'--mute-audio',
|
||||||
@@ -38,8 +39,8 @@ class Browser {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const { fingerprint, headers } = new FingerprintGenerator().getFingerprint({
|
const { fingerprint, headers } = new FingerprintGenerator().getFingerprint({
|
||||||
devices: isMobile ? ['mobile'] : ['desktop'],
|
devices: this.bot.isMobile ? ['mobile'] : ['desktop'],
|
||||||
operatingSystems: isMobile ? ['android'] : ['windows'],
|
operatingSystems: this.bot.isMobile ? ['android'] : ['windows'],
|
||||||
browsers: ['edge'],
|
browsers: ['edge'],
|
||||||
browserListQuery: 'last 2 Edge versions'
|
browserListQuery: 'last 2 Edge versions'
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { Page } from 'puppeteer'
|
import { Page } from 'puppeteer'
|
||||||
import { CheerioAPI, load } from 'cheerio'
|
import { CheerioAPI, load } from 'cheerio'
|
||||||
import fs from 'fs'
|
|
||||||
import path from 'path'
|
|
||||||
|
|
||||||
import { MicrosoftRewardsBot } from '../index'
|
import { MicrosoftRewardsBot } from '../index'
|
||||||
|
|
||||||
@@ -16,7 +14,12 @@ export default class BrowserFunc {
|
|||||||
this.bot = bot
|
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 {
|
try {
|
||||||
const dashboardURL = new URL(this.bot.config.baseURL)
|
const dashboardURL = new URL(this.bot.config.baseURL)
|
||||||
@@ -39,12 +42,14 @@ export default class BrowserFunc {
|
|||||||
try {
|
try {
|
||||||
// If activities are found, exit the loop
|
// If activities are found, exit the loop
|
||||||
await page.waitForSelector('#more-activities', { timeout: 1000 })
|
await page.waitForSelector('#more-activities', { timeout: 1000 })
|
||||||
|
this.bot.log('GO-HOME', 'Visited homepage successfully')
|
||||||
break
|
break
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Continue if element is not found
|
// Continue if element is not found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Below runs if the homepage was unable to be visited
|
||||||
const currentURL = new URL(page.url())
|
const currentURL = new URL(page.url())
|
||||||
|
|
||||||
if (currentURL.hostname !== dashboardURL.hostname) {
|
if (currentURL.hostname !== dashboardURL.hostname) {
|
||||||
@@ -52,34 +57,37 @@ export default class BrowserFunc {
|
|||||||
|
|
||||||
await this.bot.utils.wait(2000)
|
await this.bot.utils.wait(2000)
|
||||||
await page.goto(this.bot.config.baseURL)
|
await page.goto(this.bot.config.baseURL)
|
||||||
|
} else {
|
||||||
|
this.bot.log('GO-HOME', 'Visited homepage successfully')
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.bot.utils.wait(5000)
|
await this.bot.utils.wait(5000)
|
||||||
this.bot.log('GO-HOME', 'Visited homepage successfully')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('An error occurred:', error)
|
throw this.bot.log('GO-HOME', 'An error occurred:' + error, 'error')
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 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!
|
// Should never happen since tasks are opened in a new tab!
|
||||||
if (currentURL.hostname !== dashboardURL.hostname) {
|
if (currentURL.hostname !== dashboardURL.hostname) {
|
||||||
this.bot.log('DASHBOARD-DATA', 'Provided page did not equal dashboard page, redirecting to dashboard page')
|
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
|
// 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 scripts = Array.from(document.querySelectorAll('script'))
|
||||||
const targetScript = scripts.find(script => script.innerText.includes('var dashboard'))
|
const targetScript = scripts.find(script => script.innerText.includes('var dashboard'))
|
||||||
|
|
||||||
@@ -91,7 +99,7 @@ export default class BrowserFunc {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Extract the dashboard object from the script content
|
// 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
|
// Extract the dashboard object using regex
|
||||||
const regex = /var dashboard = (\{.*?\});/s
|
const regex = /var dashboard = (\{.*?\});/s
|
||||||
const match = regex.exec(scriptContent)
|
const match = regex.exec(scriptContent)
|
||||||
@@ -106,47 +114,23 @@ export default class BrowserFunc {
|
|||||||
return dashboardData
|
return dashboardData
|
||||||
}
|
}
|
||||||
|
|
||||||
async getQuizData(page: Page): Promise<QuizData> {
|
/**
|
||||||
try {
|
* Get search point counters
|
||||||
const html = await page.content()
|
* @returns {Counters} Object of search counter data
|
||||||
const $ = load(html)
|
*/
|
||||||
|
async getSearchPoints(): Promise<Counters> {
|
||||||
const scriptContent = $('script').filter((index, element) => {
|
const dashboardData = await this.getDashboardData() // Always fetch newest data
|
||||||
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
|
|
||||||
|
|
||||||
return dashboardData.userStatus.counters
|
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 {
|
try {
|
||||||
// Fetch new data if page is provided
|
const data = await this.getDashboardData()
|
||||||
if (page) {
|
|
||||||
data = await this.getDashboardData(page)
|
|
||||||
}
|
|
||||||
|
|
||||||
// These only include the points from tasks that the script can complete!
|
// These only include the points from tasks that the script can complete!
|
||||||
let totalEarnablePoints = 0
|
let totalEarnablePoints = 0
|
||||||
@@ -176,12 +160,13 @@ 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 {
|
try {
|
||||||
// Fetch new data if page is provided
|
const data = await this.getDashboardData()
|
||||||
if (page) {
|
|
||||||
data = await this.getDashboardData(page)
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.userStatus.availablePoints
|
return data.userStatus.availablePoints
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -189,24 +174,43 @@ export default class BrowserFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
try {
|
||||||
// Create session dir
|
const html = await page.content()
|
||||||
if (!fs.existsSync(sessionDir)) {
|
const $ = load(html)
|
||||||
await fs.promises.mkdir(sessionDir, { recursive: true })
|
|
||||||
|
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) {
|
} 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> {
|
async waitForQuizRefresh(page: Page): Promise<boolean> {
|
||||||
try {
|
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)
|
await this.bot.utils.wait(2000)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -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')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -19,9 +19,9 @@ export default class Activities {
|
|||||||
this.bot = bot
|
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)
|
const search = new Search(this.bot)
|
||||||
await search.doSearch(page, data, mobile)
|
await search.doSearch(page, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
doABC = async (page: Page): Promise<void> => {
|
doABC = async (page: Page): Promise<void> => {
|
||||||
|
|||||||
@@ -20,11 +20,12 @@ export class Login {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Navigate to the Bing login page
|
// Navigate to the Bing login page
|
||||||
await page.goto('https://login.live.com/')
|
await page.goto('https://rewards.bing.com/signin')
|
||||||
|
|
||||||
const isLoggedIn = await page.waitForSelector('html[data-role-name="MeePortal"]', { timeout: 10_000 }).then(() => true).catch(() => false)
|
const isLoggedIn = await page.waitForSelector('html[data-role-name="RewardsPortal"]', { timeout: 10_000 }).then(() => true).catch(() => false)
|
||||||
|
|
||||||
if (!isLoggedIn) {
|
if (!isLoggedIn) {
|
||||||
|
// Check if account is locked
|
||||||
const isLocked = await page.waitForSelector('.serviceAbusePageContainer', { visible: true, timeout: 10_000 }).then(() => true).catch(() => false)
|
const isLocked = await page.waitForSelector('.serviceAbusePageContainer', { visible: true, timeout: 10_000 }).then(() => true).catch(() => false)
|
||||||
if (isLocked) {
|
if (isLocked) {
|
||||||
this.bot.log('LOGIN', 'This account has been locked!', 'error')
|
this.bot.log('LOGIN', 'This account has been locked!', 'error')
|
||||||
@@ -64,9 +65,11 @@ export class Login {
|
|||||||
await page.type('#i0118', password)
|
await page.type('#i0118', password)
|
||||||
await page.click('#idSIButton9')
|
await page.click('#idSIButton9')
|
||||||
|
|
||||||
|
// When erroring at this stage it means a 2FA code is required
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.bot.log('LOGIN', '2FA code required')
|
this.bot.log('LOGIN', '2FA code required')
|
||||||
|
|
||||||
|
// Wait for user input
|
||||||
const code = await new Promise<string>((resolve) => {
|
const code = await new Promise<string>((resolve) => {
|
||||||
rl.question('Enter 2FA code:\n', (input) => {
|
rl.question('Enter 2FA code:\n', (input) => {
|
||||||
rl.close()
|
rl.close()
|
||||||
@@ -83,13 +86,13 @@ export class Login {
|
|||||||
|
|
||||||
const currentURL = new URL(page.url())
|
const currentURL = new URL(page.url())
|
||||||
|
|
||||||
while (currentURL.pathname !== '/' || currentURL.hostname !== 'account.microsoft.com') {
|
while (currentURL.pathname !== '/' || currentURL.hostname !== 'rewards.bing.com') {
|
||||||
await this.bot.browser.utils.tryDismissAllMessages(page)
|
await this.bot.browser.utils.tryDismissAllMessages(page)
|
||||||
currentURL.href = page.url()
|
currentURL.href = page.url()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for login to complete
|
// Wait for login to complete
|
||||||
await page.waitForSelector('html[data-role-name="MeePortal"]', { timeout: 10_000 })
|
await page.waitForSelector('html[data-role-name="RewardsPortal"]', { timeout: 10_000 })
|
||||||
}
|
}
|
||||||
|
|
||||||
private async checkBingLogin(page: Page): Promise<void> {
|
private async checkBingLogin(page: Page): Promise<void> {
|
||||||
@@ -103,11 +106,11 @@ export class Login {
|
|||||||
const currentUrl = new URL(page.url())
|
const currentUrl = new URL(page.url())
|
||||||
|
|
||||||
if (currentUrl.hostname === 'www.bing.com' && currentUrl.pathname === '/') {
|
if (currentUrl.hostname === 'www.bing.com' && currentUrl.pathname === '/') {
|
||||||
await this.bot.utils.wait(3000)
|
|
||||||
await this.bot.browser.utils.tryDismissBingCookieBanner(page)
|
await this.bot.browser.utils.tryDismissBingCookieBanner(page)
|
||||||
|
|
||||||
const loggedIn = await this.checkBingLoginStatus(page)
|
const loggedIn = await this.checkBingLoginStatus(page)
|
||||||
if (loggedIn) {
|
// If mobile browser, skip this step
|
||||||
|
if (loggedIn || this.bot.isMobile) {
|
||||||
this.bot.log('LOGIN-BING', 'Bing login verification passed!')
|
this.bot.log('LOGIN-BING', 'Bing login verification passed!')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -123,7 +126,7 @@ export class Login {
|
|||||||
|
|
||||||
private async checkBingLoginStatus(page: Page): Promise<boolean> {
|
private async checkBingLoginStatus(page: Page): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
await page.waitForSelector('#id_n', { timeout: 10_000 })
|
await page.waitForSelector('#id_n', { timeout: 5000 })
|
||||||
return true
|
return true
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -92,6 +92,8 @@ export class Workers {
|
|||||||
|
|
||||||
// Solve all the different types of activities
|
// Solve all the different types of activities
|
||||||
private async solveActivities(page: Page, activities: PromotionalItem[] | MorePromotion[], punchCard?: PunchCard) {
|
private async solveActivities(page: Page, activities: PromotionalItem[] | MorePromotion[], punchCard?: PunchCard) {
|
||||||
|
let activityPage = page
|
||||||
|
|
||||||
for (const activity of activities) {
|
for (const activity of activities) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
@@ -111,14 +113,11 @@ export class Workers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for element to load
|
|
||||||
await page.waitForSelector(selector, { timeout: 10_000 })
|
|
||||||
|
|
||||||
// Click element, it will be opened in a new tab
|
// Click element, it will be opened in a new tab
|
||||||
await page.click(selector)
|
await page.click(selector)
|
||||||
|
|
||||||
// Select the new activity page
|
// Select the new activity page
|
||||||
const activityPage = await this.bot.browser.utils.getLatestTab(page)
|
activityPage = await this.bot.browser.utils.getLatestTab(page)
|
||||||
|
|
||||||
// Wait for the new tab to fully load, ignore error.
|
// Wait for the new tab to fully load, ignore error.
|
||||||
/*
|
/*
|
||||||
@@ -126,9 +125,7 @@ export class Workers {
|
|||||||
if it didn't then it gave enough time for the page to load.
|
if it didn't then it gave enough time for the page to load.
|
||||||
*/
|
*/
|
||||||
await activityPage.waitForNetworkIdle({ timeout: 10_000 }).catch(() => { })
|
await activityPage.waitForNetworkIdle({ timeout: 10_000 }).catch(() => { })
|
||||||
|
await this.bot.utils.wait(5000)
|
||||||
// Cooldown
|
|
||||||
await this.bot.utils.wait(4000)
|
|
||||||
|
|
||||||
switch (activity.promotionType) {
|
switch (activity.promotionType) {
|
||||||
// Quiz (Poll, Quiz or ABC)
|
// Quiz (Poll, Quiz or ABC)
|
||||||
@@ -175,8 +172,14 @@ export class Workers {
|
|||||||
|
|
||||||
// Cooldown
|
// Cooldown
|
||||||
await this.bot.utils.wait(2000)
|
await this.bot.utils.wait(2000)
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.bot.log('ACTIVITY', 'An error occurred:' + error, 'error')
|
this.bot.log('ACTIVITY', 'An error occurred:' + error, 'error')
|
||||||
|
const tabs = await (page.browser()).pages()
|
||||||
|
|
||||||
|
if (tabs.length > 2) {
|
||||||
|
await activityPage.close() // Already assigned to be the "latest tab"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export class Quiz extends Workers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other type quiz
|
// Other type quiz, lightspeed
|
||||||
} else if ([2, 3, 4].includes(quizData.numberOfOptions)) {
|
} else if ([2, 3, 4].includes(quizData.numberOfOptions)) {
|
||||||
quizData = await this.bot.browser.func.getQuizData(page) // Refresh Quiz Data
|
quizData = await this.bot.browser.func.getQuizData(page) // Refresh Quiz Data
|
||||||
const correctOption = quizData.correctAnswer
|
const correctOption = quizData.correctAnswer
|
||||||
|
|||||||
@@ -12,19 +12,25 @@ export class Search extends Workers {
|
|||||||
|
|
||||||
private searchPageURL = 'https://bing.com'
|
private searchPageURL = 'https://bing.com'
|
||||||
|
|
||||||
public async doSearch(page: Page, data: DashboardData, mobile: boolean) {
|
public async doSearch(page: Page, data: DashboardData) {
|
||||||
this.bot.log('SEARCH-BING', 'Starting bing searches')
|
this.bot.log('SEARCH-BING', 'Starting bing searches')
|
||||||
|
|
||||||
|
let retries = 0
|
||||||
|
while ((!data.userStatus.counters?.pcSearch || data.userStatus.counters.pcSearch.length < 2) && retries < 3) {
|
||||||
|
data = await this.bot.browser.func.getDashboardData()
|
||||||
|
retries++
|
||||||
|
}
|
||||||
|
|
||||||
const mobileData = data.userStatus.counters?.mobileSearch ? data.userStatus.counters.mobileSearch[0] : null // Mobile searches
|
const mobileData = data.userStatus.counters?.mobileSearch ? data.userStatus.counters.mobileSearch[0] : null // Mobile searches
|
||||||
const edgeData = data.userStatus.counters.pcSearch[1] as DashboardImpression // Edge searches
|
const edgeData = data.userStatus.counters.pcSearch[1] as DashboardImpression // Edge searches
|
||||||
const genericData = data.userStatus.counters.pcSearch[0] as DashboardImpression // Normal searches
|
const genericData = data.userStatus.counters.pcSearch[0] as DashboardImpression // Normal searches
|
||||||
|
|
||||||
let missingPoints = (mobile && mobileData) ?
|
let missingPoints = (this.bot.isMobile && mobileData) ?
|
||||||
(mobileData.pointProgressMax - mobileData.pointProgress) :
|
(mobileData.pointProgressMax - mobileData.pointProgress) :
|
||||||
(edgeData.pointProgressMax - edgeData.pointProgress) + (genericData.pointProgressMax - genericData.pointProgress)
|
(edgeData.pointProgressMax - edgeData.pointProgress) + (genericData.pointProgressMax - genericData.pointProgress)
|
||||||
|
|
||||||
if (missingPoints == 0) {
|
if (missingPoints == 0) {
|
||||||
this.bot.log('SEARCH-BING', `Bing searches for ${mobile ? 'MOBILE' : 'DESKTOP'} have already been completed`)
|
this.bot.log('SEARCH-BING', `Bing searches for ${this.bot.isMobile ? 'MOBILE' : 'DESKTOP'} have already been completed`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,31 +41,39 @@ export class Search extends Workers {
|
|||||||
// Deduplicate the search terms
|
// Deduplicate the search terms
|
||||||
googleSearchQueries = [...new Set(googleSearchQueries)]
|
googleSearchQueries = [...new Set(googleSearchQueries)]
|
||||||
|
|
||||||
// Open a new tab
|
|
||||||
const browser = page.browser()
|
|
||||||
const searchPage = await browser.newPage()
|
|
||||||
|
|
||||||
// Go to bing
|
// Go to bing
|
||||||
await searchPage.goto(this.searchPageURL)
|
await page.goto(this.searchPageURL)
|
||||||
|
|
||||||
let maxLoop = 0 // If the loop hits 10 this when not gaining any points, we're assuming it's stuck. If it ddoesn't continue after 5 more searches with alternative queries, abort search
|
let maxLoop = 0 // If the loop hits 10 this when not gaining any points, we're assuming it's stuck. If it ddoesn't continue after 5 more searches with alternative queries, abort search
|
||||||
|
|
||||||
const queries: string[] = []
|
const queries: string[] = []
|
||||||
googleSearchQueries.forEach(x => queries.push(x.topic, ...x.related))
|
// Mobile search doesn't seem to like related queries?
|
||||||
|
googleSearchQueries.forEach(x => { this.bot.isMobile ? queries.push(x.topic) : queries.push(x.topic, ...x.related) })
|
||||||
|
|
||||||
// Loop over Google search queries
|
// Loop over Google search queries
|
||||||
for (let i = 0; i < queries.length; i++) {
|
for (let i = 0; i < queries.length; i++) {
|
||||||
const query = queries[i] as string
|
const query = queries[i] as string
|
||||||
|
|
||||||
this.bot.log('SEARCH-BING', `${missingPoints} Points Remaining | Query: ${query} | Mobile: ${mobile}`)
|
this.bot.log('SEARCH-BING', `${missingPoints} Points Remaining | Query: ${query} | Mobile: ${this.bot.isMobile}`)
|
||||||
|
|
||||||
const newData = await this.bingSearch(page, searchPage, query)
|
let newData = await this.bingSearch(page, page, query)
|
||||||
|
|
||||||
|
let retries = 0
|
||||||
|
while ((!newData?.pcSearch || newData.pcSearch.length < 2) && retries < 3) {
|
||||||
|
newData = await this.bot.browser.func.getSearchPoints()
|
||||||
|
retries++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newData?.pcSearch || newData.pcSearch.length < 2) {
|
||||||
|
newData = await this.bot.browser.func.getSearchPoints()
|
||||||
|
}
|
||||||
|
|
||||||
const newMobileData = newData.mobileSearch ? newData.mobileSearch[0] : null // Mobile searches
|
const newMobileData = newData.mobileSearch ? newData.mobileSearch[0] : null // Mobile searches
|
||||||
const newEdgeData = newData.pcSearch[1] as DashboardImpression // Edge searches
|
const newEdgeData = newData.pcSearch[1] as DashboardImpression // Edge searches
|
||||||
const newGenericData = newData.pcSearch[0] as DashboardImpression // Normal searches
|
const newGenericData = newData.pcSearch[0] as DashboardImpression // Normal searches
|
||||||
|
|
||||||
const newMissingPoints = (mobile && newMobileData) ?
|
const newMissingPoints = (this.bot.isMobile && newMobileData) ?
|
||||||
(newMobileData.pointProgressMax - newMobileData.pointProgress) :
|
(newMobileData.pointProgressMax - newMobileData.pointProgress) :
|
||||||
(newEdgeData.pointProgressMax - newEdgeData.pointProgress) + (newGenericData.pointProgressMax - newGenericData.pointProgress)
|
(newEdgeData.pointProgressMax - newEdgeData.pointProgress) + (newGenericData.pointProgressMax - newGenericData.pointProgress)
|
||||||
|
|
||||||
@@ -97,14 +111,21 @@ export class Search extends Workers {
|
|||||||
if (relatedTerms.length > 3) {
|
if (relatedTerms.length > 3) {
|
||||||
// Search for the first 2 related terms
|
// Search for the first 2 related terms
|
||||||
for (const term of relatedTerms.slice(1, 3)) {
|
for (const term of relatedTerms.slice(1, 3)) {
|
||||||
this.bot.log('SEARCH-BING-EXTRA', `${missingPoints} Points Remaining | Query: ${term} | Mobile: ${mobile}`)
|
this.bot.log('SEARCH-BING-EXTRA', `${missingPoints} Points Remaining | Query: ${term} | Mobile: ${this.bot.isMobile}`)
|
||||||
const newData = await this.bingSearch(page, searchPage, query.topic)
|
|
||||||
|
let newData = await this.bingSearch(page, page, query.topic)
|
||||||
|
|
||||||
|
let retries = 0
|
||||||
|
while ((!newData?.pcSearch || newData.pcSearch.length < 2) && retries < 3) {
|
||||||
|
newData = await this.bot.browser.func.getSearchPoints()
|
||||||
|
retries++
|
||||||
|
}
|
||||||
|
|
||||||
const newMobileData = newData.mobileSearch ? newData.mobileSearch[0] : null // Mobile searches
|
const newMobileData = newData.mobileSearch ? newData.mobileSearch[0] : null // Mobile searches
|
||||||
const newEdgeData = newData.pcSearch[1] as DashboardImpression // Edge searches
|
const newEdgeData = newData.pcSearch[1] as DashboardImpression // Edge searches
|
||||||
const newGenericData = newData.pcSearch[0] as DashboardImpression // Normal searches
|
const newGenericData = newData.pcSearch[0] as DashboardImpression // Normal searches
|
||||||
|
|
||||||
const newMissingPoints = (mobile && newMobileData) ?
|
const newMissingPoints = (this.bot.isMobile && newMobileData) ?
|
||||||
(newMobileData.pointProgressMax - newMobileData.pointProgress) :
|
(newMobileData.pointProgressMax - newMobileData.pointProgress) :
|
||||||
(newEdgeData.pointProgressMax - newEdgeData.pointProgress) + (newGenericData.pointProgressMax - newGenericData.pointProgress)
|
(newEdgeData.pointProgressMax - newEdgeData.pointProgress) + (newGenericData.pointProgressMax - newGenericData.pointProgress)
|
||||||
|
|
||||||
@@ -162,7 +183,7 @@ export class Search extends Workers {
|
|||||||
|
|
||||||
await this.bot.utils.wait(Math.floor(this.bot.utils.randomNumber(this.bot.config.searchSettings.searchDelay.min, this.bot.config.searchSettings.searchDelay.max)))
|
await this.bot.utils.wait(Math.floor(this.bot.utils.randomNumber(this.bot.config.searchSettings.searchDelay.min, this.bot.config.searchSettings.searchDelay.max)))
|
||||||
|
|
||||||
return await this.bot.browser.func.getSearchPoints(page)
|
return await this.bot.browser.func.getSearchPoints()
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (i === 5) {
|
if (i === 5) {
|
||||||
@@ -178,7 +199,7 @@ export class Search extends Workers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.bot.log('SEARCH-BING', 'Search failed after 5 retries, ending', 'error')
|
this.bot.log('SEARCH-BING', 'Search failed after 5 retries, ending', 'error')
|
||||||
return await this.bot.browser.func.getSearchPoints(page)
|
return await this.bot.browser.func.getSearchPoints()
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getGoogleTrends(geoLocale: string, queryCount: number): Promise<GoogleSearch[]> {
|
private async getGoogleTrends(geoLocale: string, queryCount: number): Promise<GoogleSearch[]> {
|
||||||
@@ -211,7 +232,7 @@ export class Search extends Workers {
|
|||||||
for (const topic of data.default.trendingSearchesDays[0]?.trendingSearches ?? []) {
|
for (const topic of data.default.trendingSearchesDays[0]?.trendingSearches ?? []) {
|
||||||
queryTerms.push({
|
queryTerms.push({
|
||||||
topic: topic.title.query.toLowerCase(),
|
topic: topic.title.query.toLowerCase(),
|
||||||
related: topic.relatedQueries.map(x => x.query.toLocaleLowerCase())
|
related: topic.relatedQueries.map(x => x.query.toLowerCase())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,9 +274,10 @@ export class Search extends Workers {
|
|||||||
private async randomScroll(page: Page) {
|
private async randomScroll(page: Page) {
|
||||||
try {
|
try {
|
||||||
// Press the arrow down key to scroll
|
// Press the arrow down key to scroll
|
||||||
for (let i = 0; i < this.bot.utils.randomNumber(5, 100); i++) {
|
for (let i = 0; i < this.bot.utils.randomNumber(5, 400); i++) {
|
||||||
await page.keyboard.press('ArrowDown')
|
await page.keyboard.press('ArrowDown')
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.bot.log('SEARCH-RANDOM-SCROLL', 'An error occurred:' + error, 'error')
|
this.bot.log('SEARCH-RANDOM-SCROLL', 'An error occurred:' + error, 'error')
|
||||||
}
|
}
|
||||||
@@ -271,57 +293,52 @@ export class Search extends Workers {
|
|||||||
let lastTab = await this.bot.browser.utils.getLatestTab(page)
|
let lastTab = await this.bot.browser.utils.getLatestTab(page)
|
||||||
|
|
||||||
// Let website load, if it doesn't load within 5 sec. exit regardless
|
// Let website load, if it doesn't load within 5 sec. exit regardless
|
||||||
await lastTab.waitForNetworkIdle({ timeout: 5000 }).catch(() => { })
|
await this.bot.utils.wait(5000)
|
||||||
|
|
||||||
// Check if the tab is closed or not
|
let lastTabURL = new URL(lastTab.url()) // Get new tab info
|
||||||
if (!lastTab.isClosed()) {
|
|
||||||
let lastTabURL = new URL(lastTab.url()) // Get new tab info
|
|
||||||
|
|
||||||
// Check if the URL is different from the original one, don't loop more than 5 times.
|
// Check if the URL is different from the original one, don't loop more than 5 times.
|
||||||
let i = 0
|
let i = 0
|
||||||
while (lastTabURL.href !== searchListingURL.href && i < 5) {
|
while (lastTabURL.href !== searchListingURL.href && i < 5) {
|
||||||
// If hostname is still bing, (Bing images/news etc)
|
// If hostname is still bing, (Bing images/news etc)
|
||||||
if (lastTabURL.hostname == searchListingURL.hostname) {
|
if (lastTabURL.hostname === searchListingURL.hostname) {
|
||||||
|
await lastTab.goBack()
|
||||||
|
|
||||||
|
// Refresh
|
||||||
|
lastTab = await this.bot.browser.utils.getLatestTab(page)
|
||||||
|
lastTabURL = new URL(lastTab.url())
|
||||||
|
|
||||||
|
// If "goBack" didn't return to search listing (due to redirects)
|
||||||
|
if (lastTabURL.hostname !== searchListingURL.hostname) {
|
||||||
|
await lastTab.goto(this.searchPageURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // No longer on bing, likely opened a new tab, close this tab
|
||||||
|
const tabs = await (page.browser()).pages()
|
||||||
|
|
||||||
|
// If the browser has more than 3 tabs open, it has opened a new one, we need to close this one.
|
||||||
|
if (tabs.length > 3) {
|
||||||
|
await lastTab.close()
|
||||||
|
|
||||||
|
} else if (lastTabURL.href !== searchListingURL.href) {
|
||||||
await lastTab.goBack()
|
await lastTab.goBack()
|
||||||
|
// Refresh
|
||||||
lastTab = await this.bot.browser.utils.getLatestTab(page) // Get last opened tab
|
lastTab = await this.bot.browser.utils.getLatestTab(page)
|
||||||
|
lastTabURL = new URL(lastTab.url())
|
||||||
|
|
||||||
// If "goBack" didn't return to search listing (due to redirects)
|
// If "goBack" didn't return to search listing (due to redirects)
|
||||||
if (lastTabURL.hostname !== searchListingURL.hostname) {
|
if (lastTabURL.hostname !== searchListingURL.hostname) {
|
||||||
await lastTab.goto(this.searchPageURL)
|
await lastTab.goto(this.searchPageURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else { // No longer on bing, likely opened a new tab, close this tab
|
|
||||||
lastTab = await this.bot.browser.utils.getLatestTab(page) // Get last opened tab
|
|
||||||
lastTabURL = new URL(lastTab.url())
|
|
||||||
|
|
||||||
const tabs = await (page.browser()).pages() // Get all tabs open
|
|
||||||
|
|
||||||
// If the browser has more than 3 tabs open, it has opened a new one, we need to close this one.
|
|
||||||
if (tabs.length > 3) {
|
|
||||||
// Make sure the page is still open!
|
|
||||||
if (!lastTab.isClosed()) {
|
|
||||||
await lastTab.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (lastTabURL.href !== searchListingURL.href) {
|
|
||||||
|
|
||||||
await lastTab.goBack()
|
|
||||||
|
|
||||||
lastTab = await this.bot.browser.utils.getLatestTab(page) // Get last opened tab
|
|
||||||
lastTabURL = new URL(lastTab.url())
|
|
||||||
|
|
||||||
// If "goBack" didn't return to search listing (due to redirects)
|
|
||||||
if (lastTabURL.hostname !== searchListingURL.hostname) {
|
|
||||||
await lastTab.goto(this.searchPageURL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
lastTab = await this.bot.browser.utils.getLatestTab(page) // Finally update the lastTab var again
|
|
||||||
i++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// End of loop, refresh lastPage
|
||||||
|
lastTab = await this.bot.browser.utils.getLatestTab(page) // Finally update the lastTab var again
|
||||||
|
lastTabURL = new URL(lastTab.url()) // Get new tab info
|
||||||
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.bot.log('SEARCH-RANDOM-CLICK', 'An error occurred:' + error, 'error')
|
this.bot.log('SEARCH-RANDOM-CLICK', 'An error occurred:' + error, 'error')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export class ThisOrThat extends Workers {
|
|||||||
async doThisOrThat(page: Page) {
|
async doThisOrThat(page: Page) {
|
||||||
this.bot.log('THIS-OR-THAT', 'Trying to complete ThisOrThat')
|
this.bot.log('THIS-OR-THAT', 'Trying to complete ThisOrThat')
|
||||||
|
|
||||||
return
|
|
||||||
try {
|
try {
|
||||||
// Check if the quiz has been started or not
|
// Check if the quiz has been started or not
|
||||||
const quizNotStarted = await page.waitForSelector('#rqStartQuiz', { visible: true, timeout: 2000 }).then(() => true).catch(() => false)
|
const quizNotStarted = await page.waitForSelector('#rqStartQuiz', { visible: true, timeout: 2000 }).then(() => true).catch(() => false)
|
||||||
@@ -22,7 +22,20 @@ export class ThisOrThat extends Workers {
|
|||||||
|
|
||||||
// Solving
|
// Solving
|
||||||
const quizData = await this.bot.browser.func.getQuizData(page)
|
const quizData = await this.bot.browser.func.getQuizData(page)
|
||||||
quizData // correctAnswer property is always null?
|
const questionsRemaining = quizData.maxQuestions - (quizData.currentQuestionNumber - 1) // Amount of questions remaining
|
||||||
|
|
||||||
|
for (let question = 0; question < questionsRemaining; question++) {
|
||||||
|
// Since there's no solving logic yet, randomly guess to complete
|
||||||
|
const buttonId = `#rqAnswerOption${Math.floor(this.bot.utils.randomNumber(0, 1))}`
|
||||||
|
await page.click(buttonId)
|
||||||
|
|
||||||
|
const refreshSuccess = await this.bot.browser.func.waitForQuizRefresh(page)
|
||||||
|
if (!refreshSuccess) {
|
||||||
|
await page.close()
|
||||||
|
this.bot.log('QUIZ', 'An error occurred, refresh was unsuccessful', 'error')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.bot.log('THIS-OR-THAT', 'Completed the ThisOrThat successfully')
|
this.bot.log('THIS-OR-THAT', 'Completed the ThisOrThat successfully')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
68
src/index.ts
68
src/index.ts
@@ -1,4 +1,5 @@
|
|||||||
import cluster from 'cluster'
|
import cluster from 'cluster'
|
||||||
|
import { Page } from 'puppeteer'
|
||||||
|
|
||||||
import Browser from './browser/Browser'
|
import Browser from './browser/Browser'
|
||||||
import BrowserFunc from './browser/BrowserFunc'
|
import BrowserFunc from './browser/BrowserFunc'
|
||||||
@@ -24,6 +25,8 @@ export class MicrosoftRewardsBot {
|
|||||||
func: BrowserFunc,
|
func: BrowserFunc,
|
||||||
utils: BrowserUtil
|
utils: BrowserUtil
|
||||||
}
|
}
|
||||||
|
public isMobile: boolean = false
|
||||||
|
public homePage!: Page
|
||||||
|
|
||||||
private collectedPoints: number = 0
|
private collectedPoints: number = 0
|
||||||
private activeWorkers: number
|
private activeWorkers: number
|
||||||
@@ -122,8 +125,8 @@ export class MicrosoftRewardsBot {
|
|||||||
|
|
||||||
// Desktop
|
// Desktop
|
||||||
async Desktop(account: Account) {
|
async Desktop(account: Account) {
|
||||||
const browser = await this.browserFactory.createBrowser(account.email, account.proxy, false)
|
const browser = await this.browserFactory.createBrowser(account.email, account.proxy)
|
||||||
const page = await browser.newPage()
|
this.homePage = await browser.newPage()
|
||||||
let pages = await browser.pages()
|
let pages = await browser.pages()
|
||||||
|
|
||||||
// If for some reason the browser initializes with more than 2 pages, close these
|
// If for some reason the browser initializes with more than 2 pages, close these
|
||||||
@@ -133,51 +136,53 @@ export class MicrosoftRewardsBot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Log into proxy
|
// Log into proxy
|
||||||
await page.authenticate({ username: account.proxy.username, password: account.proxy.password })
|
await this.homePage.authenticate({ username: account.proxy.username, password: account.proxy.password })
|
||||||
|
|
||||||
log('MAIN', 'Starting DESKTOP browser')
|
log('MAIN', 'Starting DESKTOP browser')
|
||||||
|
|
||||||
// Login into MS Rewards
|
// Login into MS Rewards, then go to rewards homepage
|
||||||
await this.login.login(page, account.email, account.password)
|
await this.login.login(this.homePage, account.email, account.password)
|
||||||
|
await this.browser.func.goHome(this.homePage)
|
||||||
|
|
||||||
const wentHome = await this.browser.func.goHome(page)
|
const data = await this.browser.func.getDashboardData()
|
||||||
if (!wentHome) {
|
|
||||||
throw log('MAIN', 'Unable to get dashboard page', 'error')
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await this.browser.func.getDashboardData(page)
|
|
||||||
log('MAIN-POINTS', `Current point count: ${data.userStatus.availablePoints}`)
|
log('MAIN-POINTS', `Current point count: ${data.userStatus.availablePoints}`)
|
||||||
|
|
||||||
const earnablePoints = await this.browser.func.getEarnablePoints(data)
|
const earnablePoints = await this.browser.func.getEarnablePoints()
|
||||||
this.collectedPoints = earnablePoints
|
this.collectedPoints = earnablePoints
|
||||||
log('MAIN-POINTS', `You can earn ${earnablePoints} points today`)
|
log('MAIN-POINTS', `You can earn ${earnablePoints} points today`)
|
||||||
|
|
||||||
// If runOnZeroPoints is false and 0 points to earn, don't continue
|
// If runOnZeroPoints is false and 0 points to earn, don't continue
|
||||||
if (!this.config.runOnZeroPoints && this.collectedPoints === 0) {
|
if (!this.config.runOnZeroPoints && this.collectedPoints === 0) {
|
||||||
log('MAIN', 'No points to earn and "runOnZeroPoints" is set to "false", stopping')
|
log('MAIN', 'No points to earn and "runOnZeroPoints" is set to "false", stopping!')
|
||||||
|
|
||||||
// Close desktop browser
|
// Close desktop browser
|
||||||
return await browser.close()
|
return await browser.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open a new tab to where the tasks are going to be completed
|
||||||
|
const workerPage = await browser.newPage()
|
||||||
|
|
||||||
|
// Go to homepage on worker page
|
||||||
|
await this.browser.func.goHome(workerPage)
|
||||||
|
|
||||||
// Complete daily set
|
// Complete daily set
|
||||||
if (this.config.workers.doDailySet) {
|
if (this.config.workers.doDailySet) {
|
||||||
await this.workers.doDailySet(page, data)
|
await this.workers.doDailySet(workerPage, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Complete more promotions
|
// Complete more promotions
|
||||||
if (this.config.workers.doMorePromotions) {
|
if (this.config.workers.doMorePromotions) {
|
||||||
await this.workers.doMorePromotions(page, data)
|
await this.workers.doMorePromotions(workerPage, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Complete punch cards
|
// Complete punch cards
|
||||||
if (this.config.workers.doPunchCards) {
|
if (this.config.workers.doPunchCards) {
|
||||||
await this.workers.doPunchCard(page, data)
|
await this.workers.doPunchCard(workerPage, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do desktop searches
|
// Do desktop searches
|
||||||
if (this.config.workers.doDesktopSearch) {
|
if (this.config.workers.doDesktopSearch) {
|
||||||
await this.activities.doSearch(page, data, false)
|
await this.activities.doSearch(workerPage, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close desktop browser
|
// Close desktop browser
|
||||||
@@ -186,8 +191,10 @@ export class MicrosoftRewardsBot {
|
|||||||
|
|
||||||
// Mobile
|
// Mobile
|
||||||
async Mobile(account: Account) {
|
async Mobile(account: Account) {
|
||||||
const browser = await this.browserFactory.createBrowser(account.email, account.proxy, true)
|
this.isMobile = true
|
||||||
const page = await browser.newPage()
|
|
||||||
|
const browser = await this.browserFactory.createBrowser(account.email, account.proxy)
|
||||||
|
this.homePage = await browser.newPage()
|
||||||
let pages = await browser.pages()
|
let pages = await browser.pages()
|
||||||
|
|
||||||
// If for some reason the browser initializes with more than 2 pages, close these
|
// If for some reason the browser initializes with more than 2 pages, close these
|
||||||
@@ -196,32 +203,37 @@ export class MicrosoftRewardsBot {
|
|||||||
pages = await browser.pages()
|
pages = await browser.pages()
|
||||||
}
|
}
|
||||||
// Log into proxy
|
// Log into proxy
|
||||||
await page.authenticate({ username: account.proxy.username, password: account.proxy.password })
|
await this.homePage.authenticate({ username: account.proxy.username, password: account.proxy.password })
|
||||||
|
|
||||||
log('MAIN', 'Starting MOBILE browser')
|
log('MAIN', 'Starting MOBILE browser')
|
||||||
|
|
||||||
// Login into MS Rewards
|
// Login into MS Rewards, then go to rewards homepage
|
||||||
await this.login.login(page, account.email, account.password)
|
await this.login.login(this.homePage, account.email, account.password)
|
||||||
|
await this.browser.func.goHome(this.homePage)
|
||||||
|
|
||||||
await this.browser.func.goHome(page)
|
const data = await this.browser.func.getDashboardData()
|
||||||
|
|
||||||
const data = await this.browser.func.getDashboardData(page)
|
|
||||||
|
|
||||||
// If no mobile searches data found, stop (Does not exist on new accounts)
|
// If no mobile searches data found, stop (Does not exist on new accounts)
|
||||||
if (!data.userStatus.counters.mobileSearch) {
|
if (!data.userStatus.counters.mobileSearch) {
|
||||||
log('MAIN', 'No mobile searches found, stopping')
|
log('MAIN', 'No mobile searches found, stopping!')
|
||||||
|
|
||||||
// Close mobile browser
|
// Close mobile browser
|
||||||
return await browser.close()
|
return await browser.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open a new tab to where the tasks are going to be completed
|
||||||
|
const workerPage = await browser.newPage()
|
||||||
|
|
||||||
|
// Go to homepage on worker page
|
||||||
|
await this.browser.func.goHome(workerPage)
|
||||||
|
|
||||||
// Do mobile searches
|
// Do mobile searches
|
||||||
if (this.config.workers.doMobileSearch) {
|
if (this.config.workers.doMobileSearch) {
|
||||||
await this.activities.doSearch(page, data, true)
|
await this.activities.doSearch(workerPage, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch new points
|
// Fetch new points
|
||||||
const earnablePoints = await this.browser.func.getEarnablePoints(data, page)
|
const earnablePoints = await this.browser.func.getEarnablePoints()
|
||||||
|
|
||||||
// If the new earnable is 0, means we got all the points, else retract
|
// If the new earnable is 0, means we got all the points, else retract
|
||||||
this.collectedPoints = earnablePoints === 0 ? this.collectedPoints : (this.collectedPoints - earnablePoints)
|
this.collectedPoints = earnablePoints === 0 ? this.collectedPoints : (this.collectedPoints - earnablePoints)
|
||||||
|
|||||||
@@ -32,4 +32,20 @@ export function loadConfig(): Config {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error as string)
|
throw new Error(error as string)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function loadSesion(sessionPath: string, email: string): Promise<string> {
|
||||||
|
try {
|
||||||
|
// Fetch path
|
||||||
|
const sessionDir = path.join(__dirname, '../browser/', sessionPath, email)
|
||||||
|
|
||||||
|
// Create session dir
|
||||||
|
if (!fs.existsSync(sessionDir)) {
|
||||||
|
await fs.promises.mkdir(sessionDir, { recursive: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
return sessionDir
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(error as string)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user