fix everything
This commit is contained in:
parent
148c2c341f
commit
3a07a892e1
63 changed files with 431 additions and 1032 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,6 +1,6 @@
|
||||||
node_modules/
|
node_modules/
|
||||||
build/
|
build/
|
||||||
bundle/
|
combined.ts
|
||||||
tHMM.ds
|
tHMM.ds
|
||||||
server-stats.log
|
server-stats.log
|
||||||
config.json
|
config.json
|
||||||
|
|
47
Binato.ts
47
Binato.ts
|
@ -8,65 +8,54 @@ if (!existsSync("./config.json")) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
import { ChatHistory } from "./server/ChatHistory";
|
import ChatHistory from "./server/ChatHistory";
|
||||||
import { Config } from "./server/interfaces/Config";
|
import Config from "./server/interfaces/Config";
|
||||||
import compression from "compression";
|
import HandleRequest from "./server/BanchoServer";
|
||||||
import express from "express";
|
|
||||||
import { HandleRequest } from "./server/BanchoServer";
|
|
||||||
import { Shared } from "./server/objects/Shared";
|
|
||||||
import { Registry, collectDefaultMetrics } from "prom-client";
|
import { Registry, collectDefaultMetrics } from "prom-client";
|
||||||
|
import http from "http";
|
||||||
const config:Config = JSON.parse(readFileSync(__dirname + "/config.json").toString()) as Config;
|
const config:Config = JSON.parse(readFileSync(__dirname + "/config.json").toString()) as Config;
|
||||||
|
|
||||||
const binatoApp:express.Application = express();
|
|
||||||
|
|
||||||
if (config["prometheus"]["enabled"]) {
|
if (config["prometheus"]["enabled"]) {
|
||||||
const register:Registry = new Registry();
|
const register:Registry = new Registry();
|
||||||
register.setDefaultLabels({ app: "nodejs_binato" });
|
register.setDefaultLabels({ app: "nodejs_binato" });
|
||||||
|
|
||||||
collectDefaultMetrics({ register });
|
collectDefaultMetrics({ register });
|
||||||
|
|
||||||
const prometheusApp:express.Application = express();
|
const prometheusServer = http.createServer(async (req, res) => {
|
||||||
prometheusApp.get("/metrics", async (req, res) => {
|
if (req.method === "GET") {
|
||||||
res.end(await register.metrics());
|
res.end(await register.metrics());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
prometheusApp.listen(config["prometheus"]["port"], () => ConsoleHelper.printInfo(`Prometheus metrics listening at port ${config["prometheus"]["port"]}`));
|
prometheusServer.listen(config["prometheus"]["port"], () => ConsoleHelper.printInfo(`Prometheus metrics listening at port ${config["prometheus"]["port"]}`));
|
||||||
} else {
|
} else {
|
||||||
ConsoleHelper.printWarn("Prometheus is disabled!");
|
ConsoleHelper.printWarn("Prometheus is disabled!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config["express"]["compression"]) {
|
|
||||||
binatoApp.use(compression());
|
|
||||||
ConsoleHelper.printInfo("Compression is enabled");
|
|
||||||
} else {
|
|
||||||
ConsoleHelper.printWarn("Compression is disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
const INDEX_PAGE:string = readFileSync("./web/serverPage.html").toString();
|
const INDEX_PAGE:string = readFileSync("./web/serverPage.html").toString();
|
||||||
|
|
||||||
binatoApp.use((req, res) => {
|
const binatoServer = http.createServer((req, res) => {
|
||||||
let packet:Buffer = Buffer.alloc(0);
|
let packet:Buffer = Buffer.alloc(0);
|
||||||
req.on("data", (chunk:Buffer) => packet = Buffer.concat([packet, chunk], packet.length + chunk.length));
|
req.on("data", (chunk:Buffer) => packet = Buffer.concat([packet, chunk], packet.length + chunk.length));
|
||||||
req.on("end", () => {
|
req.on("end", () => {
|
||||||
switch (req.method) {
|
switch (req.method) {
|
||||||
case "GET":
|
case "GET":
|
||||||
if (req.url == "/" || req.url == "/index.html" || req.url == "/index") {
|
if (req.url == "/" || req.url == "/index.html" || req.url == "/index") {
|
||||||
res.send(INDEX_PAGE);
|
res.end(INDEX_PAGE);
|
||||||
} else if (req.url == "/chat") {
|
} else if (req.url == "/chat") {
|
||||||
// I don't think this works??
|
// I don't think this works??
|
||||||
res.send(ChatHistory.GenerateForWeb());
|
res.end(ChatHistory.GenerateForWeb());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "POST":
|
case "POST":
|
||||||
HandleRequest(req, res, packet);
|
HandleRequest(req, res, packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
res.status(405).send("405 | Method not allowed!<hr>Binato");
|
res.writeHead(405);
|
||||||
break;
|
res.end("Method not allowed");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
binatoApp.listen(config.express.port, () => ConsoleHelper.printInfo(`Binato is up! Listening at port ${config.express.port}`));
|
binatoServer.listen(config.http.port, () => ConsoleHelper.printInfo(`Binato is up! Listening at port ${config.http.port}`));
|
|
@ -1,4 +1,4 @@
|
||||||
export abstract class Constants {
|
export default abstract class Constants {
|
||||||
public static readonly DEBUG = false;
|
public static readonly DEBUG = false;
|
||||||
public static readonly PROTOCOL_VERSION = 19;
|
public static readonly PROTOCOL_VERSION = 19;
|
||||||
}
|
}
|
|
@ -1,9 +1,8 @@
|
||||||
import { OsuPacketWriter } from "./server/interfaces/OsuPacketWriter";
|
import OsuPacketWriter from "./server/interfaces/OsuPacketWriter";
|
||||||
|
|
||||||
// Dummy file
|
|
||||||
const nodeOsu = require("osu-packet");
|
const nodeOsu = require("osu-packet");
|
||||||
|
|
||||||
export abstract class osu {
|
export default abstract class osu {
|
||||||
static Bancho = {
|
static Bancho = {
|
||||||
Writer: function() : OsuPacketWriter {
|
Writer: function() : OsuPacketWriter {
|
||||||
return new nodeOsu.Bancho.Writer();
|
return new nodeOsu.Bancho.Writer();
|
||||||
|
|
737
package-lock.json
generated
737
package-lock.json
generated
File diff suppressed because it is too large
Load diff
14
package.json
14
package.json
|
@ -18,25 +18,21 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"aes256": "^1.1.0",
|
"aes256": "^1.1.0",
|
||||||
"compression": "^1.7.4",
|
|
||||||
"dyetty": "^1.0.1",
|
"dyetty": "^1.0.1",
|
||||||
"express": "^4.18.2",
|
"mysql2": "^3.6.1",
|
||||||
"mysql2": "^3.6.0",
|
"node-fetch": "^2.7.0",
|
||||||
"node-fetch": "^2.6.13",
|
|
||||||
"osu-packet": "^4.1.2",
|
"osu-packet": "^4.1.2",
|
||||||
"prom-client": "^14.2.0",
|
"prom-client": "^14.2.0",
|
||||||
"redis": "^4.6.7"
|
"redis": "^4.6.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/compression": "^1.7.2",
|
"@types/node": "^20.6.0",
|
||||||
"@types/express": "^4.17.17",
|
|
||||||
"@types/node": "^20.5.1",
|
|
||||||
"@types/node-fetch": "^2.6.4",
|
"@types/node-fetch": "^2.6.4",
|
||||||
"check-outdated": "^2.12.0",
|
"check-outdated": "^2.12.0",
|
||||||
"nodemon": "^3.0.1",
|
"nodemon": "^3.0.1",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"ts-loader": "^9.4.4",
|
"ts-loader": "^9.4.4",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "^5.1.6"
|
"typescript": "^5.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
|
import Channel from "./objects/Channel";
|
||||||
import { ConsoleHelper } from "../ConsoleHelper";
|
import { ConsoleHelper } from "../ConsoleHelper";
|
||||||
import { Channel } from "./objects/Channel";
|
import Constants from "../Constants";
|
||||||
import { LatLng } from "./objects/LatLng";
|
import LoginProcess from "./LoginProcess";
|
||||||
import { LoginProcess } from "./LoginProcess";
|
import { IncomingMessage, ServerResponse } from "http";
|
||||||
import { Packets } from "./enums/Packets";
|
import { Packets } from "./enums/Packets";
|
||||||
import { RedisClientType, createClient } from "redis";
|
import { RedisClientType, createClient } from "redis";
|
||||||
import { Request, Response } from "express";
|
import MessageData from "./interfaces/MessageData";
|
||||||
import { SpectatorManager } from "./SpectatorManager";
|
import PrivateMessage from "./packets/PrivateMessage";
|
||||||
import { User } from "./objects/User";
|
import Shared from "./objects/Shared";
|
||||||
import { PrivateMessage } from "./packets/PrivateMessage";
|
import SpectatorManager from "./SpectatorManager";
|
||||||
import { MessageData } from "./interfaces/MessageData";
|
import osu from "../osuTyping";
|
||||||
import { Shared } from "./objects/Shared";
|
|
||||||
|
|
||||||
const shared:Shared = new Shared();
|
const shared:Shared = new Shared();
|
||||||
shared.database.query("UPDATE mp_matches SET close_time = UNIX_TIMESTAMP() WHERE close_time IS NULL");
|
shared.database.query("UPDATE mp_matches SET close_time = UNIX_TIMESTAMP() WHERE close_time IS NULL");
|
||||||
|
@ -55,19 +55,17 @@ if (shared.config.redis.enabled) {
|
||||||
} else ConsoleHelper.printWarn("Redis is disabled!");
|
} else ConsoleHelper.printWarn("Redis is disabled!");
|
||||||
|
|
||||||
// Import packets
|
// Import packets
|
||||||
import { ChangeAction } from "./packets/ChangeAction";
|
import ChangeAction from "./packets/ChangeAction";
|
||||||
import { Logout } from "./packets/Logout";
|
import Logout from "./packets/Logout";
|
||||||
import { UserPresence } from "./packets/UserPresence";
|
import UserPresence from "./packets/UserPresence";
|
||||||
import { UserStatsRequest } from "./packets/UserStatsRequest";
|
import UserStatsRequest from "./packets/UserStatsRequest";
|
||||||
import { UserPresenceBundle } from "./packets/UserPresenceBundle";
|
import UserPresenceBundle from "./packets/UserPresenceBundle";
|
||||||
import { TourneyMatchSpecialInfo } from "./packets/TourneyMatchSpecialInfo";
|
import TourneyMatchSpecialInfo from "./packets/TourneyMatchSpecialInfo";
|
||||||
import { osu } from "../osuTyping";
|
import TourneyMatchJoinChannel from "./packets/TourneyJoinMatchChannel";
|
||||||
import { TourneyMatchJoinChannel } from "./packets/TourneyJoinMatchChannel";
|
import TourneyMatchLeaveChannel from "./packets/TourneyMatchLeaveChannel";
|
||||||
import { TourneyMatchLeaveChannel } from "./packets/TourneyMatchLeaveChannel";
|
import AddFriend from "./packets/AddFriend";
|
||||||
import { AddFriend } from "./packets/AddFriend";
|
import RemoveFriend from "./packets/RemoveFriend";
|
||||||
import { RemoveFriend } from "./packets/RemoveFriend";
|
import PrivateChannel from "./objects/PrivateChannel";
|
||||||
import { PrivateChannel } from "./objects/PrivateChannel";
|
|
||||||
import { Constants } from "../Constants";
|
|
||||||
|
|
||||||
// User timeout interval
|
// User timeout interval
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
|
@ -83,30 +81,23 @@ setInterval(() => {
|
||||||
|
|
||||||
const EMPTY_BUFFER = Buffer.alloc(0);
|
const EMPTY_BUFFER = Buffer.alloc(0);
|
||||||
|
|
||||||
export async function HandleRequest(req:Request, res:Response, packet:Buffer) {
|
export default async function HandleRequest(req:IncomingMessage, res:ServerResponse, packet:Buffer) {
|
||||||
// Get the client's token string and request data
|
// Get the client's token string and request data
|
||||||
const requestTokenString:string | undefined = req.header("osu-token");
|
const requestTokenString = typeof(req.headers["osu-token"]) === "string" ? req.headers["osu-token"] : undefined;
|
||||||
|
|
||||||
// Check if the user is logged in
|
// Check if the user is logged in
|
||||||
if (requestTokenString == null) {
|
if (requestTokenString === undefined) {
|
||||||
// Only do this if we're absolutely sure that we're connected to the DB
|
// Client doesn't have a token yet, let's auth them!
|
||||||
if (shared.database.connected) {
|
|
||||||
// Client doesn't have a token yet, let's auth them!
|
await LoginProcess(req, res, packet, shared);
|
||||||
|
shared.database.query("UPDATE osu_info SET value = ? WHERE name = 'online_now'", [shared.users.getLength() - 1]);
|
||||||
await LoginProcess(req, res, packet, shared);
|
|
||||||
shared.database.query("UPDATE osu_info SET value = ? WHERE name = 'online_now'", [shared.users.getLength() - 1]);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let responseData:Buffer | string = EMPTY_BUFFER;
|
let responseData = EMPTY_BUFFER;
|
||||||
|
|
||||||
// Remove headers we don't need for Bancho
|
|
||||||
res.removeHeader('X-Powered-By');
|
|
||||||
res.removeHeader('Date'); // This is not spec compilant
|
|
||||||
|
|
||||||
// Client has a token, let's see what they want.
|
// Client has a token, let's see what they want.
|
||||||
try {
|
try {
|
||||||
// Get the current user
|
// Get the current user
|
||||||
const PacketUser:User | undefined = shared.users.getByToken(requestTokenString);
|
const PacketUser = shared.users.getByToken(requestTokenString);
|
||||||
|
|
||||||
// Make sure the client's token isn't invalid
|
// Make sure the client's token isn't invalid
|
||||||
if (PacketUser != null) {
|
if (PacketUser != null) {
|
||||||
|
@ -298,12 +289,12 @@ export async function HandleRequest(req:Request, res:Response, packet:Buffer) {
|
||||||
responseData = PacketUser.queue;
|
responseData = PacketUser.queue;
|
||||||
PacketUser.clearQueue();
|
PacketUser.clearQueue();
|
||||||
} else {
|
} else {
|
||||||
// Only do this if we're absolutely sure that we're connected to the DB
|
// User's token is invlid, force a reconnect
|
||||||
if (shared.database.connected) {
|
ConsoleHelper.printBancho(`Forced client re-login (Token is invalid)`);
|
||||||
// User's token is invlid, force a reconnect
|
const osuPacketWriter = osu.Bancho.Writer();
|
||||||
ConsoleHelper.printBancho(`Forced client re-login (Token is invalid)`);
|
osuPacketWriter.Announce("Reconnecting...");
|
||||||
responseData = "\u0005\u0000\u0000\u0004\u0000\u0000\u0000<30><30><EFBFBD><EFBFBD>\u0018\u0000\u0000\u0011\u0000\u0000\u0000\u000b\u000fReconnecting...";
|
osuPacketWriter.Restart(0);
|
||||||
}
|
responseData = osuPacketWriter.toBuffer;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (Constants.DEBUG) {
|
if (Constants.DEBUG) {
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { ICommand } from "./interfaces/ICommand";
|
import ICommand from "./interfaces/ICommand";
|
||||||
import { Channel } from "./objects/Channel";
|
import Channel from "./objects/Channel";
|
||||||
import { Shared } from "./objects/Shared";
|
import Shared from "./objects/Shared";
|
||||||
import { User } from "./objects/User";
|
import User from "./objects/User";
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
import { RankingCommand } from "./commands/Ranking";
|
import RankingCommand from "./commands/Ranking";
|
||||||
import { LockCommand } from "./commands/Lock";
|
import LockCommand from "./commands/Lock";
|
||||||
import { MultiplayerCommands } from "./commands/Multiplayer";
|
import MultiplayerCommands from "./commands/Multiplayer";
|
||||||
import { HelpCommand } from "./commands/Help";
|
import HelpCommand from "./commands/Help";
|
||||||
import { RollCommand } from "./commands/RollCommand";
|
import RollCommand from "./commands/RollCommand";
|
||||||
|
|
||||||
export class Bot {
|
export default class Bot {
|
||||||
public user:User;
|
public user:User;
|
||||||
private commands:{ [id: string]: ICommand } = {};
|
private commands:{ [id: string]: ICommand } = {};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { readFileSync } from "fs";
|
import { readFileSync } from "fs";
|
||||||
|
|
||||||
export abstract class ChatHistory {
|
export default abstract class ChatHistory {
|
||||||
private static _history:Array<string> = new Array<string>();
|
private static _history:Array<string> = new Array<string>();
|
||||||
private static _lastGeneratedPage:string;
|
private static _lastGeneratedPage:string;
|
||||||
private static _hasChanged:boolean = true;
|
private static _hasChanged:boolean = true;
|
||||||
|
@ -8,7 +8,7 @@ export abstract class ChatHistory {
|
||||||
private static readonly PAGE_TEMPLATE = readFileSync("./web/chatPageTemplate.html").toString();
|
private static readonly PAGE_TEMPLATE = readFileSync("./web/chatPageTemplate.html").toString();
|
||||||
|
|
||||||
public static AddMessage(message:string) : void {
|
public static AddMessage(message:string) : void {
|
||||||
if (this._history.length === 10) {
|
if (this._history.length === this.HISTORY_LENGTH) {
|
||||||
this._history.splice(0, 1);
|
this._history.splice(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,14 +17,14 @@ export abstract class ChatHistory {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GenerateForWeb() : string {
|
public static GenerateForWeb() : string {
|
||||||
let lines:string = "", flip:boolean = false;
|
|
||||||
|
|
||||||
for (let i:number = Math.max(this._history.length - this.HISTORY_LENGTH, this.HISTORY_LENGTH); i < this._history.length; i++) {
|
|
||||||
lines += `<div class="line line${flip ? 1 : 0}">${this._history[i] == null ? "<hidden>blank</hidden>" : this._history[i]}</div>`
|
|
||||||
flip = !flip;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._hasChanged) {
|
if (this._hasChanged) {
|
||||||
|
let lines = "", flip = false;
|
||||||
|
|
||||||
|
for (let i = 0; i < this.HISTORY_LENGTH; i++) {
|
||||||
|
lines += `<div class="line line${flip ? 1 : 0}">${this._history[i] == null ? "<hidden>blank</hidden>" : this._history[i].replaceAll("<", "<").replaceAll(">", ">").replaceAll("\n", "<br>")}</div>`
|
||||||
|
flip = !flip;
|
||||||
|
}
|
||||||
|
|
||||||
this._lastGeneratedPage = this.PAGE_TEMPLATE.toString().replace("|content|", lines);
|
this._lastGeneratedPage = this.PAGE_TEMPLATE.toString().replace("|content|", lines);
|
||||||
this._hasChanged = false;
|
this._hasChanged = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { Channel } from "./objects/Channel";
|
import Channel from "./objects/Channel";
|
||||||
import { ConsoleHelper } from "../ConsoleHelper";
|
import { ConsoleHelper } from "../ConsoleHelper";
|
||||||
import { FunkyArray } from "./objects/FunkyArray";
|
import FunkyArray from "./objects/FunkyArray";
|
||||||
import { User } from "./objects/User";
|
import User from "./objects/User";
|
||||||
import { Shared } from "./objects/Shared";
|
import Shared from "./objects/Shared";
|
||||||
import { osu } from "../osuTyping";
|
import osu from "../osuTyping";
|
||||||
import { PrivateChannel } from "./objects/PrivateChannel";
|
import PrivateChannel from "./objects/PrivateChannel";
|
||||||
|
|
||||||
export class ChatManager {
|
export default class ChatManager {
|
||||||
public chatChannels:FunkyArray<Channel> = new FunkyArray<Channel>();
|
public chatChannels:FunkyArray<Channel> = new FunkyArray<Channel>();
|
||||||
public forceJoinChannels:FunkyArray<Channel> = new FunkyArray<Channel>();
|
public forceJoinChannels:FunkyArray<Channel> = new FunkyArray<Channel>();
|
||||||
private readonly shared:Shared;
|
private readonly shared:Shared;
|
||||||
|
|
|
@ -254,7 +254,7 @@ enum CountryCodes {
|
||||||
const keys = Object.keys(CountryCodes);
|
const keys = Object.keys(CountryCodes);
|
||||||
const values = Object.values(CountryCodes);
|
const values = Object.values(CountryCodes);
|
||||||
|
|
||||||
export function getCountryID(code:string) : number {
|
export default function getCountryID(code:string) : number {
|
||||||
// Get id of a country from a 2 char code
|
// Get id of a country from a 2 char code
|
||||||
const upperCode:string = code.toUpperCase();
|
const upperCode:string = code.toUpperCase();
|
||||||
if (upperCode in CountryCodes) {
|
if (upperCode in CountryCodes) {
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import { ConsoleHelper } from "../ConsoleHelper";
|
import { ConsoleHelper } from "../ConsoleHelper";
|
||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
import { getCountryID } from "./Country";
|
import getCountryID from "./Country";
|
||||||
import { generateSession } from "./Util";
|
import { generateSession } from "./Util";
|
||||||
import { LatLng } from "./objects/LatLng";
|
import LatLng from "./objects/LatLng";
|
||||||
import { LoginInfo } from "./objects/LoginInfo";
|
import LoginInfo from "./objects/LoginInfo";
|
||||||
import { Logout } from "./packets/Logout";
|
import Logout from "./packets/Logout";
|
||||||
import { pbkdf2 } from "crypto";
|
import { pbkdf2 } from "crypto";
|
||||||
import { Request, Response } from "express";
|
import User from "./objects/User";
|
||||||
import { User } from "./objects/User";
|
import UserPresenceBundle from "./packets/UserPresenceBundle";
|
||||||
import { UserPresenceBundle } from "./packets/UserPresenceBundle";
|
import UserPresence from "./packets/UserPresence";
|
||||||
import { UserPresence } from "./packets/UserPresence";
|
import StatusUpdate from "./packets/StatusUpdate";
|
||||||
import { StatusUpdate } from "./packets/StatusUpdate";
|
import Shared from "./objects/Shared";
|
||||||
import { Shared } from "./objects/Shared";
|
import osu from "../osuTyping";
|
||||||
import { osu } from "../osuTyping";
|
import IpZxqResponse from "./interfaces/IpZxqResponse";
|
||||||
import { IpZxqResponse } from "./interfaces/IpZxqResponse";
|
import { IncomingMessage, ServerResponse } from "http";
|
||||||
const { decrypt: aesDecrypt } = require("aes256");
|
const { decrypt: aesDecrypt } = require("aes256");
|
||||||
|
|
||||||
const incorrectLoginResponse:Buffer = osu.Bancho.Writer().LoginReply(-1).toBuffer;
|
const incorrectLoginResponse:Buffer = osu.Bancho.Writer().LoginReply(-1).toBuffer;
|
||||||
|
@ -43,7 +43,6 @@ function TestLogin(loginInfo:LoginInfo, shared:Shared) {
|
||||||
// Make sure the username is the same as the login info
|
// Make sure the username is the same as the login info
|
||||||
if (userDBData.username !== loginInfo.username) return resolve(LoginResult.INCORRECT);
|
if (userDBData.username !== loginInfo.username) return resolve(LoginResult.INCORRECT);
|
||||||
|
|
||||||
console.log(userDBData.has_old_password);
|
|
||||||
switch (userDBData.has_old_password) {
|
switch (userDBData.has_old_password) {
|
||||||
case LoginTypes.CURRENT:
|
case LoginTypes.CURRENT:
|
||||||
pbkdf2(loginInfo.password, userDBData.password_salt, shared.config.database.pbkdf2.itterations, shared.config.database.pbkdf2.keylength, "sha512", (err, derivedKey) => {
|
pbkdf2(loginInfo.password, userDBData.password_salt, shared.config.database.pbkdf2.itterations, shared.config.database.pbkdf2.keylength, "sha512", (err, derivedKey) => {
|
||||||
|
@ -58,11 +57,9 @@ function TestLogin(loginInfo:LoginInfo, shared:Shared) {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case LoginTypes.OLD_AES:
|
case LoginTypes.OLD_AES:
|
||||||
console.log("OLD AES");
|
|
||||||
if (aesDecrypt(shared.config.database.key, userDBData.password_hash) !== loginInfo.password) {
|
if (aesDecrypt(shared.config.database.key, userDBData.password_hash) !== loginInfo.password) {
|
||||||
return resolve(LoginResult.INCORRECT);
|
return resolve(LoginResult.INCORRECT);
|
||||||
}
|
}
|
||||||
console.log("correct password");
|
|
||||||
return resolve(LoginResult.MIGRATION);
|
return resolve(LoginResult.MIGRATION);
|
||||||
case LoginTypes.OLD_MD5:
|
case LoginTypes.OLD_MD5:
|
||||||
if (userDBData.password_hash !== loginInfo.password) {
|
if (userDBData.password_hash !== loginInfo.password) {
|
||||||
|
@ -73,7 +70,7 @@ function TestLogin(loginInfo:LoginInfo, shared:Shared) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function LoginProcess(req:Request, res:Response, packet:Buffer, shared:Shared) {
|
export default async function LoginProcess(req:IncomingMessage, res:ServerResponse, packet:Buffer, shared:Shared) {
|
||||||
const loginStartTime = Date.now();
|
const loginStartTime = Date.now();
|
||||||
const loginInfo = LoginInfo.From(packet);
|
const loginInfo = LoginInfo.From(packet);
|
||||||
|
|
||||||
|
@ -93,11 +90,11 @@ export async function LoginProcess(req:Request, res:Response, packet:Buffer, sha
|
||||||
|
|
||||||
// Get users IP for getting location
|
// Get users IP for getting location
|
||||||
// Get cloudflare requestee IP first
|
// Get cloudflare requestee IP first
|
||||||
let requestIP = req.get("cf-connecting-ip");
|
let requestIP = req.headers["cf-connecting-ip"];
|
||||||
|
|
||||||
// Get IP of requestee since we are probably behind a reverse proxy
|
// Get IP of requestee since we are probably behind a reverse proxy
|
||||||
if (requestIP === undefined) {
|
if (requestIP === undefined) {
|
||||||
requestIP = req.get("X-Real-IP");
|
requestIP = req.headers["X-Real-IP"];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just get the requestee IP (we are not behind a reverse proxy)
|
// Just get the requestee IP (we are not behind a reverse proxy)
|
||||||
|
@ -196,7 +193,7 @@ export async function LoginProcess(req:Request, res:Response, packet:Buffer, sha
|
||||||
|
|
||||||
osuPacketWriter.Announce(`Welcome back ${loginInfo.username}!`);
|
osuPacketWriter.Announce(`Welcome back ${loginInfo.username}!`);
|
||||||
// TODO: Remove once merged into master
|
// TODO: Remove once merged into master
|
||||||
osuPacketWriter.Announce("WARNING\nThis is a development test server made for the TypeScript rewrite.\nAnything could happen be it data loss, catastrophic crashes or otherwise.\nHere be dragons.");
|
osuPacketWriter.Announce("Heads up!\nWhile the TypeScript server rewrite is mostly stable it still has some issues.");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
@ -208,10 +205,10 @@ export async function LoginProcess(req:Request, res:Response, packet:Buffer, sha
|
||||||
const writerBuffer:Buffer = osuPacketWriter.toBuffer;
|
const writerBuffer:Buffer = osuPacketWriter.toBuffer;
|
||||||
if (newUser === undefined) {
|
if (newUser === undefined) {
|
||||||
res.writeHead(200, {
|
res.writeHead(200, {
|
||||||
|
"cho-token": "no",
|
||||||
"Connection": "keep-alive",
|
"Connection": "keep-alive",
|
||||||
"Keep-Alive": "timeout=5, max=100"
|
"Keep-Alive": "timeout=5, max=100"
|
||||||
});
|
});
|
||||||
console.log(res.headersSent);
|
|
||||||
switch (loginResult) {
|
switch (loginResult) {
|
||||||
case LoginResult.INCORRECT:
|
case LoginResult.INCORRECT:
|
||||||
res.end(incorrectLoginResponse, () => {
|
res.end(incorrectLoginResponse, () => {
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import { Channel } from "./objects/Channel";
|
import Channel from "./objects/Channel";
|
||||||
import { Shared } from "./objects/Shared";
|
import Shared from "./objects/Shared";
|
||||||
import { SlotStatus } from "./enums/SlotStatus";
|
import { SlotStatus } from "./enums/SlotStatus";
|
||||||
import { DataStream } from "./objects/DataStream";
|
import DataStream from "./objects/DataStream";
|
||||||
import { Match } from "./objects/Match";
|
import Match from "./objects/Match";
|
||||||
import { User } from "./objects/User";
|
import User from "./objects/User";
|
||||||
import { StatusUpdate } from "./packets/StatusUpdate";
|
import StatusUpdate from "./packets/StatusUpdate";
|
||||||
import { UserPresence } from "./packets/UserPresence";
|
import UserPresence from "./packets/UserPresence";
|
||||||
import { UserPresenceBundle } from "./packets/UserPresenceBundle";
|
import UserPresenceBundle from "./packets/UserPresenceBundle";
|
||||||
import { MatchArray } from "./objects/MatchArray";
|
import MatchArray from "./objects/MatchArray";
|
||||||
import { MatchJoinData } from "./interfaces/MatchJoinData";
|
import MatchJoinData from "./interfaces/MatchJoinData";
|
||||||
import { MatchData } from "./interfaces/MatchData";
|
import MatchData from "./interfaces/MatchData";
|
||||||
import { osu } from "../osuTyping";
|
import osu from "../osuTyping";
|
||||||
|
|
||||||
export class MultiplayerManager {
|
export default class MultiplayerManager {
|
||||||
private readonly shared:Shared;
|
private readonly shared:Shared;
|
||||||
private matches:MatchArray = new MatchArray();
|
private matches:MatchArray = new MatchArray();
|
||||||
private readonly lobbyStream:DataStream;
|
private readonly lobbyStream:DataStream;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { Channel } from "./objects/Channel";
|
import Channel from "./objects/Channel";
|
||||||
import { ConsoleHelper } from "../ConsoleHelper";
|
import { ConsoleHelper } from "../ConsoleHelper";
|
||||||
import { FunkyArray } from "./objects/FunkyArray";
|
import FunkyArray from "./objects/FunkyArray";
|
||||||
import { User } from "./objects/User";
|
import User from "./objects/User";
|
||||||
import { Shared } from "./objects/Shared";
|
import Shared from "./objects/Shared";
|
||||||
import { osu } from "../osuTyping";
|
import osu from "../osuTyping";
|
||||||
import { PrivateChannel } from "./objects/PrivateChannel";
|
import PrivateChannel from "./objects/PrivateChannel";
|
||||||
|
|
||||||
export class PrivateChatManager {
|
export default class PrivateChatManager {
|
||||||
public chatChannels:FunkyArray<PrivateChannel> = new FunkyArray<PrivateChannel>();
|
public chatChannels:FunkyArray<PrivateChannel> = new FunkyArray<PrivateChannel>();
|
||||||
private readonly shared:Shared;
|
private readonly shared:Shared;
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { DataStream } from "./objects/DataStream";
|
import DataStream from "./objects/DataStream";
|
||||||
import { Shared } from "./objects/Shared";
|
import Shared from "./objects/Shared";
|
||||||
import { User } from "./objects/User";
|
import User from "./objects/User";
|
||||||
import { osu } from "../osuTyping";
|
import osu from "../osuTyping";
|
||||||
|
|
||||||
export class SpectatorManager {
|
export default class SpectatorManager {
|
||||||
private shared:Shared;
|
private shared:Shared;
|
||||||
|
|
||||||
public constructor(shared:Shared) {
|
public constructor(shared:Shared) {
|
||||||
|
|
|
@ -12,10 +12,6 @@ export function generateSession() : Promise<string> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateSessionSync() : string {
|
|
||||||
return randomBytes(12).toString("hex");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function hexlify(data:Buffer) : string {
|
export function hexlify(data:Buffer) : string {
|
||||||
let out:string = "";
|
let out:string = "";
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { ICommand } from "../interfaces/ICommand";
|
import ICommand from "../interfaces/ICommand";
|
||||||
import { Channel } from "../objects/Channel";
|
import Channel from "../objects/Channel";
|
||||||
import { Shared } from "../objects/Shared";
|
import Shared from "../objects/Shared";
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
|
|
||||||
export class BaseCommand implements ICommand {
|
export default class BaseCommand implements ICommand {
|
||||||
public shared:Shared;
|
public shared:Shared;
|
||||||
public readonly helpText:string = "No help page was found for that command";
|
public readonly helpText:string = "No help page was found for that command";
|
||||||
public readonly helpDescription:string = "Command has no description set";
|
public readonly helpDescription:string = "Command has no description set";
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Channel } from "../objects/Channel";
|
import Channel from "../objects/Channel";
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
import { BaseCommand } from "./BaseCommand";
|
import BaseCommand from "./BaseCommand";
|
||||||
import { Shared } from "../objects/Shared";
|
import Shared from "../objects/Shared";
|
||||||
import { ICommand } from "../interfaces/ICommand";
|
import ICommand from "../interfaces/ICommand";
|
||||||
|
|
||||||
export class HelpCommand extends BaseCommand {
|
export default class HelpCommand extends BaseCommand {
|
||||||
public readonly helpDescription:string = "Shows this message! :)";
|
public readonly helpDescription:string = "Shows this message! :)";
|
||||||
|
|
||||||
private readonly commandList:{ [id:string]: ICommand };
|
private readonly commandList:{ [id:string]: ICommand };
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { Channel } from "../objects/Channel";
|
import Channel from "../objects/Channel";
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
import { BaseCommand } from "./BaseCommand";
|
import BaseCommand from "./BaseCommand";
|
||||||
|
|
||||||
export class LockCommand extends BaseCommand {
|
export default class LockCommand extends BaseCommand {
|
||||||
public readonly helpDescription:string = "Locks/Unlocks a channel and limits conversation to mods and above.";
|
public readonly helpDescription:string = "Locks/Unlocks a channel and limits conversation to mods and above.";
|
||||||
|
|
||||||
public exec(channel:Channel, sender:User, args:Array<string>) {
|
public exec(channel:Channel, sender:User, args:Array<string>) {
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
import { Channel } from "../objects/Channel";
|
import Channel from "../objects/Channel";
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
import { Match } from "../objects/Match";
|
import Match from "../objects/Match";
|
||||||
import { BaseCommand } from "./BaseCommand";
|
import BaseCommand from "./BaseCommand";
|
||||||
|
|
||||||
const helpText = `Multiplayer Subcommands:
|
export default class MultiplayerCommands extends BaseCommand {
|
||||||
|
public readonly helpText:string = `Multiplayer Subcommands:
|
||||||
!mp start - Starts a multiplayer match with a delay (optional)
|
!mp start - Starts a multiplayer match with a delay (optional)
|
||||||
!mp abort - Aborts the currently running round / countdown
|
!mp abort - Aborts the currently running round / countdown
|
||||||
!mp obr - Toggles Battle Royale mode`;
|
!mp obr - Toggles Battle Royale mode`;
|
||||||
|
|
||||||
export class MultiplayerCommands extends BaseCommand {
|
|
||||||
public readonly helpText:string = helpText;
|
|
||||||
public readonly helpDescription:string = "Command for use in multiplayer matches.";
|
public readonly helpDescription:string = "Command for use in multiplayer matches.";
|
||||||
public readonly helpArguments:Array<string> = ["subCommand"];
|
public readonly helpArguments:Array<string> = ["subCommand"];
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
import { Channel } from "../objects/Channel";
|
import Channel from "../objects/Channel";
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
import { RankingModes } from "../enums/RankingModes";
|
import { RankingModes } from "../enums/RankingModes";
|
||||||
import { BaseCommand } from "./BaseCommand";
|
import BaseCommand from "./BaseCommand";
|
||||||
|
|
||||||
const helpText = `Ranking Modes:
|
export default class RankingCommand extends BaseCommand {
|
||||||
|
public readonly helpText:string = `Ranking Modes:
|
||||||
!ranking pp - Sets your ranking mode to pp
|
!ranking pp - Sets your ranking mode to pp
|
||||||
!ranking score - Sets your ranking mode to score
|
!ranking score - Sets your ranking mode to score
|
||||||
!ranking acc - Sets your ranking mode to accuracy`;
|
!ranking acc - Sets your ranking mode to accuracy`;
|
||||||
|
|
||||||
export class RankingCommand extends BaseCommand {
|
|
||||||
public readonly helpText:string = helpText;
|
|
||||||
public readonly helpDescription:string = "Sets your prefered ranking type";
|
public readonly helpDescription:string = "Sets your prefered ranking type";
|
||||||
|
|
||||||
public exec(channel:Channel, sender:User, args:Array<string>) {
|
public exec(channel:Channel, sender:User, args:Array<string>) {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { Channel } from "../objects/Channel";
|
import Channel from "../objects/Channel";
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
import { BaseCommand } from "./BaseCommand";
|
import BaseCommand from "./BaseCommand";
|
||||||
|
|
||||||
export class RollCommand extends BaseCommand {
|
export default class RollCommand extends BaseCommand {
|
||||||
public readonly helpDescription:string = "Roll some dice and get a random number between 1 and a number (default 100)";
|
public readonly helpDescription:string = "Roll some dice and get a random number between 1 and a number (default 100)";
|
||||||
public readonly helpArguments:Array<string> = ["number"];
|
public readonly helpArguments:Array<string> = ["number"];
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
export interface Config {
|
export default interface Config {
|
||||||
express:ExpressConfigSection,
|
http:HttpConfigSection,
|
||||||
prometheus:PrometheusConfigSection,
|
prometheus:PrometheusConfigSection,
|
||||||
redis:RedisConfigSection,
|
redis:RedisConfigSection,
|
||||||
database:DatabaseConfigSection
|
database:DatabaseConfigSection
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ExpressConfigSection {
|
interface HttpConfigSection {
|
||||||
port:number,
|
port:number,
|
||||||
compression:boolean
|
compression:boolean
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { Channel } from "../objects/Channel";
|
import Channel from "../objects/Channel";
|
||||||
import { Shared } from "../objects/Shared";
|
import Shared from "../objects/Shared";
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
|
|
||||||
export interface ICommand {
|
export default interface ICommand {
|
||||||
shared:Shared,
|
shared:Shared,
|
||||||
helpText:string,
|
helpText:string,
|
||||||
helpDescription:string,
|
helpDescription:string,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export interface IpZxqResponse {
|
export default interface IpZxqResponse {
|
||||||
country: string,
|
country: string,
|
||||||
loc: string
|
loc: string
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { MatchDataSlot } from "./MatchDataSlot";
|
import MatchDataSlot from "./MatchDataSlot";
|
||||||
|
|
||||||
export interface MatchData {
|
export default interface MatchData {
|
||||||
matchId:number,
|
matchId:number,
|
||||||
matchType:number,
|
matchType:number,
|
||||||
activeMods:number,
|
activeMods:number,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export interface MatchDataSlot {
|
export default interface MatchDataSlot {
|
||||||
status:number,
|
status:number,
|
||||||
team:number,
|
team:number,
|
||||||
playerId:number,
|
playerId:number,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export interface MatchJoinData {
|
export default interface MatchJoinData {
|
||||||
matchId: number,
|
matchId: number,
|
||||||
gamePassword: string
|
gamePassword: string
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
export interface MatchScoreData {
|
export default interface MatchScoreData {
|
||||||
time:number,
|
time:number,
|
||||||
id:number,
|
id:number,
|
||||||
count300:number,
|
count300:number,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export interface MatchStartSkipData {
|
export default interface MatchStartSkipData {
|
||||||
playerId:number,
|
playerId:number,
|
||||||
flag:boolean
|
flag:boolean
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
export interface MessageData {
|
export default interface MessageData {
|
||||||
sendingClient: string,
|
sendingClient: string,
|
||||||
message: string,
|
message: string,
|
||||||
target: string,
|
target: string,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { MatchData } from "./MatchData"
|
import MatchData from "./MatchData"
|
||||||
import { MessageData } from "./MessageData"
|
import MessageData from "./MessageData"
|
||||||
|
|
||||||
export interface OsuPacketWriter {
|
export default interface OsuPacketWriter {
|
||||||
// Functions
|
// Functions
|
||||||
LoginReply(data:number) : OsuPacketWriter,
|
LoginReply(data:number) : OsuPacketWriter,
|
||||||
CommandError() : OsuPacketWriter,
|
CommandError() : OsuPacketWriter,
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { Slot } from "../objects/Slot";
|
import Slot from "../objects/Slot";
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
import { MatchScoreData } from "./MatchScoreData";
|
import MatchScoreData from "./MatchScoreData";
|
||||||
|
|
||||||
export interface PlayerScore {
|
export default interface PlayerScore {
|
||||||
player:User,
|
player:User,
|
||||||
slot:Slot,
|
slot:Slot,
|
||||||
score:number,
|
score:number,
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import { osu } from "../../osuTyping";
|
import osu from "../../osuTyping";
|
||||||
import { Bot } from "../Bot";
|
import Bot from "../Bot";
|
||||||
import { Shared } from "../objects/Shared";
|
import ChatHistory from "../ChatHistory";
|
||||||
import { DataStream } from "./DataStream";
|
import Shared from "../objects/Shared";
|
||||||
import { User } from "./User";
|
import DataStream from "./DataStream";
|
||||||
|
import User from "./User";
|
||||||
|
|
||||||
export class Channel {
|
export default class Channel {
|
||||||
public name:string;
|
public name:string;
|
||||||
public description:string;
|
public description:string;
|
||||||
public stream:DataStream;
|
public stream:DataStream;
|
||||||
|
@ -40,6 +41,9 @@ export class Channel {
|
||||||
senderId: sender.id
|
senderId: sender.id
|
||||||
});
|
});
|
||||||
this.stream.SendWithExclusion(osuPacketWriter.toBuffer, sender);
|
this.stream.SendWithExclusion(osuPacketWriter.toBuffer, sender);
|
||||||
|
if (this.name === "#osu") {
|
||||||
|
ChatHistory.AddMessage(`${sender.username}: ${message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message[0] === "!") {
|
if (message[0] === "!") {
|
||||||
|
@ -63,6 +67,10 @@ export class Channel {
|
||||||
} else {
|
} else {
|
||||||
this.stream.Send(osuPacketWriter.toBuffer);
|
this.stream.Send(osuPacketWriter.toBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.name === "#osu") {
|
||||||
|
ChatHistory.AddMessage(`${this.bot.user.username}: ${message}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SendSystemMessage(message:string, sendTo?:User) {
|
public SendSystemMessage(message:string, sendTo?:User) {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { ConsoleHelper } from "../../ConsoleHelper";
|
import { ConsoleHelper } from "../../ConsoleHelper";
|
||||||
import { Constants } from "../../Constants";
|
import Constants from "../../Constants";
|
||||||
import { DataStreamArray } from "./DataStreamArray";
|
import DataStreamArray from "./DataStreamArray";
|
||||||
import { User } from "./User";
|
import User from "./User";
|
||||||
import { UserArray } from "./UserArray";
|
import UserArray from "./UserArray";
|
||||||
import { hexlify } from "../Util";
|
import { hexlify } from "../Util";
|
||||||
|
|
||||||
type DeleteFunction = (dataStream:DataStream) => void;
|
type DeleteFunction = (dataStream:DataStream) => void;
|
||||||
|
|
||||||
export class DataStream {
|
export default class DataStream {
|
||||||
private users:UserArray = new UserArray();
|
private users:UserArray = new UserArray();
|
||||||
public readonly name:string;
|
public readonly name:string;
|
||||||
private readonly parent:DataStreamArray;
|
private readonly parent:DataStreamArray;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { ConsoleHelper } from "../../ConsoleHelper";
|
import { ConsoleHelper } from "../../ConsoleHelper";
|
||||||
import { DataStream } from "./DataStream";
|
import DataStream from "./DataStream";
|
||||||
import { FunkyArray } from "./FunkyArray";
|
import FunkyArray from "./FunkyArray";
|
||||||
import { User } from "./User";
|
import User from "./User";
|
||||||
|
|
||||||
export class DataStreamArray extends FunkyArray<DataStream> {
|
export default class DataStreamArray extends FunkyArray<DataStream> {
|
||||||
public CreateStream(name:string, removeWhenEmpty:boolean = true) : DataStream {
|
public CreateStream(name:string, removeWhenEmpty:boolean = true) : DataStream {
|
||||||
const dataStream:DataStream = this.add(name, new DataStream(name, this, removeWhenEmpty));
|
const dataStream:DataStream = this.add(name, new DataStream(name, this, removeWhenEmpty));
|
||||||
ConsoleHelper.printStream(`Created stream [${name}]`);
|
ConsoleHelper.printStream(`Created stream [${name}]`);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { ConsoleHelper } from "../../ConsoleHelper";
|
import { ConsoleHelper } from "../../ConsoleHelper";
|
||||||
import { createPool, Pool } from "mysql2";
|
import { createPool, Pool } from "mysql2";
|
||||||
|
|
||||||
export class Database {
|
export default class Database {
|
||||||
private connectionPool:Pool;
|
private connectionPool:Pool;
|
||||||
private static readonly CONNECTION_LIMIT = 128;
|
private static readonly CONNECTION_LIMIT = 128;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export class FunkyArray<T> {
|
export default class FunkyArray<T> {
|
||||||
private items:any = {};
|
private items:any = {};
|
||||||
private itemKeys:Array<string> = Object.keys(this.items);
|
private itemKeys:Array<string> = Object.keys(this.items);
|
||||||
private iterableArray:Array<T> = new Array<T>();
|
private iterableArray:Array<T> = new Array<T>();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export class LatLng {
|
export default class LatLng {
|
||||||
public latitude:number;
|
public latitude:number;
|
||||||
public longitude:number;
|
public longitude:number;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export class LoginInfo {
|
export default class LoginInfo {
|
||||||
public username:string;
|
public username:string;
|
||||||
public password:string;
|
public password:string;
|
||||||
public version:string;
|
public version:string;
|
||||||
|
@ -19,8 +19,6 @@ export class LoginInfo {
|
||||||
data = data.toString();
|
data = data.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
const loginData:Array<string> = data.split("\n");
|
const loginData:Array<string> = data.split("\n");
|
||||||
const extraData:Array<string> = loginData[2].split("|");
|
const extraData:Array<string> = loginData[2].split("|");
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import { Channel } from "./Channel";
|
import Channel from "./Channel";
|
||||||
import { Shared } from "../objects/Shared";
|
import Shared from "../objects/Shared";
|
||||||
import { DataStream } from "./DataStream";
|
import DataStream from "./DataStream";
|
||||||
import { Slot } from "./Slot";
|
import Slot from "./Slot";
|
||||||
import { User } from "./User";
|
import User from "./User";
|
||||||
import { StatusUpdate } from "../packets/StatusUpdate";
|
import StatusUpdate from "../packets/StatusUpdate";
|
||||||
import { SlotStatus } from "../enums/SlotStatus";
|
import { SlotStatus } from "../enums/SlotStatus";
|
||||||
import { MatchData } from "../interfaces/MatchData";
|
import MatchData from "../interfaces/MatchData";
|
||||||
import { Team } from "../enums/Team";
|
import { Team } from "../enums/Team";
|
||||||
import { MatchStartSkipData } from "../interfaces/MatchStartSkipData";
|
import MatchStartSkipData from "../interfaces/MatchStartSkipData";
|
||||||
import { Mods } from "../enums/Mods";
|
import { Mods } from "../enums/Mods";
|
||||||
import { PlayerScore } from "../interfaces/PlayerScore";
|
import PlayerScore from "../interfaces/PlayerScore";
|
||||||
import { MatchScoreData } from "../interfaces/MatchScoreData";
|
import MatchScoreData from "../interfaces/MatchScoreData";
|
||||||
import { osu } from "../../osuTyping";
|
import osu from "../../osuTyping";
|
||||||
|
|
||||||
export class Match {
|
export default class Match {
|
||||||
// osu! Data
|
// osu! Data
|
||||||
public matchId:number = -1;
|
public matchId:number = -1;
|
||||||
public inProgress:boolean = false;
|
public inProgress:boolean = false;
|
||||||
|
@ -236,8 +236,6 @@ export class Match {
|
||||||
|
|
||||||
// Update all users in the match with new match information
|
// Update all users in the match with new match information
|
||||||
this.matchStream.Send(osuPacketWriter.toBuffer);
|
this.matchStream.Send(osuPacketWriter.toBuffer);
|
||||||
|
|
||||||
console.log(this.slots);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public moveToSlot(user:User, slotToMoveTo:number) {
|
public moveToSlot(user:User, slotToMoveTo:number) {
|
||||||
|
@ -448,7 +446,6 @@ export class Match {
|
||||||
|
|
||||||
this.matchLoadSlots = new Array<MatchStartSkipData>();
|
this.matchLoadSlots = new Array<MatchStartSkipData>();
|
||||||
// Loop through all slots in the match
|
// Loop through all slots in the match
|
||||||
console.log(this.slots);
|
|
||||||
for (let slot of this.slots) {
|
for (let slot of this.slots) {
|
||||||
// Make sure the slot has a user in it
|
// Make sure the slot has a user in it
|
||||||
if (slot.player === undefined || slot.status === SlotStatus.Empty || slot.status === SlotStatus.Locked) {
|
if (slot.player === undefined || slot.status === SlotStatus.Empty || slot.status === SlotStatus.Locked) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { FunkyArray } from "./FunkyArray";
|
import FunkyArray from "./FunkyArray";
|
||||||
import { Match } from "./Match";
|
import Match from "./Match";
|
||||||
|
|
||||||
export class MatchArray extends FunkyArray<Match> {
|
export default class MatchArray extends FunkyArray<Match> {
|
||||||
public getById(id:number) : Match | undefined {
|
public getById(id:number) : Match | undefined {
|
||||||
for (let match of this.getIterableItems()) {
|
for (let match of this.getIterableItems()) {
|
||||||
if (match.matchId === id) {
|
if (match.matchId === id) {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { osu } from "../../osuTyping";
|
import osu from "../../osuTyping";
|
||||||
import { Shared } from "../objects/Shared";
|
import Shared from "../objects/Shared";
|
||||||
import { Channel } from "./Channel";
|
import Channel from "./Channel";
|
||||||
import { DataStream } from "./DataStream";
|
import DataStream from "./DataStream";
|
||||||
import { User } from "./User";
|
import User from "./User";
|
||||||
|
|
||||||
export class PrivateChannel extends Channel {
|
export default class PrivateChannel extends Channel {
|
||||||
private readonly user0:User;
|
private readonly user0:User;
|
||||||
private readonly user1:User;
|
private readonly user1:User;
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { ChatManager } from "../ChatManager";
|
import ChatManager from "../ChatManager";
|
||||||
import { Config } from "../interfaces/Config";
|
import Config from "../interfaces/Config";
|
||||||
import { Database } from "../objects/Database";
|
import Database from "../objects/Database";
|
||||||
import { DataStreamArray } from "../objects/DataStreamArray";
|
import DataStreamArray from "../objects/DataStreamArray";
|
||||||
import { MultiplayerManager } from "../MultiplayerManager";
|
import MultiplayerManager from "../MultiplayerManager";
|
||||||
import { PrivateChatManager } from "../PrivateChatManager";
|
import PrivateChatManager from "../PrivateChatManager";
|
||||||
import { readFileSync } from "fs";
|
import { readFileSync } from "fs";
|
||||||
import { UserArray } from "../objects/UserArray";
|
import UserArray from "../objects/UserArray";
|
||||||
import { User } from "./User";
|
import User from "./User";
|
||||||
import { LatLng } from "./LatLng";
|
import LatLng from "./LatLng";
|
||||||
import { Bot } from "../Bot";
|
import Bot from "../Bot";
|
||||||
|
|
||||||
export class Shared {
|
export default class Shared {
|
||||||
public readonly chatManager:ChatManager;
|
public readonly chatManager:ChatManager;
|
||||||
public readonly config:Config;
|
public readonly config:Config;
|
||||||
public readonly database:Database;
|
public readonly database:Database;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { Mods } from "../enums/Mods";
|
import { Mods } from "../enums/Mods";
|
||||||
import { SlotStatus } from "../enums/SlotStatus";
|
import { SlotStatus } from "../enums/SlotStatus";
|
||||||
import { User } from "./User";
|
import User from "./User";
|
||||||
|
|
||||||
export class Slot {
|
export default class Slot {
|
||||||
public readonly slotId:number;
|
public readonly slotId:number;
|
||||||
public status:SlotStatus;
|
public status:SlotStatus;
|
||||||
public team:number;
|
public team:number;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { LatLng } from "./LatLng";
|
import LatLng from "./LatLng";
|
||||||
import { RankingModes } from "../enums/RankingModes";
|
import { RankingModes } from "../enums/RankingModes";
|
||||||
import { Match } from "./Match";
|
import Match from "./Match";
|
||||||
import { DataStream } from "./DataStream";
|
import DataStream from "./DataStream";
|
||||||
import { StatusUpdate } from "../packets/StatusUpdate";
|
import StatusUpdate from "../packets/StatusUpdate";
|
||||||
import { Shared } from "../objects/Shared";
|
import Shared from "../objects/Shared";
|
||||||
import { Slot } from "./Slot";
|
import Slot from "./Slot";
|
||||||
|
|
||||||
const rankingModes = [
|
const rankingModes = [
|
||||||
"pp_raw",
|
"pp_raw",
|
||||||
|
@ -12,7 +12,7 @@ const rankingModes = [
|
||||||
"avg_accuracy"
|
"avg_accuracy"
|
||||||
];
|
];
|
||||||
|
|
||||||
export class User {
|
export default class User {
|
||||||
private static readonly EMPTY_BUFFER = Buffer.alloc(0);
|
private static readonly EMPTY_BUFFER = Buffer.alloc(0);
|
||||||
|
|
||||||
public shared:Shared;
|
public shared:Shared;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { FunkyArray } from "./FunkyArray";
|
import FunkyArray from "./FunkyArray";
|
||||||
import { User } from "./User";
|
import User from "./User";
|
||||||
|
|
||||||
export class UserArray extends FunkyArray<User> {
|
export default class UserArray extends FunkyArray<User> {
|
||||||
public getById(id:number) : User | undefined {
|
public getById(id:number) : User | undefined {
|
||||||
for (let user of this.getIterableItems()) {
|
for (let user of this.getIterableItems()) {
|
||||||
if (user.id == id)
|
if (user.id == id)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export class UserInfo {
|
export default class UserInfo {
|
||||||
id:number = Number.MIN_VALUE;
|
id:number = Number.MIN_VALUE;
|
||||||
username:string = "";
|
username:string = "";
|
||||||
username_safe:string = "";
|
username_safe:string = "";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
|
|
||||||
export function AddFriend(user:User, friendId:number) {
|
export default function AddFriend(user:User, friendId:number) {
|
||||||
user.shared.database.query("INSERT INTO friends (user, friendsWith) VALUES (?, ?)", [
|
user.shared.database.query("INSERT INTO friends (user, friendsWith) VALUES (?, ?)", [
|
||||||
user.id, friendId
|
user.id, friendId
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
import { StatusUpdate } from "./StatusUpdate";
|
import StatusUpdate from "./StatusUpdate";
|
||||||
|
|
||||||
export function ChangeAction(user:User, data:any) {
|
export default function ChangeAction(user:User, data:any) {
|
||||||
user.updatePresence(data);
|
user.updatePresence(data);
|
||||||
|
|
||||||
if (user.spectatorStream != null) {
|
if (user.spectatorStream != null) {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { ConsoleHelper } from "../../ConsoleHelper";
|
import { ConsoleHelper } from "../../ConsoleHelper";
|
||||||
import { Database } from "../objects/Database";
|
import Database from "../objects/Database";
|
||||||
import { DataStreamArray } from "../objects/DataStreamArray";
|
import DataStreamArray from "../objects/DataStreamArray";
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
|
|
||||||
export async function Logout(user:User) {
|
export default async function Logout(user:User) {
|
||||||
if (user.uuid === "bot") throw "Tried to log bot out, WTF???";
|
if (user.uuid === "bot") throw "Tried to log bot out, WTF???";
|
||||||
|
|
||||||
const logoutStartTime = Date.now();
|
const logoutStartTime = Date.now();
|
||||||
|
|
|
@ -1,27 +1,23 @@
|
||||||
import { MessageData } from "../interfaces/MessageData";
|
import MessageData from "../interfaces/MessageData";
|
||||||
import { Shared } from "../objects/Shared";
|
import Shared from "../objects/Shared";
|
||||||
import { PrivateChannel } from "../objects/PrivateChannel";
|
import PrivateChannel from "../objects/PrivateChannel";
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
|
|
||||||
export function PrivateMessage(user:User, message:MessageData) {
|
export default function PrivateMessage(user:User, message:MessageData) {
|
||||||
const shared:Shared = user.shared;
|
const shared:Shared = user.shared;
|
||||||
const sendingTo = shared.users.getByUsername(message.target);
|
const sendingTo = shared.users.getByUsername(message.target);
|
||||||
if (!(sendingTo instanceof User)) {
|
if (!(sendingTo instanceof User)) {
|
||||||
console.log("Sending User invalid");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let channel = shared.privateChatManager.GetChannelByName(`${user.username}${sendingTo.username}`);
|
let channel = shared.privateChatManager.GetChannelByName(`${user.username}${sendingTo.username}`);
|
||||||
if (!(channel instanceof PrivateChannel)) {
|
if (!(channel instanceof PrivateChannel)) {
|
||||||
console.log("First find failed");
|
|
||||||
// Try it the other way around
|
// Try it the other way around
|
||||||
channel = shared.privateChatManager.GetChannelByName(`${sendingTo.username}${user.username}`);
|
channel = shared.privateChatManager.GetChannelByName(`${sendingTo.username}${user.username}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(channel instanceof PrivateChannel)) {
|
if (!(channel instanceof PrivateChannel)) {
|
||||||
console.log("Second find failed, creating");
|
|
||||||
channel = shared.privateChatManager.AddChannel(user, sendingTo);
|
channel = shared.privateChatManager.AddChannel(user, sendingTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("sending");
|
|
||||||
channel.SendMessage(user, message.message);
|
channel.SendMessage(user, message.message);
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
|
|
||||||
export function RemoveFriend(user:User, friendId:number) {
|
export default function RemoveFriend(user:User, friendId:number) {
|
||||||
user.shared.database.query("DELETE FROM friends WHERE user = ? AND friendsWith = ? LIMIT 1", [
|
user.shared.database.query("DELETE FROM friends WHERE user = ? AND friendsWith = ? LIMIT 1", [
|
||||||
user.id, friendId
|
user.id, friendId
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { Shared } from "../objects/Shared";
|
import Shared from "../objects/Shared";
|
||||||
import { RankingModes } from "../enums/RankingModes";
|
import { RankingModes } from "../enums/RankingModes";
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
import { osu } from "../../osuTyping";
|
import osu from "../../osuTyping";
|
||||||
|
|
||||||
export function StatusUpdate(arg0:User | Shared, id:number) {
|
export default function StatusUpdate(arg0:User | Shared, id:number) {
|
||||||
if (id == 3) return; // Ignore Bot
|
if (id == 3) return; // Ignore Bot
|
||||||
|
|
||||||
// Create new osu packet writer
|
// Create new osu packet writer
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { osu } from "../../osuTyping";
|
import osu from "../../osuTyping";
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
|
|
||||||
export function TourneyMatchJoinChannel(user:User, matchId:number) {
|
export default function TourneyMatchJoinChannel(user:User, matchId:number) {
|
||||||
const match = user.shared.multiplayerManager.GetMatchById(matchId);
|
const match = user.shared.multiplayerManager.GetMatchById(matchId);
|
||||||
if (match === undefined) {
|
if (match === undefined) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
|
|
||||||
export function TourneyMatchLeaveChannel(user:User, matchId:number) {
|
export default function TourneyMatchLeaveChannel(user:User, matchId:number) {
|
||||||
const match = user.shared.multiplayerManager.GetMatchById(matchId);
|
const match = user.shared.multiplayerManager.GetMatchById(matchId);
|
||||||
if (match === undefined) {
|
if (match === undefined) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { osu } from "../../osuTyping";
|
import osu from "../../osuTyping";
|
||||||
import { Match } from "../objects/Match";
|
import Match from "../objects/Match";
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
import { StatusUpdate } from "./StatusUpdate";
|
import StatusUpdate from "./StatusUpdate";
|
||||||
import { UserPresence } from "./UserPresence";
|
import UserPresence from "./UserPresence";
|
||||||
|
|
||||||
export function TourneyMatchSpecialInfo(user:User, matchId:number) {
|
export default function TourneyMatchSpecialInfo(user:User, matchId:number) {
|
||||||
const match = user.shared.multiplayerManager.GetMatchById(matchId);
|
const match = user.shared.multiplayerManager.GetMatchById(matchId);
|
||||||
if (!(match instanceof Match)) {
|
if (!(match instanceof Match)) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { osu } from "../../osuTyping";
|
import osu from "../../osuTyping";
|
||||||
import { Shared } from "../objects/Shared";
|
import Shared from "../objects/Shared";
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
|
|
||||||
export function UserPresence(arg0:User | Shared, id:number) {
|
export default function UserPresence(arg0:User | Shared, id:number) {
|
||||||
const osuPacketWriter = osu.Bancho.Writer();
|
const osuPacketWriter = osu.Bancho.Writer();
|
||||||
let shared:Shared;
|
let shared:Shared;
|
||||||
if (arg0 instanceof User) {
|
if (arg0 instanceof User) {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { osu } from "../../osuTyping";
|
import osu from "../../osuTyping";
|
||||||
import { Shared } from "../objects/Shared";
|
import Shared from "../objects/Shared";
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
|
|
||||||
export function UserPresenceBundle(arg0:User | Shared) : Buffer {
|
export default function UserPresenceBundle(arg0:User | Shared) : Buffer {
|
||||||
const osuPacketWriter = osu.Bancho.Writer();
|
const osuPacketWriter = osu.Bancho.Writer();
|
||||||
let shared:Shared;
|
let shared:Shared;
|
||||||
if (arg0 instanceof User) {
|
if (arg0 instanceof User) {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { User } from "../objects/User";
|
import User from "../objects/User";
|
||||||
import { StatusUpdate } from "./StatusUpdate";
|
import StatusUpdate from "./StatusUpdate";
|
||||||
import { UserPresence } from "./UserPresence";
|
import UserPresence from "./UserPresence";
|
||||||
import { UserPresenceBundle } from "./UserPresenceBundle";
|
import UserPresenceBundle from "./UserPresenceBundle";
|
||||||
|
|
||||||
export function UserStatsRequest(user:User, data:Array<number>) {
|
export default function UserStatsRequest(user:User, data:Array<number>) {
|
||||||
UserPresenceBundle(user);
|
UserPresenceBundle(user);
|
||||||
|
|
||||||
for (let id of data) {
|
for (let id of data) {
|
||||||
|
|
12
tooling/cleanup.ts
Normal file
12
tooling/cleanup.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { readdirSync, rmSync, renameSync } from "fs";
|
||||||
|
|
||||||
|
const libFiles = readdirSync("./build");
|
||||||
|
|
||||||
|
for (const file of libFiles) {
|
||||||
|
if (!file.startsWith("index.min.js")) {
|
||||||
|
rmSync(`./build/${file}`, { recursive: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//renameSync("./build/combined.js", "./build/index.js");
|
||||||
|
//renameSync("./build/combined.d.ts", "./build/index.d.ts");
|
67
tooling/fileSmasher.ts
Normal file
67
tooling/fileSmasher.ts
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
// fileSmasher ~.~
|
||||||
|
// for when you're just too lazy to
|
||||||
|
// do it properly.
|
||||||
|
|
||||||
|
import { readdirSync, lstatSync, readFileSync, writeFileSync } from "fs";
|
||||||
|
|
||||||
|
let tsFileData:Array<string> = new Array<string>();
|
||||||
|
const tsFirstFileData:Array<string> = new Array<string>();
|
||||||
|
const tsLastFileData:Array<string> = new Array<string>();
|
||||||
|
const tsEverythingElse:Array<string> = new Array<string>();
|
||||||
|
|
||||||
|
function readDir(nam:string) {
|
||||||
|
const files = readdirSync(nam);
|
||||||
|
for (const file of files) {
|
||||||
|
if (nam == "./" && (file.startsWith(".") || file == "tooling" || file == "build" || file == "node_modules" || file == "combined.ts")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a very dumb way of checking for folders
|
||||||
|
// protip: don't do this.
|
||||||
|
if (lstatSync(`${nam}/${file}`).isDirectory()) {
|
||||||
|
readDir(`${nam}/${file}`);
|
||||||
|
} else if (file.endsWith(".ts")) {
|
||||||
|
if (file == "Binato.ts") {
|
||||||
|
tsLastFileData.push(readFileSync((`${nam}/${file}`).replace("//", "/")).toString());
|
||||||
|
} else if (nam.includes("enum") || nam.includes("packets") || file.includes("FunkyArray") || file.includes("SpectatorManager") || file.includes("Shared")) {
|
||||||
|
tsFirstFileData.push(readFileSync((`${nam}/${file}`).replace("//", "/")).toString());
|
||||||
|
} else {
|
||||||
|
tsEverythingElse.push(readFileSync((`${nam}/${file}`).replace("//", "/")).toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readDir("./");
|
||||||
|
|
||||||
|
tsFileData = tsFileData.concat(tsFirstFileData).concat(tsEverythingElse).concat(tsLastFileData);
|
||||||
|
|
||||||
|
const combinedFiles = tsFileData.join("\n");
|
||||||
|
|
||||||
|
const splitLines = combinedFiles.split("\n");
|
||||||
|
const resultLines:Array<string> = new Array<string>();
|
||||||
|
|
||||||
|
// Insert allowed imports
|
||||||
|
resultLines.push(`import { IncomingMessage, ServerResponse } from "http";
|
||||||
|
import { Registry, collectDefaultMetrics } from "prom-client";
|
||||||
|
import { RedisClientType, createClient } from "redis";
|
||||||
|
import { readFileSync, existsSync } from "fs";
|
||||||
|
import { randomBytes, pbkdf2 } from "crypto";
|
||||||
|
import { createPool, Pool } from "mysql2";
|
||||||
|
import * as dyetty from "dyetty";
|
||||||
|
import fetch from "node-fetch";
|
||||||
|
import http from "http";`);
|
||||||
|
|
||||||
|
// Let's process the file to make it usable
|
||||||
|
for (const line of splitLines) {
|
||||||
|
// Throw away imports as they aren't needed
|
||||||
|
// TODO: Add allow list for npm module imports
|
||||||
|
if (line.startsWith("import")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Fix up classes, interfaces and such.
|
||||||
|
//resultLines.push(line);
|
||||||
|
resultLines.push(line.replace("export default", "").replace("export class", "class").replace("export interface", "interface").replace("export enum", "enum").replace("export type", "type"));
|
||||||
|
}
|
||||||
|
|
||||||
|
writeFileSync("./combined.ts", resultLines.join("\n"));
|
10
tooling/mangle.ts
Normal file
10
tooling/mangle.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { readFileSync, writeFileSync } from "fs";
|
||||||
|
import { minify } from "terser";
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const mangled = await minify(readFileSync("./build/combined.js").toString(), {
|
||||||
|
mangle: true,
|
||||||
|
toplevel: true,
|
||||||
|
});
|
||||||
|
writeFileSync("./build/index.min.js", `${mangled.code}`);
|
||||||
|
})();
|
Loading…
Reference in a new issue