From 773304fc851fd43e01ba69f0250697d505cc4c46 Mon Sep 17 00:00:00 2001 From: LightZirconite Date: Sat, 8 Nov 2025 21:26:06 +0100 Subject: [PATCH] Refactor: Simplify recovery email handling and validation; update documentation for clarity --- docs/accounts.md | 10 ++++----- src/accounts.example.jsonc | 9 ++------ src/browser/Browser.ts | 6 +---- src/config.jsonc | 2 +- src/interface/Account.ts | 4 +--- src/util/Load.ts | 21 ++++++------------ src/util/StartupValidator.ts | 43 +++++++++--------------------------- 7 files changed, 28 insertions(+), 67 deletions(-) diff --git a/docs/accounts.md b/docs/accounts.md index 9d22c7c..f15caa6 100644 --- a/docs/accounts.md +++ b/docs/accounts.md @@ -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. @@ -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 { @@ -70,13 +70,13 @@ Most users should keep recovery validation enabled. If an account genuinely has { "email": "example@outlook.com", "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. --- diff --git a/src/accounts.example.jsonc b/src/accounts.example.jsonc index 8590a36..be84499 100644 --- a/src/accounts.example.jsonc +++ b/src/accounts.example.jsonc @@ -7,9 +7,8 @@ "enabled": true, "email": "", "password": "", - "totp": "", - "recoveryRequired": true, - "recoveryEmail": "", + "totp": "", // Optional: leave empty if no 2FA, or put your TOTP secret + "recoveryEmail": "", // Optional: recovery email for security challenges "proxy": { "proxyAxios": false, "url": "", @@ -24,7 +23,6 @@ "email": "", "password": "", "totp": "", - "recoveryRequired": true, "recoveryEmail": "", "proxy": { "proxyAxios": false, @@ -40,7 +38,6 @@ "email": "", "password": "", "totp": "", - "recoveryRequired": true, "recoveryEmail": "", "proxy": { "proxyAxios": false, @@ -56,7 +53,6 @@ "email": "", "password": "", "totp": "", - "recoveryRequired": true, "recoveryEmail": "", "proxy": { "proxyAxios": false, @@ -72,7 +68,6 @@ "email": "", "password": "", "totp": "", - "recoveryRequired": true, "recoveryEmail": "", "proxy": { "proxyAxios": false, diff --git a/src/browser/Browser.ts b/src/browser/Browser.ts index ea1c105..ce7a816 100644 --- a/src/browser/Browser.ts +++ b/src/browser/Browser.ts @@ -162,11 +162,7 @@ class Browser { } async generateFingerprint() { - const fingerPrintData = new FingerprintGenerator().getFingerprint({ - devices: this.bot.isMobile ? ['mobile'] : ['desktop'], - operatingSystems: this.bot.isMobile ? ['android'] : ['windows'], - browsers: [{ name: 'edge' }] - }) + const fingerPrintData = new FingerprintGenerator().getFingerprint() const updatedFingerPrintData = await updateFingerprintUserAgent(fingerPrintData, this.bot.isMobile) diff --git a/src/config.jsonc b/src/config.jsonc index 2632412..e3c32b5 100644 --- a/src/config.jsonc +++ b/src/config.jsonc @@ -145,7 +145,7 @@ // Updates "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") // "git" = Uses Git commands (requires Git installed, can have conflicts) // "github-api" = Downloads ZIP from GitHub (no Git needed, no conflicts, recommended) diff --git a/src/interface/Account.ts b/src/interface/Account.ts index c91d6e9..bc0f34b 100644 --- a/src/interface/Account.ts +++ b/src/interface/Account.ts @@ -5,10 +5,8 @@ export interface Account { password: string; /** Optional TOTP secret in Base32 (e.g., from Microsoft Authenticator setup) */ totp?: string; - /** Recovery email used during security challenge verification */ + /** Recovery email used during security challenge verification. Leave empty if not needed. */ recoveryEmail?: string; - /** Override to allow skipping recovery email checks for this account */ - recoveryRequired?: boolean; proxy: AccountProxy; } diff --git a/src/util/Load.ts b/src/util/Load.ts index 41254dc..281f670 100644 --- a/src/util/Load.ts +++ b/src/util/Load.ts @@ -379,27 +379,20 @@ export function loadAccounts(): Account[] { } a.email = String(a.email).trim() a.password = String(a.password) - const recoveryRequired = a.recoveryRequired !== false - a.recoveryRequired = recoveryRequired - if (recoveryRequired) { - if (typeof a.recoveryEmail !== 'string') { - throw new Error(`account ${a.email || ''} 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() + // Simplified recovery email logic: if present and non-empty, validate it + if (typeof a.recoveryEmail === 'string') { + const trimmed = a.recoveryEmail.trim() + if (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 } else { a.recoveryEmail = undefined } + } else { + a.recoveryEmail = undefined } if (!a.proxy || typeof a.proxy !== 'object') { diff --git a/src/util/StartupValidator.ts b/src/util/StartupValidator.ts index 55eaa37..6fdd665 100644 --- a/src/util/StartupValidator.ts +++ b/src/util/StartupValidator.ts @@ -1,8 +1,8 @@ +import chalk from 'chalk' import fs from 'fs' import path from 'path' -import chalk from 'chalk' -import { Config } from '../interface/Config' import { Account } from '../interface/Account' +import { Config } from '../interface/Config' import { log } from './Logger' interface ValidationError { @@ -105,43 +105,22 @@ export class StartupValidator { ) } - const recoveryRequired = account.recoveryRequired !== false - if (recoveryRequired) { - if (!account.recoveryEmail || typeof account.recoveryEmail !== 'string') { - 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)) { + // Simplified: only validate recovery email if provided + if (account.recoveryEmail && typeof account.recoveryEmail === 'string' && account.recoveryEmail.trim() !== '') { + 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)' ) - } 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 { - if (!account.recoveryEmail || account.recoveryEmail.trim() === '') { - this.addWarning( - 'accounts', - `${prefix}: Recovery email checks disabled`, - 'The bot will skip recovery-email mismatch detection for this account. Re-enable by removing "recoveryRequired": false.', - '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)' - ) - } + this.addWarning( + 'accounts', + `${prefix}: No recovery email configured`, + 'Recovery email is optional but recommended for security challenge verification', + 'docs/accounts.md' + ) } // Optional but recommended: TOTP