-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.js
More file actions
145 lines (120 loc) · 4.14 KB
/
server.js
File metadata and controls
145 lines (120 loc) · 4.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
const http = require('http');
const express = require('express');
const { WebSocketServer } = require('ws');
const cors = require('cors');
const path = require('path');
const fs = require('fs');
// ─── Modules ───
const db = require('./modules/database');
const auth = require('./modules/auth');
const discovery = require('./modules/discovery');
const processManager = require('./modules/processManager');
const scheduler = require('./modules/scheduler');
const updater = require('./modules/updater');
const monitor = require('./modules/monitor');
const wsHandler = require('./modules/wsHandler');
const tgBot = require('./modules/telegram');
const apiRoutes = require('./routes/api');
// ─── Init ───
const PORT = process.env.PORT || 3000;
const HOST = process.env.HOST || '0.0.0.0';
const DATA_DIR = path.join(__dirname, 'data');
const PID_FILE = path.join(DATA_DIR, 'server.pid');
const app = express();
const server = http.createServer(app);
// ─── Middleware ───
app.use(cors());
app.use(express.json());
app.use(auth.authMiddleware);
app.use(express.static(path.join(__dirname, 'public')));
// ─── API Routes ───
app.use('/api', apiRoutes);
// ─── API 404 ───
app.all('/api/*', (req, res) => {
res.status(404).json({ error: 'API route not found' });
});
// ─── SPA Fallback ───
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
// ─── WebSocket ───
const wss = new WebSocketServer({ server, path: '/ws' });
wsHandler.init(wss);
// ─── Bootstrap ───
async function start() {
// 1. Initialize database
db.init();
console.log('[Server] Database initialized');
// 2. Check if any users exist
if (db.getUserCount() === 0) {
console.log('[Server] No users found. Use manager.bat to create an admin account.');
}
// 3. Auto-Discovery
const scanResult = discovery.scan();
console.log(`[Server] Discovery: ${scanResult.discovered} new soft(s) found`);
// 4. Start scheduler
scheduler.init(processManager);
console.log('[Server] Scheduler initialized');
// 4.5 Start updater
updater.start();
console.log('[Server] Auto-updater initialized');
// 5. Start OS monitor
monitor.start(2000);
console.log('[Server] Monitor started');
// 6. Start server
server.listen(PORT, HOST, () => {
console.log(`[Server] Running on http://${HOST}:${PORT}`);
console.log(`[Server] WebSocket on ws://${HOST}:${PORT}/ws`);
// Write PID file for manager.bat
try {
if (!fs.existsSync(DATA_DIR)) fs.mkdirSync(DATA_DIR, { recursive: true });
fs.writeFileSync(PID_FILE, String(process.pid), 'utf-8');
console.log(`[Server] PID ${process.pid} written to ${PID_FILE}`);
} catch (err) {
console.log(`[Server] Warning: could not write PID file: ${err.message}`);
}
// Show LAN IPs
const nets = require('os').networkInterfaces();
for (const name of Object.keys(nets)) {
for (const net of nets[name]) {
if (net.family === 'IPv4' && !net.internal) {
console.log(`[Server] LAN: http://${net.address}:${PORT}`);
}
}
}
});
}
// ─── Graceful Shutdown ───
async function shutdown() {
console.log('\n[Server] Shutting down...');
try { fs.writeFileSync(path.join(DATA_DIR, 'manual_stop.flag'), '1', 'utf8'); } catch {}
// Remove PID file
try { fs.unlinkSync(PID_FILE); } catch {}
// Stop monitor
monitor.stop();
// Stop all processes gracefully
const running = processManager.getAllRunning();
for (const softId of Object.keys(running)) {
console.log(`[Server] Stopping ${softId}...`);
processManager.forceKill(softId);
}
// Close WebSocket connections
wss.clients.forEach(client => client.close());
// Close server
server.close(() => {
console.log('[Server] HTTP server closed');
process.exit(0);
});
// Force exit after 10s
setTimeout(() => {
console.log('[Server] Forced exit');
process.exit(1);
}, 10000);
}
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
// ─── Start ───
start().catch(err => {
console.error('[Server] Fatal error:', err);
process.exit(1);
});