diff --git a/.gitignore b/.gitignore index 800c73f16..96231e386 100644 --- a/.gitignore +++ b/.gitignore @@ -3,9 +3,16 @@ Panel/node_modules Panel/package-lock.json Panel/data +Panel/config.json +Panel/json.sqlite +Panel/images +Panel/start.bat +Panel/eng.traineddata +Panel/proxy Daemon/node_modules Daemon/package-lock.json -BetaDaemon/node_modules -BetaDaemon/package-lock.json +Test/* + +OutageBot/* \ No newline at end of file diff --git a/BetaDaemon/config.json b/BetaDaemon/config.json deleted file mode 100644 index 558849ed3..000000000 --- a/BetaDaemon/config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "panelip": "192.168.0.3", - "panelport": "80", - "debug": true, - "panelping": true, - "panelms": 5000, - - "Discord": false, - "DiscordWebhook": "HOE", - - "SystemIPs": [ - "192.168.1.175", - "173.249.33.82" - ], - - "Docker": false -} \ No newline at end of file diff --git a/BetaDaemon/index.js b/BetaDaemon/index.js deleted file mode 100644 index 22fdf7a66..000000000 --- a/BetaDaemon/index.js +++ /dev/null @@ -1,371 +0,0 @@ -/* _____ __ __ _ _ - / ____| | \/ | (_)| | - | (___ ___ _ __ __ __ ___ _ __ | \ / | ___ _ __ _ | |_ ___ _ __ - \___ \ / _ \| '__|\ \ / // _ \| '__|| |\/| | / _ \ | '_ \ | || __|/ _ \ | '__| - ____) || __/| | \ V /| __/| | | | | || (_) || | | || || |_| (_) || | - |_____/ \___||_| \_/ \___||_| |_| |_| \___/ |_| |_||_| \__|\___/ |_| - Free Monitoring software made by danielpmc -*/ - -var PORT = 2001; -var app = require('express')(); -var server = require('http').createServer(app); -var request = require("request"); -var si = require('systeminformation'); -var os = require("os"); -var pretty = require('prettysize'); -var ping = require('node-http-ping'); -var package = require("./package.json"); -var config = require("./config.json"); -var { get } = require('superagent') -var chalk = require('chalk'); -var moment = require("moment"); - -server.listen(PORT, function () { - console.log(chalk.blueBright("The servers hostname is: " + chalk.green(os.hostname) + ", Please put this in the config file")) - console.log(PORT + " listening..."); - ping('0.0.0.0', 2001) - - //Config file checking - if (config.panelip == "Your panel ip here") { - //Log that the ip has not been set and process will exit. - console.log(chalk.red("Your panel ip has not been set in config.json. Please set the panel ip.")) - process.exit(); - } else { - //Panel ip has been set. Ping the panel and see if its alive. - ping(config.panelip, config.panelport) - .then(time => console.log(chalk.green(`Panel is online! Response time: ${time}ms`))) - .catch(() => console.log(chalk.red(`Failed to ping the panel. Please check if the panel is running!`)) + process.exit()) - } -}); - -if (config.panelping == true) { - //User requested to ping the panel every x ms - setInterval(async () => { - var timestamp = `${moment().format("YYYY-MM-DD HH:mm:ss")}`; - ping(config.panelip, config.panelport) - .then(time => console.log(chalk.white(`[${timestamp}] Panel Pinger: ` + chalk.green(`Response time: ${time}ms`)))) - .catch(() => console.log(chalk.white(`[${timestamp}] Panel Pinger: ` + chalk.red(`Failed to ping the panel. Please check if the panel is running! `) + chalk.white("Will continue to ping panel.")))) - }, config.panelms) -} - - -app.get('/', async function (req, res) { - - setInterval(async () => { - //Data using the systeminformation package. - var memdata = await si.mem(); - var ramused = pretty(memdata.used); - var ramtotal = pretty(memdata.total); - var swapused = pretty(memdata.swapused); - var swaptotal = pretty(memdata.swaptotal); - var diskdata = await si.fsSize(); - var diskused = pretty(diskdata[0].used); - var disktotal = pretty(diskdata[0].size); - var netdata = await si.networkStats(); - var netrx = pretty(netdata[0].rx_bytes); - var nettx = pretty(netdata[0].tx_bytes); - var osdata = await si.osInfo(); - var bios = await si.bios(); - var docker = await si.dockerInfo(); - - //CPU data. - var cl = await si.currentLoad(); - var cpudata = await si.cpu(); - var cputhreads = cpudata.cores; - var cpucores = cpudata.physicalCores; - var cpumain = os.cpus().length > 0 ? os.cpus()[0].model : 'Uh oh. You dont have a cpu?'; - - //OS UPTIME - var uptime = os.uptime(); - var d = Math.floor(uptime / (3600*24)); - var h = Math.floor(uptime % (3600*24) / 3600); - var m = Math.floor(uptime % 3600 / 60); - var s = Math.floor(uptime % 60); - var dDisplay = d > 0 ? d + (d == 1 ? " day, " : " days, ") : ""; - var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : ""; - var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : ""; - var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : ""; - - //Version - var Version = package.version; - - //Fetch time that data was sent. (Used panel sided to check if server has gone offline) - var datatime = Date.now(); - - //Different errors - function discordchecker() { - if (config.Discord == true) { - if (config.DiscordWebhook == " ") { - console.log(chalk.red("Error: Discord webhooks are enabled but no url is valid. Please enter a valid url or go into the config file and change `Discord: true` to `Discord: false`")); - } else { - //Discord is enabled and webhook has a input. Check for discord webhook link. - var WebhookURL = ["https://discordapp.com/api/webhooks/", "https://canary.discordapp.com/api/webhooks/"] - if (WebhookURL.some(link => config.DiscordWebhook.includes(link))) { - //Webhook config has discord link. Check if link is valid. - get(config.DiscordWebhook).end((response) => { - console.log("Valid link") - - if (response.body.type == "1") { - console.log(chalk.green("Url valid")) - } else { - console.log(chalk.red("URL invalid.")) - } - }) - - } else { - //Post in console that there is no valid discord link. - console.log(chalk.red("Error: Discord webhooks are enabled but the text entered in the config is not a valid discord link.")); - } - } - } - } - - //Find system OS if windows and else linux (No MacOS support yet, Sorry Apple fans) - if (osdata.platform == "win32") { - discordchecker(); - if (config.Docker == true) { - if (docker.containers == "undefined") { - //Docker enabled but no docker found. - console.log(chalk.red("You enabled docker in the config but your system does not have docker installed. Please disable this!")); - process.exit(); - } else { - request({ - uri: "http://" + config.panelip + ":" + config.panelport + "/data?servername=" + os.hostname + //OS hostname for saving data panel sided. - "&cpu=" + cpumain + //CPU make and brand. - "&cpuload=" + cl.currentload.toFixed(2) + //CPU load but doesn't work on windows :( - "&cputhreads=" + cputhreads + //CPU threads. - "&cpucores=" + cpucores + //CPU cores - "&memused=" + ramused + //Ram used (Auto to MB, GB, TB) - "&memtotal=" + ramtotal + //Ram total (Auto to MB, GB, TB) - "&swapused=" + swapused + //Swap used (Auto to MB, GB, TB) - "&swaptotal=" + swaptotal + //Swap total (Auto to MB, GB, TB) - "&diskused=" + diskused + //Disk used (Auto to MB, GB, TB) - "&disktotal=" + disktotal + //Disk total (Auto to MB, GB, TB) - "&netrx=" + netrx + //Network received (Auto to MB, GB, TB) - "&nettx=" + nettx + //Network transmited (Auto to MB, GB, TB) - "&osplatform=" + osdata.platform + //OS platform (win32 or linux) - "&oslogofile=" + osdata.logofile + //OS logofile (Linux example: Debian/Ubuntu | Windows example: Windows) - "&osrelease=" + osdata.release + //OS release (Linux example: 9 | Windows example: 10.0.18362) - "&osuptime=" + dDisplay + hDisplay + mDisplay + sDisplay + //OS uptime (Day/Days, Hours/Hour, Minutes/Minute, Seconds/Second) - "&biosvendor=" + bios.vendor + //Bios vendor (Example: Dell Inc) - "&biosversion=" + bios.version + //Bios version (Example: A22.00) - "&biosdate=" + bios.releaseDate + //Bios release date (Example: 2018-11-29) - "&servermonitorversion=" + Version + //ServerMonitor version (Example: 1.0.1) - "&datatime=" + datatime + //Date and time (Example: 1578594094569) - "&dockercontainers=" + docker.containers + //Number of docker containers - "&dockercontainersrunning=" + docker.containersRunning + //Number of running docker containers - "&dockercontainerspaused=" + docker.containersPaused + //Number of paused docker containers - "&dockercontainersstopped=" + docker.containersStopped, //Number of stopped docker containers - method: "GET", - timeout: 5000, - followRedirect: true, - maxRedirects: 10 - }, function (error, response, body) { - - //Send data to panel - res.send(body); - - //Error checking. - if (error == "undefined") { - //No errors = Do nothing :D - } else if (error == "Error: ESOCKETTIMEDOUT") { - //Because Panel doesn't give response to Daemon it thinks it timed out. - //But really it didn't data was still sent. - //So ignore this error. - } else if (error == "Error: read ECONNRESET") { - //Do nothing because panel went down. Program will still continue to try and send data. - //So ignore this error. - } else if (error == "Error: connect ECONNREFUSED " + config.panelip + ":" + config.panelport) { - //Do nothing because panel went down. Program will still continue to try and send data. - //So ignore this error. - }else { - //Log the error in red and exit process - console.log(chalk.red("ERROR! " + error)) - process.exit(); - } - - }); - } - } else { - request({ - uri: "http://" + config.panelip + ":" + config.panelport + "/data?servername=" + os.hostname + //OS hostname for saving data panel sided. - "&cpu=" + cpumain + //CPU make and brand. - "&cpuload=" + cl.currentload.toFixed(2) + //CPU load but doesn't work on windows :( - "&cputhreads=" + cputhreads + //CPU threads. - "&cpucores=" + cpucores + //CPU cores - "&memused=" + ramused + //Ram used (Auto to MB, GB, TB) - "&memtotal=" + ramtotal + //Ram total (Auto to MB, GB, TB) - "&swapused=" + swapused + //Swap used (Auto to MB, GB, TB) - "&swaptotal=" + swaptotal + //Swap total (Auto to MB, GB, TB) - "&diskused=" + diskused + //Disk used (Auto to MB, GB, TB) - "&disktotal=" + disktotal + //Disk total (Auto to MB, GB, TB) - "&netrx=" + netrx + //Network received (Auto to MB, GB, TB) - "&nettx=" + nettx + //Network transmited (Auto to MB, GB, TB) - "&osplatform=" + osdata.platform + //OS platform (win32 or linux) - "&oslogofile=" + osdata.logofile + //OS logofile (Linux example: Debian/Ubuntu | Windows example: Windows) - "&osrelease=" + osdata.release + //OS release (Linux example: 9 | Windows example: 10.0.18362) - "&osuptime=" + dDisplay + hDisplay + mDisplay + sDisplay + //OS uptime (Day/Days, Hours/Hour, Minutes/Minute, Seconds/Second) - "&biosvendor=" + bios.vendor + //Bios vendor (Example: Dell Inc) - "&biosversion=" + bios.version + //Bios version (Example: A22.00) - "&biosdate=" + bios.releaseDate + //Bios release date (Example: 2018-11-29) - "&servermonitorversion=" + Version + //ServerMonitor version (Example: 1.0.1) - "&datatime=" + datatime, //Date and time (Example: 1578594094569) - method: "GET", - timeout: 5000, - followRedirect: true, - maxRedirects: 10 - }, function (error, response, body) { - - //Send data to panel - res.send(body); - - //Error checking. - if (error == "undefined") { - //No errors = Do nothing :D - } else if (error == "Error: ESOCKETTIMEDOUT") { - //Because Panel doesn't give response to Daemon it thinks it timed out. - //But really it didn't data was still sent. - //So ignore this error. - } else if (error == "Error: read ECONNRESET") { - //Do nothing because panel went down. Program will still continue to try and send data. - //So ignore this error. - } else if (error == "Error: connect ECONNREFUSED " + config.panelip + ":" + config.panelport) { - //Do nothing because panel went down. Program will still continue to try and send data. - //So ignore this error. - }else { - //Log the error in red and exit process - console.log(chalk.red("ERROR! " + error)) - process.exit(); - } - - }); - } - } else if (osdata.platform == "linux") { - discordchecker(); - if (config.Docker == true) { - if (docker.containers == "undefined") { - //Docker enabled but no docker found. - console.log(chalk.red("You enabled docker in the config but your system does not have docker installed. Please disable this!")); - process.exit(); - } else { - request({ - uri: "http://" + config.panelip + ":" + config.panelport + "/data?servername=" + os.hostname + //OS hostname for saving data panel sided. - "&cpu=" + cpudata.manufacturer + " " + cpudata.brand + //CPU make and brand. - "&cpuload=" + cl.currentload.toFixed(2) + //CPU load but doesn't work on windows :( - "&cputhreads=" + cputhreads + //CPU threads. - "&cpucores=" + cpucores + //CPU cores - "&memused=" + ramused + //Ram used (Auto to MB, GB, TB) - "&memtotal=" + ramtotal + //Ram total (Auto to MB, GB, TB) - "&swapused=" + swapused + //Swap used (Auto to MB, GB, TB) - "&swaptotal=" + swaptotal + //Swap total (Auto to MB, GB, TB) - "&diskused=" + diskused + //Disk used (Auto to MB, GB, TB) - "&disktotal=" + disktotal + //Disk total (Auto to MB, GB, TB) - "&netrx=" + netrx + //Network received (Auto to MB, GB, TB) - "&nettx=" + nettx + //Network transmited (Auto to MB, GB, TB) - "&osplatform=" + osdata.platform + //OS platform (win32 or linux) - "&oslogofile=" + osdata.logofile + //OS logofile (Linux example: Debian/Ubuntu | Windows example: Windows) - "&osrelease=" + osdata.release + //OS release (Linux example: 9 | Windows example: 10.0.18362) - "&osuptime=" + dDisplay + hDisplay + mDisplay + sDisplay + //OS uptime (Day/Days, Hours/Hour, Minutes/Minute, Seconds/Second) - "&biosvendor=" + bios.vendor + //Bios vendor (Example: Dell Inc) - "&biosversion=" + bios.version + //Bios version (Example: A22.00) - "&biosdate=" + bios.releaseDate + //Bios release date (Example: 2018-11-29) - "&servermonitorversion=" + Version + //ServerMonitor version (Example: 1.0.1) - "&datatime=" + datatime + //Date and time (Example: 1578594094569) - "&dockercontainers=" + docker.containers + //Number of docker containers - "&dockercontainersrunning=" + docker.containersRunning + //Number of running docker containers - "&dockercontainerspaused=" + docker.containersPaused + //Number of paused docker containers - "&dockercontainersstopped=" + docker.containersStopped, //Number of stopped docker containers - method: "GET", - timeout: 5000, - followRedirect: true, - maxRedirects: 10 - }, function (error, response, body) { - - //Send data to panel - res.send(body); - - //Error checking. - if (error == "undefined") { - //No errors = Do nothing :D - } else if (error == "Error: ESOCKETTIMEDOUT") { - //Because Panel doesn't give response to Daemon it thinks it timed out. - //But really it didn't data was still sent. - //So ignore this error. - } else if (error == "Error: read ECONNRESET") { - //Do nothing because panel went down. Program will still continue to try and send data. - //So ignore this error. - } else if (error == "Error: ETIMEDOUT") { - //Do nothing because panel went down. Program will still continue to try and send data. - //So ignore this error. - }else { - //Log the error in red and exit process - console.log(chalk.red("ERROR! " + error)) - process.exit(); - } - - }); - } - } else { - request({ - uri: "http://" + config.panelip + ":" + config.panelport + "/data?servername=" + os.hostname + //OS hostname for saving data panel sided. - "&cpu=" + cpudata.manufacturer + " " + cpudata.brand + //CPU make and brand. - "&cpuload=" + cl.currentload.toFixed(2) + //CPU load but doesn't work on windows :( - "&cputhreads=" + cputhreads + //CPU threads. - "&cpucores=" + cpucores + //CPU cores - "&memused=" + ramused + //Ram used (Auto to MB, GB, TB) - "&memtotal=" + ramtotal + //Ram total (Auto to MB, GB, TB) - "&swapused=" + swapused + //Swap used (Auto to MB, GB, TB) - "&swaptotal=" + swaptotal + //Swap total (Auto to MB, GB, TB) - "&diskused=" + diskused + //Disk used (Auto to MB, GB, TB) - "&disktotal=" + disktotal + //Disk total (Auto to MB, GB, TB) - "&netrx=" + netrx + //Network received (Auto to MB, GB, TB) - "&nettx=" + nettx + //Network transmited (Auto to MB, GB, TB) - "&osplatform=" + osdata.platform + //OS platform (win32 or linux) - "&oslogofile=" + osdata.logofile + //OS logofile (Linux example: Debian/Ubuntu | Windows example: Windows) - "&osrelease=" + osdata.release + //OS release (Linux example: 9 | Windows example: 10.0.18362) - "&osuptime=" + dDisplay + hDisplay + mDisplay + sDisplay + //OS uptime (Day/Days, Hours/Hour, Minutes/Minute, Seconds/Second) - "&biosvendor=" + bios.vendor + //Bios vendor (Example: Dell Inc) - "&biosversion=" + bios.version + //Bios version (Example: A22.00) - "&biosdate=" + bios.releaseDate + //Bios release date (Example: 2018-11-29) - "&servermonitorversion=" + Version + //ServerMonitor version (Example: 1.0.1) - "&datatime=" + datatime, //Date and time (Example: 1578594094569) - method: "GET", - timeout: 5000, - followRedirect: true, - maxRedirects: 10 - }, function (error, response, body) { - - //Send data to panel - res.send(body); - - //Error checking. - if (error == "undefined") { - //No errors = Do nothing :D - } else if (error == "Error: ESOCKETTIMEDOUT") { - //Because Panel doesn't give response to Daemon it thinks it timed out. - //But really it didn't data was still sent. - //So ignore this error. - } else if (error == "Error: read ECONNRESET") { - //Do nothing because panel went down. Program will still continue to try and send data. - //So ignore this error. - } else if (error == "Error: ETIMEDOUT") { - //Do nothing because panel went down. Program will still continue to try and send data. - //So ignore this error. - }else { - //Log the error in red and exit process - console.log(chalk.red("ERROR! " + error)) - process.exit(); - } - - }); - } - - } else { - console.log("Your running a unsupported OS. :(") - process.exit(); - } - -}, 2500); - -}); diff --git a/BetaDaemon/package.json b/BetaDaemon/package.json deleted file mode 100644 index 1cc5417c8..000000000 --- a/BetaDaemon/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "servermonitor-fetch", - "version": "1.0.1", - "description": "A program that runs in system background to fetch data for the main ServerMonitor program.", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "danielpmc", - "license": "MIT", - "dependencies": { - "body-parser": "latest", - "chalk": "^3.0.0", - "express": "latest", - "http": "latest", - "moment": "^2.24.0", - "node-http-ping": "^0.3.1", - "prettysize": "^2.0.0", - "request": "^2.88.0", - "socket.io": "latest", - "superagent": "^5.2.1", - "systeminformation": "^4.16.0" - } -} diff --git a/Daemon/config.json b/Daemon/config.json index 24dfb7d15..36602c17f 100644 --- a/Daemon/config.json +++ b/Daemon/config.json @@ -1,4 +1,14 @@ { - "panelip": "173.249.33.82", - "panelport": "70" + "panelip": "danbot.host", + "panelport": "80", + "debug": true, + "panelping": true, + "panelms": 5000, + + "daemonport": "2001", + + "Discord": false, + "DiscordWebhook": "No webhook token", + + "Docker": false } \ No newline at end of file diff --git a/Daemon/index.js b/Daemon/index.js index 978fd7c60..dee2942e9 100644 --- a/Daemon/index.js +++ b/Daemon/index.js @@ -1,82 +1,171 @@ -/* _____ __ __ _ _ - / ____| | \/ | (_)| | - | (___ ___ _ __ __ __ ___ _ __ | \ / | ___ _ __ _ | |_ ___ _ __ - \___ \ / _ \| '__|\ \ / // _ \| '__|| |\/| | / _ \ | '_ \ | || __|/ _ \ | '__| - ____) || __/| | \ V /| __/| | | | | || (_) || | | || || |_| (_) || | - |_____/ \___||_| \_/ \___||_| |_| |_| \___/ |_| |_||_| \__|\___/ |_| - Free Monitoring software made by danielpmc -*/ - -var PORT = 2001; -var app = require('express')(); -var server = require('http').createServer(app); -var request = require("request"); -var si = require('systeminformation'); -var os = require("os"); -var pretty = require('prettysize'); -var ping = require('node-http-ping'); -var package = require("./package.json"); -var config = require("./config.json"); - -server.listen(PORT, function () { - console.log(PORT + " listening..."); - ping('0.0.0.0', 2001) - -}); - -app.get('/', async function (req, res) { - - setInterval(async () => { - //Data using the systeminformation package. - var cpudata = await si.cpu(); - var cpu = os.loadavg(); - var memdata = await si.mem(); - var ramused = pretty(memdata.used); - var ramtotal = pretty(memdata.total); - var diskdata = await si.fsSize(); - var diskused = pretty(diskdata[0].used); - var disktotal = pretty(diskdata[0].size); - var netdata = await si.networkStats(); - var netrx = pretty(netdata[0].rx_bytes); - var nettx = pretty(netdata[0].tx_bytes); - var osdata = await si.osInfo(); - var bios = await si.bios(); - var ipadd = await si.networkInterfaces(); - var ip = ipadd.ip4 - - //OS UPTIME - var uptime = os.uptime(); - var d = Math.floor(uptime / (3600*24)); - var h = Math.floor(uptime % (3600*24) / 3600); - var m = Math.floor(uptime % 3600 / 60); - var s = Math.floor(uptime % 60); - var dDisplay = d > 0 ? d + (d == 1 ? " day, " : " days, ") : ""; - var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : ""; - var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : ""; - var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : ""; - - //Version - var Version = package.version; - - //Fetch time that data was sent. (Used panel sided to check if server has gone offline) - var datatime = Date.now(); - -console.log(cpudata) - - console.log(cpudata.brand) - //console.log("http://" + config.panelip + ":" + config.panelport + "/data?servername=" + os.hostname + "&cpuman= " + cpudata.manufacturer + "&cpubrand= " + cpudata.brand + "&cpuload= " + Math.ceil(cpu[1] * 100) / 10 + "&cpuspeed=" + cpudata.speed + "GHz" + "&memused=" + ramused + "&memtotal=" + ramtotal + "&diskused=" + diskused + "&disktotal=" + disktotal + "&netrx=" + netrx + "&nettx=" + nettx + "&osplatform=" + osdata.platform + "&oslogofile=" + osdata.logofile + "&osrelease=" + osdata.release + "&osuptime=" + dDisplay + hDisplay + mDisplay + sDisplay + "&biosvendor=" + bios.vendor + "&biosversion=" + bios.version + "&biosdate=" + bios.releaseDate + "&servermonitorversion=" + Version + "&datatime=" + datatime) - request({ - uri: "http://" + config.panelip + ":" + config.panelport + "/data?servername=" + os.hostname + "&cpuman=" + cpudata.manufacturer + "&cpuload=" + Math.ceil(cpu[1] * 100) / 10 + "&cpuspeed=" + cpudata.speed + "GHz" + "&memused=" + ramused + "&memtotal=" + ramtotal + "&diskused=" + diskused + "&disktotal=" + disktotal + "&netrx=" + netrx + "&nettx=" + nettx + "&osplatform=" + osdata.platform + "&oslogofile=" + osdata.logofile + "&osrelease=" + osdata.release + "&osuptime=" + dDisplay + hDisplay + mDisplay + sDisplay + "&biosvendor=" + bios.vendor + "&biosversion=" + bios.version + "&biosdate=" + bios.releaseDate + "&servermonitorversion=" + Version + "&datatime=" + datatime, - method: "GET", - timeout: 10000, - followRedirect: true, - maxRedirects: 10 - }, function (error, response, body) { - res.send(body); - console.log(body) - console.log(response) - console.log(error) - }); -}, 2500); - -}); +/* + ____ ____ __ __ __ __ _ + / __ \____ _____ / __ )____ / /_ / / / /___ _____/ /_(_)___ ____ _ + / / / / __ `/ __ \/ __ / __ \/ __/ / /_/ / __ \/ ___/ __/ / __ \/ __ `/ + / /_/ / /_/ / / / / /_/ / /_/ / /_ / __ / /_/ (__ ) /_/ / / / / /_/ / +/_____/\__,_/_/ /_/_____/\____/\__/ /_/ /_/\____/____/\__/_/_/ /_/\__, / +Free Hosting for ever! /____/ +*/ + +var si = require('systeminformation'); +var os = require("os"); +var pretty = require('prettysize'); +var chalk = require('chalk'); +var moment = require("moment"); +var request = require("request"); +var config = require("./config.json"); +const speedTest = require('speedtest-net'); + +//Issue speedtest on startup +speedtest(); +data(); + +//Speedtest every 3hours, Then send that data to the panel to store. +setInterval(async () => { + speedtest() +}, 10800000); + +//Send data to the panel every 2seconds +setInterval(async () => { + data() +}, 2000) + +async function data() { + + //Data using the systeminformation package. + var memdata = await si.mem(); + var ramused = pretty(memdata.active); + var ramtotal = pretty(memdata.total); + var swapused = pretty(memdata.swapused); + var swaptotal = pretty(memdata.swaptotal); + var diskdata = await si.fsSize(); + var diskused = pretty(diskdata[0].used); + var disktotal = pretty(diskdata[0].size); + var netdata = await si.networkStats(); + var netrx = pretty(netdata[0].rx_bytes); + var nettx = pretty(netdata[0].tx_bytes); + var osdata = await si.osInfo(); + var bios = await si.bios(); + var docker = await si.dockerInfo(); + + //CPU data. + var cl = await si.currentLoad(); + var cpudata = await si.cpu(); + var cputhreads = cpudata.cores; + var cpucores = cpudata.physicalCores; + var cpumain = os.cpus().length > 0 ? os.cpus()[0].model : 'Uh oh. You dont have a cpu?'; + + //OS UPTIME + var uptime = os.uptime(); + var d = Math.floor(uptime / (3600*24)); + var h = Math.floor(uptime % (3600*24) / 3600); + var m = Math.floor(uptime % 3600 / 60); + var s = Math.floor(uptime % 60); + var dDisplay = d > 0 ? d + (d == 1 ? " day, " : " days, ") : ""; + var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : ""; + var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : ""; + var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : ""; + + //Version + var Version = "1.0.0"; + + //Fetch time that data was sent. (Used panel sided to check if server has gone offline) + var datatime = Date.now(); + + var timestamp = `${moment().format("YYYY-MM-DD HH:mm:ss")}`; + request({ + uri: "http://" + config.panelip + ":" + config.panelport + "/data?servername=" + os.hostname + //OS hostname for saving data panel sided. + "&cpu=" + cpudata.manufacturer + " " + cpudata.brand + //CPU make and brand. + "&cpuload=" + cl.currentload.toFixed(2) + //CPU load but doesn't work on windows :( + "&cputhreads=" + cputhreads + //CPU threads. + "&cpucores=" + cpucores + //CPU cores + "&memused=" + ramused + //Ram used (Auto to MB, GB, TB) + "&memtotal=" + ramtotal + //Ram total (Auto to MB, GB, TB) + "&swapused=" + swapused + //Swap used (Auto to MB, GB, TB) + "&swaptotal=" + swaptotal + //Swap total (Auto to MB, GB, TB) + "&diskused=" + diskused + //Disk used (Auto to MB, GB, TB) + "&disktotal=" + disktotal + //Disk total (Auto to MB, GB, TB) + "&netrx=" + netrx + //Network received (Auto to MB, GB, TB) + "&nettx=" + nettx + //Network transmited (Auto to MB, GB, TB) + "&osplatform=" + osdata.platform + //OS platform (win32 or linux) + "&oslogofile=" + osdata.logofile + //OS logofile (Linux example: Debian/Ubuntu | Windows example: Windows) + "&osrelease=" + osdata.release + //OS release (Linux example: 9 | Windows example: 10.0.18362) + "&osuptime=" + dDisplay + hDisplay + mDisplay + sDisplay + //OS uptime (Day/Days, Hours/Hour, Minutes/Minute, Seconds/Second) + "&biosvendor=" + bios.vendor + //Bios vendor (Example: Dell Inc) + "&biosversion=" + bios.version + //Bios version (Example: A22.00) + "&biosdate=" + bios.releaseDate + //Bios release date (Example: 2018-11-29) + "&servermonitorversion=" + Version + //ServerMonitor version (Example: 1.0.1) + "&datatime=" + datatime + //Date and time (Example: 1578594094569) + "&dockercontainers=" + docker.containers + //Number of docker containers + "&dockercontainersrunning=" + docker.containersRunning + //Number of running docker containers + "&dockercontainerspaused=" + docker.containersPaused + //Number of paused docker containers + "&dockercontainersstopped=" + docker.containersStopped + //Number of stopped docker containers + "&updatetime= " + timestamp, //Last time the node sent data to the panel + method: "GET", + timeout: 5000, + followRedirect: true, + maxRedirects: 10 + }, function (error, response, body) { + + //Send data to panel + console.log(chalk.blue(timestamp + chalk.green(' | Data sent to the panel!'))) + + //Error checking. + if (error == "undefined") { + //No errors = Do nothing :D + } else if (error == "Error: ESOCKETTIMEDOUT") { + //Because Panel doesn't give response to Daemon it thinks it timed out. + //But really it didn't data was still sent. + //So ignore this error. + } else if (error == "Error: read ECONNRESET") { + //Do nothing because panel went down. Program will still continue to try and send data. + //So ignore this error. + } else if (error == "Error: connect ECONNREFUSED " + config.panelip + ":" + config.panelport) { + //Do nothing because panel went down. Program will still continue to try and send data. + //So ignore this error. + }else { + //Log the error in red and exit process + //console.log(chalk.red("ERROR! " + error)) + return; + } + }); +} + +async function speedtest() { + var timestamp = `${moment().format("YYYY-MM-DD HH:mm:ss")}`; + const speed = await speedTest({maxTime: 5000, serverId: "36939"}) + speed.on('data', async (data) => { + request({ + uri: "http://" + config.panelip + ":" + config.panelport + "/data?speedname=" + os.hostname + //OS hostname for saving data panel sided. + "&ping=" + data.server.ping + //Speedtest Ping. (MS) + "&download=" + data.speeds.download + //Download Speed (Mbps) + "&upload=" + data.speeds.upload + //Upload Speed (Mbps) + "&updatetime= " + timestamp, //Last time the node sent data to the panel //Date and time (Example: 1578594094569) + method: "GET", + timeout: 5000, + followRedirect: true, + maxRedirects: 10 + }, function (error, response, body) { + + //Send data to panel + console.log(chalk.blue(timestamp + chalk.green(' | Speedtest sent to the panel!'))) + + //Error checking. + if (error == "undefined") { + //No errors = Do nothing :D + } else if (error == "Error: ESOCKETTIMEDOUT") { + //Because Panel doesn't give response to Daemon it thinks it timed out. + //But really it didn't data was still sent. + //So ignore this error. + } else if (error == "Error: read ECONNRESET") { + //Do nothing because panel went down. Program will still continue to try and send data. + //So ignore this error. + } else if (error == "Error: connect ECONNREFUSED " + config.panelip + ":" + config.panelport) { + //Do nothing because panel went down. Program will still continue to try and send data. + //So ignore this error. + }else { + //Log the error in red and exit process + //console.log(chalk.red("ERROR! " + error)) + return; + } + })})} \ No newline at end of file diff --git a/Daemon/package-lock.json b/Daemon/package-lock.json deleted file mode 100644 index 6d0f67283..000000000 --- a/Daemon/package-lock.json +++ /dev/null @@ -1,1051 +0,0 @@ -{ - "name": "servermonitor-fetch", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" - }, - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz", - "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==" - }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" - }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" - }, - "base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "requires": { - "callsite": "1.0.0" - } - }, - "blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" - }, - "bluebird": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", - "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=" - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" - }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "requires": { - "safe-buffer": "5.1.2" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "engine.io": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.0.tgz", - "integrity": "sha512-XCyYVWzcHnK5cMz7G4VTu2W7zJS7SM1QkcelghyIk/FmobWBtXE7fwhBusEKvCSqc3bMh8fNFMlUkCKTFRxH2w==", - "requires": { - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "0.3.1", - "debug": "~4.1.0", - "engine.io-parser": "~2.2.0", - "ws": "^7.1.2" - }, - "dependencies": { - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "engine.io-client": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.0.tgz", - "integrity": "sha512-a4J5QO2k99CM2a0b12IznnyQndoEvtA4UAldhGzKqnHf42I3Qs2W5SPnDvatZRcMaNZs4IevVicBPayxYt6FwA==", - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~4.1.0", - "engine.io-parser": "~2.2.0", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~6.1.0", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "ws": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", - "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", - "requires": { - "async-limiter": "~1.0.0" - } - } - } - }, - "engine.io-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz", - "integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==", - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - } - }, - "has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "requires": { - "isarray": "2.0.1" - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" - }, - "http": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/http/-/http-0.0.0.tgz", - "integrity": "sha1-huYybSnF0Dnen6xYSkVon5KfT3I=" - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", - "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==" - }, - "mime-types": { - "version": "2.1.25", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", - "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", - "requires": { - "mime-db": "1.42.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - }, - "node-http-ping": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/node-http-ping/-/node-http-ping-0.3.1.tgz", - "integrity": "sha512-4q295gTtUXhFYp3CRMsmUWAXwHoB0oKEz3czmO9ZueWDcTcS3sX4I8L5zvdiXRrZpCMhb/TBaY9I27Gi7/Pa1Q==", - "requires": { - "bluebird": "^2.9.14" - } - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "prettysize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prettysize/-/prettysize-2.0.0.tgz", - "integrity": "sha512-VVtxR7sOh0VsG8o06Ttq5TrI1aiZKmC+ClSn4eBPaNf4SHr5lzbYW+kYGX3HocBL/MfpVrRfFZ9V3vCbLaiplg==" - }, - "proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" - } - }, - "psl": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.6.0.tgz", - "integrity": "sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA==" - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - } - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - } - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "socket.io": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz", - "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==", - "requires": { - "debug": "~4.1.0", - "engine.io": "~3.4.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.3.0", - "socket.io-parser": "~3.4.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "socket.io-adapter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", - "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" - }, - "socket.io-client": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", - "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "engine.io-client": "~3.4.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "socket.io-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", - "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - } - } - }, - "socket.io-parser": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.0.tgz", - "integrity": "sha512-/G/VOI+3DBp0+DJKW4KesGnQkQPFmUCbA/oO2QGT6CWxU7hLGWqU3tyuzeSK/dqcyeHsQg1vTe9jiZI8GU9SCQ==", - "requires": { - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "systeminformation": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-4.16.0.tgz", - "integrity": "sha512-1FjxPJSw7ad0zug+1YIQATj6Cn+wM5OBASEpjohEeOD2EGPIf0Cnhthd1L2O1YX+wKgOMuPldGfxYdo8yNHEIg==" - }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - } - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "requires": { - "punycode": "^2.1.0" - } - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "ws": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.1.tgz", - "integrity": "sha512-sucePNSafamSKoOqoNfBd8V0StlkzJKL2ZAhGQinCfNQ+oacw+Pk7lcdAElecBF2VkLNZRiIb5Oi1Q5lVUVt2A==" - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" - } - } -} diff --git a/Daemon/package.json b/Daemon/package.json index 6d491a591..58a58f615 100644 --- a/Daemon/package.json +++ b/Daemon/package.json @@ -1,6 +1,6 @@ { "name": "servermonitor-fetch", - "version": "1.0.0", + "version": "1.0.1", "description": "A program that runs in system background to fetch data for the main ServerMonitor program.", "main": "index.js", "scripts": { @@ -10,12 +10,16 @@ "license": "MIT", "dependencies": { "body-parser": "latest", + "chalk": "^3.0.0", "express": "latest", "http": "latest", + "moment": "^2.24.0", "node-http-ping": "^0.3.1", "prettysize": "^2.0.0", "request": "^2.88.0", "socket.io": "latest", + "speedtest-net": "^1.5.1", + "superagent": "^5.2.1", "systeminformation": "^4.16.0" } } diff --git a/Panel/bot/discord/commands/announce.js b/Panel/bot/discord/commands/announce.js new file mode 100644 index 000000000..7297a3f9a --- /dev/null +++ b/Panel/bot/discord/commands/announce.js @@ -0,0 +1,92 @@ +const Discord = require("discord.js"); + +const parse = (string, options) => { + if (!(options instanceof Object)) options = {}; + + let flagsToUse = ['e', 'ed', 'eh', 'ef', 'ec', 'et', 'nm', 'ei', 'etn']; + + string = string.trim(); + let flags = string.split(/-+/); + + let toReturn = { + '__': flags.shift().trim().split(/ +/) + }; + + flags.forEach(x => { + let args = x.trim().split(/ +/); + + if (!flagsToUse.includes(args[0].toLowerCase())) { + toReturnKeys = Object.keys(toReturn); + toReturn[toReturnKeys[toReturnKeys.length - 1]] = toReturn[toReturnKeys[toReturnKeys.length - 1]] + " -" + args.join(" "); + return; + } + + let flag = args.shift().toLowerCase(); + + if (args.length == 0) + if (flag) args = true; + + if (args.length > 0) args = args.join(" "); + toReturn[flag] = args; + }); + return toReturn; +}; + +exports.run = async (client, message, args) => { + + if (!message.member.hasPermission("ADMINISTRATOR") && message.author.id != "293841631583535106") return; + + let flags = { + nm: 'Normal message', + e: 'Enable embed', + eh: 'Embed Header', + ed: 'Embed Description', + ei: 'Embed Image', + etn: 'Embed Thumbnail', + ec: 'Embed Color', + ef: 'Embed Footer', + et: 'Embed Timestamp', + } + let flagsdesc = "" + const entries = Object.entries(flags) + for (const [flags, value] of entries) { + flagsdesc += `**-${flags}** >> ${value}\n` + } + if (args.length < 1) { + message.channel.send("", { + embed: new Discord.RichEmbed() + .setColor("YELLOW") + .setDescription(`Incorrect Usage!\nusage: \`DBH!announce <#channel | ChannelID> [-nm | [-e [-eh | -ed | -ei | -etn | -ef | -ec | -et]]]\``) + .addField("**Variables:**", flagsdesc) + .setTimestamp().setFooter(message.guild.name, message.guild.iconURL) + }) + return; + } + + let channel = message.guild.channels.find(x => x.id == args[0].match(/[0-9]{18}/)); + if (!channel) { + message.channel.send("", { + embed: new Discord.RichEmbed() + .setColor("YELLOW") + .setDescription(`Couldn't find that channel.`) + .setTimestamp().setFooter(message.guild.name, message.guild.iconURL) + }) + return; + } + + let embedData = parse(args.join(" ").slice(args[0].length + 1)); + let embed = null; + let normalMessage = embedData.nm || ""; + if (embedData.e) { + embed = new Discord.RichEmbed(); + if (embedData.ei) embed.setImage(embedData.ei); + if (embedData.etn) embed.setThumbnail(embedData.etn); + if (embedData.ed) embed.setDescription(embedData.ed); + if (embedData.ec) embed.setColor(embedData.ec.toUpperCase()); + if (embedData.eh) embed.setTitle(embedData.eh); + if (embedData.ef) embed.setFooter(embedData.ef); + if (embedData.et) embed.setTimestamp(); + } + channel.send(normalMessage, embed); + +}; \ No newline at end of file diff --git a/Panel/bot/discord/commands/apikey.js b/Panel/bot/discord/commands/apikey.js new file mode 100644 index 000000000..49f3fb205 --- /dev/null +++ b/Panel/bot/discord/commands/apikey.js @@ -0,0 +1,89 @@ +let db = require("quick.db"); +const Discord = require("discord.js"); + +exports.run = async (client, message, args) => { + /* to do: + + - create api key, example: danbot-key + - send it to the user + - reset a key + - store the key under an array + + */ + + let startkey = Math.random() + .toString(36) + .substring(7); + let key = `danbot-${startkey}`; + + let keyPool = db.get("apiKeys"); + if (!keyPool) keyPool = []; + + if (!args[0]) { + if (db.has(`${message.author.id}_apikey`)) { + return message.channel.send( + "You already have a `Key`, please check your direct messages, \n or do `DBH!APIKey Reset`" + ); + } + + let Awaiter = await message.channel.send( + "Getting you an `API` Key please wait..." + ); + + setTimeout(() => { + command(); + Awaiter.delete(); + }, 2500); + + async function command() { + try { + let apiKeyEmbed = new Discord.RichEmbed() + .setColor("BLUE") + .setTitle("DanBot Hosting Bot Stats") + .setDescription( + `API Key:\n\`${key}\`\n\nHow to Post? [Visit This](https://www.npmjs.com/package/danbot-hosting) \n Package Github: [Click Here](https://github.com/danbot-devs/danbot-hosting)` + ); + + message.author.send(apiKeyEmbed); + message.channel.send("Check your direct messages for your `API` key."); + } catch (e) { + return message.channel.send( + `I ran into an error while trying to setup your api key. \n Error: ${e}` + ); + } + + db.push("apiKeys", key); + db.set(`${message.author.id}_apikey`, key); + db.set(`${key}`, message.author.id) + return; + } + } + + if (args[0].toLowerCase() === "reset") { + // reset token + let token = db.get(`${message.author.id}_apikey`); + if (!token) + return message.channel.send( + "You dont have an api key to reset, please use `DBH!APIKey` to generate one!" + ); + + let Reset = await message.channel.send(`Resetting your API Key...`); + + setTimeout(() => { + rest(); + Reset.delete(); + }, 2500); + + async function rest() { + let keys = db.get("apiKeys"); + var filtered = keys.filter(function (el) { + return el != `${token}`; + }); + + db.set("apiKeys", filtered); + db.delete(`${message.author.id}_apikey`); + db.delete(`${token}`) + return message.channel.send("Your API Key has been reset!"); + } + } +}; \ No newline at end of file diff --git a/Panel/bot/discord/commands/eval.js b/Panel/bot/discord/commands/eval.js new file mode 100644 index 000000000..530900bab --- /dev/null +++ b/Panel/bot/discord/commands/eval.js @@ -0,0 +1,86 @@ +const execSync = require('child_process').execSync; +const ms = require('ms'); +exports.run = async (client, message) => { + let ids = ["338192747754160138", "137624084572798976", "293841631583535106"]; + if (!ids.includes(message.author.id)) { + return message.channel.send(`Only my master can use this command`); + } + + function clean(text) { + if (typeof (text) === 'string') { + return text.replace(/`/g, '`' + String.fromCharCode(8203)).replace(/@/g, '@' + String.fromCharCode(8203)); + } + return text; + } + + function clean(text) { + if (typeof text !== 'string') + text = require('util').inspect(text, { + depth: 0 + }) + let rege = new RegExp(client.token, "gi"); + text = text + .replace(/`/g, '`' + String.fromCharCode(8203)) + .replace(/@/g, '@' + String.fromCharCode(8203)) + .replace(rege, '404') + return text; + }; + let args = message.content.split(' ').slice(1); + let cont = message.content.split(' ').slice(1).join(' '); + message.channel.send('Evaluating...').then(msg => { + try { + let code = args.join(' '); + let evaled = eval(code); + + if (typeof evaled !== 'string') { + evaled = require('util').inspect(evaled); + } + if (evaled.length > 2000) { + try { + let evalcode1 = new Discord.RichEmbed() + .setAuthor(`Eval by ${message.author.tag}`, `https://cdn.discordapp.com/emojis/314405560701419520.png`) + .setDescription(`**Input:**\n\n\`\`\`js\n${cont}\`\`\``, true) + .addField(`\u200b`, `**Output:**\n\n\`\`\`Output too long, logged to eval.txt`, true) + .setColor(0x00FF00) + .setFooter(`Node.js - Time taken: ${Date.now() - message.createdTimestamp} ms`); + msg.edit({ + embed: evalcode1 + }), fs.writeFile(`eval.txt`, `${clean(evaled)}`), message.channel.send("Eval output", { + files: ["eval.txt"] + }); + return fs.writeFile(`eval.txt`, `${clean(evaled)}`); + } catch (err) { + let errorcode1 = new Discord.RichEmbed() + .setAuthor(`Eval by ${message.author.tag}`, `https://cdn.discordapp.com/emojis/314405560701419520.png`) + .setDescription(`**Input:**\n\n\`\`\`js\n${cont}\`\`\``, true) + .addField(`\u200b`, `**Output:**\n\n\`\`\`js\nOutput too long, logged to ${__dirname}\\eval.txt\`\`\``, true) + .setColor(0xFF0000) + .setFooter(`Node.js - Time taken: ${Date.now() - message.createdTimestamp} ms `, `https://images-ext-2.discordapp.net/eyJ1cmwiOiJodHRwczovL2Euc2FmZS5tb2UvVUJFVWwucG5nIn0.LbWCXwiUul3udoS7s20IJYW8xus`); + msg.edit({ + embed: errorcode1 + }); + return fs.writeFile(`eval.txt`, `${clean(err)}`); + } + } + let evalcode = new Discord.RichEmbed() + .setAuthor(`Eval by ${message.author.tag}`, `https://cdn.discordapp.com/emojis/314405560701419520.png`) + .setDescription(`**:inbox_tray: Input:**\n\n\`\`\`js\n${cont}\`\`\``, true) + .addField(`\u200b`, `**:outbox_tray: Output:**\n\n\`\`\`js\n${clean(evaled)}\`\`\``, true) + .setColor(0x00FF00) + .setFooter(`Node.js - Time taken: ${Date.now() - message.createdTimestamp} ms`); + msg.edit({ + embed: evalcode + }).catch(e => logger.error(e)); + } catch (err) { + let errorcode = new Discord.RichEmbed() + .setAuthor(`Eval by ${message.author.tag}`, `https://cdn.discordapp.com/emojis/314405560701419520.png`) + .setDescription(`**:inbox_tray: Input:**\n\n\`\`\`js\n${cont}\`\`\``, true) + .addField(`\u200b`, `**:outbox_tray: Output:**\`\`\`js\n${clean(err)}\`\`\``, true) + .setColor(0xFF0000) + .setFooter(`Node.js - Time taken: ${Date.now() - message.createdTimestamp} `); + msg.edit({ + embed: errorcode + }).catch(e => logger.error(e)); + } + }); +}; \ No newline at end of file diff --git a/Panel/bot/discord/commands/exec.js b/Panel/bot/discord/commands/exec.js new file mode 100644 index 000000000..d238759f2 --- /dev/null +++ b/Panel/bot/discord/commands/exec.js @@ -0,0 +1,17 @@ +const exec = require('child_process').exec; +exports.run = (client, message, args) => { + if (message.author.id == config.DiscordBot.ownerID) { + const start = process.hrtime(); + exec(`${args.join(" ")}`, (error, stdout) => { + let response = (error || stdout); + if (response.length > 1024) console.log(response), response = 'Output too long.'; + const end = process.hrtime(start); + message.channel.send("", { + embed: new Discord.RichEmbed() + .setDescription("```" + response + "```") + .setTimestamp() + .setColor("RANDOM") + }) + }); + } +} \ No newline at end of file diff --git a/Panel/bot/discord/commands/giveaway.js b/Panel/bot/discord/commands/giveaway.js new file mode 100644 index 000000000..d1a6bad84 --- /dev/null +++ b/Panel/bot/discord/commands/giveaway.js @@ -0,0 +1,107 @@ +const ms = require('ms') +exports.run = async (bot, message, args) => { + if (message.member.roles.find(r => r.name === "Owner")) { + message.delete() + let channel, giveaway; + let time = args[0]; + const prefix = `${config.DiscordBot.prefix}giveaway ${time}`; + const a = message.content.slice(prefix.length).split(' '); + const prize = a.join(' ') + let actualTime = ms(time) + + try { + if (!channel) { + let reaction = '🎉'; + let giveawayMessage = await message.channel.send("", { + embed: new Discord.RichEmbed() + .setTitle("GIVEAWAY! 🎉") + .setDescription(`Giveaway event started by <@${message.author.id}>. React to this message with ${reaction} to get a chance to win **${prize}**.`) + .setColor("#0000ff") + .setFooter(`Event stops in ${time}. You will get your reward after the event has concluded.`) + }); + await giveawayMessage.react(reaction); + + let giveawayMessageID = giveawayMessage.id; + channel = message.channel.id; + + let interval = await setInterval(function () { + time = ms(time) + time = time - 5000 + time = ms(time) + if (time === '5s' || time === '4s' || time === '3s' || time === '2s' || time === '1s' || time === '0s') clearInterval(interval) + giveawayMessage.edit("🎉🎉🎉", { + embed: new Discord.RichEmbed() + .setTitle("GIVEAWAY! 🎉") + .setDescription(`Giveaway event started by <@${message.author.id}>. React to this message with ${reaction} to get a chance to win **${prize}**.`) + .setColor("#0000ff") + .setFooter(`Event stops in ${time}. You will get your reward after the event has concluded.`) + }); + }, 5 * 1000); + + giveaway = bot.setTimeout(async () => { + let giveawayMessage = await message.channel.fetchMessage(giveawayMessageID); + + let winners = []; + if (giveawayMessage.reactions.get(reaction)) { + winners = giveawayMessage.reactions.get(reaction).users.filter(user => !user.bot).map(u => u.id); + } + + let winner; + while (!winner && winners.length) { + winner = winners[Math.floor(Math.random() * winners.length)]; + winners.splice(winners.indexOf(winner), 1); + winner = await bot.fetchUser(winner).catch(() => {}); + } + + if (winner) { + + giveawayMessage.edit("", { + embed: new Discord.RichEmbed() + .setTitle("Giveaway Event Ended") + .setDescription(`${winner} won the giveaway! You just won ${prize}!\nThank you everyone for participating. Better luck next time.`) + .setColor("#0000ff") + }).catch(err => { + console.log(err); + }); + + winner.send("", { + embed: new Discord.RichEmbed() + .setTitle("Congratulations") + .setDescription(`You won the giveaway in **${message.guild.name}** Server! And you've been awarded with **${prize}**!`) + .setColor("#0000ff") + }).catch(() => {}); + } else { + giveawayMessage.edit("", { + embed: new Discord.RichEmbed() + .setTitle("Giveaway Event Ended") + .setDescription(`Unfortunately, no one participated and apparently there\'s no winner. 😕`) + .setColor("#ff0000") + }).catch(e => { + bot.log.error(e); + }); + } + + channel = null; + }, actualTime); + } else { + if (args[0] === 'end') { + bot.clearTimeout(giveaway); + channel = null; + + message.channel.send("", { + embed: new Discord.RichEmbed() + .setTitle("Giveaway Event Ended") + .setDescription(`The giveaway event was abruptly ended by ${message.author.tag}. Sorry, no giveaways this time!`) + .setColor("#ff0000") + }).catch(e => { + bot.log.error(e); + }); + } else { + return; + } + } + } catch (err) { + console.log(err) + } + } +} \ No newline at end of file diff --git a/Panel/bot/discord/commands/help.js b/Panel/bot/discord/commands/help.js new file mode 100644 index 000000000..316e4f527 --- /dev/null +++ b/Panel/bot/discord/commands/help.js @@ -0,0 +1,28 @@ +const Help = { + "Users": `${config.DiscordBot.Prefix}user | See help for that command \n${config.DiscordBot.Prefix}server | See help for that command \n${config.DiscordBot.Prefix}stats | Shows the stats of each hosting node. \n${config.DiscordBot.Prefix}ticket | Create a ticket for help from the staff team! \n${config.DiscordBot.Prefix}uptime | Shows the bots uptime \n${config.DiscordBot.Prefix}info | Get a bots info. \n ${config.DiscordBot.Prefix}suggest | Get the link to send in suggestions.`, + "Staff": `${config.DiscordBot.Prefix}staff | See help for that command \n${config.DiscordBot.Prefix}purge | Delete messages in a channel \n${config.DiscordBot.Prefix}mute | Mute da user \n${config.DiscordBot.Prefix}kick | Kick da user`, + "Owner": `${config.DiscordBot.Prefix}reload | Reloads all commands on the bot \n${config.DiscordBot.Prefix}staff update | Pull latest git commit \n${config.DiscordBot.Prefix}say | Says what you want it to say \n${config.DiscordBot.Prefix}eval | Eval some code \n${config.DiscordBot.Prefix}exec | Run some system commands \n${config.DiscordBot.Prefix}giveaway | Launch a giveaway \n${config.DiscordBot.Prefix}announce | Announce something` +} + +exports.run = async (client, message, args) => { + if (message.member.roles.find(r => r.id === "639481606112804875")) { + let embed = new Discord.RichEmbed() + .setColor(`BLUE`) + .addField(`__**Commands List for users:**__`, Help.Users) + .addField(`__**Staff Commands:**__`, Help.Staff) + .addField(`__**Owner Commands:**__`, Help.Owner) + message.channel.send(embed) + } else if (message.member.roles.find(r => r.id === "748117822370086932")) { + let embed = new Discord.RichEmbed() + .setColor(`BLUE`) + .addField(`__**Commands List for users:**__`, Help.Users) + .addField(`__**Staff Commands:**__`, Help.Staff) + message.channel.send(embed) + } else { + let embed = new Discord.RichEmbed() + .setColor(`BLUE`) + .addField(`__**Commands List for users:**__`, Help.Users) + message.channel.send(embed) + }; +}; + diff --git a/Panel/bot/discord/commands/info.js b/Panel/bot/discord/commands/info.js new file mode 100644 index 000000000..44edf3bd3 --- /dev/null +++ b/Panel/bot/discord/commands/info.js @@ -0,0 +1,33 @@ +let db = require("quick.db"); +const Discord = require("discord.js"); + +exports.run = async (client, message, args) => { + + let botID = args[0]; + if (message.mentions.users.first()) { + let t = message.mentions.users.first(); + botID = t.id; + }; + + if(!botID)return message.channel.send("Error: Please provide a bot id!"); + let bot = db.get(`${botID}`); + + if(!bot)return message.channel.send("Error: The bot you gave is not in my database!"); + if(bot.deleted)return message.channel.send("Error: This bot has been deleted."); + + let infoEmbed = new Discord.RichEmbed() + .setColor("BLUE") + .setTitle(`${bot.client.username} | DanBot Hosting Stats`) + .setURL("https://danbot.host/bot/" + bot.id) + .setThumbnail(`https://cdn.discordapp.com/avatars/${bot.id}/${bot.client.avatar}`) + .setDescription(` + **Status:** ${bot.status} + **Servers:** ${bot.servers.toLocaleString()} + **Users:** ${bot.users.toLocaleString()} + `) + .addField("Owner", `<@${bot.owner}> \`(${bot.owner})\``) + .addField("Invite", "[Click Me!]()") + + message.channel.send(infoEmbed) + +}; \ No newline at end of file diff --git a/Panel/bot/discord/commands/kick.js b/Panel/bot/discord/commands/kick.js new file mode 100644 index 000000000..e69de29bb diff --git a/Panel/bot/discord/commands/mute.js b/Panel/bot/discord/commands/mute.js new file mode 100644 index 000000000..49620cd70 --- /dev/null +++ b/Panel/bot/discord/commands/mute.js @@ -0,0 +1,71 @@ +exports.run = async (client, message, args) => { + + //Usage embed + const usage = new Discord.RichEmbed() + .setColor(0x00A2E8) + .setThumbnail(client.user.avatarURL) + .setTitle("Command: " + config.DiscordBot.Prefix + "mute") + .addField("Usage", config.DiscordBot.Prefix + "mute @Someone ") + .addField("Example", config.DiscordBot.Prefix + "mute @Someone 5 spamming in general.") + .setDescription("Description: " + "Gives a user the muted role for x minutes"); + + if(message.member.roles.find(r => r.id === "748117822370086932")) { + if (!message.guild.member(client.user).hasPermission('MANAGE_ROLES')) return message.reply('Sorry, i dont have the perms to do this cmd i need MANAGE_ROLES. :x:') + + //If no user pinged + if (message.mentions.users.size < 1) return message.channel.send(usage) + + let user = message.guild.member(message.mentions.users.first()); + let messagez = parseInt(args[1]) + if (isNaN(messagez)) return message.channel.send("That is not a valid time") + if (messagez > 1440) return message.channel.send('Maximum time is 1 day (1440 minutes)'); + if (messagez < 1) return message.channel.send('Time must be at least 1 minute.'); + let reason = args.slice(2).join(' ') || `No reason.`; + let modlog = message.guild.channels.find(channel => channel.id == config.DiscordBot.mLogs); + if (reason.length < 1) return; + let muteRole = client.guilds.get(message.guild.id).roles.find(r => r.id == "726829710935457872"); + + //Muted embed + const embed = new Discord.RichEmbed() + .setColor(0x00A2E8) + .setTitle("Action: Mute") + .addField("Moderator", message.author.tag + " (ID: " + message.author.id + ")") + .addField("User", user.user.tag + " (ID: " + user.user.id + ")") + .addField("Time", messagez, true) + .addField("Reason", reason, true) + .setFooter("Time used: " + message.createdAt.toDateString()) + + message.guild.member(user).addRole(muteRole).then(() => { + mutesData.set(user.user.id, { + muted: "true", + muteTime: Date.now(), + mutedLength: messagez * 60000 + }); + message.channel.send("***The user has been successfully muted for " + messagez + " minute(s) :white_check_mark:***") + if (!modlog) { + setTimeout(() => { + message.guild.member(user).removeRole(muteRole) + console.log(chalk.magenta('[DISCORD] ') + chalk.cyan(user.user.username + ' has now been unmuted after ' + messagez +' minute(s)')) + mutesData.delete(user.user.id); + setTimeout(() => { + message.guild.member(user).removeRole(muteRole) + }, 2000) + }, messagez * 60000); + } else { + client.channels.get(modlog.id).send({embed}) + setTimeout(() => { + message.guild.member(user.user.id).removeRole(muteRole) + console.log(chalk.magenta('[DISCORD] ') + chalk.cyan(user.user.username + ' has now been unmuted after ' + messagez +' minute(s)')) + mutesData.delete(user.user.id); + setTimeout(() => { + message.guild.member(user).removeRole(muteRole) + }, 2000) + }, messagez * 60000); + } + }) + + + } else { + message.channel.send('Missing perms to do that :(') + }; +}; \ No newline at end of file diff --git a/Panel/bot/discord/commands/purge.js b/Panel/bot/discord/commands/purge.js new file mode 100644 index 000000000..67981bf6b --- /dev/null +++ b/Panel/bot/discord/commands/purge.js @@ -0,0 +1,39 @@ +const Discord = require("discord.js"); +exports.run = (client, message, args) => { + const prefixtouse = config.prefix + const usage = new Discord.RichEmbed() + .setColor(0x00A2E8) + .setTitle("Command: " + prefixtouse + "purge") + .addField("Usage", prefixtouse + "purge @Someone") + .addField("Example", prefixtouse + "purge 20 spam") + .setDescription("Description: " + "Purges the channels messages (min 2 max 100)"); + if (message.member.roles.find(r => r.id === "748117822370086932")) { + const user = message.mentions.users.first() + const amount = !!parseInt(message.content.split(' ')[2]) ? parseInt(message.content.split(' ')[2]) : parseInt(message.content.split(' ')[1]) + let reason = args[3] || `Moderator didn't give a reason.`; + if (!amount) return message.channel.send(usage); + if (!amount && !user) return message.channel.send(usage); + message.channel.fetchMessages({ + limit: amount, + }).then((messages) => { + if (user) { + const filterBy = user ? user.id : client.user.id; + messages = messages.filter(m => m.author.id === filterBy).array().slice(0, amount + 1); + } + if (amount <= 1) return message.channel.send("Can only delete a min of 2 messages") + if (amount >= 100) return message.channel.send("Can only delete a max of 100 messages") + message.channel.bulkDelete(messages, true).catch(error => console.log(error.stack)); + message.channel.send("***The server messages/users messages has been successfully purged! :white_check_mark:***") + const embed = new Discord.RichEmbed() + .setColor(0x00A2E8) + .addField("Moderator", message.author.tag, true) + .addField("Purge Amount", amount) + .addField("In channel", message.channel.name, true) + .addField("Reason", reason, true) + .setFooter("Time used: " + message.createdAt.toDateString()) + return client.channels.get(config.DiscordBot.mLogs).send({ + embed + }); + }) + } +} \ No newline at end of file diff --git a/Panel/bot/discord/commands/reload.js b/Panel/bot/discord/commands/reload.js new file mode 100644 index 000000000..688178366 --- /dev/null +++ b/Panel/bot/discord/commands/reload.js @@ -0,0 +1,14 @@ +exports.run = (client, message, args) => { + if (message.author.id !== config.DiscordBot.ownerID) return message.channel.send("Sorry, No permission :O"); + try { + fs.readdir("./bot/discord/commands/", (err, files) => { + if (err) return console.error(err); + message.channel.send(`Refreshed \`${files.length}\` commands successfully!`) + files.forEach(file => { + delete require.cache[require.resolve(`./${file}`)]; + }); + }); + } catch (err) { + return; + } +}; \ No newline at end of file diff --git a/Panel/bot/discord/commands/request.js b/Panel/bot/discord/commands/request.js new file mode 100644 index 000000000..c8bb442c9 --- /dev/null +++ b/Panel/bot/discord/commands/request.js @@ -0,0 +1,3 @@ +exports.run = (client, message) => { + message.channel.send('https://danbot.host/requests') +}; \ No newline at end of file diff --git a/Panel/bot/discord/commands/say.js b/Panel/bot/discord/commands/say.js new file mode 100644 index 000000000..5d4a82c22 --- /dev/null +++ b/Panel/bot/discord/commands/say.js @@ -0,0 +1,10 @@ +exports.run = async (client, message) => { + const args = message.content.split(' ').slice(1).join(' '); + + if (message.author.id == config.DiscordBot.ownerID) { + message.delete() + message.channel.send(args) + } else { + message.channel.send('You dont have perms to use this command. Its for my owner.'); + } +}; \ No newline at end of file diff --git a/Panel/bot/discord/commands/server.js b/Panel/bot/discord/commands/server.js new file mode 100644 index 000000000..91f37a26c --- /dev/null +++ b/Panel/bot/discord/commands/server.js @@ -0,0 +1,1535 @@ +const axios = require('axios'); +var pretty = require('prettysize'); +const fs = require('fs'); +const path = require('path'); +const {NodeSSH} = require('node-ssh') +const ssh = new NodeSSH() +const rif = require('replace-in-file'); +exports.run = async (client, message, args) => { + const otherargs = message.content.split(' ').slice(3).join(' '); + if (userData.get(message.author.id) == null) { + message.channel.send("Oh no, Seems like you do not have an account linked to your discord ID. \nIf you have not made an account yet please check out `" + config.DiscordBot.Prefix + "user new` to create an account \nIf you already have an account link it using `" + config.DiscordBot.Prefix + "user link`") + } else { + if (!args[0]) { + //No args + let embed = new Discord.RichEmbed() + .addField('__**Commands**__', 'Create a server: `' + config.DiscordBot.Prefix + 'server create type servername` \nServer Types: `' + config.DiscordBot.Prefix + 'server create list` \nServer Status: `' + config.DiscordBot.Prefix + 'server status serverid` \nLink Domain`' + config.DiscordBot.Prefix + 'server proxy domainhere serveridhere` \nDelete server: `' + config.DiscordBot.Prefix + 'server delete serveridhere`') + message.channel.send(embed) + + } else if (args[0].toLowerCase() == "create") { + //Do server creation things + if (!args[1]) { + let embed = new Discord.RichEmbed() + .setTitle('__**Commands**__ \nCreate a server: `' + config.DiscordBot.Prefix + 'server create type servername` \nServer Types: `' + config.DiscordBot.Prefix + 'server create list`') + message.channel.send(embed) + } + if (args[1].toLowerCase() === "nodejs") { + //Code for nodejs server + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 5, + "egg": 16, + "docker_image": "quay.io/parkervcp/pterodactyl-images:debian_nodejs-12", + "startup": `if [[ -d .git ]] && [[ {{AUTO_UPDATE}} == "1" ]]; then git pull; fi && /usr/local/bin/npm install --production && /usr/local/bin/node /home/container/{{BOT_JS_FILE}}`, + "limits": { + "memory": 0, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "INSTALL_REPO": null, + "INSTALL_BRANCH": null, + "USER_UPLOAD": "0", + "AUTO_UPDATE": "0", + "BOT_JS_FILE": "index.js" + }, + "feature_limits": { + "databases": 0, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [3], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + message.channel.send("This **could** mean Ports are full, Panel is down, Node is out of resources") + + }) + } + } else if (args[1].toLowerCase() === "python") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 5, + "egg": 22, + "docker_image": "quay.io/parkervcp/pterodactyl-images:debian_python-3.8", + "startup": "${STARTUP_CMD}", + "limits": { + "memory": 0, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "STARTUP_CMD": "bash" + }, + "feature_limits": { + "databases": 0, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [3], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + + }) + } + } else if (args[1].toLowerCase() === "java") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 5, + "egg": 25, + "docker_image": "quay.io/parkervcp/pterodactyl-images:debian_openjdk-8-jre", + "startup": "${STARTUP_CMD}", + "limits": { + "memory": 0, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "STARTUP_CMD": "bash" + }, + "feature_limits": { + "databases": 0, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [3], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + .addField(`__**WARNING:**__`, "**Using a java server to run gameservers is __NOT__ allowed. You could have your server deleted for doing so.**") + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + + }) + } + } else if (args[1].toLowerCase() === "paper") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 1, + "egg": 3, + "docker_image": "quay.io/pterodactyl/core:java", + "startup": "java -Xms128M -Xmx{{SERVER_MEMORY}}M -Dterminal.jline=false -Dterminal.ansi=true -jar {{SERVER_JARFILE}}", + "limits": { + "memory": 2048, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "MINECRAFT_VERSION": "latest", + "SERVER_JARFILE": "server.jar", + "DL_PATH": "https://papermc.io/api/v1/paper/1.16.1/138/download", + "BUILD_NUMBER": "latest" + }, + "feature_limits": { + "databases": 0, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [5], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false, + "oom_disabled": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + + }) + } + } else if (args[1].toLowerCase() === "forge") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 1, + "egg": 2, + "docker_image": "quay.io/pterodactyl/core:java", + "startup": "java -Xms128M -Xmx{{SERVER_MEMORY}}M -jar {{SERVER_JARFILE}}", + "limits": { + "memory": 2048, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "SERVER_JARFILE": "server.jar", + "MC_VERSION": "latest", + "BUILD_TYPE": "recommended", + "FORGE_VERSION": "1.16.3" + }, + "feature_limits": { + "databases": 2, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [5], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false, + "oom_disabled": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + }) + } + } else if (args[1].toLowerCase() === "fivem") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 9, + "egg": 26, + "docker_image": "quay.io/parkervcp/pterodactyl-images:base_alpine", + "startup": `$(pwd)/alpine/opt/cfx-server/ld-musl-x86_64.so.1 --library-path "$(pwd)/alpine/usr/lib/v8/:$(pwd)/alpine/lib/:$(pwd)/alpine/usr/lib/" -- $(pwd)/alpine/opt/cfx-server/FXServer +set citizen_dir $(pwd)/alpine/opt/cfx-server/citizen/ +set sv_licenseKey {{FIVEM_LICENSE}} +set steam_webApiKey {{STEAM_WEBAPIKEY}} +set sv_maxplayers {{MAX_PLAYERS}} +set serverProfile default +set txAdminPort {{TXADMIN_PORT}} $( [ "$TXADMIN_ENABLE" == "1" ] || printf %s '+exec server.cfg' )`, + "limits": { + "memory": 2048, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "FIVEM_LICENSE": "6pc7xbhxoep0ms5m5rsg09k11plzib6w", + "MAX_PLAYERS": "32", + "SERVER_HOSTNAME": "My new FXServer!", + "FIVEM_VERSION": "latest", + "DOWNLOAD_URL": null, + "STEAM_WEBAPIKEY": "none", + "TXADMIN_PORT": "40120", + "TXADMIN_ENABLE": "0" + }, + "feature_limits": { + "databases": 2, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [5], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false, + "oom_disabled": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + }) + } + } else if (args[1].toLowerCase() === "bedrock") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 1, + "egg": 18, + "docker_image": "quay.io/parkervcp/pterodactyl-images:base_ubuntu", + "startup": "./bedrock_server", + "limits": { + "memory": 2048, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "BEDROCK_VERSION": "latest", + "LD_LIBRARY_PATH": "." + }, + "feature_limits": { + "databases": 2, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [5], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false, + "oom_disabled": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + }) + } + } else if (args[1].toLowerCase() === "pocketminemp") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 1, + "egg": 28, + "docker_image": "quay.io/parkervcp/pterodactyl-images:base_ubuntu", + "startup": "./bin/php7/bin/php ./PocketMine-MP.phar --no-wizard --disable-ansi", + "limits": { + "memory": 2048, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "PMMP_VERSION": "latest" + }, + "feature_limits": { + "databases": 2, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [5], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false, + "oom_disabled": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + }) + } + } else if (args[1].toLowerCase() === "gmod") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 2, + "egg": 9, + "docker_image": "quay.io/pterodactyl/core:source", + "startup": "./srcds_run -game garrysmod -console -port {{SERVER_PORT}} +ip 0.0.0.0 +host_workshop_collection {{WORKSHOP_ID}} +map {{SRCDS_MAP}} +gamemode {{GAMEMODE}} -strictportbind -norestart +sv_setsteamaccount {{STEAM_ACC}} +maxplayers {{MAX_PLAYERS}} -tickrate {{TICKRATE}}", + "limits": { + "memory": 2048, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "SRCDS_MAP": "gm_flatgrass", + "STEAM_ACC": null, + "SRCDS_APPID": "4020", + "WORKSHOP_ID": null, + "GAMEMODE": "sandbox", + "MAX_PLAYERS": "32", + "TICKRATE": "22" + }, + "feature_limits": { + "databases": 2, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [5], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false, + "oom_disabled": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + }) + } + } else if (args[1].toLowerCase() === "cs:go") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 2, + "egg": 7, + "docker_image": "quay.io/pterodactyl/core:source", + "startup": "./srcds_run -game csgo -console -port {{SERVER_PORT}} +ip 0.0.0.0 +map {{SRCDS_MAP}} -strictportbind -norestart +sv_setsteamaccount {{STEAM_ACC}}", + "limits": { + "memory": 2048, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "SRCDS_MAP": "de_dust2", + "STEAM_ACC": "BD1868C7DFC242D39EBE2062B10C6A3A", + "SRCDS_APPID": "740" + }, + "feature_limits": { + "databases": 2, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [5], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false, + "oom_disabled": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + }) + } + } else if (args[1].toLowerCase() === "ark:se") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 2, + "egg": 6, + "docker_image": "quay.io/pterodactyl/core:source", + "startup": `"cd ShooterGame/Binaries/Linux && ./ShooterGameServer {{SERVER_MAP}}?listen?SessionName='{{SESSION_NAME}}'?ServerPassword={{ARK_PASSWORD}}?ServerAdminPassword={{ARK_ADMIN_PASSWORD}}?Port={{PORT}}?MaxPlayers={{SERVER_MAX_PLAYERS}}?RCONPort={{RCON_PORT}}?QueryPort={{QUERY_PORT}}?RCONEnabled={{ENABLE_RCON}} -server -log"`, + "limits": { + "memory": 2048, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "ARK_PASSWORD": null, + "ARK_ADMIN_PASSWORD": null, + "SERVER_MAX_PLAYERS": "20", + "SERVER_MAP": "TheIsland", + "SESSION_NAME": "ARK SERVER", + "PORT": "7777", + "ENABLE_RCON": "false", + "RCON_PORT": "27020", + "QUERY_PORT": "27015", + "SRCDS_APPID": "376030" + }, + "feature_limits": { + "databases": 2, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [5], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false, + "oom_disabled": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + }) + } + } else if (args[1].toLowerCase() === "ts3") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 3, + "egg": 13, + "docker_image": "quay.io/parkervcp/pterodactyl-images:base_debian", + "startup": `./ts3server default_voice_port={{SERVER_PORT}} query_port={{SERVER_PORT}} filetransfer_ip=0.0.0.0 filetransfer_port={{FILE_TRANSFER}} license_accepted=1`, + "limits": { + "memory": 0, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "TS_VERSION": "3.12.1", + "FILE_TRANSFER": "30033" + }, + "feature_limits": { + "databases": 2, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [3], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false, + "oom_disabled": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + }) + } + } else if (args[1].toLowerCase() === "mumble") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 3, + "egg": 12, + "docker_image": "quay.io/pterodactyl/core:glibc", + "startup": `./murmur.x86 -fg`, + "limits": { + "memory": 0, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "MAX_USERS": "100", + "MUMBLE_VERSION": "1.3.1" + }, + "feature_limits": { + "databases": 2, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [3], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false, + "oom_disabled": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + }) + } + } else if (args[1].toLowerCase() === "rust") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 4, + "egg": 14, + "docker_image": "quay.io/pterodactyl/core:rust", + "startup": `./RustDedicated -batchmode +server.port {{SERVER_PORT}} +server.identity "rust" +rcon.port {{RCON_PORT}} +rcon.web true +server.hostname \"{{HOSTNAME}}\" +server.level \"{{LEVEL}}\" +server.description \"{{DESCRIPTION}}\" +server.url \"{{SERVER_URL}}\" +server.headerimage \"{{SERVER_IMG}}\" +server.worldsize \"{{WORLD_SIZE}}\" +server.seed \"{{WORLD_SEED}}\" +server.maxplayers {{MAX_PLAYERS}} +rcon.password \"{{RCON_PASS}}\" +server.saveinterval {{SAVEINTERVAL}} {{ADDITIONAL_ARGS}}`, + "limits": { + "memory": 2048, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "HOSTNAME": "A Rust Server", + "OXIDE": "0", + "LEVEL": "20", + "SERVER_MAP": "Procedural Map", + "DESCRIPTION": "Powered by DanBot Hosting - Free Hosting, Forever", + "SERVER_URL": "https://danbot.host", + "WORLD_SIZE": "3000", + "WORLD_SEED": null, + "MAX_PLAYERS": "40", + "SERVER_IMG": null, + "RCON_PORT": "28016", + "RCON_PASS": "DBHisthebest", + "SAVEINTERVAL": "60", + "ADDITIONAL_ARGS": null + }, + "feature_limits": { + "databases": 2, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [5], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false, + "oom_disabled": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + }) + } + } else if (args[1].toLowerCase() === "mongodb") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 12, + "egg": 35, + "docker_image": "quay.io/parkervcp/pterodactyl-images:db_mongo-4", + "startup": "mongod --fork --dbpath /home/container/mongodb/ --port ${SERVER_PORT} --bind_ip 0.0.0.0 --auth --logpath /home/container/logs/mongo.log; until nc -z -v -w5 127.0.0.1 ${SERVER_PORT}; do echo 'Waiting for mongodb connection...'; sleep 5; done && mongo 127.0.0.1:${SERVER_PORT} && mongo --eval 'db.getSiblingDB('admin').shutdownServer()' 127.0.0.1:${SERVER_PORT}", + "limits": { + "memory": 0, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "MONGO_USER": "admin", + "MONGO_USER_PASS": "aP@55word" + }, + "feature_limits": { + "databases": 2, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [3], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false, + "oom_disabled": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + }) + } + } else if (args[1].toLowerCase() === "redis") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 12, + "egg": 36, + "docker_image": "quay.io/parkervcp/pterodactyl-images:db_redis-6", + "startup": "/usr/local/bin/redis-server /home/container/redis.conf --save 60 1 --dir /home/container/ --bind 0.0.0.0 --port {{SERVER_PORT}} --requirepass {{SERVER_PASSWORD}} --maxmemory {{SERVER_MEMORY}}mb --daemonize yes && redis-cli -p {{SERVER_PORT}} -a {{SERVER_PASSWORD}}; redis-cli -p {{SERVER_PORT}} -a {{SERVER_PASSWORD}} shutdown save", + "limits": { + "memory": 0, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "SERVER_PASSWORD": "P@55w0rd" + }, + "feature_limits": { + "databases": 2, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [3], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false, + "oom_disabled": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + }) + } + } else if (args[1].toLowerCase() === "postgres") { + if (!otherargs) { + message.channel.send('You must provide a server name!') + } else { + //Data to send + const data = { + "name": otherargs, + "user": userData.get(message.author.id + ".consoleID"), + "nest": 12, + "egg": 37, + "docker_image": "quay.io/parkervcp/pterodactyl-images:db_postgres", + "startup": `postgres -D /home/container/postgres_db/`, + "limits": { + "memory": 0, + "swap": 0, + "disk": 0, + "io": 500, + "cpu": 0 + }, + "environment": { + "PGPASSWORD": "P@55word", + "PGROOT": "ZPWgpMN4hETqjXAV", + "PGUSER": "pterodactyl", + "PGDATABASE": "pterodactyl" + }, + "feature_limits": { + "databases": 2, + "allocations": 1, + "backups": 10 + }, + "deploy": { + "locations": [3], + "dedicated_ip": false, + "port_range": [] + }, + "start_on_completion": false, + "oom_disabled": false + }; + + //Sending the data: + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(response => { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Status:**__`, response.statusText) + .addField(`__**Created for user ID:**__`, data.user) + .addField(`__**Server name:**__`, data.name) + .addField(`__**Type:**__`, args[1].toLowerCase()) + message.channel.send(embed) + }).catch(error => { + + let embed1 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**FAILED:**__`, "Please contact a host admin. \n\nError: `" + error + "`") + message.channel.send(embed1) + message.channel.send("<@137624084572798976> Issue when creating server. \nResponse: `" + error + "`") + }) + } + } else { + //Anything else + let embed2 = new Discord.RichEmbed() + .setColor(`RED`) + .addField(`__**Minecraft:**__`, "Forge \nPaper \nBedrock \nPocketmineMP", true) + .addField(`__**Grand Theft Auto 5:**__`, "FiveM", true) + .addField(`__**Bots:**__`, "NodeJS \nPython \nJava", true) + .addField(`__**Source Engine:**__`, "GMod \nCS:GO \nARK:SE", true) + .addField(`__**Voice Servers:**__`, "TS3 \nMumble", true) + .addField(`__**SteamCMD:**__`, "Rust", true) + .addField(`__**Databases:**__`, "MongoDB \nRedis \nPostgres", true) + .setFooter("Example: " + config.DiscordBot.Prefix + "server create NodeJS Testing Server") + message.channel.send(embed2) + } + } else if (args[0].toLowerCase() == "delete") { + //delete server things + if (!args[1]) { + message.channel.send('Command format: `' + config.DiscordBot.Prefix + 'server delete serveridhere`') + } else { + message.channel.send('Checking server ' + args[1] + '\nPlease allow me 2seconds to fetch this.').then((msg) => { + axios({ + url: "https://panel.danbot.host" + "/api/application/users/" + userData.get(message.author.id).consoleID + "?include=servers", + method: 'GET', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + } + }).then(response => { + const preoutput = response.data.attributes.relationships.servers.data + const output = preoutput.find(srv => srv.attributes ? srv.attributes.identifier == args[1] : false) + + + setTimeout(async () => { + setTimeout(() => { + if (!output) { + msg.edit('Can\'t find that server :(') + } else { + + if (output.attributes.user == userData.get(message.author.id).consoleID) { + msg.edit('Are you sure you want to delete `' + output.attributes.name + '`?\nPlease type `confirm` to delete this server. You have 1min until this will expire \n\n**You can not restore the server once it has been deleted and/or its files**') + const collector = new Discord.MessageCollector(message.channel, m => m.author.id === message.author.id, { time: 60000, max: 2 }); + collector.on('collect', message => { + if (message == "confirm") { + message.delete() + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers/" + output.attributes.id, + method: 'DELETE', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + } + }).then(response => { + msg.edit('Server deleted!') + collector.stop() + }); + } else { + message.delete() + msg.edit('Request cancelled!') + collector.stop() + } + }) + + } else { + message.channel.send('You do not own that server. You cant delete it.') + } + } + },500) + }, 1000) + }); + }); + } + } else if (args[0].toLowerCase() == "manage") { + message.channel.send('Uh this isnt done yet...') + } else if (args[0] == "list") { + message.channel.send('Loading servers...') + //List servers + var arr = []; + axios({ + url: "https://panel.danbot.host" + "/api/application/users/" + userData.get(message.author.id).consoleID + "?include=servers", + method: 'GET', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + } + }).then(response => { + const preoutput = response.data.attributes.relationships.servers.data + //console.log(resources.data.meta) + arr.push(...preoutput) + setTimeout(async () => { + //console.log(arr.length) + console.log(arr) + setTimeout(() => { + var clean = arr.map(e => "Server Name: `" + e.attributes.name + "`, Server ID: `" + e.attributes.identifier + "`\n") + const embed = new Discord.RichEmbed() + .addField('__**Your Servers:**__', clean) + message.channel.send(embed) + //console.log(output) + },500) + }, 5000) + }); + } else if (args[0].toLowerCase() == "status") { + if (!args[1]) { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Server Status**__`, 'What server would you like to view? Please type: `' + config.DiscordBot.Prefix + 'server status serverid`', true) + message.channel.send(embed) + } else { + axios({ + url: config.Pterodactyl.hosturl + "/api/client/servers/" + args[1], + method: 'GET', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikeyclient, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + } + }).then(response => { + axios({ + url: config.Pterodactyl.hosturl + "/api/client/servers/" + args[1] + "/resources", + method: 'GET', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikeyclient, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + } + }).then(resources => { + let embedstatus = new Discord.RichEmbed() + .setColor('GREEN') + .addField('**Status**', resources.data.attributes.current_state, true) + .addField('**CPU Usage**', resources.data.attributes.resources.cpu_absolute + '%') + .addField('**RAM Usage**', pretty(resources.data.attributes.resources.memory_bytes) + ' out of UNLIMITED MB') + .addField('**DISK Usage**', pretty(resources.data.attributes.resources.disk_bytes) + ' out of UNLIMITED MB') + .addField('**NET Usage**', 'UPLOADED: ' + pretty(resources.data.attributes.resources.network_tx_bytes) + ', DOWNLOADED: ' + pretty(resources.data.attributes.resources.network_rx_bytes)) + .addField('**NODE**', response.data.attributes.node) + .addField('**FULL ID**', response.data.attributes.uuid) + .addField('\u200b', '\u200b') + .addField('**LIMITS (0 = unlimited)**', 'MEMORY: ' + response.data.attributes.limits.memory + 'MB \nDISK: ' + response.data.attributes.limits.disk + 'MB \nCPU: ' + response.data.attributes.limits.cpu) + .addField('**MISC LIMITS**', 'DATABASES: ' + response.data.attributes.feature_limits.databases + '\nBACKUPS: ' + response.data.attributes.feature_limits.backups) + message.reply(embedstatus) + })}); + } + } else if (args[0].toLowerCase() == "proxy") { + const embed = new Discord.RichEmbed() + .setTitle('__**How to link a domain to a website/server**__ \nCommand format: ' + config.DiscordBot.Prefix + 'server proxy domainhere serverid') + if (!args[1]) { + message.channel.send(embed) + } else { + if (!args[2]) { + message.channel.send(embed) + } else { + message.channel.send('Please give me a few seconds. Trying to link that domain!') + //SSH Connection + ssh.connect({ + host: config.SSH.Host, + username: config.SSH.User, + port: config.SSH.Port, + password: config.SSH.Password, + tryKeyboard: true, + }) + + //Copy template file. Ready to be changed! + fs.access(path.resolve(path.dirname(require.main.filename), "proxy/" + args[1].toLowerCase() + ".conf"), fs.constants.R_OK, (err) => { + if (!err) { + return message.channel.send("This domain has been linked before or is currently linked..") + } else { + fs.copyFile(path.resolve('./proxy/template.txt'), './proxy/' + args[1] + '.conf', (err) => { + if (err) { + console.log("Error Found:", err); + } + }) + fs.copyFile(path.resolve('./proxy/template.txt'), './proxy/' + args[1] + '.conf', (err) => { + if (err) { + console.log("Error Found:", err); + } + }) + + setTimeout(() => { + //Change Domain + var z = 0; + while (z <5) { + const domainchange = rif.sync({ + files: '/root/DBH/Panel/proxy/' + args[1] + '.conf', + from: "REPLACE-DOMAIN", + to: args[1].toLowerCase(), + countMatches: true, + }); + z++ + } + + //Grab node and port ready for the config + axios({ + url: config.Pterodactyl.hosturl + "/api/client/servers/" + args[2], + method: 'GET', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikeyclient, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + } + }).then(response => { + const node = response.data.attributes.node; + console.log(node) + const port = response.data.attributes.relationships.allocations.data[0].attributes.port + if (node === "Node 1") { + + //Change Server IP + setTimeout(() => { + var y = 0; + while (y <3) { + const ipchange = rif.sync({ + files: '/root/DBH/Panel/proxy/' + args[1] + '.conf', + from: "REPLACE-IP", + to: "154.27.68.232", + countMatches: true, + }); + y++ + }; + + //Change Server Port + setTimeout(() => { + var x = 0; + while (x <3) { + const portchange = rif.sync({ + files: '/root/DBH/Panel/proxy/' + args[1] + '.conf', + from: "REPLACE-PORT", + to: port, + countMatches: true, + }); + x++ + } + }, 100) //END - Change Server Port + }, 100) //END - Change Server IP + } else if (node === "Node 2") { + + //Change Server IP + setTimeout(() => { + var y = 0; + while (y <3) { + const ipchange = rif.sync({ + files: '/root/DBH/Panel/proxy/' + args[1] + '.conf', + from: "REPLACE-IP", + to: "154.27.68.233", + countMatches: true, + }); + y++ + }; + + //Change Server Port + setTimeout(() => { + var x = 0; + while (x <3) { + const portchange = rif.sync({ + files: '/root/DBH/Panel/proxy/' + args[1] + '.conf', + from: "REPLACE-PORT", + to: port, + countMatches: true, + }); + x++ + } + }, 100) //END - Change Server Port + }, 100) //END - Change Server IP + } else { + message.channel.send('Unsupported node. Stopping reverse proxy.') + fs.unlinkSync("./proxy/" + args[1] + ".conf"); + } + + + //Upload file to /etc/apache2/sites-available + setTimeout(() => { + ssh.putFile('/root/DBH/Panel/proxy/' + args[1] + '.conf', '/etc/apache2/sites-available/' + args[1] + ".conf").then(function() { + + //Run command to genate SSL cert. + ssh.execCommand(`certbot certonly -d ${args[1]} --non-interactive --webroot --webroot-path /var/www/html --agree-tos -m danielpd93@gmail.com`, { cwd:'/root' }).then(function(result) { + if (result.stdout.includes('Congratulations!')) { + //No error. Continue to enable site on apache2 then restart + console.log('SSL Gen complete. Continue!') + + ssh.execCommand(`a2ensite ${args[1]} && service apache2 restart`, { cwd:'/root' }).then(function(result) { + //Complete + message.reply('Domain has now been linked!') + + /* + domains.set(args[1], { + DiscordID: message.author.id, + ServerID: args[2], + Domain: args[1] + }); + */ + }) + } else { + message.channel.send('Error making SSL cert. Either the domain is not pointing to `154.27.68.234` or cloudflare proxy is enabled! \n\n**If you have just done this after running the command. Please give the bot 5 - 10mins to refresh the DNS cache** \n\nFull Error: ```' + result.stdout + '```') + fs.unlinkSync("./proxy/" + args[1] + ".conf"); + } + }) + }, function(error) { + //If error exists. Error and delete proxy file + fs.unlinkSync("./proxy/" + args[1] + ".conf"); + message.channel.send("FAILED \nERROR: " + error); + }) + }, 250) //END - Upload file to /etc/apache2/sites-available + }) //END - Grab server info (Node and Port) + }, 250) //END - //Change Domain + } + }) + } + } + } else if (args[0].toLowerCase() == "unproxy") { + if (message.author.id == "137624084572798976") { + if (!args[1]) { + const embed = new Discord.RichEmbed() + .setTitle('__**How to remove a domain from a server**__ \nCommand format: ' + config.DiscordBot.Prefix + 'server unproxy domainhere') + message.channel.send(embed) + } else { + + //SSH Connection + ssh.connect({ + host: config.SSH.Host, + username: config.SSH.User, + port: config.SSH.Port, + password: config.SSH.Password, + tryKeyboard: true, + }) + + //Delete file from apache2 dir + ssh.execCommand('a2dissite ' + args[1] + ' && rm /etc/apache2/sites-available/' + args[1] + '.conf && rm -rf /etc/letsencrypt/live/' + args[1] + ' && rm -rf /etc/letsencrypt/archive' + args[1] + '&& service apache2 restart', { cwd:'/root' }) + fs.unlinkSync("./proxy/" + args[1] + ".conf"); + message.channel.send('Proxy has been removed from ' + args[1]) + } + } else { + message.channel.send('command temp disabled') + } + } + } +}; diff --git a/Panel/bot/discord/commands/staff.js b/Panel/bot/discord/commands/staff.js new file mode 100644 index 000000000..7a54b5f44 --- /dev/null +++ b/Panel/bot/discord/commands/staff.js @@ -0,0 +1,137 @@ +//const {config} = require('process'); + +const exec = require('child_process').exec; +exports.run = async (client, message, args) => { + if (!message.member.roles.find(r => r.id == "748117822370086932")) return; + + if (args[0] == null) { + if (message.member.roles.find(r => r.id == "639489438036000769")) { + let embed = new Discord.RichEmbed() + .setColor('RANDOM') + .addField('**Staff Commands:**', config.DiscordBot.Prefix + "staff linked useridhere | Shows if the users account is linked.") + .addField('**Admin Commands:**', config.DiscordBot.Prefix + "staff apply open/close | Open or close staff applications. \n" + config.DiscordBot.Prefix + "staff settings | Shows current website settings") + .addField('**Owner Commands:**', config.DiscordBot.Prefix + "staff maintenance on/off | Enable or disable website maintenance. \n" + config.DiscordBot.Prefix + "staff update | Pulls updates from GitHub") + message.channel.send(embed) + } else { + let embed = new Discord.RichEmbed() + .setColor('RANDOM') + .addField('**Staff Commands:**', config.DiscordBot.Prefix + "staff linked useridhere | Shows if the users account is linked.") + message.channel.send(embed) + } + return; + } + + switch (args[0].toLowerCase()) { + case 'linked': + if (args[1] == null) { + message.channel.send('Please send a users discord ID to see if they are linked with an account on the host.') + } else { + if (userData.get(args[1]) == null) { + message.channel.send("That account is not linked with a console account :sad:") + } else { + console.log(userData.fetch(args[1])) + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Username**__`, userData.fetch(args[1] + ".username")) + .addField(`__**Email**__`, userData.fetch(args[1] + ".email")) + .addField(`__**Discord ID**__`, userData.fetch(args[1] + ".discordID")) + .addField(`__**Console ID**__`, userData.fetch(args[1] + ".consoleID")) + .addField(`__**Date (YYYY/MM/DD)**__`, userData.fetch(args[1] + ".linkDate")) + .addField(`__**Time**__`, userData.fetch(args[1] + ".linkTime")) + message.channel.send('That account is linked. Heres some data: ', embed) + } + } + break; + + case 'apply': + if (args[1] == null) { + message.channel.send("Please run the command using the following format: `" + config.DiscordBot.Prefix + "staff apply open/close` to enable or disable staff applications") + } else { + if (args[1] == "open") { + webSettings.set("staff-applications", { + enabled: "true" + }); + message.channel.send("Staff applications now open") + } else if (args[1] == "close") { + webSettings.set("staff-applications", { + enabled: "false" + }); + message.channel.send("Staff applications now closed") + } else { + if (webSettings.fetch("staff-applications.enabled") == "true") { + message.channel.send("Please run the command using the following format: `" + config.DiscordBot.Prefix + "staff apply open/close` to enable or disable staff applications \n**Staff applications are currently:** **OPEN**"); + } else if (webSettings.fetch("staff-applications.enabled") == "false") { + message.channel.send("Please run the command using the following format: `" + config.DiscordBot.Prefix + "staff apply open/close` to enable or disable staff applications \n**Staff applications are currently:** **CLOSED**"); + } + }; + }; + break; + + case 'settings': + if (message.member.roles.find(r => r.id === "639489438036000769")) { + let embed = new Discord.RichEmbed() + .addField('__**Staff Applications Enabled?**__', webSettings.fetch("staff-applications.enabled"), true) + .addField('__**Website maintenance enabled?**__', webSettings.fetch("maintenance.enabled"), true) + message.channel.send(embed) + }; + break; + case 'request': + if (args[1] === "new") { + if (args[2] === "proxy") { + //Type: Proxy + } + //New request + message.channel.send('Please use the following format: `' + config.DiscordBot.Prefix + "staff request type userid serverid` \nYou can view types by running: `" + config.DiscordBot.Prefix + "staff request types`") + } else if (args[1] === "types") { + //Types + let embed = new Discord.RichEmbed() + .addField('__**Request Types (Type | Type Meaning):**__', "`proxy` | Reverse Proxy \n`password` | Password reset \n`server` | Server creation (If not on createserver) \n`delete` | Server Deletion") + message.channel.send(embed) + } else if (args[1] === "delete") { + //Delete request + } + break; + case 'reactionroles': + let reactionRoles = require('../reactionRoles'); + client.reactionRoles = reactionRoles; + + let reactionRolesChannels = Object.keys(reactionRoles); + reactionRolesChannels.forEach(c => { + let rchannel = client.channels.get(c); + let reactionRolesChannelMessages = Object.keys(reactionRoles[c]); + + reactionRolesChannelMessages.forEach(async m => { + let rmessage = await rchannel.fetchMessage(m); + let reactions = Object.keys(reactionRoles[c][m]); + await rmessage.clearReactions(); + + for (let ri in reactions) { + let reaction = reactions[ri]; + if (reaction.length == 18) reaction = client.emojis.get(reaction); + await rmessage.react(reaction); + } + }); + }) + break; + case 'update': + if (message.member.roles.find(r => r.id === "639481606112804875") || message.author.id == '293841631583535106') { + exec(`git pull`, (error, stdout) => { + let response = (error || stdout); + if (!error) { + if (response.includes("Already up to date.")) { + message.channel.send('Bot already up to date. No changes since last pull') + } else { + message.channel.send('Pulled from GitHub. Restarting bot. \n\nLogs: \n```' + response + "```") + setTimeout(() => { + process.exit(); + }, 1000) + }; + } + }); + } else { + message.channel.send('OwO') + } + break; + } + +} \ No newline at end of file diff --git a/Panel/bot/discord/commands/stats.js b/Panel/bot/discord/commands/stats.js new file mode 100644 index 000000000..767a3c4ce --- /dev/null +++ b/Panel/bot/discord/commands/stats.js @@ -0,0 +1,20 @@ +exports.run = async(client, message) => { + + //Sends message while the json's are being cached + let embed = new Discord.RichEmbed() + .setColor(`RANDOM`) + .addField(`__**Please wait...**__`, `Loading all node's stats! (If this takes longer than 5seconds. This command is broken)`, true); + let msg = await message.channel.send(embed) + + //Edits the message to display the data + embed.fields.pop() + embed.addField("\u200b", "__**[Node 1 - Discord Bots](https://danbot.host/Node1)**__ \n**CPU LOAD**: " + nodeData.fetch("Node1.cpuload") + "% \n**RAM (USED/TOTAL)**: " + nodeData.fetch("Node1.memused") + " / " + nodeData.fetch("Node1.memtotal") + " \n**STORAGE (USED/TOTAL)**: " + nodeData.fetch("Node1.diskused") + " / " + nodeData.fetch("Node1.disktotal") + " \n**UPTIME**: " + nodeData.fetch("Node1.osuptime") + "\n**Servers:** **Total**: " + nodeData.fetch("Node1.dockercontainers") + ", **Running**: " + nodeData.fetch("Node1.dockercontainersrunning") + ", **Stopped**: " + nodeData.fetch("Node1.dockercontainersstopped")) + embed.addField('\u200b', '\u200b') + embed.addField("\u200b", "__**[Node 2 - Discord Bots](https://danbot.host/Node2)**__ \n**CPU LOAD**: " + nodeData.fetch("Node2.cpuload") + "% \n**RAM (USED/TOTAL)**: " + nodeData.fetch("Node2.memused") + " / " + nodeData.fetch("Node2.memtotal") + " \n**STORAGE (USED/TOTAL)**: " + nodeData.fetch("Node2.diskused") + " / " + nodeData.fetch("Node2.disktotal") + " \n**UPTIME**: " + nodeData.fetch("Node2.osuptime") + "\n**Servers**: **Total**: " + nodeData.fetch("Node2.dockercontainers") + ", **Running**: " + nodeData.fetch("Node2.dockercontainersrunning") + ", **Stopped**: " + nodeData.fetch("Node2.dockercontainersstopped")) + embed.addField('\u200b', '\u200b') + embed.addField("\u200b", "__**[Node 3 - Gaming](https://danbot.host/Node3)**__ \n**CPU LOAD**: " + nodeData.fetch("Node3.cpuload") + "% \n**RAM (USED/TOTAL)**: " + nodeData.fetch("Node3.memused") + " / " + nodeData.fetch("Node3.memtotal") + " \n**STORAGE (USED/TOTAL)**: " + nodeData.fetch("Node3.diskused") + " / " + nodeData.fetch("Node3.disktotal") + " \n**UPTIME**: " + nodeData.fetch("Node3.osuptime") + "\n**Servers**: **Total**: " + nodeData.fetch("Node3.dockercontainers") + ", **Running**: " + nodeData.fetch("Node3.dockercontainersrunning") + ", **Stopped**: " + nodeData.fetch("Node3.dockercontainersstopped")) + embed.addField('\u200b', '\u200b') + embed.addField("\u200b", "__**[Node 4 - Test](https://danbot.host/Node4)**__ \n**CPU LOAD**: " + nodeData.fetch("Node4.cpuload") + "% \n**RAM (USED/TOTAL)**: " + nodeData.fetch("Node4.memused") + " / " + nodeData.fetch("Node4.memtotal") + " \n**STORAGE (USED/TOTAL)**: " + nodeData.fetch("Node4.diskused") + " / " + nodeData.fetch("Node4.disktotal") + " \n**UPTIME**: " + nodeData.fetch("Node4.osuptime") + "\n**Servers**: **Total**: " + nodeData.fetch("Node4.dockercontainers") + ", **Running**: " + nodeData.fetch("Node4.dockercontainersrunning") + ", **Stopped**: " + nodeData.fetch("Node4.dockercontainersstopped")) + embed.setDescription('Want to view more stats live? [Click Here!](https://danbot.host/stats)') + msg.edit(embed); +}; \ No newline at end of file diff --git a/Panel/bot/discord/commands/suggest.js b/Panel/bot/discord/commands/suggest.js new file mode 100644 index 000000000..a2f9997d5 --- /dev/null +++ b/Panel/bot/discord/commands/suggest.js @@ -0,0 +1,12 @@ +let db = require("quick.db"); +const Discord = require("discord.js"); + +exports.run = async (client, message, args) => { + +let embed = new Discord.RichEmbed() +.setColor("BLUE") +.setTitle("DanBot Hosting Suggestion") +.setDescription("To send in Suggestions and or Feedback please visit our Feedback form [Here](https://stats.danbot.xyz/feedback)") +message.channel.send(embed) + +}; \ No newline at end of file diff --git a/Panel/bot/discord/commands/ticket.js b/Panel/bot/discord/commands/ticket.js new file mode 100644 index 000000000..a8c6a938d --- /dev/null +++ b/Panel/bot/discord/commands/ticket.js @@ -0,0 +1,130 @@ +exports.run = async (client, message) => { + const args = message.content.split(' ').slice(1).join(' '); + const user = message.content.split(' ').slice(2).join(' '); + + if (args == "") { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Tickets**__`, 'You can create a new ticket by typing: `' + + config.DiscordBot.Prefix + 'ticket new` \nYou can download your old tickets by running: `' + + config.DiscordBot.Prefix + 'ticket logs` \nYou can close your ticket by running: `' + + config.DiscordBot.Prefix + 'ticket close` \nYou can upgrade your ticket by running:`' + + config.DiscordBot.Prefix + 'ticket upgrade` \n\nAny problems? Please send a message in <#739231758087880845> and someone will help you.' , true); + message.channel.send(embed) + + } else if (args == "new") { + const server = message.guild + + let channel = await server.createChannel(message.author.username + "-Ticket", "text", [{ + type: 'role', + id: message.guild.id, + deny: 0x400 + }, + { + type: 'user', + id: message.author.id, + deny: 1024 + }, + { + type: "role", + id: "748117822370086932", + allow: 84992 + } + ]).catch(console.error); + message.reply(`Please check <#${channel.id}> for your ticket.`) + + let category = server.channels.find(c => c.id == "738538742603841650" && c.type == "category"); + if (!category) throw new Error("Category channel does not exist"); + + let categorybackup = server.channels.find(c => c.id == "741082659610034257" && c.type == "category"); + if (!categorybackup) throw new Error("Category channel does not exist"); + + await channel.setParent(category.id).catch(channel.setParent(categorybackup.id).catch(console.error)); + + setTimeout(() => { + channel.overwritePermissions(message.author, { + VIEW_CHANNEL: true, + SEND_MESSAGES: true, + READ_MESSAGE_HISTORY: true + }) + + }, 1000) + + if (userData.get(message.author.id) == null) { + channel.send('<@' + message.author.id + '> here is your ticket! Please give as much info as possible about your problem. \n\n *This account is not linked with a console account*') + } else { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Username**__`, userData.fetch(message.author.id + ".username")) + .addField(`__**Email**__`, userData.fetch(message.author.id + ".email")) + .addField(`__**Date (YYYY/MM/DD)**__`, userData.fetch(message.author.id + ".linkDate")) + .addField(`__**Time**__`, userData.fetch(message.author.id + ".linkTime")) + channel.send('<@' + message.author.id + '> here is your ticket! Please give as much info as possible about your problem. \n\n *This account is linked with:* ', embed) + } + } else if (args == "close") { + if (message.channel.name.includes('-ticket')) { + const filter2 = m => m.author.id === message.author.id; + const warning = await message.channel.send('<@' + message.author.id + '> are you sure you want to close this ticket? please type `confirm` to close the ticket or `cancel` to keep the ticket open.') + + let collected1 = await message.channel.awaitMessages(filter2, { + max: 1, + time: 30000, + errors: ['time'], + }).catch(x => { + warning.delete() + message.channel.send(`ERROR: User failed to provide an answer. Ticket staying open.`); + setTimeout(() => { + message.channel.delete(); + }, 3000); + return false; + }) + + if (collected1.first().content === 'confirm') { + return message.channel.send("**Closing ticket.**", null).then(setTimeout(() => { + message.channel.delete() + }, 5000)) + } else if (collected1.first().content === 'cancel') { + return message.channel.send('Closing ticket. __**Canceled**__ Ticket staying open.'); + } + } else if (!message.channel.name.includes('-ticket')) { + message.channel.send('ERROR: You can only use this command in ticket channels.') + + } + } else if (args == "add") { + if (message.channel.name.includes('-ticket')) { + if (!args[1] == "") { + message.channel.send('Please run this command again with the users ID') + } else { + console.log(args[1]) + message.channel.overwritePermissions(args[1], { + VIEW_CHANNEL: true, + SEND_MESSAGES: true, + READ_MESSAGE_HISTORY: true + }) + } + } else { + message.channel.send('This command is only to be used inside of ticket channels.') + } + } else if (args == "upgrade") { + if (message.channel.name.includes('-ticket')) { + message.reply("Only admins can see this ticket now.") + message.channel.overwritePermissions("748117822370086932", { + VIEW_CHANNEL: false, + SEND_MESSAGES: false, + READ_MESSAGE_HISTORY: false + }) + } else { + message.channel.send('This command is only to be used inside of ticket channels.') + } + } else if (args == "remove") { + if (!args[1] == "") { + message.channel.send('Please run this command again with the users ID') + } else { + message.channel.overwritePermissions(args[1], { + VIEW_CHANNEL: false, + SEND_MESSAGES: false, + READ_MESSAGE_HISTORY: false + }) + } + } +}; diff --git a/Panel/bot/discord/commands/uptime.js b/Panel/bot/discord/commands/uptime.js new file mode 100644 index 000000000..40a44e9c5 --- /dev/null +++ b/Panel/bot/discord/commands/uptime.js @@ -0,0 +1,52 @@ +exports.run = async(client, message, args) => { + + var getUptime = function(millis) { + var dur = {}; + var units = [{ + label: "milliseconds", + mod: 1000 + }, + { + label: "seconds", + mod: 60 + }, + { + label: "minutes", + mod: 60 + }, + { + label: "hours", + mod: 24 + }, + { + label: "days", + mod: 31 + } + ]; + + units.forEach(function(u) { + millis = (millis - (dur[u.label] = (millis % u.mod))) / u.mod; + }); + + var nonZero = function(u) { + return dur[u.label]; + }; + dur.toString = function() { + return units + .reverse() + .filter(nonZero) + .map(function(u) { + return dur[u.label] + " " + (dur[u.label] == 1 ? u.label.slice(0, -1) : u.label); + }) + .join(', '); + }; + return dur; + }; + +let myDate = new Date(client.readyTimestamp); + var embed = new Discord.RichEmbed() + .addField(":white_check_mark: Uptime:", `**${getUptime(client.uptime)}**`) + .setFooter(`Ready Timestamp: ${myDate.toString()}`) + .setColor("GREEN") + message.channel.send(embed); + } \ No newline at end of file diff --git a/Panel/bot/discord/commands/user.js b/Panel/bot/discord/commands/user.js new file mode 100644 index 000000000..759c8e131 --- /dev/null +++ b/Panel/bot/discord/commands/user.js @@ -0,0 +1,402 @@ +const axios = require("axios"); +var validator = require('validator'); +exports.run = async(client, message, args) => { + + //Random password gen + var CAPSNUM = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + let getPassword = () => { + + var password = ""; + while (password.length < 10) { + password += CAPSNUM[Math.floor(Math.random() * CAPSNUM.length)]; + } + return password; + }; + + + if (!args[0]) { + //No args, Help + const embed = new Discord.RichEmbed() + .setTitle("__**Commands**__ \n`" + config.DiscordBot.Prefix + "user new` | Create an account \n`" + config.DiscordBot.Prefix + "user password` | Reset account password \n`" + config.DiscordBot.Prefix + "user link` | Link this account with console account \n`" + config.DiscordBot.Prefix + "user unlink` | Unlinks account from the console account") + message.channel.send(embed) + } else if (args[0].toLowerCase() == "new") { + if (userData.get(message.author.id) == null) { + const server = message.guild + + let channel = await server.createChannel(message.author.tag, "text", [{ + type: 'role', + id: message.guild.id, + deny: 0x400 + }, + { + type: 'user', + id: message.author.id, + deny: 1024 + } + ]).catch(console.error); + message.reply(`Please check <#${channel.id}> to create an account.`) + + let category = server.channels.find(c => c.id == settings.fetch("accountcategory.id") && c.type == "category"); + if (!category) throw new Error("Category channel does not exist"); + + await channel.setParent(category.id); + + channel.overwritePermissions(message.author, { + VIEW_CHANNEL: true, + SEND_MESSAGES: true, + READ_MESSAGE_HISTORY: true + }) + + + const filter2 = m => m.author.id === message.author.id; + + let msg = await channel.send("<@" + message.author.id + ">", { + embed: new Discord.RichEmbed() + .setColor(0x36393e) + .setDescription("Please enter a username (**Please dont use spaces**)") + .setFooter("You can type 'cancel' to cancel the request") + }) + + //First Collection "UserName" + + let collected1 = await channel.awaitMessages(filter2, { + max: 1, + time: 30000, + errors: ['time'], + }).catch(x => { + msg.delete() + channel.send(`ERROR: User failed to provide an answer.`); + setTimeout(() => { + channel.delete(); + }, 3000); + return false; + }) + + if (collected1.first().content === 'cancel') { + return msg.edit("Request to create a new user has been canceled!", null).then(channel.delete()) + } + + await msg.edit("", { + embed: new Discord.RichEmbed() + .setColor(0x36393e) + .setDescription(`Username: **${collected1.first().content}** \nPlease enter a Email.`) + .setFooter("You can type 'cancel' to cancel the request") + }) + collected1.first().delete(); + + //scnd Collection "Email" + + let collected2 = await channel.awaitMessages(filter2, { + max: 1, + time: 30000, + errors: ['time'], + }).catch(x => { + msg.delete() + channel.send(`ERROR: User failed to provide an answer.`); + setTimeout(() => { + channel.delete(); + }, 3000); + return false; + }) + + + if (!validator.isEmail(collected2.first().content.trim())) { + msg.delete() + channel.send(`\`${collected2.first().content.trim()}`+"` is not a Valid Email!"); + setTimeout(() => { + channel.delete(); + }, 10000); + return false; + } + collected2.first().delete(); + + let password = await getPassword(); + + const data = { + "username": collected1.first().content, + "email": collected2.first().content, + "first_name": collected1.first().content, + "last_name": ".", + "password": password, + "root_admin": false, + "language": "en" + } + axios({ + url: config.Pterodactyl.hosturl + "/api/application/users", + method: 'POST', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(user=> { + + console.log(user) + + const timestamp = `${moment().format("HH:mm:ss")}`; + const datestamp = `${moment().format("YYYY-MM-DD")}`; + + userData.set(`${message.author.id}`, { + discordID: message.author.id, + consoleID: user.data.attributes.id, + email: user.data.attributes.email, + username: user.data.attributes.username, + linkTime: timestamp, + linkDate: datestamp + }) + + if (user == "Error: User already exists! (Or Email/Username is in use already)") { + msg.edit("ERROR: A user with that email/username already exists.", null) + setTimeout(function () { + channel.delete(); + }, 10000); + return false; + } + msg.edit("Hello! You created an new account, Heres the login information", { + embed: new Discord.RichEmbed() + .setColor(0x36393e) + .setDescription("URL: " + config.Pterodactyl.hosturl + " \nUsername: " + collected1.first().content + " \nEmail: " + collected2.first().content + " \nPassword: " + password) + .setFooter("Please note: It is recommended that you change the password") + }) + channel.send('**You have 30mins to keep note of this info before the channel is deleted.**') + message.guild.members.get(message.author.id).addRole("639489891016638496"); + setTimeout(function () { + channel.delete(); + }, 1800000); + + }).catch(err => { + if (err = "Error: User already exists! (Or Email/Username is in use already)") { + msg.edit("ERROR: A user with that email/username already exists.", null) + setTimeout(function () { + channel.delete(); + }, 10000); + } + }) + } + } else if (args[0].toLowerCase() == "password") { + //Password reset + let password = await getPassword(); + axios({ + url: config.Pterodactyl.hosturl + "/api/application/users/" + userData.get(message.author.id).consoleID, + method: 'GET', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + }).then(fetch => { + console.log(fetch.data.attributes) + const data = { + "email": fetch.data.attributes.email, + "username": fetch.data.attributes.username, + "first_name": fetch.data.attributes.first_name, + "last_name": fetch.data.attributes.last_name, + "password": password + } + axios({ + url: config.Pterodactyl.hosturl + "/api/application/users/" + userData.get(message.author.id).consoleID, + method: 'PATCH', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + }, + data: data, + }).then(user=> { + message.channel.send('The console account that is linked with the discord account has now been reset. Please check dms for the password. \nA email will also be sent containing the new password') + client.users.get(message.author.id).send(`New password for DanBot Hosting: ||**${data.password}**||`) + + const emailmessage = { + from: config.Email.From, + to: messagecollected.content, + subject: 'DanBot Hosting - Password reset via bot', + html: "Hello, the console account password for email: " + userData.get(message.author.id).email + " was just reset. here is the new password" + data.password + }; + transport.sendMail(emailmessage); + }).catch(err => { + message.channel.send(err) + }) + }) + + } else if (args[0].toLowerCase() == "link") { + //Link account + if (userData.get(message.author.id) == null) { + + const server = message.guild + + let channel = await server.createChannel(message.author.tag, "text", [{ + type: 'role', + id: message.guild.id, + deny: 0x400 + }, + { + type: 'user', + id: message.author.id, + deny: 1024 + } + ]).catch(console.error); + message.reply(`Please check <#${channel.id}> to link your account.`) + + let category = server.channels.find(c => c.id == "738539016688894024" && c.type == "category"); + if (!category) throw new Error("Category channel does not exist"); + + await channel.setParent(category.id); + + channel.overwritePermissions(message.author, { + VIEW_CHANNEL: true, + SEND_MESSAGES: true, + READ_MESSAGE_HISTORY: true + }) + + + + let msg = await channel.send(message.author, { + embed: new Discord.RichEmbed() + .setColor(0x36393e) + .setDescription("Please enter your console email address") + .setFooter("You can type 'cancel' to cancel the request \n**This will take a few seconds to find your account.**") + }) + + const collector = new Discord.MessageCollector(channel, m => m.author.id === message.author.id, { time: 60000, max: 1 }); + collector.on('collect', messagecollected => { + //console.log(message.content) + + if (messagecollected.content === 'cancel') { + return msg.edit("Request to link your account canceled.", null).then(channel.delete()) + } + + const axios = require('axios'); + var arr = []; + + axios({ + url: "https://panel.danbot.host" + "/api/application/users", + method: 'GET', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + } + }).then(resources => { + var countmax = resources.data.meta.pagination.total_pages + var i2 = countmax++ + + var i = 0 + while (i m.author.id === message.author.id, { time: 120000, max: 2 }); + collector.on('collect', message => { + if (message.content == code) { + const timestamp = `${moment().format("HH:mm:ss")}`; + const datestamp = `${moment().format("YYYY-MM-DD")}`; + userData.set(`${message.author.id}`, { + discordID: message.author.id, + consoleID: consoleUser.attributes.id, + email: consoleUser.attributes.email, + username: consoleUser.attributes.username, + linkTime: timestamp, + linkDate: datestamp + }); + + let embedstaff = new Discord.RichEmbed() + .setColor('Green') + .addField('__**Linked Discord account:**__', message.author.id) + .addField('__**Linked Console account email:**__', consoleUser.attributes.email) + .addField('__**Linked At: (TIME / DATE)**__', timestamp + " / " + datestamp) + .addField('__**Linked Console username:**__', consoleUser.attributes.username) + .addField('__**Linked Console ID:**__', consoleUser.attributes.id) + + channel.send("Account linked!").then( + client.channels.get(config.DiscordBot.oLogs).send(`<@${message.author.id}> linked their account. Heres some info: `, embedstaff), + setTimeout(() => { + channel.delete(); + }, 5000) + ); + } else { + channel.send('Code is incorrect. Linking cancelled! \n\nRemoving channel!') + setTimeout(() => { + channel.delete(); + }, 2000) + } + }); + } + }); + + }; + }, 12000) + + }) + } else { + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`__**Username**__`, userData.fetch(message.author.id + ".username")) + .addField(`__**Linked Date (DD/MM/YY)**__`, userData.fetch(message.author.id + ".linkDate")) + .addField(`__**Linked Time**__`, userData.fetch(message.author.id + ".linkTime")) + message.channel.send("This account is linked!", embed) + } + } else if (args[0].toLowerCase() == "unlink") { + userData.delete(message.author.id) + message.channel.send('You have unlinked this account!') + } + }; \ No newline at end of file diff --git a/Panel/bot/discord/commands/vc.js b/Panel/bot/discord/commands/vc.js new file mode 100644 index 000000000..c8ef58899 --- /dev/null +++ b/Panel/bot/discord/commands/vc.js @@ -0,0 +1,55 @@ +exports.run = async (client, message, args) => { + if (args.length < 2) { + message.channel.send("usage: `DBH!vc < <@user | userID>`") + } + + if (args[0].toLowerCase() == "add") { + if (client.pvc.get(message.member.voiceChannelID) && client.pvc.get(message.member.voiceChannelID).owner == message.member.id) { + let member = message.guild.members.get(args[1].match(/[0-9]{18}/)[0]) + + if (member == null) { + message.reply("Couldn't find that user.") + return; + } + + message.member.voiceChannel.overwritePermissions(member, { + CONNECT: true, + VIEW_CHANNEL: true, + STREAM: true, + SPEAK: true + }); + + message.reply("successfully added **" + member.user.username + "** to the Voice Channel.") + + } else { + message.reply("You must be in a channel that you own in order to use this command.") + } + } + if (args[0].toLowerCase() == "remove") { + if (client.pvc.get(message.member.voiceChannelID) && client.pvc.get(message.member.voiceChannelID).owner == message.member.id) { + + let member = message.guild.members.get(args[1].match(/[0-9]{18}/)[0]) + + if (member == null) { + message.reply("Couldn't find that user.") + return; + } + + if (member.hasPermission("ADMINISTRATOR")) { + message.reply("can't remove **" + member.user.username + "** from the Voice Channel.") + return; + } + + message.member.voiceChannel.overwritePermissions(member, { + CONNECT: false, + VIEW_CHANNEL: false + }); + member.setVoiceChannel(null); + message.reply("successfully removed **" + member.user.username + "** from the Voice Channel.") + + + } else { + message.reply("You must be in a channel that you own in order to use this command.") + } + } +} \ No newline at end of file diff --git a/Panel/bot/discord/events/guildMemberAdd.js b/Panel/bot/discord/events/guildMemberAdd.js new file mode 100644 index 000000000..68fa5312f --- /dev/null +++ b/Panel/bot/discord/events/guildMemberAdd.js @@ -0,0 +1,134 @@ +const config2 = { + "welcome": "738527858594414663", + "inviterewmsg": "738527858594414663", + "invite5": "704650026076602449", + "invite10": "704650153797091418", + "invite25": "704650197732556891", + "invite50": "704650269182394398", + "invite100": "766873791103238155", + "invite150": "766873898024828949", + "invite200": "766873967561539634", + "invitechannel": "738536628376698981", + "member": "639490038434103306", + "bot": "704467807122882562" +} + +const Canvas = require("canvas"); +const db = require("quick.db"); +module.exports = async(client, member, guild) => { + + var getAge = function(millis) { + var dur = {}; + var units = [{ + label: "milliseconds", + mod: 1000 + }, + { + label: "seconds", + mod: 60 + }, + { + label: "minutes", + mod: 60 + }, + { + label: "hours", + mod: 24 + }, + { + label: "days", + mod: 31 + } + ]; + + units.forEach(function(u) { + millis = (millis - (dur[u.label] = (millis % u.mod))) / u.mod; + }); + + var nonZero = function(u) { + return dur[u.label]; + }; + dur.toString = function() { + return units + .reverse() + .filter(nonZero) + .map(function(u) { + return dur[u.label] + " " + (dur[u.label] == 1 ? u.label.slice(0, -1) : u.label); + }) + .join(', '); + }; + return dur; + }; + + if (Date.now() - member.user.createdAt < 863136000) { + member.kick().then(memberkicked => { + client.channels.get('738527858594414663').send(member.user.tag + ` has been auto-kicked as account is under 10days old \nThat account was created ${getAge(Date.now() - member.user.createdAt)}, ago`) + client.users.get(member.user.id).send('Sorry! We only allow accounts over the age of 10days to join. \nYou\'r account is ' + getAge(Date.now() - member.user.createdAt) + ", ago. \n\nYou are welcome to join again once this account is over 10days old!") + }); + } + + if(member.user.bot) { + let botID = member.user.id; + let bot = db.get(`${botID}`); + if(!bot) { + client.channels.get(config2.welcome).send("Bot: <@" + member.user.id + ">, tried to join but is not using our API.") + member.kick(); + } else { + const botrole = member.guild.roles.find(role => role.id === config2.bot); + member.guild.members.get(member.user.id).addRole(botrole); + client.channels.get(config2.welcome).send("Welcome <@" + member.user.id + ">, More bot friends :D \nBot owned by: <@" + bot.owner + ">"); + } + } else { + if (userData.get(member.user.id) == null) { + const memberrole = member.guild.roles.find(role => role.id === config2.member); + member.guild.members.get(member.user.id).addRole(memberrole) + client.channels.get(config2.welcome).send("Welcome <@" + member.user.id + "> to DanBot Hosting. To get started please read <#738527470164377630>"); + } else { + const memberrole = member.guild.roles.find(role => role.id === config2.member); + const clientrole = member.guild.roles.find(role => role.id === "639489891016638496"); + member.guild.members.get(member.user.id).addRole(memberrole) + member.guild.members.get(member.user.id).addRole(clientrole) + client.channels.get(config2.welcome).send("Welcome back <@" + member.user.id + "> to DanBot Hosting!"); + } + + if(mutesData.fetch(member.user.id + ".muted") === "true") { + let muteRole = client.guilds.get(member.guild.id).roles.find(r => r.id == "726829710935457872"); + member.guild.members.get(member.user.id).addRole(muteRole) + } + + member.guild.fetchInvites().then(guildInvites => { + const ei = invites[member.guild.id]; + invites[member.guild.id] = guildInvites; + const invite = guildInvites.find(i => ei.get(i.code).uses < i.uses); + const inviter = client.users.get(invite.inviter.id); + let embed = new Discord.RichEmbed() + .setColor(`GREEN`) + .addField(`New Members Username:`, member.user.tag, true) + .addField(`New Members ID:`, '`' + member.user.id + '`', true) + .addField('Account created:', member.user.createdAt.toDateString(), true) + .addField("Members Status", member.user.presence !== null && member.user.presence.status !== null ? member.user.presence.status : "Offline") + .addField('\u200b', '\u200b') + .addField(`Invited by:`, inviter.tag, true) + .addField(`Inviter's ID:`, '`' + inviter.id + '`', true) + .addField(`Invite code used:`, '`' + invite.code + '`', true) + .addField(`Invite used`, invite.uses + ' times', true); + client.channels.get(config2.invitechannel).send(embed) + const invite5 = member.guild.roles.find(role => role.id === config2.invite5); + const invite10 = member.guild.roles.find(role => role.id === config2.invite10); + const invite25 = member.guild.roles.find(role => role.id === config2.invite25); + const invite50 = member.guild.roles.find(role => role.id === config2.invite50); + const invite100 = member.guild.roles.find(role => role.id === config2.invite100); + const invite150 = member.guild.roles.find(role => role.id === config2.invite150); + const invite200 = member.guild.roles.find(role => role.id === config2.invite200); + if (invite.uses == 5) return member.guild.members.get(inviter.id).addRole(invite5), client.channels.get(config2.inviterewmsg).send(`<@${inviter.id}> just hit 5 invites! Here's a role for you :)`); + if (invite.uses == 10) return member.guild.members.get(inviter.id).removeRole(invite5), member.guild.members.get(inviter.id).addRole(invite10), client.channels.get(config2.inviterewmsg).send(`<@${inviter.id}> just hit 10 invites! Here's a role for you :)`); + if (invite.uses == 25) return member.guild.members.get(inviter.id).removeRole(invite10), member.guild.members.get(inviter.id).addRole(invite25), client.channels.get(config2.inviterewmsg).send(`<@${inviter.id}> just hit 25 invites! Here's a role for you :)`); + if (invite.uses == 50) return member.guild.members.get(inviter.id).removeRole(invite25), member.guild.members.get(inviter.id).addRole(invite50), client.channels.get(config2.inviterewmsg).send(`<@${inviter.id}> just hit 50 invites! Here's a role for you :)`); + if (invite.uses == 100) return member.guild.members.get(inviter.id).removeRole(invite50), member.guild.members.get(inviter.id).addRole(invite100), client.channels.get(config2.inviterewmsg).send(`<@${inviter.id}> just hit 100 invites! Here's a role for you :)`);; + if (invite.uses == 150) return member.guild.members.get(inviter.id).removeRole(invite100), member.guild.members.get(inviter.id).addRole(invite150), client.channels.get(config2.inviterewmsg).send(`<@${inviter.id}> just hit 150 invites! Here's a role for you :)`);; + if (invite.uses == 200) return member.guild.members.get(inviter.id).removeRole(invite150), member.guild.members.get(inviter.id).addRole(invite200), client.channels.get(config2.inviterewmsg).send(`<@${inviter.id}> just hit 200 invites! Here's a role for you :)`);; + }); + + + } +}; \ No newline at end of file diff --git a/Panel/bot/discord/events/guildMemberUpdate.js b/Panel/bot/discord/events/guildMemberUpdate.js new file mode 100644 index 000000000..f023d8192 --- /dev/null +++ b/Panel/bot/discord/events/guildMemberUpdate.js @@ -0,0 +1,44 @@ +module.exports = async (client, oldMember, newMember) => { + // If user nickname changes. + if (oldMember.nickname !== newMember.nickname) { + + // Make local vars + var oldName = oldMember.nickname; + var newName = newMember.nickname; + + // If no set nickname, use the user's username. + if (oldMember.nickname === null) { + oldName = oldMember.user.username; + } + if (newMember.nickname === null) { + newName = newMember.user.username; + } + const a = "\u200B"; + if (newName.includes(" ឵឵")) { + oldMember.setNickname('') + } else if (newName.includes("͔")) { + oldMember.setNickname("") + } else if (newName.includes(" ឵឵")) { + oldMember.setNickname("") + } else if (newName.includes(a)) { + oldMember.setNickname("") + } else if (newName.includes("!")) { + oldMember.setNickname("I'm a furry OwO") + } + + // Make a new RichEmbed + const embed = new Discord.RichEmbed() + .setTitle("User Nickname changed.") + .setThumbnail(`${oldMember.user.displayAvatarURL}`) + .setDescription(`User: ${oldMember.user} Nickname has changed.`) + .addField("Old Nickname", oldName, true) + .addField("New Nickname", newName, true) + .setColor(0xFF7700) + .setTimestamp(new Date()); + + //oldMember.setNickname('') + client.channels.get(config.DiscordBot.oLogs).send(embed) + + return; + } +}; \ No newline at end of file diff --git a/Panel/bot/discord/events/message.js b/Panel/bot/discord/events/message.js new file mode 100644 index 000000000..5205b6292 --- /dev/null +++ b/Panel/bot/discord/events/message.js @@ -0,0 +1,95 @@ +module.exports = (client, message) => { + if (message.content.toLowerCase().includes("discord.gg")) { + message.delete(); + } else if (message.content.toLowerCase().includes("discord.com")) { + message.delete() + } else if (message.content.toLowerCase().includes("discordapp.com឵឵")) { + message.delete() + } + if (mutesData.fetch(message.author.id + ".muted") === "true") { + let muteRole = client.guilds.get(message.guild.id).roles.find(r => r.id == "726829710935457872"); + message.guild.members.get(message.author.id).addRole(muteRole) + } else if (mutesData.fetch(message.author.id + ".muted") === "false") { + let muteRole = client.guilds.get(message.guild.id).roles.find(r => r.id == "726829710935457872"); + message.guild.members.get(message.author.id).removeRole(muteRole) + } + +/* + if (message.attachments.size > 0) { + if (message.attachments.every(attachIsImage)) { + const Tesseract = require("tesseract.js") + message.attachments.forEach(attachment => { + Tesseract.recognize( + attachment.url, + 'eng', + ).then(({ data: { text } }) => { + if (text.includes("There was an error attempting to establish")) { + message.reply('It looks like you are getting a error with the websocket. Try refreshing if that doesnt work please check <#738530520945786921>') + } else if (text.includes("HTTP/E_CONN_REFUSED")) { + message.reply('It looks like you might be getting a `HTTP/E_CONN_REFUSED` error. \nThis error is normally found in the file management. Please refresh. \nIf that doesnt fix check <#738530520945786921> for any possible outages. No outages but still got the error? make a ticket!') + } else if (text.includes("We were unable to locate the requested resource on the server.")) { + message.reply('Uh oh. Server you are trying to access doesnt exist. Did you get the wrong url or was the server deleted?') + } else if (text.includes("You do not have permission to access this resource on this server.")) { + message.reply('The server you are trying to access you do not have perms to view. If you did before the user might of removed you as subuser.') + } else if (text.includes('Gateway Timeout')) { + message.reply('It looks like you are getting a `Gateway Timeout` error. This normally happens when a outage is happening. \nIf nothing is posted in <#738530520945786921> then you might just be having the issue. \nIt should fix its self soon') + } else if (text.includes('instal process')) { + message.reply('It looks like your server might be stuck on installing. Please open a ticket so we can fix this for you.') + } else if (text.includes('invalid ELF header')) { + message.reply('Looks like you might be getting a error about a invalid ELF header on a node.js server. If this is happening please delete `node_modules` folder and let it auto reinstall next time you start the server. This should fix the problem!') + } else if (text.includes(`find module '/home/container/index.js'`)) { + message.reply('Looks like the server cant find a `index.js` file. Please check make sure you uploaded your main file and changed startup prams to make sure the server is starting with the correct file. \nIf that doesnt help please wait for a human to come help you.') + } else if (text.includes('Please try re-compiling or re-installing')) { + message.channel.send('Looks like you might of uploaded your `node_modules` folder. Please delete this folder and when you server starts modules will be auto installed.') + } + }) + }) + } + } + + function attachIsImage(msgAttach) { + var url = msgAttach.url; + //True if this url is a png image. + return url.indexOf("png", url.length - "png".length /*or 3*/// ) !== -1; + // } + + + if (message.channel.type == "dm") { + if (message.author.id == "137624084572798976") { + const args = message.content.trim().split(/ +/g); + client.channels.get(args[0]).startTyping() + setTimeout(async () => { + client.channels.get(args[0]).send(message.content.split(' ').slice(1).join(' ')) + }, 5000) + client.channels.get(args[0]).stopTyping() + } + }; + + + const prefix = config.DiscordBot.Prefix; + if (message.content.indexOf(prefix) !== 0) return; + const args = message.content.slice(prefix.length).trim().split(/ +/g); + const commandargs = message.content.split(' ').slice(1).join(' '); + const command = args.shift().toLowerCase(); + console.log(chalk.magenta("[DISCORD] ") + chalk.yellow(`[${message.author.username}] [${message.author.id}] >> ${prefix}${command} ${commandargs}`)); + try { + let blacklisted = [ + '754441222424363088', '739231758087880845', + '738839334333186068', '738840097218101309', + '738844675372482720', '738846229919825992', + '738548111323955270' + ] + //Channel checker + + if(blacklisted.includes(message.channel.id) && (message.member.roles.find(x => x.id == '748117822370086932') == null) && + !(message.channel.id == '738548111323955270' && command == 'info')) return; + + let commandFile = require(`../commands/${command}.js`); + commandFile.run(client, message, args); + } catch (err) { + if (err instanceof Error && err.code === "MODULE_NOT_FOUND") { + return; + } + } + +}; \ No newline at end of file diff --git a/Panel/bot/discord/events/messageDelete.js b/Panel/bot/discord/events/messageDelete.js new file mode 100644 index 000000000..29bd1310d --- /dev/null +++ b/Panel/bot/discord/events/messageDelete.js @@ -0,0 +1,22 @@ +module.exports = (client, message) => { + if (!message.attachments.size > 0) { + + if (message.author.bot) return; + if (message.channel.type === 'dm') return; + if (message.channel.type !== 'text') return; + + + const description = message.cleanContent + const descriptionfix = description.substr(0, 600); + const embed = new Discord.RichEmbed() + .setColor(0x00A2E8) + .setThumbnail(message.author.avatarURL) + .addField("Author ", `${message.author.tag} (ID: ${message.author.id})`) + .addField("Message Content:", `${descriptionfix}`) + .setTimestamp() + .setFooter("Message delete in " + message.channel.name); + client.channels.get(config.DiscordBot.mLogs).send({embed}); + + } else { + } +}; \ No newline at end of file diff --git a/Panel/bot/discord/events/messageUpdate.js b/Panel/bot/discord/events/messageUpdate.js new file mode 100644 index 000000000..0ebd427d5 --- /dev/null +++ b/Panel/bot/discord/events/messageUpdate.js @@ -0,0 +1,28 @@ +//let client = require("../../../../index.js").client; + +module.exports = (client, message, editedMessage) => { + if (editedMessage.content.toLowerCase().includes("discord.gg")) { + editedMessage.delete(); + } else if (editedMessage.content.toLowerCase().includes("discord.com")) { + editedMessage.delete() + } else if (editedMessage.content.toLowerCase().includes("discordapp.com឵឵")) { + message.delete() + } + + if (message.author.bot) return; + if (message.channel.type === 'dm') return; + if (message === editedMessage) return; + if (message.channel.type !== 'text') return; + + const embed = new Discord.RichEmbed() + .setColor(0x00A2E8) + .setThumbnail(message.author.avatarURL) + .addField("Author ", `${message.author.tag} (ID: ${message.author.id})`) + .addField("Before Edit ", `${message}`) + .addField("After Edit", `${editedMessage}`) + .setTimestamp() + .setFooter("Message edit in " + message.channel.name); + client.channels.get(config.DiscordBot.mLogs).send({ + embed + }); +}; \ No newline at end of file diff --git a/Panel/bot/discord/events/raw.js b/Panel/bot/discord/events/raw.js new file mode 100644 index 000000000..d4bef227a --- /dev/null +++ b/Panel/bot/discord/events/raw.js @@ -0,0 +1,43 @@ +let findDuplicates = arr => arr.filter((e, i) => arr.indexOf(e) != i) + +module.exports = async (client, e) => { + + if (e.t == "MESSAGE_REACTION_ADD") { + let channel = client.channels.get(e.d.channel_id); + let message = await channel.fetchMessage(e.d.message_id); + let emoji = e.d.emoji; + let member = message.guild.members.get(e.d.user_id); + + if (member.user.bot || client.reactionRoles[channel.id] == null || client.reactionRoles[channel.id][message.id] == null) return; + try { + let reactionRoles = client.reactionRoles[channel.id][message.id]; + + let input = emoji.id != null ? emoji.id : emoji.name; + + if (reactionRoles[input] != null) { + let role = message.guild.roles.get(reactionRoles[input]); + + if (member.roles.find(x => x.id == reactionRoles[input])) { + await member.removeRole(role); + member.user.send("removed the role: `" + role.name + "`!"); + } else { + await member.addRole(role); + member.user.send("gave you the role: `" + role.name + "`!"); + }; + + let memberRoles = member.roles.map(x => x.id).concat(Object.values(reactionRoles)); + if (findDuplicates(memberRoles)) member.addRole('765869330024890378') + else member.removeRole('765869330024890378'); + } + + message.reactions.forEach(reaction => { + if (e.d.user_id == client.user.id) return; + else reaction.remove(e.d.user_id) + }) + } catch (error) { + client.channels.get('757029522682937354').send(error.name) + } + } + + +} \ No newline at end of file diff --git a/Panel/bot/discord/events/ready.js b/Panel/bot/discord/events/ready.js new file mode 100644 index 000000000..7dae55423 --- /dev/null +++ b/Panel/bot/discord/events/ready.js @@ -0,0 +1,135 @@ +const exec = require('child_process').exec; +const axios = require('axios'); +const { Message } = require('discord.js'); +module.exports = async (client, guild, files) => { + console.log(chalk.magenta('[DISCORD] ') + chalk.green(client.user.username + " has logged in!")); + + //Check make sure create account channels are closed after a hour + setTimeout(() => { + client.guilds.get("639477525927690240").channels.filter(x => x.parentID == '738539016688894024' && (Date.now() - x.createdAt) > 1800000 ).forEach(x => x.delete()) + }, 60000) + + //Auto Activities List + const activities = [{ + "text": "over DanBot Hosting", + "type": "WATCHING" + }, + { + "text": "DanBot FM", + "type": "LISTENING" + }, + { + "text": "Stalking Dan coding me :)", + "type": "WATCHING" + } + ]; + + //Automatic 30second git pull. + setInterval(() => { + exec(`git pull`, (error, stdout) => { + let response = (error || stdout); + if (!error) { + if (response.includes("Already up to date.")) { + console.log('Bot already up to date. No changes since last pull') + } else { + client.channels.get('766068015686483989').send('**[AUTOMATIC]** \nNew update on GitHub. Pulling. \n\nLogs: \n```' + response + "```" + "\n\n\n**Restarting bot**") + setTimeout(() => { + process.exit(); + }, 1000) + }; + } + }) + }, 30000) + + setInterval(() => { + const activity = activities[Math.floor(Math.random() * activities.length)]; + client.user.setActivity(activity.text, { + type: activity.type + }); + }, 30000); + + //Reaction-Roles: + + let reactionRoles = require('../reactionRoles'); + client.reactionRoles = reactionRoles; + + // end of Reaction-Roles + + global.invites = {}; + client.guilds.forEach(g => { + g.fetchInvites().then(guildInvites => { + invites[g.id] = guildInvites; + }); + }); + + //Node status channel embed + setInterval(() => { + + //Node status + client.channels.get("757949242495991918").fetchMessage("771507868997648384").then(msg => { + const embed = new Discord.RichEmbed() + .setTitle(`__**Node Status**__ \n**Node 1**: ${nodeStatus.get("node1").status} \n**Node 2**: ${nodeStatus.get("node2").status} \n**Node 3**: ${nodeStatus.get("node3").status} \n**Node 4**: ${nodeStatus.get("node4").status}`) + msg.edit(embed) + }); + + //Misc status + client.channels.get("757949242495991918").fetchMessage("771508453344673814").then(msg => { + const embed = new Discord.RichEmbed() + .setTitle(`__**Misc Status**__ \n**Lavalink 1**: ${nodeStatus.get("lava.danbot.host").status} \n**Lavalink 2**: ${nodeStatus.get("lava2.danbot.host").status} \n**Mail Server**: ${nodeStatus.get("mail.danbot.host").status} \n**Reverse Proxy**: ${nodeStatus.get("154.27.68.234").status} \n**Panel Website**: ${nodeStatus.get("panel.danbot.host").status}`) + msg.edit(embed) + }); + }, 15000) + + //Voice channel stats updator + setInterval(async () => { + let guild1 = await client.guilds.get("639477525927690240").fetchMembers(); + let roleID1 = '748117822370086932'; + let staffCount = guild1.roles.get(roleID1).members.size; + client.channels.get("739821419910791348").edit({ name: `Staff: ${staffCount}`, reason: "Staff count update" }); + + let guild2 = await client.guilds.get("639477525927690240").fetchMembers(); + let roleID2 = '639490038434103306'; + let memberCount = guild2.roles.get(roleID2).members.size; + client.channels.get("739821366991257621").edit({ name: `Members: ${memberCount}`, reason: "Member count update" }); + + let guild3 = await client.guilds.get("639477525927690240").fetchMembers(); + let roleID3 = '704467807122882562'; + let botCount = guild3.roles.get(roleID3).members.size; + client.channels.get("739821468296413254").edit({ name: `Bots: ${botCount}`, reason: "Bot count update" }); + + let guild4 = await client.guilds.get("639477525927690240") + const ticketcount = guild4.channels.filter(x=> x.name.endsWith("-ticket")).size + client.channels.get("739821447924416562").edit({ name: `Tickets: ${ticketcount}`, reason: "Ticket count update"}) + + axios({ + url: config.Pterodactyl.hosturl + "/api/application/servers", + method: 'GET', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + } + }).then(response => { + client.channels.get("757199549977722890").edit({ name: `Servers Hosting: ${response.data.meta.pagination.total}`, reason: "Server count update"}) + }); + + axios({ + url: config.Pterodactyl.hosturl + "/api/application/users", + method: 'GET', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikey, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + } + }).then(response => { + client.channels.get("757222585015599214").edit({ name: `Clients Hosting: ${response.data.meta.pagination.total}`, reason: "Client count update"}) + }); + client.channels.get("758746579636191382").edit({ name: `Boosts: ${client.guilds.get("639477525927690240").premiumSubscriptionCount}`, reason: "Boosts count update" }) + }, 30000); + + +}; diff --git a/Panel/bot/discord/events/voiceStateUpdate.js b/Panel/bot/discord/events/voiceStateUpdate.js new file mode 100644 index 000000000..ba7cee476 --- /dev/null +++ b/Panel/bot/discord/events/voiceStateUpdate.js @@ -0,0 +1,36 @@ +module.exports = async (newM, oldM) => { + console.log(client.pvc) + let guild = newM.guild; + if (oldM.voiceChannelID == newM.voiceChannelID) return; + + if (oldM.voiceChannel != null && oldM.voiceChannelID != "757660050977456238" && oldM.voiceChannel.parentID == "757659750342197289") { + if (client.pvc.get(oldM.voiceChannelID) != null && client.pvc.get(oldM.voiceChannelID).owner == oldM.id) { + console.log("delete") + + oldM.voiceChannel.delete(); + client.pvc.delete(oldM.voiceChannelID); + } + } + + if (newM.voiceChannelID == "757660050977456238") { + console.log("create") + let cleanName = transliterate.slugify(newM.user.username); + if (cleanName == '') cleanName = 'unknown'; + let vc = await guild.createChannel(`${cleanName}'s Room`, { + type: "voice", + permissionOverwrites: [{ + id: guild.id, + deny: ["CONNECT", "VIEW_CHANNEL"] + }, { + id: newM.id, + allow: ["SPEAK", "STREAM", "CONNECT", "VIEW_CHANNEL"] + }] + }) + vc.setParent("757659750342197289"); + newM.setVoiceChannel(vc.id); + client.pvc.set(vc.id, { + channelID: vc.id, + owner: newM.id + }) + } +}; \ No newline at end of file diff --git a/Panel/bot/discord/events/welcome-background.png b/Panel/bot/discord/events/welcome-background.png new file mode 100644 index 000000000..371b00a55 Binary files /dev/null and b/Panel/bot/discord/events/welcome-background.png differ diff --git a/Panel/bot/discord/music/functions.js b/Panel/bot/discord/music/functions.js new file mode 100644 index 000000000..0ab4ef8ea --- /dev/null +++ b/Panel/bot/discord/music/functions.js @@ -0,0 +1,71 @@ +const fs = require('fs'); +module.exports = (client, utils, ytdl, message) => { + const prefix = config.DiscordBot.Prefix; + + client.handleVideo = async (video, message, vc, playlist = false) => { + let queue = client.queue.get(message.guild.id); + let music = { + id: video.id, + title: video.title, + url: `https://www.youtube.com/watch?v=${video.id}` + }; + + if (!queue) { + let queueConstruct = { + textChannel: message.channel, + voiceChannel: vc, + connection: null, + musics: [], + volume: 100, + playing: true + }; + let voteConstruct = { + votes: 0, + voters: [] + }; + + client.queue.set(message.guild.id, queueConstruct); + client.votes.set(message.guild.id, voteConstruct) + queueConstruct.musics.push(music); + + try { + var connection = await vc.join(); + queueConstruct.connection = connection; + client.play(message.guild, queueConstruct.musics[0]); + } catch (err) { + client.queue.delete(message.guild.id); + console.error(`I could not join your voice channel: ${err}`); + } + } else { + queue.musics.push(music); + if (playlist) return; + else return message.channel.send(`**${music.title}** has been added to queue`); + } + return; + } + + client.play = (guild, music) => { + let queue = client.queue.get(guild.id); + let votes = client.votes.get(guild.id) + if (!music) { + queue.voiceChannel.leave(); + client.queue.delete(guild.id); + client.votes.delete(guild.id); + return queue.textChannel.send(`Music playback has ended`); + } + + let dispatcher = queue.connection.playStream(ytdl(music.url)) + .on('end', () => { + queue.musics.shift(); + votes.votes = 0; + votes.voters = []; + setTimeout(() => { + client.play(guild, queue.musics[0]); + }, 250); + }) + .on('error', err => console.error(err)); + dispatcher.setVolumeLogarithmic(queue.volume / 100); + + queue.textChannel.send(`**${music.title}** is now being played`); + } +} \ No newline at end of file diff --git a/Panel/bot/discord/music/utils.js b/Panel/bot/discord/music/utils.js new file mode 100644 index 000000000..849c35d12 --- /dev/null +++ b/Panel/bot/discord/music/utils.js @@ -0,0 +1,41 @@ +let disc; +let b; +let conf; +let msg; +let a; +let g; + +module.exports = { + + load: (discord, client, config, message, args, guild) => { + disc = discord; + b = client; + conf = config; + msg = message; + a = args; + g = guild; + }, + + timed_msg: (string, time) => { + return message.channel.send(string).then(msg => msg.delete(time)); + }, + + no_perm: (error) => { + let embed = new Discord.RichEmbed() + .setColor('#B6C2F5') + .setAuthor('ERROR: Insufficient Permissions!') + .setDescription(error) + .setFooter('Insufficient Permissions!'); + + return embed; + }, + + cmd_fail: (error, syntax) => { + let embed = new Discord.RichEmbed() + .setColor("#B6C2F5") + .setAuthor('ERROR: WRONG SYNTAX') + .setDescription(error) + .setFooter(syntax); + return embed; + } +} \ No newline at end of file diff --git a/Panel/bot/discord/reactionRoles.js b/Panel/bot/discord/reactionRoles.js new file mode 100644 index 000000000..7faeafec3 --- /dev/null +++ b/Panel/bot/discord/reactionRoles.js @@ -0,0 +1,16 @@ +let reactionRoles = { + "765877675147264000": { //channelID + "767897280401375244": { //messageID + '📣': '767845918350376960', + }, + "767897353721086012": { //messageID + '🕹️': '760207814546817085', + '🎥': '758020921939460166', + '🎉': '765865412725440522', + '❔': '767846121195175938', + '⌛': '745358424883200210', + } + } +} + +module.exports = reactionRoles; \ No newline at end of file diff --git a/Panel/bot/discord/tickets/ticketModule.js b/Panel/bot/discord/tickets/ticketModule.js new file mode 100644 index 000000000..a1491d353 --- /dev/null +++ b/Panel/bot/discord/tickets/ticketModule.js @@ -0,0 +1,3 @@ +const Discord = require('discord.js'); +const fs = require('fs'); + diff --git a/Panel/config.json b/Panel/config.json deleted file mode 100644 index 946595731..000000000 --- a/Panel/config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "ListeningPort": 80, - - "Servers": { - "NumberOfServers": 2, - "One": "Server-01", - "Two": "DESKTOP-4GLHDVM", - "Three": " ", - "Four": " ", - "Five": " ", - "Six": " ", - "Seven": " ", - "Eight": " ", - "Nine": " ", - "Ten": " " - } -} \ No newline at end of file diff --git a/Panel/example-config.json b/Panel/example-config.json new file mode 100644 index 000000000..b7fbf029d --- /dev/null +++ b/Panel/example-config.json @@ -0,0 +1,59 @@ +{ + "Port": 1144, + + "DiscordBot": { + "Token": "Bot Token", + "Prefix": "Prefix", + "clientID": "Client ID from Discord Dev portal for the bot", + "clientSecret": "Client Secret from the Discord Dev Portal.", + "callbackURL": "Call back url. For logging into the website", + "ownerID": "Owner ID. Gives you access to a few more commands :)", + "mLogs": "Message logs channel ID", + "oLogs": "Other logs channel id (Currently used for namechanges and linking logs)", + "welcome": "Welcome channel ID", + "inviterewmsg": "Invite reward message channel ID", + "invite5": "Invite 5+ role ID", + "invite10": "Invite 10+ role ID", + "invite25": "Invite 25+ role ID", + "invite50": "Invite 50+ role ID", + "invitechannel": "Invite logs channel ID", + "requestsChannel": "Request channel ID" + }, + + "DiscordSuggestions": { + "channelID": "Channel ID for Suggestions webhook", + "Token": "Discord Webhook token" + }, + + "DB": { + "MongoDB": "MongoDB connection (forgot what this is for but give it one anyway)" + }, + + "Pterodactyl": { + "hosturl": "Pterodactyl URL (Dont put the / on the end) Example: https://your.panel.com", + "apikey": "Pterodactyl ADMIN Api key. Where to find? add admin/api to the end of your panel domain", + "apikeyclient": "Pterodactyl CLIENT Api key. Find it: add account/api to the end of your panel domain" + }, + + "Proxmox": { + "url": "Proxmox (Not used yet so ignore this)", + "auth": "Proxmox (Not used yet so ignore this)", + "username": "Proxmox (Not used yet so ignore this)", + "password": "Proxmox (Not used yet so ignore this)" + }, + + "Email": { + "Host": "smtp mail server host", + "Port": "587", + "User": "smtp mail server username", + "Password": "smtp mail server password", + "From": "Mail from email" + }, + + "SSH": { + "Host": "SSH Host (Used for Proxy servers right now)", + "User": "root", + "Password": "User password for SSH", + "Port": 22 + } +} \ No newline at end of file diff --git a/Panel/index.js b/Panel/index.js index a6c8208e1..d465d99ba 100644 --- a/Panel/index.js +++ b/Panel/index.js @@ -1,195 +1,478 @@ -/* _____ __ __ _ _ - / ____| | \/ | (_)| | - | (___ ___ _ __ __ __ ___ _ __ | \ / | ___ _ __ _ | |_ ___ _ __ - \___ \ / _ \| '__|\ \ / // _ \| '__|| |\/| | / _ \ | '_ \ | || __|/ _ \ | '__| - ____) || __/| | \ V /| __/| | | | | || (_) || | | || || |_| (_) || | - |_____/ \___||_| \_/ \___||_| |_| |_| \___/ |_| |_||_| \__|\___/ |_| - Free Monitoring software made by danielpmc -*/ - -var config = require("./config.json"); -var PORT = config.ListeningPort; -var express = require('express'); -var app = express(); -var server = require('http').createServer(app); -var bodyParser = require('body-parser'); -var fs = require("fs"); -var hbs = require('express-handlebars'); -var chalk = require('chalk'); - -app.use(bodyParser.json()); -app.use(bodyParser.urlencoded({extended: true})); - -server.listen(PORT, function () { - console.log(chalk.green("Listening on port " + PORT)); -}); - - -app.get('/data', function (req, res) { - console.log(req.query); - - //Write data to JSON file after checking servername. - var data = JSON.stringify(req.query); - fs.writeFileSync('data/' + req.query.servername + '.json', data); - -}); - -//View engine setup -app.set('view engine', 'hbs'); -app.engine('hbs', hbs({ - extname: 'hbs', - defaultView: 'default', - layoutsDir: '/views/pages', - partialsDir: '/views/partials' -})); - -//Config Loading and setting up -if (config.Servers.NumberOfServers == 0) { - - //Errors if config is not setup. - console.log(chalk.red("You have not set up the config file")) - process.exit() - -} else if (config.Servers.NumberOfServers == 1) { - if (config.Servers.One == " ") { - - //Checks if server one field in config has valid data. - console.log(chalk.red("You have not set up Server names. Please fill in `One` in the config with your hostname. Don't know it? Run the daemon and that will tell you the hostname!")); - process.exit(); - - } else { - - //Config has valid data for server one. Set up the website! - //Loads the data - var ServerOneData = fs.readFileSync("./data/" + config.Servers.One + ".json", 'utf8'); - var ServerOne = JSON.parse(ServerOneData); - - //Gets the website page and is ready to display it. - app.get("/" + config.Servers.One, (req, res) => { - res.render('ServerOne', { layout: false, - Data: ServerOne - }); - }); - - } -} else if (config.Servers.NumberOfServers == 2) { - if (config.Servers.One == " ") { - - //Checks if server one field in config has valid data. - console.log(chalk.red("You have not set up Server names. Please fill in `One` in the config with your hostname. Don't know it? Run the daemon and that will tell you the hostname!")); - process.exit(); - - } else if (config.Servers.Two == " ") { - - //Checks if server two field in config has valid data. - console.log(chalk.red("You have not set up Server names. Please fill in `Two` in the config with your hostname. Don't know it? Run the daemon and that will tell you the hostname!")); - process.exit(); - - } else { - - //Config has valid data for server one. Set up the website! - - //Loads the data (SERVER ONE) - var ServerOneData = fs.readFileSync("./data/" + config.Servers.One + ".json", 'utf8'); - var ServerOne = JSON.parse(ServerOneData); - - //Gets the website page and is ready to display it. (Server ONE) - app.get("/" + config.Servers.One, (req, res) => { - - //Loads the data (SERVER ONE) - var ServerOneData = fs.readFileSync("./data/" + config.Servers.One + ".json", 'utf8'); - var ServerOne = JSON.parse(ServerOneData); - - res.render('ServerOne', { layout: false, - Data: ServerOne - }); - }); - - //Loads the data (SERVER TWO) - var ServerTwoData = fs.readFileSync("./data/" + config.Servers.Two + ".json", 'utf8'); - var ServerTwo = JSON.parse(ServerTwoData); - - //Gets the website page and is ready to display it. (Server ONE) - app.get("/" + config.Servers.Two, (req, res) => { - res.render('ServerTwo', { layout: false, - Data: ServerTwo - }); - }); - - } -} else if (config.Servers.NumberOfServers == 3) { - if (config.Servers.One == " ") { - - //Checks if server one field in config has valid data. - console.log(chalk.red("You have not set up Server names. Please fill in `One` in the config with your hostname. Don't know it? Run the daemon and that will tell you the hostname!")); - process.exit(); - - } else if (config.Servers.Two == " ") { - - //Checks if server two field in config has valid data. - console.log(chalk.red("You have not set up Server names. Please fill in `Two` in the config with your hostname. Don't know it? Run the daemon and that will tell you the hostname!")); - process.exit(); - - } else if (config.Servers.Three == " ") { - - //Checks if server two field in config has valid data. - console.log(chalk.red("You have not set up Server names. Please fill in `Three` in the config with your hostname. Don't know it? Run the daemon and that will tell you the hostname!")); - process.exit(); - - } else { - - //Config has valid data for server one. Set up the website! - - //Loads the data (SERVER ONE) - var ServerOneData = fs.readFileSync("./data/" + config.Servers.One + ".json", 'utf8'); - var ServerOne = JSON.parse(ServerOneData); - - //Gets the website page and is ready to display it. (Server ONE) - app.get("/" + config.Servers.One, (req, res) => { - res.render('ServerOne', { layout: false, - Data: ServerOne - }); - }); - - //Loads the data (SERVER TWO) - var ServerTwoData = fs.readFileSync("./data/" + config.Servers.Two + ".json", 'utf8'); - var ServerTwo = JSON.parse(ServerTwoData); - - //Gets the website page and is ready to display it. (Server TWO) - app.get("/" + config.Servers.Two, (req, res) => { - res.render('ServerTwo', { layout: false, - Data: ServerTwo - }); - }); - - //Loads the data (SERVER THREE) - var ServerThreeData = fs.readFileSync("./data/" + config.Servers.Three + ".json", 'utf8'); - var ServerThree = JSON.parse(ServerThreeData); - - //Gets the website page and is ready to display it. (Server THREE) - app.get("/" + config.Servers.Three, (req, res) => { - res.render('ServerThree', { layout: false, - Data: ServerThree - }); - }); - - } -} - -//Import data -var data = fs.readFileSync('./data/DESKTOP-4GLHDVM.json', 'utf8'); -var data1 = JSON.parse(data); - -//Routes -app.get("/", (req, res) => { - res.render('index', { layout: false, - info: data1 -}); -}); - -//Catch 404 and forward to error handler -app.use(function(req, res, next) { - var err = new Error('Not Found'); - err.status = 404; - next(err); -}); \ No newline at end of file +/* + ____ ____ __ __ __ __ _ + / __ \____ _____ / __ )____ / /_ / / / /___ _____/ /_(_)___ ____ _ + / / / / __ `/ __ \/ __ / __ \/ __/ / /_/ / __ \/ ___/ __/ / __ \/ __ `/ + / /_/ / /_/ / / / / /_/ / /_/ / /_ / __ / /_/ (__ ) /_/ / / / / /_/ / +/_____/\__,_/_/ /_/_____/\____/\__/ /_/ /_/\____/____/\__/_/_/ /_/\__, / +Free Hosting for ever! /____/ +*/ + +global.config = require("./config.json"); +var PORT = config.Port; +var express = require('express'); +var app = express(); +var server = require('http').createServer(app); +var bodyParser = require('body-parser'); +global.fs = require("fs"); +const hbs = require('hbs'); +global.chalk = require('chalk'); +const nodemailer = require('nodemailer'); +const axios = require('axios'); +var ping = require('ping'); +const ping2 = require('ping-tcp-js') +global.transport = nodemailer.createTransport({ + host: config.Email.Host, + port: config.Email.Port, + auth: { + user: config.Email.User, + pass: config.Email.Password + } +}); + +const isSnowflake = require(process.cwd() + "/util/isSnowflake.js"); +const { + getUser, + getBot +} = require(process.cwd() + "/util/discordAPI"); + + +//Node status +setInterval(() => { +//Node 1 +axios({ + url: config.Pterodactyl.hosturl + "/api/client/servers/99d65091/resources", + method: 'GET', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikeyclient, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + } +}).then(response => { + nodeStatus.set("node1", { + status: "Online 🟢" + }); +}).catch(error => { + nodeStatus.set("node1", { + status: "Offline 🔴" + }); +}) + +//Node 2 +axios({ + url: config.Pterodactyl.hosturl + "/api/client/servers/0cb9a74e/resources", + method: 'GET', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikeyclient, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + } +}).then(response => { + nodeStatus.set("node2", { + status: "Online 🟢" + }); +}).catch(error => { + nodeStatus.set("node2", { + status: "Offline 🔴" + }); +}) + +//Node 3 +axios({ + url: config.Pterodactyl.hosturl + "/api/client/servers/373fafce/resources", + method: 'GET', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikeyclient, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + } +}).then(response => { + nodeStatus.set("node3", { + status: "Online 🟢" + }); +}).catch(error => { + nodeStatus.set("node3", { + status: "Offline 🔴" + }); +}) + +//Node 4 +axios({ + url: config.Pterodactyl.hosturl + "/api/client/servers/98ca4dbd/resources", + method: 'GET', + followRedirect: true, + maxRedirects: 5, + headers: { + 'Authorization': 'Bearer ' + config.Pterodactyl.apikeyclient, + 'Content-Type': 'application/json', + 'Accept': 'Application/vnd.pterodactyl.v1+json', + } +}).then(response => { + nodeStatus.set("node4", { + status: "Online 🟢" + }); +}).catch(error => { + nodeStatus.set("node4", { + status: "Offline 🔴" + }); +}) + +var hosts = ['154.27.68.234', 'panel.danbot.host', 'mail.danbot.host']; +hosts.forEach(function(host){ + ping.sys.probe(host, function(isAlive){ + if (isAlive == true) { + nodeStatus.set(host, { + status: "Online 🟢" + }) + } else if (isAlive == false) { + nodeStatus.set(host, { + status: "Offline 🔴" + }); + } + }); +}, { timeout: 4 }); + +const portz = 2333; + +//Lavalink Server 1 +const hostz = 'lava.danbot.host'; +ping2 + .ping(hostz, portz) + .then(() => nodeStatus.set("lava.danbot.host", { + status: "Online 🟢" + })) + .catch((e) => nodeStatus.set("lava.danbot.host", { + status: "Offline 🔴" + })); + +//Lavalink Server 2 +const hostz2 = 'lava2.danbot.host'; +ping2 + .ping(hostz2, portz) + .then(() => nodeStatus.set("lava2.danbot.host", { + status: "Online 🟢" + })) + .catch((e) => nodeStatus.set("lava2.danbot.host", { + status: "Offline 🔴" + })); + +}, 5000) + + +//Discord Bot +let db = require("quick.db"); +global.Discord = require("discord.js"); +global.fs = require("fs"); +global.moment = require("moment"); +global.userData = new db.table("userData"); +global.settings = new db.table("settings"); +global.webSettings = new db.table("webSettings"); +global.mutesData = new db.table("muteData"); +global.domains = new db.table("linkedDomains"); +global.nodeStatus = new db.table("nodeStatus"); +global.client = new Discord.Client({ + disableEveryone: true +}); +global.bot = client; +global.suggestionLog = new Discord.WebhookClient(config.DiscordSuggestions.channelID, config.DiscordSuggestions.channelID) +bot.pvc = new Discord.Collection(); + +//Event handler +fs.readdir('./bot/discord/events/', (err, files) => { + files = files.filter(f => f.endsWith('.js')); + files.forEach(f => { + const event = require(`./bot/discord/events/${f}`); + client.on(f.split('.')[0], event.bind(null, client)); + delete require.cache[require.resolve(`./bot/discord/events/${f}`)]; + }); +}); + +//Bot login +client.login(config.DiscordBot.Token); +global.Allowed = ["338192747754160138", "137624084572798976"]; + +//Test Email +//const message = { +// from: config.Email.From, +// to: 'danielpd93@gmail.com', +// subject: 'DanBot Hosting Webpage and Discord Bot now online!', +// html: "DanBot Hosting Stats page is now online!" +//}; +//transport.sendMail(message, function(err, info) { +// if (err) { +// console.log(err) +// } else { +// console.log(info); +// } +//}); + +// website things + +const passport = require("passport"); +const session = require("express-session"); +const strategy = require("passport-discord").Strategy; +const MongoStore = require("connect-mongo")(session); +const cookieParser = require("cookie-parser"); +const csrf = require("csurf"); +const helmet = require("helmet"); + +passport.serializeUser((user, done) => { + done(null, user); +}); +passport.deserializeUser((obj, done) => { + done(null, obj); +}); + +passport.use( + new strategy({ + clientID: config.DiscordBot.clientID, + clientSecret: config.DiscordBot.clientSecret, + callbackURL: config.DiscordBot.callbackURL, + scope: ["identify"] + }, + (accessToken, refreshToken, profile, done) => { + process.nextTick(() => { + return done(null, profile); + }); + } + ) +); + +app.use( + session({ + store: new MongoStore({ + url: config.DB.MongoDB + }), + secret: "FROPT", + resave: false, + saveUninitialized: false + }) +); + +app.use(passport.initialize()); +app.use(passport.session()); +app.use(helmet({ + frameguard: false +})); +app.use(cookieParser()); + +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ + extended: true +})); + +server.listen(PORT, function () { + console.log(chalk.magenta('[WEB] ') + chalk.green("Listening on port " + PORT)); +}); + +global.nodeData = new db.table("nodeData") +app.get('/data', function (req, res) { + let nodes = ["154.27.68.232", "154.27.68.233", "167.86.113.158", "51.38.69.73"]; + if (req.query.servername == undefined) { + if (!nodes.includes(req.headers["x-forwarded-for" || "cf-connecting-ip"])) { + res.redirect("/") + } else { + nodeData.set(req.query.speedname + '-speedtest', { + speedname: req.query.speedname, + ping: req.query.ping, + download: req.query.download, + upload: req.query.upload, + updatetime: req.query.updatetime + }); + }; + } else { + if (!nodes.includes(req.headers["x-forwarded-for" || "cf-connecting-ip"])) { + res.redirect("/") + } else { + nodeData.set(req.query.servername, { + servername: req.query.servername, + cpu: req.query.cpu, + cpuload: req.query.cpuload, + cputhreads: req.query.cputhreads, + cpucores: req.query.cpucores, + memused: req.query.memused, + memtotal: req.query.memtotal, + swapused: req.query.swapused, + swaptotal: req.query.swaptotal, + diskused: req.query.diskused, + disktotal: req.query.disktotal, + netrx: req.query.netrx, + nettx: req.query.nettx, + osplatform: req.query.osplatform, + oslogofile: req.query.oslogofile, + osrelease: req.query.osrelease, + osuptime: req.query.osuptime, + biosvendor: req.query.biosvendor, + biosversion: req.query.biosversion, + biosdate: req.query.biosdate, + servermonitorversion: req.query.servermonitorversion, + datatime: req.query.datatime, + dockercontainers: req.query.dockercontainers, + dockercontainersrunning: req.query.dockercontainersrunning, + dockercontainerspaused: req.query.dockercontainerspaused, + dockercontainersstopped: req.query.dockercontainersstopped, + updatetime: req.query.updatetime + }); + } + } +}) + +//View engine setup +hbs.registerPartials(__dirname + '/views/partials') +app.set('view engine', 'hbs'); + +app.use((req, res, next) => { + res.set("Access-Control-Allow-Origin", "*"); + res.set("Access-Control-Allow-Methods", "GET, POST"); + + console.log( + (req.headers["cf-connecting-ip"] || + req.headers["x-forwarded-for"] || + req.ip) + + " [" + + req.method + + "] " + + req.url + ); + + next(); +}); + +//Routes + + +// DanBot Hosting Stats + +const apiRoute = require("./routes/api.js"); +const botRoute = require("./routes/bot.js"); +const indexRoute = require("./routes/index.js"); +const statsRoute = require("./routes/stats.js"); +const meRoute = require("./routes/me.js"); +const adminRoute = require("./routes/admin.js"); +//const { config } = require("process"); + +app.use("/api", apiRoute); +app.use("/bot", botRoute); +app.use("/", indexRoute); +app.use("/stats", statsRoute); +app.use("/me", meRoute); +app.use("/admin", adminRoute); + +app.get("/user/:ID", async (req, res) => { + let user = req.params.ID; + let memberr = "No" + + if (!isSnowflake(user)) { + return res.render("error.ejs", { + user: req.isAuthenticated() ? req.user : null, + message: "Make sure ID is a valid ID" + }); + } + + let [use] = await getBot(user) + + if (use.user_id && use.user_id[0].endsWith("is not snowflake.")) + return res.render("error.ejs", { + user: req.isAuthenticated() ? req.user : null, + message: "ID is invalid" + }); + + if (use.message == "Unknown User") + return res.render("error.ejs", { + user: req.isAuthenticated() ? req.user : null, + message: "Discord API - Unknown User" + }); + + if (use.bot === true) return res.redirect("/bot/" + user); + + try { + bot.fetchUser(user).then(User => { + if (User.bot) { + return res.redirect("/bot/" + User.id); + } + + var member = bot.guilds + .get("639477525927690240") + .members.get(User.id); + if (!member) { + (pColor = "grey"), (presence = "offline"); + } + let guild = bot.guilds.get("639477525927690240"); + if (guild.member(User.id)) { + memberr = "yes"; + } + if (member) { + presence = member.presence.status; + + if (presence) { + if (presence === "offline") { + presence = "Offline"; + pColor = "grey"; + } else if (presence === "online") { + presence = "Online"; + pColor = "#43B581"; + } else if (presence === "dnd") { + presence = "DND"; + pColor = "#F04747"; + } else if (presence === "streaming") { + presence = "Streaming"; + pColor = "purple"; + } else if (presence === "idle") { + presence = "Idle"; + pColor = "#FAA61A"; + } else { + (pColor = "grey"), (presence = "Not Available"); + } + } + } + + let avatar = `https://mythicalbots.xyz/bot/${user}/avatar`; + + let bots = db.get(`${User.id}.bots`); + if (!bots) bots = null; + + console.log(bots) + + res.render("me/user.ejs", { + user: req.isAuthenticated() ? req.user : null, + User, + avatar, + // Data, + pColor, + presence, + // info, + memberr, + use, + bots, + db, + // Discord, + // pageType: { user: true } + }); + }); + } catch (e) { + return res.render("error.ejs", { + user: req.isAuthenticated() ? req.user : null, + message: e + }); + } + +}); + + +//Catch 404 and forward to error handler +app.use(function (req, res, next) { + res.status(404).render("error.ejs", { + message: "Page Not Found", + user: req.isAuthenticated() ? req.user : null + }); +}); + +setInterval(async () => { + console.log("[Automatic Process] Getting bot stats from MBL") + require("./util/MBL.js") +}, 600000); \ No newline at end of file diff --git a/Panel/package.json b/Panel/package.json index 4a8e9b849..a0dc4510e 100644 --- a/Panel/package.json +++ b/Panel/package.json @@ -1,29 +1,61 @@ { - "name": "servermonitor", - "version": "1.0.0", - "description": "A software that runs a local web server to show system info, E.G: CPU Graph, Memory Graph along with more helpful info. Good for anyone who has multiple servers/computers like me and needs some way to monitor them from a single or multiple computers. ", + "name": "danbothostingstats", + "version": "1.0.4", + "description": "A modified version of ServerMonitor by danielpmc. ", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", - "url": "git+https://github.com/danielpmc/ServerMonitor.git" + "url": "git+https://github.com/danbot-devs/DanBotHostingStats.git" }, - "author": "danielpmc", + "author": "danbot-devs", "license": "MIT", "bugs": { - "url": "https://github.com/danielpmc/ServerMonitor/issues" + "url": "https://github.com/danbot-devs/DanBotHostingStats/issues" }, - "homepage": "https://github.com/danielpmc/ServerMonitor#readme", + "homepage": "https://github.com/danbot-devs/DanBotHostingStats#readme", "dependencies": { + "axios": "^0.21.0", "body-parser": "latest", + "canvas": "^2.6.1", "chalk": "^3.0.0", - "ejs": "^3.0.1", + "connect-mongo": "^3.2.0", + "cookie-parser": "^1.4.5", + "csurf": "^1.11.0", + "discord.js": "^11.6.4", + "ejs": "^3.1.3", + "events": "^3.1.0", "express": "latest", "express-handlebars": "^3.1.0", - "helmet": "^3.21.2", + "express-rate-limit": "^5.1.3", + "express-session": "^1.17.1", + "git-repo-info": "^2.1.1", + "hbs": "^4.1.1", + "helmet": "^3.23.3", "http": "latest", - "socket.io": "latest" + "moment": "^2.27.0", + "node-cron": "^2.0.3", + "node-fetch": "^2.6.0", + "node-proxmox": "^0.1.2", + "node-ssh": "^11.1.1", + "node-tesseract-ocr": "^2.0.0", + "nodemailer": "^6.4.11", + "passport": "^0.4.1", + "passport-discord": "^0.1.4", + "ping": "^0.3.0", + "ping-tcp-js": "^1.3.0", + "prettysize": "^2.0.0", + "proxmox": "^0.1.0", + "pterodactyl.js": "^2.1.1", + "puppeteer": "^1.20.0", + "quick.db": "^7.1.1", + "replace-in-file": "^6.1.0", + "resolve": "^1.17.0", + "socket.io": "latest", + "tesseract.js": "^2.1.1", + "unirest": "^0.6.0", + "validator": "^13.1.1" } } diff --git a/Panel/routes/admin.js b/Panel/routes/admin.js new file mode 100644 index 000000000..904975a51 --- /dev/null +++ b/Panel/routes/admin.js @@ -0,0 +1,56 @@ +const Router = require("express").Router(); +const db = require("quick.db"); +const isSnowflake = require(process.cwd() + "/util/isSnowflake.js"); + +Router.get("/", checkAuth, (req, res) => { + let bots = db.get(`${req.user.id}.bots`); + res.render("admin.ejs", { user: req.isAuthenticated() ? req.user : null, bots, db }); +}); + +Router.post("/", checkAuth, (req, res) => { + + let data = req.body; + console.log(data); + +}); + +//Settings page +Router.get("/settings", checkAuth, (req, res) => { + let bots = db.get(`${req.user.id}.bots`); + res.render("admin-settings.ejs", { user: req.isAuthenticated() ? req.user : null, bots, db }); +}); + +Router.post("/settings", checkAuth, (req, res) => { + + let data = req.body; + console.log(data); + +}); + +//Requests/tickets page +Router.get("/requests", checkAuth, (req, res) => { + let bots = db.get(`${req.user.id}.bots`); + res.render("requests-admin.ejs", { user: req.isAuthenticated() ? req.user : null, bots, db }); +}); + +Router.post("/requests", checkAuth, (req, res) => { + + let data = req.body; + console.log(data); + +}); + +module.exports = Router; + +/* + * Authorization check, if not authorized return them to the login page. + */ +function checkAuth(req, res, next) { + if (req.isAuthenticated()) { + return next(); + } else { + req.session.backURL = req.url; + + res.redirect("/login?redirect=/me"); + } +} \ No newline at end of file diff --git a/Panel/routes/api.js b/Panel/routes/api.js new file mode 100644 index 000000000..a89cfb3db --- /dev/null +++ b/Panel/routes/api.js @@ -0,0 +1,183 @@ +// api stuff for bots to submit their stats + +const Router = require("express").Router(); +const db = require("quick.db"); +const isSnowflake = require(process.cwd() + "/util/isSnowflake.js"); +const passport = require("passport"); +let Developers = [ "137624084572798976", "338192747754160138" ]; +const rateLimitt = require('express-rate-limit'); + +Router.post("/bot/:ID/stats", /* rateLimit(10000, 2) , */ (req, res) => { // temp remove if ratelimit + let ID = req.params.ID; + if (!ID) + return res + .status(400) + .send({ error: true, message: "Please give a bot ID" }); + + if (!isSnowflake(ID)) { + return res + .status(400) + .send({ error: true, message: "'bot_id' must be a snowflake" }); + } + + let data = req.body; + let keys = db.get("apiKeys"); + + if (keys.includes(data.key)) { + let owner = db.get(`${data.key}`); + // console.log(data); + let info = db.get(data.id); + + console.log(chalk.magenta('[API] ') + chalk.green(`${data.id} just submitted stats`)); + + if (info) { + let botData = { + id: data.id, + keyLastUsed: data.key, + servers: data.servers, + users: data.users, + owner: owner, + client: data.clientInfo, + deleted: info.deleted, + added: info.added, + status: info.status || "N/A", + mbl: info.mbl || [], + lastPost: Date.now() + }; + + db.set(ID, botData); + } else { + let botData = { + id: data.id, + keyLastUsed: data.key, + servers: data.servers, + users: data.users, + owner: owner, + client: data.clientInfo, + deleted: false, + added: Date.now(), + status: "N/A", + mbl: [], + lastPost: Date.now() + }; + + db.set(ID, botData); + } + + + /* db.fetch(`botIDs`) + db.push("botIDs", `${ID}`); + */ + + let ids = db.get("bot.IDs"); + if(!ids.includes(ID)) { + db.push("bot.IDs", `${ID}`); + } + + let bots = db.get(`${owner}.bots`); + + if(bots) { + + if(!bots.includes(ID)) { + db.push(`${owner}.bots`, `${ID}`); + } + + } else { + db.push(`${owner}.bots`, `${ID}`); + } + + return res + .status(200) + .send({ error: false, message: "Bot stats have been recorded" }); + } else { + return res + .status(400) + .send({ error: true, message: "The API Key you gave is invalid" }); + } +}); + +Router.get("/bot/:ID/info", rateLimit(15000, 4), (req, res) => { + let ID = req.params.ID; + if (!ID) + return res + .status(400) + .send({ error: true, message: "Please give a bot ID" }); + + if (!isSnowflake(ID)) { + return res + .status(400) + .send({ error: true, message: "'bot_id' must be a snowflake" }); + } + + let bot = db.get(`${ID}`); + if (!bot) + return res.status(400).send({ error: true, message: "bot not found" }); + + let data = { + id: bot.id, + servers: bot.servers, + users: bot.users, + owner: bot.owner, + client: bot.client, + deleted: bot.deleted, + added: bot.added + }; + + res.json(data); +}); + +Router.get("/bots", rateLimit(15000, 4), (req, res) => { + + let bots = db.get("bot.IDs"); + + res.json(bots); +}); + +Router.get( + "/callback", + passport.authenticate("discord", { failureRedirect: "/404" }), + (req, res) => { + console.log(`Testing: ` + req.query.state); + // addUser(req.user); + if (Developers.includes(req.user.id)) { + req.session.isAdmin = true; + } else { + req.session.isAdmin = false; + } + res.redirect("/me"); + + //maybe future features. + + } +); + +Router.use("*", (req, res) => { + res + .status(404) + .json({ error: true, status: 404, message: "Endpoint not found" }); +}); + +Router.use("*", (err, req, res) => { + res + .status(404) + .json({ error: true, status: 404, message: "Endpoint not found" }); +}); + +module.exports = Router; + +function rateLimit(windowMs, max, req, res, next) { + return rateLimitt({ + windowMs, + max, + // keyGenerator: req.header("x-forwarded-for") || req.connection.remoteAddress, + handler: function(req, res) { + return res + .status(429) + .json({ + error: true, + code: 429, + message: "DanBot Hosting Stats API - You are sending too many requests, please slow down" + }); + } + }); +} \ No newline at end of file diff --git a/Panel/routes/bot.js b/Panel/routes/bot.js new file mode 100644 index 000000000..ad8881c20 --- /dev/null +++ b/Panel/routes/bot.js @@ -0,0 +1,70 @@ +// route for users to get bot information + +const Router = require("express").Router(); +const db = require("quick.db"); +const isSnowflake = require(process.cwd() + "/util/isSnowflake.js"); + +Router.get("/:ID/", (req, res) => { + /* + let ID = req.params.ID; + if (!ID) return res.status(400).send({ error: true, message: "Please give a bot ID" }); + + if (!isSnowflake(ID)) { + return res.status(400).send({ error: true, message: "'bot_id' must be a snowflake" }); + } + + let bot = db.get(`${ID}`); + if(!bot)return res.render("error.ejs", { message: "Bot Not Found" }); + + res.render("bot/index.ejs", { bot, user: req.isAuthenticated() ? req.user : null }); + +}); + +Router.get("/:ID/remove", checkAuth, (req, res) => { + + let ID = req.params.ID; + if (!ID) return res.status(400).send({ error: true, message: "Please give a bot ID" }); + + if (!isSnowflake(ID)) { + return res.status(400).send({ error: true, message: "'bot_id' must be a snowflake" }); + } + + let bot = db.get(`${ID}`); + if(!bot)return res.render("error.ejs", { message: "Bot Not Found" }); + + let allowed = ["338192747754160138","137624084572798976"]; + allowed.push(bot.owner); + + if(allowed.includes(req.user.id)) { + + let bots = db.get("bot.IDs"); + var filtered = bots.filter(function(el) { return el != `${ID}`; }); + + let ownerbots = db.get(`${bot.owner}.bots`); + let own = ownerbots.filter(function (be) { return be != `${ID}` }); + + db.delete(`${ID}`); // remove bot from db + db.set("bot.IDs", filtered); // remove bot from the array + db.set(`${bot.owner}.bots`, own); + + res.redirect("/me?s=removed_" + ID + "_from_stats"); + + } else { + return res.render("error.ejs", { message: "You're not authorized to make changes to this bot." }); + } + */ +}); + +module.exports = Router; + + /* Authorization check, if not authorized return them to the login page. + */ +function checkAuth(req, res, next) { + if (req.isAuthenticated()) { + return next(); + } else { + req.session.backURL = req.url; + + res.redirect("/login?redirect=" + req.url); + } +} \ No newline at end of file diff --git a/Panel/routes/index.js b/Panel/routes/index.js new file mode 100644 index 000000000..2bff36beb --- /dev/null +++ b/Panel/routes/index.js @@ -0,0 +1,177 @@ +const Router = require("express").Router(); +const db = require("quick.db"); +const isSnowflake = require(process.cwd() + "/util/isSnowflake.js"); + +Router.get("/", (req, res) => { + + let Query = req.query.q; + let from = req.query.utm_source; + let Message = null; + let MessageDefined = null; + + res.render('main.ejs', { + user: req.isAuthenticated() ? req.user : null +}); +}); + +Router.get("/Node1", (req, res) => { + res.redirect("/stats/Node1"); +}); + +Router.get("/Node2", (req, res) => { + res.redirect("/stats/Node2"); +}); + +Router.get("/Node3", (req, res) => { + res.redirect("/stats/Node3"); +}); + +Router.get("/Node4", (req, res) => { + res.redirect("/stats/Node4"); +}); + +//Node status json format +Router.get("/nodeStatus", (req, res) => { + let data = { + nodestatus: { + Node1: nodeStatus.fetch("node1").status, + Node2: nodeStatus.fetch("node2").status, + Node3: nodeStatus.fetch("node3").status, + Node4: nodeStatus.fetch("node4").status + }, + misc: { + Lava1: nodeStatus.fetch("lava.danbot.host").status, + Lava2: nodeStatus.fetch("lava2.danbot.host").status, + Mail: nodeStatus.fetch("mail.danbot.host").status, + RProxy: nodeStatus.fetch("154.27.68.234").status, + Panel: nodeStatus.fetch("panel.danbot.host").status + } + }; + + res.json(data); +}); + + +Router.get("/bots", (req, res) => { + let q = req.query.q; + + let ar = []; + let lar = []; + + let bots = db.get("bot.IDs"); + for(var i=0; i < bots.length; i++) { + ar.push(db.get(bots[i])); + lar.push(db.get(bots[i])); + } + ar.sort((a, b) => a.client.username.localeCompare(b.client.username)); + // console.log(ar); + + lar.sort(function(a, b) { + return b.servers - a.servers; + }); + + res.render('bots.ejs', { + bots: db.get("bot.IDs"), + db, + user: req.isAuthenticated() ? req.user : null, + q, + ar, + lar + }); +}); + +Router.get("/login", (req, res) => { + let redirect = req.query.redirect; + if (!redirect) redirect = "/me"; + //console.log(redirect) + res.redirect( + "https://discordapp.com/api/oauth2/authorize?client_id=640161047671603205&redirect_uri=https%3A%2F%2Fdanbot.host%2Fapi%2Fcallback&response_type=code&scope=identify&prompt=none&state=" + + redirect + ); +}); + +Router.get("/logout", function(req, res) { + req.session.destroy(() => { + req.logout(); + // req.flash('success_msg', 'You are logged out'); + res.redirect("/"); + }); +}); + +Router.get("/feedback", async (req, res) => { + let Page = "Feedback"; + let ErrorMessage = null; + let Error = req.query.error; + if (Error === "not_msg") ErrorMessage = "no_message"; + res.render("feedback.ejs", { + user: req.isAuthenticated() ? req.user : null, + ErrorMessage, + }); +}); + +Router.post("/feedback/post/suggestion", checkAuth, async (req, res) => { + if (req.body.suggestion) { + + // embed + + let Kiro = req.isAuthenticated() ? req.user : null; + let suggestion = req.body.suggestion; + let SuggestionEmbed = new Discord.RichEmbed() + .setColor("BLUE") + .setTitle("Suggestion Submission") + .setThumbnail(`https://cdn.discordapp.com/avatars/${Kiro.id}/${Kiro.avatar}`) + .addField("User", `<@${Kiro.id}>(${Kiro.id})`) + .addField("Suggestion", `${suggestion}`) + + suggestionLog.send(SuggestionEmbed) + + res.redirect("/?q=SENT_FEEDBACK"); + } else { + res.redirect("/feedback?error=not_msg"); + } +}); + +Router.post("/feedback/post/bug", checkAuth, async (req, res) => { + if (req.body.bug) { + + let Kiro = req.isAuthenticated() ? req.user : null; + let Bug = req.body.bug; + + let BugEmbed = new Discord.RichEmbed() + .setColor("BLUE") + .setTitle("Bug Submission") + .setThumbnail(`https://cdn.discordapp.com/avatars/${Kiro.id}/${Kiro.avatar}`) + .addField("User", `<@${Kiro.id}>(${Kiro.id})`) + .addField("Bug", `${Bug}`); + + suggestionLog.send(BugEmbed) + + res.redirect("/?q=SENT_FEEDBACK"); + } else { + res.redirect("/feedback?error=not_msg"); + } +}); + +Router.get(["/discord","/support"], (req, res) => { + res.redirect("//discord.gg/92HBc2Z") +}); + +Router.get("/partners", async (req, res) => { + res.render("partners.ejs", { + user: req.isAuthenticated() ? req.user : null, + }); +}); + +module.exports = Router; + + /* Authorization check, if not authorized return them to the login page. + */ +function checkAuth(req, res, next) { + if (req.isAuthenticated()) { + return next(); + } else { + req.session.backURL = req.url; + + res.redirect("/login?redirect=" + req.url); + } +} \ No newline at end of file diff --git a/Panel/routes/me.js b/Panel/routes/me.js new file mode 100644 index 000000000..15f23440b --- /dev/null +++ b/Panel/routes/me.js @@ -0,0 +1,94 @@ +// route for users to get their own bots + +const Router = require("express").Router(); +const db = require("quick.db"); +const isSnowflake = require(process.cwd() + "/util/isSnowflake.js"); + +Router.get("/", checkAuth, (req, res) => { + let bots = db.get(`${req.user.id}.bots`); + res.render("me/index.ejs", { user: req.isAuthenticated() ? req.user : null, bots, db }); +}); + +Router.get("/form/new-server", checkAuth, (req, res) => { + let bots = db.get(`${req.user.id}.bots`); + res.render("forms/newserver.ejs", { user: req.isAuthenticated() ? req.user : null, bots, db }); +}); + +Router.post("/form/new-server", checkAuth, (req, res) => { + + let data = req.body; + console.log(data); + res.redirect("/me?e=ERROR"); + +}); + +Router.get("/form/staff-apply", checkAuth, (req, res) => { + let bots = db.get(`${req.user.id}.bots`); + if (webSettings.fetch("staff-applications.enabled") == "true") { + res.render("forms/apply-staff.ejs", { user: req.isAuthenticated() ? req.user : null, bots, db }); + } else if (webSettings.fetch("staff-applications.enabled") == "false") { + res.render("forms/apply-staff-closed.ejs", { user: req.isAuthenticated() ? req.user : null, bots, db }); + } +}); + +Router.post("/form/staff-apply", checkAuth, (req, res) => { + + let data = req.body; + console.log(data); + const embed = new Discord.RichEmbed() + .setColor(0x00A2E8) + .addField("__**Ping**__", `<@${data.id}>`) + .addField("__**User ID**__", data.id) + .addField("__**Console Email**__", data.cemail) + .addField("__**How long have you been in DBH?**__", data.joindate) + .addField("__**Previous experiences**__", data.prev) + .addField("__**Coding knowledge**__", data.coding) + .addField("__**Any projects you are proud of?**__", data.projects) + .setTimestamp() + .setFooter("New staff app submitted! "); + client.channels.get("757204887242014760").send({embed}); + + res.redirect("/me?e=COMPLETE"); + +}); + +Router.get("/requests", checkAuth, (req, res) => { + let bots = db.get(`${req.user.id}.bots`); + res.render("requests.ejs", { user: req.isAuthenticated() ? req.user : null, bots, db }); +}); + +Router.post("/requests", checkAuth, (req, res) => { + + let data = req.body; + console.log(data); + const embed = new Discord.RichEmbed() + .setColor(0x00A2E8) + .addField("__**Ping**__", `<@${data.id}>`) + .addField("__**User ID**__", data.id) + .addField("__**Console Email**__", data.cemail) + .addField("__**How long have you been in DBH?**__", data.joindate) + .addField("__**Previous experiences**__", data.prev) + .addField("__**Coding knowledge**__", data.coding) + .addField("__**Any projects you are proud of?**__", data.projects) + .setTimestamp() + .setFooter("New staff app submitted! "); + client.channels.get("757204887242014760").send({embed}); + + res.redirect("/me?e=COMPLETE"); + +}); + +module.exports = Router; + +/* + * Authorization check, if not authorized return them to the login page. + */ +function checkAuth(req, res, next) { + if (req.isAuthenticated()) { + return next(); + } else { + req.session.backURL = req.url; + + res.redirect("/login?redirect=/me"); + } +} \ No newline at end of file diff --git a/Panel/routes/stats.js b/Panel/routes/stats.js new file mode 100644 index 000000000..f98aa94be --- /dev/null +++ b/Panel/routes/stats.js @@ -0,0 +1,36 @@ +const Router = require("express").Router(); +const db = require("quick.db"); +const isSnowflake = require(process.cwd() + "/util/isSnowflake.js"); + +Router.get("/", (req, res) => { + + res.render('index.ejs', { layout: false, + user: req.isAuthenticated() ? req.user : null +}); +}); + +Router.get("/Node1", (req, res) => { + res.render('node1.ejs', { layout: false, + user: req.isAuthenticated() ? req.user : null +}); +}); + +Router.get("/Node2", (req, res) => { + res.render('node2.ejs', { layout: false, + user: req.isAuthenticated() ? req.user : null +}); +}); + +Router.get("/Node3", (req, res) => { + res.render('node3.ejs', { layout: false, + user: req.isAuthenticated() ? req.user : null +}); +}); + +Router.get("/Node4", (req, res) => { + res.render('node4.ejs', { layout: false, + user: req.isAuthenticated() ? req.user : null +}); +}); + +module.exports = Router; \ No newline at end of file diff --git a/Panel/util/MBL.js b/Panel/util/MBL.js new file mode 100644 index 000000000..33ac3577a --- /dev/null +++ b/Panel/util/MBL.js @@ -0,0 +1,43 @@ +const db = require("quick.db"); +let ids = db.get("bot.IDs"); +let fetch = require("node-fetch"); + +ids.map(async ID => { + + let res = await fetch(`https://mythicalbots.xyz/api/dan/bot/${ID}/info`); + + let response = await res.json(); + + if(response.error) return; // bot not in mbl + + let info = db.get(ID); + if(!info)return; // bot not found + + let mbl = { + invite: response.invite + } + + console.log(response.invite) + let up = "N/A"; + + if(response.uptime) { + up = response.uptime.status + } + + let botData = { + id: info.id, + keyLastUsed: info.keyLastUsed, + servers: info.servers, + users: info.users, + owner: info.owner, + client: info.client, + deleted: info.deleted, + added: info.added, + status: up, + mbl: mbl, + lastPost: info.lastPost + }; + + db.set(ID, botData); + +}); \ No newline at end of file diff --git a/Panel/util/discordAPI.js b/Panel/util/discordAPI.js new file mode 100644 index 000000000..2bfcee650 --- /dev/null +++ b/Panel/util/discordAPI.js @@ -0,0 +1,47 @@ +const unirest = require("unirest"); +const fetch = require("node-fetch"); +//const btoa = require("btoa"); + +const { CLIENT_ID, CLIENT_SECRET, DOMAIN } = process.env; + +module.exports.getUser = token => { + /* return new Promise(async function(resolve, reject) { + const creds = btoa(`${CLIENT_ID}:${CLIENT_SECRET}`); + const response = await fetch( + `https://discordapp.com/api/oauth2/token?grant_type=refresh_token&refresh_token=${token}&scope=identify&redirect_uri=${encodeURIComponent( + DOMAIN + )}/api/callback`, + { + method: "POST", + headers: { + Authorization: `Basic ${creds}` + } + } + ); + const json = await response.json(); + let data = []; + unirest + .get("https://discordapp.com/api/users/@me") + .headers({ Authorization: `Bearer ${json.access_token}` }) + .end(function(user) { + if (user["raw_body"].error) return resolve(false); + data.push(JSON.parse(user["raw_body"])); + data.push(json.refresh_token); + resolve(data); + }); + }); */ +}; + +module.exports.getBot = id => { + return new Promise(function(resolve, reject) { + let data = []; + unirest + .get(`https://discordapp.com/api/users/${id}`) + .headers({ Authorization: `Bot ${config.DiscordBot.Token}` }) + .end(function(user) { + if (user["raw_body"].error) return resolve(false); + data.push(JSON.parse(user["raw_body"])); + resolve(data); + }); + }); +}; \ No newline at end of file diff --git a/Panel/util/isSnowflake.js b/Panel/util/isSnowflake.js new file mode 100644 index 000000000..4dd4fad7e --- /dev/null +++ b/Panel/util/isSnowflake.js @@ -0,0 +1,4 @@ +module.exports = snowflake => { + return !isNaN(snowflake) && snowflake.length >= 16; +}; +// Added to make life easier \ No newline at end of file diff --git a/Panel/util/pterodactyl.js b/Panel/util/pterodactyl.js new file mode 100644 index 000000000..8964fab4e --- /dev/null +++ b/Panel/util/pterodactyl.js @@ -0,0 +1,51 @@ +const request = ('request'); +module.exports = { + + createServer: function(servername, type, userid, url, apikey) { + + //Post data + request({ + uri: "http://" + config.panelip + ":" + config.panelport + "/data?servername=" + os.hostname + //OS hostname for saving data panel sided. + "&cpu=" + cpumain + //CPU make and brand. + "&cpuload=" + cl.currentload.toFixed(2) + //CPU load but doesn't work on windows :( + "&cputhreads=" + cputhreads + //CPU threads. + "&cpucores=" + cpucores + //CPU cores + "&memused=" + ramused + //Ram used (Auto to MB, GB, TB) + "&memtotal=" + ramtotal + //Ram total (Auto to MB, GB, TB) + "&swapused=" + swapused + //Swap used (Auto to MB, GB, TB) + "&swaptotal=" + swaptotal + //Swap total (Auto to MB, GB, TB) + "&diskused=" + diskused + //Disk used (Auto to MB, GB, TB) + "&disktotal=" + disktotal + //Disk total (Auto to MB, GB, TB) + "&netrx=" + netrx + //Network received (Auto to MB, GB, TB) + "&nettx=" + nettx + //Network transmited (Auto to MB, GB, TB) + "&osplatform=" + osdata.platform + //OS platform (win32 or linux) + "&oslogofile=" + osdata.logofile + //OS logofile (Linux example: Debian/Ubuntu | Windows example: Windows) + "&osrelease=" + osdata.release + //OS release (Linux example: 9 | Windows example: 10.0.18362) + "&osuptime=" + dDisplay + hDisplay + mDisplay + sDisplay + //OS uptime (Day/Days, Hours/Hour, Minutes/Minute, Seconds/Second) + "&biosvendor=" + bios.vendor + //Bios vendor (Example: Dell Inc) + "&biosversion=" + bios.version + //Bios version (Example: A22.00) + "&biosdate=" + bios.releaseDate + //Bios release date (Example: 2018-11-29) + "&servermonitorversion=" + Version + //ServerMonitor version (Example: 1.0.1) + "&datatime=" + datatime + //Date and time (Example: 1578594094569) + "&dockercontainers=" + docker.containers + //Number of docker containers + "&dockercontainersrunning=" + docker.containersRunning + //Number of running docker containers + "&dockercontainerspaused=" + docker.containersPaused + //Number of paused docker containers + "&dockercontainersstopped=" + docker.containersStopped + //Number of stopped docker containers + "&updatetime= " + timestamp, //Last time the node sent data to the panel + method: "GET", + timeout: 5000, + followRedirect: true, + maxRedirects: 10 + }, function (error, response, body) { + + //Send request + res.send(body); + + }); + + return result; + } + +}; + + diff --git a/Panel/views/ServerOne.hbs b/Panel/views/ServerOne.hbs deleted file mode 100644 index b4656ae82..000000000 --- a/Panel/views/ServerOne.hbs +++ /dev/null @@ -1,50 +0,0 @@ - -ServerMonitor - {{Data.hostname}} - - - - {{ Data.hostname }} - - - - -
-
-

{{Data.servername}} Statistics.

-
-
-
CPU: {{Data.cpu}} (Cores: {{Data.cpucores}}, Threads: {{Data.cputhreads}})
-
-
-
CPU Load: {{Data.cpuload}}%
-
-
-
RAM (Used/Total) {{Data.memused}} / {{Data.memtotal}}
-
-
-
OS Boot Drive (Used/Total): {{Data.diskused}} / {{Data.disktotal}}
-
-
-
Network: Rx: {{Data.netrx}} Tx: {{Data.nettx}}
-
-
-
Uptime: {{Data.osuptime}}
-
-
- \ No newline at end of file diff --git a/Panel/views/admin-settings.ejs b/Panel/views/admin-settings.ejs new file mode 100644 index 000000000..a91f51c4b --- /dev/null +++ b/Panel/views/admin-settings.ejs @@ -0,0 +1,133 @@ +<%- include("./partials/header.ejs", { botInfo: false, Title: `Your Bots`, Avatar: ``, Redirect: `/me` }) %> + + + + + + + + + + + + + + + + + + + +
+
+
+
+

Server settings

+

Change/View server settings

+
+
+
+ + + +
+
+
+
+
+ + +
*
+
+
+ +
+ +
+

+
+ +
Welcome Channel *
+
+
+ +
+ +
+

- Use the selector +

+
+ +
Location? *
+
+
+ +
+ +
+

- Use the selector (ONLY WORKS FOR GAMESERVERS) +

+
+ +
+ +
+ +
+ +
+
+
+
+ +
+ + \ No newline at end of file diff --git a/Panel/views/admin.ejs b/Panel/views/admin.ejs new file mode 100644 index 000000000..fee52850b --- /dev/null +++ b/Panel/views/admin.ejs @@ -0,0 +1,70 @@ +<%- include("./partials/header.ejs", { botInfo: false, Title: `Your Bots`, Avatar: ``, Redirect: `/me` }) %> + + + + + + + + + + + + + + + + + + + +
+
+
+
+

Admin Options

+

Select where you would like to go

+
+
+
+ + + +
+
+ +
+ +
+ + \ No newline at end of file diff --git a/Panel/views/bot/index.ejs b/Panel/views/bot/index.ejs new file mode 100644 index 000000000..fb65b04e2 --- /dev/null +++ b/Panel/views/bot/index.ejs @@ -0,0 +1,136 @@ +<%- include("../partials/header.ejs", { botInfo: true, Title: `${bot.client.username}`, Avatar: `https://cdn.discordapp.com/avatars/${bot.id}/${bot.client.avatar}`, Redirect: `/bot/${bot.id}`, user }) %> + +



+
+ +
+
Page still being done <3
+
+ +
+

+
+ +
+
+
+
+
+
Bot Name
+
<%= bot.client.username %>
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
Status
+
<% if(bot.status === "online") { %> Online <% } else if(bot.status === "idle") { %> Idle <% } else { %> <%- bot.status %> <% } %>
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
Servers
+<% let servers = Number(bot.servers) %> +
<%- servers.toLocaleString() %>
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
Users
+<% let users = Number(bot.users) %> +
<%- users.toLocaleString() %>
+
+
+ +
+
+
+
+
+
+ + +
+ +
+
+
+
+
+
Bot Invite
+
+ +<% if(bot.mbl.invite) { %> + +<% } else { %> + +<% } %> + +
+
+
+ +
+
+
+
+
+ +<% if(user) { %> +<% console.log(bot) %> +<% +let allowed = ["338192747754160138","137624084572798976"]; +allowed.push(bot.owner); +%> + +<% if(allowed.includes(user.id)) { %> + +
+
+
+
+
+
Settings
+
+ +
+
+
+ +
+
+
+
+
+<% } %> + +<% } %> \ No newline at end of file diff --git a/Panel/views/bots.ejs b/Panel/views/bots.ejs new file mode 100644 index 000000000..97913381c --- /dev/null +++ b/Panel/views/bots.ejs @@ -0,0 +1,151 @@ +<%- include("./partials/header.ejs", { botInfo: false, Title: "Bots", Avatar: "", Redirect: "/bots" }) %> + + + +


+ +<% if(!q) { %> + +
+
+
All of the bot that send stats.
+ + + +
+ +
+
+ +<% for(var i=0; i < bots.length; i++) { %> + + <% let data = db.get(bots[i]) + %> + + + +<% } %> +
+
+ +<% } else { %> +<% if(q === "sort_abc") { %> +
+
+
All of bots sorted alphabetically.
+ + +
+ +
+
+ +<% for(var i=0; i < ar.length; i++) { %> + + <% let data = db.get(ar[i].id) + %> + + + +<% } %> +
+
+ + <% } %> + +<% if(q === "sort_largest") { %> +
+
+
All of bots sorted alphabetically.
+ + + +
+ +
+
+ +<% for(var i=0; i < lar.length; i++) { %> + + <% let data = db.get(lar[i].id) + %> + + + +<% } %> +
+
+ + <% } %> + +<% } %> + + + \ No newline at end of file diff --git a/Panel/views/error.ejs b/Panel/views/error.ejs new file mode 100644 index 000000000..f40a0f5ed --- /dev/null +++ b/Panel/views/error.ejs @@ -0,0 +1,9 @@ +<%- include("./partials/header.ejs", { botInfo: false, Title: "Home", Avatar: "", Redirect: "/me" }) %> + + +



+ +
+
<%- message %>
+ +
\ No newline at end of file diff --git a/Panel/views/feedback.ejs b/Panel/views/feedback.ejs new file mode 100644 index 000000000..dbecfd559 --- /dev/null +++ b/Panel/views/feedback.ejs @@ -0,0 +1,74 @@ +<%- include("./partials/header.ejs", { botInfo: false, Title: "Bots", Avatar: "", Redirect: "/bots" }) %> + + + + + + + + + + + + + + +
+
+
+
+
+
+
+

Feedback Area

+
+Welcome to the Feedback Area of DanBot Hosting. You can report bugs & suggestions via this forms.

Before posting, please verify if your bug/suggestion isn't listed. +

+
+ +
+
+
+
+
+
+
+
+
+

I would like to file a bug report.

+
+
+ + +
+ +
+
+
+
+
+

I have a suggestion!

+
+
+ + +
+ +
+
+
+
+









+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/Panel/views/forms/apply-staff-closed.ejs b/Panel/views/forms/apply-staff-closed.ejs new file mode 100644 index 000000000..939ba75e7 --- /dev/null +++ b/Panel/views/forms/apply-staff-closed.ejs @@ -0,0 +1,76 @@ +<%- include("../partials/header.ejs", { botInfo: false, Title: `Your Bots`, Avatar: ``, Redirect: `/me` }) %> + + + + + + + + + + + + + + + + + + + +
+
+
+
+

Staff application

+

Apply for staff

+

Please give as much information as possible.

+
+
+
+ + + +
+
+
+
+
+ + +
Sorry! Staff applications are closed right now.
+
We will announce when we are looking for more staff
+ +
+
+
+
+ +
+ + \ No newline at end of file diff --git a/Panel/views/forms/apply-staff.ejs b/Panel/views/forms/apply-staff.ejs new file mode 100644 index 000000000..a72df1952 --- /dev/null +++ b/Panel/views/forms/apply-staff.ejs @@ -0,0 +1,128 @@ +<%- include("../partials/header.ejs", { botInfo: false, Title: `Your Bots`, Avatar: ``, Redirect: `/me` }) %> + + + + + + + + + + + + + + + + + + + +
+
+
+
+

Staff application

+

Apply for staff

+

Please give as much information as possible.

+
+
+
+ + + +
+
+
+
+
+ + +
Console Email: *
+
+
+ +
+ +
+
+ +
How long have you been in DBH? *
+
+
+ +
+ +
+
+ +
Previous experiences: *
+
+
+ +
+ +
+
+
Coding knowledge: *
+
+
+ +
+ +
+
+
Any projects you are proud of? *
+
+
+ +
+ +
+ +
+ +
+ +
+ +
+
+
+
+ +
+ + \ No newline at end of file diff --git a/Panel/views/forms/newserver.ejs b/Panel/views/forms/newserver.ejs new file mode 100644 index 000000000..be2187334 --- /dev/null +++ b/Panel/views/forms/newserver.ejs @@ -0,0 +1,130 @@ +<%- include("../partials/header.ejs", { botInfo: false, Title: `Your Bots`, Avatar: ``, Redirect: `/me` }) %> + + + + + + + + + + + + + + + + + + + +
+
+
+
+

New Server

+

Create a new server

+
+
+
+ + + +
+
+
+
+
+ + +
Server Name *
+
+
+ +
+ +
+

- Ex: Baby Witch Help +

+
+ +
What type of Server? *
+
+
+ +
+ +
+

- Use the selector +

+
+ +
Location? *
+
+
+ +
+ +
+

- Use the selector (ONLY WORKS FOR GAMESERVERS) +

+
+ +
+ +
+ +
+ +
+
+
+
+ +
+ + \ No newline at end of file diff --git a/Panel/views/index.ejs b/Panel/views/index.ejs new file mode 100644 index 000000000..17cb24b51 --- /dev/null +++ b/Panel/views/index.ejs @@ -0,0 +1,172 @@ +<%- include("./partials/header.ejs", { botInfo: false, Title: "Home", Avatar: "", Redirect: "/me" }) %> + + +


+ +


+ + +
+ +
+
CPU: <%- nodeData.fetch("Node1.cpu") %> (Cores: <%- nodeData.fetch("Node1.cpucores") %>, Threads: <%- nodeData.fetch("Node1.cputhreads") %>)
+
+
+
CPU Load: <%- nodeData.fetch("Node1.cpuload") %>%
+
+
+
RAM (Used/Total) <%- nodeData.fetch("Node1.memused") %> / <%- nodeData.fetch("Node1.memtotal") %>
+
+
+
SWAP (Used/Total) <%- nodeData.fetch("Node1.swapused") %> / <%- nodeData.fetch("Node1.swaptotal") %>
+
+
+
Host storage drive (Used/Total): <%- nodeData.fetch("Node1.diskused") %> / <%- nodeData.fetch("Node1.disktotal") %>
+
+
+
Network: Rx: <%- nodeData.fetch("Node1.netrx") %> Tx: <%- nodeData.fetch("Node1.nettx") %>
+
+
+
Uptime: <%- nodeData.fetch("Node1.osuptime") %>
+
+
+
Last Updated: <%- nodeData.fetch("Node1.updatetime") %>
+
+
+
Speedtest (Updates every 6hours) | Ping: <%- nodeData.fetch("Node1-speedtest.ping") %>ms
Download: <%- nodeData.fetch("Node1-speedtest.download") %>Mbps, Upload: <%- nodeData.fetch("Node1-speedtest.upload") %>Mbps, Last Updated: <%- nodeData.fetch("Node1-speedtest.updatetime") %>
+
+ + +
+
CPU: <%- nodeData.fetch("Node2.cpu") %> (Cores: <%- nodeData.fetch("Node2.cpucores") %>, Threads: <%- nodeData.fetch("Node2.cputhreads") %>)
+
+
+
CPU Load: <%- nodeData.fetch("Node2.cpuload") %>%
+
+
+
RAM (Used/Total) <%- nodeData.fetch("Node2.memused") %> / <%- nodeData.fetch("Node2.memtotal") %>
+
+
+
SWAP (Used/Total) <%- nodeData.fetch("Node2.swapused") %> / <%- nodeData.fetch("Node2.swaptotal") %>
+
+
+
Host storage drive (Used/Total): <%- nodeData.fetch("Node2.diskused") %> / <%- nodeData.fetch("Node2.disktotal") %>
+
+
+
Network: Rx: <%- nodeData.fetch("Node2.netrx") %> Tx: <%- nodeData.fetch("Node2.nettx") %>
+
+
+
Uptime: <%- nodeData.fetch("Node2.osuptime") %>
+
+
+
Last Updated: <%- nodeData.fetch("Node2.updatetime") %>
+
+
+
Speedtest (Updates every 6hours) | Ping: <%- nodeData.fetch("Node2-speedtest.ping") %>ms
Download: <%- nodeData.fetch("Node2-speedtest.download") %>Mbps, Upload: <%- nodeData.fetch("Node2-speedtest.upload") %>Mbps, Last Updated: <%- nodeData.fetch("Node2-speedtest.updatetime") %>
+
+ + +
+
CPU: <%- nodeData.fetch("Node3.cpu") %> (Cores: <%- nodeData.fetch("Node3.cpucores") %>, Threads: <%- nodeData.fetch("Node3.cputhreads") %>)
+
+
+
CPU Load: <%- nodeData.fetch("Node3.cpuload") %>%
+
+
+
RAM (Used/Total) <%- nodeData.fetch("Node3.memused") %> / <%- nodeData.fetch("Node3.memtotal") %>
+
+
+
SWAP (Used/Total) <%- nodeData.fetch("Node3.swapused") %> / <%- nodeData.fetch("Node3.swaptotal") %>
+
+
+
Host storage drive (Used/Total): <%- nodeData.fetch("Node3.diskused") %> / <%- nodeData.fetch("Node3.disktotal") %>
+
+
+
Network: Rx: <%- nodeData.fetch("Node3.netrx") %> Tx: <%- nodeData.fetch("Node3.nettx") %>
+
+
+
Uptime: <%- nodeData.fetch("Node3.osuptime") %>
+
+
+
Last Updated: <%- nodeData.fetch("Node3.updatetime") %>
+
+
+
Speedtest (Updates every 6hours) | Ping: <%- nodeData.fetch("Node3-speedtest.ping") %>ms
Download: <%- nodeData.fetch("Node3-speedtest.download") %>Mbps, Upload: <%- nodeData.fetch("Node3-speedtest.upload") %>Mbps, Last Updated: <%- nodeData.fetch("Node3-speedtest.updatetime") %>
+
+ + +
+
CPU: <%- nodeData.fetch("Node4.cpu") %> (Cores: <%- nodeData.fetch("Node4.cpucores") %>, Threads: <%- nodeData.fetch("Node4.cputhreads") %>)
+
+
+
CPU Load: <%- nodeData.fetch("Node4.cpuload") %>%
+
+
+
RAM (Used/Total) <%- nodeData.fetch("Node4.memused") %> / <%- nodeData.fetch("Node4.memtotal") %>
+
+
+
SWAP (Used/Total) <%- nodeData.fetch("Node4.swapused") %> / <%- nodeData.fetch("Node4.swaptotal") %>
+
+
+
Host storage drive (Used/Total): <%- nodeData.fetch("Node4.diskused") %> / <%- nodeData.fetch("Node4.disktotal") %>
+
+
+
Network: Rx: <%- nodeData.fetch("Node4.netrx") %> Tx: <%- nodeData.fetch("Node4.nettx") %>
+
+
+
Uptime: <%- nodeData.fetch("Node4.osuptime") %>
+
+
+
Last Updated: <%- nodeData.fetch("Node4.updatetime") %>
+
+
+
Speedtest (Updates every 6hours) | Ping: <%- nodeData.fetch("Node4-speedtest.ping") %>ms
Download: <%- nodeData.fetch("Node4-speedtest.download") %>Mbps, Upload: <%- nodeData.fetch("Node4-speedtest.upload") %>Mbps, Last Updated: <%- nodeData.fetch("Node4-speedtest.updatetime") %>
+
+ +
+ + + \ No newline at end of file diff --git a/Panel/views/index.hbs b/Panel/views/index.hbs deleted file mode 100644 index 7f81ada3f..000000000 --- a/Panel/views/index.hbs +++ /dev/null @@ -1,50 +0,0 @@ - -ServerMonitor - - - - {{ info.hostname }} - - - - -
-
-

{{info.servername}} Statistics.

-
-
-
CPU: {{info.cpu}} (Cores: {{info.cpucores}}, Threads: {{info.cputhreads}})
-
-
-
CPU Load: {{info.cpuload}}%
-
-
-
RAM (Used/Total) {{info.memused}} / {{info.memtotal}}
-
-
-
OS Boot Drive (Used/Total): {{info.diskused}} / {{info.disktotal}}
-
-
-
Network: Rx: {{info.netrx}} Tx: {{info.nettx}}
-
-
-
Uptime: {{info.osuptime}}
-
-
- \ No newline at end of file diff --git a/Panel/views/main.ejs b/Panel/views/main.ejs new file mode 100644 index 000000000..8530a6404 --- /dev/null +++ b/Panel/views/main.ejs @@ -0,0 +1,41 @@ +<%- include("./partials/header.ejs", { botInfo: false, Title: "Home", Avatar: "", Redirect: "/me" }) %> +




+ + +
+

Welcome To DanBot Hosting

+

Free and fast hosting, available for everyone to use.

+ +
+ + we're still working on this page so check back soon! + +
+
+ +

About Us

+ + + \ No newline at end of file diff --git a/Panel/views/me/index.ejs b/Panel/views/me/index.ejs new file mode 100644 index 000000000..fa6f68a1c --- /dev/null +++ b/Panel/views/me/index.ejs @@ -0,0 +1,57 @@ +<%- include("../partials/header.ejs", { botInfo: false, Title: `Your Bots`, Avatar: ``, Redirect: `/me` }) %> + + +


+ +
+
+
+
+
+
+ +

<%- user.username%>#<%- user.discriminator %>

+
You can find your Bots & More here.

+
+
+
+
+ +
+ +<% if(bots) { %> +
+
+ + +<% for(var i=0; i < bots.length; i++) { %> + + <% let data = db.get(bots[i]) %> + + + +<% } %> +
+
+ +<% } else { %> +
+
+
Sorry no bots were found.
This might be a code issue or you have no bots.
+
+<% } %> \ No newline at end of file diff --git a/Panel/views/me/user.ejs b/Panel/views/me/user.ejs new file mode 100644 index 000000000..1cd0ad607 --- /dev/null +++ b/Panel/views/me/user.ejs @@ -0,0 +1,139 @@ +<%- include("../partials/header.ejs", { botInfo: false, Title: `Your Bots`, Avatar: `${avatar}`, Redirect: `/me` }) %> + + + +
+
+
+
+
+
+ + +

<%= User.tag %>

+ + + + +

<%- presence %>

+ + + <% + let flags = use.public_flags; + let userFlags = []; + + if ((flags & 1) === 1) userFlags.push("Discord Employee"); + if ((flags & 2) === 2) userFlags.push("Discord Partner"); + if ((flags & 4) === 4) userFlags.push("HypeSquad Events"); + if ((flags & 8) === 8) userFlags.push("Bug Hunter Level 1"); + if ((flags & 64) === 64) userFlags.push("HypeSquad House of Bravery"); + else if ((flags & 128) === 128) + userFlags.push("HypeSquad House of Brilliance"); + else if ((flags & 256) === 256) + userFlags.push("HypeSquad House of Balance"); + if ((flags & 512) === 512) userFlags.push("Early_Supporter"); + if ((flags & 1024) === 1024) userFlags.push("Team User"); + if ((flags & 4096) === 4096) userFlags.push("System"); + if ((flags & 16384) === 16384) userFlags.push("Bug Hunter Level 2"); + if ((flags & 131072) === 131072) + userFlags.push("Verified_Bot_Developer"); + + + + %> + + + + + + + +

+ + + + <% if(userFlags.includes("Verified_Bot_Developer")) { %> + + <% } %> + + <% if(userFlags.includes("Early_Supporter")) { %> + + <% } %> + +

+ +
+
+
+
+
+
+ +<% if(bots) { %> +
+
+
All of <%= User.tag %> bots.
+
+ +
+
+ +<% for(var i=0; i < bots.length; i++) { %> + + + <% let data = db.get(bots[i]) %> + + + +<% } %> + + +
+
+<% } else { %> +
+
+
Sorry no bots were found.
+
+<% } %> \ No newline at end of file diff --git a/Panel/views/node1.ejs b/Panel/views/node1.ejs new file mode 100644 index 000000000..1d6af26a9 --- /dev/null +++ b/Panel/views/node1.ejs @@ -0,0 +1,57 @@ +<%- include("./partials/header.ejs", { botInfo: false, Title: "Node 1 Stats", Avatar: "", Redirect: "/me" }) %> + + +


+ +


+ + + +
+
+

All Stats

+
+
+
CPU: <%- nodeData.fetch("Node1.cpu") %> (Cores: <%- nodeData.fetch("Node1.cpucores") %>, Threads: <%- nodeData.fetch("Node1.cputhreads") %>)
+
+
+
CPU Load: <%- nodeData.fetch("Node1.cpuload") %>%
+
+
+
RAM (Used/Total) <%- nodeData.fetch("Node1.memused") %> / <%- nodeData.fetch("Node1.memtotal") %>
+
+
+
SWAP (Used/Total) <%- nodeData.fetch("Node1.swapused") %> / <%- nodeData.fetch("Node1.swaptotal") %>
+
+
+
Host storage drive (Used/Total): <%- nodeData.fetch("Node1.diskused") %> / <%- nodeData.fetch("Node1.total") %>
+
+
+
Network: Rx: <%- nodeData.fetch("Node1.netrx") %> Tx: <%- nodeData.fetch("Node1.nettx") %>
+
+
+
Uptime: <%- nodeData.fetch("Node1.osuptime") %>
+
+
+
Last Updated: <%- nodeData.fetch("Node1.updatetime") %>
+
+
+
Speedtest (Updates every 6hours) | Ping: <%- nodeData.fetch("Node1-speedtest.ping") %>ms
Download: <%- nodeData.fetch("Node1-speedtest.download") %>Mbps, Upload: <%- nodeData.fetch("Node1-speedtest.upload") %>Mbps, Last Updated: <%- nodeData.fetch("Node1-speedtest.updatetime") %>
+
+ + + +
\ No newline at end of file diff --git a/Panel/views/node2.ejs b/Panel/views/node2.ejs new file mode 100644 index 000000000..ec40424e3 --- /dev/null +++ b/Panel/views/node2.ejs @@ -0,0 +1,57 @@ +<%- include("./partials/header.ejs", { botInfo: false, Title: "Node 2 Stats", Avatar: "", Redirect: "/me" }) %> + + +


+ +


+ + + +
+
+

All Stats

+
+
+
CPU: <%- nodeData.fetch("Node2.cpu") %> (Cores: <%- nodeData.fetch("Node2.cpucores") %>, Threads: <%- nodeData.fetch("Node2.cputhreads") %>)
+
+
+
CPU Load: <%- nodeData.fetch("Node2.cpuload") %>%
+
+
+
RAM (Used/Total) <%- nodeData.fetch("Node2.memused") %> / <%- nodeData.fetch("Node2.memtotal") %>
+
+
+
SWAP (Used/Total) <%- nodeData.fetch("Node2.swapused") %> / <%- nodeData.fetch("Node2.swaptotal") %>
+
+
+
Host storage drive (Used/Total): <%- nodeData.fetch("Node2.diskused") %> / <%- nodeData.fetch("Node2.total") %>
+
+
+
Network: Rx: <%- nodeData.fetch("Node2.netrx") %> Tx: <%- nodeData.fetch("Node2.nettx") %>
+
+
+
Uptime: <%- nodeData.fetch("Node2.osuptime") %>
+
+
+
Last Updated: <%- nodeData.fetch("Node2.updatetime") %>
+
+
+
Speedtest (Updates every 6hours) | Ping: <%- nodeData.fetch("Node2-speedtest.ping") %>ms
Download: <%- nodeData.fetch("Node2-speedtest.download") %>Mbps, Upload: <%- nodeData.fetch("Node2-speedtest.upload") %>Mbps, Last Updated: <%- nodeData.fetch("Node2-speedtest.updatetime") %>
+
+ + + +
\ No newline at end of file diff --git a/Panel/views/node3.ejs b/Panel/views/node3.ejs new file mode 100644 index 000000000..bff63f35b --- /dev/null +++ b/Panel/views/node3.ejs @@ -0,0 +1,57 @@ +<%- include("./partials/header.ejs", { botInfo: false, Title: "Node 3 Stats", Avatar: "", Redirect: "/me" }) %> + + +


+ +


+ + + +
+
+

All Stats

+
+
+
CPU: <%- nodeData.fetch("Node3.cpu") %> (Cores: <%- nodeData.fetch("Node3.cpucores") %>, Threads: <%- nodeData.fetch("Node3.cputhreads") %>)
+
+
+
CPU Load: <%- nodeData.fetch("Node3.cpuload") %>%
+
+
+
RAM (Used/Total) <%- nodeData.fetch("Node3.memused") %> / <%- nodeData.fetch("Node3.memtotal") %>
+
+
+
SWAP (Used/Total) <%- nodeData.fetch("Node3.swapused") %> / <%- nodeData.fetch("Node3.swaptotal") %>
+
+
+
Host storage drive (Used/Total): <%- nodeData.fetch("Node3.diskused") %> / <%- nodeData.fetch("Node3.total") %>
+
+
+
Network: Rx: <%- nodeData.fetch("Node3.netrx") %> Tx: <%- nodeData.fetch("Node3.nettx") %>
+
+
+
Uptime: <%- nodeData.fetch("Node3.osuptime") %>
+
+
+
Last Updated: <%- nodeData.fetch("Node3.updatetime") %>
+
+
+
Speedtest (Updates every 6hours) | Ping: <%- nodeData.fetch("Node3-speedtest.ping") %>ms
Download: <%- nodeData.fetch("Node3-speedtest.download") %>Mbps, Upload: <%- nodeData.fetch("Node3-speedtest.upload") %>Mbps, Last Updated: <%- nodeData.fetch("Node3-speedtest.updatetime") %>
+
+ + + +
\ No newline at end of file diff --git a/Panel/views/node4.ejs b/Panel/views/node4.ejs new file mode 100644 index 000000000..6ab1ac437 --- /dev/null +++ b/Panel/views/node4.ejs @@ -0,0 +1,57 @@ +<%- include("./partials/header.ejs", { botInfo: false, Title: "Node 4 Stats", Avatar: "", Redirect: "/me" }) %> + + +


+ +


+ + + +
+
+

All Stats

+
+
+
CPU: <%- nodeData.fetch("Node4.cpu") %> (Cores: <%- nodeData.fetch("Node4.cpucores") %>, Threads: <%- nodeData.fetch("Node4.cputhreads") %>)
+
+
+
CPU Load: <%- nodeData.fetch("Node4.cpuload") %>%
+
+
+
RAM (Used/Total) <%- nodeData.fetch("Node4.memused") %> / <%- nodeData.fetch("Node4.memtotal") %>
+
+
+
SWAP (Used/Total) <%- nodeData.fetch("Node4.swapused") %> / <%- nodeData.fetch("Node4.swaptotal") %>
+
+
+
Host storage drive (Used/Total): <%- nodeData.fetch("Node4.diskused") %> / <%- nodeData.fetch("Node4.total") %>
+
+
+
Network: Rx: <%- nodeData.fetch("Node4.netrx") %> Tx: <%- nodeData.fetch("Node4.nettx") %>
+
+
+
Uptime: <%- nodeData.fetch("Node4.osuptime") %>
+
+
+
Last Updated: <%- nodeData.fetch("Node4.updatetime") %>
+
+
+
Speedtest (Updates every 6hours) | Ping: <%- nodeData.fetch("Node4-speedtest.ping") %>ms
Download: <%- nodeData.fetch("Node4-speedtest.download") %>Mbps, Upload: <%- nodeData.fetch("Node4-speedtest.upload") %>Mbps, Last Updated: <%- nodeData.fetch("Node4-speedtest.updatetime") %>
+
+ + + +
\ No newline at end of file diff --git a/Panel/views/partials/header.ejs b/Panel/views/partials/header.ejs new file mode 100644 index 000000000..1cf869f03 --- /dev/null +++ b/Panel/views/partials/header.ejs @@ -0,0 +1,284 @@ + + + + + + + + +<%= Title %> | DanBot Hosting +<% if(botInfo) { %> + + +<% } else { %> + + +<% } %> + + + + + + + + + + + + + + + + + + + + + + + + + + + +<% if(botInfo) { %> + + + + + + + + + + + + +<% } %> + + + + + + + + + + + \ No newline at end of file diff --git a/Panel/views/partials/header.hbs b/Panel/views/partials/header.hbs new file mode 100644 index 000000000..6050c7f61 --- /dev/null +++ b/Panel/views/partials/header.hbs @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + +
+ + + + + + + DanBot Hosting Stats + + + + + + +
+

+ You need JavaScript enabled to view this page :( +

+
+
+
+ + + +
\ No newline at end of file diff --git a/Panel/views/partners.ejs b/Panel/views/partners.ejs new file mode 100644 index 000000000..060ab509f --- /dev/null +++ b/Panel/views/partners.ejs @@ -0,0 +1,28 @@ +<%- include("./partials/header.ejs", { botInfo: false, Title: "Partners", Avatar: "", Redirect: "/partners" }) %> + + + +
+
+
Our Partners!
+
+ +
+
+ +
+
+ + +
+
Mythical Bot List
+
+Mythical Bot List, do you ever feel like your bot hasn't experienced quality advertising? Have you ever dreamt of having your bot on the front page of a botlist being featured? Well Mythical Bot List is your place! +
+
+ +0? + +
+
+
\ No newline at end of file diff --git a/Panel/views/request.ejs b/Panel/views/request.ejs new file mode 100644 index 000000000..db89f9f45 --- /dev/null +++ b/Panel/views/request.ejs @@ -0,0 +1,108 @@ +<%- include("./partials/header.ejs", { botInfo: false, Title: `Your Bots`, Avatar: ``, Redirect: `/me` }) %> + + + + + + + + + + + + + + + + + + + +
+
+
+
+

Requests

+

View and submit a new request here!

+
+
+
+ +
+
+
+
+
+ + +
*
+
+
+ +
+ +
+

+
+ +
Welcome Channel *
+
+
+ +
+ +
+

- Use the selector +

+
+ +
Location? *
+
+
+ +
+ +
+

- Use the selector (ONLY WORKS FOR GAMESERVERS) +

+
+ +
+ +
+ +
+ +
+
+
+
+ +
+ + \ No newline at end of file diff --git a/Panel/views/requests-admin.ejs b/Panel/views/requests-admin.ejs new file mode 100644 index 000000000..a91f51c4b --- /dev/null +++ b/Panel/views/requests-admin.ejs @@ -0,0 +1,133 @@ +<%- include("./partials/header.ejs", { botInfo: false, Title: `Your Bots`, Avatar: ``, Redirect: `/me` }) %> + + + + + + + + + + + + + + + + + + + +
+
+
+
+

Server settings

+

Change/View server settings

+
+
+
+ + + +
+
+
+
+
+ + +
*
+
+
+ +
+ +
+

+
+ +
Welcome Channel *
+
+
+ +
+ +
+

- Use the selector +

+
+ +
Location? *
+
+
+ +
+ +
+

- Use the selector (ONLY WORKS FOR GAMESERVERS) +

+
+ +
+ +
+ +
+ +
+
+
+
+ +
+ + \ No newline at end of file