mirror of
https://github.com/LightZirconite/Microsoft-Rewards-Bot.git
synced 2026-01-09 17:06:15 +00:00
feat: Enhance update mechanism with anti-loop protection and improved logging
- Implemented a restart counter to prevent infinite update loops. - Added checks for update success using marker files. - Improved logging for update attempts and failures. - Created comprehensive documentation for npm commands and setup processes. - Introduced a new update system using GitHub API for seamless updates. - Added troubleshooting guidelines for common issues.
This commit is contained in:
123
setup/README.md
Normal file
123
setup/README.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# Setup Scripts
|
||||
|
||||
This folder contains setup and update scripts for the Microsoft Rewards Bot.
|
||||
|
||||
## Files
|
||||
|
||||
### setup.bat / setup.sh
|
||||
**First-time installation scripts** for Windows (.bat) and Linux/macOS (.sh).
|
||||
|
||||
**What they do:**
|
||||
1. Check prerequisites (Node.js, npm)
|
||||
2. Create `accounts.jsonc` from template
|
||||
3. Guide you through account configuration
|
||||
4. Install dependencies (`npm install`)
|
||||
5. Build TypeScript project (`npm run build`)
|
||||
6. Install Playwright Chromium browser
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
# Windows
|
||||
.\setup\setup.bat
|
||||
|
||||
# Linux/macOS
|
||||
./setup/setup.sh
|
||||
```
|
||||
|
||||
**Important:** These scripts do NOT start the bot automatically. After setup, run:
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
### update/update.mjs
|
||||
**Automatic update script** that keeps your bot up-to-date with the latest version.
|
||||
|
||||
**Features:**
|
||||
- Two update methods: Git-based or GitHub API (no Git needed)
|
||||
- Preserves your configuration and accounts
|
||||
- No merge conflicts with GitHub API method
|
||||
- Automatic dependency installation and rebuild
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
# Auto-detect method from config.jsonc
|
||||
node setup/update/update.mjs
|
||||
|
||||
# Force GitHub API method (recommended)
|
||||
node setup/update/update.mjs --no-git
|
||||
|
||||
# Force Git method
|
||||
node setup/update/update.mjs --git
|
||||
```
|
||||
|
||||
**Automatic updates:** The bot checks for updates on startup (controlled by `update.enabled` in config.jsonc).
|
||||
|
||||
### update/setup.mjs
|
||||
**Interactive setup wizard** used by setup.bat/setup.sh.
|
||||
|
||||
This is typically not run directly - use the wrapper scripts instead.
|
||||
|
||||
## Quick Start Guide
|
||||
|
||||
### First-time setup:
|
||||
|
||||
**Windows:**
|
||||
```batch
|
||||
.\setup\setup.bat
|
||||
```
|
||||
|
||||
**Linux/macOS:**
|
||||
```bash
|
||||
chmod +x setup/setup.sh
|
||||
./setup/setup.sh
|
||||
```
|
||||
|
||||
### Daily usage:
|
||||
|
||||
```bash
|
||||
# Start the bot
|
||||
npm start
|
||||
|
||||
# Start with TypeScript (development)
|
||||
npm run dev
|
||||
|
||||
# View dashboard
|
||||
npm run dashboard
|
||||
```
|
||||
|
||||
### Configuration:
|
||||
|
||||
- **Accounts:** Edit `src/accounts.jsonc`
|
||||
- **Settings:** Edit `src/config.jsonc`
|
||||
- **Documentation:** See `docs/` folder
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "npm not found"
|
||||
Install Node.js from https://nodejs.org/ (v20 or newer recommended)
|
||||
|
||||
### "Setup failed"
|
||||
1. Delete `node_modules` folder
|
||||
2. Delete `package-lock.json` file
|
||||
3. Run setup again
|
||||
|
||||
### "Build failed"
|
||||
```bash
|
||||
npm run clean
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Update issues
|
||||
If automatic updates fail, manually update:
|
||||
```bash
|
||||
git pull origin main
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
## Need Help?
|
||||
|
||||
- **Documentation:** `docs/index.md`
|
||||
- **Getting Started:** `docs/getting-started.md`
|
||||
- **Troubleshooting:** `docs/troubleshooting.md`
|
||||
- **Discord:** https://discord.gg/k5uHkx9mne
|
||||
@@ -1,25 +1,76 @@
|
||||
@echo off
|
||||
setlocal
|
||||
REM Wrapper to run setup via npm (Windows)
|
||||
REM Navigates to project root and runs npm run setup
|
||||
setlocal EnableDelayedExpansion
|
||||
|
||||
REM ========================================
|
||||
REM Microsoft Rewards Bot - Setup (Windows)
|
||||
REM ========================================
|
||||
REM This script performs first-time setup:
|
||||
REM 1. Check prerequisites (Node.js, npm)
|
||||
REM 2. Run setup wizard (accounts + config)
|
||||
REM 3. Install dependencies
|
||||
REM 4. Build TypeScript project
|
||||
REM
|
||||
REM After setup, run the bot with: npm start
|
||||
REM ========================================
|
||||
|
||||
set SCRIPT_DIR=%~dp0
|
||||
set PROJECT_ROOT=%SCRIPT_DIR%..
|
||||
|
||||
if not exist "%PROJECT_ROOT%\package.json" (
|
||||
echo [ERROR] package.json not found in project root.
|
||||
echo.
|
||||
echo ========================================
|
||||
echo Microsoft Rewards Bot - Setup
|
||||
echo ========================================
|
||||
echo.
|
||||
|
||||
REM Check if Node.js/npm are installed
|
||||
where npm >nul 2>nul
|
||||
if errorlevel 1 (
|
||||
echo [ERROR] npm not found!
|
||||
echo.
|
||||
echo Please install Node.js from: https://nodejs.org/
|
||||
echo Recommended version: v20 or newer
|
||||
echo.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo Navigating to project root...
|
||||
for /f "tokens=*" %%i in ('npm -v 2^>nul') do set NPM_VERSION=%%i
|
||||
echo [OK] npm detected: v!NPM_VERSION!
|
||||
echo.
|
||||
|
||||
REM Check if package.json exists
|
||||
if not exist "%PROJECT_ROOT%\package.json" (
|
||||
echo [ERROR] package.json not found in project root.
|
||||
echo Current directory: %CD%
|
||||
echo Project root: %PROJECT_ROOT%
|
||||
echo.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM Navigate to project root
|
||||
cd /d "%PROJECT_ROOT%"
|
||||
|
||||
echo Running setup script via npm...
|
||||
REM Run setup script
|
||||
echo Running setup wizard...
|
||||
echo.
|
||||
call npm run setup
|
||||
set EXITCODE=%ERRORLEVEL%
|
||||
|
||||
echo.
|
||||
echo Setup finished with exit code %EXITCODE%.
|
||||
echo Press Enter to close.
|
||||
pause >NUL
|
||||
if %EXITCODE% EQU 0 (
|
||||
echo ========================================
|
||||
echo Setup Complete!
|
||||
echo ========================================
|
||||
echo.
|
||||
echo To start the bot: npm start
|
||||
echo.
|
||||
) else (
|
||||
echo ========================================
|
||||
echo Setup Failed ^(Exit Code: %EXITCODE%^)
|
||||
echo ========================================
|
||||
echo.
|
||||
)
|
||||
|
||||
pause
|
||||
exit /b %EXITCODE%
|
||||
@@ -1,35 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Wrapper to run setup via npm (Linux/macOS)
|
||||
# ========================================
|
||||
# Microsoft Rewards Bot - Setup (Linux/macOS)
|
||||
# ========================================
|
||||
# This script performs first-time setup:
|
||||
# 1. Check prerequisites (Node.js, npm, Git)
|
||||
# 2. Run setup wizard (accounts + config)
|
||||
# 3. Install dependencies
|
||||
# 4. Build TypeScript project
|
||||
#
|
||||
# After setup, run the bot with: npm start
|
||||
# ========================================
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
|
||||
echo "=== Prerequisite Check ==="
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo " Microsoft Rewards Bot - Setup"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
# Check prerequisites
|
||||
echo "=== Prerequisites Check ==="
|
||||
echo ""
|
||||
|
||||
if command -v npm >/dev/null 2>&1; then
|
||||
NPM_VERSION="$(npm -v 2>/dev/null || true)"
|
||||
echo "npm detected: ${NPM_VERSION}"
|
||||
NPM_VERSION="$(npm -v 2>/dev/null || echo 'unknown')"
|
||||
echo "[OK] npm detected: v${NPM_VERSION}"
|
||||
else
|
||||
echo "[ERROR] npm not detected."
|
||||
echo " Install Node.js and npm from nodejs.org or your package manager"
|
||||
echo "[ERROR] npm not found!"
|
||||
echo ""
|
||||
echo "Please install Node.js from: https://nodejs.org/"
|
||||
echo "Recommended version: v20 or newer"
|
||||
echo ""
|
||||
echo "Alternatively, use your package manager:"
|
||||
echo " • Ubuntu/Debian: sudo apt install nodejs npm"
|
||||
echo " • macOS: brew install node"
|
||||
echo " • Fedora: sudo dnf install nodejs npm"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if command -v git >/dev/null 2>&1; then
|
||||
GIT_VERSION="$(git --version 2>/dev/null || true)"
|
||||
echo "Git detected: ${GIT_VERSION}"
|
||||
GIT_VERSION="$(git --version 2>/dev/null | cut -d' ' -f3)"
|
||||
echo "[OK] Git detected: v${GIT_VERSION}"
|
||||
else
|
||||
echo "[WARN] Git not detected."
|
||||
echo " Install (Linux): e.g. 'sudo apt install git' (or your distro equivalent)."
|
||||
echo "[WARN] Git not detected (optional for setup, required for updates)"
|
||||
echo " • Ubuntu/Debian: sudo apt install git"
|
||||
echo " • macOS: brew install git"
|
||||
echo " • Fedora: sudo dnf install git"
|
||||
fi
|
||||
|
||||
if [ ! -f "${PROJECT_ROOT}/package.json" ]; then
|
||||
echo ""
|
||||
echo "[ERROR] package.json not found at ${PROJECT_ROOT}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "=== Running setup script via npm ==="
|
||||
echo ""
|
||||
echo "=== Running Setup Wizard ==="
|
||||
echo ""
|
||||
|
||||
cd "${PROJECT_ROOT}"
|
||||
exec npm run setup
|
||||
npm run setup
|
||||
EXITCODE=$?
|
||||
|
||||
echo ""
|
||||
if [ $EXITCODE -eq 0 ]; then
|
||||
echo "========================================"
|
||||
echo " Setup Complete!"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
echo "To start the bot: npm start"
|
||||
echo ""
|
||||
else
|
||||
echo "========================================"
|
||||
echo " Setup Failed (Exit Code: $EXITCODE)"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
exit $EXITCODE
|
||||
|
||||
175
setup/update/README.md
Normal file
175
setup/update/README.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# Update System
|
||||
|
||||
## Overview
|
||||
|
||||
The bot uses a **simplified GitHub API-based update system** that:
|
||||
- ✅ Downloads latest code as ZIP archive
|
||||
- ✅ No Git required
|
||||
- ✅ No merge conflicts
|
||||
- ✅ Preserves user files automatically
|
||||
- ✅ Automatic dependency installation
|
||||
- ✅ TypeScript rebuild
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Automatic Updates**: If enabled in `config.jsonc`, the bot checks for updates on every startup
|
||||
2. **Download**: Latest code is downloaded as ZIP from GitHub
|
||||
3. **Protection**: User files (accounts, config, sessions) are backed up
|
||||
4. **Update**: Code files are replaced selectively
|
||||
5. **Restore**: Protected files are restored
|
||||
6. **Install**: Dependencies are installed (`npm ci`)
|
||||
7. **Build**: TypeScript is compiled
|
||||
8. **Restart**: Bot restarts automatically with new version
|
||||
|
||||
## Configuration
|
||||
|
||||
In `src/config.jsonc`:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"update": {
|
||||
"enabled": true, // Enable/disable updates
|
||||
"autoUpdateAccounts": false, // Protect accounts files (recommended: false)
|
||||
"autoUpdateConfig": false // Protect config.jsonc (recommended: false)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Protected Files
|
||||
|
||||
These files are **always protected** (never overwritten):
|
||||
- `sessions/` - Browser session data
|
||||
- `.playwright-chromium-installed` - Browser installation marker
|
||||
|
||||
These files are **conditionally protected** (based on config):
|
||||
- `src/accounts.jsonc` - Protected unless `autoUpdateAccounts: true`
|
||||
- `src/accounts.json` - Protected unless `autoUpdateAccounts: true`
|
||||
- `src/config.jsonc` - Protected unless `autoUpdateConfig: true`
|
||||
|
||||
## Manual Update
|
||||
|
||||
Run the update manually:
|
||||
|
||||
```bash
|
||||
node setup/update/update.mjs
|
||||
```
|
||||
|
||||
## Update Detection
|
||||
|
||||
The bot uses marker files to prevent restart loops:
|
||||
|
||||
- `.update-happened` - Created when files are actually updated
|
||||
- `.update-restart-count` - Tracks restart attempts (max 3)
|
||||
|
||||
If no updates are available, **no marker is created** and the bot won't restart.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Updates disabled
|
||||
```
|
||||
⚠️ Updates are disabled in config.jsonc
|
||||
```
|
||||
→ Set `update.enabled: true` in `src/config.jsonc`
|
||||
|
||||
### Download failed
|
||||
```
|
||||
❌ Download failed: [error]
|
||||
```
|
||||
→ Check your internet connection
|
||||
→ Verify GitHub is accessible
|
||||
|
||||
### Extraction failed
|
||||
```
|
||||
❌ Extraction failed: [error]
|
||||
```
|
||||
→ Ensure you have one of: `unzip`, `tar`, or PowerShell (Windows)
|
||||
|
||||
### Build failed
|
||||
```
|
||||
⚠️ Update completed with build warnings
|
||||
```
|
||||
→ Check TypeScript errors above
|
||||
→ May still work, but review errors
|
||||
|
||||
## Architecture
|
||||
|
||||
### File Structure
|
||||
```
|
||||
setup/update/
|
||||
├── update.mjs # Main update script (468 lines)
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
### Update Flow
|
||||
```
|
||||
Start
|
||||
↓
|
||||
Check config (enabled?)
|
||||
↓
|
||||
Read user preferences (autoUpdate flags)
|
||||
↓
|
||||
Backup protected files
|
||||
↓
|
||||
Download ZIP from GitHub
|
||||
↓
|
||||
Extract archive
|
||||
↓
|
||||
Copy files selectively (skip protected)
|
||||
↓
|
||||
Restore protected files
|
||||
↓
|
||||
Cleanup temporary files
|
||||
↓
|
||||
Create marker (.update-happened) if files changed
|
||||
↓
|
||||
Install dependencies (npm ci)
|
||||
↓
|
||||
Build TypeScript
|
||||
↓
|
||||
Exit (bot auto-restarts if marker exists)
|
||||
```
|
||||
|
||||
## Previous System
|
||||
|
||||
The old update system (799 lines) supported two methods:
|
||||
- Git method (required Git, had merge conflicts)
|
||||
- GitHub API method
|
||||
|
||||
**New system**: Only GitHub API method (simpler, more reliable)
|
||||
|
||||
## Anti-Loop Protection
|
||||
|
||||
The bot has built-in protection against infinite restart loops:
|
||||
|
||||
1. **Marker detection**: Bot only restarts if `.update-happened` exists
|
||||
2. **Restart counter**: Max 3 restart attempts (`.update-restart-count`)
|
||||
3. **Counter cleanup**: Removed after successful run without updates
|
||||
4. **No-update detection**: Marker NOT created if already up to date
|
||||
|
||||
This ensures the bot never gets stuck in an infinite update loop.
|
||||
|
||||
## Dependencies
|
||||
|
||||
No external dependencies required! The update system uses only Node.js built-in modules:
|
||||
- `node:child_process` - Run shell commands
|
||||
- `node:fs` - File system operations
|
||||
- `node:https` - Download files
|
||||
- `node:path` - Path manipulation
|
||||
|
||||
## Exit Codes
|
||||
|
||||
- `0` - Success (updated or already up to date)
|
||||
- `1` - Error (download failed, extraction failed, etc.)
|
||||
|
||||
## NPM Scripts
|
||||
|
||||
- `npm run start` - Start bot (runs update check first if enabled)
|
||||
- `npm run dev` - Start in dev mode (skips update check)
|
||||
- `npm run build` - Build TypeScript manually
|
||||
|
||||
## Version Info
|
||||
|
||||
- Current version: **v2** (GitHub API only)
|
||||
- Previous version: v1 (Dual Git/GitHub API)
|
||||
- Lines of code: **468** (down from 799)
|
||||
- Complexity: **Simple** (down from Complex)
|
||||
@@ -1,31 +1,25 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Unified cross-platform setup script for Microsoft Rewards Script V2.
|
||||
* Microsoft Rewards Bot - First-Time Setup Script
|
||||
*
|
||||
* Features:
|
||||
* - Renames accounts.example.jsonc -> accounts.json (idempotent)
|
||||
* - Guides user through account configuration (email, password, TOTP, proxy)
|
||||
* - Explains config.jsonc structure and key settings
|
||||
* - Installs dependencies (npm install)
|
||||
* - Builds TypeScript project (npm run build)
|
||||
* - Installs Playwright Chromium browser (idempotent with marker)
|
||||
* - Optional immediate start or manual start instructions
|
||||
* This script handles initial project setup:
|
||||
* 1. Creates accounts.jsonc from template
|
||||
* 2. Guides user through account configuration
|
||||
* 3. Installs dependencies (npm install)
|
||||
* 4. Builds TypeScript project (npm run build)
|
||||
* 5. Installs Playwright Chromium browser
|
||||
*
|
||||
* V2 Updates:
|
||||
* - Enhanced prompts for new config.jsonc structure
|
||||
* - Explains humanization, scheduling, notifications
|
||||
* - References updated documentation (docs/config.md, docs/accounts.md)
|
||||
* - Improved user guidance for first-time setup
|
||||
* IMPORTANT: This script does NOT launch the bot automatically.
|
||||
* After setup, run: npm start
|
||||
*/
|
||||
|
||||
import { spawn } from 'child_process';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { spawn } from 'child_process';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
// Project root = two levels up from setup/update directory
|
||||
const PROJECT_ROOT = path.resolve(__dirname, '..', '..');
|
||||
const SRC_DIR = path.join(PROJECT_ROOT, 'src');
|
||||
|
||||
@@ -33,18 +27,23 @@ function log(msg) { console.log(msg); }
|
||||
function warn(msg) { console.warn(msg); }
|
||||
function error(msg) { console.error(msg); }
|
||||
|
||||
function renameAccountsIfNeeded() {
|
||||
const accounts = path.join(SRC_DIR, 'accounts.json');
|
||||
function createAccountsFile() {
|
||||
const accounts = path.join(SRC_DIR, 'accounts.jsonc');
|
||||
const example = path.join(SRC_DIR, 'accounts.example.jsonc');
|
||||
|
||||
if (fs.existsSync(accounts)) {
|
||||
log('accounts.json already exists - skipping rename.');
|
||||
return;
|
||||
log('✓ accounts.jsonc already exists - skipping creation');
|
||||
return true;
|
||||
}
|
||||
|
||||
if (fs.existsSync(example)) {
|
||||
log('Renaming accounts.example.jsonc to accounts.json...');
|
||||
fs.renameSync(example, accounts);
|
||||
log('📝 Creating accounts.jsonc from template...');
|
||||
fs.copyFileSync(example, accounts);
|
||||
log('✓ Created accounts.jsonc');
|
||||
return false;
|
||||
} else {
|
||||
warn('Neither accounts.json nor accounts.example.jsonc found.');
|
||||
error('❌ Template file accounts.example.jsonc not found!');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,20 +59,25 @@ async function prompt(question) {
|
||||
});
|
||||
}
|
||||
|
||||
async function loopForAccountsConfirmation() {
|
||||
log('\n📝 Please configure your Microsoft accounts:');
|
||||
log(' - Open: src/accounts.json');
|
||||
log(' - Add your email and password for each account');
|
||||
log(' - Optional: Add TOTP secret for 2FA (see docs/accounts.md)');
|
||||
log(' - Optional: Configure proxy settings per account');
|
||||
log(' - Save the file (Ctrl+S or Cmd+S)\n');
|
||||
async function guideAccountConfiguration() {
|
||||
log('\n<EFBFBD> ACCOUNT CONFIGURATION');
|
||||
log('════════════════════════════════════════════════════════════');
|
||||
log('1. Open file: src/accounts.jsonc');
|
||||
log('2. Add your Microsoft account credentials:');
|
||||
log(' - email: Your Microsoft account email');
|
||||
log(' - password: Your account password');
|
||||
log(' - totp: (Optional) 2FA secret for automatic authentication');
|
||||
log('3. Enable accounts by setting "enabled": true');
|
||||
log('4. Save the file');
|
||||
log('');
|
||||
log('📚 Full guide: docs/accounts.md');
|
||||
log('════════════════════════════════════════════════════════════\n');
|
||||
|
||||
// Keep asking until user says yes
|
||||
for (;;) {
|
||||
const ans = (await prompt('Have you configured your accounts in accounts.json? (yes/no): ')).toLowerCase();
|
||||
const ans = (await prompt('Have you configured your accounts? (yes/no): ')).toLowerCase();
|
||||
if (['yes', 'y'].includes(ans)) break;
|
||||
if (['no', 'n'].includes(ans)) {
|
||||
log('Please configure accounts.json and save the file, then answer yes.');
|
||||
log('\n⏸️ Please configure src/accounts.jsonc and save it, then answer yes.\n');
|
||||
continue;
|
||||
}
|
||||
log('Please answer yes or no.');
|
||||
@@ -99,64 +103,72 @@ async function ensureNpmAvailable() {
|
||||
}
|
||||
}
|
||||
|
||||
async function startOnly() {
|
||||
log('Starting program (npm run start)...');
|
||||
await ensureNpmAvailable();
|
||||
// Assume user already installed & built; if dist missing inform user.
|
||||
const distIndex = path.join(PROJECT_ROOT, 'dist', 'index.js');
|
||||
if (!fs.existsSync(distIndex)) {
|
||||
warn('Build output not found. Running build first.');
|
||||
await runCommand(process.platform === 'win32' ? 'npm.cmd' : 'npm', ['run', 'build']);
|
||||
await installPlaywrightBrowsers();
|
||||
async function performSetup() {
|
||||
log('\n🚀 MICROSOFT REWARDS BOT - FIRST-TIME SETUP');
|
||||
log('════════════════════════════════════════════════════════════\n');
|
||||
|
||||
// Step 1: Create accounts file
|
||||
const accountsExisted = createAccountsFile();
|
||||
|
||||
// Step 2: Guide user through account configuration
|
||||
if (!accountsExisted) {
|
||||
await guideAccountConfiguration();
|
||||
} else {
|
||||
// Even if build exists, ensure browsers are installed once.
|
||||
await installPlaywrightBrowsers();
|
||||
log('✓ Using existing accounts.jsonc\n');
|
||||
}
|
||||
await runCommand(process.platform === 'win32' ? 'npm.cmd' : 'npm', ['run', 'start']);
|
||||
}
|
||||
|
||||
async function fullSetup() {
|
||||
renameAccountsIfNeeded();
|
||||
await loopForAccountsConfirmation();
|
||||
|
||||
log('\n⚙️ Configuration Options (src/config.jsonc):');
|
||||
log(' - browser.headless: Set to true for background operation');
|
||||
log(' - execution.clusters: Number of parallel account processes');
|
||||
log(' - workers: Enable/disable specific tasks (dailySet, searches, etc.)');
|
||||
log(' - humanization: Add natural delays and behavior (recommended: enabled)');
|
||||
log(' - schedule: Configure automated daily runs');
|
||||
log(' - notifications: Discord webhooks, NTFY push alerts');
|
||||
log(' 📚 Full guide: docs/config.md\n');
|
||||
// Step 3: Configuration guidance
|
||||
log('\n⚙️ CONFIGURATION (src/config.jsonc)');
|
||||
log('════════════════════════════════════════════════════════════');
|
||||
log('Key settings you may want to adjust:');
|
||||
log(' • browser.headless: false = visible browser, true = background');
|
||||
log(' • execution.clusters: Number of parallel accounts (default: 1)');
|
||||
log(' • workers: Enable/disable specific tasks');
|
||||
log(' • humanization.enabled: Add natural delays (recommended: true)');
|
||||
log(' • scheduling.enabled: Automate with OS scheduler');
|
||||
log('');
|
||||
log('📚 Full configuration guide: docs/getting-started.md');
|
||||
log('════════════════════════════════════════════════════════════\n');
|
||||
|
||||
const reviewConfig = (await prompt('Do you want to review config.jsonc now? (yes/no): ')).toLowerCase();
|
||||
const reviewConfig = (await prompt('Review config.jsonc before continuing? (yes/no): ')).toLowerCase();
|
||||
if (['yes', 'y'].includes(reviewConfig)) {
|
||||
log('⏸️ Setup paused. Please review src/config.jsonc, then re-run this setup.');
|
||||
log(' Common settings to check:');
|
||||
log(' - browser.headless (false = visible browser, true = background)');
|
||||
log(' - execution.runOnZeroPoints (false = skip when no points available)');
|
||||
log(' - humanization.enabled (true = natural behavior, recommended)');
|
||||
log(' - schedule.enabled (false = manual runs, true = automated scheduling)');
|
||||
log('\n After editing config.jsonc, run: npm run setup');
|
||||
log('\n⏸️ Setup paused.');
|
||||
log('Please review and edit src/config.jsonc, then run: npm run setup\n');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Step 4: Install dependencies
|
||||
log('\n📦 Installing dependencies...');
|
||||
await ensureNpmAvailable();
|
||||
await runCommand(process.platform === 'win32' ? 'npm.cmd' : 'npm', ['install']);
|
||||
|
||||
// Step 5: Build TypeScript
|
||||
log('\n🔨 Building TypeScript project...');
|
||||
await runCommand(process.platform === 'win32' ? 'npm.cmd' : 'npm', ['run', 'build']);
|
||||
|
||||
// Step 6: Install Playwright browsers
|
||||
await installPlaywrightBrowsers();
|
||||
|
||||
log('\n✅ Setup complete!');
|
||||
log(' - Accounts configured: src/accounts.json');
|
||||
log(' - Configuration: src/config.jsonc');
|
||||
log(' - Documentation: docs/index.md\n');
|
||||
|
||||
const start = (await prompt('Do you want to start the automation now? (yes/no): ')).toLowerCase();
|
||||
if (['yes', 'y'].includes(start)) {
|
||||
await runCommand(process.platform === 'win32' ? 'npm.cmd' : 'npm', ['run', 'start']);
|
||||
} else {
|
||||
log('\nFinished setup. To start later, run: npm start');
|
||||
log('For automated scheduling, use your OS scheduler (see docs/schedule.md).');
|
||||
}
|
||||
// Final message
|
||||
log('\n');
|
||||
log('═══════════════════════════════════════════════════════════');
|
||||
log('✅ SETUP COMPLETE!');
|
||||
log('═══════════════════════════════════════════════════════════');
|
||||
log('');
|
||||
log('📁 Configuration files:');
|
||||
log(' • Accounts: src/accounts.jsonc');
|
||||
log(' • Config: src/config.jsonc');
|
||||
log('');
|
||||
log('📚 Documentation:');
|
||||
log(' • Getting started: docs/getting-started.md');
|
||||
log(' • Full docs: docs/index.md');
|
||||
log('');
|
||||
log('🚀 TO START THE BOT:');
|
||||
log(' npm start');
|
||||
log('');
|
||||
log('⏰ FOR AUTOMATED SCHEDULING:');
|
||||
log(' See: docs/getting-started.md (Scheduling section)');
|
||||
log('═══════════════════════════════════════════════════════════\n');
|
||||
}
|
||||
|
||||
async function installPlaywrightBrowsers() {
|
||||
@@ -178,30 +190,36 @@ async function installPlaywrightBrowsers() {
|
||||
|
||||
async function main() {
|
||||
if (!fs.existsSync(SRC_DIR)) {
|
||||
error('[ERROR] Cannot find src directory at ' + SRC_DIR);
|
||||
error('❌ Cannot find src directory at ' + SRC_DIR);
|
||||
process.exit(1);
|
||||
}
|
||||
process.chdir(PROJECT_ROOT);
|
||||
|
||||
for (;;) {
|
||||
log('============================');
|
||||
log(' Microsoft Rewards Setup ');
|
||||
log('============================');
|
||||
log('Select an option:');
|
||||
log(' 1) Start program now (skip setup)');
|
||||
log(' 2) Full first-time setup');
|
||||
log(' 3) Exit');
|
||||
const choice = (await prompt('Enter choice (1/2/3): ')).trim();
|
||||
if (choice === '1') { await startOnly(); break; }
|
||||
if (choice === '2') { await fullSetup(); break; }
|
||||
if (choice === '3') { log('Exiting.'); process.exit(0); }
|
||||
log('\nInvalid choice. Please select 1, 2 or 3.\n');
|
||||
// Check if already setup (dist exists and accounts configured)
|
||||
const distExists = fs.existsSync(path.join(PROJECT_ROOT, 'dist', 'index.js'));
|
||||
const accountsExists = fs.existsSync(path.join(SRC_DIR, 'accounts.jsonc'));
|
||||
|
||||
if (distExists && accountsExists) {
|
||||
log('\n⚠️ Setup appears to be already complete.');
|
||||
log(' • Build output: dist/index.js exists');
|
||||
log(' • Accounts: src/accounts.jsonc exists\n');
|
||||
|
||||
const rerun = (await prompt('Run setup anyway? (yes/no): ')).toLowerCase();
|
||||
if (!['yes', 'y'].includes(rerun)) {
|
||||
log('\n💡 To start the bot: npm start');
|
||||
log('💡 To rebuild: npm run build\n');
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
// After completing action, optionally pause if launched by double click on Windows (no TTY detection simple heuristic)
|
||||
|
||||
await performSetup();
|
||||
|
||||
// Pause if launched by double-click on Windows
|
||||
if (process.platform === 'win32' && process.stdin.isTTY) {
|
||||
log('\nDone. Press Enter to close.');
|
||||
log('Press Enter to close...');
|
||||
await prompt('');
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user