mirror of
https://github.com/TheNetsky/Microsoft-Rewards-Script.git
synced 2026-01-19 06:23:58 +00:00
v3 init
Based of v3.0.0b10.
This commit is contained in:
130
src/functions/activities/api/FindClippy.ts
Normal file
130
src/functions/activities/api/FindClippy.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
import type { AxiosRequestConfig } from 'axios'
|
||||
import type { FindClippyPromotion } from '../../../interface/DashboardData'
|
||||
import { Workers } from '../../Workers'
|
||||
|
||||
export class FindClippy extends Workers {
|
||||
private cookieHeader: string = ''
|
||||
|
||||
private fingerprintHeader: { [x: string]: string } = {}
|
||||
|
||||
private gainedPoints: number = 0
|
||||
|
||||
private oldBalance: number = this.bot.userData.currentPoints
|
||||
|
||||
public async doFindClippy(promotion: FindClippyPromotion) {
|
||||
const offerId = promotion.offerId
|
||||
const activityType = promotion.activityType
|
||||
|
||||
try {
|
||||
if (!this.bot.requestToken) {
|
||||
this.bot.logger.warn(
|
||||
this.bot.isMobile,
|
||||
'FIND-CLIPPY',
|
||||
'Skipping: Request token not available, this activity requires it!'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
this.cookieHeader = (this.bot.isMobile ? this.bot.cookies.mobile : this.bot.cookies.desktop)
|
||||
.map((c: { name: string; value: string }) => `${c.name}=${c.value}`)
|
||||
.join('; ')
|
||||
|
||||
const fingerprintHeaders = { ...this.bot.fingerprint.headers }
|
||||
delete fingerprintHeaders['Cookie']
|
||||
delete fingerprintHeaders['cookie']
|
||||
this.fingerprintHeader = fingerprintHeaders
|
||||
|
||||
this.bot.logger.info(
|
||||
this.bot.isMobile,
|
||||
'FIND-CLIPPY',
|
||||
`Starting Find Clippy | offerId=${offerId} | activityType=${activityType} | oldBalance=${this.oldBalance}`
|
||||
)
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'FIND-CLIPPY',
|
||||
`Prepared headers | cookieLength=${this.cookieHeader.length} | fingerprintHeaderKeys=${Object.keys(this.fingerprintHeader).length}`
|
||||
)
|
||||
|
||||
const formData = new URLSearchParams({
|
||||
id: offerId,
|
||||
hash: promotion.hash,
|
||||
timeZone: '60',
|
||||
activityAmount: '1',
|
||||
dbs: '0',
|
||||
form: '',
|
||||
type: activityType,
|
||||
__RequestVerificationToken: this.bot.requestToken
|
||||
})
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'FIND-CLIPPY',
|
||||
`Prepared Find Clippy form data | offerId=${offerId} | hash=${promotion.hash} | timeZone=60 | activityAmount=1 | type=${activityType}`
|
||||
)
|
||||
|
||||
const request: AxiosRequestConfig = {
|
||||
url: 'https://rewards.bing.com/api/reportactivity?X-Requested-With=XMLHttpRequest',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...(this.bot.fingerprint?.headers ?? {}),
|
||||
Cookie: this.cookieHeader,
|
||||
Referer: 'https://rewards.bing.com/',
|
||||
Origin: 'https://rewards.bing.com'
|
||||
},
|
||||
data: formData
|
||||
}
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'FIND-CLIPPY',
|
||||
`Sending Find Clippy request | offerId=${offerId} | url=${request.url}`
|
||||
)
|
||||
|
||||
const response = await this.bot.axios.request(request)
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'FIND-CLIPPY',
|
||||
`Received Find Clippy response | offerId=${offerId} | status=${response.status}`
|
||||
)
|
||||
|
||||
const newBalance = await this.bot.browser.func.getCurrentPoints()
|
||||
this.gainedPoints = newBalance - this.oldBalance
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'FIND-CLIPPY',
|
||||
`Balance delta after Find Clippy | offerId=${offerId} | oldBalance=${this.oldBalance} | newBalance=${newBalance} | gainedPoints=${this.gainedPoints}`
|
||||
)
|
||||
|
||||
if (this.gainedPoints > 0) {
|
||||
this.bot.userData.currentPoints = newBalance
|
||||
this.bot.userData.gainedPoints = (this.bot.userData.gainedPoints ?? 0) + this.gainedPoints
|
||||
|
||||
this.bot.logger.info(
|
||||
this.bot.isMobile,
|
||||
'FIND-CLIPPY',
|
||||
`Found Clippy | offerId=${offerId} | status=${response.status} | gainedPoints=${this.gainedPoints} | newBalance=${newBalance}`,
|
||||
'green'
|
||||
)
|
||||
} else {
|
||||
this.bot.logger.warn(
|
||||
this.bot.isMobile,
|
||||
'FIND-CLIPPY',
|
||||
`Found Clippy but no points were gained | offerId=${offerId} | status=${response.status} | oldBalance=${this.oldBalance} | newBalance=${newBalance}`
|
||||
)
|
||||
}
|
||||
|
||||
this.bot.logger.debug(this.bot.isMobile, 'FIND-CLIPPY', `Waiting after Find Clippy | offerId=${offerId}`)
|
||||
|
||||
await this.bot.utils.wait(this.bot.utils.randomDelay(5000, 10000))
|
||||
} catch (error) {
|
||||
this.bot.logger.error(
|
||||
this.bot.isMobile,
|
||||
'FIND-CLIPPY',
|
||||
`Error in doFindClippy | offerId=${offerId} | message=${error instanceof Error ? error.message : String(error)}`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
173
src/functions/activities/api/Quiz.ts
Normal file
173
src/functions/activities/api/Quiz.ts
Normal file
@@ -0,0 +1,173 @@
|
||||
import type { AxiosRequestConfig } from 'axios'
|
||||
import type { BasePromotion } from '../../../interface/DashboardData'
|
||||
import { Workers } from '../../Workers'
|
||||
|
||||
export class Quiz extends Workers {
|
||||
private cookieHeader: string = ''
|
||||
|
||||
private fingerprintHeader: { [x: string]: string } = {}
|
||||
|
||||
private gainedPoints: number = 0
|
||||
|
||||
private oldBalance: number = this.bot.userData.currentPoints
|
||||
|
||||
async doQuiz(promotion: BasePromotion) {
|
||||
const offerId = promotion.offerId
|
||||
this.oldBalance = Number(this.bot.userData.currentPoints ?? 0)
|
||||
const startBalance = this.oldBalance
|
||||
|
||||
this.bot.logger.info(
|
||||
this.bot.isMobile,
|
||||
'QUIZ',
|
||||
`Starting quiz | offerId=${offerId} | pointProgressMax=${promotion.pointProgressMax} | activityProgressMax=${promotion.activityProgressMax} | currentPoints=${startBalance}`
|
||||
)
|
||||
|
||||
try {
|
||||
this.cookieHeader = (this.bot.isMobile ? this.bot.cookies.mobile : this.bot.cookies.desktop)
|
||||
.map((c: { name: string; value: string }) => `${c.name}=${c.value}`)
|
||||
.join('; ')
|
||||
|
||||
const fingerprintHeaders = { ...this.bot.fingerprint.headers }
|
||||
delete fingerprintHeaders['Cookie']
|
||||
delete fingerprintHeaders['cookie']
|
||||
this.fingerprintHeader = fingerprintHeaders
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'QUIZ',
|
||||
`Prepared quiz headers | offerId=${offerId} | cookieLength=${this.cookieHeader.length} | fingerprintHeaderKeys=${Object.keys(this.fingerprintHeader).length}`
|
||||
)
|
||||
|
||||
// 8-question quiz
|
||||
if (promotion.activityProgressMax === 80) {
|
||||
this.bot.logger.warn(
|
||||
this.bot.isMobile,
|
||||
'QUIZ',
|
||||
`Detected 8-question quiz (activityProgressMax=80), marking as completed | offerId=${offerId}`
|
||||
)
|
||||
|
||||
// Not implemented
|
||||
return
|
||||
}
|
||||
|
||||
//Standard points quizzes (20/30/40/50 max)
|
||||
if ([20, 30, 40, 50].includes(promotion.pointProgressMax)) {
|
||||
let oldBalance = startBalance
|
||||
let gainedPoints = 0
|
||||
const maxAttempts = 20
|
||||
let totalGained = 0
|
||||
let attempts = 0
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'QUIZ',
|
||||
`Starting ReportActivity loop | offerId=${offerId} | maxAttempts=${maxAttempts} | startingBalance=${oldBalance}`
|
||||
)
|
||||
|
||||
for (let i = 0; i < maxAttempts; i++) {
|
||||
try {
|
||||
const jsonData = {
|
||||
UserId: null,
|
||||
TimeZoneOffset: -60,
|
||||
OfferId: offerId,
|
||||
ActivityCount: 1,
|
||||
QuestionIndex: '-1'
|
||||
}
|
||||
|
||||
const request: AxiosRequestConfig = {
|
||||
url: 'https://www.bing.com/bingqa/ReportActivity?ajaxreq=1',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
cookie: this.cookieHeader,
|
||||
...this.fingerprintHeader
|
||||
},
|
||||
data: JSON.stringify(jsonData)
|
||||
}
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'QUIZ',
|
||||
`Sending ReportActivity request | attempt=${i + 1}/${maxAttempts} | offerId=${offerId} | url=${request.url}`
|
||||
)
|
||||
|
||||
const response = await this.bot.axios.request(request)
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'QUIZ',
|
||||
`Received ReportActivity response | attempt=${i + 1}/${maxAttempts} | offerId=${offerId} | status=${response.status}`
|
||||
)
|
||||
|
||||
const newBalance = await this.bot.browser.func.getCurrentPoints()
|
||||
gainedPoints = newBalance - oldBalance
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'QUIZ',
|
||||
`Balance delta after ReportActivity | attempt=${i + 1}/${maxAttempts} | offerId=${offerId} | oldBalance=${oldBalance} | newBalance=${newBalance} | gainedPoints=${gainedPoints}`
|
||||
)
|
||||
|
||||
attempts = i + 1
|
||||
|
||||
if (gainedPoints > 0) {
|
||||
this.bot.userData.currentPoints = newBalance
|
||||
this.bot.userData.gainedPoints = (this.bot.userData.gainedPoints ?? 0) + gainedPoints
|
||||
|
||||
oldBalance = newBalance
|
||||
totalGained += gainedPoints
|
||||
this.gainedPoints += gainedPoints
|
||||
|
||||
this.bot.logger.info(
|
||||
this.bot.isMobile,
|
||||
'QUIZ',
|
||||
`ReportActivity ${i + 1} → ${response.status} | offerId=${offerId} | gainedPoints=${gainedPoints} | newBalance=${newBalance}`,
|
||||
'green'
|
||||
)
|
||||
} else {
|
||||
this.bot.logger.warn(
|
||||
this.bot.isMobile,
|
||||
'QUIZ',
|
||||
`ReportActivity ${i + 1} | offerId=${offerId} | no more points gained, ending quiz | lastBalance=${newBalance}`
|
||||
)
|
||||
break
|
||||
}
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'QUIZ',
|
||||
`Waiting between ReportActivity attempts | attempt=${i + 1}/${maxAttempts} | offerId=${offerId}`
|
||||
)
|
||||
|
||||
await this.bot.utils.wait(this.bot.utils.randomDelay(5000, 7000))
|
||||
} catch (error) {
|
||||
this.bot.logger.error(
|
||||
this.bot.isMobile,
|
||||
'QUIZ',
|
||||
`Error during ReportActivity | attempt=${i + 1}/${maxAttempts} | offerId=${offerId} | message=${error instanceof Error ? error.message : String(error)}`
|
||||
)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
this.bot.logger.info(
|
||||
this.bot.isMobile,
|
||||
'QUIZ',
|
||||
`Completed the quiz successfully | offerId=${offerId} | attempts=${attempts} | totalGained=${totalGained} | startBalance=${startBalance} | finalBalance=${this.bot.userData.currentPoints}`
|
||||
)
|
||||
} else {
|
||||
this.bot.logger.warn(
|
||||
this.bot.isMobile,
|
||||
'QUIZ',
|
||||
`Unsupported quiz configuration | offerId=${offerId} | pointProgressMax=${promotion.pointProgressMax} | activityProgressMax=${promotion.activityProgressMax}`
|
||||
)
|
||||
}
|
||||
} catch (error) {
|
||||
this.bot.logger.error(
|
||||
this.bot.isMobile,
|
||||
'QUIZ',
|
||||
`Error in doQuiz | offerId=${promotion.offerId} | message=${error instanceof Error ? error.message : String(error)}`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
129
src/functions/activities/api/UrlReward.ts
Normal file
129
src/functions/activities/api/UrlReward.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import type { AxiosRequestConfig } from 'axios'
|
||||
import type { BasePromotion } from '../../../interface/DashboardData'
|
||||
import { Workers } from '../../Workers'
|
||||
|
||||
export class UrlReward extends Workers {
|
||||
private cookieHeader: string = ''
|
||||
|
||||
private fingerprintHeader: { [x: string]: string } = {}
|
||||
|
||||
private gainedPoints: number = 0
|
||||
|
||||
private oldBalance: number = this.bot.userData.currentPoints
|
||||
|
||||
public async doUrlReward(promotion: BasePromotion) {
|
||||
if (!this.bot.requestToken) {
|
||||
this.bot.logger.warn(
|
||||
this.bot.isMobile,
|
||||
'URL-REWARD',
|
||||
'Skipping: Request token not available, this activity requires it!'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const offerId = promotion.offerId
|
||||
|
||||
this.bot.logger.info(
|
||||
this.bot.isMobile,
|
||||
'URL-REWARD',
|
||||
`Starting UrlReward | offerId=${offerId} | geo=${this.bot.userData.geoLocale} | oldBalance=${this.oldBalance}`
|
||||
)
|
||||
|
||||
try {
|
||||
this.cookieHeader = (this.bot.isMobile ? this.bot.cookies.mobile : this.bot.cookies.desktop)
|
||||
.map((c: { name: string; value: string }) => `${c.name}=${c.value}`)
|
||||
.join('; ')
|
||||
|
||||
const fingerprintHeaders = { ...this.bot.fingerprint.headers }
|
||||
delete fingerprintHeaders['Cookie']
|
||||
delete fingerprintHeaders['cookie']
|
||||
this.fingerprintHeader = fingerprintHeaders
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'URL-REWARD',
|
||||
`Prepared UrlReward headers | offerId=${offerId} | cookieLength=${this.cookieHeader.length} | fingerprintHeaderKeys=${Object.keys(this.fingerprintHeader).length}`
|
||||
)
|
||||
|
||||
const formData = new URLSearchParams({
|
||||
id: offerId,
|
||||
hash: promotion.hash,
|
||||
timeZone: '60',
|
||||
activityAmount: '1',
|
||||
dbs: '0',
|
||||
form: '',
|
||||
type: '',
|
||||
__RequestVerificationToken: this.bot.requestToken
|
||||
})
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'URL-REWARD',
|
||||
`Prepared UrlReward form data | offerId=${offerId} | hash=${promotion.hash} | timeZone=60 | activityAmount=1`
|
||||
)
|
||||
|
||||
const request: AxiosRequestConfig = {
|
||||
url: 'https://rewards.bing.com/api/reportactivity?X-Requested-With=XMLHttpRequest',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...(this.bot.fingerprint?.headers ?? {}),
|
||||
Cookie: this.cookieHeader,
|
||||
Referer: 'https://rewards.bing.com/',
|
||||
Origin: 'https://rewards.bing.com'
|
||||
},
|
||||
data: formData
|
||||
}
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'URL-REWARD',
|
||||
`Sending UrlReward request | offerId=${offerId} | url=${request.url}`
|
||||
)
|
||||
|
||||
const response = await this.bot.axios.request(request)
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'URL-REWARD',
|
||||
`Received UrlReward response | offerId=${offerId} | status=${response.status}`
|
||||
)
|
||||
|
||||
const newBalance = await this.bot.browser.func.getCurrentPoints()
|
||||
this.gainedPoints = newBalance - this.oldBalance
|
||||
|
||||
this.bot.logger.debug(
|
||||
this.bot.isMobile,
|
||||
'URL-REWARD',
|
||||
`Balance delta after UrlReward | offerId=${offerId} | oldBalance=${this.oldBalance} | newBalance=${newBalance} | gainedPoints=${this.gainedPoints}`
|
||||
)
|
||||
|
||||
if (this.gainedPoints > 0) {
|
||||
this.bot.userData.currentPoints = newBalance
|
||||
this.bot.userData.gainedPoints = (this.bot.userData.gainedPoints ?? 0) + this.gainedPoints
|
||||
|
||||
this.bot.logger.info(
|
||||
this.bot.isMobile,
|
||||
'URL-REWARD',
|
||||
`Completed UrlReward | offerId=${offerId} | status=${response.status} | gainedPoints=${this.gainedPoints} | newBalance=${newBalance}`,
|
||||
'green'
|
||||
)
|
||||
} else {
|
||||
this.bot.logger.warn(
|
||||
this.bot.isMobile,
|
||||
'URL-REWARD',
|
||||
`Failed UrlReward with no points | offerId=${offerId} | status=${response.status} | oldBalance=${this.oldBalance} | newBalance=${newBalance}`
|
||||
)
|
||||
}
|
||||
|
||||
this.bot.logger.debug(this.bot.isMobile, 'URL-REWARD', `Waiting after UrlReward | offerId=${offerId}`)
|
||||
|
||||
await this.bot.utils.wait(this.bot.utils.randomDelay(5000, 10000))
|
||||
} catch (error) {
|
||||
this.bot.logger.error(
|
||||
this.bot.isMobile,
|
||||
'URL-REWARD',
|
||||
`Error in doUrlReward | offerId=${promotion.offerId} | message=${error instanceof Error ? error.message : String(error)}`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user