poe2-bot/src-old/server/Server.ts
2026-02-13 01:12:11 -05:00

97 lines
2.9 KiB
TypeScript

import express from 'express';
import http from 'http';
import { WebSocketServer, WebSocket } from 'ws';
import path from 'path';
import { fileURLToPath } from 'url';
import { logger } from '../util/logger.js';
import { statusRoutes } from './routes/status.js';
import { controlRoutes } from './routes/control.js';
import { linkRoutes } from './routes/links.js';
import { debugRoutes } from './routes/debug.js';
import type { Bot } from '../bot/Bot.js';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
export class Server {
private app = express();
private server: http.Server;
private wss: WebSocketServer;
private clients: Set<WebSocket> = new Set();
private bot: Bot;
constructor(bot: Bot, private port: number = 3000) {
this.bot = bot;
this.app.use(express.json());
this.app.get('/', (_req, res) => {
res.sendFile(path.join(__dirname, '..', '..', 'src', 'server', 'index.html'));
});
// Mount routes
this.app.use('/api', statusRoutes(bot));
this.app.use('/api', controlRoutes(bot));
this.app.use('/api/links', linkRoutes(bot));
this.app.use('/api/debug', debugRoutes(bot, this));
this.server = http.createServer(this.app);
this.wss = new WebSocketServer({ server: this.server });
this.wss.on('connection', (ws) => {
this.clients.add(ws);
ws.send(JSON.stringify({ type: 'status', data: bot.getStatus() }));
ws.on('close', () => this.clients.delete(ws));
});
// Subscribe to bot events
bot.on('status-update', () => this.broadcastStatus());
bot.on('log', (level: string, message: string) => this.broadcastLog(level, message));
}
broadcastStatus(): void {
const msg = JSON.stringify({ type: 'status', data: this.bot.getStatus() });
for (const client of this.clients) {
if (client.readyState === WebSocket.OPEN) {
client.send(msg);
}
}
}
broadcastLog(level: string, message: string): void {
const msg = JSON.stringify({
type: 'log',
data: { level, message, time: new Date().toISOString() },
});
for (const client of this.clients) {
if (client.readyState === WebSocket.OPEN) {
client.send(msg);
}
}
}
broadcastDebug(action: string, data: Record<string, unknown>): void {
const msg = JSON.stringify({ type: 'debug', data: { action, ...data } });
for (const client of this.clients) {
if (client.readyState === WebSocket.OPEN) {
client.send(msg);
}
}
}
async start(): Promise<void> {
return new Promise((resolve) => {
this.server.listen(this.port, () => {
logger.info({ port: this.port }, `Dashboard running at http://localhost:${this.port}`);
resolve();
});
});
}
async stop(): Promise<void> {
for (const client of this.clients) {
client.close();
}
return new Promise((resolve) => {
this.server.close(() => resolve());
});
}
}