Initial
This commit is contained in:
commit
c552956516
23 files changed
+5193
No files matched your search
@@ -0,0 +1,140 @@
|
||||
import express from 'express';
|
||||
import path from 'path';
|
||||
import type { Server } from 'http';
|
||||
import type { Logger } from '../utils/logger.js';
|
||||
import type { PostsRepository, MessagesRepository, SuccessfulMessagesRepository } from '../database/repositories.js';
|
||||
import type { Config } from '../config/index.js';
|
||||
|
||||
export interface BotStats {
|
||||
isRunning: boolean;
|
||||
dryRunMode: boolean;
|
||||
totalProcessed: number;
|
||||
totalMessagesSent: number;
|
||||
totalResponses: number;
|
||||
responseRate: number;
|
||||
messagesThisHour: number;
|
||||
maxMessagesPerHour: number;
|
||||
subreddits: string[];
|
||||
targetGenders: string[];
|
||||
recentActivity: ActivityItem[];
|
||||
}
|
||||
|
||||
export interface ActivityItem {
|
||||
timestamp: number;
|
||||
type: 'sent' | 'skipped' | 'response' | 'error';
|
||||
message: string;
|
||||
recipient?: string;
|
||||
}
|
||||
|
||||
export class WebServer {
|
||||
private app: express.Application;
|
||||
private server: Server | null = null;
|
||||
private activityLog: ActivityItem[] = [];
|
||||
private botStats = {
|
||||
isRunning: true,
|
||||
messagesThisHour: 0,
|
||||
};
|
||||
|
||||
constructor(
|
||||
private port: number,
|
||||
private config: Config,
|
||||
private postsRepo: PostsRepository,
|
||||
private messagesRepo: MessagesRepository,
|
||||
private successfulMessagesRepo: SuccessfulMessagesRepository,
|
||||
private logger: Logger
|
||||
) {
|
||||
this.app = express();
|
||||
this.setupRoutes();
|
||||
}
|
||||
|
||||
private setupRoutes(): void {
|
||||
// Serve static files
|
||||
this.app.use(express.static(path.join(process.cwd(), 'public')));
|
||||
this.app.use(express.json());
|
||||
|
||||
// API: Get stats
|
||||
this.app.get('/api/stats', (req, res) => {
|
||||
const stats = this.getStats();
|
||||
res.json(stats);
|
||||
});
|
||||
|
||||
// API: Get recent activity
|
||||
this.app.get('/api/activity', (req, res) => {
|
||||
res.json(this.activityLog.slice(-50).reverse());
|
||||
});
|
||||
|
||||
// API: Get recent messages
|
||||
this.app.get('/api/messages', (req, res) => {
|
||||
const messages = this.messagesRepo.getRecent(20);
|
||||
res.json(messages);
|
||||
});
|
||||
|
||||
// API: Get successful messages (ones that got responses)
|
||||
this.app.get('/api/successful', (req, res) => {
|
||||
const successful = this.successfulMessagesRepo.getRecent(10);
|
||||
res.json(successful);
|
||||
});
|
||||
|
||||
// Serve dashboard for all other routes
|
||||
this.app.get('*', (req, res) => {
|
||||
res.sendFile(path.join(process.cwd(), 'public', 'index.html'));
|
||||
});
|
||||
}
|
||||
|
||||
private getStats(): BotStats {
|
||||
const messages = this.messagesRepo.getRecent(1000);
|
||||
const totalSent = messages.length;
|
||||
const totalResponses = messages.filter((m) => m.gotResponse).length;
|
||||
|
||||
return {
|
||||
isRunning: this.botStats.isRunning,
|
||||
dryRunMode: this.config.browser.dryRun,
|
||||
totalProcessed: this.getTotalProcessed(),
|
||||
totalMessagesSent: totalSent,
|
||||
totalResponses,
|
||||
responseRate: totalSent > 0 ? Math.round((totalResponses / totalSent) * 100) : 0,
|
||||
messagesThisHour: this.botStats.messagesThisHour,
|
||||
maxMessagesPerHour: this.config.rateLimit.maxMessagesPerHour,
|
||||
subreddits: this.config.reddit.subreddits,
|
||||
targetGenders: this.config.reddit.targetGenders,
|
||||
recentActivity: this.activityLog.slice(-10).reverse(),
|
||||
};
|
||||
}
|
||||
|
||||
private getTotalProcessed(): number {
|
||||
// This is a simple count - in production you'd query the DB
|
||||
return this.activityLog.filter((a) => a.type === 'sent' || a.type === 'skipped').length;
|
||||
}
|
||||
|
||||
logActivity(type: ActivityItem['type'], message: string, recipient?: string): void {
|
||||
const item: ActivityItem = {
|
||||
timestamp: Date.now(),
|
||||
type,
|
||||
message,
|
||||
recipient,
|
||||
};
|
||||
this.activityLog.push(item);
|
||||
|
||||
// Keep only last 200 items
|
||||
if (this.activityLog.length > 200) {
|
||||
this.activityLog = this.activityLog.slice(-200);
|
||||
}
|
||||
}
|
||||
|
||||
updateStats(messagesThisHour: number): void {
|
||||
this.botStats.messagesThisHour = messagesThisHour;
|
||||
}
|
||||
|
||||
start(): void {
|
||||
this.server = this.app.listen(this.port, () => {
|
||||
this.logger.info(`Web dashboard running at http://localhost:${this.port}`);
|
||||
});
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
if (this.server) {
|
||||
this.server.close();
|
||||
this.server = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user