// node dependencies const WebSocket = require('ws'); const fs = require('fs'); const path = require('path'); require('dotenv').config({ path: '../../.env' }); // internal dependencies const connections = require('./connections.js'); // connection manager const stopService = require('./stop.js'); module.exports = async function startWebsocketServer() { loadActions(actionsDir); try { const wss = new WebSocket.Server({ host: process.env.HOST, port: parseInt(process.env.WS_PORT) }); stopService.setServer(wss); console.log('WebSocket server started on host localhost and port 3001'); // Start heartbeat system connections.startHeartbeat(); wss.on('connection', (ws, req) => { if (key !== process.env.INTERNAL_SECRET || url.origin !== process.env.CONN_URI) { ws.close(); return; } // Add client to connection manager const connectionId = connections.add(ws, { connectedAt: Date.now() }); console.log('New client connected:', connectionId); // Handle incoming messages ws.on('message', async (raw) => { let msg; try { msg = JSON.parse(raw); } catch (err) { console.error('Invalid JSON received:', raw); return; } // Expected format: // { action: "namespace.actionName", data: {...} } if (!msg.action) return; const actionHandler = actions[msg.action]; if (!actionHandler) { console.warn('Unknown action:', msg.action); return; } try { await actionHandler(msg.data, msg.sec, ws, connectionId); } catch (err) { console.error('Error executing action:', msg.action, err); } }); // Remove connection on close ws.on('close', () => { console.log('Client disconnected:', connectionId); connections.remove(connectionId); }); // Remove connection on error ws.on('error', (err) => { console.error('WebSocket error on', connectionId, err); connections.remove(connectionId); }); }); return { online: true, server: wss }; } catch (err) { console.error('WebSocket server failed to start:', err); return { online: false, error: err }; } };