Initial commit

This commit is contained in:
2026-08-30 15:23:57 +02:00
commit dab5679098
1293 changed files with 240952 additions and 0 deletions
@@ -0,0 +1,86 @@
// 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 };
}
};
@@ -0,0 +1,36 @@
// internal dependencies
const connections = require('./connections.js'); // connection manager
const stopService = require('./stop.js'); // for server reference
/*
* Get WebSocket service status
* Returns:
* {
* online: boolean,
* clients: {
* connectionId1: { metadata: {...}, lastHeartbeat: ... },
* connectionId2: { ... }
* }
* }
*/
module.exports = async function websocketStatus() {
try {
// check if server exists and is running
const serverOnline = !!stopService.getServer();
// get active clients
const clients = connections.getAll(); // object with connectionId -> { metadata, lastHeartbeat }
return {
online: serverOnline,
clients
};
} catch (err) {
console.error('Error getting WebSocket status:', err);
return {
online: false,
clients: {},
error: err
};
}
};
@@ -0,0 +1,42 @@
// internal dependencies
const connections = require('./connections.js');
// This will hold a reference to the running WebSocket server
let serverInstance = null;
/*
* Stop the WebSocket service
* - Stops heartbeat
* - Closes all active connections
* - Closes the WebSocket server
*/
async function stopService () {
try {
if (!serverInstance) return { online: false };
// Stop heartbeat system
connections.stopHeartbeat();
// Terminate all active connections
connections.clearAll();
// Close WebSocket server
await new Promise((resolve, reject) => {
serverInstance.close((err) => {
if (err) return reject(err);
resolve();
});
});
serverInstance = null;
console.log('WebSocket server stopped successfully');
return { online: false };
} catch (err) {
console.error('Error stopping WebSocket server:', err);
return { online: true, error: err };
}
};
module.exports = stopService;