mirror of
https://github.com/TheNetsky/Microsoft-Rewards-Script.git
synced 2026-01-11 19:06:18 +00:00
1.0.7
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,3 +5,4 @@ package-lock.json
|
|||||||
accounts.json
|
accounts.json
|
||||||
notes
|
notes
|
||||||
accounts.dev.json
|
accounts.dev.json
|
||||||
|
accounts.main.json
|
||||||
@@ -23,6 +23,7 @@ Under development, however mainly for personal use!
|
|||||||
- [ ] Completing Punchcards
|
- [ ] Completing Punchcards
|
||||||
- [ ] Solving This Or That Quiz
|
- [ ] Solving This Or That Quiz
|
||||||
- [x] Clicking Promotional Items
|
- [x] Clicking Promotional Items
|
||||||
|
- [x] Solving ABC quiz
|
||||||
- [ ] Completing Shop And Earn
|
- [ ] Completing Shop And Earn
|
||||||
- [ ] Proxy Support
|
- [ ] Proxy Support
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "microsoft-rewards-script",
|
"name": "microsoft-rewards-script",
|
||||||
"version": "1.0.6",
|
"version": "1.0.7",
|
||||||
"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": {
|
||||||
|
|||||||
@@ -8,24 +8,10 @@ import { headless } from '../config.json'
|
|||||||
|
|
||||||
puppeteer.use(StealthPlugin())
|
puppeteer.use(StealthPlugin())
|
||||||
|
|
||||||
export async function Browser(email: string) {
|
class Browser {
|
||||||
const userAgent = await getUserAgent(false)
|
|
||||||
|
|
||||||
const browser = await puppeteer.launch({
|
async createBrowser(email: string, isMobile: boolean) {
|
||||||
headless: headless,
|
const userAgent = await getUserAgent(isMobile)
|
||||||
userDataDir: await loadSesion(email),
|
|
||||||
args: [
|
|
||||||
'--no-sandbox',
|
|
||||||
'--disable-setuid-sandbox',
|
|
||||||
`--user-agent=${userAgent.userAgent}`
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
return browser
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function mobileBrowser(email: string) {
|
|
||||||
const userAgent = await getUserAgent(true)
|
|
||||||
|
|
||||||
const browser = await puppeteer.launch({
|
const browser = await puppeteer.launch({
|
||||||
headless: headless,
|
headless: headless,
|
||||||
@@ -34,9 +20,12 @@ export async function mobileBrowser(email: string) {
|
|||||||
'--no-sandbox',
|
'--no-sandbox',
|
||||||
'--disable-setuid-sandbox',
|
'--disable-setuid-sandbox',
|
||||||
`--user-agent=${userAgent.userAgent}`,
|
`--user-agent=${userAgent.userAgent}`,
|
||||||
'--window-size=568,1024'
|
isMobile ? '--window-size=568,1024' : ''
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
return browser
|
return browser
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Browser
|
||||||
@@ -219,3 +219,10 @@ export async function checkQuizCompleted(page: Page) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function refreshCheerio(page: Page) {
|
||||||
|
const html = await page.content()
|
||||||
|
const $ = load(html)
|
||||||
|
|
||||||
|
return $
|
||||||
|
}
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
import { Page } from 'puppeteer'
|
|
||||||
|
|
||||||
import { doPoll } from './activities/Poll'
|
|
||||||
import { doQuiz } from './activities/Quiz'
|
|
||||||
import { doUrlReward } from './activities/UrlReward'
|
|
||||||
import { doThisOrThat } from './activities/ThisOrThat'
|
|
||||||
|
|
||||||
import { getFormattedDate, wait } from '../util/Utils'
|
|
||||||
import { log } from '../util/Logger'
|
|
||||||
|
|
||||||
import { DashboardData } from '../interface/DashboardData'
|
|
||||||
|
|
||||||
export async function doDailySet(page: Page, data: DashboardData) {
|
|
||||||
const todayData = data.dailySetPromotions[getFormattedDate()]
|
|
||||||
|
|
||||||
const activitiesUncompleted = todayData?.filter(x => !x.complete) ?? []
|
|
||||||
|
|
||||||
if (!activitiesUncompleted.length) {
|
|
||||||
log('DAILY-SET', 'All daily set items have already been completed')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const activity of activitiesUncompleted) {
|
|
||||||
log('DAILY-SET', 'Started doing daily set items')
|
|
||||||
|
|
||||||
// If activity does not give points, skip
|
|
||||||
if (activity.pointProgressMax <= 0) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (activity.promotionType) {
|
|
||||||
// Quiz (Poll/Quiz)
|
|
||||||
case 'quiz':
|
|
||||||
|
|
||||||
switch (activity.pointProgressMax) {
|
|
||||||
// Poll (Usually 10 points)
|
|
||||||
case 10:
|
|
||||||
log('ACTIVITY', 'Found daily activity type: Poll')
|
|
||||||
await doPoll(page, activity)
|
|
||||||
break
|
|
||||||
|
|
||||||
// This Or That Quiz (Usually 50 points)
|
|
||||||
case 50:
|
|
||||||
log('ACTIVITY', 'Found daily activity type: ThisOrThat')
|
|
||||||
await doThisOrThat(page, activity)
|
|
||||||
break
|
|
||||||
|
|
||||||
// Quizzes are usually 30-40 points
|
|
||||||
default:
|
|
||||||
log('ACTIVITY', 'Found daily activity type: Quiz')
|
|
||||||
await doQuiz(page, activity)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
// UrlReward (Visit)
|
|
||||||
case 'urlreward':
|
|
||||||
log('ACTIVITY', 'Found daily activity type: UrlReward')
|
|
||||||
await doUrlReward(page, activity)
|
|
||||||
break
|
|
||||||
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
await wait(1500)
|
|
||||||
}
|
|
||||||
|
|
||||||
log('DAILY-SET', 'Daily set items have been completed')
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
import { Page } from 'puppeteer'
|
|
||||||
|
|
||||||
import { doPoll } from './activities/Poll'
|
|
||||||
import { doQuiz } from './activities/Quiz'
|
|
||||||
import { doUrlReward } from './activities/UrlReward'
|
|
||||||
import { doThisOrThat } from './activities/ThisOrThat'
|
|
||||||
|
|
||||||
import { wait } from '../util/Utils'
|
|
||||||
import { log } from '../util/Logger'
|
|
||||||
|
|
||||||
import { DashboardData, MorePromotion } from '../interface/DashboardData'
|
|
||||||
|
|
||||||
export async function doMorePromotions(page: Page, data: DashboardData) {
|
|
||||||
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) ?? []
|
|
||||||
|
|
||||||
if (!activitiesUncompleted.length) {
|
|
||||||
log('MORE-PROMOTIONS', 'All more promotion items have already been completed')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const activity of activitiesUncompleted) {
|
|
||||||
// If activity does not give points, skip
|
|
||||||
if (activity.pointProgressMax <= 0) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (activity.promotionType) {
|
|
||||||
// Quiz (Poll/Quiz)
|
|
||||||
case 'quiz':
|
|
||||||
|
|
||||||
switch (activity.pointProgressMax) {
|
|
||||||
// Poll (Usually 10 points)
|
|
||||||
case 10:
|
|
||||||
log('ACTIVITY', 'Found promotion activity type: Poll')
|
|
||||||
await doPoll(page, activity)
|
|
||||||
break
|
|
||||||
|
|
||||||
// This Or That Quiz (Usually 50 points)
|
|
||||||
case 50:
|
|
||||||
log('ACTIVITY', 'Found daily activity type: ThisOrThat')
|
|
||||||
await doThisOrThat(page, activity)
|
|
||||||
break
|
|
||||||
|
|
||||||
// Quizzes are usually 30-40 points
|
|
||||||
default:
|
|
||||||
log('ACTIVITY', 'Found promotion activity type: Quiz')
|
|
||||||
await doQuiz(page, activity)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
// UrlReward (Visit)
|
|
||||||
case 'urlreward':
|
|
||||||
log('ACTIVITY', 'Found promotion activity type: UrlReward')
|
|
||||||
await doUrlReward(page, activity)
|
|
||||||
break
|
|
||||||
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
await wait(1500)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
import { Page } from 'puppeteer'
|
|
||||||
|
|
||||||
import { doPoll } from './activities/Poll'
|
|
||||||
import { doQuiz } from './activities/Quiz'
|
|
||||||
import { doUrlReward } from './activities/UrlReward'
|
|
||||||
import { doThisOrThat } from './activities/ThisOrThat'
|
|
||||||
|
|
||||||
import { wait } from '../util/Utils'
|
|
||||||
import { log } from '../util/Logger'
|
|
||||||
|
|
||||||
import { DashboardData } from '../interface/DashboardData'
|
|
||||||
|
|
||||||
export async function doPunchCard(page: Page, data: DashboardData) {
|
|
||||||
|
|
||||||
const punchCardsUncompleted = data.punchCards?.filter(x => !x.parentPromotion.complete) ?? [] // filter out the uncompleted punch cards
|
|
||||||
|
|
||||||
if (!punchCardsUncompleted.length) {
|
|
||||||
log('PUNCH-CARD', 'All punch cards have already been completed')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Todo
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const activitiesUncompleted: any = ''
|
|
||||||
|
|
||||||
for (const activity of activitiesUncompleted) {
|
|
||||||
log('PUNCH-CARD', 'Started doing daily set items')
|
|
||||||
|
|
||||||
// If activity does not give points, skip
|
|
||||||
if (activity.pointProgressMax <= 0) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (activity.promotionType) {
|
|
||||||
// Quiz (Poll/Quiz)
|
|
||||||
case 'quiz':
|
|
||||||
|
|
||||||
switch (activity.pointProgressMax) {
|
|
||||||
// Poll (Usually 10 points)
|
|
||||||
case 10:
|
|
||||||
log('ACTIVITY', 'Found daily activity type: Poll')
|
|
||||||
await doPoll(page, activity)
|
|
||||||
break
|
|
||||||
|
|
||||||
// This Or That Quiz (Usually 50 points)
|
|
||||||
case 50:
|
|
||||||
log('ACTIVITY', 'Found daily activity type: ThisOrThat')
|
|
||||||
await doThisOrThat(page, activity)
|
|
||||||
break
|
|
||||||
|
|
||||||
// Quizzes are usually 30-40 points
|
|
||||||
default:
|
|
||||||
log('ACTIVITY', 'Found daily activity type: Quiz')
|
|
||||||
await doQuiz(page, activity)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
// UrlReward (Visit)
|
|
||||||
case 'urlreward':
|
|
||||||
log('ACTIVITY', 'Found daily activity type: UrlReward')
|
|
||||||
await doUrlReward(page, activity)
|
|
||||||
break
|
|
||||||
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
await wait(1500)
|
|
||||||
}
|
|
||||||
|
|
||||||
log('PUNCH-CARD', 'Punch card items have been completed')
|
|
||||||
}
|
|
||||||
211
src/functions/Workers.ts
Normal file
211
src/functions/Workers.ts
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
import { Page } from 'puppeteer'
|
||||||
|
|
||||||
|
import { doPoll } from './activities/Poll'
|
||||||
|
import { doQuiz } from './activities/Quiz'
|
||||||
|
import { doUrlReward } from './activities/UrlReward'
|
||||||
|
import { doThisOrThat } from './activities/ThisOrThat'
|
||||||
|
import { doABC } from './activities/ABC'
|
||||||
|
|
||||||
|
import { getFormattedDate, wait } from '../util/Utils'
|
||||||
|
import { log } from '../util/Logger'
|
||||||
|
|
||||||
|
import { DashboardData, MorePromotion } from '../interface/DashboardData'
|
||||||
|
|
||||||
|
// Daily Set
|
||||||
|
export async function doDailySet(page: Page, data: DashboardData) {
|
||||||
|
const todayData = data.dailySetPromotions[getFormattedDate()]
|
||||||
|
|
||||||
|
const activitiesUncompleted = todayData?.filter(x => !x.complete) ?? []
|
||||||
|
|
||||||
|
if (!activitiesUncompleted.length) {
|
||||||
|
log('DAILY-SET', 'All daily set items have already been completed')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const activity of activitiesUncompleted) {
|
||||||
|
log('DAILY-SET', 'Started doing daily set items')
|
||||||
|
|
||||||
|
// If activity does not give points, skip
|
||||||
|
if (activity.pointProgressMax <= 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (activity.promotionType) {
|
||||||
|
// Quiz (Poll, Quiz or ABC)
|
||||||
|
case 'quiz':
|
||||||
|
|
||||||
|
switch (activity.pointProgressMax) {
|
||||||
|
// Poll or ABC (Usually 10 points)
|
||||||
|
case 10:
|
||||||
|
// Normal poll
|
||||||
|
if (activity.destinationUrl.toLowerCase().includes('pollscenarioid')) {
|
||||||
|
log('ACTIVITY', 'Found daily activity type: Poll')
|
||||||
|
await doPoll(page, activity)
|
||||||
|
} else { // ABC
|
||||||
|
log('ACTIVITY', 'Found daily activity type: ABC')
|
||||||
|
await doABC(page, activity)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
// This Or That Quiz (Usually 50 points)
|
||||||
|
case 50:
|
||||||
|
log('ACTIVITY', 'Found daily activity type: ThisOrThat')
|
||||||
|
await doThisOrThat(page, activity)
|
||||||
|
break
|
||||||
|
|
||||||
|
// Quizzes are usually 30-40 points
|
||||||
|
default:
|
||||||
|
log('ACTIVITY', 'Found daily activity type: Quiz')
|
||||||
|
await doQuiz(page, activity)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
// UrlReward (Visit)
|
||||||
|
case 'urlreward':
|
||||||
|
log('ACTIVITY', 'Found daily activity type: UrlReward')
|
||||||
|
await doUrlReward(page, activity)
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
await wait(1500)
|
||||||
|
}
|
||||||
|
|
||||||
|
log('DAILY-SET', 'Daily set items have been completed')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Punch Card
|
||||||
|
export async function doPunchCard(page: Page, data: DashboardData) {
|
||||||
|
|
||||||
|
const punchCardsUncompleted = data.punchCards?.filter(x => !x.parentPromotion.complete) ?? [] // Only return uncompleted punch cards
|
||||||
|
|
||||||
|
if (!punchCardsUncompleted.length) {
|
||||||
|
log('PUNCH-CARD', 'All punch cards have already been completed')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const promotion of punchCardsUncompleted) {
|
||||||
|
const activities = promotion.childPromotions.filter(x => !x.complete) // Only return uncompleted activities
|
||||||
|
|
||||||
|
for (const activity of activities) {
|
||||||
|
log('PUNCH-CARD', 'Started doing daily set items')
|
||||||
|
|
||||||
|
// If activity does not give points, skip
|
||||||
|
if (activity.pointProgressMax <= 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (activity.promotionType) {
|
||||||
|
// Quiz (Poll, Quiz or ABC)
|
||||||
|
case 'quiz':
|
||||||
|
|
||||||
|
switch (activity.pointProgressMax) {
|
||||||
|
// Poll or ABC (Usually 10 points)
|
||||||
|
case 10:
|
||||||
|
// Normal poll
|
||||||
|
if (activity.destinationUrl.toLowerCase().includes('pollscenarioid')) {
|
||||||
|
log('ACTIVITY', 'Found daily activity type: Poll')
|
||||||
|
await doPoll(page, activity)
|
||||||
|
} else { // ABC
|
||||||
|
log('ACTIVITY', 'Found daily activity type: ABC')
|
||||||
|
await doABC(page, activity)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
// This Or That Quiz (Usually 50 points)
|
||||||
|
case 50:
|
||||||
|
log('ACTIVITY', 'Found daily activity type: ThisOrThat')
|
||||||
|
await doThisOrThat(page, activity)
|
||||||
|
break
|
||||||
|
|
||||||
|
// Quizzes are usually 30-40 points
|
||||||
|
default:
|
||||||
|
log('ACTIVITY', 'Found daily activity type: Quiz')
|
||||||
|
await doQuiz(page, activity)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
// UrlReward (Visit)
|
||||||
|
case 'urlreward':
|
||||||
|
log('ACTIVITY', 'Found daily activity type: UrlReward')
|
||||||
|
await doUrlReward(page, activity)
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
await wait(1500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log('PUNCH-CARD', 'Punch card items have been completed')
|
||||||
|
}
|
||||||
|
|
||||||
|
// More Promotions
|
||||||
|
export async function doMorePromotions(page: Page, data: DashboardData) {
|
||||||
|
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) ?? []
|
||||||
|
|
||||||
|
if (!activitiesUncompleted.length) {
|
||||||
|
log('MORE-PROMOTIONS', 'All more promotion items have already been completed')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const activity of activitiesUncompleted) {
|
||||||
|
// If activity does not give points, skip
|
||||||
|
if (activity.pointProgressMax <= 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (activity.promotionType) {
|
||||||
|
// Quiz (Poll, Quiz or ABC)
|
||||||
|
case 'quiz':
|
||||||
|
|
||||||
|
switch (activity.pointProgressMax) {
|
||||||
|
// Poll or ABC (Usually 10 points)
|
||||||
|
case 10:
|
||||||
|
// Normal poll
|
||||||
|
if (activity.destinationUrl.toLowerCase().includes('pollscenarioid')) {
|
||||||
|
log('ACTIVITY', 'Found daily activity type: Poll')
|
||||||
|
await doPoll(page, activity)
|
||||||
|
} else { // ABC
|
||||||
|
log('ACTIVITY', 'Found daily activity type: ABC')
|
||||||
|
await doABC(page, activity)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
// This Or That Quiz (Usually 50 points)
|
||||||
|
case 50:
|
||||||
|
log('ACTIVITY', 'Found daily activity type: ThisOrThat')
|
||||||
|
await doThisOrThat(page, activity)
|
||||||
|
break
|
||||||
|
|
||||||
|
// Quizzes are usually 30-40 points
|
||||||
|
default:
|
||||||
|
log('ACTIVITY', 'Found promotion activity type: Quiz')
|
||||||
|
await doQuiz(page, activity)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
// UrlReward (Visit)
|
||||||
|
case 'urlreward':
|
||||||
|
log('ACTIVITY', 'Found promotion activity type: UrlReward')
|
||||||
|
await doUrlReward(page, activity)
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
await wait(1500)
|
||||||
|
}
|
||||||
|
}
|
||||||
54
src/functions/activities/ABC.ts
Normal file
54
src/functions/activities/ABC.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { Page } from 'puppeteer'
|
||||||
|
|
||||||
|
import { refreshCheerio } from '../../browser/BrowserFunc'
|
||||||
|
import { getLatestTab } from '../../browser/BrowserUtil'
|
||||||
|
import { log } from '../../util/Logger'
|
||||||
|
import { randomNumber, wait } from '../../util/Utils'
|
||||||
|
|
||||||
|
import { MorePromotion, PromotionalItem } from '../../interface/DashboardData'
|
||||||
|
|
||||||
|
export async function doABC(page: Page, data: PromotionalItem | MorePromotion) {
|
||||||
|
log('ABC', 'Trying to complete poll')
|
||||||
|
|
||||||
|
try {
|
||||||
|
const selector = `[data-bi-id="${data.offerId}"]`
|
||||||
|
|
||||||
|
// Wait for page to load and click to load the quiz in a new tab
|
||||||
|
await page.waitForSelector(selector, { timeout: 5000 })
|
||||||
|
await page.click(selector)
|
||||||
|
|
||||||
|
let abcPage = await getLatestTab(page)
|
||||||
|
await wait(2000)
|
||||||
|
let $ = await refreshCheerio(abcPage)
|
||||||
|
|
||||||
|
while (!$('span.rw_icon').length) {
|
||||||
|
await abcPage.waitForSelector('.wk_OptionClickClass', { visible: true, timeout: 5000 })
|
||||||
|
|
||||||
|
const answers = $('.wk_OptionClickClass')
|
||||||
|
const answer = answers[randomNumber(0, 2)]?.attribs['id']
|
||||||
|
|
||||||
|
await abcPage.waitForSelector(`#${answer}`, { visible: true, timeout: 5000 })
|
||||||
|
|
||||||
|
await wait(2000)
|
||||||
|
await abcPage.click(`#${answer}`) // Click answer
|
||||||
|
|
||||||
|
await wait(4000)
|
||||||
|
await abcPage.waitForSelector('div.wk_button', { visible: true, timeout: 5000 })
|
||||||
|
await abcPage.click('div.wk_button') // Click next question button
|
||||||
|
|
||||||
|
abcPage = await getLatestTab(abcPage)
|
||||||
|
$ = await refreshCheerio(abcPage)
|
||||||
|
await wait(1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
await wait(4000)
|
||||||
|
await abcPage.close()
|
||||||
|
|
||||||
|
log('ABC', 'Completed the ABC successfully')
|
||||||
|
} catch (error) {
|
||||||
|
const abcPage = await getLatestTab(page)
|
||||||
|
await abcPage.close()
|
||||||
|
log('ABC', 'An error occurred:' + error, 'error')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -22,10 +22,11 @@ export async function doPoll(page: Page, data: PromotionalItem | MorePromotion)
|
|||||||
|
|
||||||
await pollPage.waitForNetworkIdle({ timeout: 5000 })
|
await pollPage.waitForNetworkIdle({ timeout: 5000 })
|
||||||
await pollPage.waitForSelector(buttonId, { visible: true, timeout: 5000 })
|
await pollPage.waitForSelector(buttonId, { visible: true, timeout: 5000 })
|
||||||
|
await wait(2000)
|
||||||
|
|
||||||
await pollPage.click(buttonId)
|
await pollPage.click(buttonId)
|
||||||
|
|
||||||
await wait(2000)
|
await wait(4000)
|
||||||
await pollPage.close()
|
await pollPage.close()
|
||||||
|
|
||||||
log('POLL', 'Completed the poll successfully')
|
log('POLL', 'Completed the poll successfully')
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export async function doQuiz(page: Page, data: PromotionalItem | MorePromotion)
|
|||||||
|
|
||||||
const quizPage = await getLatestTab(page)
|
const quizPage = await getLatestTab(page)
|
||||||
await quizPage.waitForNetworkIdle({ timeout: 5000 })
|
await quizPage.waitForNetworkIdle({ timeout: 5000 })
|
||||||
|
await wait(2000)
|
||||||
|
|
||||||
// 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)
|
||||||
|
|||||||
@@ -263,41 +263,57 @@ async function randomScroll(page: Page) {
|
|||||||
async function clickRandomLink(page: Page, mobile: boolean) {
|
async function clickRandomLink(page: Page, mobile: boolean) {
|
||||||
try {
|
try {
|
||||||
const searchListingURL = new URL(page.url()) // Get page info before clicking
|
const searchListingURL = new URL(page.url()) // Get page info before clicking
|
||||||
|
mobile
|
||||||
await page.click('#b_results .b_algo h2').catch(() => { }) // Since we don't really care if it did it or not
|
await page.click('#b_results .b_algo h2').catch(() => { }) // Since we don't really care if it did it or not
|
||||||
|
|
||||||
|
|
||||||
await wait(3000)
|
await wait(3000)
|
||||||
|
|
||||||
const newTab = await getLatestTab(page) // Will get current tab if no new one is created
|
let lastTab = await getLatestTab(page) // Will get current tab if no new one is created
|
||||||
|
await lastTab.waitForNetworkIdle() // Wait for page to load
|
||||||
|
|
||||||
// Check if the tab is closed or not
|
// Check if the tab is closed or not
|
||||||
if (!newTab.isClosed()) {
|
if (!lastTab.isClosed()) {
|
||||||
const newTabURL = new URL(newTab.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
|
// Check if the URL is different from the original one
|
||||||
if (newTabURL.href !== searchListingURL.href) {
|
while (lastTabURL.href !== searchListingURL.href) {
|
||||||
// Mobile is always same tab
|
|
||||||
if (mobile) {
|
// If hostname is still bing, (Bing images/news etc)
|
||||||
await page.goBack()
|
if (lastTabURL.hostname == searchListingURL.hostname) {
|
||||||
|
await lastTab.goBack()
|
||||||
|
|
||||||
|
lastTab = await getLatestTab(page) // Get last opened tab
|
||||||
|
lastTabURL = new URL(lastTab.url())
|
||||||
|
|
||||||
const currentURL = new URL(page.url())
|
|
||||||
// If "goBack" didn't return to search listing (due to redirects)
|
// If "goBack" didn't return to search listing (due to redirects)
|
||||||
if (currentURL.hostname !== searchListingURL.hostname) {
|
if (lastTabURL.hostname !== searchListingURL.hostname) {
|
||||||
await page.goto(searchListingURL.href)
|
await lastTab.goto(searchListingURL.href)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Still on bing, go back (news/images pages on bing search)
|
break
|
||||||
} else if (newTabURL.hostname == searchListingURL.hostname) {
|
} else { // No longer on bing, likely opened a new tab, close this tab
|
||||||
await page.goBack()
|
lastTab = await getLatestTab(page) // Get last opened tab
|
||||||
|
lastTabURL = new URL(lastTab.url())
|
||||||
|
|
||||||
const currentURL = new URL(page.url())
|
const tabs = await (page.browser()).pages() // Get all tabs open
|
||||||
// If "goBack" didn't return to search listing (due to redirects)
|
|
||||||
if (currentURL.hostname !== searchListingURL.hostname) {
|
|
||||||
await page.goto(searchListingURL.href)
|
|
||||||
}
|
|
||||||
|
|
||||||
// No longer on bing, likely opened a new tab, close this tab
|
// 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 {
|
} else {
|
||||||
await newTab.close()
|
await lastTab.goBack()
|
||||||
|
|
||||||
|
lastTab = await 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(searchListingURL.href)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export async function doThisOrThat(page: Page, data: PromotionalItem | MorePromo
|
|||||||
|
|
||||||
const thisorthatPage = await getLatestTab(page)
|
const thisorthatPage = await getLatestTab(page)
|
||||||
await thisorthatPage.waitForNetworkIdle({ timeout: 5000 })
|
await thisorthatPage.waitForNetworkIdle({ timeout: 5000 })
|
||||||
|
await wait(2000)
|
||||||
|
|
||||||
// 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)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ 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.waitForNetworkIdle({ timeout: 10_000 })
|
||||||
await visitPage.close()
|
await visitPage.close()
|
||||||
|
|
||||||
log('URL-REWARD', 'Completed the UrlReward successfully')
|
log('URL-REWARD', 'Completed the UrlReward successfully')
|
||||||
|
|||||||
47
src/index.ts
47
src/index.ts
@@ -1,10 +1,9 @@
|
|||||||
import { Browser, mobileBrowser } from './browser/Browser'
|
import Browser from './browser/Browser'
|
||||||
import { getDashboardData, getEarnablePoints, goHome } from './browser/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'
|
||||||
import { doDailySet } from './functions/DailySet'
|
import { doDailySet, doMorePromotions } from './functions/Workers'
|
||||||
import { doMorePromotions } from './functions/MorePromotions'
|
|
||||||
import { doSearch } from './functions/activities/Search'
|
import { doSearch } from './functions/activities/Search'
|
||||||
|
|
||||||
import { Account } from './interface/Account'
|
import { Account } from './interface/Account'
|
||||||
@@ -12,38 +11,41 @@ import { Account } from './interface/Account'
|
|||||||
import accounts from './accounts.json'
|
import accounts from './accounts.json'
|
||||||
import { runOnZeroPoints, searches } from './config.json'
|
import { runOnZeroPoints, searches } from './config.json'
|
||||||
|
|
||||||
let collectedPoints = 0
|
// Main bot class
|
||||||
|
class MicrosoftRewardsBot {
|
||||||
|
private collectedPoints: number = 0
|
||||||
|
private browserFactory: Browser = new Browser()
|
||||||
|
|
||||||
async function main() {
|
async run() {
|
||||||
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}`)
|
||||||
|
|
||||||
// Desktop Searches, DailySet and More Promotions
|
// Desktop Searches, DailySet and More Promotions
|
||||||
await Desktop(account)
|
await this.Desktop(account)
|
||||||
|
|
||||||
// If runOnZeroPoints is false and 0 points to earn, stop and try the next account
|
// If runOnZeroPoints is false and 0 points to earn, stop and try the next account
|
||||||
if (!runOnZeroPoints && collectedPoints === 0) {
|
if (!runOnZeroPoints && this.collectedPoints === 0) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mobile Searches
|
// Mobile Searches
|
||||||
await Mobile(account)
|
await this.Mobile(account)
|
||||||
|
|
||||||
log('MAIN', `Completed tasks for account ${account.email}`)
|
log('MAIN', `Completed tasks for account ${account.email}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Clean exit
|
// Clean exit
|
||||||
log('MAIN', 'Completed tasks for ALL accounts')
|
log('MAIN', 'Completed tasks for ALL accounts')
|
||||||
log('MAIN', 'Bot exited')
|
log('MAIN', 'Bot exited')
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Desktop
|
||||||
// Desktop
|
async Desktop(account: Account) {
|
||||||
async function Desktop(account: Account) {
|
const browser = await this.browserFactory.createBrowser(account.email, false)
|
||||||
const browser = await Browser(account.email)
|
|
||||||
const page = await browser.newPage()
|
const page = await browser.newPage()
|
||||||
|
|
||||||
log('MAIN', 'Starting DESKTOP browser')
|
log('MAIN', 'Starting DESKTOP browser')
|
||||||
@@ -60,11 +62,11 @@ async function Desktop(account: Account) {
|
|||||||
log('MAIN-POINTS', `Current point count: ${data.userStatus.availablePoints}`)
|
log('MAIN-POINTS', `Current point count: ${data.userStatus.availablePoints}`)
|
||||||
|
|
||||||
const earnablePoints = await getEarnablePoints(data)
|
const earnablePoints = await getEarnablePoints(data)
|
||||||
collectedPoints = earnablePoints
|
this.collectedPoints = earnablePoints
|
||||||
log('MAIN-POINTS', `You can earn ${earnablePoints} points today`)
|
log('MAIN-POINTS', `You can earn ${earnablePoints} points today`)
|
||||||
|
|
||||||
// If runOnZeroPoints is false and 0 points to earn, don't continue
|
// If runOnZeroPoints is false and 0 points to earn, don't continue
|
||||||
if (!runOnZeroPoints && collectedPoints === 0) {
|
if (!runOnZeroPoints && this.collectedPoints === 0) {
|
||||||
log('MAIN', 'No points to earn and "runOnZeroPoints" is set to "false", stopping')
|
log('MAIN', 'No points to earn and "runOnZeroPoints" is set to "false", stopping')
|
||||||
|
|
||||||
// Close desktop browser
|
// Close desktop browser
|
||||||
@@ -84,10 +86,10 @@ async function Desktop(account: Account) {
|
|||||||
|
|
||||||
// Close desktop browser
|
// Close desktop browser
|
||||||
await browser.close()
|
await browser.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function Mobile(account: Account) {
|
async Mobile(account: Account) {
|
||||||
const browser = await mobileBrowser(account.email)
|
const browser = await this.browserFactory.createBrowser(account.email, true)
|
||||||
const page = await browser.newPage()
|
const page = await browser.newPage()
|
||||||
|
|
||||||
log('MAIN', 'Starting MOBILE browser')
|
log('MAIN', 'Starting MOBILE browser')
|
||||||
@@ -114,13 +116,14 @@ async function Mobile(account: Account) {
|
|||||||
|
|
||||||
// Fetch new points
|
// Fetch new points
|
||||||
const earnablePoints = await getEarnablePoints(data, page)
|
const earnablePoints = await getEarnablePoints(data, page)
|
||||||
|
|
||||||
// If the new earnable is 0, means we got all the points, else retract
|
// If the new earnable is 0, means we got all the points, else retract
|
||||||
collectedPoints = earnablePoints === 0 ? collectedPoints : (collectedPoints - earnablePoints)
|
this.collectedPoints = earnablePoints === 0 ? this.collectedPoints : (this.collectedPoints - earnablePoints)
|
||||||
log('MAIN-POINTS', `The script collected ${collectedPoints} points today`)
|
log('MAIN-POINTS', `The script collected ${this.collectedPoints} points today`)
|
||||||
|
|
||||||
// Close mobile browser
|
// Close mobile browser
|
||||||
await browser.close()
|
await browser.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run main script
|
new MicrosoftRewardsBot().run()
|
||||||
main()
|
|
||||||
Reference in New Issue
Block a user