mirror of
https://github.com/TheNetsky/Microsoft-Rewards-Script.git
synced 2026-01-20 23:13:58 +00:00
1.5 inital (#234)
* 1.4.12 * Update README.md * Update package.json * Update package.json * 1.5 initial - Added parallel mode (experimental, likely no Docker supported) - Added chalk for clearer logging - Added support for "SearchOnBing" Activities - Added more configurable options for certain things - Redone some of the popup/banner clicking for searching (Redo the entire "popup" clicking, so they're more specifically targeted) - Axios proxy is now optional in the config - Fingerprint saving is now optional for desktop and mobile There needs to be many changes for Docker support, including parallel, the new config settings and general testing! This is still highly experimental, if you use Docker or want something more stable, use the version before this commit! * Add queries.json to build * fix(Login): update URL within authorization loop to reflect current page (#210) * Many changes - Updated Packages - Fixed mobile searches erroring out for dashboard data - Reworked "bad page" detection - Catching more errors - Reworked the search and "close tabs" - More fixes to the login - Fixed to paralell and clustering, thanks to @AariaX * Docker 1.5 preliminary support (#211) * Basic docker functionality for 1.5 Preliminary docker support for 1.5. Requires headless=true, clusters=1 * Tidy up timezone, add TZ to compose file Minor changes that should improve timezone handling, and (hopefully) improve scheduling function * updated readme to simplify and clarify docker instructions also removed env vars from table * Fix syntax for cron * Fix scheduling, add .gitattributes to normalize line endings fixed line endings caused by Windows in crontab.template and run_daily.sh, which were breaking cron and script execution in the Docker container. * Removed unnecessary scheduling key from config.json This key isn't necessary for docker or the base script. * Basic docker functionality for 1.5 Preliminary docker support for 1.5. Requires headless=true, clusters=1 Tidied up timezone, add TZ to compose file Minor changes that should improve timezone handling, and (hopefully) improve scheduling function updated readme to simplify and clarify docker instructions also removed env vars from table Fixed syntax for cron Fixed scheduling, add .gitattributes to normalize line endings Fixed line endings caused by Windows in crontab.template and run_daily.sh, which were breaking cron and script execution in the Docker container. Removed unnecessary scheduling key from config.json This key isn't necessary for docker or the base script. * Improve scheduling handling, show logs in console Fixes scheduling when RUN_ON_START=true, and fixes scheduled runs not appearing in docker logs. * Update compose.yaml revert service and container name, revert volumes for better generalization, add tips to environment to set scheduling, timezone and whether to run on container start * Update README.md proper container name Co-authored-by: AariaX <196196201+AariaX@users.noreply.github.com> --------- Co-authored-by: AariaX <196196201+AariaX@users.noreply.github.com> * Fixes - Reworked some of the point counting - Reverted back to the "playwright" package - Fixed error throw for emailPrefill * Update config.json * Add pre-build script * Update package.json * Handle 2FA in parallel mode (#219) * catch error in reloadBadPage (#220) * Use pre-build and simplify dockerfile (#218) This uses the new pre-build script included in package.json to handle deps greatly simplifying the dockerfile. * Small improvements * Small fixes - Fixed log spam for "Waiting for authorization" - Increased wait from 2 to 5 seconds - Increased search to "safer" values for default * Experimenting with selectors Seeing #223 I want to try if this is a good new addition, since for most user this SHOULD work just as good as clicking the entire box. * More stuff - Added ability to exclude logs by their function name - Now caching config settings * fix: don't retry on 0 (#228) * Improvements - Check if searches for mobile are enabled before creating the new page in the browser - Return message if mobile search data cannot be found - Added more selectors for coupons * Improve Popup Dismissal - Now executes in Parallel - Respects a timeout of 1 second --------- Co-authored-by: AariaX <196196201+AariaX@users.noreply.github.com> Co-authored-by: mgrimace <55518507+mgrimace@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Page } from 'playwright'
|
||||
import { Page } from 'rebrowser-playwright'
|
||||
|
||||
import { Workers } from '../Workers'
|
||||
|
||||
@@ -6,10 +6,10 @@ import { Workers } from '../Workers'
|
||||
export class ABC extends Workers {
|
||||
|
||||
async doABC(page: Page) {
|
||||
this.bot.log('ABC', 'Trying to complete poll')
|
||||
this.bot.log(this.bot.isMobile, 'ABC', 'Trying to complete poll')
|
||||
|
||||
try {
|
||||
let $ = await this.bot.browser.func.refreshCheerio(page)
|
||||
let $ = await this.bot.browser.func.loadInCheerio(page)
|
||||
|
||||
// Don't loop more than 15 in case unable to solve, would lock otherwise
|
||||
const maxIterations = 15
|
||||
@@ -30,7 +30,7 @@ export class ABC extends Workers {
|
||||
await page.click('div.wk_button') // Click next question button
|
||||
|
||||
page = await this.bot.browser.utils.getLatestTab(page)
|
||||
$ = await this.bot.browser.func.refreshCheerio(page)
|
||||
$ = await this.bot.browser.func.loadInCheerio(page)
|
||||
await this.bot.utils.wait(1000)
|
||||
}
|
||||
|
||||
@@ -38,14 +38,14 @@ export class ABC extends Workers {
|
||||
await page.close()
|
||||
|
||||
if (i === maxIterations) {
|
||||
this.bot.log('ABC', 'Failed to solve quiz, exceeded max iterations of 15', 'warn')
|
||||
this.bot.log(this.bot.isMobile, 'ABC', 'Failed to solve quiz, exceeded max iterations of 15', 'warn')
|
||||
} else {
|
||||
this.bot.log('ABC', 'Completed the ABC successfully')
|
||||
this.bot.log(this.bot.isMobile, 'ABC', 'Completed the ABC successfully')
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
await page.close()
|
||||
this.bot.log('ABC', 'An error occurred:' + error, 'error')
|
||||
this.bot.log(this.bot.isMobile, 'ABC', 'An error occurred:' + error, 'error')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import axios from 'axios'
|
||||
import { randomBytes } from 'crypto'
|
||||
import { AxiosRequestConfig } from 'axios'
|
||||
|
||||
import { Workers } from '../Workers'
|
||||
|
||||
@@ -8,7 +8,7 @@ import { DashboardData } from '../../interface/DashboardData'
|
||||
|
||||
export class DailyCheckIn extends Workers {
|
||||
public async doDailyCheckIn(accessToken: string, data: DashboardData) {
|
||||
this.bot.log('DAILY-CHECK-IN', 'Starting Daily Check In')
|
||||
this.bot.log(this.bot.isMobile, 'DAILY-CHECK-IN', 'Starting Daily Check In')
|
||||
|
||||
try {
|
||||
let geoLocale = data.userProfile.attributes.country
|
||||
@@ -24,7 +24,7 @@ export class DailyCheckIn extends Workers {
|
||||
}
|
||||
}
|
||||
|
||||
const claimRequest = {
|
||||
const claimRequest: AxiosRequestConfig = {
|
||||
url: 'https://prod.rewardsplatform.microsoft.com/dapi/me/activities',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -36,12 +36,12 @@ export class DailyCheckIn extends Workers {
|
||||
data: JSON.stringify(jsonData)
|
||||
}
|
||||
|
||||
const claimResponse = await axios(claimRequest)
|
||||
const claimedPoint = parseInt((await claimResponse.data).response.activity.p)
|
||||
const claimResponse = await this.bot.axios.request(claimRequest)
|
||||
const claimedPoint = parseInt((await claimResponse.data).response?.activity?.p) ?? 0
|
||||
|
||||
this.bot.log('DAILY-CHECK-IN', claimedPoint > 0 ? `Claimed ${claimedPoint} points` : 'Already claimed today')
|
||||
this.bot.log(this.bot.isMobile, 'DAILY-CHECK-IN', claimedPoint > 0 ? `Claimed ${claimedPoint} points` : 'Already claimed today')
|
||||
} catch (error) {
|
||||
this.bot.log('DAILY-CHECK-IN', 'An error occurred:' + error, 'error')
|
||||
this.bot.log(this.bot.isMobile, 'DAILY-CHECK-IN', 'An error occurred:' + error, 'error')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Page } from 'playwright'
|
||||
import { Page } from 'rebrowser-playwright'
|
||||
|
||||
import { Workers } from '../Workers'
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Workers } from '../Workers'
|
||||
export class Poll extends Workers {
|
||||
|
||||
async doPoll(page: Page) {
|
||||
this.bot.log('POLL', 'Trying to complete poll')
|
||||
this.bot.log(this.bot.isMobile, 'POLL', 'Trying to complete poll')
|
||||
|
||||
try {
|
||||
const buttonId = `#btoption${Math.floor(this.bot.utils.randomNumber(0, 1))}`
|
||||
@@ -19,10 +19,10 @@ export class Poll extends Workers {
|
||||
await this.bot.utils.wait(4000)
|
||||
await page.close()
|
||||
|
||||
this.bot.log('POLL', 'Completed the poll successfully')
|
||||
this.bot.log(this.bot.isMobile, 'POLL', 'Completed the poll successfully')
|
||||
} catch (error) {
|
||||
await page.close()
|
||||
this.bot.log('POLL', 'An error occurred:' + error, 'error')
|
||||
this.bot.log(this.bot.isMobile, 'POLL', 'An error occurred:' + error, 'error')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Page } from 'playwright'
|
||||
import { Page } from 'rebrowser-playwright'
|
||||
|
||||
import { Workers } from '../Workers'
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Workers } from '../Workers'
|
||||
export class Quiz extends Workers {
|
||||
|
||||
async doQuiz(page: Page) {
|
||||
this.bot.log('QUIZ', 'Trying to complete quiz')
|
||||
this.bot.log(this.bot.isMobile, 'QUIZ', 'Trying to complete quiz')
|
||||
|
||||
try {
|
||||
// Check if the quiz has been started or not
|
||||
@@ -14,7 +14,7 @@ export class Quiz extends Workers {
|
||||
if (quizNotStarted) {
|
||||
await page.click('#rqStartQuiz')
|
||||
} else {
|
||||
this.bot.log('QUIZ', 'Quiz has already been started, trying to finish it')
|
||||
this.bot.log(this.bot.isMobile, 'QUIZ', 'Quiz has already been started, trying to finish it')
|
||||
}
|
||||
|
||||
await this.bot.utils.wait(2000)
|
||||
@@ -47,7 +47,7 @@ export class Quiz extends Workers {
|
||||
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')
|
||||
this.bot.log(this.bot.isMobile, 'QUIZ', 'An error occurred, refresh was unsuccessful', 'error')
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ export class Quiz extends Workers {
|
||||
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')
|
||||
this.bot.log(this.bot.isMobile, 'QUIZ', 'An error occurred, refresh was unsuccessful', 'error')
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -81,10 +81,11 @@ export class Quiz extends Workers {
|
||||
// Done with
|
||||
await this.bot.utils.wait(2000)
|
||||
await page.close()
|
||||
this.bot.log('QUIZ', 'Completed the quiz successfully')
|
||||
|
||||
this.bot.log(this.bot.isMobile, 'QUIZ', 'Completed the quiz successfully')
|
||||
} catch (error) {
|
||||
await page.close()
|
||||
this.bot.log('QUIZ', 'An error occurred:' + error, 'error')
|
||||
this.bot.log(this.bot.isMobile, 'QUIZ', 'An error occurred:' + error, 'error')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import axios from 'axios'
|
||||
import { randomBytes } from 'crypto'
|
||||
import { AxiosRequestConfig } from 'axios'
|
||||
|
||||
import { Workers } from '../Workers'
|
||||
|
||||
@@ -8,13 +8,13 @@ import { DashboardData } from '../../interface/DashboardData'
|
||||
|
||||
export class ReadToEarn extends Workers {
|
||||
public async doReadToEarn(accessToken: string, data: DashboardData) {
|
||||
this.bot.log('READ-TO-EARN', 'Starting Read to Earn')
|
||||
this.bot.log(this.bot.isMobile, 'READ-TO-EARN', 'Starting Read to Earn')
|
||||
|
||||
try {
|
||||
let geoLocale = data.userProfile.attributes.country
|
||||
geoLocale = (this.bot.config.searchSettings.useGeoLocaleQueries && geoLocale.length === 2) ? geoLocale.toLowerCase() : 'us'
|
||||
|
||||
const userDataRequest = {
|
||||
const userDataRequest: AxiosRequestConfig = {
|
||||
url: 'https://prod.rewardsplatform.microsoft.com/dapi/me',
|
||||
method: 'GET',
|
||||
headers: {
|
||||
@@ -23,7 +23,7 @@ export class ReadToEarn extends Workers {
|
||||
'X-Rewards-Language': 'en'
|
||||
}
|
||||
}
|
||||
const userDataResponse = await axios(userDataRequest)
|
||||
const userDataResponse = await this.bot.axios.request(userDataRequest)
|
||||
const userData = (await userDataResponse.data).response
|
||||
let userBalance = userData.balance
|
||||
|
||||
@@ -52,22 +52,22 @@ export class ReadToEarn extends Workers {
|
||||
data: JSON.stringify(jsonData)
|
||||
}
|
||||
|
||||
const claimResponse = await axios(claimRequest)
|
||||
const claimResponse = await this.bot.axios.request(claimRequest)
|
||||
const newBalance = (await claimResponse.data).response.balance
|
||||
|
||||
if (newBalance == userBalance) {
|
||||
this.bot.log('READ-TO-EARN', 'Read all available articles')
|
||||
this.bot.log(this.bot.isMobile, 'READ-TO-EARN', 'Read all available articles')
|
||||
break
|
||||
} else {
|
||||
this.bot.log('READ-TO-EARN', `Read article ${i + 1} of ${articleCount} max | Gained ${newBalance - userBalance} Points`)
|
||||
this.bot.log(this.bot.isMobile, 'READ-TO-EARN', `Read article ${i + 1} of ${articleCount} max | Gained ${newBalance - userBalance} Points`)
|
||||
userBalance = newBalance
|
||||
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.utils.stringToMs(this.bot.config.searchSettings.searchDelay.min), this.bot.utils.stringToMs(this.bot.config.searchSettings.searchDelay.max))))
|
||||
}
|
||||
}
|
||||
|
||||
this.bot.log('READ-TO-EARN', 'Completed Read to Earn')
|
||||
this.bot.log(this.bot.isMobile, 'READ-TO-EARN', 'Completed Read to Earn')
|
||||
} catch (error) {
|
||||
this.bot.log('READ-TO-EARN', 'An error occurred:' + error, 'error')
|
||||
this.bot.log(this.bot.isMobile, 'READ-TO-EARN', 'An error occurred:' + error, 'error')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Page } from 'playwright'
|
||||
import axios from 'axios'
|
||||
import { Page } from 'rebrowser-playwright'
|
||||
import { platform } from 'os'
|
||||
|
||||
import { Workers } from '../Workers'
|
||||
@@ -14,7 +13,7 @@ export class Search extends Workers {
|
||||
private searchPageURL = ''
|
||||
|
||||
public async doSearch(page: Page, data: DashboardData) {
|
||||
this.bot.log('SEARCH-BING', 'Starting Bing searches')
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-BING', 'Starting Bing searches')
|
||||
|
||||
page = await this.bot.browser.utils.getLatestTab(page)
|
||||
|
||||
@@ -22,7 +21,7 @@ export class Search extends Workers {
|
||||
let missingPoints = this.calculatePoints(searchCounters)
|
||||
|
||||
if (missingPoints === 0) {
|
||||
this.bot.log('SEARCH-BING', `Bing searches for ${this.bot.isMobile ? 'MOBILE' : 'DESKTOP'} have already been completed`)
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-BING', 'Bing searches have already been completed')
|
||||
return
|
||||
}
|
||||
|
||||
@@ -36,19 +35,21 @@ export class Search extends Workers {
|
||||
// Go to bing
|
||||
await page.goto(this.searchPageURL ? this.searchPageURL : this.bingHome)
|
||||
|
||||
await this.bot.utils.wait(2000)
|
||||
|
||||
await this.bot.browser.utils.tryDismissAllMessages(page)
|
||||
|
||||
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[] = []
|
||||
// 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) })
|
||||
|
||||
await this.bot.browser.utils.tryDismissBingCookieBanner(page)
|
||||
|
||||
// Loop over Google search queries
|
||||
for (let i = 0; i < queries.length; i++) {
|
||||
const query = queries[i] as string
|
||||
|
||||
this.bot.log('SEARCH-BING', `${missingPoints} Points Remaining | Query: ${query} | Mobile: ${this.bot.isMobile}`)
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-BING', `${missingPoints} Points Remaining | Query: ${query}`)
|
||||
|
||||
searchCounters = await this.bingSearch(page, query)
|
||||
const newMissingPoints = this.calculatePoints(searchCounters)
|
||||
@@ -67,14 +68,14 @@ export class Search extends Workers {
|
||||
}
|
||||
|
||||
// Only for mobile searches
|
||||
if (maxLoop > 3 && this.bot.isMobile) {
|
||||
this.bot.log('SEARCH-BING-MOBILE', 'Search didn\'t gain point for 3 iterations, likely bad User-Agent', 'warn')
|
||||
if (maxLoop > 5 && this.bot.isMobile) {
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-BING', 'Search didn\'t gain point for 5 iterations, likely bad User-Agent', 'warn')
|
||||
break
|
||||
}
|
||||
|
||||
// If we didn't gain points for 10 iterations, assume it's stuck
|
||||
if (maxLoop > 10) {
|
||||
this.bot.log('SEARCH-BING', 'Search didn\'t gain point for 10 iterations aborting searches', 'warn')
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-BING', 'Search didn\'t gain point for 10 iterations aborting searches', 'warn')
|
||||
maxLoop = 0 // Reset to 0 so we can retry with related searches below
|
||||
break
|
||||
}
|
||||
@@ -87,7 +88,7 @@ export class Search extends Workers {
|
||||
|
||||
// If we still got remaining search queries, generate extra ones
|
||||
if (missingPoints > 0) {
|
||||
this.bot.log('SEARCH-BING', `Search completed but we're missing ${missingPoints} points, generating extra searches`)
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-BING', `Search completed but we're missing ${missingPoints} points, generating extra searches`)
|
||||
|
||||
let i = 0
|
||||
while (missingPoints > 0) {
|
||||
@@ -98,7 +99,7 @@ export class Search extends Workers {
|
||||
if (relatedTerms.length > 3) {
|
||||
// Search for the first 2 related terms
|
||||
for (const term of relatedTerms.slice(1, 3)) {
|
||||
this.bot.log('SEARCH-BING-EXTRA', `${missingPoints} Points Remaining | Query: ${term} | Mobile: ${this.bot.isMobile}`)
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-BING-EXTRA', `${missingPoints} Points Remaining | Query: ${term}`)
|
||||
|
||||
searchCounters = await this.bingSearch(page, term)
|
||||
const newMissingPoints = this.calculatePoints(searchCounters)
|
||||
@@ -119,7 +120,7 @@ export class Search extends Workers {
|
||||
|
||||
// Try 5 more times, then we tried a total of 15 times, fair to say it's stuck
|
||||
if (maxLoop > 5) {
|
||||
this.bot.log('SEARCH-BING-EXTRA', 'Search didn\'t gain point for 5 iterations aborting searches', 'warn')
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-BING-EXTRA', 'Search didn\'t gain point for 5 iterations aborting searches', 'warn')
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -127,7 +128,7 @@ export class Search extends Workers {
|
||||
}
|
||||
}
|
||||
|
||||
this.bot.log('SEARCH-BING', 'Completed searches')
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-BING', 'Completed searches')
|
||||
}
|
||||
|
||||
private async bingSearch(searchPage: Page, query: string) {
|
||||
@@ -157,12 +158,14 @@ export class Search extends Workers {
|
||||
await searchPage.keyboard.type(query)
|
||||
await searchPage.keyboard.press('Enter')
|
||||
|
||||
await this.bot.utils.wait(1000)
|
||||
await this.bot.utils.wait(3000)
|
||||
|
||||
// Bing.com in Chrome opens a new tab when searching
|
||||
const resultPage = await this.bot.browser.utils.getLatestTab(searchPage)
|
||||
this.searchPageURL = new URL(resultPage.url()).href // Set the results page
|
||||
|
||||
await this.bot.browser.utils.reloadBadPage(resultPage)
|
||||
|
||||
if (this.bot.config.searchSettings.scrollRandomResults) {
|
||||
await this.bot.utils.wait(2000)
|
||||
await this.randomScroll(resultPage)
|
||||
@@ -174,19 +177,19 @@ export class Search extends Workers {
|
||||
}
|
||||
|
||||
// Delay between searches
|
||||
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.utils.stringToMs(this.bot.config.searchSettings.searchDelay.min), this.bot.utils.stringToMs(this.bot.config.searchSettings.searchDelay.max))))
|
||||
|
||||
return await this.bot.browser.func.getSearchPoints()
|
||||
|
||||
} catch (error) {
|
||||
if (i === 5) {
|
||||
this.bot.log('SEARCH-BING', 'Failed after 5 retries... An error occurred:' + error, 'error')
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-BING', 'Failed after 5 retries... An error occurred:' + error, 'error')
|
||||
break
|
||||
|
||||
}
|
||||
|
||||
this.bot.log('SEARCH-BING', 'Search failed, An error occurred:' + error, 'error')
|
||||
this.bot.log('SEARCH-BING', `Retrying search, attempt ${i}/5`, 'warn')
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-BING', 'Search failed, An error occurred:' + error, 'error')
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-BING', `Retrying search, attempt ${i}/5`, 'warn')
|
||||
|
||||
// Reset the tabs
|
||||
const lastTab = await this.bot.browser.utils.getLatestTab(searchPage)
|
||||
@@ -196,7 +199,7 @@ export class Search extends Workers {
|
||||
}
|
||||
}
|
||||
|
||||
this.bot.log('SEARCH-BING', 'Search failed after 5 retries, ending', 'error')
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-BING', 'Search failed after 5 retries, ending', 'error')
|
||||
return await this.bot.browser.func.getSearchPoints()
|
||||
}
|
||||
|
||||
@@ -206,7 +209,7 @@ export class Search extends Workers {
|
||||
|
||||
geoLocale = (this.bot.config.searchSettings.useGeoLocaleQueries && geoLocale.length === 2) ? geoLocale.toUpperCase() : 'US'
|
||||
|
||||
this.bot.log('SEARCH-GOOGLE-TRENDS', `Generating search queries, can take a while! | GeoLocale: ${geoLocale}`)
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-GOOGLE-TRENDS', `Generating search queries, can take a while! | GeoLocale: ${geoLocale}`)
|
||||
|
||||
while (queryCount > queryTerms.length) {
|
||||
i += 1
|
||||
@@ -223,7 +226,7 @@ export class Search extends Workers {
|
||||
}
|
||||
}
|
||||
|
||||
const response = await axios(request)
|
||||
const response = await this.bot.axios.request(request)
|
||||
|
||||
const data: GoogleTrends = JSON.parse((await response.data).slice(5))
|
||||
|
||||
@@ -235,7 +238,8 @@ export class Search extends Workers {
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
this.bot.log('SEARCH-GOOGLE-TRENDS', 'An error occurred:' + error, 'error')
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-GOOGLE-TRENDS', 'An error occurred:' + error, 'error')
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,12 +256,13 @@ export class Search extends Workers {
|
||||
}
|
||||
}
|
||||
|
||||
const response = await axios(request)
|
||||
const response = await this.bot.axios.request(request)
|
||||
|
||||
return response.data[1] as string[]
|
||||
} catch (error) {
|
||||
this.bot.log('SEARCH-BING-RELATED', 'An error occurred:' + error, 'error')
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-BING-RELATED', 'An error occurred:' + error, 'error')
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
@@ -280,7 +285,7 @@ export class Search extends Workers {
|
||||
}, randomScrollPosition)
|
||||
|
||||
} catch (error) {
|
||||
this.bot.log('SEARCH-RANDOM-SCROLL', 'An error occurred:' + error, 'error')
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-RANDOM-SCROLL', 'An error occurred:' + error, 'error')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,6 +293,9 @@ export class Search extends Workers {
|
||||
try {
|
||||
await page.click('#b_results .b_algo h2', { timeout: 2000 }).catch(() => { }) // Since we don't really care if it did it or not
|
||||
|
||||
// Only used if the browser is not the edge browser (continue on Edge popup)
|
||||
await this.closeContinuePopup(page)
|
||||
|
||||
// Stay for 10 seconds for page to load and "visit"
|
||||
await this.bot.utils.wait(10_000)
|
||||
|
||||
@@ -309,7 +317,7 @@ export class Search extends Workers {
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
this.bot.log('SEARCH-RANDOM-CLICK', 'An error occurred:' + error, 'error')
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-RANDOM-CLICK', 'An error occurred:' + error, 'error')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,23 +325,35 @@ export class Search extends Workers {
|
||||
const browser = lastTab.context()
|
||||
const tabs = browser.pages()
|
||||
|
||||
// If more than 2 tabs are open, close the last tab
|
||||
if (tabs.length > 2) {
|
||||
await lastTab.close()
|
||||
try {
|
||||
if (tabs.length > 2) {
|
||||
// If more than 2 tabs are open, close the last tab
|
||||
|
||||
// If only 1 tab is open, open a new one to search in
|
||||
} else if (tabs.length === 1) {
|
||||
const newPage = await browser.newPage()
|
||||
await this.bot.utils.wait(1000)
|
||||
await newPage.goto(this.bingHome)
|
||||
await this.bot.utils.wait(3000)
|
||||
this.searchPageURL = newPage.url()
|
||||
await lastTab.close()
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-CLOSE-TABS', `More than 2 were open, closed the last tab: "${new URL(lastTab.url()).host}"`)
|
||||
|
||||
// Else reset the last tab back to the search listing or Bing.com
|
||||
} else {
|
||||
lastTab = await this.bot.browser.utils.getLatestTab(lastTab)
|
||||
await lastTab.goto(this.searchPageURL ? this.searchPageURL : this.bingHome)
|
||||
} else if (tabs.length === 1) {
|
||||
// If only 1 tab is open, open a new one to search in
|
||||
|
||||
const newPage = await browser.newPage()
|
||||
await this.bot.utils.wait(1000)
|
||||
|
||||
await newPage.goto(this.bingHome)
|
||||
await this.bot.utils.wait(3000)
|
||||
this.searchPageURL = newPage.url()
|
||||
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-CLOSE-TABS', 'There was only 1 tab open, crated a new one')
|
||||
} else {
|
||||
// Else reset the last tab back to the search listing or Bing.com
|
||||
|
||||
lastTab = await this.bot.browser.utils.getLatestTab(lastTab)
|
||||
await lastTab.goto(this.searchPageURL ? this.searchPageURL : this.bingHome)
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-CLOSE-TABS', 'An error occurred:' + error, 'error')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private calculatePoints(counters: Counters) {
|
||||
@@ -348,4 +368,18 @@ export class Search extends Workers {
|
||||
|
||||
return missingPoints
|
||||
}
|
||||
}
|
||||
|
||||
private async closeContinuePopup(page: Page) {
|
||||
try {
|
||||
await page.waitForSelector('#sacs_close', { timeout: 1000 })
|
||||
const continueButton = await page.$('#sacs_close')
|
||||
|
||||
if (continueButton) {
|
||||
await continueButton.click()
|
||||
}
|
||||
} catch (error) {
|
||||
// Continue if element is not found or other error occurs
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
75
src/functions/activities/SearchOnBing.ts
Normal file
75
src/functions/activities/SearchOnBing.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { Page } from 'rebrowser-playwright'
|
||||
import * as fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import { Workers } from '../Workers'
|
||||
|
||||
import { MorePromotion, PromotionalItem } from '../../interface/DashboardData'
|
||||
|
||||
|
||||
export class SearchOnBing extends Workers {
|
||||
|
||||
async doSearchOnBing(page: Page, activity: MorePromotion | PromotionalItem) {
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-ON-BING', 'Trying to complete SearchOnBing')
|
||||
|
||||
try {
|
||||
await this.bot.utils.wait(5000)
|
||||
|
||||
await this.bot.browser.utils.tryDismissAllMessages(page)
|
||||
|
||||
const query = await this.getSearchQuery(activity.title)
|
||||
|
||||
const searchBar = '#sb_form_q'
|
||||
await page.waitForSelector(searchBar, { state: 'visible', timeout: 10_000 })
|
||||
await page.click(searchBar)
|
||||
await this.bot.utils.wait(500)
|
||||
await page.keyboard.type(query)
|
||||
await page.keyboard.press('Enter')
|
||||
await this.bot.utils.wait(3000)
|
||||
|
||||
await page.close()
|
||||
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-ON-BING', 'Completed the SearchOnBing successfully')
|
||||
} catch (error) {
|
||||
await page.close()
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-ON-BING', 'An error occurred:' + error, 'error')
|
||||
}
|
||||
}
|
||||
|
||||
private async getSearchQuery(title: string): Promise<string> {
|
||||
interface Queries {
|
||||
title: string;
|
||||
queries: string[]
|
||||
}
|
||||
|
||||
let queries: Queries[] = []
|
||||
|
||||
try {
|
||||
if (this.bot.config.searchOnBingLocalQueries) {
|
||||
const data = fs.readFileSync(path.join(__dirname, '../queries.json'), 'utf8')
|
||||
queries = JSON.parse(data)
|
||||
} else {
|
||||
// Fetch from the repo directly so the user doesn't need to redownload the script for the new activities
|
||||
const response = await this.bot.axios.request({
|
||||
method: 'GET',
|
||||
url: 'https://raw.githubusercontent.com/TheNetsky/Microsoft-Rewards-Script/refs/heads/main/src/functions/queries.json'
|
||||
})
|
||||
queries = response.data
|
||||
}
|
||||
|
||||
const answers = queries.find(x => this.normalizeString(x.title) === this.normalizeString(title))
|
||||
const answer = answers ? this.bot.utils.shuffleArray(answers?.queries)[0] as string : title
|
||||
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-ON-BING-QUERY', `Fetched answer: ${answer} | question: ${title}`)
|
||||
return answer
|
||||
|
||||
} catch (error) {
|
||||
this.bot.log(this.bot.isMobile, 'SEARCH-ON-BING-QUERY', 'An error occurred:' + error, 'error')
|
||||
return title
|
||||
}
|
||||
}
|
||||
|
||||
private normalizeString(string: string): string {
|
||||
return string.normalize('NFD').trim().toLowerCase().replace(/[^\x20-\x7E]/g, '').replace(/[?!]/g, '')
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Page } from 'playwright'
|
||||
import { Page } from 'rebrowser-playwright'
|
||||
|
||||
import { Workers } from '../Workers'
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Workers } from '../Workers'
|
||||
export class ThisOrThat extends Workers {
|
||||
|
||||
async doThisOrThat(page: Page) {
|
||||
this.bot.log('THIS-OR-THAT', 'Trying to complete ThisOrThat')
|
||||
this.bot.log(this.bot.isMobile, 'THIS-OR-THAT', 'Trying to complete ThisOrThat')
|
||||
|
||||
|
||||
try {
|
||||
@@ -15,7 +15,7 @@ export class ThisOrThat extends Workers {
|
||||
if (quizNotStarted) {
|
||||
await page.click('#rqStartQuiz')
|
||||
} else {
|
||||
this.bot.log('THIS-OR-THAT', 'ThisOrThat has already been started, trying to finish it')
|
||||
this.bot.log(this.bot.isMobile, 'THIS-OR-THAT', 'ThisOrThat has already been started, trying to finish it')
|
||||
}
|
||||
|
||||
await this.bot.utils.wait(2000)
|
||||
@@ -32,15 +32,15 @@ export class ThisOrThat extends Workers {
|
||||
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')
|
||||
this.bot.log(this.bot.isMobile, 'QUIZ', 'An error occurred, refresh was unsuccessful', 'error')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.bot.log('THIS-OR-THAT', 'Completed the ThisOrThat successfully')
|
||||
this.bot.log(this.bot.isMobile, 'THIS-OR-THAT', 'Completed the ThisOrThat successfully')
|
||||
} catch (error) {
|
||||
await page.close()
|
||||
this.bot.log('THIS-OR-THAT', 'An error occurred:' + error, 'error')
|
||||
this.bot.log(this.bot.isMobile, 'THIS-OR-THAT', 'An error occurred:' + error, 'error')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Page } from 'playwright'
|
||||
import { Page } from 'rebrowser-playwright'
|
||||
|
||||
import { Workers } from '../Workers'
|
||||
|
||||
@@ -6,17 +6,17 @@ import { Workers } from '../Workers'
|
||||
export class UrlReward extends Workers {
|
||||
|
||||
async doUrlReward(page: Page) {
|
||||
this.bot.log('URL-REWARD', 'Trying to complete UrlReward')
|
||||
this.bot.log(this.bot.isMobile, 'URL-REWARD', 'Trying to complete UrlReward')
|
||||
|
||||
try {
|
||||
this.bot.utils.wait(2000)
|
||||
|
||||
await page.close()
|
||||
|
||||
this.bot.log('URL-REWARD', 'Completed the UrlReward successfully')
|
||||
this.bot.log(this.bot.isMobile, 'URL-REWARD', 'Completed the UrlReward successfully')
|
||||
} catch (error) {
|
||||
await page.close()
|
||||
this.bot.log('URL-REWARD', 'An error occurred:' + error, 'error')
|
||||
this.bot.log(this.bot.isMobile, 'URL-REWARD', 'An error occurred:' + error, 'error')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user