From cf94d2a787d9a11ad2b4841102fa6d552076d5cb Mon Sep 17 00:00:00 2001 From: Skylar Sadlier Date: Tue, 6 Aug 2024 11:34:06 -0600 Subject: [PATCH 1/3] - Fixed halt if option --- query-game-server.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/query-game-server.js b/query-game-server.js index f3e54dd..1e9633b 100644 --- a/query-game-server.js +++ b/query-game-server.js @@ -55,7 +55,7 @@ module.exports = function(RED) { .then(function(state) { msg.payload = 'online'; msg.data = state; - if (msg.payload === msg.halt_if) { + if (msg.payload === node.halt_if) { return null; } node.status({fill:"green",shape:"dot",text: 'Online ' + msg.data.players.length + ' players' }); @@ -65,7 +65,7 @@ module.exports = function(RED) { msg.data = { 'error': error }; - if (msg.payload === msg.halt_if) { + if (msg.payload === node.halt_if) { return null; } node.status({fill:"red", shape:"dot", text: 'Offline'}); From c0c40910aebcba5a607a8cf2f3b1f20378377316 Mon Sep 17 00:00:00 2001 From: Skylar Sadlier Date: Thu, 21 Nov 2024 11:08:03 -0700 Subject: [PATCH 2/3] - Update GameDig from 5.1.0 to 5.1.4 - Errors in parsing GameDig response now throw an error instead of returning to output - Prevents "Class constructor Players cannot be invoked without 'new'" error when Node-RED attempts to clone the server response data (this happens when the gamedig node feeds into a function node for example) --- package-lock.json | 49 +++++++++++---------------- package.json | 4 +-- query-game-server.js | 80 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 88 insertions(+), 45 deletions(-) diff --git a/package-lock.json b/package-lock.json index 854edbd..68e76db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "3.0.0", "license": "MIT", "dependencies": { - "gamedig": "^5.1.0" + "gamedig": "^5.1.4" } }, "node_modules/@sindresorhus/is": { @@ -267,19 +267,18 @@ } }, "node_modules/gamedig": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/gamedig/-/gamedig-5.1.0.tgz", - "integrity": "sha512-eif4dAvR9hpSPuuLcP8cGrD3d1XjNrgzgI2N9JjuObp6RepGjm31SCJfOF85Q0eQsS5VgTeHdLfTyfG4DS+cRA==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/gamedig/-/gamedig-5.1.4.tgz", + "integrity": "sha512-MgSbNVGh5QMdrmRTrZ3W7W6sC5/Mx+dMgTy2uZCKQ9vns9eFXkQj61Pw2Y2FNHNMMp4DXFSUMYAPJWLcR16Wwg==", "dependencies": { - "cheerio": "^1.0.0-rc.12", - "gbxremote": "^0.2.1", - "got": "^13.0.0", - "iconv-lite": "^0.6.3", - "long": "^5.2.3", - "minimist": "^1.2.8", - "punycode": "^2.3.0", - "seek-bzip": "^2.0.0", - "varint": "^6.0.0" + "cheerio": "1.0.0-rc.12", + "gbxremote": "0.2.1", + "got": "13.0.0", + "iconv-lite": "0.6.3", + "long": "5.2.3", + "minimist": "1.2.8", + "seek-bzip": "2.0.0", + "varint": "6.0.0" }, "bin": { "gamedig": "bin/gamedig.js" @@ -473,22 +472,22 @@ } }, "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", "dependencies": { - "entities": "^4.4.0" + "entities": "^4.5.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" } }, "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", - "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", "dependencies": { - "domhandler": "^5.0.2", + "domhandler": "^5.0.3", "parse5": "^7.0.0" }, "funding": { @@ -500,14 +499,6 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "engines": { - "node": ">=6" - } - }, "node_modules/quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", diff --git a/package.json b/package.json index 955ad8c..5e00cc1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-red-contrib-gamedig", - "version": "3.0.0", + "version": "3.0.1", "description": "Query for the status of any game server using node-red", "repository": { "type": "git", @@ -23,6 +23,6 @@ } }, "dependencies": { - "gamedig": "^5.1.0" + "gamedig": "^5.1.4" } } diff --git a/query-game-server.js b/query-game-server.js index 1e9633b..8c80dc5 100644 --- a/query-game-server.js +++ b/query-game-server.js @@ -1,6 +1,44 @@ module.exports = function(RED) { const { GameDig, games } = require('gamedig'); + function deepCloneToPlain(obj) { + // Handle null/undefined + if (!obj) { + return obj; + } + + // Handle arrays and array-like objects (including Players collection) + if (Array.isArray(obj) || (typeof obj === 'object' && obj.length >= 0)) { + return Array.from(obj, item => deepCloneToPlain(item)); + } + + // Handle instances of custom classes (like Player, Results) + if (obj && typeof obj === 'object' && Object.getPrototypeOf(obj) !== Object.prototype) { + // Convert to plain object while preserving enumerable properties + const plainObj = {}; + for (const key of Object.keys(obj)) { + plainObj[key] = deepCloneToPlain(obj[key]); + } + return plainObj; + } + + // Handle plain objects + if (obj && typeof obj === 'object') { + const result = {}; + for (const key of Object.keys(obj)) { + // Skip the Buffer instance + if (key === 'rulesBytes' && Buffer.isBuffer(obj[key])) { + continue; + } + result[key] = deepCloneToPlain(obj[key]); + } + return result; + } + + // Return primitive values as-is + return obj; + } + function QueryGameServer(config) { RED.nodes.createNode(this, config); let node = this; @@ -53,24 +91,38 @@ module.exports = function(RED) { GameDig.query(options) .then(function(state) { - msg.payload = 'online'; - msg.data = state; - if (msg.payload === node.halt_if) { - return null; - } - node.status({fill:"green",shape:"dot",text: 'Online ' + msg.data.players.length + ' players' }); - node.send(msg); - }).catch(function(error) { + try { + msg.payload = 'online'; + // GameDig returns Results, Players, and Player objects that we need to convert + // to standard Array/Object instances so that Node-RED doesn't error + console.log("RESULT", state); + msg.data = deepCloneToPlain(state); + console.log("FORMATTED", msg.data); + + if (msg.payload === node.halt_if) { + return null; + } + node.status({ fill: "green", shape: "dot", text: `Online ${state.players.length} players` }); + node.send(msg); + } catch(e) { + node.error("Failed returning data: " + e.stack); + } + }) + .catch(function(error) { msg.payload = 'offline'; msg.data = { - 'error': error + error, + stack: error.stack, }; - if (msg.payload === node.halt_if) { - return null; - } - node.status({fill:"red", shape:"dot", text: 'Offline'}); - node.send(msg); + if (msg.payload === node.halt_if) { + return null; + } + node.status({ fill: "red", shape: "dot", text: "Offline" }); + node.send(msg); + node.error(`GameDig Error: \n${error.stack}`); + console.error(error); }); + }); } RED.nodes.registerType("query-game-server", QueryGameServer); From 12d4a40cf4c31dd91b8b82b072601f8529baec81 Mon Sep 17 00:00:00 2001 From: Skylar Sadlier Date: Thu, 21 Nov 2024 11:16:04 -0700 Subject: [PATCH 3/3] - Remove console.log debug lines --- query-game-server.html | 1 - query-game-server.js | 3 --- 2 files changed, 4 deletions(-) diff --git a/query-game-server.html b/query-game-server.html index 8172a29..cf5a339 100644 --- a/query-game-server.html +++ b/query-game-server.html @@ -36,7 +36,6 @@ }, oneditprepare: function() { let server_types = null; - console.log("THIS:", this); if(typeof this.strip_colors === "undefined") { this.strip_colors = true; $("#node-input-strip_colors").prop('checked', true); diff --git a/query-game-server.js b/query-game-server.js index 8c80dc5..6364535 100644 --- a/query-game-server.js +++ b/query-game-server.js @@ -95,9 +95,7 @@ module.exports = function(RED) { msg.payload = 'online'; // GameDig returns Results, Players, and Player objects that we need to convert // to standard Array/Object instances so that Node-RED doesn't error - console.log("RESULT", state); msg.data = deepCloneToPlain(state); - console.log("FORMATTED", msg.data); if (msg.payload === node.halt_if) { return null; @@ -131,7 +129,6 @@ module.exports = function(RED) { "/gamedig/types", RED.auth.needsPermission('flows.write'), function(req, res) { - console.log(games); let server_types = Object.keys(games).map(gameKey => { let game = games[gameKey]; game["type"] = gameKey;