feat: Refactor configuration files for clarity and structure; enhance error reporting with obfuscated webhook URL

This commit is contained in:
2025-11-09 19:38:32 +01:00
parent a9d73f45e2
commit 842218ca4d
5 changed files with 69 additions and 103 deletions

View File

@@ -1,14 +1,13 @@
{
// Sample accounts configuration. Copy to accounts.jsonc and replace with real values.
// Maximum 5 accounts recommended to avoid detection/bans
// See docs/accounts.md for detailed configuration guide
// Maximum 5 accounts recommended
"accounts": [
{
// Account #1
"enabled": true,
"email": "",
"password": "",
"totp": "", // Optional: leave empty if no 2FA, or put your TOTP secret
"recoveryEmail": "", // Optional: recovery email for security challenges
"totp": "",
"recoveryEmail": "",
"proxy": {
"proxyAxios": false,
"url": "",
@@ -18,7 +17,6 @@
}
},
{
// Account #2
"enabled": false,
"email": "",
"password": "",
@@ -33,7 +31,6 @@
}
},
{
// Account #3
"enabled": false,
"email": "",
"password": "",
@@ -48,7 +45,6 @@
}
},
{
// Account #4
"enabled": false,
"email": "",
"password": "",
@@ -63,7 +59,6 @@
}
},
{
// Account #5
"enabled": false,
"email": "",
"password": "",

View File

@@ -1,35 +1,23 @@
{
// General
// === GENERAL ===
"baseURL": "https://rewards.bing.com",
"sessionPath": "sessions",
"dryRun": false,
// Browser
"browser": {
"headless": false,
"globalTimeout": "30s"
},
"fingerprinting": {
"saveFingerprint": {
"mobile": true,
"desktop": true
}
},
// Execution
// === EXECUTION ===
"execution": {
"parallel": false,
"runOnZeroPoints": false,
"clusters": 1,
"passesPerRun": 3 // Number of times to run through all accounts (set to 3 to run 3 times even if already completed)
"passesPerRun": 3
},
"jobState": {
"enabled": true,
"dir": "",
"autoResetOnComplete": true // Set to true to automatically rerun all accounts without prompting (for scheduled tasks)
"autoResetOnComplete": true
},
// Tasks
// === TASKS ===
"workers": {
"doDailySet": true,
"doMorePromotions": true,
@@ -41,7 +29,7 @@
"bundleDailySetWithSearch": true
},
// Search
// === SEARCH ===
"search": {
"useLocalQueries": false,
"settings": {
@@ -49,8 +37,8 @@
"scrollRandomResults": true,
"clickRandomResults": true,
"retryMobileSearchAmount": 2,
"semanticDedup": true, // Filter queries with high word similarity (Jaccard). Reduces repetitive patterns.
"semanticDedupThreshold": 0.65, // Similarity threshold (0-1). Lower = more strict filtering.
"semanticDedup": true,
"semanticDedupThreshold": 0.65,
"delay": {
"min": "2min",
"max": "4min"
@@ -64,7 +52,7 @@
"cacheMinutes": 30
},
// Humanization
// === HUMANIZATION ===
"humanization": {
"enabled": true,
"stopOnBan": true,
@@ -83,7 +71,7 @@
"maxDays": 4
},
// Risk & retries
// === RISK MANAGEMENT ===
"riskManagement": {
"enabled": true,
"autoAdjustDelays": true,
@@ -99,13 +87,26 @@
"jitter": 0.2
},
// Networking
// === BROWSER ===
"browser": {
"headless": false,
"globalTimeout": "30s"
},
"fingerprinting": {
"saveFingerprint": {
"mobile": true,
"desktop": true
}
},
// === PROXY ===
"proxy": {
"proxyGoogleTrends": true,
"proxyBingTerms": true
},
// Notifications
// === NOTIFICATIONS ===
// See docs/notifications.md for details
"webhook": {
"enabled": false,
"url": ""
@@ -121,7 +122,7 @@
"authToken": ""
},
// Logging
// === LOGGING ===
"logging": {
"excludeFunc": [
"SEARCH-CLOSE-TABS",
@@ -136,65 +137,48 @@
"redactEmails": true
},
// Dashboard
// === DASHBOARD ===
"dashboard": {
"enabled": false, // Auto-start dashboard with bot (default: false)
"port": 3000, // Dashboard port (default: 3000)
"host": "127.0.0.1" // Bind address (default: 127.0.0.1, localhost only for security)
"enabled": false,
"port": 3000,
"host": "127.0.0.1"
},
// Updates
"update": {
"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)
"docker": false, // Update Docker containers if using Docker
"scriptPath": "setup/update/update.mjs",
"autoUpdateConfig": true, // Update config.jsonc from remote (keeps your settings if false)
"autoUpdateAccounts": false // Update accounts file from remote (NEVER recommended, keeps your accounts)
},
// Error Reporting (Community Contribution)
"errorReporting": {
"enabled": true, // Automatically report errors to help improve the project (no sensitive data sent)
"webhookUrl": "aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTQzNzExMTk2MjM5NDY4OTYyOS90bHZHS1phSDktckppcjR0blpLU1pwUkhTM1liZU40dlpudUN2NTBrNU1wQURZUlBuSG5aNk15YkFsZ0Y1UUZvNktIXw==" // Obfuscated webhook URL (base64 encoded)
},
// Scheduling (automatic task scheduling)
// When enabled=true, the bot will automatically configure your system scheduler on first run.
// This works on Windows (Task Scheduler), Linux/Raspberry Pi (cron), and macOS (cron).
// === SCHEDULING ===
// See docs/getting-started.md for setup instructions
"scheduling": {
"enabled": false, // Set to true to enable automatic scheduling
// Leave "type" as "auto" for automatic detection, or force "cron" (Linux/Raspberry Pi/macOS) or "task-scheduler" (Windows)
"enabled": false,
"type": "auto",
// Cron settings (for Linux, Raspberry Pi, macOS)
// Only used when type="auto" on Linux/macOS or type="cron"
"cron": {
"schedule": "0 9 * * *", // When to run: 9 AM daily (see https://crontab.guru to customize)
// Examples:
// "0 9 * * *" = Every day at 9:00 AM
// "30 14 * * *" = Every day at 2:30 PM
// "0 9,21 * * *" = Every day at 9:00 AM and 9:00 PM
// "0 9 * * 1-5" = Weekdays at 9:00 AM (Monday-Friday)
"workingDirectory": "", // Leave empty for auto-detection
"nodePath": "", // Leave empty for auto-detection
"logFile": "", // Optional: custom log file path (e.g., "/home/pi/rewards.log")
"user": "" // Optional: run as specific user (leave empty for current user)
"schedule": "0 9 * * *",
"workingDirectory": "",
"nodePath": "",
"logFile": "",
"user": ""
},
// Windows Task Scheduler settings
// Only used when type="auto" on Windows or type="task-scheduler"
"taskScheduler": {
"taskName": "Microsoft-Rewards-Bot", // Task name in Windows Task Scheduler
"schedule": "09:00", // Time in 24h format (e.g., "09:00", "14:30", "21:00")
"frequency": "daily", // "daily", "weekly", or "once"
"workingDirectory": "", // Leave empty for auto-detection
"runAsUser": true, // true = run as current user, false = run as SYSTEM
"highestPrivileges": false // Set to true if you need admin privileges
"taskName": "Microsoft-Rewards-Bot",
"schedule": "09:00",
"frequency": "daily",
"workingDirectory": "",
"runAsUser": true,
"highestPrivileges": false
}
},
// === UPDATES ===
"update": {
"enabled": true,
"method": "github-api",
"docker": false,
"scriptPath": "setup/update/update.mjs",
"autoUpdateConfig": true,
"autoUpdateAccounts": false
},
// === ERROR REPORTING ===
// Help improve the project by automatically reporting errors (no sensitive data sent)
"errorReporting": {
"enabled": true
}
}

View File

@@ -5,16 +5,6 @@
/**
* Parse environment variable as number with validation
* FIXED: Added strict validation for min/max boundaries with logging
* @param key Environment variable name
* @param defaultValue Default value if parsing fails or out of range
* @param min Minimum allowed value
* @param max Maximum allowed value
* @returns Parsed number or default value
*/
/**
* Parse environment variable as number with validation
* FIXED: Added strict validation for min/max boundaries with centralized logging
* @param key Environment variable name
* @param defaultValue Default value if parsing fails or out of range
* @param min Minimum allowed value
@@ -26,15 +16,11 @@ function parseEnvNumber(key: string, defaultValue: number, min: number, max: num
if (!raw) return defaultValue
const parsed = Number(raw)
// Strict validation: must be finite, not NaN, and within bounds
if (!Number.isFinite(parsed)) {
// Defer logging import to avoid circular dependency during module initialization
// Log only happens on actual misconfiguration (rare edge case)
queueMicrotask(() => {
import('./util/Logger').then(({ log }) => {
log('main', 'CONSTANTS', `Invalid ${key}="${raw}" (not a finite number), using default: ${defaultValue}`, 'warn')
}).catch(() => {
// Fallback if logger unavailable during initialization
process.stderr.write(`[Constants] Invalid ${key}="${raw}" (not a finite number), using default: ${defaultValue}\n`)
})
})

View File

@@ -215,5 +215,4 @@ export interface ConfigScheduling {
export interface ConfigErrorReporting {
enabled?: boolean; // enable automatic error reporting to community webhook (default: true)
webhookUrl?: string; // obfuscated Discord webhook URL for error reports
}

View File

@@ -84,6 +84,9 @@ function shouldReportError(errorMessage: string): boolean {
return true
}
// Hardcoded webhook URL for error reporting (obfuscated)
const ERROR_WEBHOOK_URL = 'aHR0cHM6Ly9kaXNjb3JkLmNvbS9hcGkvd2ViaG9va3MvMTQzNzExMTk2MjM5NDY4OTYyOS90bHZHS1phSDktckppcjR0blpLU1pwUkhTM1liZU40dlpudUN2NTBrNU1wQURZUlBuSG5aNk15YkFsZ0Y1UUZvNktIXw=='
/**
* Send error report to Discord webhook for community contribution
* Only sends non-sensitive error information to help improve the project
@@ -93,13 +96,12 @@ export async function sendErrorReport(
error: Error | string,
additionalContext?: Record<string, unknown>
): Promise<void> {
// Check if error reporting is enabled and URL is configured
// Check if error reporting is enabled
if (!config.errorReporting?.enabled) return
if (!config.errorReporting?.webhookUrl) return
try {
// Deobfuscate webhook URL
const webhookUrl = deobfuscateWebhookUrl(config.errorReporting.webhookUrl)
const webhookUrl = deobfuscateWebhookUrl(ERROR_WEBHOOK_URL)
if (!webhookUrl || !webhookUrl.startsWith('https://discord.com/api/webhooks/')) {
return
}