diff --git a/commands.json b/commands.json new file mode 100644 index 0000000..87bb4cd --- /dev/null +++ b/commands.json @@ -0,0 +1,8 @@ +[ + { + "name": "send", + "description": "Send a message with it's ID for the config file!", + "type": 1, + "default_member_permissions": 0 + } +] \ No newline at end of file diff --git a/config.json.default b/config.json.default index e69de29..006ff1b 100644 --- a/config.json.default +++ b/config.json.default @@ -0,0 +1,16 @@ +{ + "discord": { + "token": "" + }, + "stormworks": { + "lowTPS": 45, + "servers": [ + { + "ip": "127.0.0.1", + "port": 25565, + "messageId": "1234567890123456789", + "channelId": "9876543210987654321" + } + ] + } +} \ No newline at end of file diff --git a/index.js b/index.js index e69de29..c4a2f41 100644 --- a/index.js +++ b/index.js @@ -0,0 +1,330 @@ +const config = require('./config.json'); +const colors = require('colors'); +const Discord = require('discord.js'); +const rest = new Discord.REST({ + version: '10' +}).setToken(config.discord.token); +const client = new Discord.Client({ + intents: ["Guilds", "GuildWebhooks"] +}); +const steam = require('steam-server-query'); + +function splitKeyword(keyword) { + data = keyword.split("-") + switch (data[1]) { + case "0": + dlcString = "None", + dlcEmoji = ":x:" + break; + case "1": + dlcString = "Weapons", + dlcEmoji = ":gun:" + break; + case "2": + dlcString = "Arid", + dlcEmoji = ":desert:" + break; + case "3": + dlcString = "Both", + dlcEmoji = ":gun::desert:" + break; + default: + break; + } + if (data[0] >= "v1.3.0") { + return { + "version": data[0], + dlcString, + dlcEmoji, + dlc: data[1], + "tps": data[2] + } + } else { // For older versions + console.log(`${colors.magenta(`[DEBUG ${new Date()}]`)} Absolutely ancient server found, ${data}`); + return { + "version": data[0], + "tps": data[1] + } + } +}; + +// checkServer function as a promise +function checkServer(address) { + return new Promise((resolve, reject) => { + steam.queryGameServerInfo(address).then(data => { + data.keywords.split("-") + data.address = address.split(":"); + data.serverInfo = splitKeyword(data.keywords); + output = { + "status": true, + "name": data.name, + "address": data.address[0], + "port": data.address[1], + "password": data.visibility == 1 ? true : false, + "version": data.serverInfo.version, + "dlc": data.serverInfo.dlc, + "dlcString": data.serverInfo.dlcString, + "dlcEmotes": data.serverInfo.dlcEmoji, + "tps": data.serverInfo.tps, + "players": data.bots, + "maxPlayers": data.maxPlayers, + "map": data.map, + "gameId": data.gameId, + "lastUpdated": new Date() + } + resolve(output); + }).catch((err) => { + output = { + "status": false, + "error": "Could not connect to server", + "name": "Unknown", + "address": address.split(":")[0], + "port": address.split(":")[1], + "version": "Unknown", + "dlc": null, + "dlcString": "Unknown", + "tps": 0, + "players": 0, + "maxPlayers": 0, + "map": "Unknown", + "gameId": "573090" + } + resolve(output); + }); + }); +} + + +function updateStatus(addr, port, msg) { + if (!serverEmbeds[`${addr}:${port}`]) { + serverEmbeds[`${addr}:${port}`] = { + "title": "Unknown", + "fields": [{ + "name": "Status", + "value": `<:lowtps:1108862303618728108>: \`Unknown\``, + "inline": true + }, + { + "name": "Version", + "value": `?`, + "inline": true + }, + { + "name": "DLC", + "value": `?`, + "inline": true + }, + { + "name": "TPS", + "value": `?`, + "inline": true + }, + { + "name": "Players", + "value": `?/?`, + "inline": true + } + ], + "color": 0x00ffff, + "footer": { + "text": `Last Updated` + }, + "timestamp": new Date() + }; + } + if(!serverStatus[`${addr}:${port}`]) { + serverStatus[`${addr}:${port}`] = { + "status": false, + "error": "Could not connect to server", + "name": "Unknown", + "address": addr, + "port": port, + "version": "Unknown", + "dlc": null, + "dlcString": "Unknown", + "tps": 0, + "players": 0, + "maxPlayers": 0, + "map": "Unknown", + "gameId": "573090" + } + } + checkServer(`${addr}:${port}`).then((data) => { + if (data.status) { + serverStatus[`${addr}:${port}`] = data; + embed = { + "title": data.name, + "fields": [{ + "name": "Status", + "value": `${data.tps <= config.stormworks.lowTPS ? "<:lowtps:1108862303618728108>: `TPS Low`" : "<:online:1108862127021756457> `Online`"}`, + "inline": true + }, + { + "name": "Version", + "value": `${data.version}`, + "inline": true + }, + { + "name": "DLC", + "value": `${data.dlcEmotes} ${data.dlcString}`, + "inline": true + }, + { + "name": "TPS", + "value": `${data.tps}`, + "inline": true + }, + { + "name": "Players", + "value": `${data.players}/${data.maxPlayers}`, + "inline": true + } + ], + "color": data.tps <= config.stormworks.lowTPS ? 0xfff000 : 0x00ff00, + "footer": { + "text": `Last Updated` + }, + "timestamp": new Date() + }; + serverEmbeds[`${addr}:${port}`] = embed; + msg.edit({ + embeds: [embed] + }).catch((err) => { + console.log(err) + }); + } else { + // Server is offline, modify embed slightly and edit it + data2 = serverStatus[`${addr}:${port}`]; + embed = { + "title": data2.name, + "fields": [{ + "name": "Status", + "value": `<:offline:1108862189793726485> \`Offline\``, + "inline": true + }, + { + "name": "Version", + "value": `${data2.version}`, + "inline": true + }, + { + "name": "DLC", + "value": `${data2.dlcEmotes} ${data2.dlcString}`, + "inline": true + }, + { + "name": "TPS", + "value": `0`, + "inline": true + }, + { + "name": "Players", + "value": `0/${data2.maxPlayers}`, + "inline": true + } + ], + "color": 0xff0000, + "footer": { + "text": `Last Updated` + }, + "timestamp": new Date() + }; + serverEmbeds[`${addr}:${port}`] = embed; + msg.edit({ + "embeds": [serverEmbeds[`${addr}:${port}`]] + }); + } + }) +} + + + +client.on("ready", async () => { + console.log(`${colors.cyan("[INFO]")} Logged in as ${colors.green(client.user.tag)}`) + // Load Commands + console.log(`${colors.cyan("[INFO]")} Loading Commands...`) + const commands = require('./commands.json'); + await (async () => { + try { + console.log(`${colors.cyan("[INFO]")} Registering Commands...`) + let start = Date.now() + // For every guild + for (const guild of client.guilds.cache.values()) { + let gStart = Date.now(); + console.log(`${colors.cyan("[INFO]")} Registering Commands for ${colors.green(guild.name)}...`); + // Register commands + await rest.put( + Discord.Routes.applicationGuildCommands(client.user.id, guild.id), { + body: commands + }, + ); + console.log(`${colors.cyan("[INFO]")} Successfully registered commands for ${colors.green(guild.name)}. Took ${colors.green((Date.now() - gStart) / 1000)} seconds.`); + }; + console.log(`${colors.cyan("[INFO]")} Successfully registered commands. Took ${colors.green((Date.now() - start) / 1000)} seconds.`); + } catch (error) { + console.error(error); + } + })(); + + // Log startup time in seconds + console.log(`${colors.cyan("[INFO]")} Startup took ${colors.green((Date.now() - initTime) / 1000)} seconds.`) + + config.stormworks.servers.forEach((server) => { + client.channels.fetch(server.channelId).then((channel) => { + channel.messages.fetch(server.messageId).then((message) => { + updateStatus(server.ip, server.port, message); + setInterval(() => { + updateStatus(server.ip, server.port, message); + }, 5000); + }); + }); + }); + // client.channels.fetch("1108126926045986856").then((channel) => { + // channel.messages.fetch("1108860190935232592").then((message) => { + // message.edit("UwU") + // }) + // }) +}); + +client.on('interactionCreate', async interaction => { + if (!interaction.isCommand()) return; + switch (interaction.commandName) { + case "send": // Send a message with it's message ID + interaction.channel.send({ + embeds: [{ + description: "Please Wait" + }] + }).then(async (msg) => { + await msg.edit({ + embeds: [{ + description: `ID: ${msg.id}` + }] + }); + interaction.reply({ + "ephemeral": true, + content: "Done!" + }) + }); + break; + } +}); + +process.on('SIGINT', async () => { + await console.log(`${colors.cyan("[INFO]")} Stop received, exiting...`); + await client.user.setPresence({ + status: "invisible", + activities: [] + }); + await client.destroy(); + await console.log(`${colors.cyan("[INFO]")} Goodbye!`); + process.exit(0); +}); + +var serverEmbeds = {}; +var serverStatus = {}; + +console.log(`${colors.cyan("[INFO]")} Starting...`) +// Start timer to see how long startup takes +const initTime = Date.now(); +// Login to Discord +client.login(config.discord.token); \ No newline at end of file