mirror of
https://github.com/TheNetsky/Microsoft-Rewards-Script.git
synced 2026-01-18 05:53:57 +00:00
Pre 1.3.0
This commit is contained in:
@@ -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> => {
|
||||
|
||||
@@ -20,11 +20,12 @@ export class Login {
|
||||
|
||||
try {
|
||||
// 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) {
|
||||
// Check if account is locked
|
||||
const isLocked = await page.waitForSelector('.serviceAbusePageContainer', { visible: true, timeout: 10_000 }).then(() => true).catch(() => false)
|
||||
if (isLocked) {
|
||||
this.bot.log('LOGIN', 'This account has been locked!', 'error')
|
||||
@@ -64,9 +65,11 @@ export class Login {
|
||||
await page.type('#i0118', password)
|
||||
await page.click('#idSIButton9')
|
||||
|
||||
// When erroring at this stage it means a 2FA code is required
|
||||
} catch (error) {
|
||||
this.bot.log('LOGIN', '2FA code required')
|
||||
|
||||
// Wait for user input
|
||||
const code = await new Promise<string>((resolve) => {
|
||||
rl.question('Enter 2FA code:\n', (input) => {
|
||||
rl.close()
|
||||
@@ -83,13 +86,13 @@ export class Login {
|
||||
|
||||
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)
|
||||
currentURL.href = page.url()
|
||||
}
|
||||
|
||||
// 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> {
|
||||
@@ -103,11 +106,11 @@ export class Login {
|
||||
const currentUrl = new URL(page.url())
|
||||
|
||||
if (currentUrl.hostname === 'www.bing.com' && currentUrl.pathname === '/') {
|
||||
await this.bot.utils.wait(3000)
|
||||
await this.bot.browser.utils.tryDismissBingCookieBanner(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!')
|
||||
break
|
||||
}
|
||||
@@ -123,7 +126,7 @@ export class Login {
|
||||
|
||||
private async checkBingLoginStatus(page: Page): Promise<boolean> {
|
||||
try {
|
||||
await page.waitForSelector('#id_n', { timeout: 10_000 })
|
||||
await page.waitForSelector('#id_n', { timeout: 5000 })
|
||||
return true
|
||||
} catch (error) {
|
||||
return false
|
||||
|
||||
@@ -92,6 +92,8 @@ export class Workers {
|
||||
|
||||
// Solve all the different types of activities
|
||||
private async solveActivities(page: Page, activities: PromotionalItem[] | MorePromotion[], punchCard?: PunchCard) {
|
||||
let activityPage = page
|
||||
|
||||
for (const activity of activities) {
|
||||
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
|
||||
await page.click(selector)
|
||||
|
||||
// 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.
|
||||
/*
|
||||
@@ -126,9 +125,7 @@ export class Workers {
|
||||
if it didn't then it gave enough time for the page to load.
|
||||
*/
|
||||
await activityPage.waitForNetworkIdle({ timeout: 10_000 }).catch(() => { })
|
||||
|
||||
// Cooldown
|
||||
await this.bot.utils.wait(4000)
|
||||
await this.bot.utils.wait(5000)
|
||||
|
||||
switch (activity.promotionType) {
|
||||
// Quiz (Poll, Quiz or ABC)
|
||||
@@ -175,8 +172,14 @@ export class Workers {
|
||||
|
||||
// Cooldown
|
||||
await this.bot.utils.wait(2000)
|
||||
|
||||
} catch (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)) {
|
||||
quizData = await this.bot.browser.func.getQuizData(page) // Refresh Quiz Data
|
||||
const correctOption = quizData.correctAnswer
|
||||
|
||||
@@ -12,19 +12,25 @@ export class Search extends Workers {
|
||||
|
||||
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')
|
||||
|
||||
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 edgeData = data.userStatus.counters.pcSearch[1] as DashboardImpression // Edge 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) :
|
||||
(edgeData.pointProgressMax - edgeData.pointProgress) + (genericData.pointProgressMax - genericData.pointProgress)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -35,31 +41,39 @@ export class Search extends Workers {
|
||||
// Deduplicate the search terms
|
||||
googleSearchQueries = [...new Set(googleSearchQueries)]
|
||||
|
||||
// Open a new tab
|
||||
const browser = page.browser()
|
||||
const searchPage = await browser.newPage()
|
||||
|
||||
// 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
|
||||
|
||||
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
|
||||
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: ${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 newEdgeData = newData.pcSearch[1] as DashboardImpression // Edge searches
|
||||
const newGenericData = newData.pcSearch[0] as DashboardImpression // Normal searches
|
||||
|
||||
const newMissingPoints = (mobile && newMobileData) ?
|
||||
const newMissingPoints = (this.bot.isMobile && newMobileData) ?
|
||||
(newMobileData.pointProgressMax - newMobileData.pointProgress) :
|
||||
(newEdgeData.pointProgressMax - newEdgeData.pointProgress) + (newGenericData.pointProgressMax - newGenericData.pointProgress)
|
||||
|
||||
@@ -97,14 +111,21 @@ 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: ${mobile}`)
|
||||
const newData = await this.bingSearch(page, searchPage, query.topic)
|
||||
this.bot.log('SEARCH-BING-EXTRA', `${missingPoints} Points Remaining | Query: ${term} | Mobile: ${this.bot.isMobile}`)
|
||||
|
||||
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 newEdgeData = newData.pcSearch[1] as DashboardImpression // Edge searches
|
||||
const newGenericData = newData.pcSearch[0] as DashboardImpression // Normal searches
|
||||
|
||||
const newMissingPoints = (mobile && newMobileData) ?
|
||||
const newMissingPoints = (this.bot.isMobile && newMobileData) ?
|
||||
(newMobileData.pointProgressMax - newMobileData.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)))
|
||||
|
||||
return await this.bot.browser.func.getSearchPoints(page)
|
||||
return await this.bot.browser.func.getSearchPoints()
|
||||
|
||||
} catch (error) {
|
||||
if (i === 5) {
|
||||
@@ -178,7 +199,7 @@ export class Search extends Workers {
|
||||
}
|
||||
|
||||
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[]> {
|
||||
@@ -211,7 +232,7 @@ export class Search extends Workers {
|
||||
for (const topic of data.default.trendingSearchesDays[0]?.trendingSearches ?? []) {
|
||||
queryTerms.push({
|
||||
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) {
|
||||
try {
|
||||
// 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')
|
||||
}
|
||||
|
||||
} catch (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 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
|
||||
if (!lastTab.isClosed()) {
|
||||
let lastTabURL = new URL(lastTab.url()) // Get new tab info
|
||||
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.
|
||||
let i = 0
|
||||
while (lastTabURL.href !== searchListingURL.href && i < 5) {
|
||||
// If hostname is still bing, (Bing images/news etc)
|
||||
if (lastTabURL.hostname == searchListingURL.hostname) {
|
||||
// Check if the URL is different from the original one, don't loop more than 5 times.
|
||||
let i = 0
|
||||
while (lastTabURL.href !== searchListingURL.href && i < 5) {
|
||||
// If hostname is still bing, (Bing images/news etc)
|
||||
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()
|
||||
|
||||
lastTab = await this.bot.browser.utils.getLatestTab(page) // Get last opened tab
|
||||
// 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
|
||||
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) {
|
||||
this.bot.log('SEARCH-RANDOM-CLICK', 'An error occurred:' + error, 'error')
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export class ThisOrThat extends Workers {
|
||||
async doThisOrThat(page: Page) {
|
||||
this.bot.log('THIS-OR-THAT', 'Trying to complete ThisOrThat')
|
||||
|
||||
return
|
||||
|
||||
try {
|
||||
// Check if the quiz has been started or not
|
||||
const quizNotStarted = await page.waitForSelector('#rqStartQuiz', { visible: true, timeout: 2000 }).then(() => true).catch(() => false)
|
||||
@@ -22,7 +22,20 @@ export class ThisOrThat extends Workers {
|
||||
|
||||
// Solving
|
||||
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')
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user