mirror of
https://github.com/LightZirconite/Microsoft-Rewards-Bot.git
synced 2026-01-10 01:06:17 +00:00
New structure
This commit is contained in:
@@ -52,16 +52,12 @@ browser/
|
|||||||
.eslintcache
|
.eslintcache
|
||||||
setup/
|
setup/
|
||||||
|
|
||||||
# Docker files (no recursion)
|
# Docker files (organized in docker/ folder - no recursion needed)
|
||||||
Dockerfile
|
docker/
|
||||||
docker-compose.yml
|
|
||||||
compose.yaml
|
|
||||||
.dockerignore
|
.dockerignore
|
||||||
|
|
||||||
# NixOS specific files (not needed in Docker)
|
# Scripts (organized in scripts/ folder - not needed in Docker)
|
||||||
flake.nix
|
scripts/
|
||||||
flake.lock
|
|
||||||
run.sh
|
|
||||||
|
|
||||||
# Asset files (not needed for runtime)
|
# Asset files (not needed for runtime)
|
||||||
assets/
|
assets/
|
||||||
|
|||||||
55
.github/copilot-instructions.md
vendored
55
.github/copilot-instructions.md
vendored
@@ -44,17 +44,33 @@ src/
|
|||||||
│ ├── Poll.ts # Poll completion
|
│ ├── Poll.ts # Poll completion
|
||||||
│ ├── ThisOrThat.ts # This or That game
|
│ ├── ThisOrThat.ts # This or That game
|
||||||
│ └── ...
|
│ └── ...
|
||||||
├── util/ # Shared utilities + infrastructure
|
├── util/ # Shared utilities (ORGANIZED BY CATEGORY)
|
||||||
│ ├── Axios.ts # HTTP client with proxy support
|
│ ├── core/ # Core utilities
|
||||||
│ ├── BrowserFactory.ts # Centralized browser creation
|
│ │ ├── Utils.ts # General-purpose helpers
|
||||||
│ ├── Humanizer.ts # Random delays, mouse gestures
|
│ │ └── Retry.ts # Exponential backoff retry logic
|
||||||
│ ├── BanDetector.ts # Heuristic ban detection
|
│ ├── network/ # HTTP & API utilities
|
||||||
│ ├── QueryDiversityEngine.ts # Multi-source search query generation
|
│ │ ├── Axios.ts # HTTP client with proxy support
|
||||||
│ ├── JobState.ts # Persistent job state tracking
|
│ │ └── QueryDiversityEngine.ts # Multi-source search query generation
|
||||||
|
│ ├── browser/ # Browser automation utilities
|
||||||
|
│ │ ├── BrowserFactory.ts # Centralized browser creation
|
||||||
|
│ │ ├── Humanizer.ts # Random delays, mouse gestures
|
||||||
|
│ │ └── UserAgent.ts # User agent generation
|
||||||
|
│ ├── state/ # State & persistence
|
||||||
|
│ │ ├── JobState.ts # Persistent job state tracking
|
||||||
|
│ │ ├── Load.ts # Configuration & session loading
|
||||||
|
│ │ └── MobileRetryTracker.ts # Mobile search retry tracking
|
||||||
|
│ ├── validation/ # Validation & detection
|
||||||
|
│ │ ├── StartupValidator.ts # Comprehensive startup validation
|
||||||
|
│ │ ├── BanDetector.ts # Heuristic ban detection
|
||||||
|
│ │ └── LoginStateDetector.ts # Login state detection
|
||||||
|
│ ├── security/ # Authentication & security
|
||||||
|
│ │ └── Totp.ts # TOTP generation for 2FA
|
||||||
|
│ └── notifications/ # Logging & notifications
|
||||||
│ ├── Logger.ts # Centralized logging with redaction
|
│ ├── Logger.ts # Centralized logging with redaction
|
||||||
│ ├── Retry.ts # Exponential backoff retry logic
|
│ ├── ConclusionWebhook.ts # Summary webhook notifications
|
||||||
│ ├── Utils.ts # General-purpose helpers
|
│ ├── ErrorReportingWebhook.ts # Error reporting
|
||||||
│ └── ...
|
│ ├── Ntfy.ts # Push notifications
|
||||||
|
│ └── AdaptiveThrottler.ts # Adaptive delay management
|
||||||
├── dashboard/ # Real-time web dashboard (Express + WebSocket)
|
├── dashboard/ # Real-time web dashboard (Express + WebSocket)
|
||||||
│ ├── server.ts # Express server + routes
|
│ ├── server.ts # Express server + routes
|
||||||
│ ├── routes.ts # API endpoints
|
│ ├── routes.ts # API endpoints
|
||||||
@@ -73,9 +89,20 @@ src/
|
|||||||
├── nameDatabase.ts # First/last name pool
|
├── nameDatabase.ts # First/last name pool
|
||||||
├── types.ts # Account creation interfaces
|
├── types.ts # Account creation interfaces
|
||||||
└── README.md # Account creation guide
|
└── README.md # Account creation guide
|
||||||
|
docker/ # Docker deployment files
|
||||||
|
├── Dockerfile # Multi-stage Docker build
|
||||||
|
├── compose.yaml # Docker Compose configuration
|
||||||
|
├── entrypoint.sh # Container initialization script
|
||||||
|
├── run_daily.sh # Daily execution wrapper (cron)
|
||||||
|
└── crontab.template # Cron schedule template
|
||||||
|
scripts/ # Utility scripts
|
||||||
|
└── run.sh # Nix development environment launcher
|
||||||
setup/
|
setup/
|
||||||
├── setup.bat # Windows setup script
|
├── setup.bat # Windows setup script
|
||||||
├── setup.sh # Linux/Mac setup script
|
├── setup.sh # Linux/Mac setup script
|
||||||
|
├── nix/ # NixOS configuration
|
||||||
|
│ ├── flake.nix # Nix flake definition
|
||||||
|
│ └── flake.lock # Nix flake lock file
|
||||||
└── update/
|
└── update/
|
||||||
├── setup.mjs # Initial setup automation
|
├── setup.mjs # Initial setup automation
|
||||||
└── update.mjs # GitHub ZIP-based auto-updater (NO GIT REQUIRED!)
|
└── update.mjs # GitHub ZIP-based auto-updater (NO GIT REQUIRED!)
|
||||||
@@ -986,8 +1013,8 @@ private combinedDeduplication(queries: string[], threshold = 0.65): string[] {
|
|||||||
|
|
||||||
### Docker & Scheduling Context
|
### Docker & Scheduling Context
|
||||||
|
|
||||||
**entrypoint.sh:**
|
**docker/entrypoint.sh:**
|
||||||
- **Purpose:** Docker container initialization script
|
- **Purpose:** Docker container initialization script (located in `docker/` directory)
|
||||||
- **Key Features:**
|
- **Key Features:**
|
||||||
- Timezone configuration (env: `TZ`, default UTC)
|
- Timezone configuration (env: `TZ`, default UTC)
|
||||||
- Initial run on start (env: `RUN_ON_START=true`)
|
- Initial run on start (env: `RUN_ON_START=true`)
|
||||||
@@ -995,8 +1022,8 @@ private combinedDeduplication(queries: string[], threshold = 0.65): string[] {
|
|||||||
- Playwright browser preinstallation (`PLAYWRIGHT_BROWSERS_PATH=0`)
|
- Playwright browser preinstallation (`PLAYWRIGHT_BROWSERS_PATH=0`)
|
||||||
- **Usage:** Docker Compose sets `CRON_SCHEDULE`, container runs cron in foreground
|
- **Usage:** Docker Compose sets `CRON_SCHEDULE`, container runs cron in foreground
|
||||||
|
|
||||||
**run_daily.sh:**
|
**docker/run_daily.sh:**
|
||||||
- **Purpose:** Daily execution wrapper for cron jobs
|
- **Purpose:** Daily execution wrapper for cron jobs (located in `docker/` directory)
|
||||||
- **Key Features:**
|
- **Key Features:**
|
||||||
- Random sleep delay (0-30min) to avoid simultaneous runs across containers
|
- Random sleep delay (0-30min) to avoid simultaneous runs across containers
|
||||||
- Environment variable: `SKIP_RANDOM_SLEEP=true` to disable delay
|
- Environment variable: `SKIP_RANDOM_SLEEP=true` to disable delay
|
||||||
|
|||||||
@@ -80,11 +80,12 @@ COPY --from=builder /usr/src/microsoft-rewards-bot/package*.json ./
|
|||||||
COPY --from=builder /usr/src/microsoft-rewards-bot/node_modules ./node_modules
|
COPY --from=builder /usr/src/microsoft-rewards-bot/node_modules ./node_modules
|
||||||
|
|
||||||
# Copy runtime scripts with proper permissions and normalize line endings for non-Unix users
|
# Copy runtime scripts with proper permissions and normalize line endings for non-Unix users
|
||||||
COPY --chmod=755 src/run_daily.sh ./src/run_daily.sh
|
# IMPROVED: Scripts now organized in docker/ folder
|
||||||
COPY --chmod=644 src/crontab.template /etc/cron.d/microsoft-rewards-cron.template
|
COPY --chmod=755 docker/run_daily.sh ./docker/run_daily.sh
|
||||||
COPY --chmod=755 entrypoint.sh /usr/local/bin/entrypoint.sh
|
COPY --chmod=644 docker/crontab.template /etc/cron.d/microsoft-rewards-cron.template
|
||||||
|
COPY --chmod=755 docker/entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||||
RUN sed -i 's/\r$//' /usr/local/bin/entrypoint.sh \
|
RUN sed -i 's/\r$//' /usr/local/bin/entrypoint.sh \
|
||||||
&& sed -i 's/\r$//' ./src/run_daily.sh
|
&& sed -i 's/\r$//' ./docker/run_daily.sh
|
||||||
|
|
||||||
# Entrypoint handles TZ, initial run toggle, cron templating & launch
|
# Entrypoint handles TZ, initial run toggle, cron templating & launch
|
||||||
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
# Run automation according to CRON_SCHEDULE; redirect both stdout & stderr to Docker logs
|
# Run automation according to CRON_SCHEDULE; redirect both stdout & stderr to Docker logs
|
||||||
${CRON_SCHEDULE} TZ=${TZ} /bin/bash /usr/src/microsoft-rewards-bot/src/run_daily.sh >> /proc/1/fd/1 2>&1
|
${CRON_SCHEDULE} TZ=${TZ} /bin/bash /usr/src/microsoft-rewards-bot/docker/run_daily.sh >> /proc/1/fd/1 2>&1
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ if [ "${RUN_ON_START:-false}" = "true" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
# Skip random sleep for initial run, but preserve setting for cron jobs
|
# Skip random sleep for initial run, but preserve setting for cron jobs
|
||||||
SKIP_RANDOM_SLEEP=true src/run_daily.sh
|
SKIP_RANDOM_SLEEP=true docker/run_daily.sh
|
||||||
echo "[entrypoint-bg] Initial run completed at $(date)"
|
echo "[entrypoint-bg] Initial run completed at $(date)"
|
||||||
) &
|
) &
|
||||||
echo "[entrypoint] Background process started (PID: $!)"
|
echo "[entrypoint] Background process started (PID: $!)"
|
||||||
22
scripts/README.md
Normal file
22
scripts/README.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Scripts Directory
|
||||||
|
|
||||||
|
This directory contains utility scripts for development and deployment.
|
||||||
|
|
||||||
|
## Available Scripts
|
||||||
|
|
||||||
|
### `run.sh`
|
||||||
|
**Purpose:** Nix development environment launcher
|
||||||
|
**Usage:** `./run.sh`
|
||||||
|
**Description:** Launches the bot using Nix develop environment with xvfb-run for headless browser support.
|
||||||
|
|
||||||
|
**Requirements:**
|
||||||
|
- Nix package manager
|
||||||
|
- xvfb (X Virtual Framebuffer)
|
||||||
|
|
||||||
|
**Environment:**
|
||||||
|
This script is designed for NixOS or systems with Nix installed. It provides a reproducible development environment as defined in `setup/nix/flake.nix`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
For Docker deployment, see the `docker/` directory.
|
||||||
|
For setup scripts, see the `setup/` directory.
|
||||||
0
flake.lock → setup/nix/flake.lock
generated
0
flake.lock → setup/nix/flake.lock
generated
@@ -2,7 +2,7 @@ import fs from 'fs'
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import * as readline from 'readline'
|
import * as readline from 'readline'
|
||||||
import type { BrowserContext, Page } from 'rebrowser-playwright'
|
import type { BrowserContext, Page } from 'rebrowser-playwright'
|
||||||
import { log } from '../util/Logger'
|
import { log } from '../util/notifications/Logger'
|
||||||
import { DataGenerator } from './DataGenerator'
|
import { DataGenerator } from './DataGenerator'
|
||||||
import { CreatedAccount } from './types'
|
import { CreatedAccount } from './types'
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Browser from '../browser/Browser'
|
import Browser from '../browser/Browser'
|
||||||
import { MicrosoftRewardsBot } from '../index'
|
import { MicrosoftRewardsBot } from '../index'
|
||||||
import { log } from '../util/Logger'
|
import { log } from '../util/notifications/Logger'
|
||||||
import { AccountCreator } from './AccountCreator'
|
import { AccountCreator } from './AccountCreator'
|
||||||
|
|
||||||
async function main(): Promise<void> {
|
async function main(): Promise<void> {
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import playwright, { BrowserContext } from 'rebrowser-playwright'
|
|||||||
|
|
||||||
import { MicrosoftRewardsBot } from '../index'
|
import { MicrosoftRewardsBot } from '../index'
|
||||||
import { AccountProxy } from '../interface/Account'
|
import { AccountProxy } from '../interface/Account'
|
||||||
import { loadSessionData, saveFingerprintData } from '../util/Load'
|
import { updateFingerprintUserAgent } from '../util/browser/UserAgent'
|
||||||
import { updateFingerprintUserAgent } from '../util/UserAgent'
|
import { loadSessionData, saveFingerprintData } from '../util/state/Load'
|
||||||
|
|
||||||
class Browser {
|
class Browser {
|
||||||
private bot: MicrosoftRewardsBot
|
private bot: MicrosoftRewardsBot
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { AppUserData } from '../interface/AppUserData'
|
|||||||
import { Counters, DashboardData, MorePromotion, PromotionalItem } from '../interface/DashboardData'
|
import { Counters, DashboardData, MorePromotion, PromotionalItem } from '../interface/DashboardData'
|
||||||
import { EarnablePoints } from '../interface/Points'
|
import { EarnablePoints } from '../interface/Points'
|
||||||
import { QuizData } from '../interface/QuizData'
|
import { QuizData } from '../interface/QuizData'
|
||||||
import { saveSessionData } from '../util/Load'
|
import { saveSessionData } from '../util/state/Load'
|
||||||
|
|
||||||
|
|
||||||
export default class BrowserFunc {
|
export default class BrowserFunc {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { load } from 'cheerio'
|
import { load } from 'cheerio'
|
||||||
import { Page } from 'rebrowser-playwright'
|
import { Page } from 'rebrowser-playwright'
|
||||||
import { MicrosoftRewardsBot } from '../index'
|
import { MicrosoftRewardsBot } from '../index'
|
||||||
import { logError } from '../util/Logger'
|
import { logError } from '../util/notifications/Logger'
|
||||||
|
|
||||||
type DismissButton = { selector: string; label: string; isXPath?: boolean }
|
type DismissButton = { selector: string; label: string; isXPath?: boolean }
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ function parseEnvNumber(key: string, defaultValue: number, min: number, max: num
|
|||||||
const parsed = Number(raw)
|
const parsed = Number(raw)
|
||||||
if (!Number.isFinite(parsed)) {
|
if (!Number.isFinite(parsed)) {
|
||||||
queueMicrotask(() => {
|
queueMicrotask(() => {
|
||||||
import('./util/Logger').then(({ log }) => {
|
import('./util/notifications/Logger').then(({ log }) => {
|
||||||
log('main', 'CONSTANTS', `Invalid ${key}="${raw}" (not a finite number), using default: ${defaultValue}`, 'warn')
|
log('main', 'CONSTANTS', `Invalid ${key}="${raw}" (not a finite number), using default: ${defaultValue}`, 'warn')
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
process.stderr.write(`[Constants] Invalid ${key}="${raw}" (not a finite number), using default: ${defaultValue}\n`)
|
process.stderr.write(`[Constants] Invalid ${key}="${raw}" (not a finite number), using default: ${defaultValue}\n`)
|
||||||
@@ -29,7 +29,7 @@ function parseEnvNumber(key: string, defaultValue: number, min: number, max: num
|
|||||||
|
|
||||||
if (parsed < min || parsed > max) {
|
if (parsed < min || parsed > max) {
|
||||||
queueMicrotask(() => {
|
queueMicrotask(() => {
|
||||||
import('./util/Logger').then(({ log }) => {
|
import('./util/notifications/Logger').then(({ log }) => {
|
||||||
log('main', 'CONSTANTS', `${key}=${parsed} out of range [${min}, ${max}], using default: ${defaultValue}`, 'warn')
|
log('main', 'CONSTANTS', `${key}=${parsed} out of range [${min}, ${max}], using default: ${defaultValue}`, 'warn')
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
process.stderr.write(`[Constants] ${key}=${parsed} out of range [${min}, ${max}], using default: ${defaultValue}\n`)
|
process.stderr.write(`[Constants] ${key}=${parsed} out of range [${min}, ${max}], using default: ${defaultValue}\n`)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { MicrosoftRewardsBot } from '../index'
|
import type { MicrosoftRewardsBot } from '../index'
|
||||||
import { log as botLog } from '../util/Logger'
|
import { getErrorMessage } from '../util/core/Utils'
|
||||||
import { getErrorMessage } from '../util/Utils'
|
import { log as botLog } from '../util/notifications/Logger'
|
||||||
import { dashboardState } from './state'
|
import { dashboardState } from './state'
|
||||||
|
|
||||||
export class BotController {
|
export class BotController {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Request, Response, Router } from 'express'
|
import { Request, Response, Router } from 'express'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { getConfigPath, loadAccounts, loadConfig } from '../util/Load'
|
import { getConfigPath, loadAccounts, loadConfig } from '../util/state/Load'
|
||||||
import { botController } from './BotController'
|
import { botController } from './BotController'
|
||||||
import { dashboardState } from './state'
|
import { dashboardState } from './state'
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import fs from 'fs'
|
|||||||
import { createServer } from 'http'
|
import { createServer } from 'http'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { WebSocket, WebSocketServer } from 'ws'
|
import { WebSocket, WebSocketServer } from 'ws'
|
||||||
import { log as botLog } from '../util/Logger'
|
import { log as botLog } from '../util/notifications/Logger'
|
||||||
import { apiRouter } from './routes'
|
import { apiRouter } from './routes'
|
||||||
import { DashboardLog, dashboardState } from './state'
|
import { DashboardLog, dashboardState } from './state'
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
import type { MicrosoftRewardsBot } from '../index'
|
import type { MicrosoftRewardsBot } from '../index'
|
||||||
import type { Account } from '../interface/Account'
|
import type { Account } from '../interface/Account'
|
||||||
import { closeBrowserSafely, createBrowserInstance } from '../util/BrowserFactory'
|
import { closeBrowserSafely, createBrowserInstance } from '../util/browser/BrowserFactory'
|
||||||
import { handleCompromisedMode } from './FlowUtils'
|
import { handleCompromisedMode } from './FlowUtils'
|
||||||
|
|
||||||
export interface DesktopFlowResult {
|
export interface DesktopFlowResult {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { MicrosoftRewardsBot } from '../index'
|
import type { MicrosoftRewardsBot } from '../index'
|
||||||
import { saveSessionData } from '../util/Load'
|
import { saveSessionData } from '../util/state/Load'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle compromised/security check mode for an account
|
* Handle compromised/security check mode for an account
|
||||||
@@ -38,7 +38,7 @@ export async function handleCompromisedMode(
|
|||||||
|
|
||||||
// Send security alert webhook
|
// Send security alert webhook
|
||||||
try {
|
try {
|
||||||
const { ConclusionWebhook } = await import('../util/ConclusionWebhook')
|
const { ConclusionWebhook } = await import('../util/notifications/ConclusionWebhook')
|
||||||
await ConclusionWebhook(
|
await ConclusionWebhook(
|
||||||
bot.config,
|
bot.config,
|
||||||
isMobile ? '🔐 Security Check (Mobile)' : '🔐 Security Check',
|
isMobile ? '🔐 Security Check (Mobile)' : '🔐 Security Check',
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
|
|
||||||
import type { MicrosoftRewardsBot } from '../index'
|
import type { MicrosoftRewardsBot } from '../index'
|
||||||
import type { Account } from '../interface/Account'
|
import type { Account } from '../interface/Account'
|
||||||
import { closeBrowserSafely, createBrowserInstance } from '../util/BrowserFactory'
|
import { closeBrowserSafely, createBrowserInstance } from '../util/browser/BrowserFactory'
|
||||||
import { MobileRetryTracker } from '../util/MobileRetryTracker'
|
import { MobileRetryTracker } from '../util/state/MobileRetryTracker'
|
||||||
import { handleCompromisedMode } from './FlowUtils'
|
import { handleCompromisedMode } from './FlowUtils'
|
||||||
|
|
||||||
export interface MobileFlowResult {
|
export interface MobileFlowResult {
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Config } from '../interface/Config'
|
import type { Config } from '../interface/Config'
|
||||||
import { ConclusionWebhook } from '../util/ConclusionWebhook'
|
import { ConclusionWebhook } from '../util/notifications/ConclusionWebhook'
|
||||||
import { JobState } from '../util/JobState'
|
import { log } from '../util/notifications/Logger'
|
||||||
import { log } from '../util/Logger'
|
import { Ntfy } from '../util/notifications/Ntfy'
|
||||||
import { Ntfy } from '../util/Ntfy'
|
import { JobState } from '../util/state/JobState'
|
||||||
|
|
||||||
export interface AccountResult {
|
export interface AccountResult {
|
||||||
email: string
|
email: string
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import readline from 'readline'
|
|||||||
|
|
||||||
import { MicrosoftRewardsBot } from '../index'
|
import { MicrosoftRewardsBot } from '../index'
|
||||||
import { OAuth } from '../interface/OAuth'
|
import { OAuth } from '../interface/OAuth'
|
||||||
import { saveSessionData } from '../util/Load'
|
import { Retry } from '../util/core/Retry'
|
||||||
import { logError } from '../util/Logger'
|
import { logError } from '../util/notifications/Logger'
|
||||||
import { LoginState, LoginStateDetector } from '../util/LoginStateDetector'
|
import { generateTOTP } from '../util/security/Totp'
|
||||||
import { Retry } from '../util/Retry'
|
import { saveSessionData } from '../util/state/Load'
|
||||||
import { generateTOTP } from '../util/Totp'
|
import { LoginState, LoginStateDetector } from '../util/validation/LoginStateDetector'
|
||||||
|
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
// REFACTORING NOTE (1700+ lines)
|
// REFACTORING NOTE (1700+ lines)
|
||||||
@@ -1603,7 +1603,7 @@ export class Login {
|
|||||||
const level: 'warn' | 'error' = severity === 'critical' ? 'error' : 'warn'
|
const level: 'warn' | 'error' = severity === 'critical' ? 'error' : 'warn'
|
||||||
this.bot.log(this.bot.isMobile, 'SECURITY', lines.join(' | '), level)
|
this.bot.log(this.bot.isMobile, 'SECURITY', lines.join(' | '), level)
|
||||||
try {
|
try {
|
||||||
const { ConclusionWebhook } = await import('../util/ConclusionWebhook')
|
const { ConclusionWebhook } = await import('../util/notifications/ConclusionWebhook')
|
||||||
const fields = [
|
const fields = [
|
||||||
{ name: 'Account', value: incident.account },
|
{ name: 'Account', value: incident.account },
|
||||||
...(incident.details?.length ? [{ name: 'Details', value: incident.details.join('\n') }] : []),
|
...(incident.details?.length ? [{ name: 'Details', value: incident.details.join('\n') }] : []),
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import { TIMEOUTS } from '../constants'
|
|||||||
import { DashboardData, MorePromotion, PromotionalItem, PunchCard } from '../interface/DashboardData'
|
import { DashboardData, MorePromotion, PromotionalItem, PunchCard } from '../interface/DashboardData'
|
||||||
|
|
||||||
import { MicrosoftRewardsBot } from '../index'
|
import { MicrosoftRewardsBot } from '../index'
|
||||||
import { AdaptiveThrottler } from '../util/AdaptiveThrottler'
|
import { Retry } from '../util/core/Retry'
|
||||||
import JobState from '../util/JobState'
|
import { AdaptiveThrottler } from '../util/notifications/AdaptiveThrottler'
|
||||||
import { logError } from '../util/Logger'
|
import { logError } from '../util/notifications/Logger'
|
||||||
import { Retry } from '../util/Retry'
|
import JobState from '../util/state/JobState'
|
||||||
|
|
||||||
// Selector patterns (extracted to avoid magic strings)
|
// Selector patterns (extracted to avoid magic strings)
|
||||||
const ACTIVITY_SELECTORS = {
|
const ACTIVITY_SELECTORS = {
|
||||||
|
|||||||
24
src/index.ts
24
src/index.ts
@@ -7,16 +7,16 @@ import type { Page } from 'playwright'
|
|||||||
import { createInterface } from 'readline'
|
import { createInterface } from 'readline'
|
||||||
import BrowserFunc from './browser/BrowserFunc'
|
import BrowserFunc from './browser/BrowserFunc'
|
||||||
import BrowserUtil from './browser/BrowserUtil'
|
import BrowserUtil from './browser/BrowserUtil'
|
||||||
import Axios from './util/Axios'
|
import Humanizer from './util/browser/Humanizer'
|
||||||
import { detectBanReason } from './util/BanDetector'
|
import { formatDetailedError, normalizeRecoveryEmail, shortErrorMessage, Util } from './util/core/Utils'
|
||||||
import Humanizer from './util/Humanizer'
|
import Axios from './util/network/Axios'
|
||||||
import JobState from './util/JobState'
|
import { QueryDiversityEngine } from './util/network/QueryDiversityEngine'
|
||||||
import { loadAccounts, loadConfig } from './util/Load'
|
import { log } from './util/notifications/Logger'
|
||||||
import { log } from './util/Logger'
|
import JobState from './util/state/JobState'
|
||||||
import { MobileRetryTracker } from './util/MobileRetryTracker'
|
import { loadAccounts, loadConfig } from './util/state/Load'
|
||||||
import { QueryDiversityEngine } from './util/QueryDiversityEngine'
|
import { MobileRetryTracker } from './util/state/MobileRetryTracker'
|
||||||
import { StartupValidator } from './util/StartupValidator'
|
import { detectBanReason } from './util/validation/BanDetector'
|
||||||
import { formatDetailedError, normalizeRecoveryEmail, shortErrorMessage, Util } from './util/Utils'
|
import { StartupValidator } from './util/validation/StartupValidator'
|
||||||
|
|
||||||
import { Activities } from './functions/Activities'
|
import { Activities } from './functions/Activities'
|
||||||
import { Login } from './functions/Login'
|
import { Login } from './functions/Login'
|
||||||
@@ -629,7 +629,7 @@ export class MicrosoftRewardsBot {
|
|||||||
try {
|
try {
|
||||||
const h = this.config?.humanization
|
const h = this.config?.humanization
|
||||||
if (!h || h.immediateBanAlert === false) return
|
if (!h || h.immediateBanAlert === false) return
|
||||||
const { ConclusionWebhook } = await import('./util/ConclusionWebhook')
|
const { ConclusionWebhook } = await import('./util/notifications/ConclusionWebhook')
|
||||||
await ConclusionWebhook(
|
await ConclusionWebhook(
|
||||||
this.config,
|
this.config,
|
||||||
'🚫 Ban Detected',
|
'🚫 Ban Detected',
|
||||||
@@ -806,7 +806,7 @@ export class MicrosoftRewardsBot {
|
|||||||
/** Send a strong alert to all channels and mention @everyone when entering global security standby. */
|
/** Send a strong alert to all channels and mention @everyone when entering global security standby. */
|
||||||
private async sendGlobalSecurityStandbyAlert(email: string, reason: string): Promise<void> {
|
private async sendGlobalSecurityStandbyAlert(email: string, reason: string): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const { ConclusionWebhook } = await import('./util/ConclusionWebhook')
|
const { ConclusionWebhook } = await import('./util/notifications/ConclusionWebhook')
|
||||||
await ConclusionWebhook(
|
await ConclusionWebhook(
|
||||||
this.config,
|
this.config,
|
||||||
'🚨 Critical Security Alert',
|
'🚨 Critical Security Alert',
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { BrowserContext } from 'rebrowser-playwright'
|
import type { BrowserContext } from 'rebrowser-playwright'
|
||||||
import type { MicrosoftRewardsBot } from '../index'
|
import type { MicrosoftRewardsBot } from '../../index'
|
||||||
import type { AccountProxy } from '../interface/Account'
|
import type { AccountProxy } from '../../interface/Account'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a browser instance for the given account
|
* Create a browser instance for the given account
|
||||||
@@ -26,7 +26,7 @@ export async function createBrowserInstance(
|
|||||||
proxy: AccountProxy,
|
proxy: AccountProxy,
|
||||||
email: string
|
email: string
|
||||||
): Promise<BrowserContext> {
|
): Promise<BrowserContext> {
|
||||||
const browserModule = await import('../browser/Browser')
|
const browserModule = await import('../../browser/Browser')
|
||||||
const Browser = browserModule.default
|
const Browser = browserModule.default
|
||||||
const browserInstance = new Browser(bot)
|
const browserInstance = new Browser(bot)
|
||||||
return await browserInstance.createBrowser(proxy, email)
|
return await browserInstance.createBrowser(proxy, email)
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Page } from 'rebrowser-playwright'
|
import { Page } from 'rebrowser-playwright'
|
||||||
import { Util } from './Utils'
|
import type { ConfigHumanization } from '../../interface/Config'
|
||||||
import type { ConfigHumanization } from '../interface/Config'
|
import { Util } from '../core/Utils'
|
||||||
|
|
||||||
export class Humanizer {
|
export class Humanizer {
|
||||||
private util: Util
|
private util: Util
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { BrowserFingerprintWithHeaders } from 'fingerprint-generator'
|
import { BrowserFingerprintWithHeaders } from 'fingerprint-generator'
|
||||||
import { Architecture, ChromeVersion, EdgeVersion, Platform } from '../interface/UserAgentUtil'
|
import { Architecture, ChromeVersion, EdgeVersion, Platform } from '../../interface/UserAgentUtil'
|
||||||
import { log } from './Logger'
|
import { Retry } from '../core/Retry'
|
||||||
import { Retry } from './Retry'
|
import { log } from '../notifications/Logger'
|
||||||
|
|
||||||
interface UserAgentMetadata {
|
interface UserAgentMetadata {
|
||||||
mobile: boolean
|
mobile: boolean
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ConfigRetryPolicy } from '../interface/Config'
|
import type { ConfigRetryPolicy } from '../../interface/Config'
|
||||||
import { Util } from './Utils'
|
import { Util } from './Utils'
|
||||||
|
|
||||||
type NumericPolicy = {
|
type NumericPolicy = {
|
||||||
@@ -2,7 +2,7 @@ import axios, { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } f
|
|||||||
import { HttpProxyAgent } from 'http-proxy-agent'
|
import { HttpProxyAgent } from 'http-proxy-agent'
|
||||||
import { HttpsProxyAgent } from 'https-proxy-agent'
|
import { HttpsProxyAgent } from 'https-proxy-agent'
|
||||||
import { SocksProxyAgent } from 'socks-proxy-agent'
|
import { SocksProxyAgent } from 'socks-proxy-agent'
|
||||||
import { AccountProxy } from '../interface/Account'
|
import { AccountProxy } from '../../interface/Account'
|
||||||
|
|
||||||
class AxiosClient {
|
class AxiosClient {
|
||||||
private instance: AxiosInstance
|
private instance: AxiosInstance
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { Util } from './Utils'
|
import { Util } from '../core/Utils'
|
||||||
|
|
||||||
export interface QueryDiversityConfig {
|
export interface QueryDiversityConfig {
|
||||||
sources: Array<'google-trends' | 'reddit' | 'news' | 'wikipedia' | 'local-fallback'>
|
sources: Array<'google-trends' | 'reddit' | 'news' | 'wikipedia' | 'local-fallback'>
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { Config } from '../interface/Config'
|
import { DISCORD } from '../../constants'
|
||||||
import { Ntfy } from './Ntfy'
|
import { Config } from '../../interface/Config'
|
||||||
import { log } from './Logger'
|
import { log } from './Logger'
|
||||||
import { DISCORD } from '../constants'
|
import { Ntfy } from './Ntfy'
|
||||||
|
|
||||||
interface DiscordField {
|
interface DiscordField {
|
||||||
name: string
|
name: string
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { DISCORD } from '../constants'
|
import { DISCORD } from '../../constants'
|
||||||
import { Config } from '../interface/Config'
|
import { Config } from '../../interface/Config'
|
||||||
|
|
||||||
interface ErrorReportPayload {
|
interface ErrorReportPayload {
|
||||||
error: string
|
error: string
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import chalk from 'chalk'
|
import chalk from 'chalk'
|
||||||
import { DISCORD, LOGGER_CLEANUP } from '../constants'
|
import { DISCORD, LOGGER_CLEANUP } from '../../constants'
|
||||||
|
import { loadConfig } from '../state/Load'
|
||||||
import { sendErrorReport } from './ErrorReportingWebhook'
|
import { sendErrorReport } from './ErrorReportingWebhook'
|
||||||
import { loadConfig } from './Load'
|
|
||||||
import { Ntfy } from './Ntfy'
|
import { Ntfy } from './Ntfy'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { loadConfig } from './Load'
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
import { loadConfig } from '../state/Load'
|
||||||
|
|
||||||
const NOTIFICATION_TYPES = {
|
const NOTIFICATION_TYPES = {
|
||||||
error: { priority: 'max', tags: 'rotating_light' }, // Customize the ERROR icon here, see: https://docs.ntfy.sh/emojis/
|
error: { priority: 'max', tags: 'rotating_light' }, // Customize the ERROR icon here, see: https://docs.ntfy.sh/emojis/
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import type { Config } from '../interface/Config'
|
import type { Config } from '../../interface/Config'
|
||||||
|
|
||||||
type AccountCompletionMeta = {
|
type AccountCompletionMeta = {
|
||||||
runId?: string
|
runId?: string
|
||||||
@@ -2,9 +2,9 @@ import { BrowserFingerprintWithHeaders } from 'fingerprint-generator'
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { BrowserContext, Cookie } from 'rebrowser-playwright'
|
import { BrowserContext, Cookie } from 'rebrowser-playwright'
|
||||||
import { Account } from '../interface/Account'
|
import { Account } from '../../interface/Account'
|
||||||
import { Config, ConfigBrowser, ConfigSaveFingerprint, ConfigScheduling } from '../interface/Config'
|
import { Config, ConfigBrowser, ConfigSaveFingerprint, ConfigScheduling } from '../../interface/Config'
|
||||||
import { Util } from './Utils'
|
import { Util } from '../core/Utils'
|
||||||
|
|
||||||
const utils = new Util()
|
const utils = new Util()
|
||||||
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import chalk from 'chalk'
|
import chalk from 'chalk'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { Account } from '../interface/Account'
|
import { Account } from '../../interface/Account'
|
||||||
import { Config } from '../interface/Config'
|
import { Config } from '../../interface/Config'
|
||||||
import { log } from './Logger'
|
import { log } from '../notifications/Logger'
|
||||||
|
|
||||||
interface ValidationError {
|
interface ValidationError {
|
||||||
severity: 'error' | 'warning'
|
severity: 'error' | 'warning'
|
||||||
Reference in New Issue
Block a user