diff --git a/Binato.js b/Binato.js deleted file mode 100755 index eaa7096..0000000 --- a/Binato.js +++ /dev/null @@ -1,79 +0,0 @@ -console.clear(); - -// Globals -global.protocolVersion = 19; - -const app = require("express")(), - consoleHelper = require("./consoleHelper.js"), - prometheusApp = require("express")(), - fs = require("fs"), - serverHandler = require("./server/serverHandler.js"), - config = require("./config.json"); - -if (config.prometheus.enabled) { - // We only need to require this if prom metrics are on. - const prom = require("prom-client"); - - const register = new prom.Registry(); - - register.setDefaultLabels({ app: "nodejs_binato" }); - - prom.collectDefaultMetrics({ register }); - - prometheusApp.get("*", async (req, res) => { - if (req.url.split("?")[0] != "/metrics") return res.status(404).end(""); - - res.end(await register.metrics()); - }); - - prometheusApp.listen(config.prometheus.port, () => consoleHelper.printBancho(`Prometheus metrics listening at port ${config.prometheus.port}`)); -} else consoleHelper.printWarn("Prometheus is disabled!"); - -if (config.express.compression) { - app.use(require("compression")()); - consoleHelper.printBancho("Compression is enabled."); -} else consoleHelper.printWarn("Compression is disabled!"); - -app.use((req, res) => { - req.packet = Buffer.alloc(0); - req.on("data", (chunk) => req.packet = Buffer.concat([req.packet, chunk], req.packet.length + chunk.length)); - req.on("end", () => { - switch (req.method) { - case "GET": - if (req.url == "/" || req.url == "/index.html" || req.url == "/index") { - res.sendFile(`${__dirname}/web/serverPage.html`); - } else if (req.url == "/chat") { - fs.readFile("./web/chatPageTemplate.html", (err, data) => { - if (err) throw err; - - let lines = "", flip = false; - const limit = global.chatHistory.length < 10 ? 10 : global.chatHistory.length; - for (let i = global.chatHistory.length - 10; i < limit; i++) { - if (i < 0) i = 0; - lines += `
${global.chatHistory[i] == null ? "blank" : global.chatHistory[i]}
` - flip = !flip; - } - - res.send(data.toString().replace("|content|", lines)); - }); - } - break; - - case "POST": - // Make sure this address should respond to bancho requests - // Bancho addresses: c, c1, c2, c3, c4, c5, c6, ce - // Just looking for the first character being "c" *should* be enough - if (req.headers["host"].split(".")[0][0] == "c") - serverHandler(req, res); - else - res.status(400).send("400 | Bad Request!
Binato only accepts POST requests on Bancho subdomains.
Binato"); - break; - - default: - res.status(405).send("405 | Method not allowed!
Binato"); - break; - } - }); -}); - -app.listen(config.express.port, () => consoleHelper.printBancho(`Binato is up! Listening at port ${config.express.port}`)); \ No newline at end of file diff --git a/Binato.ts b/Binato.ts new file mode 100644 index 0000000..9ca2e43 --- /dev/null +++ b/Binato.ts @@ -0,0 +1,74 @@ +import { Application } from "express"; +import compression from "compression"; +import { ConsoleHelper } from "./ConsoleHelper"; +import express from "express"; +import { readFile } from "fs"; +import { Registry, collectDefaultMetrics } from "prom-client"; + +const binatoApp:Application = express(); +const config = require("./config.json"); + +if (config["prometheus"]["enabled"]) { + const register:Registry = new Registry(); + register.setDefaultLabels({ app: "nodejs_binato" }); + + collectDefaultMetrics({ register }); + + const prometheusApp:Application = express(); + prometheusApp.get("/metrics", async (req, res) => { + res.end(await register.metrics()); + }); + + prometheusApp.listen(config["prometheus"]["port"], () => ConsoleHelper.printBancho(`Prometheus metrics listening at port ${config["prometheus"]["port"]}`)); +} else { + ConsoleHelper.printWarn("Prometheus is disabled!"); +} + +if (config["express"]["compression"]) { + binatoApp.use(compression()); + ConsoleHelper.printBancho("Compression is enabled"); +} else { + ConsoleHelper.printWarn("Compression is disabled"); +} + +binatoApp.use((req, res) => { + let packet:Buffer = Buffer.alloc(0); + req.on("data", (chunk:Buffer) => packet = Buffer.concat([packet, chunk], packet.length + chunk.length)); + req.on("end", () => { + switch (req.method) { + case "GET": + if (req.url == "/" || req.url == "/index.html" || req.url == "/index") { + res.sendFile(`${__dirname}/web/serverPage.html`); + } else if (req.url == "/chat") { + readFile("./web/chatPageTemplate.html", (err, data) => { + if (err) throw err; + + let lines = "", flip = false; + const limit = global.chatHistory.length < 10 ? 10 : global.chatHistory.length; + for (let i = global.chatHistory.length - 10; i < limit; i++) { + if (i < 0) i = 0; + lines += `
${global.chatHistory[i] == null ? "blank" : global.chatHistory[i]}
` + flip = !flip; + } + + res.send(data.toString().replace("|content|", lines)); + }); + } + break; + + case "POST": + // Make sure this address should respond to bancho requests + // Bancho addresses: c, c1, c2, c3, c4, c5, c6, ce + // Just looking for the first character being "c" *should* be enough + if (req.headers["host"].split(".")[0][0] == "c") + serverHandler(req, res); + else + res.status(400).send("400 | Bad Request!
Binato only accepts POST requests on Bancho subdomains.
Binato"); + break; + + default: + res.status(405).send("405 | Method not allowed!
Binato"); + break; + } + }); +}); \ No newline at end of file diff --git a/ConsoleHelper.ts b/ConsoleHelper.ts new file mode 100644 index 0000000..f656bc3 --- /dev/null +++ b/ConsoleHelper.ts @@ -0,0 +1,63 @@ +import chalk from "chalk"; + +enum LogType { + INFO, + WARN, + ERROR +}; + +const LogTags = { + BANCHO: chalk.bgMagenta(chalk.black(" BCHO ")), + WEBREQ: chalk.bgGreen(chalk.black(" WEBR ")), + CHAT: chalk.bgCyan(chalk.black(" CHAT ")), + WARN: chalk.bgYellow(chalk.black(" WARN ")), + ERROR: chalk.bgRed(" ERRR "), + REDIS: chalk.bgRed(chalk.white(" RDIS ")) +} as const; + +function correctValue(i:number) : string { + if (i <= 9) return `0${i}`; + else return i.toString(); +} + +function getTime() : string { + const time = new Date(); + return chalk.green(`[${correctValue(time.getHours())}:${correctValue(time.getMinutes())}:${correctValue(time.getSeconds())}]`); +} + +function log(tag:string, log:string, logType:LogType = LogType.INFO) : void { + switch (logType) { + case LogType.INFO: + return console.log(`${getTime()} ${tag} ${log}`); + case LogType.WARN: + return console.warn(`${getTime()} ${tag} ${log}`); + case LogType.ERROR: + return console.error(`${getTime()} ${tag} ${log}`); + } +} + +export class ConsoleHelper { + public static printWebReq(s:string) : void { + log(LogTags.WEBREQ, s); + } + + public static printBancho(s:string) : void { + log(LogTags.BANCHO, s); + } + + public static printRedis(s:string) : void { + log(LogTags.REDIS, s); + } + + public static printChat(s:string) : void { + log(LogTags.CHAT, s); + } + + public static printWarn(s:string) : void { + log(LogTags.WARN, s); + } + + public static printError(s:string) : void { + log(LogTags.ERROR, s); + } +} \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 3cd11ea..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Holly Stubbs - -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. diff --git a/README.md b/README.md deleted file mode 100644 index d48bc51..0000000 --- a/README.md +++ /dev/null @@ -1,82 +0,0 @@ -# Binato [![CodeFactor](https://www.codefactor.io/repository/github/tgpholly/binato/badge)](https://www.codefactor.io/repository/github/tgpholly/binato) -An implementation of osu!bancho in Javascript - -i'm sorry peppy -
- -### Features: - - Multiplayer + Invites - - Spectator - - Tourney Client - - User Panel - - Friends List - - Chat & Channels - - Private Messages - - Minimum Viable Product of a bot - - For a command list check [BotCommandHandler](https://github.com/tgpholly/Binato/blob/master/server/BotCommandHandler.js) or use !help on a live server - -### [Planned additions](https://github.com/tgpholly/Binato/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement) | [List of currently known bugs](https://github.com/tgpethan/Binato/issues?q=is%3Aopen+is%3Aissue+label%3Abug) - -
- -## Setup: -While I don't support setting this up yourself it is fairly easy to do, all that should be required is: - - **NodeJS >= 10** - - **MariaDB or MySQL** (MariaDB is prefered as that is what this is tested and ran against in prod) - - Optional (Disabled via config): - - **Redis** - - **Prometheus** - -Clone the repo and run `npm i` to install required packages, then copy `config.example.json` to `config.json` and edit to your liking (this is where http compression, prometheus and redis can be enabled/disabled) - -After doing this running `node .` should start the server - -## Reporting bugs: -To report a bug [create a new issue](https://github.com/tgpholly/Binato/issues/new) and include information such as your OS / Distro, Node version, disabled Binato features (e.g. Prometheus, Redis, compression) and console output at the time of the bug if applicable. - -
- -## How to connect: - -### 2013 - Stable Fallback (2015 / 2016 ?): -Stable fallback uses HTTP so for that you just need to direct it to the server
-You can do this using the hosts file - -Location on Linux: /etc/hosts
-Location on Mac: /private/etc/hosts
-Location on Windows: C:/Windows/system32/drivers/etc/hosts - -Add an entry in the hosts file that looks like the following: -``` - osu.ppy.sh c.ppy.sh c1.ppy.sh -``` -Where is the IP Address of the server hosting the bancho server - -### 2016 - Early 2021: -Versions of osu! past Stable Fallback use HTTPS and as such you'll have to create a self signed certificate and make the server identify as ppy.sh
-In 2018 there were also new subdomains added which are: - - c2.ppy.sh - - c3.ppy.sh - - c4.ppy.sh - - c5.ppy.sh - - c6.ppy.sh - - ce.ppy.sh - -### Now (2022): -There is a `-devserver` launch flag in the game which can be passed to the client to connect to a specific server. Example usage: -``` -osu!.exe -devserver eusv.ml -``` -You need to have your subdomains structured like osu!'s with the exception of `c*.ppy.sh` domains. There is only one that is polled for `-devserver` usage. - -An example setup would be: - - osu.example.com (Score submit & web stuff) - - c.example.com (Bancho) - - a.example.com (Profile pictures) -
- -## Other Binato components: -### Website: -Binato's website is handled by [Binato-Website](https://github.com/tgpholly/Binato-Website) -### Profile Pictures: -Profile pictures can be handled by any standard HTTP server, there is also one I made for the task here: [Binato-ProfilePicture](https://github.com/tgpholly/Binato-ProfilePicture) diff --git a/config.example.json b/config.example.json deleted file mode 100644 index 58022e3..0000000 --- a/config.example.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "express": { - "port": 5001, - "compression": true - }, - "prometheus": { - "enabled": false, - "port": 9100 - }, - "redis": { - "enabled": false, - "address": "127.0.0.1", - "port": 6379, - "password": "", - "database": 0 - }, - "database": { - "address": "127.0.0.1", - "port": 3306, - "username": "username", - "password": "password", - "name": "osu!", - "pbkdf2": { - "itterations": 1337, - "keylength": 1337 - }, - "key": "examplekey" - } -} \ No newline at end of file diff --git a/consoleHelper.js b/consoleHelper.js deleted file mode 100755 index 76de979..0000000 --- a/consoleHelper.js +++ /dev/null @@ -1,63 +0,0 @@ -const chalk = require("chalk"); - -const LogType = { - INFO: 0, - WARN: 1, - ERROR: 2 -} - -const LogTags = { - BANCHO: chalk.bgMagenta(chalk.black(" BANCHO ")), - WEBREQ: chalk.bgGreen(chalk.black(" WEBREQ ")), - CHAT: chalk.bgCyan(chalk.black(" CHATTO ")), - WARN: chalk.bgYellow(chalk.black(" WARNIN ")), - ERROR: chalk.bgRed(" ERROR! "), - REDIS: chalk.bgRed(chalk.white(" bREDIS ")) -} - -function correctValue(i) { - if (i <= 9) return "0"+i; - else return i; -} - -function getTime() { - const time = new Date(); - return chalk.green(`[${correctValue(time.getHours())}:${correctValue(time.getMinutes())}:${correctValue(time.getSeconds())}]`); -} - -function log(tag = "", log = "", logType = LogType.INFO) { - switch (logType) { - case LogType.INFO: - return console.log(`${getTime()} ${tag} ${log}`); - case LogType.WARN: - return console.warn(`${getTime()} ${tag} ${log}`); - case LogType.ERROR: - return console.error(`${getTime()} ${tag} ${log}`); - } -} - -module.exports = { - printWebReq:function(s) { - log(LogTags.WEBREQ, s); - }, - - printBancho:function(s) { - log(LogTags.BANCHO, s); - }, - - printRedis:function(s) { - log(LogTags.REDIS, s); - }, - - printChat:function(s) { - log(LogTags.CHAT, s); - }, - - printWarn:function(s) { - log(LogTags.WARN, chalk.yellow(s), LogType.WARN); - }, - - printError:function(s) { - log(LogTags.ERROR, chalk.red(s), LogType.ERROR); - } -} \ No newline at end of file diff --git a/osu!.sql b/osu!.sql deleted file mode 100755 index 54891c6..0000000 --- a/osu!.sql +++ /dev/null @@ -1,176 +0,0 @@ -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -SET time_zone = "+00:00"; - -CREATE DATABASE IF NOT EXISTS `osu!` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci; -USE `osu!`; - -CREATE TABLE `friends` ( - `user` int(11) NOT NULL, - `friendsWith` int(11) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -CREATE TABLE `scores` ( - `id` int(11) NOT NULL, - `userid` int(11) NOT NULL, - `beatmap_md5` varchar(32) NOT NULL DEFAULT '', - `username` varchar(30) NOT NULL DEFAULT '', - `score` bigint(20) NOT NULL, - `max_combo` int(11) NOT NULL DEFAULT '0', - `full_combo` tinyint(1) NOT NULL DEFAULT '0', - `mods` int(11) NOT NULL DEFAULT '0', - `300_count` int(11) NOT NULL DEFAULT '0', - `100_count` int(11) NOT NULL DEFAULT '0', - `50_count` int(11) NOT NULL DEFAULT '0', - `katus_count` int(11) NOT NULL DEFAULT '0', - `gekis_count` int(11) NOT NULL DEFAULT '0', - `misses_count` int(11) NOT NULL DEFAULT '0', - `time` varchar(18) NOT NULL DEFAULT '', - `play_mode` tinyint(4) NOT NULL DEFAULT '0', - `completed` tinyint(11) NOT NULL DEFAULT '0', - `accuracy` float(15,12) DEFAULT NULL, - `pp` float NOT NULL DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -CREATE TABLE `mp_matches` ( - `id` int(10) UNSIGNED NOT NULL, - `name` varchar(127) NOT NULL, - `open_time` varchar(18) NOT NULL, - `close_time` varchar(18) DEFAULT NULL, - `seed` int(11) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -CREATE TABLE `mp_match_rounds` ( - `id` int(11) NOT NULL, - `match_id` int(11) NOT NULL, - `round_id` int(11) NOT NULL, - `round_mode` tinyint(4) NOT NULL, - `match_type` tinyint(4) NOT NULL, - `round_scoring_type` tinyint(4) NOT NULL, - `round_team_type` tinyint(4) NOT NULL, - `round_mods` int(11) NOT NULL, - `beatmap_md5` varchar(127) NOT NULL, - `freemod` tinyint(1) NOT NULL DEFAULT 0, - `player0` tinytext DEFAULT NULL, - `player1` tinytext DEFAULT NULL, - `player2` tinytext DEFAULT NULL, - `player3` tinytext DEFAULT NULL, - `player4` tinytext DEFAULT NULL, - `player5` tinytext DEFAULT NULL, - `player6` tinytext DEFAULT NULL, - `player7` tinytext DEFAULT NULL, - `player8` tinytext DEFAULT NULL, - `player9` tinytext DEFAULT NULL, - `player10` tinytext DEFAULT NULL, - `player11` tinytext DEFAULT NULL, - `player12` tinytext DEFAULT NULL, - `player13` tinytext DEFAULT NULL, - `player14` tinytext DEFAULT NULL, - `player15` tinytext DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -CREATE TABLE `users_info` ( - `id` int(11) NOT NULL, - `username` varchar(15) NOT NULL, - `username_safe` varchar(15) NOT NULL, - `password_hash` text NOT NULL, - `password_salt` text NOT NULL, - `email` text NOT NULL, - `country` varchar(2) NOT NULL, - `reg_date` datetime NOT NULL, - `last_login_date` datetime NOT NULL, - `last_played_mode` tinyint(4) NOT NULL, - `online_now` tinyint(1) NOT NULL, - `tags` int(11) NOT NULL, - `supporter` tinyint(1) NOT NULL, - `web_session` varchar(64) NOT NULL, - `verification_needed` tinyint(1) NOT NULL DEFAULT '0', - `password_change_required` tinyint(1) NOT NULL, - `has_old_password` int(11) NOT NULL DEFAULT 0, - `password_reset_key` text DEFAULT NULL, - `away_message` varchar(100) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -CREATE TABLE `users_modes_info` ( - `n` int(11) NOT NULL, - `user_id` int(11) NOT NULL, - `mode_id` tinyint(4) NOT NULL, - `count300` int(10) UNSIGNED NOT NULL, - `count100` int(10) UNSIGNED NOT NULL, - `count50` int(10) UNSIGNED NOT NULL, - `countmiss` int(10) UNSIGNED NOT NULL, - `playcount` int(10) UNSIGNED NOT NULL, - `total_score` int(10) UNSIGNED NOT NULL, - `ranked_score` int(11) UNSIGNED NOT NULL, - `pp_rank` int(11) NOT NULL, - `pp_raw` int(11) NOT NULL DEFAULT '1', - `count_rank_ss` int(10) UNSIGNED NOT NULL, - `count_rank_s` int(10) UNSIGNED NOT NULL, - `count_rank_a` int(10) UNSIGNED NOT NULL, - `pp_country_rank` int(11) NOT NULL, - `playtime` bigint(255) NOT NULL DEFAULT '0', - `avg_accuracy` float NOT NULL DEFAULT '0', - `level` int(255) NOT NULL DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -CREATE TABLE `web_info` ( - `i` int(11) NOT NULL, - `HomepageText` varchar(255) NOT NULL DEFAULT 'A default Binato instance!' -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -CREATE TABLE `web_prefs` ( - `id` int(11) NOT NULL, - `keyboard` tinyint(1) NOT NULL DEFAULT '0', - `mouse` tinyint(1) NOT NULL DEFAULT '0', - `tablet` tinyint(1) NOT NULL DEFAULT '0', - `touch` tinyint(1) NOT NULL DEFAULT '0', - `location` varchar(32) NOT NULL, - `interests` varchar(64) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -CREATE TABLE `web_titles` ( - `id` int(11) NOT NULL, - `title` varchar(32) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - - -ALTER TABLE `scores` - ADD PRIMARY KEY (`id`); - -ALTER TABLE `users_info` - ADD PRIMARY KEY (`id`), - ADD UNIQUE KEY `id` (`id`); - -ALTER TABLE `users_modes_info` - ADD PRIMARY KEY (`n`); - -ALTER TABLE `web_info` - ADD PRIMARY KEY (`i`); - -ALTER TABLE `web_prefs` - ADD PRIMARY KEY (`id`); - -ALTER TABLE `web_titles` - ADD PRIMARY KEY (`id`); - -ALTER TABLE `mp_matches` - ADD PRIMARY KEY (`id`); - -ALTER TABLE `mp_match_rounds` - ADD PRIMARY KEY (`id`); - -ALTER TABLE `mp_matches` - MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT; - -ALTER TABLE `mp_match_rounds` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; - -ALTER TABLE `scores` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0; - -ALTER TABLE `users_info` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=100; - -ALTER TABLE `users_modes_info` - MODIFY `n` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=0; - -INSERT INTO `web_info` (`i`, `HomepageText`) VALUES ('0', 'A default Binato instance!'); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7f89465..9547078 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,88 +9,186 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "aes256": "^1.1.0", + "@types/express": "^4.17.14", + "@types/node": "^18.11.9", "chalk": "^4.1.0", "compression": "^1.7.4", - "express": "^4.17.1", + "express": "^4.18.2", "mysql2": "^2.3.3", - "node-fetch": "^2.6.7", "osu-packet": "^4.1.2", - "prom-client": "^13.2.0", - "redis": "^4.0.6", - "uuid": "^8.3.2" + "prom-client": "^14.1.0" + }, + "devDependencies": { + "nodemon": "^2.0.20", + "ts-node": "^10.9.1" } }, - "node_modules/@node-redis/bloom": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@node-redis/bloom/-/bloom-1.0.1.tgz", - "integrity": "sha512-mXEBvEIgF4tUzdIN89LiYsbi6//EdpFA7L8M+DHCvePXg+bfHWi+ct5VI6nHUFQE5+ohm/9wmgihCH3HSkeKsw==", - "peerDependencies": { - "@node-redis/client": "^1.0.0" - } - }, - "node_modules/@node-redis/client": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@node-redis/client/-/client-1.0.5.tgz", - "integrity": "sha512-ESZ3bd1f+od62h4MaBLKum+klVJfA4wAeLHcVQBkoXa1l0viFesOWnakLQqKg+UyrlJhZmXJWtu0Y9v7iTMrig==", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, "dependencies": { - "cluster-key-slot": "1.1.0", - "generic-pool": "3.8.2", - "redis-parser": "3.0.0", - "yallist": "4.0.0" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { "node": ">=12" } }, - "node_modules/@node-redis/graph": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@node-redis/graph/-/graph-1.0.0.tgz", - "integrity": "sha512-mRSo8jEGC0cf+Rm7q8mWMKKKqkn6EAnA9IA2S3JvUv/gaWW/73vil7GLNwion2ihTptAm05I9LkepzfIXUKX5g==", - "peerDependencies": { - "@node-redis/client": "^1.0.0" + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@node-redis/json": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@node-redis/json/-/json-1.0.2.tgz", - "integrity": "sha512-qVRgn8WfG46QQ08CghSbY4VhHFgaTY71WjpwRBGEuqGPfWwfRcIf3OqSpR7Q/45X+v3xd8mvYjywqh0wqJ8T+g==", - "peerDependencies": { - "@node-redis/client": "^1.0.0" + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@node-redis/search": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@node-redis/search/-/search-1.0.5.tgz", - "integrity": "sha512-MCOL8iCKq4v+3HgEQv8zGlSkZyXSXtERgrAJ4TSryIG/eLFy84b57KmNNa/V7M1Q2Wd2hgn2nPCGNcQtk1R1OQ==", - "peerDependencies": { - "@node-redis/client": "^1.0.0" + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" } }, - "node_modules/@node-redis/time-series": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@node-redis/time-series/-/time-series-1.0.2.tgz", - "integrity": "sha512-HGQ8YooJ8Mx7l28tD7XjtB3ImLEjlUxG1wC1PAjxu6hPJqjPshUZxAICzDqDjtIbhDTf48WXXUcx8TQJB1XTKA==", - "peerDependencies": { - "@node-redis/client": "^1.0.0" + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dependencies": { + "@types/node": "*" } }, + "node_modules/@types/express": { + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", + "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.31", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", + "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/mime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" + }, + "node_modules/@types/node": { + "version": "18.11.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", + "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", + "dependencies": { + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { "node": ">= 0.6" } }, - "node_modules/aes256": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/aes256/-/aes256-1.1.0.tgz", - "integrity": "sha512-JfjTA5HEpvnn4lX9lsfgPMiV6HYqefRmvUj5MScIUeaRCbWEIT8URNpKA9ddY9iWl+Ye9oUHrdusO1cDmS/tEQ==" + "node_modules/acorn": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } }, "node_modules/ansi-styles": { "version": "4.3.0", @@ -106,48 +204,119 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } }, "node_modules/bintrees": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", - "integrity": "sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", + "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==" }, "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dependencies": { - "bytes": "3.1.0", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" } }, "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "engines": { "node": ">= 0.8" } }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -159,12 +328,50 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/cluster-key-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", - "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==", + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "engines": { - "node": ">=0.10.0" + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, "node_modules/color-convert": { @@ -214,17 +421,28 @@ "node_modules/compression/node_modules/bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", "engines": { "node": ">= 0.8" } }, + "node_modules/compression/node_modules/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==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "dependencies": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" }, "engines": { "node": ">= 0.6" @@ -239,9 +457,9 @@ } }, "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", "engines": { "node": ">= 0.6" } @@ -249,7 +467,13 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true }, "node_modules/debug": { "version": "2.6.9", @@ -260,35 +484,48 @@ } }, "node_modules/denque": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz", - "integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", "engines": { "node": ">=0.10" } }, "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "engines": { "node": ">= 0.8" } @@ -296,48 +533,49 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "engines": { "node": ">= 0.6" } }, "node_modules/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "dependencies": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.11.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", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -346,17 +584,29 @@ "node": ">= 0.10.0" } }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" }, "engines": { @@ -364,9 +614,9 @@ } }, "node_modules/forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "engines": { "node": ">= 0.6" } @@ -374,11 +624,30 @@ "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "engines": { "node": ">= 0.6" } }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, "node_modules/generate-function": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", @@ -387,35 +656,75 @@ "is-property": "^1.0.2" } }, - "node_modules/generic-pool": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz", - "integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==", + "node_modules/get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, "engines": { - "node": ">= 4" + "node": ">= 6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" } }, "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/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==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/iconv-lite": { @@ -429,10 +738,16 @@ "node": ">=0.10.0" } }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ipaddr.js": { "version": "1.9.1", @@ -442,10 +757,52 @@ "node": ">= 0.10" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" }, "node_modules/long": { "version": "4.0.0", @@ -463,10 +820,16 @@ "node": ">=10" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "engines": { "node": ">= 0.6" } @@ -474,12 +837,12 @@ "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "engines": { "node": ">= 0.6" } @@ -496,28 +859,40 @@ } }, "node_modules/mime-db": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", - "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.30", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", - "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "mime-db": "1.47.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" } }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/mysql2": { "version": "2.3.3", @@ -548,14 +923,6 @@ "node": ">=0.10.0" } }, - "node_modules/mysql2/node_modules/sqlstring": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", - "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/named-placeholders": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", @@ -579,39 +946,95 @@ "node_modules/named-placeholders/node_modules/yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" }, "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "engines": { "node": ">= 0.6" } }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "node_modules/nodemon": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", + "dev": true, "dependencies": { - "whatwg-url": "^5.0.0" + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" }, "engines": { - "node": "4.x || >=6.0.0" + "node": ">=8.10.0" }, - "peerDependencies": { - "encoding": "^0.1.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dependencies": { "ee-first": "1.1.1" }, @@ -652,12 +1075,24 @@ "node_modules/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=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } }, "node_modules/prom-client": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-13.2.0.tgz", - "integrity": "sha512-wGr5mlNNdRNzEhRYXgboUU2LxHWIojxscJKmtG3R8f4/KiWqyYgXTLHs0+Ted7tG3zFT7pgHJbtomzZ1L0ARaQ==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-14.1.0.tgz", + "integrity": "sha512-iFWCchQmi4170omLpFXbzz62SQTmPhtBL35v0qGEVRHKcqIeiexaoYeP0vfZTujxEq3tA87iqOdRbC9svS1B9A==", "dependencies": { "tdigest": "^0.1.1" }, @@ -666,11 +1101,11 @@ } }, "node_modules/proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dependencies": { - "forwarded": "~0.1.2", + "forwarded": "0.2.0", "ipaddr.js": "1.9.1" }, "engines": { @@ -680,14 +1115,26 @@ "node_modules/pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true }, "node_modules/qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, "engines": { "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/range-parser": { @@ -699,12 +1146,12 @@ } }, "node_modules/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==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -712,139 +1159,247 @@ "node": ">= 0.8" } }, - "node_modules/redis": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.0.6.tgz", - "integrity": "sha512-IaPAxgF5dV0jx+A9l6yd6R9/PAChZIoAskDVRzUODeLDNhsMlq7OLLTmu0AwAr0xjrJ1bibW5xdpRwqIQ8Q0Xg==", + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, "dependencies": { - "@node-redis/bloom": "1.0.1", - "@node-redis/client": "1.0.5", - "@node-redis/graph": "1.0.0", - "@node-redis/json": "1.0.2", - "@node-redis/search": "1.0.5", - "@node-redis/time-series": "1.0.2" - } - }, - "node_modules/redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=", - "engines": { - "node": ">=4" - } - }, - "node_modules/redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", - "dependencies": { - "redis-errors": "^1.0.0" + "picomatch": "^2.2.1" }, "engines": { - "node": ">=4" + "node": ">=8.10.0" } }, "node_modules/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==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dependencies": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "2.0.0", "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", + "ms": "2.1.3", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/send/node_modules/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==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/seq-queue": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" }, "node_modules/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==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.18.0" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-update-notifier": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", + "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", + "dev": true, + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", "engines": { "node": ">= 0.6" } }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/tdigest": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", - "integrity": "sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", + "integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==", "dependencies": { - "bintrees": "1.0.1" + "bintrees": "1.0.2" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" } }, "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "engines": { "node": ">=0.6" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } }, "node_modules/type-is": { "version": "1.6.18", @@ -858,10 +1413,30 @@ "node": ">= 0.6" } }, + "node_modules/typescript": { + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", + "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", + "dev": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "engines": { "node": ">= 0.8" } @@ -869,102 +1444,189 @@ "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "engines": { "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "engines": { "node": ">= 0.8" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } } }, "dependencies": { - "@node-redis/bloom": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@node-redis/bloom/-/bloom-1.0.1.tgz", - "integrity": "sha512-mXEBvEIgF4tUzdIN89LiYsbi6//EdpFA7L8M+DHCvePXg+bfHWi+ct5VI6nHUFQE5+ohm/9wmgihCH3HSkeKsw==", - "requires": {} - }, - "@node-redis/client": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@node-redis/client/-/client-1.0.5.tgz", - "integrity": "sha512-ESZ3bd1f+od62h4MaBLKum+klVJfA4wAeLHcVQBkoXa1l0viFesOWnakLQqKg+UyrlJhZmXJWtu0Y9v7iTMrig==", + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, "requires": { - "cluster-key-slot": "1.1.0", - "generic-pool": "3.8.2", - "redis-parser": "3.0.0", - "yallist": "4.0.0" + "@jridgewell/trace-mapping": "0.3.9" } }, - "@node-redis/graph": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@node-redis/graph/-/graph-1.0.0.tgz", - "integrity": "sha512-mRSo8jEGC0cf+Rm7q8mWMKKKqkn6EAnA9IA2S3JvUv/gaWW/73vil7GLNwion2ihTptAm05I9LkepzfIXUKX5g==", - "requires": {} + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true }, - "@node-redis/json": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@node-redis/json/-/json-1.0.2.tgz", - "integrity": "sha512-qVRgn8WfG46QQ08CghSbY4VhHFgaTY71WjpwRBGEuqGPfWwfRcIf3OqSpR7Q/45X+v3xd8mvYjywqh0wqJ8T+g==", - "requires": {} + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true }, - "@node-redis/search": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@node-redis/search/-/search-1.0.5.tgz", - "integrity": "sha512-MCOL8iCKq4v+3HgEQv8zGlSkZyXSXtERgrAJ4TSryIG/eLFy84b57KmNNa/V7M1Q2Wd2hgn2nPCGNcQtk1R1OQ==", - "requires": {} + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } }, - "@node-redis/time-series": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@node-redis/time-series/-/time-series-1.0.2.tgz", - "integrity": "sha512-HGQ8YooJ8Mx7l28tD7XjtB3ImLEjlUxG1wC1PAjxu6hPJqjPshUZxAICzDqDjtIbhDTf48WXXUcx8TQJB1XTKA==", - "requires": {} + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "dev": true + }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/express": { + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", + "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.31", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", + "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/mime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" + }, + "@types/node": { + "version": "18.11.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", + "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "@types/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", + "requires": { + "@types/mime": "*", + "@types/node": "*" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true }, "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" } }, - "aes256": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/aes256/-/aes256-1.1.0.tgz", - "integrity": "sha512-JfjTA5HEpvnn4lX9lsfgPMiV6HYqefRmvUj5MScIUeaRCbWEIT8URNpKA9ddY9iWl+Ye9oUHrdusO1cDmS/tEQ==" + "acorn": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "dev": true + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true }, "ansi-styles": { "version": "4.3.0", @@ -974,51 +1636,135 @@ "color-convert": "^2.0.1" } }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true }, "bintrees": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", - "integrity": "sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", + "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==" }, "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "requires": { - "bytes": "3.1.0", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" } }, "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } } }, - "cluster-key-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", - "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==" + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } }, "color-convert": { "version": "2.0.1", @@ -1058,16 +1804,27 @@ "bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" + }, + "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==" } } }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "5.2.1" } }, "content-type": { @@ -1076,14 +1833,20 @@ "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==" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true }, "debug": { "version": "2.6.9", @@ -1094,100 +1857,128 @@ } }, "denque": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz", - "integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "requires": { - "accepts": "~1.3.7", + "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.11.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", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" } }, "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "generate-function": { "version": "2.3.1", @@ -1197,26 +1988,54 @@ "is-property": "^1.0.2" } }, - "generic-pool": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz", - "integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==" + "get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } }, "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, "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==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" } }, "iconv-lite": { @@ -1227,20 +2046,56 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" }, "long": { "version": "4.0.0", @@ -1255,20 +2110,26 @@ "yallist": "^4.0.0" } }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "mime": { "version": "1.6.0", @@ -1276,22 +2137,31 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", - "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==" + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { - "version": "2.1.30", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", - "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "requires": { - "mime-db": "1.47.0" + "mime-db": "1.52.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" } }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "mysql2": { "version": "2.3.3", @@ -1315,11 +2185,6 @@ "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" } - }, - "sqlstring": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", - "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==" } } }, @@ -1343,27 +2208,74 @@ "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" } } }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "nodemon": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", + "dev": true, "requires": { - "whatwg-url": "^5.0.0" + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } } }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + }, "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "requires": { "ee-first": "1.1.1" } @@ -1396,34 +2308,49 @@ "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=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true }, "prom-client": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-13.2.0.tgz", - "integrity": "sha512-wGr5mlNNdRNzEhRYXgboUU2LxHWIojxscJKmtG3R8f4/KiWqyYgXTLHs0+Ted7tG3zFT7pgHJbtomzZ1L0ARaQ==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-14.1.0.tgz", + "integrity": "sha512-iFWCchQmi4170omLpFXbzz62SQTmPhtBL35v0qGEVRHKcqIeiexaoYeP0vfZTujxEq3tA87iqOdRbC9svS1B9A==", "requires": { "tdigest": "^0.1.1" } }, "proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "requires": { - "forwarded": "~0.1.2", + "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } }, "range-parser": { "version": "1.2.1", @@ -1431,130 +2358,186 @@ "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==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, - "redis": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.0.6.tgz", - "integrity": "sha512-IaPAxgF5dV0jx+A9l6yd6R9/PAChZIoAskDVRzUODeLDNhsMlq7OLLTmu0AwAr0xjrJ1bibW5xdpRwqIQ8Q0Xg==", + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, "requires": { - "@node-redis/bloom": "1.0.1", - "@node-redis/client": "1.0.5", - "@node-redis/graph": "1.0.0", - "@node-redis/json": "1.0.2", - "@node-redis/search": "1.0.5", - "@node-redis/time-series": "1.0.2" - } - }, - "redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" - }, - "redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", - "requires": { - "redis-errors": "^1.0.0" + "picomatch": "^2.2.1" } }, "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==" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "requires": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "2.0.0", "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", + "ms": "2.1.3", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "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==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, "seq-queue": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" }, "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==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.18.0" } }, "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "simple-update-notifier": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", + "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", + "dev": true, + "requires": { + "semver": "~7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, + "sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==" }, "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { - "has-flag": "^4.0.0" + "has-flag": "^3.0.0" } }, "tdigest": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", - "integrity": "sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", + "integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==", "requires": { - "bintrees": "1.0.1" + "bintrees": "1.0.2" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" } }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "requires": { + "nopt": "~1.0.10" + } + }, + "ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + } }, "type-is": { "version": "1.6.18", @@ -1565,44 +2548,50 @@ "mime-types": "~2.1.24" } }, + "typescript": { + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", + "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", + "dev": true, + "peer": true + }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true } } } diff --git a/package.json b/package.json old mode 100755 new mode 100644 index 11ecf6d..0b11669 --- a/package.json +++ b/package.json @@ -2,21 +2,25 @@ "name": "binato", "version": "1.0.0", "description": "", - "main": "index.js", - "scripts": {}, + "main": "Binato.ts", + "scripts": { + "dev:run": "nodemon --watch './**/*.ts' Binato.ts" + }, "keywords": [], "author": "", "license": "MIT", "dependencies": { - "aes256": "^1.1.0", + "@types/express": "^4.17.14", + "@types/node": "^18.11.9", "chalk": "^4.1.0", "compression": "^1.7.4", - "express": "^4.17.1", + "express": "^4.18.2", "mysql2": "^2.3.3", - "node-fetch": "^2.6.7", "osu-packet": "^4.1.2", - "prom-client": "^13.2.0", - "redis": "^4.0.6", - "uuid": "^8.3.2" + "prom-client": "^14.1.0" + }, + "devDependencies": { + "nodemon": "^2.0.20", + "ts-node": "^10.9.1" } } diff --git a/server/serverHandler.js b/server/BanchoServer.ts old mode 100755 new mode 100644 similarity index 81% rename from server/serverHandler.js rename to server/BanchoServer.ts index 6ab7438..92ac648 --- a/server/serverHandler.js +++ b/server/BanchoServer.ts @@ -1,7 +1,8 @@ -const osu = require("osu-packet"), - fs = require("fs"), - consoleHelper = require("../consoleHelper.js"), - packetIDs = require("./packetIDs.js"), +import * as osu from "osu-packet"; +import { ConsoleHelper } from "../ConsoleHelper"; +import { Packets } from "./enums/Packets"; + +const loginHandler = require("./loginHandler.js"), parseUserData = require("./util/parseUserData.js"), User = require("./User.js"), @@ -34,7 +35,7 @@ async function subscribeToChannel(channelName = "", callback = function(message await subscriptionClient.connect(); // Subscribe to channel await subscriptionClient.subscribe(channelName, callback); - consoleHelper.printRedis(`Subscribed to ${channelName} channel`); + ConsoleHelper.printRedis(`Subscribed to ${channelName} channel`); } // Do redis if it's enabled @@ -128,25 +129,25 @@ const ChangeAction = require("./Packets/ChangeAction.js"), // A class for managing everything multiplayer global.MultiplayerManager = new MultiplayerManager(); -module.exports = async function(req, res) { +module.exports = async function(req, res, packet:Buffer) { // Get the client's token string and request data - const requestTokenString = req.header("osu-token"), - requestData = req.packet; + const requestTokenString:string = req.header("osu-token"), + requestData:Buffer = packet; // Server's response - let responseData; + let responseData:Buffer; // Check if the user is logged in if (requestTokenString == null) { // Client doesn't have a token yet, let's auth them! const userData = parseUserData(requestData); - consoleHelper.printBancho(`New client connection. [User: ${userData.username}]`); + ConsoleHelper.printBancho(`New client connection. [User: ${userData.username}]`); await loginHandler(req, res, userData); } else { // Client has a token, let's see what they want. try { // Get the current user - const PacketUser = getUserFromToken(requestTokenString); + const PacketUser:User = getUserFromToken(requestTokenString); // Make sure the client's token isn't invalid if (PacketUser != null) { @@ -161,164 +162,164 @@ module.exports = async function(req, res) { // Go through each packet sent by the client for (CurrentPacket of PacketData) { switch (CurrentPacket.id) { - case packetIDs.client_changeAction: + case Packets.Client_ChangeAction: ChangeAction(PacketUser, CurrentPacket.data); break; - case packetIDs.client_sendPublicMessage: + case Packets.Client_SendPublicMessage: SendPublicMessage(PacketUser, CurrentPacket.data); break; - case packetIDs.client_logout: + case Packets.Client_Logout: await Logout(PacketUser); break; - case packetIDs.client_requestStatusUpdate: + case Packets.Client_RequestStatusUpdate: UserPresenceBundle(PacketUser); break; - case packetIDs.client_startSpectating: + case Packets.Client_StartSpectating: Spectator.startSpectatingUser(PacketUser, CurrentPacket.data); break; - case packetIDs.client_spectateFrames: + case Packets.Client_SpectateFrames: Spectator.sendSpectatorFrames(PacketUser, CurrentPacket.data); break; - case packetIDs.client_stopSpectating: + case Packets.Client_StopSpectating: Spectator.stopSpectatingUser(PacketUser); break; - case packetIDs.client_sendPrivateMessage: + case Packets.client_sendPrivateMessage: SendPrivateMessage(PacketUser, CurrentPacket.data); break; - case packetIDs.client_joinLobby: + case Packets.client_joinLobby: global.MultiplayerManager.userEnterLobby(PacketUser); break; - case packetIDs.client_partLobby: + case Packets.client_partLobby: global.MultiplayerManager.userLeaveLobby(PacketUser); break; - case packetIDs.client_createMatch: + case Packets.client_createMatch: await global.MultiplayerManager.createMultiplayerMatch(PacketUser, CurrentPacket.data); break; - case packetIDs.client_joinMatch: + case Packets.client_joinMatch: global.MultiplayerManager.joinMultiplayerMatch(PacketUser, CurrentPacket.data); break; - case packetIDs.client_matchChangeSlot: + case Packets.client_matchChangeSlot: PacketUser.currentMatch.moveToSlot(PacketUser, CurrentPacket.data); break; - case packetIDs.client_matchReady: + case Packets.client_matchReady: PacketUser.currentMatch.setStateReady(PacketUser); break; - case packetIDs.client_matchChangeSettings: + case Packets.client_matchChangeSettings: await PacketUser.currentMatch.updateMatch(PacketUser, CurrentPacket.data); break; - case packetIDs.client_matchNotReady: + case Packets.client_matchNotReady: PacketUser.currentMatch.setStateNotReady(PacketUser); break; - case packetIDs.client_partMatch: + case Packets.client_partMatch: await global.MultiplayerManager.leaveMultiplayerMatch(PacketUser); break; // Also handles user kick if the slot has a user - case packetIDs.client_matchLock: + case Packets.client_matchLock: PacketUser.currentMatch.lockMatchSlot(PacketUser, CurrentPacket.data); break; - case packetIDs.client_matchNoBeatmap: + case Packets.client_matchNoBeatmap: PacketUser.currentMatch.missingBeatmap(PacketUser); break; - case packetIDs.client_matchSkipRequest: + case Packets.client_matchSkipRequest: PacketUser.currentMatch.matchSkip(PacketUser); break; - case packetIDs.client_matchHasBeatmap: + case Packets.client_matchHasBeatmap: PacketUser.currentMatch.notMissingBeatmap(PacketUser); break; - case packetIDs.client_matchTransferHost: + case Packets.client_matchTransferHost: PacketUser.currentMatch.transferHost(PacketUser, CurrentPacket.data); break; - case packetIDs.client_matchChangeMods: + case Packets.client_matchChangeMods: PacketUser.currentMatch.updateMods(PacketUser, CurrentPacket.data); break; - case packetIDs.client_matchStart: + case Packets.client_matchStart: PacketUser.currentMatch.startMatch(); break; - case packetIDs.client_matchLoadComplete: + case Packets.client_matchLoadComplete: PacketUser.currentMatch.matchPlayerLoaded(PacketUser); break; - case packetIDs.client_matchComplete: + case Packets.client_matchComplete: await PacketUser.currentMatch.onPlayerFinishMatch(PacketUser); break; - case packetIDs.client_matchScoreUpdate: + case Packets.client_matchScoreUpdate: PacketUser.currentMatch.updatePlayerScore(PacketUser, CurrentPacket.data); break; - case packetIDs.client_matchFailed: + case Packets.client_matchFailed: PacketUser.currentMatch.matchFailed(PacketUser); break; - case packetIDs.client_matchChangeTeam: + case Packets.client_matchChangeTeam: PacketUser.currentMatch.changeTeam(PacketUser); break; - case packetIDs.client_channelJoin: + case Packets.client_channelJoin: ChannelJoin(PacketUser, CurrentPacket.data); break; - case packetIDs.client_channelPart: + case Packets.client_channelPart: ChannelPart(PacketUser, CurrentPacket.data); break; - case packetIDs.client_setAwayMessage: + case Packets.client_setAwayMessage: SetAwayMessage(PacketUser, CurrentPacket.data); break; - case packetIDs.client_friendAdd: + case Packets.client_friendAdd: AddFriend(PacketUser, CurrentPacket.data); break; - case packetIDs.client_friendRemove: + case Packets.client_friendRemove: RemoveFriend(PacketUser, CurrentPacket.data); break; - case packetIDs.client_userStatsRequest: + case Packets.client_userStatsRequest: UserStatsRequest(PacketUser, CurrentPacket.data); break; - case packetIDs.client_specialMatchInfoRequest: + case Packets.client_specialMatchInfoRequest: TourneyMatchSpecialInfo(PacketUser, CurrentPacket.data); break; - case packetIDs.client_specialJoinMatchChannel: + case Packets.client_specialJoinMatchChannel: TourneyMatchJoinChannel(PacketUser, CurrentPacket.data); break; - case packetIDs.client_specialLeaveMatchChannel: + case Packets.client_specialLeaveMatchChannel: TourneyMatchLeaveChannel(PacketUser, CurrentPacket.data); break; - case packetIDs.client_invite: + case Packets.client_invite: MultiplayerInvite(PacketUser, CurrentPacket.data); break; - case packetIDs.client_userPresenceRequest: + case Packets.client_userPresenceRequest: UserPresence(PacketUser, PacketUser.id); // Can't really think of a way to generalize this? break; @@ -352,4 +353,4 @@ module.exports = async function(req, res) { res.end(responseData); } } -}; +}; \ No newline at end of file diff --git a/server/BotCommandHandler.js b/server/BotCommandHandler.js deleted file mode 100755 index 534f222..0000000 --- a/server/BotCommandHandler.js +++ /dev/null @@ -1,213 +0,0 @@ -const osu = require("osu-packet"), - maths = require("./util/Maths.js"), - Streams = require("./Streams.js"), - OsuBattleRoyale = require("./MultiplayerExtras/OsuBattleRoyale.js"); - -module.exports = function(User, Message, Stream, IsCalledFromMultiplayer = false) { - if (Message[0] != "!") return; - - const command = Message.split(" ")[0]; - const args = Message.split(" "); - - let responseMessage = ""; - - let commandBanchoPacketWriter = null; - - switch (command) { - case "!help": - // This is terrible - if (args.length == 1) { - responseMessage = "Commands with an * next to them have a sub help section" + - "\n!help - Shows this message" + - "\n!roll - Rolls a random number or a number between 0 and a given number" + - "\n!ranking* - Sets your perfered ranking type" + - "\n!mp* - Shows information about all multiplayer commands" + - "\n!admin* - Shows information about all admin commands"; - } else { - switch (args[1]) { - case "ranking": - responseMessage = "Ranking Commands:" + - "\n!ranking pp - Sets your ranking type to pp" + - "\n!ranking score - Sets your ranking type to score" + - "\n!ranking acc - Sets your ranking type to accuracy"; - break; - - case "mp": - responseMessage = "Multiplayer Commands:" + - "\n!mp start - Starts a multiplayer match with a delay" + - "\n!mp abort - Aborts the currently running multiplayer match" + - "\n!mp obr - Enables Battle Royale mode"; - break; - - case "admin": - responseMessage = "Admin Commands:" + - "\n!lock - Locks/Unlocks a channel and limits conversation to mods and above only"; - break; - - default: - break; - } - } - break; - - case "!ranking": - if (args.length == 1) { - responseMessage = "You need to select a ranking mode! use \"!help ranking\" to see the options."; - } else { - switch (args[1]) { - case "pp": - responseMessage = "Set ranking mode to pp"; - User.rankingMode = 0; - User.updateUserInfo(true); - break; - - case "score": - responseMessage = "Set ranking mode to score"; - User.rankingMode = 1; - User.updateUserInfo(true); - break; - - case "acc": - responseMessage = "Set ranking mode to accuracy"; - User.rankingMode = 2; - User.updateUserInfo(true); - break; - } - } - break; - - case "!roll": - if (args.length == 1) { - responseMessage = User.username + " rolled " + maths.randInt(0, 65535); - } else { - if (`${parseInt(args[1])}` == "NaN") responseMessage = User.username + " rolled " + maths.randInt(0, 65535); - else responseMessage = User.username + " rolled " + maths.randInt(0, parseInt(args[1])); - } - break; - - case "!lock": - if (!Stream.includes("#")) responseMessage = "Multiplayer channels and private channels cannot be locked!"; - else { - for (let i = 0; i < global.channels.length; i++) { - // Find the channel that pertains to this stream - if (global.channels[i].channelName == Stream) { - if (global.channels[i].locked) { - global.channels[i].locked = false; - responseMessage = "Channel is now unlocked."; - } else { - global.channels[i].locked = true; - responseMessage = "Channel is now locked, chat restricted to mods and above."; - } - break; - } - } - } - break; - - case "!mp": - if (!IsCalledFromMultiplayer) return; - if (User.currentMatch.matchStartCountdownActive) return; - if (args.length == 1) return; - switch (args[1]) { - case "start": - if (args.length > 3) return; - if (!isNaN(args[2])) { - User.currentMatch.matchStartCountdownActive = true; - let countdown = parseInt(args[2]); - let intervalRef = setInterval(() => { - let local_osuPacketWriter = new osu.Bancho.Writer; - if (countdown != 0 && countdown > 0) countdown--; - if (countdown <= 10 && countdown > 0) { - local_osuPacketWriter.SendMessage({ - sendingClient: global.botUser.username, - message: "Starting in " + countdown, - target: "#multiplayer", - senderId: global.botUser.id - }); - Streams.sendToStream(Stream, local_osuPacketWriter.toBuffer, null); - } else if (countdown == 0) { - local_osuPacketWriter.SendMessage({ - sendingClient: global.botUser.username, - message: "Good luck, have fun!", - target: "#multiplayer", - senderId: global.botUser.id - }); - Streams.sendToStream(Stream, local_osuPacketWriter.toBuffer, null); - User.currentMatch.matchStartCountdownActive = false; - setTimeout(() => User.currentMatch.startMatch(), 1000); - clearInterval(intervalRef); - } - }, 1000); - } else { - responseMessage = "Good luck, have fun!"; - setTimeout(() => User.currentMatch.startMatch(), 1000); - } - break; - - case "abort": - //if (args.length > 2) return; - User.currentMatch.finishMatch(); - break; - - case "obr": - if (User.currentMatch.multiplayerExtras != null) { - if (User.currentMatch.multiplayerExtras.name == "osu! Battle Royale") { - commandBanchoPacketWriter = new osu.Bancho.Writer; - commandBanchoPacketWriter.SendMessage({ - sendingClient: global.botUser.username, - message: "osu! Battle Royale has been disabled!", - target: "#multiplayer", - senderId: global.botUser.id - }); - User.currentMatch.multiplayerExtras = null; - Streams.sendToStream(Stream, commandBanchoPacketWriter.toBuffer, null); - } - else enableOBR(User, Stream, commandBanchoPacketWriter); - } - else enableOBR(User, Stream, commandBanchoPacketWriter); - break; - - default: - break; - } - break; - } - - const osuPacketWriter = new osu.Bancho.Writer; - if (responseMessage != "") { - if (Stream.includes("#")) { - osuPacketWriter.SendMessage({ - sendingClient: global.botUser.username, - message: responseMessage, - target: Stream, - senderId: global.botUser.id - }); - } else { - osuPacketWriter.SendMessage({ - sendingClient: global.botUser.username, - message: responseMessage, - target: "#multiplayer", - senderId: global.botUser.id - }); - } - } - Streams.sendToStream(Stream, osuPacketWriter.toBuffer, null); -} - -function enableOBR(User, Stream, commandBanchoPacketWriter) { - User.currentMatch.multiplayerExtras = new OsuBattleRoyale(User.currentMatch); - commandBanchoPacketWriter = new osu.Bancho.Writer; - commandBanchoPacketWriter.SendMessage({ - sendingClient: global.botUser.username, - message: "osu! Battle Royale has been enabled!", - target: "#multiplayer", - senderId: global.botUser.id - }); - commandBanchoPacketWriter.SendMessage({ - sendingClient: global.botUser.username, - message: "New Multiplayer Rules Added:\n - Players that are in a failed state by the end of the map get eliminated\n - The player(s) with the lowest score get eliminated", - target: "#multiplayer", - senderId: global.botUser.id - }); - Streams.sendToStream(Stream, commandBanchoPacketWriter.toBuffer, null); -} \ No newline at end of file diff --git a/server/Channels.ts b/server/Channels.ts new file mode 100644 index 0000000..e69de29 diff --git a/server/DatabaseHelper.js b/server/DatabaseHelper.js deleted file mode 100755 index 80e1253..0000000 --- a/server/DatabaseHelper.js +++ /dev/null @@ -1,79 +0,0 @@ -const mysql = require("mysql2"); -const consoleHelper = require("../consoleHelper.js"); - -module.exports = class { - constructor(databaseAddress, databasePort = 3306, databaseUsername, databasePassword, databaseName, connectedCallback) { - this.connectionPool = mysql.createPool({ - connectionLimit: 128, - host: databaseAddress, - port: databasePort, - user: databaseUsername, - password: databasePassword, - database: databaseName - }); - - const classCreationTime = Date.now(); - this.dbActive = false; - if (connectedCallback == null) { - this.dbActive = true; - } else { - const connectionCheckInterval = setInterval(() => { - this.query("SELECT name FROM osu_info LIMIT 1") - .then(data => { - consoleHelper.printBancho(`Connected to database. Took ${Date.now() - classCreationTime}ms`); - this.dbActive = true; - clearInterval(connectionCheckInterval); - - connectedCallback(); - }) - .catch(err => {}); - }, 167); // Roughly 6 times per sec - } - } - - query(query = "", data) { - const limited = query.includes("LIMIT 1"); - - return new Promise((resolve, reject) => { - this.connectionPool.getConnection((err, connection) => { - if (err) { - reject(err); - try { connection.release();} - catch (e) { - console.error("Failed to release mysql connection", err); - } - } else { - // Use old query - if (data == null) { - connection.query(query, (err, data) => { - if (err) { - reject(err); - connection.release(); - } else { - dataReceived(resolve, data, limited); - connection.release(); - } - }); - } - // Use new prepared statements w/ placeholders - else { - connection.execute(query, data, (err, data) => { - if (err) { - reject(err); - connection.release(); - } else { - dataReceived(resolve, data, limited); - connection.release(); - } - }); - } - } - }); - }); - } -} - -function dataReceived(resolveCallback, data, limited = false) { - if (limited) resolveCallback(data[0]); - else resolveCallback(data); -} \ No newline at end of file diff --git a/server/MultiplayerExtras/OsuBattleRoyale.js b/server/MultiplayerExtras/OsuBattleRoyale.js deleted file mode 100755 index 9b9af4d..0000000 --- a/server/MultiplayerExtras/OsuBattleRoyale.js +++ /dev/null @@ -1,143 +0,0 @@ -const osu = require("osu-packet"), - MultiplayerMatch = require("../MultiplayerMatch.js"), - getUserById = require("../util/getUserById.js"), - Streams = require("../Streams.js"); - -function sameScoreCheck(playerScores = [{playerId:0,slotId:0,score:0,isCurrentlyFailed:false}], lowestScore = 0) { - for (let playerScore of playerScores) { - // All players don't have the same score - if (playerScore.score != lowestScore || playerScore.isCurrentlyFailed) - return false; - } - - return true; -} - -function kickLowScorers(playerScores = [{playerId:0,slotId:0,score:0,isCurrentlyFailed:false}], MultiplayerMatch) { - for (let playerScore of playerScores) { - // Kick players if they have the lowest score or they are in a failed state - if (playerScore.score == lowestScore || playerScore.isCurrentlyFailed) { - let osuPacketWriter = new osu.Bancho.Writer; - // Get the slot this player is in - const slot = MultiplayerMatch.slots[playerScore.slotId]; - // Get the kicked player's user class - const kickedPlayer = getUserById(slot.playerId); - // Remove the kicked player's referance to the slot they were in - kickedPlayer.matchSlotId = -1; - // Lock the slot the kicked player was in - slot.playerId = -1; - slot.status = 2; - // Remove the kicked player from the match's stream - Streams.removeUserFromStream(MultiplayerMatch.matchStreamName, kickedPlayer.uuid); - Streams.removeUserFromStream(MultiplayerMatch.matchChatStreamName, kickedPlayer.uuid); - // Remove the kicked player's referance this this match - kickedPlayer.currentMatch = null; - - // Inform the kicked user's client that they were kicked - osuPacketWriter.MatchUpdate(MultiplayerMatch.createOsuMatchJSON()); - osuPacketWriter.SendMessage({ - sendingClient: global.botUser.username, - message: "You were eliminated from the match!", - target: global.botUser.username, - senderId: global.botUser.id - }); - - kickedPlayer.addActionToQueue(osuPacketWriter.toBuffer); - - osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.SendMessage({ - sendingClient: global.botUser.username, - message: `${kickedPlayer.username} was eliminated from the match!`, - target: "#multiplayer", - senderId: global.botUser.id - }); - - Streams.sendToStream(MultiplayerMatch.matchChatStreamName, osuPacketWriter.toBuffer, null); - } - } -} - -function getRemainingPlayerCount(playerScores = [{playerId:0,slotId:0,score:0,isCurrentlyFailed:false}], MultiplayerMatch) { - let numberOfPlayersRemaining = 0; - for (let playerScore of playerScores) { - const slot = MultiplayerMatch.slots[playerScore.slotId]; - - if (slot.playerId !== -1 && slot.status !== 2) { - numberOfPlayersRemaining++; - } - } - - return numberOfPlayersRemaining; -} - -module.exports = class { - constructor(MultiplayerMatchClass = new MultiplayerMatch) { - this.name = "osu! Battle Royale"; - this.MultiplayerMatch = MultiplayerMatchClass; - } - - onMatchFinished(playerScores = [{playerId:0,slotId:0,score:0,isCurrentlyFailed:false}]) { - let lowestScore = 8589934588; - // Find the lowest score - for (let i = 0; i < playerScores.length; i++) { - const playerScore = playerScores[i]; - if (playerScore.score < lowestScore) lowestScore = playerScore.score; - } - - // Check if everyone has the same score, we don't need to kick anyone if they do. - if (sameScoreCheck(playerScores)) return; - - // Kick everyone with the lowest score - kickLowScorers(playerScores, this.MultiplayerMatch); - - // Get number of players remaining - let numberOfPlayersRemaining = getRemainingPlayerCount(playerScores, this.MultiplayerMatch); - - let playerClassContainer = null; - let remainingWriterContainer = null; - let i = 0; - - if (numberOfPlayersRemaining == 1) { - for (let i1 = 0; i1 < playerScores.length; i++) { - const slot = this.MultiplayerMatch.slots[playerScores[i].slotId]; - if (slot.playerId !== -1 && slot.status !== 2) { - playerClassContainer = getUserById(slot.playerId); - break; - } - } - } - - switch (numberOfPlayersRemaining) { - case 0: - remainingWriterContainer = new osu.Bancho.Writer; - remainingWriterContainer.SendMessage({ - sendingClient: global.botUser.username, - message: "Everyone was eliminated from the match! Nobody wins.", - target: global.botUser.username, - senderId: global.botUser.id - }); - for (i = 0; i < playerScores.length; i++) { - playerClassContainer = getUserById(playerScores[i].playerId); - playerClassContainer.addActionToQueue(remainingWriterContainer.toBuffer); - } - break; - - case 1: - remainingWriterContainer = new osu.Bancho.Writer; - remainingWriterContainer.SendMessage({ - sendingClient: global.botUser.username, - message: "You are the last one remaining, you win!", - target: global.botUser.username, - senderId: global.botUser.id - }); - playerClassContainer.addActionToQueue(remainingWriterContainer.toBuffer); - break; - } - - // Update match for players in the match - this.MultiplayerMatch.sendMatchUpdate(); - // Update the match listing for users in the multiplayer lobby - global.MultiplayerManager.updateMatchListing(); - } -} \ No newline at end of file diff --git a/server/MultiplayerManager.js b/server/MultiplayerManager.js deleted file mode 100755 index 844b5db..0000000 --- a/server/MultiplayerManager.js +++ /dev/null @@ -1,227 +0,0 @@ -const osu = require("osu-packet"), - UserPresenceBundle = require("./Packets/UserPresenceBundle.js"), - UserPresence = require("./Packets/UserPresence.js"), - StatusUpdate = require("./Packets/StatusUpdate.js"), - MultiplayerMatch = require("./MultiplayerMatch.js"), - Streams = require("./Streams.js"), - User = require("./User.js"); - -module.exports = class { - constructor() { - this.matches = []; - } - - userEnterLobby(currentUser) { - // If the user is currently already in a match force them to leave - if (currentUser.currentMatch != null) - currentUser.currentMatch.leaveMatch(currentUser); - - // Add user to the stream for the lobby - Streams.addUserToStream("multiplayer_lobby", currentUser.uuid); - - // Send user ids of all online users to all users in the lobby - Streams.sendToStream("multiplayer_lobby", UserPresenceBundle(currentUser, false), null); - - // Loop through all matches - for (let i = 0; i < this.matches.length; i++) { - // Loop through all the users in this match - for (let i1 = 0; i1 < this.matches[i].slots.length; i1++) { - const slot = this.matches[i].slots[i1]; - // Make sure there is a player / the slot is not locked - if (slot.playerId == -1 || slot.status == 2) continue; - - // Send information for this user to all users in the lobby - Streams.sendToStream("multiplayer_lobby", UserPresence(currentUser, slot.playerId, false), null); - Streams.sendToStream("multiplayer_lobby", StatusUpdate(currentUser, slot.playerId, false), null); - } - const osuPacketWriter = new osu.Bancho.Writer; - - // List the match on the client - osuPacketWriter.MatchNew(this.matches[i].createOsuMatchJSON()); - - currentUser.addActionToQueue(osuPacketWriter.toBuffer); - } - - const osuPacketWriter = new osu.Bancho.Writer; - - // Add the user to the #lobby channel - if (!Streams.isUserInStream("#lobby", currentUser.uuid)) { - Streams.addUserToStream("#lobby", currentUser.uuid); - osuPacketWriter.ChannelJoinSuccess("#lobby"); - } - - currentUser.addActionToQueue(osuPacketWriter.toBuffer); - } - - userLeaveLobby(currentUser) { - // Remove user from the stream for the multiplayer lobby if they are a part of it - if (Streams.isUserInStream("multiplayer_lobby", currentUser.uuid)) - Streams.removeUserFromStream("multiplayer_lobby", currentUser.uuid); - } - - updateMatchListing() { - // Send user ids of all online users to all users in the lobby - Streams.sendToStream("multiplayer_lobby", UserPresenceBundle(null, false), null); - - // List through all matches - for (let i = 0; i < this.matches.length; i++) { - // List through all users in the match - for (let i1 = 0; i1 < this.matches[i].slots.length; i1++) { - const slot = this.matches[i].slots[i1]; - // Make sure the slot has a user in it / isn't locked - if (slot.playerId == -1 || slot.status == 2) continue; - - // Send information for this user to all users in the lobby - Streams.sendToStream("multiplayer_lobby", UserPresence(null, slot.playerId, false), null); - Streams.sendToStream("multiplayer_lobby", StatusUpdate(null, slot.playerId, false), null); - } - const osuPacketWriter = new osu.Bancho.Writer; - - // List the match on the client - osuPacketWriter.MatchNew(this.matches[i].createOsuMatchJSON()); - - // Send this data back to every user in the lobby - Streams.sendToStream("multiplayer_lobby", osuPacketWriter.toBuffer, null); - } - } - - async createMultiplayerMatch(MatchHost, MatchData) { - let matchClass = null; - this.matches.push(matchClass = await MultiplayerMatch.createMatch(MatchHost, MatchData)); - - // Join the user to the newly created match - this.joinMultiplayerMatch(MatchHost, { - matchId: matchClass.matchId, - gamePassword: matchClass.gamePassword - }); - } - - joinMultiplayerMatch(JoiningUser, JoinInfo) { - try { - let osuPacketWriter = new osu.Bancho.Writer; - const osuPacketWriter1 = new osu.Bancho.Writer; - - let matchIndex = 0; - for (let i = 0; i < this.matches.length; i++) { - if (this.matches[i].matchId == JoinInfo.matchId) { - matchIndex = i; - break; - } - } - - const streamName = this.matches[matchIndex].matchStreamName; - const chatStreamName = this.matches[matchIndex].matchChatStreamName; - const match = this.matches[matchIndex]; - - let full = true; - // Loop through all slots to find an empty one - for (let i = 0; i < match.slots.length; i++) { - const slot = match.slots[i]; - // Make sure the slot doesn't have a player in it / the slot is locked - if (slot.playerId !== -1 || slot.status === 2) continue; - - // Slot is empty and not locked, we can join the match! - full = false; - slot.playerId = JoiningUser.id; - JoiningUser.matchSlotId = i; - slot.status = 4; - break; - } - - const matchJSON = match.createOsuMatchJSON(); - osuPacketWriter1.MatchUpdate(matchJSON); - osuPacketWriter.MatchJoinSuccess(matchJSON); - - if (full) { - throw "MatchFullException"; - } - - // Set the user's current match to this match - JoiningUser.currentMatch = match; - JoiningUser.inMatch = true; - - // Add user to the stream for the match - Streams.addUserToStream(streamName, JoiningUser.uuid); - Streams.addUserToStream(chatStreamName, JoiningUser.uuid); - - // Inform all users in the match that a new user has joined - Streams.sendToStream(streamName, osuPacketWriter1.toBuffer, null); - - osuPacketWriter.ChannelJoinSuccess("#multiplayer"); - - // Inform joining client they they have joined the match - JoiningUser.addActionToQueue(osuPacketWriter.toBuffer); - - // Update the match listing for all users in the lobby since - // A user has joined a match - this.updateMatchListing(); - } catch (e) { - // Inform the client that there was an issue joining the match - const osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.MatchJoinFail(); - - JoiningUser.addActionToQueue(osuPacketWriter.toBuffer); - - this.updateMatchListing(); - } - } - - async leaveMultiplayerMatch(MatchUser = new User) { - // Make sure the user is in a match - if (MatchUser.currentMatch == null) return; - - const mpMatch = MatchUser.currentMatch; - - mpMatch.leaveMatch(MatchUser); - - let empty = true; - // Check if the match is empty - for (let i = 0; i < mpMatch.slots.length; i++) { - const slot = mpMatch.slots[i]; - // Check if the slot is avaliable - if (slot.playerId === -1) continue; - - // There is a user in the match - empty = false; - break; - } - - // The match is empty, proceed to remove it. - if (empty) { - let matchIndex; - // Loop through all matches - for (let i = 0; i < this.matches.length; i++) { - // If the match matches the match the user has left - if (this.matches[i].matchStreamName == MatchUser.currentMatch.matchStreamName) { - matchIndex = i; - break; - } - } - - // Make sure we got a match index - if (matchIndex == null) return; - - // Remove this match from the list of active matches - this.matches.splice(matchIndex, 1); - - // Close the db match - global.DatabaseHelper.query("UPDATE mp_matches SET close_time = UNIX_TIMESTAMP() WHERE id = ?", [mpMatch.matchId]); - } - - MatchUser.currentMatch = null; - MatchUser.matchSlotId = -1; - - MatchUser.inMatch = false; - - // Update the match listing to reflect this change (either removal or user leaving) - this.updateMatchListing(); - } - - getMatch(MatchID) { - for (let match in this.matches) { - if (match.matchId == MatchID) return match; - } - return null; - } -} \ No newline at end of file diff --git a/server/MultiplayerMatch.js b/server/MultiplayerMatch.js deleted file mode 100755 index 76dd89f..0000000 --- a/server/MultiplayerMatch.js +++ /dev/null @@ -1,564 +0,0 @@ -const osu = require("osu-packet"), - getUserById = require("./util/getUserById.js"), - StatusUpdate = require("./Packets/StatusUpdate.js"), - Streams = require("./Streams.js"), - User = require("./User.js"); - -// TODO: Cache the player's slot position in their user class for a small optimisation - -class MultiplayerMatch { - constructor(MatchData = {matchId: -1,inProgress: false,matchType: 0,activeMods: 0,gameName: "",gamePassword: '',beatmapName: '',beatmapId: 0,beatmapChecksum: '',slots: [],host: 0,playMode: 0,matchScoringType: 0,matchTeamType: 0,specialModes: 0,seed: 0}) { - this.matchId = MatchData.matchId; - - this.roundId = 0; - - this.inProgress = MatchData.inProgress; - this.matchStartCountdownActive = false; - - this.matchType = MatchData.matchType; - - this.activeMods = MatchData.activeMods; - - this.gameName = MatchData.gameName; - if (MatchData.gamePassword == '') MatchData.gamePassword == null; - this.gamePassword = MatchData.gamePassword; - - this.beatmapName = MatchData.beatmapName; - this.beatmapId = MatchData.beatmapId; - this.beatmapChecksum = MatchData.beatmapChecksum; - - this.slots = MatchData.slots; - for (let i = 0; i < this.slots.length; i++) { - this.slots[i].mods = 0; - } - - this.host = MatchData.host; - - this.playMode = MatchData.playMode; - - this.matchScoringType = MatchData.matchScoringType; - this.matchTeamType = MatchData.matchTeamType; - this.specialModes = MatchData.specialModes; - - this.seed = MatchData.seed; - - this.matchStreamName = `mp_${this.matchId}`; - this.matchChatStreamName = `mp_chat_${this.matchId}`; - - this.matchLoadSlots = null; - this.matchSkippedSlots = null; - - this.playerScores = null; - - this.multiplayerExtras = null; - - this.isTourneyMatch = false; - this.tourneyClientUsers = []; - } - - static createMatch(MatchHost = new User, MatchData = {matchId: -1,inProgress: false,matchType: 0,activeMods: 0,gameName: "",gamePassword: '',beatmapName: '',beatmapId: 0,beatmapChecksum: '',slots: [],host: 0,playMode: 0,matchScoringType: 0,matchTeamType: 0,specialModes: 0,seed: 0}) { - return new Promise(async (resolve, reject) => { - MatchData.matchId = (await global.DatabaseHelper.query( - "INSERT INTO mp_matches (id, name, open_time, close_time, seed) VALUES (NULL, ?, UNIX_TIMESTAMP(), NULL, ?) RETURNING id;", - [MatchData.gameName, MatchData.seed] - ))[0]["id"]; - - const matchInstance = new MultiplayerMatch(MatchData); - - console.log(matchInstance.matchId); - - // Update the status of the current user - StatusUpdate(MatchHost, MatchHost.id); - - const osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.MatchNew(matchInstance.createOsuMatchJSON()); - - MatchHost.addActionToQueue(osuPacketWriter.toBuffer); - - Streams.addStream(matchInstance.matchStreamName, true, matchInstance.matchId); - Streams.addStream(matchInstance.matchChatStreamName, true, matchInstance.matchId); - - // Update the match listing for users in the multiplayer lobby - global.MultiplayerManager.updateMatchListing(); - - resolve(matchInstance); - }); - } - - getSlotIdByPlayerId(playerId = 0) { - const player = getUserById(playerId); - - if (player != null) return player.matchSlotId; - else return null; - } - - createOsuMatchJSON() { - return { - matchId: this.matchId, - inProgress: this.inProgress, - matchType: this.matchType, - activeMods: this.activeMods, - gameName: this.gameName, - gamePassword: this.gamePassword, - beatmapName: this.beatmapName, - beatmapId: this.beatmapId, - beatmapChecksum: this.beatmapChecksum, - slots: this.slots, - host: this.host, - playMode: this.playMode, - matchScoringType: this.matchScoringType, - matchTeamType: this.matchTeamType, - specialModes: this.specialModes, - seed: this.seed - }; - } - - leaveMatch(MatchUser = new User) { - // Make sure this leave call is valid - if (!MatchUser.inMatch) return; - - // Get the user's slot - const slot = this.slots[MatchUser.matchSlotId]; - - // Set the slot's status to avaliable - slot.playerId = -1; - slot.status = 1; - - // Remove the leaving user from the match's stream - Streams.removeUserFromStream(this.matchStreamName, MatchUser.uuid); - Streams.removeUserFromStream(this.matchChatStreamName, MatchUser.uuid); - - // Send this after removing the user from match streams to avoid a leave notification for self - this.sendMatchUpdate(); - - const osuPacketWriter = new osu.Bancho.Writer; - - // Remove user from the multiplayer channel for the match - osuPacketWriter.ChannelRevoked("#multiplayer"); - - MatchUser.addActionToQueue(osuPacketWriter.toBuffer); - } - - async updateMatch(MatchUser = new User, MatchData) { - // Update match with new data - this.inProgress = MatchData.inProgress; - - this.matchType = MatchData.matchType; - - this.activeMods = MatchData.activeMods; - - const gameNameChanged = this.gameName !== MatchData.gameName; - this.gameName = MatchData.gameName; - - if (MatchData.gamePassword == '') MatchData.gamePassword == null; - this.gamePassword = MatchData.gamePassword; - - this.beatmapName = MatchData.beatmapName; - this.beatmapId = MatchData.beatmapId; - this.beatmapChecksum = MatchData.beatmapChecksum; - - this.host = MatchData.host; - - this.playMode = MatchData.playMode; - - this.matchScoringType = MatchData.matchScoringType; - this.matchTeamType = MatchData.matchTeamType; - this.specialModes = MatchData.specialModes; - - const gameSeedChanged = this.seed !== MatchData.seed; - this.seed = MatchData.seed; - - if (gameNameChanged || gameSeedChanged) { - const queryData = []; - if (gameNameChanged) { - queryData.push(MatchData.gameName); - } - if (gameSeedChanged) { - queryData.push(MatchData.seed); - } - queryData.push(this.matchId); - - await global.DatabaseHelper.query(`UPDATE mp_matches SET ${gameNameChanged ? `name = ?${gameSeedChanged ? ", " : ""}` : ""}${gameSeedChanged ? `seed = ?` : ""} WHERE id = ?`, queryData); - } - - this.sendMatchUpdate(); - - // Update the match listing in the lobby to reflect these changes - global.MultiplayerManager.updateMatchListing(); - } - - sendMatchUpdate() { - const osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.MatchUpdate(this.createOsuMatchJSON()); - - // Update all users in the match with new match information - if (Streams.exists(this.matchStreamName)) - Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } - - moveToSlot(MatchUser = new User, SlotToMoveTo) { - const oldSlot = this.slots[MatchUser.matchSlotId]; - - // Set the new slot's data to the user's old slot data - this.slots[SlotToMoveTo].playerId = MatchUser.id; - MatchUser.matchSlotId = SlotToMoveTo; - this.slots[SlotToMoveTo].status = 4; - - // Set the old slot's data to open - oldSlot.playerId = -1; - oldSlot.status = 1; - - this.sendMatchUpdate(); - - // Update the match listing in the lobby to reflect this change - global.MultiplayerManager.updateMatchListing(); - } - - changeTeam(MatchUser = new User) { - const slot = this.slots[MatchUser.matchSlotId]; - slot.team = slot.team == 0 ? 1 : 0; - - this.sendMatchUpdate(); - } - - setStateReady(MatchUser = new User) { - if (!MatchUser.inMatch) return; - - // Set the user's ready state to ready - this.slots[MatchUser.matchSlotId].status = 8; - - this.sendMatchUpdate(); - } - - setStateNotReady(MatchUser = new User) { - if (!MatchUser.inMatch) return; - - // Set the user's ready state to not ready - this.slots[MatchUser.matchSlotId].status = 4; - - this.sendMatchUpdate(); - } - - lockMatchSlot(MatchUser = new User, MatchUserToKick) { - // Make sure the user attempting to kick / lock is the host of the match - if (this.host != MatchUser.id) return; - - // Make sure the user that is attempting to be kicked is not the host - if (this.slots[MatchUserToKick].playerId === this.host) return; - - // Get the data of the slot at the index sent by the client - const slot = this.slots[MatchUserToKick]; - - let isSlotEmpty = true; - - // If the slot is empty lock/unlock instead of kicking - if (slot.playerId === -1) - slot.status = slot.status === 1 ? 2 : 1; - - // The slot isn't empty, kick the player - else { - const kickedPlayer = getUserById(slot.playerId); - kickedPlayer.matchSlotId = -1; - slot.playerId = -1; - slot.status = 1; - isSlotEmpty = false; - } - - this.sendMatchUpdate(); - - // Update the match listing in the lobby listing to reflect this change - global.MultiplayerManager.updateMatchListing(); - - if (!isSlotEmpty) { - let cachedPlayerToken = getUserById(slot.playerId).uuid; - - if (cachedPlayerToken !== null && cachedPlayerToken !== "") { - // Remove the kicked user from the match stream - Streams.removeUserFromStream(this.matchStreamName, cachedPlayerToken); - } - } - } - - missingBeatmap(MatchUser = new User) { - // User is missing the beatmap set the status to reflect it - this.slots[MatchUser.matchSlotId].status = 16; - - this.sendMatchUpdate(); - } - - notMissingBeatmap(MatchUser = new User) { - // The user is not missing the beatmap, set the status to normal - this.slots[MatchUser.matchSlotId].status = 4; - - this.sendMatchUpdate(); - } - - matchSkip(MatchUser = new User) { - if (this.matchSkippedSlots == null) { - this.matchSkippedSlots = []; - - const skippedSlots = this.matchSkippedSlots; - - for (let slot of this.slots) { - // Make sure the slot has a user in it - if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; - - // Add the slot's user to the loaded checking array - skippedSlots.push({playerId: slot.playerId, skipped: false}); - } - } - - let allSkipped = true; - for (let skippedSlot of this.matchSkippedSlots) { - // If loadslot belongs to this user then set loaded to true - if (skippedSlot.playerId == MatchUser.id) { - skippedSlot.skipped = true; - } - - if (skippedSlot.skipped) continue; - - // A user hasn't skipped - allSkipped = false; - } - - // All players have finished playing, finish the match - if (allSkipped) { - const osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.MatchPlayerSkipped(MatchUser.id); - osuPacketWriter.MatchSkip(); - - Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - - this.matchSkippedSlots = null; - } else { - const osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.MatchPlayerSkipped(MatchUser.id); - - Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } - } - - transferHost(MatchUser = new User, SlotIDToTransferTo) { - // Set the lobby's host to the new user - this.host = this.slots[SlotIDToTransferTo].playerId; - - this.sendMatchUpdate(); - } - - // TODO: Fix not being able to add DT when freemod is active - updateMods(MatchUser = new User, MatchMods) { - // Check if freemod is enabled - if (this.specialModes === 1) { - this.slots[MatchUser.matchSlotId].mods = MatchMods; - - this.sendMatchUpdate(); - } else { - // Make sure the person updating mods is the host of the match - if (this.host !== MatchUser.id) return; - - // Change the matches mods to these new mods - // TODO: Do this per user if freemod is enabled - this.activeMods = MatchMods; - - this.sendMatchUpdate(); - } - - // Update match listing in the lobby to reflect this change - global.MultiplayerManager.updateMatchListing(); - } - - startMatch() { - // Make sure the match is not already in progress - // The client sometimes double fires the start packet - if (this.inProgress) return; - this.inProgress = true; - // Create array for monitoring users until they are ready to play - this.matchLoadSlots = []; - // Loop through all slots in the match - for (let slot of this.slots) { - // Make sure the slot has a user in it - if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; - - // Add the slot's user to the loaded checking array - this.matchLoadSlots.push({ - playerId: slot.playerId, - loaded: false - }); - - // Set the user's status to playing - slot.status = 32; - } - - const osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.MatchStart(this.createOsuMatchJSON()); - - // Inform all users in the match that it has started - Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - - // Update all users in the match with new info - this.sendMatchUpdate(); - - // Update match listing in lobby to show the game is in progress - global.MultiplayerManager.updateMatchListing(); - } - - matchPlayerLoaded(MatchUser = new User) { - // Loop through all user load check items and check if all users are loaded - let allLoaded = true; - for (let loadedSlot of this.matchLoadSlots) { - // If loadslot belongs to this user then set loaded to true - if (loadedSlot.playerId == MatchUser.id) { - loadedSlot.loaded = true; - } - - if (loadedSlot.loaded) continue; - - allLoaded = false; - } - - // All players have loaded the beatmap, start playing. - if (allLoaded) { - let osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.MatchAllPlayersLoaded(); - Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - - // Blank out user loading array - this.matchLoadSlots = null; - - this.playerScores = []; - for (let i = 0; i < this.slots.length; i++) { - const slot = this.slots[i]; - if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; - - this.playerScores.push({playerId: slot.playerId, slotId: i, score: 0, isCurrentlyFailed: false}); - } - } - } - - async onPlayerFinishMatch(MatchUser = new User) { - if (this.matchLoadSlots == null) { - // Repopulate user loading slots again - this.matchLoadSlots = []; - for (let slot of this.slots) { - // Make sure the slot has a user - if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) continue; - - // Populate user loading slots with this user's id and load status - this.matchLoadSlots.push({ - playerId: slot.playerId, - loaded: false - }); - } - } - - let allLoaded = true; - - // Loop through all loaded slots to make sure all users have finished playing - for (let loadedSlot of this.matchLoadSlots) { - if (loadedSlot.playerId == MatchUser.id) { - loadedSlot.loaded = true; - } - - if (loadedSlot.loaded) continue; - - // A user hasn't finished playing - allLoaded = false; - } - - // All players have finished playing, finish the match - if (allLoaded) await this.finishMatch(); - } - - async finishMatch() { - if (!this.inProgress) return; - this.matchLoadSlots = null; - this.inProgress = false; - let osuPacketWriter = new osu.Bancho.Writer; - - let queryData = [this.matchId, this.roundId++, this.playMode, this.matchType, this.matchScoringType, this.matchTeamType, this.activeMods, this.beatmapChecksum, (this.specialModes === 1) ? 1 : 0]; - - // Loop through all slots in the match - for (let slot of this.slots) { - // Make sure the slot has a user - if (slot.playerId === -1 || slot.status === 1 || slot.status === 2) { - queryData.push(null); - continue; - } - - let score = null; - for (let _playerScore of this.playerScores) { - if (_playerScore.playerId === slot.playerId) { - score = _playerScore._raw; - break; - } - } - - queryData.push(`${slot.playerId}|${score.totalScore}|${score.maxCombo}|${score.count300}|${score.count100}|${score.count50}|${score.countGeki}|${score.countKatu}|${score.countMiss}|${(score.currentHp == 254) ? 1 : 0}${(this.specialModes === 1) ? `|${slot.mods}` : ""}|${score.usingScoreV2 ? 1 : 0}${score.usingScoreV2 ? `|${score.comboPortion}|${score.bonusPortion}` : ""}`); - - // Set the user's status back to normal from playing - slot.status = 4; - } - - console.log(queryData); - - osuPacketWriter.MatchComplete(); - - // Inform all users in the match that it is complete - Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - - // Update all users in the match with new info - this.sendMatchUpdate(); - - // Update match info in the lobby to reflect that the match has finished - global.MultiplayerManager.updateMatchListing(); - - if (this.multiplayerExtras != null) this.multiplayerExtras.onMatchFinished(JSON.parse(JSON.stringify(this.playerScores))); - - await global.DatabaseHelper.query("INSERT INTO mp_match_rounds (id, match_id, round_id, round_mode, match_type, round_scoring_type, round_team_type, round_mods, beatmap_md5, freemod, player0, player1, player2, player3, player4, player5, player6, player7, player8, player9, player10, player11, player12, player13, player14, player15) VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", queryData); - - this.playerScores = null; - } - - updatePlayerScore(MatchPlayer = new User, MatchScoreData) { - const osuPacketWriter = new osu.Bancho.Writer; - - // Make sure the user's slot ID is not invalid - if (this.matchSlotId == -1) return; - - // Get the user's current slotID and append it to the givien data, just incase. - MatchScoreData.id = MatchPlayer.matchSlotId; - - // Update the playerScores array accordingly - for (let playerScore of this.playerScores) { - if (playerScore.playerId == MatchPlayer.id) { - playerScore.score = MatchScoreData.totalScore; - playerScore.isCurrentlyFailed = MatchScoreData.currentHp == 254; - playerScore._raw = MatchScoreData; - break; - } - } - - osuPacketWriter.MatchScoreUpdate(MatchScoreData); - - // Send the newly updated score to all users in the match - Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } - - matchFailed(MatchUser = new User) { - const osuPacketWriter = new osu.Bancho.Writer; - - // Make sure the user's slot ID is not invalid - if (MatchUser.matchSlotId == -1) return; - - osuPacketWriter.MatchPlayerFailed(MatchUser.id); - - Streams.sendToStream(this.matchStreamName, osuPacketWriter.toBuffer, null); - } -} - -module.exports = MultiplayerMatch; \ No newline at end of file diff --git a/server/Packets/AddFriend.js b/server/Packets/AddFriend.js deleted file mode 100755 index 3517a59..0000000 --- a/server/Packets/AddFriend.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = function(CurrentUser, FriendToAdd) { - global.DatabaseHelper.query("INSERT INTO friends (user, friendsWith) VALUES (?, ?);", [CurrentUser.id, FriendToAdd]); -} \ No newline at end of file diff --git a/server/Packets/ChangeAction.js b/server/Packets/ChangeAction.js deleted file mode 100755 index 1ce77a6..0000000 --- a/server/Packets/ChangeAction.js +++ /dev/null @@ -1,11 +0,0 @@ -const StatusUpdate = require("./StatusUpdate.js"), - Streams = require("../Streams.js"); - -module.exports = function(currentUser, data) { - currentUser.updatePresence(data); - - if (Streams.exists(`sp_${currentUser.username}`)) { - const statusUpdate = StatusUpdate(currentUser, currentUser.id, false); - Streams.sendToStream(`sp_${currentUser.username}`, statusUpdate, null); - } -} \ No newline at end of file diff --git a/server/Packets/ChannelJoin.js b/server/Packets/ChannelJoin.js deleted file mode 100755 index e535754..0000000 --- a/server/Packets/ChannelJoin.js +++ /dev/null @@ -1,17 +0,0 @@ -const osu = require("osu-packet"), - consoleHelper = require("../../consoleHelper.js"), - Streams = require("../Streams.js"); - -module.exports = function(CurrentUser, channelName = "") { - // Make sure the user is not already in the channel - if (Streams.isUserInStream(channelName, CurrentUser.uuid)) - return consoleHelper.printBancho(`Did not add user to channel ${channelName} because they are already in it`); - - const osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.ChannelJoinSuccess(channelName); - if (!Streams.isUserInStream(channelName, CurrentUser.uuid)) - Streams.addUserToStream(channelName, CurrentUser.uuid); - - CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); -} \ No newline at end of file diff --git a/server/Packets/ChannelPart.js b/server/Packets/ChannelPart.js deleted file mode 100755 index 02640dd..0000000 --- a/server/Packets/ChannelPart.js +++ /dev/null @@ -1,7 +0,0 @@ -const Streams = require("../Streams.js"); - -module.exports = function(CurrentUser, data) { - if (data == "#multiplayer") return; // Ignore requests for multiplayer - - Streams.removeUserFromStream(data, CurrentUser.uuid); -} \ No newline at end of file diff --git a/server/Packets/Logout.js b/server/Packets/Logout.js deleted file mode 100755 index 61a91b0..0000000 --- a/server/Packets/Logout.js +++ /dev/null @@ -1,23 +0,0 @@ -const consoleHelper = require("../../consoleHelper.js"), - Streams = require("../Streams.js"); - -module.exports = async function(CurrentUser) { - if (CurrentUser.uuid === "bot") throw "Tried to log bot out, WTF???"; - - const logoutStartTime = Date.now(); - - const streamList = Streams.getStreams(); - - for (let i = 0; i < streamList.length; i++) { - if (Streams.isUserInStream(streamList[i], CurrentUser.uuid)) { - Streams.removeUserFromStream(streamList[i], CurrentUser.uuid); - } - } - - // Remove user from user list - global.users.remove(CurrentUser.uuid); - - await global.DatabaseHelper.query("UPDATE osu_info SET value = ? WHERE name = 'online_now'", [global.users.getLength() - 1]); - - consoleHelper.printBancho(`User logged out, took ${Date.now() - logoutStartTime}ms. [User: ${CurrentUser.username}]`); -} \ No newline at end of file diff --git a/server/Packets/MultiplayerInvite.js b/server/Packets/MultiplayerInvite.js deleted file mode 100755 index a113c68..0000000 --- a/server/Packets/MultiplayerInvite.js +++ /dev/null @@ -1,17 +0,0 @@ -const osu = require("osu-packet"), - getUserById = require("../util/getUserById.js"); - -module.exports = function(CurrentUser, InvitedUser) { - let osuPacketWriter = new osu.Bancho.Writer; - - const InvitedUserClass = getUserById(InvitedUser); - - osuPacketWriter.SendMessage({ - sendingClient: CurrentUser.username, - message: `Come join my multiplayer match: [osump://${CurrentUser.currentMatch.matchId}/ ${CurrentUser.currentMatch.gameName}]`, - target: CurrentUser.username, - senderId: CurrentUser.id - }); - - InvitedUserClass.addActionToQueue(osuPacketWriter.toBuffer); -} \ No newline at end of file diff --git a/server/Packets/RemoveFriend.js b/server/Packets/RemoveFriend.js deleted file mode 100755 index 248c045..0000000 --- a/server/Packets/RemoveFriend.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = function(CurrentUser, FriendToRemove) { - global.DatabaseHelper.query("DELETE FROM friends WHERE user = ? AND friendsWith = ? LIMIT 1", [CurrentUser.id, FriendToRemove]); -} \ No newline at end of file diff --git a/server/Packets/SendPrivateMessage.js b/server/Packets/SendPrivateMessage.js deleted file mode 100755 index b72c883..0000000 --- a/server/Packets/SendPrivateMessage.js +++ /dev/null @@ -1,19 +0,0 @@ -const osu = require("osu-packet"), - getUserByUsername = require("../util/getUserByUsername.js"); - -module.exports = function(CurrentUser, CurrentPacket) { - const osuPacketWriter = new osu.Bancho.Writer; - const userSentTo = getUserByUsername(CurrentPacket.target); - - if (userSentTo == null) return; - - osuPacketWriter.SendMessage({ - sendingClient: CurrentUser.username, - message: CurrentPacket.message, - target: CurrentUser.username, - senderId: CurrentUser.id - }); - - // Write chat message to stream asociated with chat channel - return userSentTo.addActionToQueue(osuPacketWriter.toBuffer); -} \ No newline at end of file diff --git a/server/Packets/SendPublicMessage.js b/server/Packets/SendPublicMessage.js deleted file mode 100755 index 0a3bf72..0000000 --- a/server/Packets/SendPublicMessage.js +++ /dev/null @@ -1,58 +0,0 @@ -const osu = require("osu-packet"), - botCommandHandler = require("../BotCommandHandler.js"), - consoleHelper = require("../../consoleHelper.js"), - Streams = require("../Streams.js"); - -module.exports = function(CurrentUser, CurrentPacket) { - let isSendingChannelLocked = false; - for (let i = 0; i < global.channels.length; i++) { - if (!CurrentPacket.target.includes("#")) break; - if (global.channels[i].channelName == CurrentPacket.target) { - isSendingChannelLocked = global.channels[i].locked; - break; - } - } - - if (isSendingChannelLocked) { - if (CurrentPacket.message.includes("!")) { - botCommandHandler(CurrentUser, CurrentPacket.message, CurrentPacket.target); - } else { - const osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.SendMessage({ - sendingClient: global.botUser.username, - message: "The channel you are currently trying to send to is locked, please check back later!", - target: CurrentPacket.target, - senderId: global.botUser.id - }); - CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); - } - return; - } - - consoleHelper.printChat(`${CurrentUser.username} in ${CurrentPacket.target} sent: ${CurrentPacket.message}`); - - const osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.SendMessage({ - sendingClient: CurrentUser.username, - message: CurrentPacket.message, - target: CurrentPacket.target, - senderId: CurrentUser.id - }); - - if (CurrentPacket.target == "#multiplayer") { - Streams.sendToStream(CurrentUser.currentMatch.matchChatStreamName, osuPacketWriter.toBuffer, CurrentUser.uuid); - botCommandHandler(CurrentUser, CurrentPacket.message, CurrentUser.currentMatch.matchChatStreamName, true); - return; - } - - // Check the stream that we're sending to even exists - if (!Streams.exists(CurrentPacket.target)) return; - - // Write chat message to stream asociated with chat channel - Streams.sendToStream(CurrentPacket.target, osuPacketWriter.toBuffer, CurrentUser.uuid); - if (CurrentPacket.target == "#osu") - global.addChatMessage(`${CurrentUser.username}: ${CurrentPacket.message.replaceAll("<", "<").replaceAll(">", ">")}`); - - botCommandHandler(CurrentUser, CurrentPacket.message, CurrentPacket.target); - return; -} \ No newline at end of file diff --git a/server/Packets/SetAwayMessage.js b/server/Packets/SetAwayMessage.js deleted file mode 100755 index 5ebe76f..0000000 --- a/server/Packets/SetAwayMessage.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = function(CurrentUser, Message) { - global.DatabaseHelper.query("UPDATE users_info SET away_message = ? WHERE id = ?", [Message.message, CurrentUser.id]); -} \ No newline at end of file diff --git a/server/Packets/StatusUpdate.js b/server/Packets/StatusUpdate.js deleted file mode 100755 index 7a76df6..0000000 --- a/server/Packets/StatusUpdate.js +++ /dev/null @@ -1,36 +0,0 @@ -const osu = require("osu-packet"), - getUserById = require("../util/getUserById.js"); - -module.exports = function(currentUser, id = 0, sendImmidiate = true) { - if (id == 3) return; // Ignore Bot - - // Create new osu packet writer - const osuPacketWriter = new osu.Bancho.Writer; - - // Get user's class - const User = getUserById(id); - - if (User == null) return; - - let UserStatusObject = { - userId: User.id, - status: User.actionID, - statusText: User.actionText, - beatmapChecksum: User.beatmapChecksum, - currentMods: User.currentMods, - playMode: User.playMode, - beatmapId: User.beatmapID, - rankedScore: User.rankedScore, - accuracy: User.accuracy * 0.01, // Scale from 0:100 to 0:1 - playCount: User.playCount, - totalScore: User.totalScore, - rank: User.rank, - performance: (User.rankingMode == 0 ? User.pp : 0) - }; - - osuPacketWriter.HandleOsuUpdate(UserStatusObject); - - // Send data to user's queue - if (sendImmidiate) currentUser.addActionToQueue(osuPacketWriter.toBuffer); - else return osuPacketWriter.toBuffer; -} \ No newline at end of file diff --git a/server/Packets/TourneyJoinMatchChannel.js b/server/Packets/TourneyJoinMatchChannel.js deleted file mode 100755 index da30de3..0000000 --- a/server/Packets/TourneyJoinMatchChannel.js +++ /dev/null @@ -1,28 +0,0 @@ -const osu = require("osu-packet"), - consoleHelper = require("./consoleHelper.js"), - Streams = require("../Streams.js"); - -module.exports = function(CurrentUser, MatchID) { - const match = global.MultiplayerManager.getMatch(MatchID); - - if (match != null) { - - match.isTourneyMatch = true; - for (let user of global.users.getIterableItems()) { - if (user.id == CurrentUser.id) { - match.tourneyClientUsers.push(user); - } - } - - if (Streams.isUserInStream(match.matchChatStreamName, CurrentUser.uuid)) - return consoleHelper.printBancho(`Did not add user to channel ${match.matchChatStreamName} because they are already in it`); - - const osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.ChannelJoinSuccess("#multiplayer"); - if (!Streams.isUserInStream(match.matchChatStreamName, CurrentUser.uuid)) - Streams.addUserToStream(match.matchChatStreamName, CurrentUser.uuid); - - CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); - } -} \ No newline at end of file diff --git a/server/Packets/TourneyLeaveMatchChannel.js b/server/Packets/TourneyLeaveMatchChannel.js deleted file mode 100755 index 5a3950d..0000000 --- a/server/Packets/TourneyLeaveMatchChannel.js +++ /dev/null @@ -1,32 +0,0 @@ -const osu = require("osu-packet"), - consoleHelper = require("../../consoleHelper.js"), - Streams = require("../Streams.js"); - -module.exports = function(CurrentUser, MatchID) { - const match = global.MultiplayerManager.getMatch(MatchID); - - if (match != null) { - - match.isTourneyMatch = false; - match.tourneyClientUsers = []; - - if (Streams.isUserInStream(match.matchChatStreamName, CurrentUser.uuid)) - return consoleHelper.printBancho(`Did not add user to channel ${match.matchChatStreamName} because they are already in it`); - - const osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.ChannelRevoked("#multiplayer"); - if (!Streams.isUserInStream(match.matchChatStreamName, CurrentUser.uuid)) - Streams.removeUserFromStream(match.matchChatStreamName, CurrentUser.uuid); - - CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); - } else { - // Still provide feedback just in case - // TODO: Check if this has any effect, if not then remove this. - const osuPacketWriter = new osu.Bancho.Writer; - - osuPacketWriter.ChannelRevoked("#multiplayer"); - - CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); - } -} \ No newline at end of file diff --git a/server/Packets/TourneyMatchSpecialInfo.js b/server/Packets/TourneyMatchSpecialInfo.js deleted file mode 100755 index 15d96bf..0000000 --- a/server/Packets/TourneyMatchSpecialInfo.js +++ /dev/null @@ -1,22 +0,0 @@ -const osu = require("osu-packet"), - UserPresence = require("./UserPresence.js"), - StatusUpdate = require("./StatusUpdate.js"); - -module.exports = function(CurrentUser, MatchID) { - const matchData = global.MultiplayerManager.getMatch(MatchID); - - if (matchData != null) { - const osuPacketWriter = new osu.Bancho.Writer(); - - osuPacketWriter.MatchUpdate(matchData.createOsuMatchJSON()); - - // Queue info on all the users in the match to the client - for (let slot in matchData.slots) { - CurrentUser.addActionToQueue(UserPresence(CurrentUser, slot.playerId, false)); - CurrentUser.addActionToQueue(StatusUpdate(CurrentUser, slot.playerId, false)); - } - - // Queue data - CurrentUser.addActionToQueue(osuPacketWriter.toBuffer); - } -} \ No newline at end of file diff --git a/server/Packets/UserPresence.js b/server/Packets/UserPresence.js deleted file mode 100755 index d9c5e3a..0000000 --- a/server/Packets/UserPresence.js +++ /dev/null @@ -1,24 +0,0 @@ -const osu = require("osu-packet"), - getUserById = require("../util/getUserById.js"); - -module.exports = function(currentUser, id = 0, sendImmidiate = true) { - const osuPacketWriter = new osu.Bancho.Writer; - - const User = getUserById(id); - - if (User == null) return; - - osuPacketWriter.UserPresence({ - userId: id, - username: User.username, - timezone: 0, - countryId: User.countryID, - permissions: 4, - longitude: User.location[1], - latitude: User.location[0], - rank: User.rank - }); - - if (sendImmidiate) currentUser.addActionToQueue(osuPacketWriter.toBuffer); - else return osuPacketWriter.toBuffer; -} \ No newline at end of file diff --git a/server/Packets/UserPresenceBundle.js b/server/Packets/UserPresenceBundle.js deleted file mode 100755 index 6d71175..0000000 --- a/server/Packets/UserPresenceBundle.js +++ /dev/null @@ -1,16 +0,0 @@ -const osu = require("osu-packet"); - -module.exports = function(currentUser, sendImmidiate = true) { - const osuPacketWriter = new osu.Bancho.Writer; - - let userIds = []; - - for (let user of global.users.getIterableItems()) { - userIds.push(user.id); - } - - osuPacketWriter.UserPresenceBundle(userIds); - - if (sendImmidiate) currentUser.addActionToQueue(osuPacketWriter.toBuffer); - else return osuPacketWriter.toBuffer; -} \ No newline at end of file diff --git a/server/Packets/UserStatsRequest.js b/server/Packets/UserStatsRequest.js deleted file mode 100755 index 8291be7..0000000 --- a/server/Packets/UserStatsRequest.js +++ /dev/null @@ -1,14 +0,0 @@ -const UserPresenceBundle = require("./UserPresenceBundle.js"), - UserPresence = require("./UserPresence.js"), - StatusUpdate = require("./StatusUpdate.js"); - -module.exports = function (currentUser, data = [0]) { - UserPresenceBundle(currentUser); - - for (let i1 = 0; i1 < data.length; i1++) { - const CurrentUserID = data[i1]; - - UserPresence(currentUser, CurrentUserID); - StatusUpdate(currentUser, CurrentUserID); - } -} \ No newline at end of file diff --git a/server/Spectator.js b/server/Spectator.js deleted file mode 100755 index 27fa6f4..0000000 --- a/server/Spectator.js +++ /dev/null @@ -1,76 +0,0 @@ -const osu = require("osu-packet"), - getUserById = require("./util/getUserById.js"), - Streams = require("./Streams.js"); - -module.exports = { - startSpectatingUser:function(currentUser, spectatedId) { - // Get the user this user is trying to spectate - const User = getUserById(spectatedId); - if (Streams.exists(`sp_${User.id}`)) { - // Just add user to stream since it already exists - Streams.addUserToStream(`sp_${User.id}`, currentUser.uuid); - } else { - // Stream doesn't exist, create it and add the spectator - Streams.addStream(`sp_${User.id}`, true, spectatedId); - Streams.addUserToStream(`sp_${User.id}`, currentUser.uuid); - } - - // We want to do this stuff regardless - // Create a new osu packet writer - let osuPacketWriter = new osu.Bancho.Writer; - - // Set the user requesting to be spectating this user - currentUser.spectating = spectatedId; - - // Tell the client of the user being spectated that they are being spectated - osuPacketWriter.SpectatorJoined(currentUser.id); - - // Send the packet to the spectated user's queue - User.addActionToQueue(osuPacketWriter.toBuffer); - - // Make a new clear osu packet writer - osuPacketWriter = new osu.Bancho.Writer; - - // Tell everyone spectating this user that another user has started spectating - osuPacketWriter.FellowSpectatorJoined(currentUser.id); - - // Send this packet to all the spectators - Streams.sendToStream(`sp_${User.id}`, osuPacketWriter.toBuffer); - }, - - sendSpectatorFrames(currentUser, data) { - // Create new osu packet writer - const osuPacketWriter = new osu.Bancho.Writer; - - // Data containing the user's actions - osuPacketWriter.SpectateFrames(data); - - // Send the frames to all the spectators - Streams.sendToStream(`sp_${currentUser.id}`, osuPacketWriter.toBuffer, null); - }, - - stopSpectatingUser(currentUser) { - // Get the user this user is spectating - const spectatedUser = getUserById(currentUser.spectating); - // Create new osu packet writer - let osuPacketWriter = new osu.Bancho.Writer; - - // Inform the client being spectated that this user has stopped spectating - osuPacketWriter.SpectatorLeft(currentUser.id); - - // Add this packet to the spectated user's queue - spectatedUser.addActionToQueue(osuPacketWriter.toBuffer); - - // Remove this user from the spectator stream - Streams.removeUserFromStream(`sp_${spectatedUser.id}`, currentUser.uuid); - - // Make a new clear osu packet writer - osuPacketWriter = new osu.Bancho.Writer; - - // Inform other users spectating that this spectator has left - osuPacketWriter.FellowSpectatorLeft(currentUser.id); - - // Send this packet to all spectators - Streams.sendToStream(`sp_${spectatedUser.id}`, osuPacketWriter.toBuffer); - } -} \ No newline at end of file diff --git a/server/Streams.js b/server/Streams.js deleted file mode 100755 index 36c796b..0000000 --- a/server/Streams.js +++ /dev/null @@ -1,129 +0,0 @@ -const getUserByToken = require("./util/getUserByToken.js"), - consoleHelper = require("../consoleHelper.js"); - -module.exports = class { - static init() { - global.avaliableStreams = {}; - global.avaliableStreamKeys = []; - } - - static addStream(streamName = "", removeIfEmpty = false, spectatorHostId = null) { - // Make sure a stream with the same name doesn't exist already - if (global.avaliableStreamKeys.includes(streamName)) - return consoleHelper.printBancho(`Did not add stream [${streamName}] A stream with the same name already exists`); - // Add new stream to the list of streams - global.avaliableStreams[streamName] = { - streamUsers: [], // An array containing a list of user tokens of the users in a given stream - streamSpectatorHost: spectatorHostId, // null unless stream is for spectating - removeIfEmpty: removeIfEmpty - } - global.avaliableStreamKeys = Object.keys(global.avaliableStreams); - consoleHelper.printBancho(`Added stream [${streamName}]`); - } - - static removeStream(streamName) { - try { - delete global.avaliableStreams[streamName]; - global.avaliableStreamKeys = Object.keys(global.avaliableStreams); - } catch (e) { - consoleHelper.printError(`Was not able to remove stream [${streamName}]`); - console.error(e); - } - } - - static addUserToStream(streamName, userToken) { - // Make sure the stream we are attempting to add this user to even exists - if (!this.exists(streamName)) - return consoleHelper.printBancho(`Did not add user to stream [${streamName}] because it does not exist!`); - - // Make sure the user isn't already in the stream - if (global.avaliableStreams[streamName].streamUsers.includes(userToken)) - return consoleHelper.printBancho(`Did not add user to stream [${streamName}] because they are already in it!`); - - // Make sure this isn't an invalid user (userId can't be lower than 1) - if (userToken == "" || userToken == null) - return consoleHelper.printBancho(`Did not add user to stream [${streamName}] because their token is invalid!`); - - // Add user's token to the stream's user list - global.avaliableStreams[streamName].streamUsers.push(userToken); - consoleHelper.printBancho(`Added user [${userToken}] to stream ${streamName}`); - } - - static removeUserFromStream(streamName, userToken) { - // Make sure the stream we are attempting to add this user to even exists - if (!this.exists(streamName)) - return consoleHelper.printBancho(`Did not remove user from stream [${streamName}] because it does not exist!`); - - const stream = global.avaliableStreams[streamName]; - - // Make sure the user isn't already in the stream - if (!stream.streamUsers.includes(userToken)) - return consoleHelper.printBancho(`Did not remove user from stream [${streamName}] because they are not in it!`); - - // Make sure this isn't an invalid user (userId can't be lower than 1) - if (userToken == "" || userToken == null) - return consoleHelper.printBancho(`Did not remove user from stream [${streamName}] because their userId is invalid!`); - try { - // Find index of user to remove - let userCurrentIndex; - for (let i = 0; i < stream.streamUsers.length; i++) { - if (userToken == stream.streamUsers[i]) { - userCurrentIndex = i; - break; - } - } - - // Remove user from stream's user list - stream.streamUsers.splice(userCurrentIndex, 1); - consoleHelper.printBancho(`Removed user [${userToken}] from stream ${streamName}`); - } catch (e) { - consoleHelper.printBancho(`Can't Remove user [${userToken}] from stream ${streamName}`); - console.error(e); - } - - if (stream.removeIfEmpty && stream.streamUsers.length == 0) { - this.removeStream(streamName); - consoleHelper.printBancho(`Removed stream [${streamName}] There were no users in stream`); - } - } - - static sendToStream(streamName, streamData, initUser = null) { - // Make sure the stream we are attempting to send to even exists - if (!this.exists(streamName)) - return consoleHelper.printBancho(`Did not send to stream [${streamName}] because it does not exist!`); - - // Get the stream to send the data to - const currentStream = global.avaliableStreams[streamName]; - - // Loop through the users in this stream - for (let i = 0; i < currentStream.streamUsers.length; i++) { - // Get the user token of the user in the queue - const currentUserToken = currentStream.streamUsers[i]; - // Make sure we don't send this data back to the user requesting this data to be sent - if (initUser != null && currentUserToken == initUser && (streamName[0] == "#" || streamName.includes("mp_"))) continue; - if (currentUserToken == 3) continue; // Skip if user is bot - - // Get user object - const currentUser = getUserByToken(currentUserToken); - // Skip if user is nonexistant - if (currentUser == null) continue; - - // Send stream data to user's own queue - currentUser.addActionToQueue(streamData); - } - } - - static exists(streamName) { - return global.avaliableStreamKeys.includes(streamName); - } - - static getStreams() { - // Return the names of all avaliable streams - return global.avaliableStreamKeys; - } - - static isUserInStream(streamName, userToken) { - if (global.avaliableStreams[streamName].streamUsers.includes(userToken)) return true; - else return false; - } -} \ No newline at end of file diff --git a/server/User.js b/server/User.js deleted file mode 100755 index 43ce3f4..0000000 --- a/server/User.js +++ /dev/null @@ -1,125 +0,0 @@ -const StatusUpdate = require("./Packets/StatusUpdate.js"); - -const rankingModes = [ - "pp_raw", - "ranked_score", - "avg_accuracy" -]; - -module.exports = class { - constructor(id, username, uuid) { - this.id = id; - this.username = username; - this.uuid = uuid; - this.connectTime = Date.now(); - this.timeoutTime = Date.now() + 30000; - this.queue = Buffer.alloc(0); - - // Binato specific - this.rankingMode = 0; - - this.playMode = 0; - this.countryID = 0; - this.spectators = []; - this.spectating = 0; - this.location = [0,0]; - this.joinedChannels = []; - - // Presence data - this.actionID = 0; - this.actionText = ""; - this.actionMods = 0; - this.beatmapChecksum = ""; - this.beatmapID = 0; - this.currentMods = 0; - - // Cached db data - this.rankedScore = 0; - this.accuracy = 0; - this.playCount = 0; - this.totalScore = 0; - this.rank = 0; - this.pp = 0; - - // Multiplayer data - this.currentMatch = null; - this.matchSlotId = -1; - - this.inMatch = false; - - this.isTourneyUser = false; - } - - // Adds new actions to the user's queue - addActionToQueue(newData) { - this.queue = Buffer.concat([this.queue, newData], this.queue.length + newData.length); - } - - // Updates the user's current action - updatePresence(action) { - this.actionID = action.status; - this.actionText = action.statusText; - this.beatmapChecksum = action.beatmapChecksum; - this.currentMods = action.currentMods; - this.actionMods = action.currentMods; - if (action.playMode != this.playMode) { - this.updateUserInfo(true); - this.playMode = action.playMode; - } - this.beatmapID = action.beatmapId; - } - - // Gets the user's score information from the database and caches it - async updateUserInfo(forceUpdate = false) { - const userScoreDB = await global.DatabaseHelper.query("SELECT * FROM users_modes_info WHERE user_id = ? AND mode_id = ? LIMIT 1", [this.id, this.playMode]); - const mappedRankingMode = rankingModes[this.rankingMode]; - const userRankDB = await global.DatabaseHelper.query(`SELECT user_id, ${mappedRankingMode} FROM users_modes_info WHERE mode_id = ? ORDER BY ${mappedRankingMode} DESC`, [this.playMode]); - - if (userScoreDB == null || userRankDB == null) throw "fuck"; - - // Handle "if we should update" checks for each rankingMode - let userScoreUpdate = false; - switch (this.rankingMode) { - case 0: - if (this.pp != userScoreDB.pp_raw) - userScoreUpdate = true; - break; - - case 1: - if (this.rankedScore != userScoreDB.ranked_score) - userScoreUpdate = true; - break; - - case 2: - if (this.accuracy != userScoreDB.avg_accuracy) - userScoreUpdate = true; - break; - } - - this.rankedScore = userScoreDB.ranked_score; - this.totalScore = userScoreDB.total_score; - this.accuracy = userScoreDB.avg_accuracy; - this.playCount = userScoreDB.playcount; - - // Fetch rank - for (let i = 0; i < userRankDB.length; i++) { - if (userRankDB[i]["user_id"] == this.id) { - this.rank = i + 1; - break; - } - } - - // Set PP to none if ranking mode is not PP - if (this.rankingMode == 0) this.pp = userScoreDB.pp_raw; - else this.pp = 0; - - if (userScoreUpdate || forceUpdate) { - StatusUpdate(this, this.id); - } - } - - // Clears out the user's queue - clearQueue() { - this.queue = Buffer.alloc(0); - } -} \ No newline at end of file diff --git a/server/bakedResponses.js b/server/bakedResponses.js deleted file mode 100755 index e4cfff4..0000000 --- a/server/bakedResponses.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = function(s) { - switch (s) { - case "reconnect": - return "\u0005\u0000\u0000\u0004\u0000\u0000\u0000����\u0018\u0000\u0000\u0011\u0000\u0000\u0000\u000b\u000fReconnecting..."; - - default: - return Buffer.alloc(0); - } -} \ No newline at end of file diff --git a/server/countryHelper.js b/server/countryHelper.js deleted file mode 100755 index b33a875..0000000 --- a/server/countryHelper.js +++ /dev/null @@ -1,274 +0,0 @@ -const countryCodes = { - "LV": 132, - "AD": 3, - "LT": 130, - "KM": 116, - "QA": 182, - "VA": 0, - "PK": 173, - "KI": 115, - "SS": 0, - "KH": 114, - "NZ": 166, - "TO": 215, - "KZ": 122, - "GA": 76, - "BW": 35, - "AX": 247, - "GE": 79, - "UA": 222, - "CR": 50, - "AE": 0, - "NE": 157, - "ZA": 240, - "SK": 196, - "BV": 34, - "SH": 0, - "PT": 179, - "SC": 189, - "CO": 49, - "GP": 86, - "GY": 93, - "CM": 47, - "TJ": 211, - "AF": 5, - "IE": 101, - "AL": 8, - "BG": 24, - "JO": 110, - "MU": 149, - "PM": 0, - "LA": 0, - "IO": 104, - "KY": 121, - "SA": 187, - "KN": 0, - "OM": 167, - "CY": 54, - "BQ": 0, - "BT": 33, - "WS": 236, - "ES": 67, - "LR": 128, - "RW": 186, - "AQ": 12, - "PW": 180, - "JE": 250, - "TN": 214, - "ZW": 243, - "JP": 111, - "BB": 20, - "VN": 233, - "HN": 96, - "KP": 0, - "WF": 235, - "EC": 62, - "HU": 99, - "GF": 80, - "GQ": 87, - "TW": 220, - "MC": 135, - "BE": 22, - "PN": 176, - "SZ": 205, - "CZ": 55, - "LY": 0, - "IN": 103, - "FM": 0, - "PY": 181, - "PH": 172, - "MN": 142, - "GG": 248, - "CC": 39, - "ME": 242, - "DO": 60, - "KR": 0, - "PL": 174, - "MT": 148, - "MM": 141, - "AW": 17, - "MV": 150, - "BD": 21, - "NR": 164, - "AT": 15, - "GW": 92, - "FR": 74, - "LI": 126, - "CF": 41, - "DZ": 61, - "MA": 134, - "VG": 0, - "NC": 156, - "IQ": 105, - "BN": 0, - "BF": 23, - "BO": 30, - "GB": 77, - "CU": 51, - "LU": 131, - "YT": 238, - "NO": 162, - "SM": 198, - "GL": 83, - "IS": 107, - "AO": 11, - "MH": 138, - "SE": 191, - "ZM": 241, - "FJ": 70, - "SL": 197, - "CH": 43, - "RU": 0, - "CW": 0, - "CX": 53, - "TF": 208, - "NL": 161, - "AU": 16, - "FI": 69, - "MS": 147, - "GH": 81, - "BY": 36, - "IL": 102, - "VC": 0, - "NG": 159, - "HT": 98, - "LS": 129, - "MR": 146, - "YE": 237, - "MP": 144, - "SX": 0, - "RE": 183, - "RO": 184, - "NP": 163, - "CG": 0, - "FO": 73, - "CI": 0, - "TH": 210, - "HK": 94, - "TK": 212, - "XK": 0, - "DM": 59, - "LC": 0, - "ID": 100, - "MG": 137, - "JM": 109, - "IT": 108, - "CA": 38, - "TZ": 221, - "GI": 82, - "KG": 113, - "NU": 165, - "TV": 219, - "LB": 124, - "SY": 0, - "PR": 177, - "NI": 160, - "KE": 112, - "MO": 0, - "SR": 201, - "VI": 0, - "SV": 203, - "HM": 0, - "CD": 0, - "BI": 26, - "BM": 28, - "MW": 151, - "TM": 213, - "GT": 90, - "AG": 0, - "UM": 0, - "US": 225, - "AR": 13, - "DJ": 57, - "KW": 120, - "MY": 153, - "FK": 71, - "EG": 64, - "BA": 0, - "CN": 48, - "GN": 85, - "PS": 178, - "SO": 200, - "IM": 249, - "GS": 0, - "BR": 31, - "GM": 84, - "PF": 170, - "PA": 168, - "PG": 171, - "BH": 25, - "TG": 209, - "GU": 91, - "CK": 45, - "MF": 252, - "VE": 230, - "CL": 46, - "TR": 217, - "UG": 223, - "GD": 78, - "TT": 218, - "TL": 0, - "MD": 0, - "MK": 0, - "ST": 202, - "CV": 52, - "MQ": 145, - "GR": 88, - "HR": 97, - "BZ": 37, - "UZ": 227, - "DK": 58, - "SN": 199, - "ET": 68, - "VU": 234, - "ER": 66, - "BJ": 27, - "LK": 127, - "NA": 155, - "AS": 14, - "SG": 192, - "PE": 169, - "IR": 0, - "MX": 152, - "TD": 207, - "AZ": 18, - "AM": 9, - "BL": 0, - "SJ": 195, - "SB": 188, - "NF": 158, - "RS": 239, - "DE": 56, - "EH": 65, - "EE": 63, - "SD": 190, - "ML": 140, - "TC": 206, - "MZ": 154, - "BS": 32, - "UY": 226, - "SI": 194, - "AI": 7 -} - -const countryCodeKeys = Object.keys(countryCodes); - -module.exports = { - getCountryID:function(code = "") { - // Get id of a country from a 2 char code - code = code.toUpperCase(); - if (countryCodes[code] != null) return countryCodes[code]; - else return 0; - }, - - getCountryLetters:function(code) { - // Get country char code from id - for (var i = 0; i < countryCodes.length; i++) { - const countryId = countryCodes[countryCodeKeys[i]]; - if (countryId === code) return countryId; - } - return "XX"; - } -} - -module.exports.countryCodes = countryCodes; \ No newline at end of file diff --git a/server/enums/Packets.ts b/server/enums/Packets.ts new file mode 100644 index 0000000..aa19f01 --- /dev/null +++ b/server/enums/Packets.ts @@ -0,0 +1,113 @@ +export enum Packets { + Client_ChangeAction, + Client_SendPublicMessage, + Client_Logout, + Client_RequestStatusUpdate, + Client_Pong, + Server_LoginReply, + Server_CommandError, + Server_SendMessage, + Server_Ping, + Server_IRCUsernameChange, + Server_IRCQuit, + Server_UserStats, + Server_UserLogout, + Server_SpectatorJoined, + Server_SpectatorLeft, + Server_SpectateFrames, + Client_StartSpectating, + Client_StopSpectating, + Client_SpectateFrames, + Server_VersionUpdate, + Client_ErrorReport, + Client_CantSpectate, + Server_SpectatorCantSpectate, + Server_GetAttention, + Server_Notification, + Client_SendPrivateMessage, + Server_UpdateMatch, + Server_NewMatch, + Server_DisposeMatch, + Client_PartLobby, + Client_JoinLobby, + Client_CreateMatch, + Client_JoinMatch, + Client_PartMatch, + Server_LobbyJoin_OLD, + Server_LobbyPart_OLD, + Server_MatchJoinSuccess, + Server_MatchJoinFail, + Client_MatchChangeSlot, + Client_MatchReady, + Client_MatchLock, + Client_MatchChangeSettings, + Server_FellowSpectatorJoined, + Server_FellowSpectatorLeft, + Client_MatchStart, + AllPlayersLoaded, + Server_MatchStart, + Client_MatchScoreUpdate, + Server_MatchScoreUpdate, + Client_MatchComplete, + Server_MatchTransferHost, + Client_MatchChangeMods, + Client_MatchLoadComplete, + Server_MatchAllPlayersLoaded, + Client_MatchNoBeatmap, + Client_MatchNotReady, + Client_MatchFailed, + Server_MatchComplete, + Client_MatchHasBeatmap, + Client_MatchSkipRequest, + Server_MatchSkip, + Server_Unauthorised, + Client_ChannelJoin, + Server_ChannelJoinSuccess, + Server_ChannelInfo, + Server_ChannelKicked, + Server_ChannelAvailableAutojoin, + Client_BeatmapInfoRequest, + Server_BeatmapInfoReply, + Client_MatchTransferHost, + Server_SupporterGMT, + Server_FriendsList, + Client_FriendAdd, + Client_FriendRemove, + Server_ProtocolNegotiation, + Server_MainMenuIcon, + Client_MatchChangeTeam, + Client_ChannelPart, + Client_ReceiveUpdates, + Server_Monitor, + Server_MatchPlayerSkipped, + Client_SetAwayMessage, + Server_UserPanel, + IRC_only, + Client_UserStatsRequest, + Server_Restart, + Client_Invite, + Server_Invite, + Server_ChannelInfoEnd, + Client_MatchChangePassword, + Server_MatchChangePassword, + Server_SilenceEnd, + Client_SpecialMatchInfoRequest, + Server_UserSilenced, + Server_UserPresenceSingle, + Server_UserPresenceBundle, + Client_UserPresenceRequest, + Client_UserPresenceRequestAll, + Client_UserToggleBlockNonFriendPM, + Server_UserPMBlocked, + Server_TargetIsSilenced, + Server_VersionUpdateForced, + Server_SwitchServer, + Server_AccountRestricted, + Server_RTX, + Client_MatchAbort, + Server_SwitchTourneyServer, + // NOTE: Tournament client only + Client_SpecialJoinMatchChannel, + // NOTE: Tournament client only + Client_SpecialLeaveMatchChanne, +} \ No newline at end of file diff --git a/server/loginHandler.js b/server/loginHandler.js deleted file mode 100755 index 68b8f39..0000000 --- a/server/loginHandler.js +++ /dev/null @@ -1,153 +0,0 @@ -const osu = require("osu-packet"), - User = require("./User.js"), - uuid = require("./util/shortUUID.js"), - ahttp = require("./util/AsyncHttpRequest.js"), - consoleHelper = require("../consoleHelper.js"), - // Packets - getUserByUsername = require("./util/getUserByUsername.js"), - getUserByToken = require("./util/getUserByToken.js"), - countryHelper = require("./countryHelper.js"), - loginHelper = require("./loginHelper.js"), - Logout = require("./Packets/Logout.js"), - Streams = require("./Streams.js"), - UserPresenceBundle = require("./Packets/UserPresenceBundle.js"), - UserPresence = require("./Packets/UserPresence.js"), - StatusUpdate = require("./Packets/StatusUpdate.js"); - -module.exports = async function(req, res, loginInfo) { - // Get time at the start of login - const loginStartTime = Date.now(), - isTourneyClient = loginInfo.osuversion.includes("tourney"); - - // Check login - const loginCheck = await loginHelper.checkLogin(loginInfo); - if (loginCheck != null) { - res.removeHeader('X-Powered-By'); - res.removeHeader('Date'); - res.writeHead(200, loginCheck[1]); - return res.end(loginCheck[0]); - } - - // Get users IP for getting location - // Get cloudflare requestee IP first - let requestIP = req.get("cf-connecting-ip"); - - // Get IP of requestee since we are probably behind a reverse proxy - if (requestIP == null) - requestIP = req.get("X-Real-IP"); - - // Just get the requestee IP (we are not behind a reverse proxy) - if (requestIP == null) - requestIP = req.remote_addr; - - // Make sure requestIP is never null - if (requestIP == null) - requestIP = ""; - - - let userLocationData = [], userLocation; - // Check if it is a local or null IP - if (requestIP.includes("192.168.") || requestIP.includes("127.0.") || requestIP == "") { - // Set location to null island - userLocationData.country = "XX"; - userLocation = [0, 0]; - } else { - // Get user's location using zxq - userLocationData = await ahttp(`http://ip.zxq.co/${requestIP}`, "json"); - userLocation = userLocationData.loc.split(","); - } - - // Get information about the user from the database - const userDB = await global.DatabaseHelper.query("SELECT id FROM users_info WHERE username = ? LIMIT 1", [loginInfo.username]); - - // Create a token for the client - const newClientToken = uuid(); - - // Make sure user is not already connected, kick off if so. - const connectedUser = getUserByUsername(loginInfo.username); - if (connectedUser != null && !isTourneyClient && !connectedUser.isTourneyUser) { - Logout(connectedUser); - } - - // Retreive the newly created user - const NewUser = global.users.add(newClientToken, new User(userDB.id, loginInfo.username, newClientToken)); - // Set tourney client flag - NewUser.isTourneyUser = isTourneyClient; - - // Get user's data from the database - NewUser.updateUserInfo(); - - try { - // Save the user's location to their class for later use - NewUser.location[0] = parseFloat(userLocation[0]); - NewUser.location[1] = parseFloat(userLocation[1]); - - // Save the country id for the same reason as above - NewUser.countryID = countryHelper.getCountryID(userLocationData.country); - - // We're ready to start putting together a login packet - // Create an osu! Packet writer - let osuPacketWriter = new osu.Bancho.Writer; - - // The reply id is the user's id in any other case than an error in which case negative numbers are used - osuPacketWriter.LoginReply(NewUser.id); - // Current bancho protocol version. Defined in Binato.js - osuPacketWriter.ProtocolNegotiation(global.protocolVersion); - // Permission level 4 is osu!supporter - osuPacketWriter.LoginPermissions(4); - - // After sending the user their friends list send them the online users - UserPresenceBundle(NewUser); - - // Set title screen image - //osuPacketWriter.TitleUpdate("http://puu.sh/jh7t7/20c04029ad.png|https://osu.ppy.sh/news/123912240253"); - - // Add user panel data packets - UserPresence(NewUser, NewUser.id); - StatusUpdate(NewUser, NewUser.id); - - // peppy pls, why - osuPacketWriter.ChannelListingComplete(); - - // Add user to #osu - osuPacketWriter.ChannelJoinSuccess("#osu"); - if (!Streams.isUserInStream("#osu", NewUser.uuid)) - Streams.addUserToStream("#osu", NewUser.uuid); - - // List all channels out to the client - for (let i = 0; i < global.channels.length; i++) { - osuPacketWriter.ChannelAvailable({ - channelName: global.channels[i].channelName, - channelTopic: global.channels[i].channelTopic, - channelUserCount: global.channels[i].channelUserCount - }); - } - - // Construct user's friends list - const userFriends = await global.DatabaseHelper.query("SELECT friendsWith FROM friends WHERE user = ?", [NewUser.id]); - let friendsArray = []; - for (let i = 0; i < userFriends.length; i++) { - friendsArray.push(userFriends[i].friendsWith); - } - // Send user's friends list - osuPacketWriter.FriendsList(friendsArray); - - osuPacketWriter.Announce(`Welcome back ${loginInfo.username}!`); - - global.DatabaseHelper.query("UPDATE osu_info SET value = ? WHERE name = 'online_now'", [global.users.getLength() - 1]); - - res.removeHeader('X-Powered-By'); - res.removeHeader('Date'); - // Complete login - res.writeHead(200, { - "cho-token": NewUser.uuid, - "Connection": "keep-alive", - "Keep-Alive": "timeout=5, max=100", - }); - res.end(osuPacketWriter.toBuffer, () => { - consoleHelper.printBancho(`User login finished, took ${Date.now() - loginStartTime}ms. [User: ${loginInfo.username}]`); - }); - } catch (err) { - console.error(err); - } -} \ No newline at end of file diff --git a/server/loginHelper.js b/server/loginHelper.js deleted file mode 100755 index f0bde5e..0000000 --- a/server/loginHelper.js +++ /dev/null @@ -1,74 +0,0 @@ -const osu = require("osu-packet"), - aes256 = require("aes256"), - crypto = require("crypto"), - config = require("../config.json"); - -module.exports = { - checkLogin: function(loginInfo) { - return new Promise(async (resolve, reject) => { - // Check if there is any login information provided - if (loginInfo == null) return resolve(incorrectLoginResponse()); - - const userDBData = await global.DatabaseHelper.query("SELECT * FROM users_info WHERE username = ? LIMIT 1", [loginInfo.username]); - - // Make sure a user was found in the database - if (userDBData == null) return resolve(incorrectLoginResponse()); - // Make sure the username is the same as the login info - if (userDBData.username !== loginInfo.username) return resolve(incorrectLoginResponse()); - /* - 1: Old MD5 password - 2: Old AES password - */ - if (userDBData.has_old_password === 1) { - if (userDBData.password_hash !== loginInfo.password) - return resolve(incorrectLoginResponse()); - - return resolve(requiredPWChangeResponse()); - } else if (userDBData.has_old_password === 2) { - if (aes256.decrypt(config.database.key, userDBData.password_hash) !== loginInfo.password) - return resolve(resolve(incorrectLoginResponse())); - - return resolve(requiredPWChangeResponse()); - } else { - crypto.pbkdf2(loginInfo.password, userDBData.password_salt, config.database.pbkdf2.itterations, config.database.pbkdf2.keylength, "sha512", (err, derivedKey) => { - if (err) { - return reject(err); - } else { - if (derivedKey.toString("hex") !== userDBData.password_hash) - return resolve(incorrectLoginResponse()); - - return resolve(null); // We good - } - }); - } - }); - }, - incorrectLoginResponse: incorrectLoginResponse -} - -function incorrectLoginResponse() { - const osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.LoginReply(-1); - return [ - osuPacketWriter.toBuffer, - { - 'cho-protocol': global.protocolVersion, - 'Connection': 'keep-alive', - 'Keep-Alive': 'timeout=5, max=100', - } - ]; -} - -function requiredPWChangeResponse() { - const osuPacketWriter = new osu.Bancho.Writer; - osuPacketWriter.Announce("As part of migration to a new password system you are required to change your password. Please log in on the website and change your password."); - osuPacketWriter.LoginReply(-1); - return [ - osuPacketWriter.toBuffer, - { - 'cho-protocol': global.protocolVersion, - 'Connection': 'keep-alive', - 'Keep-Alive': 'timeout=5, max=100', - } - ]; -} \ No newline at end of file diff --git a/server/objects/Channel.ts b/server/objects/Channel.ts new file mode 100644 index 0000000..e69de29 diff --git a/server/objects/User.ts b/server/objects/User.ts new file mode 100644 index 0000000..e69de29 diff --git a/server/packetIDs.js b/server/packetIDs.js deleted file mode 100755 index 631cca9..0000000 --- a/server/packetIDs.js +++ /dev/null @@ -1,111 +0,0 @@ -module.exports = { - "client_changeAction":0, - "client_sendPublicMessage":1, - "client_logout":2, - "client_requestStatusUpdate":3, - "client_pong":4, - "server_userID":5, - "server_commandError":6, - "server_sendMessage":7, - "server_ping":8, - "server_handleIRCUsernameChange":9, - "server_handleIRCQuit":10, - "server_userStats":11, - "server_userLogout":12, - "server_spectatorJoined":13, - "server_spectatorLeft":14, - "server_spectateFrames":15, - "client_startSpectating":16, - "client_stopSpectating":17, - "client_spectateFrames":18, - "server_versionUpdate":19, - "client_errorReport":20, - "client_cantSpectate":21, - "server_spectatorCantSpectate":22, - "server_getAttention":23, - "server_notification":24, - "client_sendPrivateMessage":25, - "server_updateMatch":26, - "server_newMatch":27, - "server_disposeMatch":28, - "client_partLobby":29, - "client_joinLobby":30, - "client_createMatch":31, - "client_joinMatch":32, - "client_partMatch":33, - "server_lobbyJoin_obsolete":34, - "server_lobbyPart_obsolete":35, - "server_matchJoinSuccess":36, - "server_matchJoinFail":37, - "client_matchChangeSlot":38, - "client_matchReady":39, - "client_matchLock":40, - "client_matchChangeSettings":41, - "server_fellowSpectatorJoined":42, - "server_fellowSpectatorLeft":43, - "client_matchStart":44, - "AllPlayersLoaded":45, - "server_matchStart":46, - "client_matchScoreUpdate":47, - "server_matchScoreUpdate":48, - "client_matchComplete":49, - "server_matchTransferHost":50, - "client_matchChangeMods":51, - "client_matchLoadComplete":52, - "server_matchAllPlayersLoaded":53, - "client_matchNoBeatmap":54, - "client_matchNotReady":55, - "client_matchFailed":56, - "server_matchComplete":58, - "client_matchHasBeatmap":59, - "client_matchSkipRequest":60, - "server_matchSkip":61, - "server_unauthorised":62, - "client_channelJoin":63, - "server_channelJoinSuccess":64, - "server_channelInfo":65, - "server_channelKicked":66, - "server_channelAvailableAutojoin":67, - "client_beatmapInfoRequest":68, - "server_beatmapInfoReply":69, - "client_matchTransferHost":70, - "server_supporterGMT":71, - "server_friendsList":72, - "client_friendAdd":73, - "client_friendRemove":74, - "server_protocolVersion":75, - "server_mainMenuIcon":76, - "client_matchChangeTeam":77, - "client_channelPart":78, - "client_receiveUpdates":79, - "server_topBotnet":80, - "server_matchPlayerSkipped":81, - "client_setAwayMessage":82, - "server_userPanel":83, - "IRC_only":84, - "client_userStatsRequest":85, - "server_restart":86, - "client_invite":87, - "server_invite":88, - "server_channelInfoEnd":89, - "client_matchChangePassword":90, - "server_matchChangePassword":91, - "server_silenceEnd":92, - "client_specialMatchInfoRequest":93, - "server_userSilenced":94, - "server_userPresenceSingle":95, - "server_userPresenceBundle":96, - "client_userPresenceRequest":97, - "client_userPresenceRequestAll":98, - "client_userToggleBlockNonFriendPM":99, - "server_userPMBlocked":100, - "server_targetIsSilenced":101, - "server_versionUpdateForced":102, - "server_switchServer":103, - "server_accountRestricted":104, - "server_jumpscare":105, - "client_matchAbort":106, - "server_switchTourneyServer":107, - "client_specialJoinMatchChannel":108, - "client_specialLeaveMatchChannel":109 -} diff --git a/server/packetIDs.json b/server/packetIDs.json deleted file mode 100644 index 116489f..0000000 --- a/server/packetIDs.json +++ /dev/null @@ -1,111 +0,0 @@ -{ - "client_changeAction":0, - "client_sendPublicMessage":1, - "client_logout":2, - "client_requestStatusUpdate":3, - "client_pong":4, - "server_userID":5, - "server_commandError":6, - "server_sendMessage":7, - "server_ping":8, - "server_handleIRCUsernameChange":9, - "server_handleIRCQuit":10, - "server_userStats":11, - "server_userLogout":12, - "server_spectatorJoined":13, - "server_spectatorLeft":14, - "server_spectateFrames":15, - "client_startSpectating":16, - "client_stopSpectating":17, - "client_spectateFrames":18, - "server_versionUpdate":19, - "client_errorReport":20, - "client_cantSpectate":21, - "server_spectatorCantSpectate":22, - "server_getAttention":23, - "server_notification":24, - "client_sendPrivateMessage":25, - "server_updateMatch":26, - "server_newMatch":27, - "server_disposeMatch":28, - "client_partLobby":29, - "client_joinLobby":30, - "client_createMatch":31, - "client_joinMatch":32, - "client_partMatch":33, - "server_lobbyJoin_obsolete":34, - "server_lobbyPart_obsolete":35, - "server_matchJoinSuccess":36, - "server_matchJoinFail":37, - "client_matchChangeSlot":38, - "client_matchReady":39, - "client_matchLock":40, - "client_matchChangeSettings":41, - "server_fellowSpectatorJoined":42, - "server_fellowSpectatorLeft":43, - "client_matchStart":44, - "AllPlayersLoaded":45, - "server_matchStart":46, - "client_matchScoreUpdate":47, - "server_matchScoreUpdate":48, - "client_matchComplete":49, - "server_matchTransferHost":50, - "client_matchChangeMods":51, - "client_matchLoadComplete":52, - "server_matchAllPlayersLoaded":53, - "client_matchNoBeatmap":54, - "client_matchNotReady":55, - "client_matchFailed":56, - "server_matchComplete":58, - "client_matchHasBeatmap":59, - "client_matchSkipRequest":60, - "server_matchSkip":61, - "server_unauthorised":62, - "client_channelJoin":63, - "server_channelJoinSuccess":64, - "server_channelInfo":65, - "server_channelKicked":66, - "server_channelAvailableAutojoin":67, - "client_beatmapInfoRequest":68, - "server_beatmapInfoReply":69, - "client_matchTransferHost":70, - "server_supporterGMT":71, - "server_friendsList":72, - "client_friendAdd":73, - "client_friendRemove":74, - "server_protocolVersion":75, - "server_mainMenuIcon":76, - "client_matchChangeTeam":77, - "client_channelPart":78, - "client_receiveUpdates":79, - "server_topBotnet":80, - "server_matchPlayerSkipped":81, - "client_setAwayMessage":82, - "server_userPanel":83, - "IRC_only":84, - "client_userStatsRequest":85, - "server_restart":86, - "client_invite":87, - "server_invite":88, - "server_channelInfoEnd":89, - "client_matchChangePassword":90, - "server_matchChangePassword":91, - "server_silenceEnd":92, - "client_specialMatchInfoRequest":93, - "server_userSilenced":94, - "server_userPresenceSingle":95, - "server_userPresenceBundle":96, - "client_userPresenceRequest":97, - "client_userPresenceRequestAll":98, - "client_userToggleBlockNonFriendPM":99, - "server_userPMBlocked":100, - "server_targetIsSilenced":101, - "server_versionUpdateForced":102, - "server_switchServer":103, - "server_accountRestricted":104, - "server_jumpscare":105, - "client_matchAbort":106, - "server_switchTourneyServer":107, - "client_specialJoinMatchChannel":108, - "client_specialLeaveMatchChannel":109 -} diff --git a/server/util/AsyncHttpRequest.js b/server/util/AsyncHttpRequest.js deleted file mode 100755 index 682ddd0..0000000 --- a/server/util/AsyncHttpRequest.js +++ /dev/null @@ -1,16 +0,0 @@ -const fetch = require("node-fetch"); - -const functionMap = { - "text": async (res) => await res.text(), - "json": async (res) => await res.json() -}; - -module.exports = async function(url, reqType = "text") { - return new Promise(async (resolve, reject) => { - try { - resolve(functionMap[reqType](await fetch(url))); - } catch (e) { - reject(e); - } - }); -} \ No newline at end of file diff --git a/server/util/Maths.js b/server/util/Maths.js deleted file mode 100755 index 10600ec..0000000 --- a/server/util/Maths.js +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = { - map:function(input, inputMin, inputMax, outputMin, outputMax) { - const newv = (input - inputMin) / (inputMax - inputMin) * (outputMax - outputMin) + outputMin; - if (outputMin < outputMax) return this.constrain(newv, outputMin, outputMax); - else return this.constrain(newv, outputMax, outputMin); - }, - - constrain:function(input, low, high) { - return Math.max(Math.min(input, high), low); - }, - - randInt:function(from, to) { - return Math.round(this.map(Math.random(), 0, 1, from, to)); - } -} \ No newline at end of file diff --git a/server/util/RequestType.json b/server/util/RequestType.json deleted file mode 100644 index 3b9fcf6..0000000 --- a/server/util/RequestType.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "Text": 0, - "JSON": 1, - "XML": 2 -} \ No newline at end of file diff --git a/server/util/funkyArray.js b/server/util/funkyArray.js deleted file mode 100755 index 04feeea..0000000 --- a/server/util/funkyArray.js +++ /dev/null @@ -1,75 +0,0 @@ -class FunkyArray { - constructor() { - this.items = {}; - this.itemKeys = Object.keys(this.items); - - this.iterableArray = []; - } - - add(uuid, item, regenerate = true) { - this.items[uuid] = item; - - if (regenerate) { - this.itemKeys = Object.keys(this.items); - this.regenerateIterableArray(); - } - - return this.items[uuid]; - } - - remove(uuid, regenerate = true) { - delete this.items[uuid]; - if (regenerate) { - this.itemKeys = Object.keys(this.items); - this.regenerateIterableArray(); - } - } - - removeFirstItem(regenerate = true) { - delete this.items[this.itemKeys[0]]; - this.itemKeys = Object.keys(this.items); - if (regenerate) this.regenerateIterableArray(); - } - - regenerateIterableArray() { - this.iterableArray = new Array(); - for (let itemKey of this.itemKeys) { - this.iterableArray.push(this.items[itemKey]); - } - this.itemKeys = Object.keys(this.items); - } - - getFirstItem() { - return this.items[this.itemKeys[0]]; - } - - getLength() { - return this.itemKeys.length; - } - - getKeyById(id) { - return this.itemKeys[id]; - } - - getById(id) { - return this.items[this.itemKeys[id]]; - } - - getByKey(key) { - return this.items[key]; - } - - getKeys() { - return this.itemKeys; - } - - getItems() { - return this.items; - } - - getIterableItems() { - return this.iterableArray; - } -} - -module.exports = FunkyArray; \ No newline at end of file diff --git a/server/util/getUserById.js b/server/util/getUserById.js deleted file mode 100755 index 529dab7..0000000 --- a/server/util/getUserById.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = function(id) { - for (let user of global.users.getIterableItems()) { - if (user.id == id) - return user; - } -} \ No newline at end of file diff --git a/server/util/getUserByToken.js b/server/util/getUserByToken.js deleted file mode 100755 index 78d3683..0000000 --- a/server/util/getUserByToken.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = function(token) { - return global.users.getByKey(token); -} \ No newline at end of file diff --git a/server/util/getUserByUsername.js b/server/util/getUserByUsername.js deleted file mode 100755 index d2e8f1b..0000000 --- a/server/util/getUserByUsername.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = function(username) { - for (let user of global.users.getIterableItems()) { - if (user.username === username) - return user; - } -} \ No newline at end of file diff --git a/server/util/parseUserData.js b/server/util/parseUserData.js deleted file mode 100755 index 3339a39..0000000 --- a/server/util/parseUserData.js +++ /dev/null @@ -1,33 +0,0 @@ -module.exports = function(packet) { - try { - const p = packet.toString(); // Convert our buffer to a String - const s = p.split('\n'); // Split our Login Data to Username Password Osuversion|blabla|bla - const n = s[2].split('|'); // Split osuversion|blablabla|blablabla to a object. - const username = s[0]; // Username ofc - const password = s[1]; // Password ofc - const osuversion = n[0]; // OsuVersion ofc. - const TimeOffset = Number(n[1]); // Comeon, i dont realy have to tell you what this is. - const clientData = n[3].split(':')[2]; // Some system information. such as MacAdress or DiskID - - // If some data is not set OR is invailed throw errors - if (username == undefined) throw 'UserName'; - if (password == undefined) throw 'password'; - if (osuversion == undefined) throw 'osuversion'; - if (TimeOffset == undefined) throw 'offset'; - if (clientData == undefined) throw 'clientData'; - - // Everything alright? return parsed data. - const obj = { - username: String(username), - password: String(password), - osuversion: String(osuversion), - timeoffset: Number(TimeOffset), - clientdata: String(clientData) - }; - // Here is the return. - return obj; - } catch (ex) { - // Else return undefined, that the login request got broke. - return undefined; - } -} \ No newline at end of file diff --git a/server/util/shortUUID.js b/server/util/shortUUID.js deleted file mode 100755 index a863855..0000000 --- a/server/util/shortUUID.js +++ /dev/null @@ -1,5 +0,0 @@ -const uuid = require("uuid").v4; - -module.exports = function() { - return uuid().split("-").slice(0, 2).join(""); -} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..d8da27b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "esModuleInterop": true, + "rootDir": "./", + "outDir": "./build", + "strict": true + } +} \ No newline at end of file diff --git a/web/chatPageTemplate.html b/web/chatPageTemplate.html deleted file mode 100755 index f99a04e..0000000 --- a/web/chatPageTemplate.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - -
- |content| -
- - \ No newline at end of file diff --git a/web/serverPage.html b/web/serverPage.html deleted file mode 100755 index 5e23aba..0000000 --- a/web/serverPage.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - Binato - - -
- 
-  .  o ..
-  o . o o.o
-       ...oo
-          __[]__           Binato
-       __|_o_o_o\__        A custom osu!Bancho
-       \""""""""""/
-        \. ..  . /         Website | Github
-  ^^^^^^^^^^^^^^^^^^^^
-		
- - \ No newline at end of file