mirror of
https://github.com/TheNetsky/Microsoft-Rewards-Script.git
synced 2026-01-11 19:06:18 +00:00
1.0.1
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "microsoft-rewards-script",
|
"name": "microsoft-rewards-script",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"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": {
|
||||||
|
|||||||
@@ -4,13 +4,15 @@ 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'
|
||||||
|
|
||||||
puppeteer.use(StealthPlugin())
|
puppeteer.use(StealthPlugin())
|
||||||
|
|
||||||
export async function Browser(email: string, headless = false) {
|
export async function Browser(email: string) {
|
||||||
const userAgent = await getUserAgent(false)
|
const userAgent = await getUserAgent(false)
|
||||||
|
|
||||||
const browser = await puppeteer.launch({
|
const browser = await puppeteer.launch({
|
||||||
headless: headless, // Set to true for a headless browser
|
headless: headless,
|
||||||
userDataDir: await loadSesion(email),
|
userDataDir: await loadSesion(email),
|
||||||
args: [
|
args: [
|
||||||
'--no-sandbox',
|
'--no-sandbox',
|
||||||
@@ -22,11 +24,11 @@ export async function Browser(email: string, headless = false) {
|
|||||||
return browser
|
return browser
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function mobileBrowser(email: string, headless = false) {
|
export async function mobileBrowser(email: string) {
|
||||||
const userAgent = await getUserAgent(true)
|
const userAgent = await getUserAgent(true)
|
||||||
|
|
||||||
const browser = await puppeteer.launch({
|
const browser = await puppeteer.launch({
|
||||||
headless: headless, // Set to true for a headless browser,
|
headless: headless,
|
||||||
userDataDir: await loadSesion(email),
|
userDataDir: await loadSesion(email),
|
||||||
args: [
|
args: [
|
||||||
'--no-sandbox',
|
'--no-sandbox',
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import fs from 'fs'
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
import { baseURL, sessionPath } from './config.json'
|
import { baseURL, sessionPath } from './config.json'
|
||||||
import { wait } from './util/Utils'
|
import { getFormattedDate, wait } from './util/Utils'
|
||||||
import { tryDismissAllMessages, tryDismissCookieBanner } from './BrowserUtil'
|
import { tryDismissAllMessages, tryDismissCookieBanner } from './BrowserUtil'
|
||||||
import { log } from './util/Logger'
|
import { log } from './util/Logger'
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ import { QuizData } from './interface/QuizData'
|
|||||||
export async function goHome(page: Page): Promise<void> {
|
export async function goHome(page: Page): Promise<void> {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const targetUrl = new URL(baseURL)
|
const dashboardURL = new URL(baseURL)
|
||||||
|
|
||||||
await page.goto(baseURL)
|
await page.goto(baseURL)
|
||||||
|
|
||||||
@@ -32,9 +32,9 @@ export async function goHome(page: Page): Promise<void> {
|
|||||||
// Continue if element is not found
|
// Continue if element is not found
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentUrl = new URL(page.url())
|
const currentURL = new URL(page.url())
|
||||||
|
|
||||||
if (currentUrl.hostname !== targetUrl.hostname) {
|
if (currentURL.hostname !== dashboardURL.hostname) {
|
||||||
await tryDismissAllMessages(page)
|
await tryDismissAllMessages(page)
|
||||||
|
|
||||||
await wait(2000)
|
await wait(2000)
|
||||||
@@ -42,7 +42,7 @@ export async function goHome(page: Page): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await wait(5000)
|
await wait(5000)
|
||||||
log('MAIN', 'Visited homepage successfully')
|
log('GO-HOME', 'Visited homepage successfully')
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -51,6 +51,16 @@ export async function goHome(page: Page): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getDashboardData(page: Page): Promise<DashboardData> {
|
export async function getDashboardData(page: Page): Promise<DashboardData> {
|
||||||
|
const dashboardURL = new URL(baseURL)
|
||||||
|
const currentURL = new URL(page.url())
|
||||||
|
|
||||||
|
// Should never happen since tasks are opened in a new tab!
|
||||||
|
if (currentURL.hostname !== dashboardURL.hostname) {
|
||||||
|
log('DASHBOARD-DATA', 'Provided page did not equal dashboard page, redirecting to dashboard page')
|
||||||
|
await goHome(page)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload the page to get new data
|
||||||
await page.reload({ waitUntil: 'networkidle2' })
|
await page.reload({ waitUntil: 'networkidle2' })
|
||||||
|
|
||||||
const scriptContent = await page.evaluate(() => {
|
const scriptContent = await page.evaluate(() => {
|
||||||
@@ -60,7 +70,7 @@ export async function getDashboardData(page: Page): Promise<DashboardData> {
|
|||||||
if (targetScript) {
|
if (targetScript) {
|
||||||
return targetScript.innerText
|
return targetScript.innerText
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Script containing dashboard data not found')
|
throw log('GET-DASHBOARD-DATA', 'Script containing dashboard data not found', 'error')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -73,19 +83,13 @@ export async function getDashboardData(page: Page): Promise<DashboardData> {
|
|||||||
if (match && match[1]) {
|
if (match && match[1]) {
|
||||||
return JSON.parse(match[1])
|
return JSON.parse(match[1])
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Dashboard data not found in the script')
|
throw log('GET-DASHBOARD-DATA', 'Dashboard data not found within script', 'error')
|
||||||
}
|
}
|
||||||
}, scriptContent)
|
}, scriptContent)
|
||||||
|
|
||||||
return dashboardData
|
return dashboardData
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getSearchPoints(page: Page): Promise<Counters> {
|
|
||||||
const dashboardData = await getDashboardData(page)
|
|
||||||
|
|
||||||
return dashboardData.userStatus.counters
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getQuizData(page: Page): Promise<QuizData> {
|
export async function getQuizData(page: Page): Promise<QuizData> {
|
||||||
const scriptContent = await page.evaluate(() => {
|
const scriptContent = await page.evaluate(() => {
|
||||||
const scripts = Array.from(document.querySelectorAll('script'))
|
const scripts = Array.from(document.querySelectorAll('script'))
|
||||||
@@ -94,7 +98,7 @@ export async function getQuizData(page: Page): Promise<QuizData> {
|
|||||||
if (targetScript) {
|
if (targetScript) {
|
||||||
return targetScript.innerText
|
return targetScript.innerText
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Script containing quiz data not found')
|
throw log('GET-QUIZ-DATA', 'Script containing quiz data not found', 'error')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -106,13 +110,48 @@ export async function getQuizData(page: Page): Promise<QuizData> {
|
|||||||
if (match && match[1]) {
|
if (match && match[1]) {
|
||||||
return JSON.parse(match[1])
|
return JSON.parse(match[1])
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Dashboard data not found in the script')
|
throw log('GET-QUIZ-DATA', 'Quiz data not found within script', 'error')
|
||||||
}
|
}
|
||||||
}, scriptContent)
|
}, scriptContent)
|
||||||
|
|
||||||
return quizData
|
return quizData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getSearchPoints(page: Page): Promise<Counters> {
|
||||||
|
const dashboardData = await getDashboardData(page) // Always fetch newest data
|
||||||
|
|
||||||
|
return dashboardData.userStatus.counters
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getEarnablePoints(data: DashboardData, page: null | Page = null): Promise<number> {
|
||||||
|
// Fetch new data if page is provided
|
||||||
|
if (page) {
|
||||||
|
data = await getDashboardData(page)
|
||||||
|
}
|
||||||
|
|
||||||
|
// These only include the points from tasks that the script can complete!
|
||||||
|
let totalEarnablePoints = 0
|
||||||
|
|
||||||
|
// Desktop Search Points
|
||||||
|
data.userStatus.counters.pcSearch.forEach(x => totalEarnablePoints += (x.pointProgressMax - x.pointProgress))
|
||||||
|
|
||||||
|
// Mobile Search Points
|
||||||
|
data.userStatus.counters.mobileSearch.forEach(x => totalEarnablePoints += (x.pointProgressMax - x.pointProgress))
|
||||||
|
|
||||||
|
// Daily Set
|
||||||
|
data.dailySetPromotions[getFormattedDate()]?.forEach(x => totalEarnablePoints += (x.pointProgressMax - x.pointProgress))
|
||||||
|
|
||||||
|
// More Promotions
|
||||||
|
data.morePromotions.forEach(x => {
|
||||||
|
// Only count points from supported activities
|
||||||
|
if (['quiz', 'urlreward'].includes(x.activityType)) {
|
||||||
|
totalEarnablePoints += (x.pointProgressMax - x.pointProgress)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return totalEarnablePoints
|
||||||
|
}
|
||||||
|
|
||||||
export async function loadSesion(email: string): Promise<string> {
|
export async function loadSesion(email: string): Promise<string> {
|
||||||
const sessionDir = path.join(__dirname, sessionPath, email)
|
const sessionDir = path.join(__dirname, sessionPath, email)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
{
|
{
|
||||||
"baseURL": "https://rewards.bing.com",
|
"baseURL": "https://rewards.bing.com",
|
||||||
"sessionPath": "sessions"
|
"sessionPath": "sessions",
|
||||||
|
"headless": false,
|
||||||
|
"runOnZeroPoints": false,
|
||||||
|
"searches": {
|
||||||
|
"doMobile": true,
|
||||||
|
"doDesktop": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -47,10 +47,12 @@ export async function doQuiz(page: Page, data: PromotionalItem | MorePromotion)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Click the answers
|
||||||
for (const answer of answers) {
|
for (const answer of answers) {
|
||||||
|
await wait(2000)
|
||||||
|
|
||||||
// Click the answer on page
|
// Click the answer on page
|
||||||
await quizPage.click(answer)
|
await quizPage.click(answer)
|
||||||
await wait(1500)
|
|
||||||
|
|
||||||
const refreshSuccess = await waitForQuizRefresh(quizPage)
|
const refreshSuccess = await waitForQuizRefresh(quizPage)
|
||||||
if (!refreshSuccess) {
|
if (!refreshSuccess) {
|
||||||
@@ -72,7 +74,7 @@ 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(1500)
|
await wait(2000)
|
||||||
|
|
||||||
const refreshSuccess = await waitForQuizRefresh(quizPage)
|
const refreshSuccess = await waitForQuizRefresh(quizPage)
|
||||||
if (!refreshSuccess) {
|
if (!refreshSuccess) {
|
||||||
@@ -88,6 +90,7 @@ export async function doQuiz(page: Page, data: PromotionalItem | MorePromotion)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Done with
|
// Done with
|
||||||
|
await wait(2000)
|
||||||
await quizPage.close()
|
await quizPage.close()
|
||||||
log('QUIZ', 'Completed the quiz successfully')
|
log('QUIZ', 'Completed the quiz successfully')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Page } from 'puppeteer'
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
import { log } from '../../util/Logger'
|
import { log } from '../../util/Logger'
|
||||||
import { shuffleArray, wait } from '../../util/Utils'
|
import { wait } from '../../util/Utils'
|
||||||
import { getSearchPoints } from '../../BrowserFunc'
|
import { getSearchPoints } from '../../BrowserFunc'
|
||||||
|
|
||||||
import { DashboardData, DashboardImpression } from '../../interface/DashboardData'
|
import { DashboardData, DashboardImpression } from '../../interface/DashboardData'
|
||||||
@@ -29,7 +29,8 @@ export async function doSearch(page: Page, data: DashboardData, mobile: boolean)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate search queries
|
// Generate search queries
|
||||||
const googleSearchQueries = shuffleArray(await getGoogleTrends(locale, missingPoints))
|
const googleSearchQueries = await getGoogleTrends(locale, missingPoints)
|
||||||
|
//const googleSearchQueries = shuffleArray(await getGoogleTrends(locale, missingPoints))
|
||||||
|
|
||||||
// Open a new tab
|
// Open a new tab
|
||||||
const browser = page.browser()
|
const browser = page.browser()
|
||||||
@@ -162,7 +163,7 @@ async function bingSearch(page: Page, searchPage: Page, query: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function getGoogleTrends(locale: string, queryCount: number): Promise<string[]> {
|
async function getGoogleTrends(locale: string, queryCount: number): Promise<string[]> {
|
||||||
const queryTerms: string[] = []
|
let queryTerms: string[] = []
|
||||||
let i = 0
|
let i = 0
|
||||||
|
|
||||||
while (queryCount > queryTerms.length) {
|
while (queryCount > queryTerms.length) {
|
||||||
@@ -193,10 +194,7 @@ async function getGoogleTrends(locale: string, queryCount: number): Promise<stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deduplicate the search terms
|
// Deduplicate the search terms
|
||||||
const uniqueSearchTerms = Array.from(new Set(queryTerms))
|
queryTerms = [...new Set(queryTerms)]
|
||||||
queryTerms.length = 0
|
|
||||||
queryTerms.push(...uniqueSearchTerms)
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log('SEARCH-GOOGLE-TRENDS', 'An error occurred:' + error, 'error')
|
log('SEARCH-GOOGLE-TRENDS', 'An error occurred:' + error, 'error')
|
||||||
}
|
}
|
||||||
|
|||||||
61
src/index.ts
61
src/index.ts
@@ -1,24 +1,33 @@
|
|||||||
import { Browser, mobileBrowser } from './Browser'
|
import { Browser, mobileBrowser } from './Browser'
|
||||||
import { getDashboardData, goHome } from './BrowserFunc'
|
import { getDashboardData, getEarnablePoints, goHome } from './BrowserFunc'
|
||||||
import { doDailySet } from './functions/DailySet'
|
import { log } from './util/Logger'
|
||||||
|
|
||||||
import { login } from './functions/Login'
|
import { login } from './functions/Login'
|
||||||
|
import { doDailySet } from './functions/DailySet'
|
||||||
import { doMorePromotions } from './functions/MorePromotions'
|
import { doMorePromotions } from './functions/MorePromotions'
|
||||||
import { doSearch } from './functions/activities/Search'
|
import { doSearch } from './functions/activities/Search'
|
||||||
import { log } from './util/Logger'
|
|
||||||
import accounts from './accounts.json'
|
|
||||||
|
|
||||||
import { Account } from './interface/Account'
|
import { Account } from './interface/Account'
|
||||||
|
|
||||||
async function init() {
|
import accounts from './accounts.json'
|
||||||
|
import { runOnZeroPoints, searches } from './config.json'
|
||||||
|
|
||||||
|
let collectedPoints = 0
|
||||||
|
|
||||||
|
async function main() {
|
||||||
log('MAIN', 'Bot started')
|
log('MAIN', 'Bot started')
|
||||||
|
|
||||||
for (const account of accounts) {
|
for (const account of accounts) {
|
||||||
log('MAIN', `Started tasks for account ${account.email}`)
|
log('MAIN', `Started tasks for account ${account.email}`)
|
||||||
|
|
||||||
// DailySet, MorePromotions and Desktop Searches
|
// Desktop Searches, DailySet and More Promotions
|
||||||
await Desktop(account)
|
await Desktop(account)
|
||||||
|
|
||||||
|
// If runOnZeroPoints is false and 0 points to earn, stop and try the next account
|
||||||
|
if (!runOnZeroPoints && collectedPoints === 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// Mobile Searches
|
// Mobile Searches
|
||||||
await Mobile(account)
|
await Mobile(account)
|
||||||
|
|
||||||
@@ -26,34 +35,49 @@ async function init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clean exit
|
// Clean exit
|
||||||
|
log('MAIN', 'Completed tasks for ALL accounts')
|
||||||
log('MAIN', 'Bot exited')
|
log('MAIN', 'Bot exited')
|
||||||
process.exit()
|
process.exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Desktop
|
// Desktop
|
||||||
async function Desktop(account: Account) {
|
async function Desktop(account: Account) {
|
||||||
const browser = await Browser(account.email)
|
const browser = await Browser(account.email)
|
||||||
const page = await browser.newPage()
|
const page = await browser.newPage()
|
||||||
|
|
||||||
|
log('MAIN', 'Starting DESKTOP browser')
|
||||||
|
|
||||||
// Login into MS Rewards
|
// Login into MS Rewards
|
||||||
await login(page, account.email, account.password)
|
await login(page, account.email, account.password)
|
||||||
|
|
||||||
await goHome(page)
|
await goHome(page)
|
||||||
|
|
||||||
const data = await getDashboardData(page)
|
const data = await getDashboardData(page)
|
||||||
log('MAIN', `Current point count: ${data.userStatus.availablePoints}`)
|
log('MAIN-POINTS', `Current point count: ${data.userStatus.availablePoints}`)
|
||||||
|
|
||||||
|
const earnablePoints = await getEarnablePoints(data)
|
||||||
|
collectedPoints = earnablePoints
|
||||||
|
log('MAIN-POINTS', `You can earn ${earnablePoints} points today`)
|
||||||
|
|
||||||
|
// If runOnZeroPoints is false and 0 points to earn, don't continue
|
||||||
|
if (!runOnZeroPoints && collectedPoints === 0) {
|
||||||
|
log('MAIN', 'No points to earn and "runOnZeroPoints" is set to "false", stopping')
|
||||||
|
|
||||||
|
// Close desktop browser
|
||||||
|
return await browser.close()
|
||||||
|
}
|
||||||
|
|
||||||
// Complete daily set
|
// Complete daily set
|
||||||
await doDailySet(page, data)
|
await doDailySet(page, data)
|
||||||
log('MAIN', `Current point count: ${data.userStatus.availablePoints}`)
|
|
||||||
|
|
||||||
// Complete more promotions
|
// Complete more promotions
|
||||||
await doMorePromotions(page, data)
|
await doMorePromotions(page, data)
|
||||||
log('MAIN', `Current point count: ${data.userStatus.availablePoints}`)
|
|
||||||
|
|
||||||
// Do desktop searches
|
// Do desktop searches
|
||||||
|
if (searches.doDesktop) {
|
||||||
await doSearch(page, data, false)
|
await doSearch(page, data, false)
|
||||||
log('MAIN', `Current point count: ${data.userStatus.availablePoints}`)
|
}
|
||||||
|
|
||||||
// Close desktop browser
|
// Close desktop browser
|
||||||
await browser.close()
|
await browser.close()
|
||||||
@@ -63,20 +87,29 @@ async function Mobile(account: Account) {
|
|||||||
const browser = await mobileBrowser(account.email)
|
const browser = await mobileBrowser(account.email)
|
||||||
const page = await browser.newPage()
|
const page = await browser.newPage()
|
||||||
|
|
||||||
|
log('MAIN', 'Starting MOBILE browser')
|
||||||
|
|
||||||
// Login into MS Rewards
|
// Login into MS Rewards
|
||||||
await login(page, account.email, account.password)
|
await login(page, account.email, account.password)
|
||||||
|
|
||||||
await goHome(page)
|
await goHome(page)
|
||||||
|
|
||||||
const data = await getDashboardData(page)
|
const data = await getDashboardData(page)
|
||||||
log('MAIN', `Current point count: ${data.userStatus.availablePoints}`)
|
|
||||||
|
|
||||||
// Do mobile searches
|
// Do mobile searches
|
||||||
|
if (searches.doMobile) {
|
||||||
await doSearch(page, data, true)
|
await doSearch(page, data, true)
|
||||||
log('MAIN', `Current point count: ${data.userStatus.availablePoints}`)
|
}
|
||||||
|
|
||||||
|
// Fetch new points
|
||||||
|
const earnablePoints = await getEarnablePoints(data, page)
|
||||||
|
// If the new earnable is 0, means we got all the points, else retract
|
||||||
|
collectedPoints = earnablePoints === 0 ? collectedPoints : (collectedPoints - earnablePoints)
|
||||||
|
log('MAIN-POINTS', `The script collected ${collectedPoints} points today`)
|
||||||
|
|
||||||
// Close mobile browser
|
// Close mobile browser
|
||||||
await browser.close()
|
await browser.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
init()
|
// Run main script
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user