fix everything
This commit is contained in:
parent
148c2c341f
commit
3a07a892e1
63 changed files with 431 additions and 1032 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,6 +1,6 @@
|
|||
node_modules/
|
||||
build/
|
||||
bundle/
|
||||
combined.ts
|
||||
tHMM.ds
|
||||
server-stats.log
|
||||
config.json
|
39
Binato.ts
39
Binato.ts
|
@ -8,65 +8,54 @@ if (!existsSync("./config.json")) {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
import { ChatHistory } from "./server/ChatHistory";
|
||||
import { Config } from "./server/interfaces/Config";
|
||||
import compression from "compression";
|
||||
import express from "express";
|
||||
import { HandleRequest } from "./server/BanchoServer";
|
||||
import { Shared } from "./server/objects/Shared";
|
||||
import ChatHistory from "./server/ChatHistory";
|
||||
import Config from "./server/interfaces/Config";
|
||||
import HandleRequest from "./server/BanchoServer";
|
||||
import { Registry, collectDefaultMetrics } from "prom-client";
|
||||
import http from "http";
|
||||
const config:Config = JSON.parse(readFileSync(__dirname + "/config.json").toString()) as Config;
|
||||
|
||||
const binatoApp:express.Application = express();
|
||||
|
||||
if (config["prometheus"]["enabled"]) {
|
||||
const register:Registry = new Registry();
|
||||
register.setDefaultLabels({ app: "nodejs_binato" });
|
||||
|
||||
collectDefaultMetrics({ register });
|
||||
|
||||
const prometheusApp:express.Application = express();
|
||||
prometheusApp.get("/metrics", async (req, res) => {
|
||||
const prometheusServer = http.createServer(async (req, res) => {
|
||||
if (req.method === "GET") {
|
||||
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 {
|
||||
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();
|
||||
|
||||
binatoApp.use((req, res) => {
|
||||
const binatoServer = http.createServer((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.send(INDEX_PAGE);
|
||||
res.end(INDEX_PAGE);
|
||||
} else if (req.url == "/chat") {
|
||||
// I don't think this works??
|
||||
res.send(ChatHistory.GenerateForWeb());
|
||||
res.end(ChatHistory.GenerateForWeb());
|
||||
}
|
||||
break;
|
||||
|
||||
case "POST":
|
||||
HandleRequest(req, res, packet);
|
||||
break;
|
||||
|
||||
default:
|
||||
res.status(405).send("405 | Method not allowed!<hr>Binato");
|
||||
res.writeHead(405);
|
||||
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 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");
|
||||
|
||||
export abstract class osu {
|
||||
export default abstract class osu {
|
||||
static Bancho = {
|
||||
Writer: function() : OsuPacketWriter {
|
||||
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",
|
||||
"dependencies": {
|
||||
"aes256": "^1.1.0",
|
||||
"compression": "^1.7.4",
|
||||
"dyetty": "^1.0.1",
|
||||
"express": "^4.18.2",
|
||||
"mysql2": "^3.6.0",
|
||||
"node-fetch": "^2.6.13",
|
||||
"mysql2": "^3.6.1",
|
||||
"node-fetch": "^2.7.0",
|
||||
"osu-packet": "^4.1.2",
|
||||
"prom-client": "^14.2.0",
|
||||
"redis": "^4.6.7"
|
||||
"redis": "^4.6.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/compression": "^1.7.2",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/node": "^20.5.1",
|
||||
"@types/node": "^20.6.0",
|
||||
"@types/node-fetch": "^2.6.4",
|
||||
"check-outdated": "^2.12.0",
|
||||
"nodemon": "^3.0.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"ts-loader": "^9.4.4",
|
||||
"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 { Channel } from "./objects/Channel";
|
||||
import { LatLng } from "./objects/LatLng";
|
||||
import { LoginProcess } from "./LoginProcess";
|
||||
import Constants from "../Constants";
|
||||
import LoginProcess from "./LoginProcess";
|
||||
import { IncomingMessage, ServerResponse } from "http";
|
||||
import { Packets } from "./enums/Packets";
|
||||
import { RedisClientType, createClient } from "redis";
|
||||
import { Request, Response } from "express";
|
||||
import { SpectatorManager } from "./SpectatorManager";
|
||||
import { User } from "./objects/User";
|
||||
import { PrivateMessage } from "./packets/PrivateMessage";
|
||||
import { MessageData } from "./interfaces/MessageData";
|
||||
import { Shared } from "./objects/Shared";
|
||||
import MessageData from "./interfaces/MessageData";
|
||||
import PrivateMessage from "./packets/PrivateMessage";
|
||||
import Shared from "./objects/Shared";
|
||||
import SpectatorManager from "./SpectatorManager";
|
||||
import osu from "../osuTyping";
|
||||
|
||||
const shared:Shared = new Shared();
|
||||
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!");
|
||||
|
||||
// Import packets
|
||||
import { ChangeAction } from "./packets/ChangeAction";
|
||||
import { Logout } from "./packets/Logout";
|
||||
import { UserPresence } from "./packets/UserPresence";
|
||||
import { UserStatsRequest } from "./packets/UserStatsRequest";
|
||||
import { UserPresenceBundle } from "./packets/UserPresenceBundle";
|
||||
import { TourneyMatchSpecialInfo } from "./packets/TourneyMatchSpecialInfo";
|
||||
import { osu } from "../osuTyping";
|
||||
import { TourneyMatchJoinChannel } from "./packets/TourneyJoinMatchChannel";
|
||||
import { TourneyMatchLeaveChannel } from "./packets/TourneyMatchLeaveChannel";
|
||||
import { AddFriend } from "./packets/AddFriend";
|
||||
import { RemoveFriend } from "./packets/RemoveFriend";
|
||||
import { PrivateChannel } from "./objects/PrivateChannel";
|
||||
import { Constants } from "../Constants";
|
||||
import ChangeAction from "./packets/ChangeAction";
|
||||
import Logout from "./packets/Logout";
|
||||
import UserPresence from "./packets/UserPresence";
|
||||
import UserStatsRequest from "./packets/UserStatsRequest";
|
||||
import UserPresenceBundle from "./packets/UserPresenceBundle";
|
||||
import TourneyMatchSpecialInfo from "./packets/TourneyMatchSpecialInfo";
|
||||
import TourneyMatchJoinChannel from "./packets/TourneyJoinMatchChannel";
|
||||
import TourneyMatchLeaveChannel from "./packets/TourneyMatchLeaveChannel";
|
||||
import AddFriend from "./packets/AddFriend";
|
||||
import RemoveFriend from "./packets/RemoveFriend";
|
||||
import PrivateChannel from "./objects/PrivateChannel";
|
||||
|
||||
// User timeout interval
|
||||
setInterval(() => {
|
||||
|
@ -83,30 +81,23 @@ setInterval(() => {
|
|||
|
||||
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
|
||||
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
|
||||
if (requestTokenString == null) {
|
||||
// Only do this if we're absolutely sure that we're connected to the DB
|
||||
if (shared.database.connected) {
|
||||
if (requestTokenString === undefined) {
|
||||
// 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]);
|
||||
}
|
||||
} else {
|
||||
let responseData:Buffer | string = EMPTY_BUFFER;
|
||||
|
||||
// Remove headers we don't need for Bancho
|
||||
res.removeHeader('X-Powered-By');
|
||||
res.removeHeader('Date'); // This is not spec compilant
|
||||
let responseData = EMPTY_BUFFER;
|
||||
|
||||
// Client has a token, let's see what they want.
|
||||
try {
|
||||
// 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
|
||||
if (PacketUser != null) {
|
||||
|
@ -298,12 +289,12 @@ export async function HandleRequest(req:Request, res:Response, packet:Buffer) {
|
|||
responseData = PacketUser.queue;
|
||||
PacketUser.clearQueue();
|
||||
} else {
|
||||
// Only do this if we're absolutely sure that we're connected to the DB
|
||||
if (shared.database.connected) {
|
||||
// User's token is invlid, force a reconnect
|
||||
ConsoleHelper.printBancho(`Forced client re-login (Token is invalid)`);
|
||||
responseData = "\u0005\u0000\u0000\u0004\u0000\u0000\u0000<30><30><EFBFBD><EFBFBD>\u0018\u0000\u0000\u0011\u0000\u0000\u0000\u000b\u000fReconnecting...";
|
||||
}
|
||||
const osuPacketWriter = osu.Bancho.Writer();
|
||||
osuPacketWriter.Announce("Reconnecting...");
|
||||
osuPacketWriter.Restart(0);
|
||||
responseData = osuPacketWriter.toBuffer;
|
||||
}
|
||||
} catch (e) {
|
||||
if (Constants.DEBUG) {
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import { ICommand } from "./interfaces/ICommand";
|
||||
import { Channel } from "./objects/Channel";
|
||||
import { Shared } from "./objects/Shared";
|
||||
import { User } from "./objects/User";
|
||||
import ICommand from "./interfaces/ICommand";
|
||||
import Channel from "./objects/Channel";
|
||||
import Shared from "./objects/Shared";
|
||||
import User from "./objects/User";
|
||||
|
||||
// Commands
|
||||
import { RankingCommand } from "./commands/Ranking";
|
||||
import { LockCommand } from "./commands/Lock";
|
||||
import { MultiplayerCommands } from "./commands/Multiplayer";
|
||||
import { HelpCommand } from "./commands/Help";
|
||||
import { RollCommand } from "./commands/RollCommand";
|
||||
import RankingCommand from "./commands/Ranking";
|
||||
import LockCommand from "./commands/Lock";
|
||||
import MultiplayerCommands from "./commands/Multiplayer";
|
||||
import HelpCommand from "./commands/Help";
|
||||
import RollCommand from "./commands/RollCommand";
|
||||
|
||||
export class Bot {
|
||||
export default class Bot {
|
||||
public user:User;
|
||||
private commands:{ [id: string]: ICommand } = {};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { readFileSync } from "fs";
|
||||
|
||||
export abstract class ChatHistory {
|
||||
export default abstract class ChatHistory {
|
||||
private static _history:Array<string> = new Array<string>();
|
||||
private static _lastGeneratedPage:string;
|
||||
private static _hasChanged:boolean = true;
|
||||
|
@ -8,7 +8,7 @@ export abstract class ChatHistory {
|
|||
private static readonly PAGE_TEMPLATE = readFileSync("./web/chatPageTemplate.html").toString();
|
||||
|
||||
public static AddMessage(message:string) : void {
|
||||
if (this._history.length === 10) {
|
||||
if (this._history.length === this.HISTORY_LENGTH) {
|
||||
this._history.splice(0, 1);
|
||||
}
|
||||
|
||||
|
@ -17,14 +17,14 @@ export abstract class ChatHistory {
|
|||
}
|
||||
|
||||
public static GenerateForWeb() : string {
|
||||
let lines:string = "", flip:boolean = false;
|
||||
if (this._hasChanged) {
|
||||
let lines = "", flip = 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>`
|
||||
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;
|
||||
}
|
||||
|
||||
if (this._hasChanged) {
|
||||
this._lastGeneratedPage = this.PAGE_TEMPLATE.toString().replace("|content|", lines);
|
||||
this._hasChanged = false;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { Channel } from "./objects/Channel";
|
||||
import Channel from "./objects/Channel";
|
||||
import { ConsoleHelper } from "../ConsoleHelper";
|
||||
import { FunkyArray } from "./objects/FunkyArray";
|
||||
import { User } from "./objects/User";
|
||||
import { Shared } from "./objects/Shared";
|
||||
import { osu } from "../osuTyping";
|
||||
import { PrivateChannel } from "./objects/PrivateChannel";
|
||||
import FunkyArray from "./objects/FunkyArray";
|
||||
import User from "./objects/User";
|
||||
import Shared from "./objects/Shared";
|
||||
import osu from "../osuTyping";
|
||||
import PrivateChannel from "./objects/PrivateChannel";
|
||||
|
||||
export class ChatManager {
|
||||
export default class ChatManager {
|
||||
public chatChannels:FunkyArray<Channel> = new FunkyArray<Channel>();
|
||||
public forceJoinChannels:FunkyArray<Channel> = new FunkyArray<Channel>();
|
||||
private readonly shared:Shared;
|
||||
|
|
|
@ -254,7 +254,7 @@ enum CountryCodes {
|
|||
const keys = Object.keys(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
|
||||
const upperCode:string = code.toUpperCase();
|
||||
if (upperCode in CountryCodes) {
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import { ConsoleHelper } from "../ConsoleHelper";
|
||||
import fetch from "node-fetch";
|
||||
import { getCountryID } from "./Country";
|
||||
import getCountryID from "./Country";
|
||||
import { generateSession } from "./Util";
|
||||
import { LatLng } from "./objects/LatLng";
|
||||
import { LoginInfo } from "./objects/LoginInfo";
|
||||
import { Logout } from "./packets/Logout";
|
||||
import LatLng from "./objects/LatLng";
|
||||
import LoginInfo from "./objects/LoginInfo";
|
||||
import Logout from "./packets/Logout";
|
||||
import { pbkdf2 } from "crypto";
|
||||
import { Request, Response } from "express";
|
||||
import { User } from "./objects/User";
|
||||
import { UserPresenceBundle } from "./packets/UserPresenceBundle";
|
||||
import { UserPresence } from "./packets/UserPresence";
|
||||
import { StatusUpdate } from "./packets/StatusUpdate";
|
||||
import { Shared } from "./objects/Shared";
|
||||
import { osu } from "../osuTyping";
|
||||
import { IpZxqResponse } from "./interfaces/IpZxqResponse";
|
||||
import User from "./objects/User";
|
||||
import UserPresenceBundle from "./packets/UserPresenceBundle";
|
||||
import UserPresence from "./packets/UserPresence";
|
||||
import StatusUpdate from "./packets/StatusUpdate";
|
||||
import Shared from "./objects/Shared";
|
||||
import osu from "../osuTyping";
|
||||
import IpZxqResponse from "./interfaces/IpZxqResponse";
|
||||
import { IncomingMessage, ServerResponse } from "http";
|
||||
const { decrypt: aesDecrypt } = require("aes256");
|
||||
|
||||
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
|
||||
if (userDBData.username !== loginInfo.username) return resolve(LoginResult.INCORRECT);
|
||||
|
||||
console.log(userDBData.has_old_password);
|
||||
switch (userDBData.has_old_password) {
|
||||
case LoginTypes.CURRENT:
|
||||
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;
|
||||
case LoginTypes.OLD_AES:
|
||||
console.log("OLD AES");
|
||||
if (aesDecrypt(shared.config.database.key, userDBData.password_hash) !== loginInfo.password) {
|
||||
return resolve(LoginResult.INCORRECT);
|
||||
}
|
||||
console.log("correct password");
|
||||
return resolve(LoginResult.MIGRATION);
|
||||
case LoginTypes.OLD_MD5:
|
||||
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 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 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
|
||||
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)
|
||||
|
@ -196,7 +193,7 @@ export async function LoginProcess(req:Request, res:Response, packet:Buffer, sha
|
|||
|
||||
osuPacketWriter.Announce(`Welcome back ${loginInfo.username}!`);
|
||||
// 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) {
|
||||
console.error(err);
|
||||
}
|
||||
|
@ -208,10 +205,10 @@ export async function LoginProcess(req:Request, res:Response, packet:Buffer, sha
|
|||
const writerBuffer:Buffer = osuPacketWriter.toBuffer;
|
||||
if (newUser === undefined) {
|
||||
res.writeHead(200, {
|
||||
"cho-token": "no",
|
||||
"Connection": "keep-alive",
|
||||
"Keep-Alive": "timeout=5, max=100"
|
||||
});
|
||||
console.log(res.headersSent);
|
||||
switch (loginResult) {
|
||||
case LoginResult.INCORRECT:
|
||||
res.end(incorrectLoginResponse, () => {
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import { Channel } from "./objects/Channel";
|
||||
import { Shared } from "./objects/Shared";
|
||||
import Channel from "./objects/Channel";
|
||||
import Shared from "./objects/Shared";
|
||||
import { SlotStatus } from "./enums/SlotStatus";
|
||||
import { DataStream } from "./objects/DataStream";
|
||||
import { Match } from "./objects/Match";
|
||||
import { User } from "./objects/User";
|
||||
import { StatusUpdate } from "./packets/StatusUpdate";
|
||||
import { UserPresence } from "./packets/UserPresence";
|
||||
import { UserPresenceBundle } from "./packets/UserPresenceBundle";
|
||||
import { MatchArray } from "./objects/MatchArray";
|
||||
import { MatchJoinData } from "./interfaces/MatchJoinData";
|
||||
import { MatchData } from "./interfaces/MatchData";
|
||||
import { osu } from "../osuTyping";
|
||||
import DataStream from "./objects/DataStream";
|
||||
import Match from "./objects/Match";
|
||||
import User from "./objects/User";
|
||||
import StatusUpdate from "./packets/StatusUpdate";
|
||||
import UserPresence from "./packets/UserPresence";
|
||||
import UserPresenceBundle from "./packets/UserPresenceBundle";
|
||||
import MatchArray from "./objects/MatchArray";
|
||||
import MatchJoinData from "./interfaces/MatchJoinData";
|
||||
import MatchData from "./interfaces/MatchData";
|
||||
import osu from "../osuTyping";
|
||||
|
||||
export class MultiplayerManager {
|
||||
export default class MultiplayerManager {
|
||||
private readonly shared:Shared;
|
||||
private matches:MatchArray = new MatchArray();
|
||||
private readonly lobbyStream:DataStream;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { Channel } from "./objects/Channel";
|
||||
import Channel from "./objects/Channel";
|
||||
import { ConsoleHelper } from "../ConsoleHelper";
|
||||
import { FunkyArray } from "./objects/FunkyArray";
|
||||
import { User } from "./objects/User";
|
||||
import { Shared } from "./objects/Shared";
|
||||
import { osu } from "../osuTyping";
|
||||
import { PrivateChannel } from "./objects/PrivateChannel";
|
||||
import FunkyArray from "./objects/FunkyArray";
|
||||
import User from "./objects/User";
|
||||
import Shared from "./objects/Shared";
|
||||
import osu from "../osuTyping";
|
||||
import PrivateChannel from "./objects/PrivateChannel";
|
||||
|
||||
export class PrivateChatManager {
|
||||
export default class PrivateChatManager {
|
||||
public chatChannels:FunkyArray<PrivateChannel> = new FunkyArray<PrivateChannel>();
|
||||
private readonly shared:Shared;
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { DataStream } from "./objects/DataStream";
|
||||
import { Shared } from "./objects/Shared";
|
||||
import { User } from "./objects/User";
|
||||
import { osu } from "../osuTyping";
|
||||
import DataStream from "./objects/DataStream";
|
||||
import Shared from "./objects/Shared";
|
||||
import User from "./objects/User";
|
||||
import osu from "../osuTyping";
|
||||
|
||||
export class SpectatorManager {
|
||||
export default class SpectatorManager {
|
||||
private 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 {
|
||||
let out:string = "";
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { ICommand } from "../interfaces/ICommand";
|
||||
import { Channel } from "../objects/Channel";
|
||||
import { Shared } from "../objects/Shared";
|
||||
import { User } from "../objects/User";
|
||||
import ICommand from "../interfaces/ICommand";
|
||||
import Channel from "../objects/Channel";
|
||||
import Shared from "../objects/Shared";
|
||||
import User from "../objects/User";
|
||||
|
||||
export class BaseCommand implements ICommand {
|
||||
export default class BaseCommand implements ICommand {
|
||||
public shared:Shared;
|
||||
public readonly helpText:string = "No help page was found for that command";
|
||||
public readonly helpDescription:string = "Command has no description set";
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { Channel } from "../objects/Channel";
|
||||
import { User } from "../objects/User";
|
||||
import { BaseCommand } from "./BaseCommand";
|
||||
import { Shared } from "../objects/Shared";
|
||||
import { ICommand } from "../interfaces/ICommand";
|
||||
import Channel from "../objects/Channel";
|
||||
import User from "../objects/User";
|
||||
import BaseCommand from "./BaseCommand";
|
||||
import Shared from "../objects/Shared";
|
||||
import ICommand from "../interfaces/ICommand";
|
||||
|
||||
export class HelpCommand extends BaseCommand {
|
||||
export default class HelpCommand extends BaseCommand {
|
||||
public readonly helpDescription:string = "Shows this message! :)";
|
||||
|
||||
private readonly commandList:{ [id:string]: ICommand };
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { Channel } from "../objects/Channel";
|
||||
import { User } from "../objects/User";
|
||||
import { BaseCommand } from "./BaseCommand";
|
||||
import Channel from "../objects/Channel";
|
||||
import User from "../objects/User";
|
||||
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 exec(channel:Channel, sender:User, args:Array<string>) {
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
import { Channel } from "../objects/Channel";
|
||||
import { User } from "../objects/User";
|
||||
import { Match } from "../objects/Match";
|
||||
import { BaseCommand } from "./BaseCommand";
|
||||
import Channel from "../objects/Channel";
|
||||
import User from "../objects/User";
|
||||
import Match from "../objects/Match";
|
||||
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 abort - Aborts the currently running round / countdown
|
||||
!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 helpArguments:Array<string> = ["subCommand"];
|
||||
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
import { Channel } from "../objects/Channel";
|
||||
import { User } from "../objects/User";
|
||||
import Channel from "../objects/Channel";
|
||||
import User from "../objects/User";
|
||||
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 score - Sets your ranking mode to score
|
||||
!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 exec(channel:Channel, sender:User, args:Array<string>) {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { Channel } from "../objects/Channel";
|
||||
import { User } from "../objects/User";
|
||||
import { BaseCommand } from "./BaseCommand";
|
||||
import Channel from "../objects/Channel";
|
||||
import User from "../objects/User";
|
||||
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 helpArguments:Array<string> = ["number"];
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
export interface Config {
|
||||
express:ExpressConfigSection,
|
||||
export default interface Config {
|
||||
http:HttpConfigSection,
|
||||
prometheus:PrometheusConfigSection,
|
||||
redis:RedisConfigSection,
|
||||
database:DatabaseConfigSection
|
||||
}
|
||||
|
||||
interface ExpressConfigSection {
|
||||
interface HttpConfigSection {
|
||||
port:number,
|
||||
compression:boolean
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { Channel } from "../objects/Channel";
|
||||
import { Shared } from "../objects/Shared";
|
||||
import { User } from "../objects/User";
|
||||
import Channel from "../objects/Channel";
|
||||
import Shared from "../objects/Shared";
|
||||
import User from "../objects/User";
|
||||
|
||||
export interface ICommand {
|
||||
export default interface ICommand {
|
||||
shared:Shared,
|
||||
helpText:string,
|
||||
helpDescription:string,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export interface IpZxqResponse {
|
||||
export default interface IpZxqResponse {
|
||||
country: string,
|
||||
loc: string
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import { MatchDataSlot } from "./MatchDataSlot";
|
||||
import MatchDataSlot from "./MatchDataSlot";
|
||||
|
||||
export interface MatchData {
|
||||
export default interface MatchData {
|
||||
matchId:number,
|
||||
matchType:number,
|
||||
activeMods:number,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export interface MatchDataSlot {
|
||||
export default interface MatchDataSlot {
|
||||
status:number,
|
||||
team:number,
|
||||
playerId:number,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export interface MatchJoinData {
|
||||
export default interface MatchJoinData {
|
||||
matchId: number,
|
||||
gamePassword: string
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
export interface MatchScoreData {
|
||||
export default interface MatchScoreData {
|
||||
time:number,
|
||||
id:number,
|
||||
count300:number,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export interface MatchStartSkipData {
|
||||
export default interface MatchStartSkipData {
|
||||
playerId:number,
|
||||
flag:boolean
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
export interface MessageData {
|
||||
export default interface MessageData {
|
||||
sendingClient: string,
|
||||
message: string,
|
||||
target: string,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { MatchData } from "./MatchData"
|
||||
import { MessageData } from "./MessageData"
|
||||
import MatchData from "./MatchData"
|
||||
import MessageData from "./MessageData"
|
||||
|
||||
export interface OsuPacketWriter {
|
||||
export default interface OsuPacketWriter {
|
||||
// Functions
|
||||
LoginReply(data:number) : OsuPacketWriter,
|
||||
CommandError() : OsuPacketWriter,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { Slot } from "../objects/Slot";
|
||||
import { User } from "../objects/User";
|
||||
import { MatchScoreData } from "./MatchScoreData";
|
||||
import Slot from "../objects/Slot";
|
||||
import User from "../objects/User";
|
||||
import MatchScoreData from "./MatchScoreData";
|
||||
|
||||
export interface PlayerScore {
|
||||
export default interface PlayerScore {
|
||||
player:User,
|
||||
slot:Slot,
|
||||
score:number,
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { osu } from "../../osuTyping";
|
||||
import { Bot } from "../Bot";
|
||||
import { Shared } from "../objects/Shared";
|
||||
import { DataStream } from "./DataStream";
|
||||
import { User } from "./User";
|
||||
import osu from "../../osuTyping";
|
||||
import Bot from "../Bot";
|
||||
import ChatHistory from "../ChatHistory";
|
||||
import Shared from "../objects/Shared";
|
||||
import DataStream from "./DataStream";
|
||||
import User from "./User";
|
||||
|
||||
export class Channel {
|
||||
export default class Channel {
|
||||
public name:string;
|
||||
public description:string;
|
||||
public stream:DataStream;
|
||||
|
@ -40,6 +41,9 @@ export class Channel {
|
|||
senderId: sender.id
|
||||
});
|
||||
this.stream.SendWithExclusion(osuPacketWriter.toBuffer, sender);
|
||||
if (this.name === "#osu") {
|
||||
ChatHistory.AddMessage(`${sender.username}: ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (message[0] === "!") {
|
||||
|
@ -63,6 +67,10 @@ export class Channel {
|
|||
} else {
|
||||
this.stream.Send(osuPacketWriter.toBuffer);
|
||||
}
|
||||
|
||||
if (this.name === "#osu") {
|
||||
ChatHistory.AddMessage(`${this.bot.user.username}: ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
public SendSystemMessage(message:string, sendTo?:User) {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { ConsoleHelper } from "../../ConsoleHelper";
|
||||
import { Constants } from "../../Constants";
|
||||
import { DataStreamArray } from "./DataStreamArray";
|
||||
import { User } from "./User";
|
||||
import { UserArray } from "./UserArray";
|
||||
import Constants from "../../Constants";
|
||||
import DataStreamArray from "./DataStreamArray";
|
||||
import User from "./User";
|
||||
import UserArray from "./UserArray";
|
||||
import { hexlify } from "../Util";
|
||||
|
||||
type DeleteFunction = (dataStream:DataStream) => void;
|
||||
|
||||
export class DataStream {
|
||||
export default class DataStream {
|
||||
private users:UserArray = new UserArray();
|
||||
public readonly name:string;
|
||||
private readonly parent:DataStreamArray;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { ConsoleHelper } from "../../ConsoleHelper";
|
||||
import { DataStream } from "./DataStream";
|
||||
import { FunkyArray } from "./FunkyArray";
|
||||
import { User } from "./User";
|
||||
import DataStream from "./DataStream";
|
||||
import FunkyArray from "./FunkyArray";
|
||||
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 {
|
||||
const dataStream:DataStream = this.add(name, new DataStream(name, this, removeWhenEmpty));
|
||||
ConsoleHelper.printStream(`Created stream [${name}]`);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { ConsoleHelper } from "../../ConsoleHelper";
|
||||
import { createPool, Pool } from "mysql2";
|
||||
|
||||
export class Database {
|
||||
export default class Database {
|
||||
private connectionPool:Pool;
|
||||
private static readonly CONNECTION_LIMIT = 128;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export class FunkyArray<T> {
|
||||
export default class FunkyArray<T> {
|
||||
private items:any = {};
|
||||
private itemKeys:Array<string> = Object.keys(this.items);
|
||||
private iterableArray:Array<T> = new Array<T>();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export class LatLng {
|
||||
export default class LatLng {
|
||||
public latitude:number;
|
||||
public longitude:number;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export class LoginInfo {
|
||||
export default class LoginInfo {
|
||||
public username:string;
|
||||
public password:string;
|
||||
public version:string;
|
||||
|
@ -19,8 +19,6 @@ export class LoginInfo {
|
|||
data = data.toString();
|
||||
}
|
||||
|
||||
console.log(data);
|
||||
|
||||
const loginData:Array<string> = data.split("\n");
|
||||
const extraData:Array<string> = loginData[2].split("|");
|
||||
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import { Channel } from "./Channel";
|
||||
import { Shared } from "../objects/Shared";
|
||||
import { DataStream } from "./DataStream";
|
||||
import { Slot } from "./Slot";
|
||||
import { User } from "./User";
|
||||
import { StatusUpdate } from "../packets/StatusUpdate";
|
||||
import Channel from "./Channel";
|
||||
import Shared from "../objects/Shared";
|
||||
import DataStream from "./DataStream";
|
||||
import Slot from "./Slot";
|
||||
import User from "./User";
|
||||
import StatusUpdate from "../packets/StatusUpdate";
|
||||
import { SlotStatus } from "../enums/SlotStatus";
|
||||
import { MatchData } from "../interfaces/MatchData";
|
||||
import MatchData from "../interfaces/MatchData";
|
||||
import { Team } from "../enums/Team";
|
||||
import { MatchStartSkipData } from "../interfaces/MatchStartSkipData";
|
||||
import MatchStartSkipData from "../interfaces/MatchStartSkipData";
|
||||
import { Mods } from "../enums/Mods";
|
||||
import { PlayerScore } from "../interfaces/PlayerScore";
|
||||
import { MatchScoreData } from "../interfaces/MatchScoreData";
|
||||
import { osu } from "../../osuTyping";
|
||||
import PlayerScore from "../interfaces/PlayerScore";
|
||||
import MatchScoreData from "../interfaces/MatchScoreData";
|
||||
import osu from "../../osuTyping";
|
||||
|
||||
export class Match {
|
||||
export default class Match {
|
||||
// osu! Data
|
||||
public matchId:number = -1;
|
||||
public inProgress:boolean = false;
|
||||
|
@ -236,8 +236,6 @@ export class Match {
|
|||
|
||||
// Update all users in the match with new match information
|
||||
this.matchStream.Send(osuPacketWriter.toBuffer);
|
||||
|
||||
console.log(this.slots);
|
||||
}
|
||||
|
||||
public moveToSlot(user:User, slotToMoveTo:number) {
|
||||
|
@ -448,7 +446,6 @@ export class Match {
|
|||
|
||||
this.matchLoadSlots = new Array<MatchStartSkipData>();
|
||||
// Loop through all slots in the match
|
||||
console.log(this.slots);
|
||||
for (let slot of this.slots) {
|
||||
// Make sure the slot has a user in it
|
||||
if (slot.player === undefined || slot.status === SlotStatus.Empty || slot.status === SlotStatus.Locked) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { FunkyArray } from "./FunkyArray";
|
||||
import { Match } from "./Match";
|
||||
import FunkyArray from "./FunkyArray";
|
||||
import Match from "./Match";
|
||||
|
||||
export class MatchArray extends FunkyArray<Match> {
|
||||
export default class MatchArray extends FunkyArray<Match> {
|
||||
public getById(id:number) : Match | undefined {
|
||||
for (let match of this.getIterableItems()) {
|
||||
if (match.matchId === id) {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { osu } from "../../osuTyping";
|
||||
import { Shared } from "../objects/Shared";
|
||||
import { Channel } from "./Channel";
|
||||
import { DataStream } from "./DataStream";
|
||||
import { User } from "./User";
|
||||
import osu from "../../osuTyping";
|
||||
import Shared from "../objects/Shared";
|
||||
import Channel from "./Channel";
|
||||
import DataStream from "./DataStream";
|
||||
import User from "./User";
|
||||
|
||||
export class PrivateChannel extends Channel {
|
||||
export default class PrivateChannel extends Channel {
|
||||
private readonly user0:User;
|
||||
private readonly user1:User;
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import { ChatManager } from "../ChatManager";
|
||||
import { Config } from "../interfaces/Config";
|
||||
import { Database } from "../objects/Database";
|
||||
import { DataStreamArray } from "../objects/DataStreamArray";
|
||||
import { MultiplayerManager } from "../MultiplayerManager";
|
||||
import { PrivateChatManager } from "../PrivateChatManager";
|
||||
import ChatManager from "../ChatManager";
|
||||
import Config from "../interfaces/Config";
|
||||
import Database from "../objects/Database";
|
||||
import DataStreamArray from "../objects/DataStreamArray";
|
||||
import MultiplayerManager from "../MultiplayerManager";
|
||||
import PrivateChatManager from "../PrivateChatManager";
|
||||
import { readFileSync } from "fs";
|
||||
import { UserArray } from "../objects/UserArray";
|
||||
import { User } from "./User";
|
||||
import { LatLng } from "./LatLng";
|
||||
import { Bot } from "../Bot";
|
||||
import UserArray from "../objects/UserArray";
|
||||
import User from "./User";
|
||||
import LatLng from "./LatLng";
|
||||
import Bot from "../Bot";
|
||||
|
||||
export class Shared {
|
||||
export default class Shared {
|
||||
public readonly chatManager:ChatManager;
|
||||
public readonly config:Config;
|
||||
public readonly database:Database;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { Mods } from "../enums/Mods";
|
||||
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 status:SlotStatus;
|
||||
public team:number;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { LatLng } from "./LatLng";
|
||||
import LatLng from "./LatLng";
|
||||
import { RankingModes } from "../enums/RankingModes";
|
||||
import { Match } from "./Match";
|
||||
import { DataStream } from "./DataStream";
|
||||
import { StatusUpdate } from "../packets/StatusUpdate";
|
||||
import { Shared } from "../objects/Shared";
|
||||
import { Slot } from "./Slot";
|
||||
import Match from "./Match";
|
||||
import DataStream from "./DataStream";
|
||||
import StatusUpdate from "../packets/StatusUpdate";
|
||||
import Shared from "../objects/Shared";
|
||||
import Slot from "./Slot";
|
||||
|
||||
const rankingModes = [
|
||||
"pp_raw",
|
||||
|
@ -12,7 +12,7 @@ const rankingModes = [
|
|||
"avg_accuracy"
|
||||
];
|
||||
|
||||
export class User {
|
||||
export default class User {
|
||||
private static readonly EMPTY_BUFFER = Buffer.alloc(0);
|
||||
|
||||
public shared:Shared;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { FunkyArray } from "./FunkyArray";
|
||||
import { User } from "./User";
|
||||
import FunkyArray from "./FunkyArray";
|
||||
import User from "./User";
|
||||
|
||||
export class UserArray extends FunkyArray<User> {
|
||||
export default class UserArray extends FunkyArray<User> {
|
||||
public getById(id:number) : User | undefined {
|
||||
for (let user of this.getIterableItems()) {
|
||||
if (user.id == id)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export class UserInfo {
|
||||
export default class UserInfo {
|
||||
id:number = Number.MIN_VALUE;
|
||||
username: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.id, friendId
|
||||
]);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { User } from "../objects/User";
|
||||
import { StatusUpdate } from "./StatusUpdate";
|
||||
import User from "../objects/User";
|
||||
import StatusUpdate from "./StatusUpdate";
|
||||
|
||||
export function ChangeAction(user:User, data:any) {
|
||||
export default function ChangeAction(user:User, data:any) {
|
||||
user.updatePresence(data);
|
||||
|
||||
if (user.spectatorStream != null) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { ConsoleHelper } from "../../ConsoleHelper";
|
||||
import { Database } from "../objects/Database";
|
||||
import { DataStreamArray } from "../objects/DataStreamArray";
|
||||
import { User } from "../objects/User";
|
||||
import Database from "../objects/Database";
|
||||
import DataStreamArray from "../objects/DataStreamArray";
|
||||
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???";
|
||||
|
||||
const logoutStartTime = Date.now();
|
||||
|
|
|
@ -1,27 +1,23 @@
|
|||
import { MessageData } from "../interfaces/MessageData";
|
||||
import { Shared } from "../objects/Shared";
|
||||
import { PrivateChannel } from "../objects/PrivateChannel";
|
||||
import { User } from "../objects/User";
|
||||
import MessageData from "../interfaces/MessageData";
|
||||
import Shared from "../objects/Shared";
|
||||
import PrivateChannel from "../objects/PrivateChannel";
|
||||
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 sendingTo = shared.users.getByUsername(message.target);
|
||||
if (!(sendingTo instanceof User)) {
|
||||
console.log("Sending User invalid");
|
||||
return;
|
||||
}
|
||||
let channel = shared.privateChatManager.GetChannelByName(`${user.username}${sendingTo.username}`);
|
||||
if (!(channel instanceof PrivateChannel)) {
|
||||
console.log("First find failed");
|
||||
// Try it the other way around
|
||||
channel = shared.privateChatManager.GetChannelByName(`${sendingTo.username}${user.username}`);
|
||||
}
|
||||
|
||||
if (!(channel instanceof PrivateChannel)) {
|
||||
console.log("Second find failed, creating");
|
||||
channel = shared.privateChatManager.AddChannel(user, sendingTo);
|
||||
}
|
||||
|
||||
console.log("sending");
|
||||
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.id, friendId
|
||||
]);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { Shared } from "../objects/Shared";
|
||||
import Shared from "../objects/Shared";
|
||||
import { RankingModes } from "../enums/RankingModes";
|
||||
import { User } from "../objects/User";
|
||||
import { osu } from "../../osuTyping";
|
||||
import User from "../objects/User";
|
||||
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
|
||||
|
||||
// Create new osu packet writer
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { osu } from "../../osuTyping";
|
||||
import { User } from "../objects/User";
|
||||
import osu from "../../osuTyping";
|
||||
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);
|
||||
if (match === undefined) {
|
||||
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);
|
||||
if (match === undefined) {
|
||||
return;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { osu } from "../../osuTyping";
|
||||
import { Match } from "../objects/Match";
|
||||
import { User } from "../objects/User";
|
||||
import { StatusUpdate } from "./StatusUpdate";
|
||||
import { UserPresence } from "./UserPresence";
|
||||
import osu from "../../osuTyping";
|
||||
import Match from "../objects/Match";
|
||||
import User from "../objects/User";
|
||||
import StatusUpdate from "./StatusUpdate";
|
||||
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);
|
||||
if (!(match instanceof Match)) {
|
||||
return;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { osu } from "../../osuTyping";
|
||||
import { Shared } from "../objects/Shared";
|
||||
import { User } from "../objects/User";
|
||||
import osu from "../../osuTyping";
|
||||
import Shared from "../objects/Shared";
|
||||
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();
|
||||
let shared:Shared;
|
||||
if (arg0 instanceof User) {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { osu } from "../../osuTyping";
|
||||
import { Shared } from "../objects/Shared";
|
||||
import { User } from "../objects/User";
|
||||
import osu from "../../osuTyping";
|
||||
import Shared from "../objects/Shared";
|
||||
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();
|
||||
let shared:Shared;
|
||||
if (arg0 instanceof User) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { User } from "../objects/User";
|
||||
import { StatusUpdate } from "./StatusUpdate";
|
||||
import { UserPresence } from "./UserPresence";
|
||||
import { UserPresenceBundle } from "./UserPresenceBundle";
|
||||
import User from "../objects/User";
|
||||
import StatusUpdate from "./StatusUpdate";
|
||||
import UserPresence from "./UserPresence";
|
||||
import UserPresenceBundle from "./UserPresenceBundle";
|
||||
|
||||
export function UserStatsRequest(user:User, data:Array<number>) {
|
||||
export default function UserStatsRequest(user:User, data:Array<number>) {
|
||||
UserPresenceBundle(user);
|
||||
|
||||
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