diff --git a/README.md b/README.md index 0ab5346..09d52c2 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ -# mc-server-watcher +A script that sends a Discord webhook whenever a server goes offline/online and when a player joins/leaves (works for up to ~5 players) + +Requires [MCStatus](https://github.com/reimarpb/mcstatus) to be installed + diff --git a/watch-server.js b/watch-server.js new file mode 100644 index 0000000..8977c2e --- /dev/null +++ b/watch-server.js @@ -0,0 +1,116 @@ +const { exec } = require("child_process"); +const https = require("https"); + +const SERVER = process.argv[2]; +const WEBHOOK_URL = process.env.WEBHOOK_URL; + +let oldServerStatus = { + online: false, + players: -1, + samplePlayers: [], +}; + +getServerStatus(SERVER); +setInterval(() => getServerStatus(SERVER), 10000); + +function getServerStatus(server) { + console.log(`Getting server status of ${server}`); + + return new Promise((resolve, reject) => { + exec("mcstatus -j " + server, async (error, stdout, stderr) => { + if (error) { + console.log(stderr); + if (oldServerStatus.online) { + sendMessage(":red_circle: The server is now offline"); + oldServerStatus = { + online: false, + players: -1, + samplePlayers: [], + }; + } + return resolve(); + } + + console.log(stdout); + + const json = JSON.parse(stdout); + + if (json.version.name.match(/Offline/)) { + if (oldServerStatus.online) { + sendMessage(":red_circle: The server is now offline"); + oldServerStatus = { + online: false, + players: -1, + samplePlayers: [], + }; + } + return resolve(); + } + + const match = json.description.text.match(new RegExp(`Connect to §a(${SERVER}:\\d+)§7§8`)); + if (match) { + resolve(await getServerStatus(match[1])); + return resolve(); + } + + if (!oldServerStatus.online) { + await sendMessage(":green_circle: The server is now online"); + } + + const samplePlayers = json.players.sample || []; + samplePlayers.forEach(player => { + if (!oldServerStatus.samplePlayers.map(p => p.id).includes(player.id)) { + sendMessage(`**${player.name}** joined the server`); + } + }); + + oldServerStatus.samplePlayers.forEach(player => { + if (!samplePlayers.map(p => p.id).includes(player.id)) { + sendMessage(`**${player.name}** left the server`); + } + }); + + /*if (oldServerStatus.players != json.players.online) { + sendMessage(`There are now **${json.players.online}** players online`); + }*/ + + oldServerStatus = { + online: true, + players: json.players.online, + samplePlayers, + }; + }); + }); +} + +function sendMessage(text) { + console.log(text); + + return new Promise((resolve, reject) => { + const data = JSON.stringify({ + content: text, + }); + + const options = { + method: "POST", + headers: { + "Accept": "application/json", + "Content-Type": "application/json", + "Content-Length": data.length, + } + }; + const req = https.request(WEBHOOK_URL, options, (res) => { + + let data = ""; + res.on("data", chunk => data += chunk); + res.on("end", () => { + console.log(res.statusCode); + resolve(); + }); + + }); + req.write(data); + req.end(); + }); +} +