19 Commits

Author SHA1 Message Date
skylord123 facf77e1fa Merge pull request #9 from skylord123/dev
Update version to 2.1.2
2023-02-23 23:09:44 -07:00
skylord123 9d200b60a1 - update version to 2.1.2
- fixed server type list
- bump gamedig to 4.0.6
2023-02-23 23:06:48 -07:00
skylord123 f6078118c0 Merge pull request #2 from skylord123/dev
update version to 2.1.1
2021-09-04 23:01:58 -06:00
skylord123 e2e8119d7f - update version to 2.1.1
- node description updated
- node now errors if msg.host or msg.port is left blank and not configured on the node
- server type & host is not required when configuring the node since it can be passed in via the inputs
- when modifying a node in the editor you can now view available server types at the bottom of the properties. This is parsed from the gamedig readme.
- Update gamedig version
- package-lock.json added
- palette label changed to "Query Game Server"
2021-09-04 23:00:32 -06:00
skylord123 09c763a605 Up version to 2.0.1
- Updated readme for NPM
2019-12-09 18:44:14 -07:00
skylord123 67ad3de10b Merge branch 'master' of github.com:skylord123/node-red-contrib-gamedig 2019-12-09 18:43:11 -07:00
skylord123 1885f7b8a1 Up version to 2.0.0 2019-12-09 18:42:51 -07:00
skylord123 072c85f78a - Fixed port not being passed through
- Added support for maxAttempts, socketTimeout, and attemptTimeout advanced options in GameDig to be configurable on the node.
- Updated help information to match new changes.
2019-12-09 18:39:53 -07:00
skylord123 36afa961a3 Fix for name field not working 2019-12-09 18:13:49 -07:00
skylord123 a2a4f47604 Change how names for nodes are displayed 2019-12-09 18:12:35 -07:00
skylord123 6836b82b0b Update README.md 2019-12-06 01:37:51 -07:00
skylord123 52bddfa603 Up version to 1.1.5
- Fixed server_type not being set correctly after last update
- Added status messages to node
2019-12-05 20:45:26 -07:00
skylord123 4770cfdc53 Up version to 1.1.5
- Fixed server_type not being set correctly after last update
- Added status messages to node
2019-12-05 20:45:12 -07:00
skylord123 3fdd0c1539 Up version to 1.1.0 2019-12-05 20:12:58 -07:00
skylord123 b8ec64d854 Up version to 1.1.0
- Added server_type, host, and port to the output message.
2019-12-05 20:11:38 -07:00
skylord123 560d24f068 Up version to 1.0.1
- Updated readme and added keywords
2019-12-04 12:58:04 -07:00
skylord123 539f7fe21f 1.0.0 release now that we are working and tested 2019-12-04 12:48:41 -07:00
skylord123 6f806ca727 Updated icon 2019-12-04 12:45:50 -07:00
skylord123 d3c076bb6a - Changed structure layout
- Fixed query-game-server node so it actually works instead of throwing browser errors when added to the user's work area.
- Updated query-game-server.html to look better
- Added stuff to the node help
2019-12-04 12:41:11 -07:00
10 changed files with 1538 additions and 94 deletions
+3
View File
@@ -1,3 +1,6 @@
# ide
.idea
# Logs # Logs
logs logs
*.log *.log
+22 -1
View File
@@ -1,2 +1,23 @@
# node-red-contrib-gamedig # node-red-contrib-gamedig
Query for the status of any game server using Node Red
Query for the status of most game/voice servers using Node-RED.
This package adds the node "Query Game Server" that uses the NPM package [GameDig](https://www.npmjs.com/package/gamedig) to query if a server is online or not and if so returns the data of the server.
You can pass the server type, host, and port on the input message or define them on the node (settings defined on the node will override msg values).
### Usage Examples
#### Inserting query data into InfluxDB and using Grafana to view results
![Flow Preview](https://skylar.tech/content/images/2019/12/image-2.png)
I created a post on my website about how to use this node to query gameservers and store the results in InfluxDB. I then give a dashboard in Grafana that can be used to display the data. Check it out here:
https://skylar.tech/tracking-game-server-statistics-using-node-red-influxdb-and-grafana/
### Other Packages
- [node-red-contrib-matrix-chat](https://www.npmjs.com/package/node-red-contrib-gamedig) - Matrix chat server client for Node-RED
### Developers
So far me (skylord123) is the only person that has contributed towards this package. Feel free to do any pull-requests to get your name here!
### License
This project is licensed under the MIT License. Check [here](LICENSE) for more information.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 913 B

+1152
View File
File diff suppressed because it is too large Load Diff
+8 -7
View File
@@ -1,11 +1,7 @@
{ {
"name": "node-red-contrib-gamedig", "name": "node-red-contrib-gamedig",
"version": "0.1.0", "version": "2.1.2",
"description": "Query for the status of any game server using node-red", "description": "Query for the status of any game server using node-red",
"main": "query-game-server/query-game-server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/skylord123/node-red-contrib-gamedig.git" "url": "git+https://github.com/skylord123/node-red-contrib-gamedig.git"
@@ -16,12 +12,17 @@
"url": "https://github.com/skylord123/node-red-contrib-gamedig/issues" "url": "https://github.com/skylord123/node-red-contrib-gamedig/issues"
}, },
"homepage": "https://github.com/skylord123/node-red-contrib-gamedig#readme", "homepage": "https://github.com/skylord123/node-red-contrib-gamedig#readme",
"keywords": [
"node-red",
"gamedig",
"query game server"
],
"node-red": { "node-red": {
"nodes": { "nodes": {
"query-game-server": "query-game-server/query-game-server.js" "query-game-server": "query-game-server.js"
} }
}, },
"dependencies": { "dependencies": {
"gamedig": "^2.0.13" "gamedig": "^4.0.6"
} }
} }
+240
View File
@@ -0,0 +1,240 @@
<script type="text/javascript">
RED.nodes.registerType('query-game-server', {
category: 'advanced',
color: '#a6bbcf',
defaults: {
name: { value: '' },
server_type: { value: '' },
host: { value: '' },
port: { value: '' },
halt_if: { value: '' },
max_attempts: { value: '' },
socket_timeout: { value: '' },
attempt_timeout: { value: '' },
},
inputs:1,
outputs:1,
icon: "icons/server.png",
paletteLabel: "Query Game Server",
label: function() {
if(this.name){
return this.name;
}
if(this.host) {
return (this.server_type ? this.server_type : 'Query') + ': ' + this.host + (this.port ? ":" + this.port : '');
}
return 'Query Game Server';
},
oneditprepare: function() {
$.getJSON('/gamedig/types', function(data) {
let html = '<table>' +
'<thead id="query-game-server-types-table"><tr><td><strong>Type</strong></td><td><strong>Name</strong></td><td><strong>Protocol</strong></td></tr></thead>' +
'<tbody id="query-game-server-type-rows">';
for(let game of data) {
html += "<tr class=\"query-game-server-type-row\">" +
"<td>"+game['type']+"</td>" +
"<td>"+game['name']+"</td>" +
"<td>"+game['protocol']+"</td>" +
"</tr>";
}
html += '</tbody>' +
'</table>';
$("#query-game-server-types").html(html);
});
}
});
</script>
<script type="text/html" data-template-name="query-game-server">
<style>
#query-game-server-types table, #query-game-server-types th, #query-game-server-types td {
border: 1px solid black;
border-collapse: collapse;
}
#query-game-server-types td {
padding: 3px;
}
</style>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-row">
<label for="node-input-server_type"><i class="fa fa-cube"></i> Server Type</label>
<input type="text" id="node-input-server_type">
</div>
<div style="margin-left: 105px;width: 50%;margin-bottom: 10px;margin-top: -10px;">
View server types <a href="#gamdig-types" style="color:#0000EE;text-decoration: underline;">below</a>.
</div>
<div class="form-row">
<label for="node-input-host"><i class="fa fa-server"></i> Host</label>
<input type="text" id="node-input-host" placeholder="msg.host" />
</div>
<div style="margin-left: 105px;width: 50%;margin-bottom: 10px;margin-top: -10px;">
Host without port. Uses <code>msg.host</code> if left blank.
</div>
<div class="form-row">
<label for="node-input-port"><i class="fa fa-ethernet"></i> Port</label>
<input type="text" id="node-input-port" placeholder="msg.host" />
</div>
<div style="margin-left: 105px;width: 50%;margin-bottom: 10px;margin-top: -10px;">
Query port for the server (join and query port may differ).
If this is left blank it will use the default port for the server type specified.
Uses <code>msg.port</code> if left blank.
</div>
<div class="form-row">
<label for="node-input-halt_if"><i class="fa fa-hand-paper-o"></i> Halt If</label>
<select type="text" id="node-input-halt_if">
<option value="">Do not halt</option>
<option value="online">Online</option>
<option value="offline">Offline</option>
</select>
</div>
<div style="margin-left: 105px;width: 50%;margin-bottom: 10px;margin-top: -10px;">
Filter messages based on server status
</div>
<div class="form-row">
<label for="node-input-max_attempts"><i class="fa fa-cogs"></i> Max Attempts</label>
<input type="text" id="node-input-max_attempts" placeholder="1" />
</div>
<div style="margin-left: 105px;width: 50%;margin-bottom: 10px;margin-top: -10px;">
Number of attempts to query server in case of failure.
</div>
<div class="form-row">
<label for="node-input-socket_timeout"><i class="fa fa-cogs"></i> Socket Timeout</label>
<input type="text" id="node-input-socket_timeout" placeholder="2000" />
</div>
<div style="margin-left: 105px;width: 50%;margin-bottom: 10px;margin-top: -10px;">
Milliseconds to wait for a single packet. Beware that increasing this will cause many queries to take longer even if the server is online.
</div>
<div class="form-row">
<label for="node-input-attempt_timeout"><i class="fas fa-cogs"></i> Attempt Timeout</label>
<input type="text" id="node-input-attempt_timeout" placeholder="10000" />
</div>
<div style="margin-left: 105px;width: 50%;margin-bottom: 10px;margin-top: -10px;">
Milliseconds allowed for an entire query attempt. This timeout is not commonly hit, as the socketTimeout typically fires first.
</div>
<h3 id="gamdig-types">Server Types</h3>
<p>
Search available types below.<br>
You can also view the list <a href="https://github.com/gamedig/node-gamedig#games-list" target="_blank" style="color:#0000EE;text-decoration: underline;">here</a>.
</p>
<div class="row">
<input type="text" id="query-game-server-types-search" placeholder="Search types.." style="margin-bottom: 10px;" />
</div>
<div id="query-game-server-types"></div>
<script type="text/javascript">
$("#query-game-server-types-search").on("input", function(e) {
let value = $(this).val();
if(value.length) {
$(".query-game-server-type-row").each(function(i, elem){
console.log('yay', $(elem).text(), value, $(elem).text().indexOf(value));
if($(elem).text().toLowerCase().indexOf(value.toLowerCase()) > -1) {
$(elem).show();
} else {
$(elem).hide();
}
});
return;
}
$(".query-game-server-type-row").show();
});
</script>
</script>
<script type="text/html" data-help-name="query-game-server">
<p>Query most Game/Voice server's using the <a href="https://github.com/gamedig/node-gamedig" target="_blank">GameDig</a> library.</p>
<h3>Inputs</h3>
<dl class="message-properties">
<dt class="optional">
msg.server_type <span class="property-type">string | null</span>
</dt>
<dd>Server type to query. View available types either at the bottom of the node editor or <a href="https://github.com/sonicsnes/node-gamedig#games-list" style="color:#0000EE;" target="_blank">click here</a>. Ignored if configured on the node.</dd>
<dt class="optional">
msg.host <span class="property-type">string | null</span>
</dt>
<dd>Server IP/Hostname. Ignored if configured on the node.</dd>
<dt class="optional">
msg.port <span class="property-type">integer | null</span>
</dt>
<dd>Query port of the server. Ignored if configured on the node. Uses default query port for the server type if left empty.</dd>
<dt class="optional">
msg.max_attempts <span class="property-type">integer | null</span>
</dt>
<dd>Number of attempts to query server in case of failure. Ignored if configured on the node.</dd>
<dt class="optional">
msg.socket_timeout <span class="property-type">integer | null</span>
</dt>
<dd>Milliseconds to wait for a single packet. Beware that increasing this will cause many queries to take longer even if the server is online. Ignored if configured on the node.</dd>
<dt class="optional">
msg.attempt_timeout <span class="property-type">integer | null</span>
</dt>
<dd>Milliseconds allowed for an entire query attempt. This timeout is not commonly hit, as the socketTimeout typically fires first. Ignored if configured on the node.</dd>
</dl>
<h3>Outputs</h3>
<dl class="message-properties">
<dt>
msg.payload <span class="property-type">string</span>
</dt>
<dd>Returns either <code>online</code> or <code>offline</code>.</dd>
<dt>
msg.data <span class="property-type">object</span>
</dt>
<dd>Returns back the results we got from GameDig. Click <a href="https://github.com/sonicsnes/node-gamedig#return-value" target="_blank" style="color:#0000EE;">here</a> for more information on what this contains.</dd>
<dt>
msg.data.error <span class="property-type">string</span>
</dt>
<dd>Reason the server failed to query. Only returns if <code>msg.payload</code> is <code>offline</code>.</dd>
<dt>
msg.server_type <span class="property-type">string</span>
</dt>
<dd>Server type to query. View available types either at the bottom of the node editor or <a href="https://github.com/sonicsnes/node-gamedig#games-list" style="color:#0000EE;" target="_blank">click here</a>. Ignored if configured on the node.</dd>
<dt>
msg.host <span class="property-type">string</span>
</dt>
<dd>Server IP/Hostname. Ignored if configured on the node.</dd>
<dt>
msg.port <span class="property-type">integer</span>
</dt>
<dd>Query port of the server. Ignored if configured on the node.</dd>
<dt>
msg.max_attempts <span class="property-type">integer</span>
</dt>
<dd>Number of attempts to query server in case of failure. Ignored if configured on the node.</dd>
<dt>
msg.socket_timeout <span class="property-type">integer</span>
</dt>
<dd>Milliseconds to wait for a single packet. Beware that increasing this will cause many queries to take longer even if the server is online. Ignored if configured on the node.</dd>
<dt>
msg.attempt_timeout <span class="property-type">integer</span>
</dt>
<dd>Milliseconds allowed for an entire query attempt. This timeout is not commonly hit, as the socketTimeout typically fires first. Ignored if configured on the node.</dd>
</dl>
</script>
+113
View File
@@ -0,0 +1,113 @@
module.exports = function(RED) {
const gamedig = require('gamedig');
const fs = require('fs');
function QueryGameServer(config) {
RED.nodes.createNode(this, config);
var node = this;
this.server_type = config.server_type;
this.host = config.host;
this.port = config.port;
this.halt_if = config.halt_if;
this.max_attempts = config.max_attempts || 1;
this.socket_timeout = config.socket_timeout || 2000;
this.attempt_timeout = config.attempt_timeout || 10000;
node.on('input', function(msg) {
if(node.server_type) {
msg.server_type = node.server_type;
}
if(node.host) {
msg.host = node.host;
}
if(!msg.host) {
node.error("msg.host missing from input.");
return;
}
if(node.port) {
msg.port = node.port;
}
if(node.halt_if) {
msg.halt_if = node.halt_if;
}
if(node.max_attempts) {
msg.max_attempts = node.max_attempts;
}
if(node.socket_timeout) {
msg.socket_timeout = node.socket_timeout;
}
if(node.attempt_timeout) {
msg.attempt_timeout = node.attempt_timeout;
}
gamedig.query({
'type': msg.server_type,
'host': msg.host,
'port': msg.port,
'maxAttempts': msg.max_attempts,
'socketTimeout': msg.socket_timeout,
'attemptTimeout': msg.attempt_timeout
})
.then(function(state) {
msg.payload = 'online';
msg.data = state;
if (msg.payload === msg.halt_if) {
return null;
}
node.status({fill:"green",shape:"dot",text: 'Online ' + msg.data.players.length + ' players' });
node.send(msg);
}).catch(function(error) {
msg.payload = 'offline';
msg.data = {
'error': error
};
if (msg.payload === msg.halt_if) {
return null;
}
node.status({fill:"red", shape:"dot", text: 'Offline'});
node.send(msg);
});
});
}
RED.nodes.registerType("query-game-server", QueryGameServer);
RED.httpAdmin.get(
"/gamedig/types",
RED.auth.needsPermission('gamedig.types'),
function(req, res) {
// gamedig has no way of listing available server types
// so we just use regex to parse the info from the README
// this could break so we also reference the gamedig repo
let availableTypesContent = fs.readFileSync(require.resolve("gamedig/games.txt"), 'utf-8')
results = [];
availableTypesContent
.split(/\r?\n/)
.forEach(line => {
if(
line.trim().length === 0
|| line.trim().length === 0
|| line.trim().startsWith('#')
) {
return;
}
// examples:
// avp2|Aliens versus Predator 2 (2001)|gamespy1|port=27888
// avp2010|Aliens vs. Predator (2010)|valve|port=27015
let [game_type, game_name, game_protocol] = line.split('|');
results.push({
'name': game_type,
'type': game_type,
'protocol': game_protocol
});
});
res.json(results);
});
};
-47
View File
@@ -1,47 +0,0 @@
<script type="text/javascript">
RED.nodes.registerType('query-game-server', {
category: 'advanced',
color: '#a6bbcf',
defaults: {
name: { value: '' },
type: { value: '', required: true },
host: { value: '', type: 'server', required: true },
port: { value: '' },
halt_if: { value: '' }
},
inputs:1,
outputs:1,
icon: "icons/down_arrow.png",
label: function() {
return this.name || 'query-game-server' || `query-game-server: ${this.server}`;
}
});
</script>
<script type="text/x-red" data-template-name="query-game-server">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-row">
<label for="node-input-type"><i class="fa fa-cube"></i> Type</label>
<input type="text" id="node-input-type">
<span>Check <a href="https://github.com/sonicsnes/node-gamedig">node-gamedig</a> README for supported types</span>
</div>
<div class="form-row">
<label for="node-input-host"><i class="fa fa-server"></i> Host</label>
<input type="text" id="node-input-host" />
<span>Host without port</span>
</div>
<div class="form-row">
<label for="node-input-port"><i class="fa fa-server"></i> Port</label>
<input type="text" id="node-input-port" />
<span>Query port for the server (not always the same as the join port)</span>
</div>
<div class="form-row">
<label for="node-input-halt_if"><i class="fa fa-hand-paper-o"></i> Halt If</label>
<input type="text" id="node-input-halt_if" placeholder="off"/>
<span>Enter "online" or "offline" (without quotes) to filter out the state you don't want.</span>
</div>
</script>
-39
View File
@@ -1,39 +0,0 @@
module.exports = function(RED) {
var Gamedig = require('gamedig');
function queryGameServer(config) {
RED.nodes.createNode(this, config);
var node = this;
node.on('input', function(msg) {
var serverInfo = {
'type': this.nodeConfig.type,
'host': this.nodeConfig.host
};
if(this.nodeConfig.port) {
serverInfo['port'] = this.nodeConfig.port;
}
Gamedig.query(serverInfo)
.then(function(state) {
msg.payload = 'online';
msg.data = state;
const shouldHaltIfState = this.nodeConfig.halt_if && ('online' === this.nodeConfig.halt_if);
if (shouldHaltIfState) {
return null;
}
node.send(msg);
}).catch(function(error) {
msg.payload = 'offline';
msg.data = {
'error': error
};
const shouldHaltIfState = this.nodeConfig.halt_if && ('offline' === this.nodeConfig.halt_if);
if (shouldHaltIfState) {
return null;
}
node.send(msg);
});
});
}
RED.nodes.registerType("query-game-server", queryGameServer);
};