refactor: remove BanPredictor, ConfigValidator, RiskManager, SecurityDetector, and related utility files

- Deleted BanPredictor.ts, ConfigValidator.ts, RiskManager.ts, SecurityDetector.ts, and their associated interfaces and methods.
- Removed all related logic for ban prediction, configuration validation, risk management, and security detection.
- Added a new utility function to retrieve error messages from unknown error types.
This commit is contained in:
2025-11-04 20:34:34 +01:00
parent c256f5265e
commit c74b131ac6
8 changed files with 76 additions and 1462 deletions

View File

@@ -1,9 +1,9 @@
import { dashboardState } from './state'
import type { MicrosoftRewardsBot } from '../index'
import { getErrorMessage } from '../util/Utils'
export class BotController {
private botInstance: MicrosoftRewardsBot | null = null
private botPromise: Promise<void> | null = null
private startTime?: Date
constructor() {
@@ -37,7 +37,8 @@ export class BotController {
dashboardState.setRunning(true)
dashboardState.setBotInstance(this.botInstance)
this.botPromise = (async () => {
// Run bot asynchronously - don't block the API response
void (async () => {
try {
this.log('✓ Bot initialized, starting execution...', 'log')
@@ -46,22 +47,16 @@ export class BotController {
this.log('✓ Bot completed successfully', 'log')
} catch (error) {
const errorMsg = error instanceof Error ? error.message : String(error)
this.log(`Bot error: ${errorMsg}`, 'error')
throw error
this.log(`Bot error: ${getErrorMessage(error)}`, 'error')
} finally {
this.cleanup()
}
})()
this.botPromise.catch(error => {
this.log(`Bot execution failed: ${error instanceof Error ? error.message : String(error)}`, 'error')
})
return { success: true, pid: process.pid }
} catch (error) {
const errorMsg = error instanceof Error ? error.message : String(error)
const errorMsg = getErrorMessage(error)
this.log(`Failed to start bot: ${errorMsg}`, 'error')
this.cleanup()
return { success: false, error: errorMsg }
@@ -81,7 +76,7 @@ export class BotController {
return { success: true }
} catch (error) {
const errorMsg = error instanceof Error ? error.message : String(error)
const errorMsg = getErrorMessage(error)
this.log(`Error stopping bot: ${errorMsg}`, 'error')
this.cleanup()
return { success: false, error: errorMsg }
@@ -90,14 +85,19 @@ export class BotController {
public async restart(): Promise<{ success: boolean; error?: string; pid?: number }> {
this.log('🔄 Restarting bot...', 'log')
this.stop()
return new Promise((resolve) => {
setTimeout(async () => {
const result = await this.start()
resolve(result)
}, 2000)
})
const stopResult = this.stop()
if (!stopResult.success && stopResult.error !== 'Bot is not running') {
return { success: false, error: `Failed to stop: ${stopResult.error}` }
}
await this.wait(2000)
return await this.start()
}
private async wait(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms))
}
public getStatus(): {
@@ -116,7 +116,6 @@ export class BotController {
private cleanup(): void {
this.botInstance = null
this.botPromise = null
this.startTime = undefined
dashboardState.setRunning(false)
dashboardState.setBotInstance(undefined)

View File

@@ -7,46 +7,39 @@ import { botController } from './BotController'
export const apiRouter = Router()
// Helper to extract error message
const getErr = (e: unknown): string => e instanceof Error ? e.message : 'Unknown error'
// Helper to load accounts if not already loaded
function ensureAccountsLoaded(): void {
const accounts = dashboardState.getAccounts()
if (accounts.length === 0) {
try {
const loadedAccounts = loadAccounts()
dashboardState.initializeAccounts(loadedAccounts.map(a => a.email))
} catch (error) {
console.error('[Dashboard] Failed to load accounts:', error)
}
}
}
// GET /api/status - Bot status
apiRouter.get('/status', (_req: Request, res: Response) => {
try {
const accounts = dashboardState.getAccounts()
// If no accounts loaded yet, try to load them
if (accounts.length === 0) {
try {
const loadedAccounts = loadAccounts()
dashboardState.initializeAccounts(loadedAccounts.map(a => a.email))
} catch (error) {
console.error('[Dashboard] Failed to load accounts for status:', error)
}
}
ensureAccountsLoaded()
res.json(dashboardState.getStatus())
} catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
res.status(500).json({ error: getErr(error) })
}
})
// GET /api/accounts - List all accounts with masked emails
apiRouter.get('/accounts', (_req: Request, res: Response) => {
try {
let accounts = dashboardState.getAccounts()
// If no accounts in state, try to load from config
if (accounts.length === 0) {
try {
const loadedAccounts = loadAccounts()
dashboardState.initializeAccounts(loadedAccounts.map(a => a.email))
accounts = dashboardState.getAccounts()
} catch (error) {
console.error('[Dashboard] Failed to load accounts:', error)
}
}
res.json(accounts)
ensureAccountsLoaded()
res.json(dashboardState.getAccounts())
} catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
res.status(500).json({ error: getErr(error) })
}
})
@@ -57,7 +50,7 @@ apiRouter.get('/logs', (req: Request, res: Response) => {
const logs = dashboardState.getLogs(Math.min(limit, 500))
res.json(logs)
} catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
res.status(500).json({ error: getErr(error) })
}
})
@@ -67,7 +60,7 @@ apiRouter.delete('/logs', (_req: Request, res: Response) => {
dashboardState.clearLogs()
res.json({ success: true })
} catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
res.status(500).json({ error: getErr(error) })
}
})
@@ -98,7 +91,7 @@ apiRouter.get('/history', (_req: Request, res: Response): void => {
res.json(summaries.slice(0, 50))
} catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
res.status(500).json({ error: getErr(error) })
}
})
@@ -115,7 +108,7 @@ apiRouter.get('/config', (_req: Request, res: Response) => {
res.json(safe)
} catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
res.status(500).json({ error: getErr(error) })
}
})
@@ -139,7 +132,7 @@ apiRouter.post('/config', (req: Request, res: Response): void => {
res.json({ success: true, backup: backupPath })
} catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
res.status(500).json({ error: getErr(error) })
}
})
@@ -148,26 +141,19 @@ apiRouter.post('/start', async (_req: Request, res: Response): Promise<void> =>
try {
const status = botController.getStatus()
if (status.running) {
res.status(400).json({ error: 'Bot already running', pid: status.pid })
sendError(res, 400, `Bot already running (PID: ${status.pid})`)
return
}
const result = await botController.start()
if (result.success) {
res.json({
success: true,
message: 'Bot started successfully',
pid: result.pid
})
sendSuccess(res, { message: 'Bot started successfully', pid: result.pid })
} else {
res.status(500).json({
success: false,
error: result.error || 'Failed to start bot'
})
sendError(res, 500, result.error || 'Failed to start bot')
}
} catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
sendError(res, 500, getErr(error))
}
})
@@ -177,12 +163,12 @@ apiRouter.post('/stop', (_req: Request, res: Response): void => {
const result = botController.stop()
if (result.success) {
res.json({ success: true, message: 'Bot stopped successfully' })
sendSuccess(res, { message: 'Bot stopped successfully' })
} else {
res.status(400).json({ success: false, error: result.error || 'Failed to stop bot' })
sendError(res, 400, result.error || 'Failed to stop bot')
}
} catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
sendError(res, 500, getErr(error))
}
})
@@ -192,19 +178,12 @@ apiRouter.post('/restart', async (_req: Request, res: Response): Promise<void> =
const result = await botController.restart()
if (result.success) {
res.json({
success: true,
message: 'Bot restarted successfully',
pid: result.pid
})
sendSuccess(res, { message: 'Bot restarted successfully', pid: result.pid })
} else {
res.status(500).json({
success: false,
error: result.error || 'Failed to restart bot'
})
sendError(res, 500, result.error || 'Failed to restart bot')
}
} catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
sendError(res, 500, getErr(error))
}
})
@@ -230,7 +209,7 @@ apiRouter.post('/sync/:email', async (req: Request, res: Response): Promise<void
suggestion: 'Use /api/restart endpoint to run all accounts'
})
} catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
res.status(500).json({ error: getErr(error) })
}
})
@@ -253,7 +232,7 @@ apiRouter.get('/metrics', (_req: Request, res: Response) => {
accountsError: accounts.filter(a => a.status === 'error').length
})
} catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
res.status(500).json({ error: getErr(error) })
}
})
@@ -275,7 +254,7 @@ apiRouter.get('/account/:email', (req: Request, res: Response): void => {
res.json(account)
} catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
res.status(500).json({ error: getErr(error) })
}
})
@@ -302,10 +281,11 @@ apiRouter.post('/account/:email/reset', (req: Request, res: Response): void => {
res.json({ success: true })
} catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
res.status(500).json({ error: getErr(error) })
}
})
// Helper to mask sensitive URLs
function maskUrl(url: string): string {
try {
const parsed = new URL(url)
@@ -320,3 +300,13 @@ function maskUrl(url: string): string {
return '***'
}
}
// Helper to send error response
function sendError(res: Response, status: number, message: string): void {
res.status(status).json({ error: message })
}
// Helper to send success response
function sendSuccess(res: Response, data: Record<string, unknown>): void {
res.json({ success: true, ...data })
}