mirror of
https://github.com/LightZirconite/Microsoft-Rewards-Bot.git
synced 2026-01-11 09:46:16 +00:00
feature: adding account management and point loading from sessions
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
<!-- This is a placeholder. The actual favicon will be served from /assets/logo.png -->
|
|
||||||
119
src/dashboard/SessionLoader.ts
Normal file
119
src/dashboard/SessionLoader.ts
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
import fs from 'fs'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
export interface SessionPoints {
|
||||||
|
email: string
|
||||||
|
points: number
|
||||||
|
lastUpdated: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to load points from session data
|
||||||
|
*/
|
||||||
|
export function loadPointsFromSessions(email: string): number | undefined {
|
||||||
|
try {
|
||||||
|
const sessionsDir = path.join(process.cwd(), 'sessions')
|
||||||
|
if (!fs.existsSync(sessionsDir)) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to find session file for this email
|
||||||
|
const emailHash = Buffer.from(email).toString('base64').replace(/[^a-zA-Z0-9]/g, '')
|
||||||
|
const possibleFiles = [
|
||||||
|
`${email}.json`,
|
||||||
|
`${emailHash}.json`,
|
||||||
|
`session_${email}.json`
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const filename of possibleFiles) {
|
||||||
|
const filepath = path.join(sessionsDir, filename)
|
||||||
|
if (fs.existsSync(filepath)) {
|
||||||
|
const data = JSON.parse(fs.readFileSync(filepath, 'utf-8'))
|
||||||
|
if (data.points !== undefined) {
|
||||||
|
return data.points
|
||||||
|
}
|
||||||
|
if (data.availablePoints !== undefined) {
|
||||||
|
return data.availablePoints
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`[Dashboard] Error loading points for ${email}:`, error)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to load all points from sessions
|
||||||
|
*/
|
||||||
|
export function loadAllPointsFromSessions(): Map<string, number> {
|
||||||
|
const pointsMap = new Map<string, number>()
|
||||||
|
|
||||||
|
try {
|
||||||
|
const sessionsDir = path.join(process.cwd(), 'sessions')
|
||||||
|
if (!fs.existsSync(sessionsDir)) {
|
||||||
|
return pointsMap
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = fs.readdirSync(sessionsDir)
|
||||||
|
|
||||||
|
for (const filename of files) {
|
||||||
|
if (!filename.endsWith('.json')) continue
|
||||||
|
|
||||||
|
try {
|
||||||
|
const filepath = path.join(sessionsDir, filename)
|
||||||
|
const data = JSON.parse(fs.readFileSync(filepath, 'utf-8'))
|
||||||
|
|
||||||
|
const email = data.email || data.account?.email
|
||||||
|
const points = data.points || data.availablePoints
|
||||||
|
|
||||||
|
if (email && points !== undefined) {
|
||||||
|
pointsMap.set(email, points)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Skip invalid files
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[Dashboard] Error loading points from sessions:', error)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pointsMap
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to load points from job state
|
||||||
|
*/
|
||||||
|
export function loadPointsFromJobState(email: string): number | undefined {
|
||||||
|
try {
|
||||||
|
const jobStateDir = path.join(process.cwd(), 'sessions', 'job-state')
|
||||||
|
if (!fs.existsSync(jobStateDir)) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = fs.readdirSync(jobStateDir)
|
||||||
|
|
||||||
|
for (const filename of files) {
|
||||||
|
if (!filename.endsWith('.json')) continue
|
||||||
|
|
||||||
|
try {
|
||||||
|
const filepath = path.join(jobStateDir, filename)
|
||||||
|
const data = JSON.parse(fs.readFileSync(filepath, 'utf-8'))
|
||||||
|
|
||||||
|
if (data.email === email || data.account === email) {
|
||||||
|
return data.points || data.availablePoints
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`[Dashboard] Error loading job state for ${email}:`, error)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,8 +10,19 @@ export const apiRouter = Router()
|
|||||||
// GET /api/status - Bot status
|
// GET /api/status - Bot status
|
||||||
apiRouter.get('/status', (_req: Request, res: Response) => {
|
apiRouter.get('/status', (_req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
const status = dashboardState.getStatus()
|
const accounts = dashboardState.getAccounts()
|
||||||
res.json(status)
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res.json(dashboardState.getStatus())
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
|
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
|
||||||
}
|
}
|
||||||
@@ -20,7 +31,19 @@ apiRouter.get('/status', (_req: Request, res: Response) => {
|
|||||||
// GET /api/accounts - List all accounts with masked emails
|
// GET /api/accounts - List all accounts with masked emails
|
||||||
apiRouter.get('/accounts', (_req: Request, res: Response) => {
|
apiRouter.get('/accounts', (_req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
const accounts = dashboardState.getAccounts()
|
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)
|
res.json(accounts)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
|
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' })
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { MicrosoftRewardsBot } from '../index'
|
import { MicrosoftRewardsBot } from '../index'
|
||||||
|
import { loadAllPointsFromSessions, loadPointsFromJobState } from './SessionLoader'
|
||||||
|
|
||||||
export interface DashboardStatus {
|
export interface DashboardStatus {
|
||||||
running: boolean
|
running: boolean
|
||||||
@@ -133,12 +134,23 @@ class DashboardState {
|
|||||||
|
|
||||||
// Initialize accounts from config
|
// Initialize accounts from config
|
||||||
public initializeAccounts(emails: string[]): void {
|
public initializeAccounts(emails: string[]): void {
|
||||||
|
// Load points from sessions if available
|
||||||
|
const pointsMap = loadAllPointsFromSessions()
|
||||||
|
|
||||||
for (const email of emails) {
|
for (const email of emails) {
|
||||||
if (!this.accounts.has(email)) {
|
if (!this.accounts.has(email)) {
|
||||||
|
// Try to get points from session or job state
|
||||||
|
let points = pointsMap.get(email)
|
||||||
|
if (points === undefined) {
|
||||||
|
points = loadPointsFromJobState(email)
|
||||||
|
}
|
||||||
|
|
||||||
this.accounts.set(email, {
|
this.accounts.set(email, {
|
||||||
email,
|
email,
|
||||||
maskedEmail: this.maskEmail(email),
|
maskedEmail: this.maskEmail(email),
|
||||||
status: 'idle'
|
status: 'idle',
|
||||||
|
points: points,
|
||||||
|
lastSync: points !== undefined ? new Date().toISOString() : undefined
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user