diff --git a/package.json b/package.json index faa6b61..362bfd2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "microsoft-rewards-script", - "version": "1.0.2", + "version": "1.0.3", "description": "Automatically do tasks for Microsoft Rewards but in TS", "main": "index.js", "scripts": { diff --git a/src/BrowserFunc.ts b/src/BrowserFunc.ts index 03c35c8..0b0cc9b 100644 --- a/src/BrowserFunc.ts +++ b/src/BrowserFunc.ts @@ -10,7 +10,7 @@ import { log } from './util/Logger' import { Counters, DashboardData } from './interface/DashboardData' import { QuizData } from './interface/QuizData' -export async function goHome(page: Page): Promise { +export async function goHome(page: Page): Promise { try { const dashboardURL = new URL(baseURL) @@ -23,6 +23,13 @@ export async function goHome(page: Page): Promise { await wait(3000) await tryDismissCookieBanner(page) + // Check if account is suspended + const isSuspended = await page.waitForSelector('#suspendedAccountHeader', { visible: true, timeout: 3000 }).then(() => true).catch(() => false) + if (isSuspended) { + log('GO-HOME', 'This account is suspended!') + throw new Error('Account has been suspended!') + } + try { // If activities are found, exit the loop await page.waitForSelector('#more-activities', { timeout: 1000 }) @@ -47,7 +54,10 @@ export async function goHome(page: Page): Promise { } catch (error) { console.error('An error occurred:', error) + return false } + + return true } export async function getDashboardData(page: Page): Promise { diff --git a/src/config.json b/src/config.json index 0c8f4a6..fcfa0d1 100644 --- a/src/config.json +++ b/src/config.json @@ -5,10 +5,12 @@ "runOnZeroPoints": false, "searches": { "doMobile": true, - "doDesktop": true + "doDesktop": true, + "scrollRandomResults": true, + "clickRandomResults": true }, "webhook": { - "enabled": true, + "enabled": false, "url": "" } } \ No newline at end of file diff --git a/src/functions/activities/Quiz.ts b/src/functions/activities/Quiz.ts index a03e2b1..75832d0 100644 --- a/src/functions/activities/Quiz.ts +++ b/src/functions/activities/Quiz.ts @@ -84,6 +84,7 @@ export async function doQuiz(page: Page, data: PromotionalItem | MorePromotion) } } } + await wait(2000) } diff --git a/src/functions/activities/Search.ts b/src/functions/activities/Search.ts index fb62454..673a32e 100644 --- a/src/functions/activities/Search.ts +++ b/src/functions/activities/Search.ts @@ -2,11 +2,14 @@ import { Page } from 'puppeteer' import axios from 'axios' import { log } from '../../util/Logger' -import { wait } from '../../util/Utils' +import { shuffleArray, wait } from '../../util/Utils' import { getSearchPoints } from '../../BrowserFunc' +import { searches } from '../../config.json' + import { DashboardData, DashboardImpression } from '../../interface/DashboardData' import { GoogleTrends } from '../../interface/GoogleDailyTrends' +import { GoogleSearch } from '../../interface/Search' export async function doSearch(page: Page, data: DashboardData, mobile: boolean) { const locale = await page.evaluate(() => { @@ -29,8 +32,11 @@ export async function doSearch(page: Page, data: DashboardData, mobile: boolean) } // Generate search queries - const googleSearchQueries = await getGoogleTrends(locale, missingPoints) - //const googleSearchQueries = shuffleArray(await getGoogleTrends(locale, missingPoints)) + let googleSearchQueries = await getGoogleTrends(locale, missingPoints) as GoogleSearch[] + googleSearchQueries = shuffleArray(googleSearchQueries) + + // Deduplicate the search terms + googleSearchQueries = [...new Set(googleSearchQueries)] // Open a new tab const browser = page.browser() @@ -41,9 +47,12 @@ export async function doSearch(page: Page, data: DashboardData, mobile: boolean) let maxLoop = 0 // If the loop hits 20 this when not gaining any points, we're assuming it's stuck. + const queries: string[] = [] + googleSearchQueries.forEach(x => queries.push(x.topic, ...x.related)) + // Loop over Google search queries - for (let i = 0; i < googleSearchQueries.length; i++) { - const query = googleSearchQueries[i] as string + for (let i = 0; i < queries.length; i++) { + const query = queries[i] as string log('SEARCH-BING', `${missingPoints} Points Remaining | Query: ${query} | Mobile: ${mobile}`) @@ -83,15 +92,15 @@ export async function doSearch(page: Page, data: DashboardData, mobile: boolean) let i = 0 while (missingPoints > 0) { - const query = googleSearchQueries[i++] as string + const query = googleSearchQueries[i++] as GoogleSearch // Get related search terms to the Google search queries - const relatedTerms = await getRelatedTerms(query) + const relatedTerms = await getRelatedTerms(query?.topic) if (relatedTerms.length > 3) { // Search for the first 2 related terms for (const term of relatedTerms.slice(1, 3)) { log('SEARCH-BING-EXTRA', `${missingPoints} Points Remaining | Query: ${term} | Mobile: ${mobile}`) - const newData = await bingSearch(page, searchPage, query) + const newData = await bingSearch(page, searchPage, query.topic) const newMobileData = newData.mobileSearch[0] as DashboardImpression // Mobile searches const newEdgeData = newData.pcSearch[1] as DashboardImpression // Edge searches @@ -138,11 +147,21 @@ async function bingSearch(page: Page, searchPage: Page, query: string) { await wait(500) await searchPage.keyboard.down('Control') await searchPage.keyboard.press('A') - await searchPage.keyboard.press('Backspace') // Delete the selected text + await searchPage.keyboard.press('Backspace') await searchPage.keyboard.up('Control') await searchPage.keyboard.type(query) await searchPage.keyboard.press('Enter') + if (searches.scrollRandomResults) { + await wait(2000) + await randomScroll(searchPage) + } + + if (searches.clickRandomResults) { + await wait(2000) + await clickRandomLink(searchPage) + } + await wait(Math.floor(Math.random() * (20_000 - 10_000) + 1) + 10_000) return await getSearchPoints(page) @@ -162,8 +181,8 @@ async function bingSearch(page: Page, searchPage: Page, query: string) { return await getSearchPoints(page) } -async function getGoogleTrends(locale: string, queryCount: number): Promise { - let queryTerms: string[] = [] +async function getGoogleTrends(locale: string, queryCount: number): Promise { + const queryTerms: GoogleSearch[] = [] let i = 0 while (queryCount > queryTerms.length) { @@ -186,21 +205,18 @@ async function getGoogleTrends(locale: string, queryCount: number): Promise x.query.toLocaleLowerCase()) + }) } - // Deduplicate the search terms - queryTerms = [...new Set(queryTerms)] } catch (error) { log('SEARCH-GOOGLE-TRENDS', 'An error occurred:' + error, 'error') } } - return queryTerms.slice(0, queryCount) + return queryTerms } async function getRelatedTerms(term: string): Promise { @@ -228,4 +244,20 @@ function formatDate(date: Date): string { const day = String(date.getDate()).padStart(2, '0') return `${year}${month}${day}` +} + +async function randomScroll(page: Page) { + const randomNumber = Math.random() * (50 - 5 + 1) + 5 + + // Press the arrow down key to scroll + for (let i = 0; i < randomNumber; i++) { + await page.keyboard.press('ArrowDown') + } +} + +async function clickRandomLink(page: Page) { + await page.click('#b_results h2') + + await wait(3000) + await page.goBack() } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 4bb74a1..5da81de 100644 --- a/src/index.ts +++ b/src/index.ts @@ -51,7 +51,10 @@ async function Desktop(account: Account) { // Login into MS Rewards await login(page, account.email, account.password) - await goHome(page) + const wentHome = await goHome(page) + if (!wentHome) { + throw log('MAIN', 'Unable to get dashboard page', 'error') + } const data = await getDashboardData(page) log('MAIN-POINTS', `Current point count: ${data.userStatus.availablePoints}`) @@ -100,7 +103,7 @@ async function Mobile(account: Account) { if (searches.doMobile) { await doSearch(page, data, true) } - + // Fetch new points const earnablePoints = await getEarnablePoints(data, page) // If the new earnable is 0, means we got all the points, else retract diff --git a/src/interface/Search.ts b/src/interface/Search.ts new file mode 100644 index 0000000..5e9371f --- /dev/null +++ b/src/interface/Search.ts @@ -0,0 +1,4 @@ +export interface GoogleSearch { + topic: string; + related: string[]; +} \ No newline at end of file diff --git a/src/util/Utils.ts b/src/util/Utils.ts index 7477413..abd56a3 100644 --- a/src/util/Utils.ts +++ b/src/util/Utils.ts @@ -13,7 +13,8 @@ export function getFormattedDate(ms = Date.now()) { return `${month}/${day}/${year}` } -export function shuffleArray(array: string[]): string[] { +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function shuffleArray(array: any[]): any[] { const shuffledArray = array.slice() shuffledArray.sort(() => Math.random() - 0.5)