Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4af1d0e
feat: add V4 Microsoft Rewards UI support
Mar 16, 2026
0e0743d
feat: add V4 activity completion attempt
Mar 16, 2026
34da6bf
feat: V4 activity completion - visit page first attempt
Mar 16, 2026
1129728
feat: implement V4 activity completion API from PR #496
Mar 17, 2026
9181edd
fix: improve V4 activity completion and error handling
Mar 17, 2026
99485eb
feat: improve V4 implementation with session validation, fallback han…
Mar 17, 2026
ad4ad7c
feat: add Keep Earning section detection and improve V4 activity comp…
Mar 17, 2026
f13c28d
feat: V4 research phase 1 completion - optimized Workers, UrlReward A…
Mar 17, 2026
e030e24
fix: combine userInfo.promotions with flyoutResult for Keep Earning a…
Mar 17, 2026
acb5a4d
fix: improve V4 Keep Earning detection - handle userInfo.promotions s…
Mar 17, 2026
a7547d9
chore: update V4 dashboard data with latest points dump
Mar 17, 2026
acfef59
refactor: clean up verbose debug logging in Workers.ts
Mar 17, 2026
a6b5946
chore: remove test log files from root directory
Mar 17, 2026
9dc739b
chore: move v4_dashboard_dump.json to refrensi/ directory
Mar 17, 2026
b9f76dc
chore: track v4_dashboard_dump.json in refrensi/
Mar 17, 2026
f31ba2f
refactor: rename ACTIVITY-V4 tag to ACTIVITY
Mar 17, 2026
3636344
refactor: simplify activity filtering - remove hardcoded ENstar filter
Mar 17, 2026
ac86508
fix: improve activity lookup and simplify complete check
Mar 17, 2026
2f92060
refactor: remove debug dump code (not in v3)
Mar 18, 2026
dc486f0
refactor: align UrlReward with PR #496 - use flyoutResult.morePromotions
Mar 18, 2026
99a5cd8
Revert "refactor: align UrlReward with PR #496 - use flyoutResult.mor…
Mar 18, 2026
6ab7288
docs: add AGENTS.md with coding guidelines and build commands for age…
Mar 19, 2026
4b68b2c
feat: implement headless-mode-compatible quest task detection and cli…
Mar 25, 2026
6f32e99
fix: set desktop viewport and user agent before processing quests
Mar 25, 2026
6c437f4
docs: update context with headless mode testing results
Mar 25, 2026
3f58e1a
fix: disable quests in headless mode with clear user message
Mar 25, 2026
2623784
docs: add quest headless investigation findings and recommendations
Mar 25, 2026
325bbda
feat: implement API-based quest processing for headless mode
Mar 25, 2026
571c2cc
revert: restore DOM-based quest detection with bing search and ms-sea…
Mar 25, 2026
e2bb2e7
chore: clean quest implementation - remove API/diagnostic overhead
Mar 25, 2026
31dbf77
chore: remove temporary log files
Mar 26, 2026
91a8568
chore: remove logs, reference files, and generated metadata
Mar 26, 2026
7937ae4
docs: improve Quest.ts JSDoc - clarify ms-search limitation and worka…
Mar 26, 2026
4134d88
chore: add tsconfig.tsbuildinfo to gitignore
Mar 26, 2026
352e851
Revert "chore: add tsconfig.tsbuildinfo to gitignore"
Mar 26, 2026
79f133e
chore: remove tsconfig.tsbuildinfo build artifact
Mar 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "microsoft-rewards-script",
"version": "3.1.4",
"version": "4.0.0-beta.1",
"description": "Automatically do tasks for Microsoft Rewards but in TS!",
"author": "Netsky",
"license": "GPL-3.0-or-later",
Expand All @@ -11,6 +11,7 @@
"pre-build": "npm i && rimraf dist && npx patchright install chromium",
"build": "rimraf dist && tsc",
"start": "node ./dist/index.js",
"start:log": "node ./dist/index.js 2>&1 | tee logs/bot-$(date +%Y%m%d-%H%M%S).log",
"ts-start": "ts-node ./src/index.ts",
"dev": "ts-node ./src/index.ts -dev",
"kill-chrome-win": "powershell -Command \"Get-Process | Where-Object { $_.MainModule.FileVersionInfo.FileDescription -eq 'Google Chrome for Testing' } | ForEach-Object { Stop-Process -Id $_.Id -Force }\"",
Expand Down
463 changes: 270 additions & 193 deletions src/browser/BrowserFunc.ts

Large diffs are not rendered by default.

15 changes: 9 additions & 6 deletions src/browser/UserAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ export class UserAgentManager {
const data: ChromeVersion = response.data
return data.channels.Stable.version
} catch (error) {
this.bot.logger.error(
this.bot.logger.warn(
isMobile,
'USERAGENT-CHROME-VERSION',
`An error occurred: ${error instanceof Error ? error.message : String(error)}`
`Failed to fetch Chrome version, using fallback: ${error instanceof Error ? error.message : String(error)}`
)
throw error
return isMobile ? '146.0.7680.80' : '146.0.0.0'
}
}

Expand All @@ -82,12 +82,15 @@ export class UserAgentManager {
windows: stable.Releases.find(x => x.Platform == 'Windows' && x.Architecture == 'x64')?.ProductVersion
}
} catch (error) {
this.bot.logger.error(
this.bot.logger.warn(
isMobile,
'USERAGENT-EDGE-VERSION',
`An error occurred: ${error instanceof Error ? error.message : String(error)}`
`Failed to fetch Edge version, using fallback: ${error instanceof Error ? error.message : String(error)}`
)
throw error
return {
android: '145.0.3800.99',
windows: '145.0.3800.99'
}
}
}

Expand Down
28 changes: 25 additions & 3 deletions src/browser/auth/Login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,14 @@ export class Login {
private async detectCurrentState(page: Page, account?: Account): Promise<LoginState> {
await page.waitForLoadState('networkidle', { timeout: 5000 }).catch(() => {})

const pageContent = await page.innerText('body').catch(() => '')
if (
pageContent.toLowerCase().includes('too many requests') ||
pageContent.toLowerCase().includes('banyak permintaan')
) {
return 'ERROR_ALERT'
}

const url = new URL(page.url())
this.bot.logger.debug(this.bot.isMobile, 'DETECT-STATE', `Current URL: ${url.hostname}${url.pathname}`)

Expand Down Expand Up @@ -292,9 +300,23 @@ export class Login {
}

case 'ERROR_ALERT': {
const alertEl = page.locator(this.selectors.errorAlert)
const errorMsg = await alertEl.innerText().catch(() => 'Unknown Error')
this.bot.logger.error(this.bot.isMobile, 'LOGIN', `Account error: ${errorMsg}`)
const alertEl = page.locator(this.selectors.errorAlert).first()
let errorMsg = await alertEl.innerText().catch(() => '')

if (!errorMsg) {
const bodyText = await page.innerText('body').catch(() => '')
if (
bodyText.toLowerCase().includes('too many requests') ||
bodyText.toLowerCase().includes('banyak permintaan')
) {
errorMsg = 'Too many requests'
} else {
errorMsg = 'Unknown Error (Check screenshot)'
}
}

this.bot.logger.error(this.bot.isMobile, 'LOGIN', `Account error detected: ${errorMsg}`)

throw new Error(`Microsoft login error: ${errorMsg}`)
}

Expand Down
3 changes: 2 additions & 1 deletion src/config.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"doDesktopSearch": true,
"doMobileSearch": true,
"doDailyCheckIn": true,
"doReadToEarn": true
"doReadToEarn": true,
"doQuests": true
},
"searchOnBingLocalQueries": false,
"globalTimeout": "30sec",
Expand Down
7 changes: 7 additions & 0 deletions src/functions/Activities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { DoubleSearchPoints } from './activities/api/DoubleSearchPoints'
// Browser
import { SearchOnBing } from './activities/browser/SearchOnBing'
import { Search } from './activities/browser/Search'
import { Quest } from './activities/browser/Quest'

import type {
BasePromotion,
Expand Down Expand Up @@ -99,4 +100,10 @@ export default class Activities {
const dailyCheckIn = new DailyCheckIn(this.bot)
await dailyCheckIn.doDailyCheckIn()
}

// Quest Activities
doQuests = async (page: Page): Promise<void> => {
const quest = new Quest(this.bot)
await quest.doQuests(page)
}
}
Loading