From 4ebf9ee0e6cc456933fa5ec34ffc654dedab0cd5 Mon Sep 17 00:00:00 2001 From: Holly Date: Wed, 16 Nov 2022 11:59:23 +0000 Subject: [PATCH] Initial Future Commit (typescript) --- Binato.js | 79 - Binato.ts | 74 + ConsoleHelper.ts | 63 + LICENSE | 21 - README.md | 82 - config.example.json | 29 - consoleHelper.js | 63 - osu!.sql | 176 -- package-lock.json | 2119 +++++++++++++----- package.json | 20 +- server/{serverHandler.js => BanchoServer.ts} | 105 +- server/BotCommandHandler.js | 213 -- server/Channels.ts | 0 server/DatabaseHelper.js | 79 - server/MultiplayerExtras/OsuBattleRoyale.js | 143 -- server/MultiplayerManager.js | 227 -- server/MultiplayerMatch.js | 564 ----- server/Packets/AddFriend.js | 3 - server/Packets/ChangeAction.js | 11 - server/Packets/ChannelJoin.js | 17 - server/Packets/ChannelPart.js | 7 - server/Packets/Logout.js | 23 - server/Packets/MultiplayerInvite.js | 17 - server/Packets/RemoveFriend.js | 3 - server/Packets/SendPrivateMessage.js | 19 - server/Packets/SendPublicMessage.js | 58 - server/Packets/SetAwayMessage.js | 3 - server/Packets/StatusUpdate.js | 36 - server/Packets/TourneyJoinMatchChannel.js | 28 - server/Packets/TourneyLeaveMatchChannel.js | 32 - server/Packets/TourneyMatchSpecialInfo.js | 22 - server/Packets/UserPresence.js | 24 - server/Packets/UserPresenceBundle.js | 16 - server/Packets/UserStatsRequest.js | 14 - server/Spectator.js | 76 - server/Streams.js | 129 -- server/User.js | 125 -- server/bakedResponses.js | 9 - server/countryHelper.js | 274 --- server/enums/Packets.ts | 113 + server/loginHandler.js | 153 -- server/loginHelper.js | 74 - server/objects/Channel.ts | 0 server/objects/User.ts | 0 server/packetIDs.js | 111 - server/packetIDs.json | 111 - server/util/AsyncHttpRequest.js | 16 - server/util/Maths.js | 15 - server/util/RequestType.json | 5 - server/util/funkyArray.js | 75 - server/util/getUserById.js | 6 - server/util/getUserByToken.js | 3 - server/util/getUserByUsername.js | 6 - server/util/parseUserData.js | 33 - server/util/shortUUID.js | 5 - tsconfig.json | 10 + web/chatPageTemplate.html | 39 - web/serverPage.html | 19 - 58 files changed, 1879 insertions(+), 3918 deletions(-) delete mode 100755 Binato.js create mode 100644 Binato.ts create mode 100644 ConsoleHelper.ts delete mode 100644 LICENSE delete mode 100644 README.md delete mode 100644 config.example.json delete mode 100755 consoleHelper.js delete mode 100755 osu!.sql mode change 100755 => 100644 package.json rename server/{serverHandler.js => BanchoServer.ts} (81%) mode change 100755 => 100644 delete mode 100755 server/BotCommandHandler.js create mode 100644 server/Channels.ts delete mode 100755 server/DatabaseHelper.js delete mode 100755 server/MultiplayerExtras/OsuBattleRoyale.js delete mode 100755 server/MultiplayerManager.js delete mode 100755 server/MultiplayerMatch.js delete mode 100755 server/Packets/AddFriend.js delete mode 100755 server/Packets/ChangeAction.js delete mode 100755 server/Packets/ChannelJoin.js delete mode 100755 server/Packets/ChannelPart.js delete mode 100755 server/Packets/Logout.js delete mode 100755 server/Packets/MultiplayerInvite.js delete mode 100755 server/Packets/RemoveFriend.js delete mode 100755 server/Packets/SendPrivateMessage.js delete mode 100755 server/Packets/SendPublicMessage.js delete mode 100755 server/Packets/SetAwayMessage.js delete mode 100755 server/Packets/StatusUpdate.js delete mode 100755 server/Packets/TourneyJoinMatchChannel.js delete mode 100755 server/Packets/TourneyLeaveMatchChannel.js delete mode 100755 server/Packets/TourneyMatchSpecialInfo.js delete mode 100755 server/Packets/UserPresence.js delete mode 100755 server/Packets/UserPresenceBundle.js delete mode 100755 server/Packets/UserStatsRequest.js delete mode 100755 server/Spectator.js delete mode 100755 server/Streams.js delete mode 100755 server/User.js delete mode 100755 server/bakedResponses.js delete mode 100755 server/countryHelper.js create mode 100644 server/enums/Packets.ts delete mode 100755 server/loginHandler.js delete mode 100755 server/loginHelper.js create mode 100644 server/objects/Channel.ts create mode 100644 server/objects/User.ts delete mode 100755 server/packetIDs.js delete mode 100644 server/packetIDs.json delete mode 100755 server/util/AsyncHttpRequest.js delete mode 100755 server/util/Maths.js delete mode 100644 server/util/RequestType.json delete mode 100755 server/util/funkyArray.js delete mode 100755 server/util/getUserById.js delete mode 100755 server/util/getUserByToken.js delete mode 100755 server/util/getUserByUsername.js delete mode 100755 server/util/parseUserData.js delete mode 100755 server/util/shortUUID.js create mode 100644 tsconfig.json delete mode 100755 web/chatPageTemplate.html delete mode 100755 web/serverPage.html 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