mirror of
https://github.com/LightZirconite/Microsoft-Rewards-Bot.git
synced 2026-01-10 17:26:17 +00:00
Refactor: Simplify recovery email handling and validation; update documentation for clarity
This commit is contained in:
@@ -21,7 +21,7 @@
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> ℹ️ `recoveryEmail` is still **recommended**. It lets the bot verify Microsoft’s masked hint during login and alert you if the recovery address ever changes. You can opt out per account by setting `"recoveryRequired": false`.
|
> ℹ️ `recoveryEmail` is **optional but recommended**. It lets the bot verify Microsoft's masked hint during login and alert you if the recovery address ever changes. Simply leave it empty (`""`) if not needed.
|
||||||
|
|
||||||
**That's it!** Run `npm start` to test.
|
**That's it!** Run `npm start` to test.
|
||||||
|
|
||||||
@@ -60,9 +60,9 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🚫 Skip the Recovery Email Check (Advanced)
|
## 🚫 Skip the Recovery Email (Advanced)
|
||||||
|
|
||||||
Most users should keep recovery validation enabled. If an account genuinely has no recovery address or you cannot disclose it, add `"recoveryRequired": false` to that entry. When disabled, the bot skips mismatch detection and logs a warning during startup validation.
|
If an account genuinely has no recovery address or you prefer not to provide it, simply leave the `recoveryEmail` field empty:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -70,13 +70,13 @@ Most users should keep recovery validation enabled. If an account genuinely has
|
|||||||
{
|
{
|
||||||
"email": "example@outlook.com",
|
"email": "example@outlook.com",
|
||||||
"password": "strong_password",
|
"password": "strong_password",
|
||||||
"recoveryRequired": false
|
"recoveryEmail": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
> ⚠️ Without a recovery email the bot cannot detect if Microsoft shows a different masked address. Enable this override only when you accept that risk.
|
> ℹ️ The bot will automatically skip recovery validation when this field is empty. A warning will be logged during startup, but the bot will function normally.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,8 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"email": "",
|
"email": "",
|
||||||
"password": "",
|
"password": "",
|
||||||
"totp": "",
|
"totp": "", // Optional: leave empty if no 2FA, or put your TOTP secret
|
||||||
"recoveryRequired": true,
|
"recoveryEmail": "", // Optional: recovery email for security challenges
|
||||||
"recoveryEmail": "",
|
|
||||||
"proxy": {
|
"proxy": {
|
||||||
"proxyAxios": false,
|
"proxyAxios": false,
|
||||||
"url": "",
|
"url": "",
|
||||||
@@ -24,7 +23,6 @@
|
|||||||
"email": "",
|
"email": "",
|
||||||
"password": "",
|
"password": "",
|
||||||
"totp": "",
|
"totp": "",
|
||||||
"recoveryRequired": true,
|
|
||||||
"recoveryEmail": "",
|
"recoveryEmail": "",
|
||||||
"proxy": {
|
"proxy": {
|
||||||
"proxyAxios": false,
|
"proxyAxios": false,
|
||||||
@@ -40,7 +38,6 @@
|
|||||||
"email": "",
|
"email": "",
|
||||||
"password": "",
|
"password": "",
|
||||||
"totp": "",
|
"totp": "",
|
||||||
"recoveryRequired": true,
|
|
||||||
"recoveryEmail": "",
|
"recoveryEmail": "",
|
||||||
"proxy": {
|
"proxy": {
|
||||||
"proxyAxios": false,
|
"proxyAxios": false,
|
||||||
@@ -56,7 +53,6 @@
|
|||||||
"email": "",
|
"email": "",
|
||||||
"password": "",
|
"password": "",
|
||||||
"totp": "",
|
"totp": "",
|
||||||
"recoveryRequired": true,
|
|
||||||
"recoveryEmail": "",
|
"recoveryEmail": "",
|
||||||
"proxy": {
|
"proxy": {
|
||||||
"proxyAxios": false,
|
"proxyAxios": false,
|
||||||
@@ -72,7 +68,6 @@
|
|||||||
"email": "",
|
"email": "",
|
||||||
"password": "",
|
"password": "",
|
||||||
"totp": "",
|
"totp": "",
|
||||||
"recoveryRequired": true,
|
|
||||||
"recoveryEmail": "",
|
"recoveryEmail": "",
|
||||||
"proxy": {
|
"proxy": {
|
||||||
"proxyAxios": false,
|
"proxyAxios": false,
|
||||||
|
|||||||
@@ -162,11 +162,7 @@ class Browser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async generateFingerprint() {
|
async generateFingerprint() {
|
||||||
const fingerPrintData = new FingerprintGenerator().getFingerprint({
|
const fingerPrintData = new FingerprintGenerator().getFingerprint()
|
||||||
devices: this.bot.isMobile ? ['mobile'] : ['desktop'],
|
|
||||||
operatingSystems: this.bot.isMobile ? ['android'] : ['windows'],
|
|
||||||
browsers: [{ name: 'edge' }]
|
|
||||||
})
|
|
||||||
|
|
||||||
const updatedFingerPrintData = await updateFingerprintUserAgent(fingerPrintData, this.bot.isMobile)
|
const updatedFingerPrintData = await updateFingerprintUserAgent(fingerPrintData, this.bot.isMobile)
|
||||||
|
|
||||||
|
|||||||
@@ -145,7 +145,7 @@
|
|||||||
|
|
||||||
// Updates
|
// Updates
|
||||||
"update": {
|
"update": {
|
||||||
"enabled": true, // Enable automatic updates (default: true)
|
"enabled": true, // Enable automatic updates (default: true) - DISABLED to preserve custom modifications
|
||||||
"method": "github-api", // Update method: "git" or "github-api" (recommended: "github-api")
|
"method": "github-api", // Update method: "git" or "github-api" (recommended: "github-api")
|
||||||
// "git" = Uses Git commands (requires Git installed, can have conflicts)
|
// "git" = Uses Git commands (requires Git installed, can have conflicts)
|
||||||
// "github-api" = Downloads ZIP from GitHub (no Git needed, no conflicts, recommended)
|
// "github-api" = Downloads ZIP from GitHub (no Git needed, no conflicts, recommended)
|
||||||
|
|||||||
@@ -5,10 +5,8 @@ export interface Account {
|
|||||||
password: string;
|
password: string;
|
||||||
/** Optional TOTP secret in Base32 (e.g., from Microsoft Authenticator setup) */
|
/** Optional TOTP secret in Base32 (e.g., from Microsoft Authenticator setup) */
|
||||||
totp?: string;
|
totp?: string;
|
||||||
/** Recovery email used during security challenge verification */
|
/** Recovery email used during security challenge verification. Leave empty if not needed. */
|
||||||
recoveryEmail?: string;
|
recoveryEmail?: string;
|
||||||
/** Override to allow skipping recovery email checks for this account */
|
|
||||||
recoveryRequired?: boolean;
|
|
||||||
proxy: AccountProxy;
|
proxy: AccountProxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -379,27 +379,20 @@ export function loadAccounts(): Account[] {
|
|||||||
}
|
}
|
||||||
a.email = String(a.email).trim()
|
a.email = String(a.email).trim()
|
||||||
a.password = String(a.password)
|
a.password = String(a.password)
|
||||||
const recoveryRequired = a.recoveryRequired !== false
|
|
||||||
a.recoveryRequired = recoveryRequired
|
|
||||||
|
|
||||||
if (recoveryRequired) {
|
// Simplified recovery email logic: if present and non-empty, validate it
|
||||||
if (typeof a.recoveryEmail !== 'string') {
|
if (typeof a.recoveryEmail === 'string') {
|
||||||
throw new Error(`account ${a.email || '<unknown>'} must include a recoveryEmail string (or set "recoveryRequired": false)`)
|
|
||||||
}
|
|
||||||
a.recoveryEmail = String(a.recoveryEmail).trim()
|
|
||||||
if (!a.recoveryEmail || !/@/.test(a.recoveryEmail)) {
|
|
||||||
throw new Error(`account ${a.email} recoveryEmail must be a valid email address (got: "${a.recoveryEmail}") - set "recoveryRequired": false if not needed`)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (typeof a.recoveryEmail === 'string' && a.recoveryEmail.trim() !== '') {
|
|
||||||
const trimmed = a.recoveryEmail.trim()
|
const trimmed = a.recoveryEmail.trim()
|
||||||
|
if (trimmed !== '') {
|
||||||
if (!/@/.test(trimmed)) {
|
if (!/@/.test(trimmed)) {
|
||||||
throw new Error(`account ${a.email} recoveryEmail must be a valid email address`)
|
throw new Error(`account ${a.email} recoveryEmail must be a valid email address (got: "${trimmed}")`)
|
||||||
}
|
}
|
||||||
a.recoveryEmail = trimmed
|
a.recoveryEmail = trimmed
|
||||||
} else {
|
} else {
|
||||||
a.recoveryEmail = undefined
|
a.recoveryEmail = undefined
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
a.recoveryEmail = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!a.proxy || typeof a.proxy !== 'object') {
|
if (!a.proxy || typeof a.proxy !== 'object') {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
import chalk from 'chalk'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import chalk from 'chalk'
|
|
||||||
import { Config } from '../interface/Config'
|
|
||||||
import { Account } from '../interface/Account'
|
import { Account } from '../interface/Account'
|
||||||
|
import { Config } from '../interface/Config'
|
||||||
import { log } from './Logger'
|
import { log } from './Logger'
|
||||||
|
|
||||||
interface ValidationError {
|
interface ValidationError {
|
||||||
@@ -105,43 +105,22 @@ export class StartupValidator {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const recoveryRequired = account.recoveryRequired !== false
|
// Simplified: only validate recovery email if provided
|
||||||
if (recoveryRequired) {
|
if (account.recoveryEmail && typeof account.recoveryEmail === 'string' && account.recoveryEmail.trim() !== '') {
|
||||||
if (!account.recoveryEmail || typeof account.recoveryEmail !== 'string') {
|
if (!/@/.test(account.recoveryEmail)) {
|
||||||
this.addError(
|
|
||||||
'accounts',
|
|
||||||
`${prefix}: Missing required field "recoveryEmail"`,
|
|
||||||
'Add your recovery/backup email address. This is required for security checks unless you explicitly disable it.\nExample: "recoveryEmail": "backup@gmail.com"',
|
|
||||||
'docs/accounts.md'
|
|
||||||
)
|
|
||||||
} else if (!/@/.test(account.recoveryEmail)) {
|
|
||||||
this.addError(
|
this.addError(
|
||||||
'accounts',
|
'accounts',
|
||||||
`${prefix}: Recovery email format is invalid`,
|
`${prefix}: Recovery email format is invalid`,
|
||||||
'Recovery email must be a valid email address (e.g., backup@gmail.com)'
|
'Recovery email must be a valid email address (e.g., backup@gmail.com)'
|
||||||
)
|
)
|
||||||
} else if (account.recoveryEmail.trim() === '') {
|
|
||||||
this.addError(
|
|
||||||
'accounts',
|
|
||||||
`${prefix}: Recovery email cannot be empty`,
|
|
||||||
'Provide the actual recovery email associated with this Microsoft account'
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!account.recoveryEmail || account.recoveryEmail.trim() === '') {
|
|
||||||
this.addWarning(
|
this.addWarning(
|
||||||
'accounts',
|
'accounts',
|
||||||
`${prefix}: Recovery email checks disabled`,
|
`${prefix}: No recovery email configured`,
|
||||||
'The bot will skip recovery-email mismatch detection for this account. Re-enable by removing "recoveryRequired": false.',
|
'Recovery email is optional but recommended for security challenge verification',
|
||||||
'docs/accounts.md'
|
'docs/accounts.md'
|
||||||
)
|
)
|
||||||
} else if (!/@/.test(account.recoveryEmail)) {
|
|
||||||
this.addError(
|
|
||||||
'accounts',
|
|
||||||
`${prefix}: Recovery email format is invalid`,
|
|
||||||
'Recovery email must be a valid email address (e.g., backup@gmail.com)'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optional but recommended: TOTP
|
// Optional but recommended: TOTP
|
||||||
|
|||||||
Reference in New Issue
Block a user