This commit is contained in:
TheNetsky
2023-10-05 15:35:25 +02:00
parent 78a7566978
commit e982e6e25f
14 changed files with 87 additions and 48 deletions

View File

@@ -22,8 +22,9 @@ Under development, however mainly for personal use!
- [x] Completing Polls - [x] Completing Polls
- [ ] Completing Punchcards - [ ] Completing Punchcards
- [ ] Solving This Or That Quiz - [ ] Solving This Or That Quiz
- [ ] Clicking Promotional Items - [x] Clicking Promotional Items
- [ ] Completing Shop And Earn - [ ] Completing Shop And Earn
- [ ] Proxy Support
## Disclaimer ## ## Disclaimer ##
Your account may be at risk of getting banned or suspended using this script, you've been warned! Your account may be at risk of getting banned or suspended using this script, you've been warned!

View File

@@ -1,6 +1,6 @@
{ {
"name": "microsoft-rewards-script", "name": "microsoft-rewards-script",
"version": "1.0.5", "version": "1.0.6",
"description": "Automatically do tasks for Microsoft Rewards but in TS", "description": "Automatically do tasks for Microsoft Rewards but in TS",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@@ -26,7 +26,7 @@
"cheerio": "^1.0.0-rc.12", "cheerio": "^1.0.0-rc.12",
"eslint": "^8.49.0", "eslint": "^8.49.0",
"eslint-plugin-modules-newline": "^0.0.6", "eslint-plugin-modules-newline": "^0.0.6",
"puppeteer": "^21.3.6", "puppeteer": "^21.2.1",
"puppeteer-extra": "^3.3.6", "puppeteer-extra": "^3.3.6",
"puppeteer-extra-plugin-stealth": "^2.11.2", "puppeteer-extra-plugin-stealth": "^2.11.2",
"ts-node": "^10.9.1" "ts-node": "^10.9.1"

View File

@@ -1,10 +1,10 @@
import puppeteer from 'puppeteer-extra' import puppeteer from 'puppeteer-extra'
import StealthPlugin from 'puppeteer-extra-plugin-stealth' import StealthPlugin from 'puppeteer-extra-plugin-stealth'
import { getUserAgent } from './util/UserAgent' import { getUserAgent } from '../util/UserAgent'
import { loadSesion } from './BrowserFunc' import { loadSesion } from './BrowserFunc'
import { headless } from './config.json' import { headless } from '../config.json'
puppeteer.use(StealthPlugin()) puppeteer.use(StealthPlugin())

View File

@@ -4,13 +4,13 @@ import path from 'path'
import { load } from 'cheerio' import { load } from 'cheerio'
import { tryDismissAllMessages, tryDismissCookieBanner } from './BrowserUtil' import { tryDismissAllMessages, tryDismissCookieBanner } from './BrowserUtil'
import { getFormattedDate, wait } from './util/Utils' import { getFormattedDate, wait } from './../util/Utils'
import { log } from './util/Logger' import { log } from './../util/Logger'
import { Counters, DashboardData } from './interface/DashboardData' import { Counters, DashboardData } from './../interface/DashboardData'
import { QuizData } from './interface/QuizData' import { QuizData } from './../interface/QuizData'
import { baseURL, sessionPath } from './config.json' import { baseURL, sessionPath } from './../config.json'
export async function goHome(page: Page): Promise<boolean> { export async function goHome(page: Page): Promise<boolean> {
@@ -55,7 +55,7 @@ export async function goHome(page: Page): Promise<boolean> {
} }
} catch (error) { } catch (error) {
console.error('An error occurred:', JSON.stringify(error, null, 2)) console.error('An error occurred:', error)
return false return false
} }
@@ -126,7 +126,7 @@ export async function getQuizData(page: Page): Promise<QuizData> {
} }
} catch (error) { } catch (error) {
throw log('GET-QUIZ-DATA', 'An error occurred:' + JSON.stringify(error, null, 2), 'error') throw log('GET-QUIZ-DATA', 'An error occurred:' + error, 'error')
} }
} }
@@ -168,7 +168,20 @@ export async function getEarnablePoints(data: DashboardData, page: null | Page =
return totalEarnablePoints return totalEarnablePoints
} catch (error) { } catch (error) {
throw log('GET-EARNABLE-POINTS', 'An error occurred:' + JSON.stringify(error, null, 2), 'error') throw log('GET-EARNABLE-POINTS', 'An error occurred:' + error, 'error')
}
}
export async function getCurrentPoints(data: DashboardData, page: null | Page = null): Promise<number> {
try {
// Fetch new data if page is provided
if (page) {
data = await getDashboardData(page)
}
return data.userStatus.availablePoints
} catch (error) {
throw log('GET-CURRENT-POINTS', 'An error occurred:' + error, 'error')
} }
} }
@@ -193,7 +206,7 @@ export async function waitForQuizRefresh(page: Page) {
await page.waitForSelector('#rqHeaderCredits', { timeout: 5000 }) await page.waitForSelector('#rqHeaderCredits', { timeout: 5000 })
return true return true
} catch (error) { } catch (error) {
log('QUIZ-REFRESH', 'An error occurred:' + JSON.stringify(error, null, 2), 'error') log('QUIZ-REFRESH', 'An error occurred:' + error, 'error')
return false return false
} }
} }

View File

@@ -1,6 +1,7 @@
import { Page } from 'puppeteer' import { Page } from 'puppeteer'
import { wait } from './util/Utils' import { wait } from './../util/Utils'
import { log } from './../util/Logger'
export async function tryDismissAllMessages(page: Page): Promise<boolean> { export async function tryDismissAllMessages(page: Page): Promise<boolean> {
const buttons = [ const buttons = [
@@ -62,10 +63,19 @@ export async function tryDismissBingCookieBanner(page: Page): Promise<void> {
} }
export async function getLatestTab(page: Page) { export async function getLatestTab(page: Page) {
await wait(2000) try {
const browser = page.browser() await wait(500)
const pages = await browser.pages()
const newTab = pages[pages.length - 1] as Page
return newTab const browser = page.browser()
const pages = await browser.pages()
const newTab = pages[pages.length - 1]
if (newTab) {
return newTab
}
throw log('GET-NEW-TAB', 'Unable to get latest tab', 'error')
} catch (error) {
throw log('GET-NEW-TAB', 'An error occurred:' + error, 'error')
}
} }

View File

@@ -6,7 +6,7 @@ const rl = readline.createInterface({
output: process.stdout output: process.stdout
}) })
import { tryDismissAllMessages, tryDismissBingCookieBanner } from '../BrowserUtil' import { tryDismissAllMessages, tryDismissBingCookieBanner } from '../browser/BrowserUtil'
import { wait } from '../util/Utils' import { wait } from '../util/Utils'
import { log } from '../util/Logger' import { log } from '../util/Logger'
@@ -34,7 +34,7 @@ export async function login(page: Page, email: string, password: string) {
log('LOGIN', 'Logged in successfully') log('LOGIN', 'Logged in successfully')
} catch (error) { } catch (error) {
log('LOGIN', 'An error occurred:' + JSON.stringify(error, null, 2), 'error') log('LOGIN', 'An error occurred:' + error, 'error')
} }
} }
@@ -103,7 +103,7 @@ async function checkBingLogin(page: Page): Promise<void> {
} }
} catch (error) { } catch (error) {
log('LOGIN-BING', 'An error occurred:' + JSON.stringify(error, null, 2), 'error') log('LOGIN-BING', 'An error occurred:' + error, 'error')
} }
} }

View File

@@ -8,11 +8,16 @@ import { doThisOrThat } from './activities/ThisOrThat'
import { wait } from '../util/Utils' import { wait } from '../util/Utils'
import { log } from '../util/Logger' import { log } from '../util/Logger'
import { DashboardData } from '../interface/DashboardData' import { DashboardData, MorePromotion } from '../interface/DashboardData'
export async function doMorePromotions(page: Page, data: DashboardData) { export async function doMorePromotions(page: Page, data: DashboardData) {
const morePromotions = data.morePromotions const morePromotions = data.morePromotions
// Check if there is a promotional item
if (data.promotionalItem) { // Convert and add the promotional item to the array
morePromotions.push(data.promotionalItem as unknown as MorePromotion)
}
const activitiesUncompleted = morePromotions?.filter(x => !x.complete) ?? [] const activitiesUncompleted = morePromotions?.filter(x => !x.complete) ?? []
if (!activitiesUncompleted.length) { if (!activitiesUncompleted.length) {

View File

@@ -1,6 +1,6 @@
import { Page } from 'puppeteer' import { Page } from 'puppeteer'
import { getLatestTab } from '../../BrowserUtil' import { getLatestTab } from '../../browser/BrowserUtil'
import { log } from '../../util/Logger' import { log } from '../../util/Logger'
import { randomNumber, wait } from '../../util/Utils' import { randomNumber, wait } from '../../util/Utils'
@@ -20,7 +20,9 @@ export async function doPoll(page: Page, data: PromotionalItem | MorePromotion)
const buttonId = `#btoption${Math.floor(randomNumber(0, 1))}` const buttonId = `#btoption${Math.floor(randomNumber(0, 1))}`
await pollPage.waitForNetworkIdle({ timeout: 5000 })
await pollPage.waitForSelector(buttonId, { visible: true, timeout: 5000 }) await pollPage.waitForSelector(buttonId, { visible: true, timeout: 5000 })
await pollPage.click(buttonId) await pollPage.click(buttonId)
await wait(2000) await wait(2000)
@@ -28,6 +30,8 @@ export async function doPoll(page: Page, data: PromotionalItem | MorePromotion)
log('POLL', 'Completed the poll successfully') log('POLL', 'Completed the poll successfully')
} catch (error) { } catch (error) {
log('POLL', 'An error occurred:' + JSON.stringify(error, null, 2), 'error') const pollPage = await getLatestTab(page)
await pollPage.close()
log('POLL', 'An error occurred:' + error, 'error')
} }
} }

View File

@@ -1,7 +1,7 @@
import { Page } from 'puppeteer' import { Page } from 'puppeteer'
import { getLatestTab } from '../../BrowserUtil' import { getLatestTab } from '../../browser/BrowserUtil'
import { getQuizData, waitForQuizRefresh } from '../../BrowserFunc' import { getQuizData, waitForQuizRefresh } from '../../browser/BrowserFunc'
import { wait } from '../../util/Utils' import { wait } from '../../util/Utils'
import { log } from '../../util/Logger' import { log } from '../../util/Logger'
@@ -18,6 +18,7 @@ export async function doQuiz(page: Page, data: PromotionalItem | MorePromotion)
await page.click(selector) await page.click(selector)
const quizPage = await getLatestTab(page) const quizPage = await getLatestTab(page)
await quizPage.waitForNetworkIdle({ timeout: 5000 })
// Check if the quiz has been started or not // Check if the quiz has been started or not
const quizNotStarted = await quizPage.waitForSelector('#rqStartQuiz', { visible: true, timeout: 3000 }).then(() => true).catch(() => false) const quizNotStarted = await quizPage.waitForSelector('#rqStartQuiz', { visible: true, timeout: 3000 }).then(() => true).catch(() => false)
@@ -29,7 +30,7 @@ export async function doQuiz(page: Page, data: PromotionalItem | MorePromotion)
await wait(2000) await wait(2000)
const quizData = await getQuizData(quizPage) let quizData = await getQuizData(quizPage)
const questionsRemaining = quizData.maxQuestions - quizData.CorrectlyAnsweredQuestionCount // Amount of questions remaining const questionsRemaining = quizData.maxQuestions - quizData.CorrectlyAnsweredQuestionCount // Amount of questions remaining
// All questions // All questions
@@ -41,7 +42,6 @@ export async function doQuiz(page: Page, data: PromotionalItem | MorePromotion)
for (let i = 0; i < quizData.numberOfOptions; i++) { for (let i = 0; i < quizData.numberOfOptions; i++) {
const answerSelector = await quizPage.waitForSelector(`#rqAnswerOption${i}`, { visible: true, timeout: 5000 }) const answerSelector = await quizPage.waitForSelector(`#rqAnswerOption${i}`, { visible: true, timeout: 5000 })
const answerAttribute = await answerSelector?.evaluate(el => el.getAttribute('iscorrectoption')) const answerAttribute = await answerSelector?.evaluate(el => el.getAttribute('iscorrectoption'))
await wait(500)
if (answerAttribute && answerAttribute.toLowerCase() === 'true') { if (answerAttribute && answerAttribute.toLowerCase() === 'true') {
answers.push(`#rqAnswerOption${i}`) answers.push(`#rqAnswerOption${i}`)
@@ -65,6 +65,7 @@ export async function doQuiz(page: Page, data: PromotionalItem | MorePromotion)
// Other type quiz // Other type quiz
} else if ([2, 3, 4].includes(quizData.numberOfOptions)) { } else if ([2, 3, 4].includes(quizData.numberOfOptions)) {
quizData = await getQuizData(quizPage) // Refresh Quiz Data
const correctOption = quizData.correctAnswer const correctOption = quizData.correctAnswer
for (let i = 0; i < quizData.numberOfOptions; i++) { for (let i = 0; i < quizData.numberOfOptions; i++) {
@@ -75,7 +76,6 @@ export async function doQuiz(page: Page, data: PromotionalItem | MorePromotion)
if (dataOption === correctOption) { if (dataOption === correctOption) {
// Click the answer on page // Click the answer on page
await quizPage.click(`#rqAnswerOption${i}`) await quizPage.click(`#rqAnswerOption${i}`)
await wait(2000)
const refreshSuccess = await waitForQuizRefresh(quizPage) const refreshSuccess = await waitForQuizRefresh(quizPage)
if (!refreshSuccess) { if (!refreshSuccess) {
@@ -98,7 +98,7 @@ export async function doQuiz(page: Page, data: PromotionalItem | MorePromotion)
} catch (error) { } catch (error) {
const quizPage = await getLatestTab(page) const quizPage = await getLatestTab(page)
await quizPage.close() await quizPage.close()
log('QUIZ', 'An error occurred:' + JSON.stringify(error, null, 2), 'error') log('QUIZ', 'An error occurred:' + error, 'error')
} }
} }

View File

@@ -1,8 +1,8 @@
import { Page } from 'puppeteer' import { Page } from 'puppeteer'
import axios from 'axios' import axios from 'axios'
import { getLatestTab } from '../../BrowserUtil' import { getLatestTab } from '../../browser/BrowserUtil'
import { getSearchPoints } from '../../BrowserFunc' import { getSearchPoints } from '../../browser/BrowserFunc'
import { log } from '../../util/Logger' import { log } from '../../util/Logger'
import { randomNumber, shuffleArray, wait } from '../../util/Utils' import { randomNumber, shuffleArray, wait } from '../../util/Utils'
@@ -169,11 +169,11 @@ async function bingSearch(page: Page, searchPage: Page, query: string, mobile: b
} catch (error) { } catch (error) {
if (i === 5) { if (i === 5) {
log('SEARCH-BING', 'Failed after 5 retries... An error occurred:' + JSON.stringify(error, null, 2), 'error') log('SEARCH-BING', 'Failed after 5 retries... An error occurred:' + error, 'error')
break break
} }
log('SEARCH-BING', 'Search failed, An error occurred:' + JSON.stringify(error, null, 2), 'error') log('SEARCH-BING', 'Search failed, An error occurred:' + error, 'error')
log('SEARCH-BING', `Retrying search, attempt ${i}/5`, 'warn') log('SEARCH-BING', `Retrying search, attempt ${i}/5`, 'warn')
await wait(4000) await wait(4000)
@@ -215,7 +215,7 @@ async function getGoogleTrends(locale: string, queryCount: number): Promise<Goog
} }
} catch (error) { } catch (error) {
log('SEARCH-GOOGLE-TRENDS', 'An error occurred:' + JSON.stringify(error, null, 2), 'error') log('SEARCH-GOOGLE-TRENDS', 'An error occurred:' + error, 'error')
} }
} }
@@ -236,7 +236,7 @@ async function getRelatedTerms(term: string): Promise<string[]> {
return response.data[1] as string[] return response.data[1] as string[]
} catch (error) { } catch (error) {
log('SEARCH-BING-RELTATED', 'An error occurred:' + JSON.stringify(error, null, 2), 'error') log('SEARCH-BING-RELTATED', 'An error occurred:' + error, 'error')
} }
return [] return []
} }
@@ -256,7 +256,7 @@ async function randomScroll(page: Page) {
await page.keyboard.press('ArrowDown') await page.keyboard.press('ArrowDown')
} }
} catch (error) { } catch (error) {
log('SEARCH-RANDOM-SCROLL', 'An error occurred:' + JSON.stringify(error, null, 2), 'error') log('SEARCH-RANDOM-SCROLL', 'An error occurred:' + error, 'error')
} }
} }
@@ -302,6 +302,6 @@ async function clickRandomLink(page: Page, mobile: boolean) {
} }
} }
} catch (error) { } catch (error) {
log('SEARCH-RANDOM-CLICK', 'An error occurred:' + JSON.stringify(error, null, 2), 'error') log('SEARCH-RANDOM-CLICK', 'An error occurred:' + error, 'error')
} }
} }

View File

@@ -1,6 +1,6 @@
import { Page } from 'puppeteer' import { Page } from 'puppeteer'
import { getLatestTab } from '../../BrowserUtil' import { getLatestTab } from '../../browser/BrowserUtil'
import { wait } from '../../util/Utils' import { wait } from '../../util/Utils'
import { log } from '../../util/Logger' import { log } from '../../util/Logger'
@@ -18,6 +18,7 @@ export async function doThisOrThat(page: Page, data: PromotionalItem | MorePromo
await page.click(selector) await page.click(selector)
const thisorthatPage = await getLatestTab(page) const thisorthatPage = await getLatestTab(page)
await thisorthatPage.waitForNetworkIdle({ timeout: 5000 })
// Check if the quiz has been started or not // Check if the quiz has been started or not
const quizNotStarted = await thisorthatPage.waitForSelector('#rqStartQuiz', { visible: true, timeout: 3000 }).then(() => true).catch(() => false) const quizNotStarted = await thisorthatPage.waitForSelector('#rqStartQuiz', { visible: true, timeout: 3000 }).then(() => true).catch(() => false)
@@ -33,7 +34,9 @@ export async function doThisOrThat(page: Page, data: PromotionalItem | MorePromo
log('THIS-OR-THAT', 'Completed the ThisOrthat successfully') log('THIS-OR-THAT', 'Completed the ThisOrthat successfully')
} catch (error) { } catch (error) {
log('THIS-OR-THAT', 'An error occurred:' + JSON.stringify(error, null, 2), 'error') const thisorthatPage = await getLatestTab(page)
await thisorthatPage.close()
log('THIS-OR-THAT', 'An error occurred:' + error, 'error')
} }
} }

View File

@@ -1,6 +1,6 @@
import { Page } from 'puppeteer' import { Page } from 'puppeteer'
import { getLatestTab } from '../../BrowserUtil' import { getLatestTab } from '../../browser/BrowserUtil'
import { log } from '../../util/Logger' import { log } from '../../util/Logger'
import { PromotionalItem, MorePromotion } from '../../interface/DashboardData' import { PromotionalItem, MorePromotion } from '../../interface/DashboardData'
@@ -17,11 +17,14 @@ export async function doUrlReward(page: Page, data: PromotionalItem | MorePromot
// After waiting, close the page // After waiting, close the page
const visitPage = await getLatestTab(page) const visitPage = await getLatestTab(page)
await visitPage.waitForNetworkIdle({ timeout: 5000 })
await visitPage.close() await visitPage.close()
log('URL-REWARD', 'Completed the UrlReward successfully') log('URL-REWARD', 'Completed the UrlReward successfully')
} catch (error) { } catch (error) {
log('URL-REWARD', 'An error occurred:' + JSON.stringify(error, null, 2), 'error') const visitPage = await getLatestTab(page)
await visitPage.close()
log('URL-REWARD', 'An error occurred:' + error, 'error')
} }
} }

View File

@@ -1,5 +1,5 @@
import { Browser, mobileBrowser } from './Browser' import { Browser, mobileBrowser } from './browser/Browser'
import { getDashboardData, getEarnablePoints, goHome } from './BrowserFunc' import { getDashboardData, getEarnablePoints, goHome } from './browser/BrowserFunc'
import { log } from './util/Logger' import { log } from './util/Logger'
import { login } from './functions/Login' import { login } from './functions/Login'

View File

@@ -51,7 +51,7 @@ export async function getChromeVersion(): Promise<string> {
return data.channels.Stable.version return data.channels.Stable.version
} catch (error) { } catch (error) {
throw log('USERAGENT-CHROME-VERSION', 'An error occurred:' + JSON.stringify(error, null, 2), 'error') throw log('USERAGENT-CHROME-VERSION', 'An error occurred:' + error, 'error')
} }
} }
@@ -75,7 +75,7 @@ export async function getEdgeVersions() {
} catch (error) { } catch (error) {
throw log('USERAGENT-EDGE-VERSION', 'An error occurred:' + JSON.stringify(error, null, 2), 'error') throw log('USERAGENT-EDGE-VERSION', 'An error occurred:' + error, 'error')
} }
} }