From 94fea37d627a7f11a67d4eb472300dfa5abaafae Mon Sep 17 00:00:00 2001 From: Minteck Date: Tue, 24 May 2022 23:06:46 +0200 Subject: Pair programming with @CloudburstSys --- .idea/copyright/MIT.xml | 6 ++ .idea/copyright/profiles_settings.xml | 3 + LICENSE | 21 ++++++ index.js | 62 ++++++++++++++---- public/assets/custom.css | 29 ++++++++ public/assets/scroll.js | 25 +++++++ public/assets/servers.js | 38 +++++++++++ refresh.js | 87 ------------------------ refresh/pluralkit.js | 120 ++++++++++++++++++++++++++++++++++ refresh/servers.js | 112 +++++++++++++++++++++++++++++++ views/index.ejs | 24 +++++++ views/partials/footer.ejs | 24 +++++++ views/partials/header.ejs | 24 +++++++ views/servers.ejs | 66 +++++++++++++++++++ 14 files changed, 541 insertions(+), 100 deletions(-) create mode 100644 .idea/copyright/MIT.xml create mode 100644 .idea/copyright/profiles_settings.xml create mode 100644 LICENSE create mode 100644 public/assets/servers.js delete mode 100644 refresh.js create mode 100644 refresh/pluralkit.js create mode 100644 refresh/servers.js create mode 100644 views/servers.ejs diff --git a/.idea/copyright/MIT.xml b/.idea/copyright/MIT.xml new file mode 100644 index 0000000..e75ed99 --- /dev/null +++ b/.idea/copyright/MIT.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..c3ba54a --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8cef2b9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022- Equestria.dev Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/index.js b/index.js index 797791a..f0cb4fd 100644 --- a/index.js +++ b/index.js @@ -1,39 +1,75 @@ +/* + * MIT License + * + * Copyright (c) 2022- Equestria.dev Developers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + // noinspection JSUnresolvedVariable,HttpUrlsUsage const express = require('express'); const app = express(); -app.use(express.static('public')); -app.set("view engine", "ejs"); - +// Public pages app.get('/', (req, res) => { res.render("index"); }); +app.get('/servers', (req, res) => { + res.render("servers"); +}); + // API -var serverCache = {}; +let serverCache = {}; +let pluralCache = {}; app.get("/api/servers", (req, res) => { res.json(serverCache); }); -const refresh = require('./refresh'); -setInterval(() => { +// Refresh handling +const refresh = require('./refresh/servers'); +const pkRefresh = require('./refresh/pluralkit'); +setInterval(cacheReload, 300000); + +function cacheReload() { console.log("Running refresh..."); refresh().then(data => { - console.log("Refresh done!"); + console.log("Refresh halfway done!"); serverCache = data; + pkRefresh().then(data => { + console.log("Refresh totally done!"); + pluralCache = data; + }); }); -}, 300000); +} + +// Server +app.use(express.static('public')); +app.set("view engine", "ejs"); const server = app.listen(8099, function () { let host = server.address().address let port = server.address().port console.log("Vapor Trail server listening at http://%s:%s", host, port) - console.log("Running refresh..."); - refresh().then(data => { - console.log("Refresh done!"); - serverCache = data; - }); + cacheReload(); }) \ No newline at end of file diff --git a/public/assets/custom.css b/public/assets/custom.css index d0a2f90..2fd749b 100644 --- a/public/assets/custom.css +++ b/public/assets/custom.css @@ -1,3 +1,28 @@ +/* + * MIT License + * + * Copyright (c) 2022- Equestria.dev Developers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + /** {*/ /* font-family: "Comic Sans MS", sans-serif !important;*/ /*}*/ @@ -76,4 +101,8 @@ html, body { .home-people-text { text-align: center; font-size: 36px; +} + +#navbar-skipper { + margin-top: 56px; } \ No newline at end of file diff --git a/public/assets/scroll.js b/public/assets/scroll.js index a0c6b78..882ad0d 100644 --- a/public/assets/scroll.js +++ b/public/assets/scroll.js @@ -1,3 +1,28 @@ +/* + * MIT License + * + * Copyright (c) 2022- Equestria.dev Developers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + function posY(elm) { var test = elm, top = 0; diff --git a/public/assets/servers.js b/public/assets/servers.js new file mode 100644 index 0000000..6c6d129 --- /dev/null +++ b/public/assets/servers.js @@ -0,0 +1,38 @@ +/* + * MIT License + * + * Copyright (c) 2022- Equestria.dev Developers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +const SERVER_API = "/api/servers"; + +// apparently document.onload is never called??? +function a() { + console.log("a"); + fetch(SERVER_API) + .then(data => data = data.json()) + .then(data => { + console.log(data); + document.getElementById("canterlot").getElementsByClassName("cpu-type")[0].innerHTML = data.canterlot.cpu.model; + }); +} + +a(); \ No newline at end of file diff --git a/refresh.js b/refresh.js deleted file mode 100644 index 212a4cb..0000000 --- a/refresh.js +++ /dev/null @@ -1,87 +0,0 @@ -const dns = require("dns"); -const superagent = require("superagent"); - -function resolveDNSAsync(domain) { - return new Promise((res, rej) => { - if (!/([\--z]+\.)?([\--z]+)\.([A-z]+)/g.test(domain)) return rej("Not a valid domain"); - - const options = { - family: 4, - hints: dns.ADDRCONFIG | dns.V4MAPPED - }; - dns.lookup(domain, options, (err, address, family) => { - if (err) return rej(err); - res(address); - }); - }); -} - -function roundToTwo(num) { - return +(Math.round(num + "e+2") + "e-2"); -} - -module.exports = () => { - // Code entered here will be run every 5 minutes - return new Promise(async (res, rej) => { - let servers = { - canterlot: [await resolveDNSAsync("canterlot.equestria.dev"), 52937], - ponyville: [await resolveDNSAsync("ponyville-ipv4.equestria.dev"), 52937], - bridlewood: [await resolveDNSAsync("bridlewood.equestria.dev"), 52937], - zephyrheights: [await resolveDNSAsync("zephyrheights-ipv4.equestria.dev"), 52938], - maretimebay: [await resolveDNSAsync("maretimebay-ipv4.equestria.dev"), 52937] - } - - let stats = {} - - for (let key in Object.keys(servers)) { - key = Object.keys(servers)[key]; - let status = { - online: null, - cpu: null, - memory: null, - os: null, - uptime: null - } - - superagent.get(`http://${servers[key][0]}:${servers[key][1]}/json`) - .timeout({ - response: 5000, - }) - .then(data => data = data.body) - .then(data => { - status.online = true; - status.cpu = data.cpu; - status.cpu.load = Math.floor(data.cpu.load * 100); - status.memory = data.memory; - status.memory.swap.used = roundToTwo(data.memory.swap.used / 1073741824); - status.memory.swap.free = roundToTwo(data.memory.swap.free / 1073741824); - status.memory.swap.total = roundToTwo(data.memory.swap.total / 1073741824); - status.memory.physical.used = roundToTwo(data.memory.physical.used / 1073741824); - status.memory.physical.free = roundToTwo(data.memory.physical.free / 1073741824); - status.memory.physical.total = roundToTwo(data.memory.physical.total / 1073741824); - status.os = data.os; - status.uptime = data.uptime; - }) - .catch(reason => { - if (reason.timeout) { - // We timed out. - status.online = false; - } else { - if(reason.code == "ECONNREFUSED") { - status.online = false; - console.warn(`Server ${key} refused our connection. `) - } else { - console.error(reason); - } - } - }) - .finally(() => { - stats[key] = status; - - if(Object.keys(stats).length == Object.keys(servers).length) { - res(stats); - } - }); - } - }); -} diff --git a/refresh/pluralkit.js b/refresh/pluralkit.js new file mode 100644 index 0000000..a0786e3 --- /dev/null +++ b/refresh/pluralkit.js @@ -0,0 +1,120 @@ +// noinspection JSDeprecatedSymbols,JSPrimitiveTypeWrapperUsage + +/* + * MIT License + * + * Copyright (c) 2022- Equestria.dev Developers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +const superagent = require("superagent"); +module.exports = () => { + // Code entered here will be run every 5 minutes + return new Promise(async (res) => { + let systems = [ + "gdapd", // Moonshine System + "ynmuc" // Cloudburst System + ] + + let stats = {} + + for (let system of systems) { + let status = { + available: true, + general: null, + members: null, + fronters: null, + switches: null + } + + superagent.get(`https://api.pluralkit.me/v2/systems/${system}`) + .timeout({ + response: 5000, + }) + .then(data => data = data.body) + .then(data => { + status.general = data; + superagent.get(`https://api.pluralkit.me/v2/systems/${system}/members`) + .timeout({ + response: 5000, + }) + .then(data => data = data.body) + .then(data => { + status.members = data; + superagent.get(`https://api.pluralkit.me/v2/systems/${system}/fronters`) + .timeout({ + response: 5000, + }) + .then(data => data = data.body) + .then(data => { + status.fronters = data; + }) + .catch(reason => { + if (reason.timeout) { + // We timed out. + status.available = false; + } else { + if(reason.code === "ECONNREFUSED") { + status.available = false; + console.warn("Error querying PluralKit API.") + } else { + console.error(reason); + } + } + }) + .finally(() => { + stats[system] = status; + + if(Object.keys(stats).length === systems.length) { + res(stats); + } + }); + }) + .catch(reason => { + if (reason.timeout) { + // We timed out. + status.available = false; + } else { + if(reason.code === "ECONNREFUSED") { + status.available = false; + console.warn("Error querying PluralKit API.") + } else { + console.error(reason); + } + } + }) + }) + .catch(reason => { + if (reason.timeout) { + // We timed out. + status.available = false; + } else { + if(reason.code === "ECONNREFUSED") { + status.available = false; + console.warn("Error querying PluralKit API.") + } else { + console.error(reason); + } + } + }) + } + }); +} diff --git a/refresh/servers.js b/refresh/servers.js new file mode 100644 index 0000000..e6b7d25 --- /dev/null +++ b/refresh/servers.js @@ -0,0 +1,112 @@ +/* + * MIT License + * + * Copyright (c) 2022- Equestria.dev Developers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +const dns = require("dns"); +const superagent = require("superagent"); + +function resolveDNSAsync(domain) { + return new Promise((res, rej) => { + if (!/([\--z]+\.)?([\--z]+)\.([A-z]+)/g.test(domain)) return rej("Not a valid domain"); + + const options = { + family: 4, + hints: dns.ADDRCONFIG | dns.V4MAPPED + }; + dns.lookup(domain, options, (err, address) => { + if (err) return rej(err); + res(address); + }); + }); +} + +function roundToTwo(num) { + return +(Math.round(num + "e+2") + "e-2"); +} + +module.exports = () => { + // Code entered here will be run every 5 minutes + return new Promise(async (res) => { + let servers = { + canterlot: [await resolveDNSAsync("canterlot.equestria.dev"), 52937], + ponyville: [await resolveDNSAsync("ponyville-ipv4.equestria.dev"), 52937], + bridlewood: [await resolveDNSAsync("bridlewood.equestria.dev"), 52937], + zephyrheights: [await resolveDNSAsync("zephyrheights-ipv4.equestria.dev"), 52938], + maretimebay: [await resolveDNSAsync("maretimebay-ipv4.equestria.dev"), 52937] + } + + let stats = {} + + for (let key in Object.keys(servers)) { + key = Object.keys(servers)[key]; + let status = { + online: null, + cpu: null, + memory: null, + os: null, + uptime: null + } + + superagent.get(`http://${servers[key][0]}:${servers[key][1]}/json`) + .timeout({ + response: 5000, + }) + .then(data => data = data.body) + .then(data => { + status.online = true; + status.cpu = data.cpu; + status.cpu.load = Math.floor(data.cpu.load * 100); + status.memory = data.memory; + status.memory.swap.used = roundToTwo(data.memory.swap.used / 1073741824); + status.memory.swap.free = roundToTwo(data.memory.swap.free / 1073741824); + status.memory.swap.total = roundToTwo(data.memory.swap.total / 1073741824); + status.memory.physical.used = roundToTwo(data.memory.physical.used / 1073741824); + status.memory.physical.free = roundToTwo(data.memory.physical.free / 1073741824); + status.memory.physical.total = roundToTwo(data.memory.physical.total / 1073741824); + status.os = data.os; + status.uptime = data.uptime; + }) + .catch(reason => { + if (reason.timeout) { + // We timed out. + status.online = false; + } else { + if(reason.code === "ECONNREFUSED") { + status.online = false; + console.warn(`Server ${key} refused our connection. `) + } else { + console.error(reason); + } + } + }) + .finally(() => { + stats[key] = status; + + if(Object.keys(stats).length === Object.keys(servers).length) { + res(stats); + } + }); + } + }); +} diff --git a/views/index.ejs b/views/index.ejs index b618586..1f1661e 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -1,3 +1,27 @@ + <%- include("./partials/header.ejs", {title: "Home"}) %>
diff --git a/views/partials/footer.ejs b/views/partials/footer.ejs index 691287b..168dc25 100644 --- a/views/partials/footer.ejs +++ b/views/partials/footer.ejs @@ -1,2 +1,26 @@ + \ No newline at end of file diff --git a/views/partials/header.ejs b/views/partials/header.ejs index 57a3511..6a80ccf 100644 --- a/views/partials/header.ejs +++ b/views/partials/header.ejs @@ -1,3 +1,27 @@ + diff --git a/views/servers.ejs b/views/servers.ejs new file mode 100644 index 0000000..4f0e6e6 --- /dev/null +++ b/views/servers.ejs @@ -0,0 +1,66 @@ + +<%- include("./partials/header.ejs", {title: "Servers"}) %> + + + + +<%- include("./partials/footer.ejs") %> \ No newline at end of file -- cgit