Ajout redirection des logs sur websocket et page /logs/view
This commit is contained in:
@@ -31,20 +31,23 @@ const getRequestToDo = async function (msn) {
|
||||
|
||||
///// Programs
|
||||
if (device.programs != undefined) {
|
||||
if (child.programmingTimestamp < device.programs.timestamp) { todo.programs = 1 }
|
||||
else if (child.programmingTimestamp > device.programs.timestamp) { todo.programs = 2 }
|
||||
timestamp = child.programmingTimestamp || -1
|
||||
if (timestamp < device.programs.timestamp) { todo.programs = 1 }
|
||||
else if (timestamp > device.programs.timestamp) { todo.programs = 2 }
|
||||
}
|
||||
|
||||
///// Configuration
|
||||
if (device.configuration != undefined) {
|
||||
if (child.configurationTimestamp < device.configuration.timestamp) { todo.configuration = 1 }
|
||||
else if (child.configurationTimestamp > device.configuration.timestamp) { todo.configuration = 2 }
|
||||
timestamp = child.configurationTimestamp || child.relayConfigurationTimestamp || -1
|
||||
if (timestamp < device.configuration.timestamp) { todo.configuration = 1 }
|
||||
else if (timestamp > device.configuration.timestamp) { todo.configuration = 2 }
|
||||
}
|
||||
|
||||
///// Slots
|
||||
if (device.slots != undefined) {
|
||||
if (child.programmingTimestamp < device.slots.timestamp) { todo.slots = 1 }
|
||||
else if (child.programmingTimestamp > device.slots.timestamp) { todo.slots = 2 }
|
||||
timestamp = child.programmingTimestamp || -1
|
||||
if (timestamp < device.slots.timestamp) { todo.slots = 1 }
|
||||
else if (timestamp > device.slots.timestamp) { todo.slots = 2 }
|
||||
}
|
||||
|
||||
///// Status
|
||||
|
||||
@@ -6,6 +6,7 @@ const ipx = require('./ipx.service')
|
||||
const journal = require('./journal.service')
|
||||
const longpolling = require('./longpolling.service')
|
||||
const device = require('./device.service')
|
||||
const log = require('./log.service')
|
||||
|
||||
module.exports = {
|
||||
status,
|
||||
@@ -16,4 +17,5 @@ module.exports = {
|
||||
journal,
|
||||
longpolling,
|
||||
device,
|
||||
log
|
||||
}
|
||||
123
services/log.service.js
Normal file
123
services/log.service.js
Normal file
@@ -0,0 +1,123 @@
|
||||
// services/logService.js
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const decodeURIComponentSafe = str => {
|
||||
try {
|
||||
return decodeURIComponent(str);
|
||||
} catch {
|
||||
return str; // fallback
|
||||
}
|
||||
};
|
||||
|
||||
const wssList = []; // all WS servers
|
||||
const sockets = []; // { ws, name }
|
||||
const originalConsole = {};
|
||||
let clients = new Map(); // ws => username
|
||||
|
||||
// ASCII check
|
||||
function isAscii(str) {
|
||||
return /^[\x00-\x7F]*$/.test(str);
|
||||
}
|
||||
|
||||
const attachLogService = async function (server, basePath = '/logs') {
|
||||
try {
|
||||
const wss = new WebSocket.Server({ noServer: true });
|
||||
wssList.push(wss);
|
||||
|
||||
// Save original console methods once
|
||||
["log", "error", "warn", "info", "debug"].forEach(fn => {
|
||||
if (!originalConsole[fn]) originalConsole[fn] = console[fn];
|
||||
});
|
||||
|
||||
// Override console methods (only once)
|
||||
if (!originalConsole._overridden) {
|
||||
["log", "error", "warn", "info", "debug"].forEach(fn => {
|
||||
console[fn] = (...args) => {
|
||||
originalConsole[fn].apply(console, args);
|
||||
const msg = args.map(a => (typeof a === "string" ? a : JSON.stringify(a))).join(" ");
|
||||
broadcast({ type: fn, message: msg, client: "server" });
|
||||
};
|
||||
});
|
||||
originalConsole._overridden = true;
|
||||
}
|
||||
|
||||
// Handle HTTP upgrade requests
|
||||
server.on("upgrade", (request, socket, head) => {
|
||||
const urlParts = request.url.split('/').filter(Boolean); // e.g. ['logs','😎']
|
||||
if (urlParts[0] === basePath.replace(/^\/+/, '') && urlParts[1]) {
|
||||
// Decode URL safely, preserving emojis
|
||||
const clientName = decodeURIComponentSafe(urlParts[1]);
|
||||
|
||||
wss.handleUpgrade(request, socket, head, ws => {
|
||||
ws.clientName = clientName;
|
||||
wss.emit('connection', ws, request);
|
||||
clients.set(ws, clientName);
|
||||
sendClientsUpdate();
|
||||
});
|
||||
} else {
|
||||
socket.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
// WS connection
|
||||
wss.on('connection', ws => {
|
||||
sockets.push(ws);
|
||||
|
||||
ws.on("message", rawMsg => {
|
||||
const msg = rawMsg.toString();
|
||||
broadcast({ type: "message", message: msg, client: ws.clientName });
|
||||
});
|
||||
|
||||
ws.on("close", () => {
|
||||
const index = sockets.indexOf(ws);
|
||||
if (index !== -1) sockets.splice(index, 1);
|
||||
|
||||
clients.delete(ws);
|
||||
sendClientsUpdate();
|
||||
});
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
} catch (e) {
|
||||
throw new Error(e.message);
|
||||
}
|
||||
};
|
||||
|
||||
const detachLogService = async function () {
|
||||
try {
|
||||
Object.keys(originalConsole).forEach(fn => {
|
||||
if (fn !== "_overridden") console[fn] = originalConsole[fn];
|
||||
});
|
||||
|
||||
sockets.forEach(ws => ws.close());
|
||||
sockets.length = 0;
|
||||
|
||||
wssList.forEach(wss => wss.close());
|
||||
wssList.length = 0;
|
||||
|
||||
return { success: true };
|
||||
} catch (e) {
|
||||
throw new Error(e.message);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Broadcast helper
|
||||
function broadcast(obj) {
|
||||
// Add timestamp
|
||||
obj.timestamp = new Date().toISOString();
|
||||
const msg = JSON.stringify(obj);
|
||||
sockets.forEach(ws => {
|
||||
if (ws.readyState === WebSocket.OPEN) ws.send(msg);
|
||||
});
|
||||
}
|
||||
|
||||
function sendClientsUpdate() {
|
||||
const clientNames = Array.from(clients.values());
|
||||
broadcast({ clients: clientNames });
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
attachLogService,
|
||||
detachLogService,
|
||||
};
|
||||
Reference in New Issue
Block a user