DB access cleanup

This commit is contained in:
Holly Stubbs 2023-10-07 13:09:10 +01:00
parent 877592bb94
commit 9d53d82997
Signed by: tgpholly
GPG key ID: B8583C4B7D18119E
10 changed files with 138 additions and 40 deletions

View file

@ -37,7 +37,7 @@ enum LoginResult {
function TestLogin(loginInfo:LoginInfo, shared:Shared) {
return new Promise<LoginResult>(async (resolve, reject) => {
const userDBData = await shared.userInfoRepository.getByUsername(loginInfo.username);
const userDBData = await shared.userInfoRepository.selectByUsername(loginInfo.username);
// Make sure a user was found in the database
if (userDBData == null) return resolve(LoginResult.INCORRECT);
@ -123,7 +123,7 @@ export default async function LoginProcess(req:IncomingMessage, res:ServerRespon
}
// Get information about the user from the database
const userInfo = await shared.userInfoRepository.getByUsername(loginInfo.username);
const userInfo = await shared.userInfoRepository.selectByUsername(loginInfo.username);
if (userInfo == null) {
return;
}

View file

@ -1,6 +1,6 @@
import Channel from "../objects/Channel";
import User from "../objects/User";
import { RankingModes } from "../enums/RankingModes";
import { RankingMode } from "../enums/RankingMode";
import BaseCommand from "./BaseCommand";
export default class RankingCommand extends BaseCommand {
@ -18,15 +18,15 @@ export default class RankingCommand extends BaseCommand {
switch (args[0].toLowerCase()) {
case "pp":
sender.rankingMode = RankingModes.PP;
sender.rankingMode = RankingMode.PP;
channel.SendBotMessage("Set ranking mode to pp.");
break;
case "score":
sender.rankingMode = RankingModes.RANKED_SCORE;
sender.rankingMode = RankingMode.RANKED_SCORE;
channel.SendBotMessage("Set ranking mode to score.");
break;
case "acc":
sender.rankingMode = RankingModes.AVG_ACCURACY;
sender.rankingMode = RankingMode.AVG_ACCURACY;
channel.SendBotMessage("Set ranking mode to accuracy.");
break;
}

7
server/enums/Mode.ts Normal file
View file

@ -0,0 +1,7 @@
export enum Mode {
Unknown = -1,
Osu,
Taiko,
Catch,
Mania
}

View file

@ -1,4 +1,4 @@
export enum RankingModes {
export enum RankingMode {
PP,
RANKED_SCORE,
AVG_ACCURACY

View file

@ -12,6 +12,7 @@ import Bot from "../Bot";
import { ConsoleHelper } from "../../ConsoleHelper";
import UserInfoRepository from "../repos/UserInfoRepository";
import { Permissions } from "../enums/Permissions";
import UserModesInfoRepository from "../repos/UserModesInfoRepository";
export default class Shared {
public readonly chatManager:ChatManager;
@ -24,6 +25,7 @@ export default class Shared {
public readonly bot:Bot;
public readonly userInfoRepository:UserInfoRepository;
public readonly userModesInfoRepository:UserModesInfoRepository;
public constructor() {
if (!existsSync("./config.json")) {
@ -53,5 +55,6 @@ export default class Shared {
// DB Repos
this.userInfoRepository = new UserInfoRepository(this);
this.userModesInfoRepository = new UserModesInfoRepository(this);
}
}

View file

@ -1,5 +1,5 @@
import LatLng from "./LatLng";
import { RankingModes } from "../enums/RankingModes";
import { RankingMode } from "../enums/RankingMode";
import Match from "./Match";
import DataStream from "./DataStream";
import StatusUpdate from "../packets/StatusUpdate";
@ -9,12 +9,6 @@ import Channel from "./Channel";
import PresenceData from "../interfaces/packetTypes/PresenceData";
import { Permissions } from "../enums/Permissions";
const rankingModes = [
"pp_raw",
"ranked_score",
"avg_accuracy"
];
export default class User {
public shared:Shared;
@ -26,7 +20,7 @@ export default class User {
public queue:Buffer = Buffer.allocUnsafe(0);
// Binato data
public rankingMode:RankingModes = RankingModes.PP;
public rankingMode:RankingMode = RankingMode.PP;
public spectatorStream?:DataStream;
public spectatingUser?:User;
public permissions:Permissions;
@ -101,26 +95,27 @@ export default class User {
// Gets the user's score information from the database and caches it
async updateUserInfo(forceUpdate:boolean = false) {
const userScoreDB = await this.shared.database.querySingle("SELECT * FROM users_modes_info WHERE user_id = ? AND mode_id = ? LIMIT 1", [this.id, this.playMode]);
const mappedRankingMode = rankingModes[this.rankingMode];
const userRankDB = await this.shared.database.query(`SELECT user_id, ${mappedRankingMode} FROM users_modes_info WHERE mode_id = ? ORDER BY ${mappedRankingMode} DESC`, [this.playMode]);
const userScoreDB = await this.shared.userModesInfoRepository.selectByUserIdModeId(this.id, this.playMode);
const userRank = await this.shared.userModesInfoRepository.selectRankByIdModeIdRankingMode(this.id, this.playMode, this.rankingMode);
if (userScoreDB == null || userRankDB == null) throw "fuck";
if (userScoreDB == null || userRank == null) throw "fuck";
this.rank = userRank;
// Handle "if we should update" checks for each rankingMode
let userScoreUpdate = false;
switch (this.rankingMode) {
case RankingModes.PP:
case RankingMode.PP:
if (this.pp != userScoreDB.pp_raw)
userScoreUpdate = true;
break;
case RankingModes.RANKED_SCORE:
case RankingMode.RANKED_SCORE:
if (this.rankedScore != userScoreDB.ranked_score)
userScoreUpdate = true;
break;
case RankingModes.AVG_ACCURACY:
case RankingMode.AVG_ACCURACY:
if (this.accuracy != userScoreDB.avg_accuracy)
userScoreUpdate = true;
break;
@ -131,14 +126,6 @@ export default class User {
this.accuracy = userScoreDB.avg_accuracy;
this.playCount = userScoreDB.playcount;
// Fetch rank
for (let i = 0; i < userRankDB.length; i++) {
if (userRankDB[i]["user_id"] == this.id) {
this.rank = i + 1;
break;
}
}
// Set PP to none if ranking mode is not PP
if (this.rankingMode == 0) this.pp = userScoreDB.pp_raw;
else this.pp = 0;

View file

@ -0,0 +1,24 @@
import { Mode } from "../../enums/Mode";
export default class UserModeInfo {
n:number = Number.MIN_VALUE;
user_id:number = Number.MIN_VALUE;
mode_id:Mode = Mode.Unknown;
count300:number = Number.MIN_VALUE;
count100:number = Number.MIN_VALUE;
count50:number = Number.MIN_VALUE;
countmiss:number = Number.MIN_VALUE;
playcount:number = Number.MIN_VALUE;
total_score:number = Number.MIN_VALUE;
ranked_score:number = Number.MIN_VALUE;
pp_rank:number = Number.MIN_VALUE;
pp_raw:number = Number.MIN_VALUE;
count_rank_ss:number = Number.MIN_VALUE;
count_rank_s:number = Number.MIN_VALUE;
count_rank_a:number = Number.MIN_VALUE;
pp_country_rank:number = Number.MIN_VALUE;
playtime:number = Number.MIN_VALUE;
avg_accuracy:number = Number.MIN_VALUE;
level:number = Number.MIN_VALUE;
is_deleted:boolean = false;
}

View file

@ -1,10 +1,13 @@
import Shared from "../objects/Shared";
import { RankingModes } from "../enums/RankingModes";
import { RankingMode } from "../enums/RankingMode";
import User from "../objects/User";
import osu from "../../osuTyping";
export default function StatusUpdate(arg0:User | Shared, id:number) {
if (id == 3) return; // Ignore Bot
// Ignore Bot
if (id == 3) {
return Buffer.allocUnsafe(0);
}
// Create new osu packet writer
const osuPacketWriter = osu.Bancho.Writer();
@ -18,7 +21,9 @@ export default function StatusUpdate(arg0:User | Shared, id:number) {
// Get user's class
const userData = shared.users.getById(id);
if (userData == null) return;
if (userData == null) {
return Buffer.allocUnsafe(0);
}
osuPacketWriter.HandleOsuUpdate({
userId: userData.id,
@ -33,7 +38,7 @@ export default function StatusUpdate(arg0:User | Shared, id:number) {
playCount: userData.playCount,
totalScore: userData.totalScore,
rank: userData.rank,
performance: (userData.rankingMode == RankingModes.PP ? userData.pp : 0)
performance: (userData.rankingMode == RankingMode.PP ? userData.pp : 0)
});
// Send data to user's queue

View file

@ -9,11 +9,11 @@ export default class UserInfoRepository {
this.database = shared.database;
}
public async getById(id:number) {
const query = await this.database.query("SELECT * FROM users_info WHERE id = ? AND is_deleted = 0 LIMIT 1", [id]);
public async selectById(id:number) {
const query = await this.database.query("CALL SelectUserInfoById(?)", [id]);
if (query != null) {
const userInfo = new UserInfo();
populateUserInfoFromRowDataPacket(userInfo, query[0]);
populateUserInfoFromRowDataPacket(userInfo, query[0][0]);
return userInfo;
}
@ -21,11 +21,11 @@ export default class UserInfoRepository {
return null;
}
public async getByUsername(username:string) {
const query = await this.database.query("SELECT * FROM users_info WHERE username = ? AND is_deleted = 0 LIMIT 1", [username]);
public async selectByUsername(username:string) {
const query = await this.database.query("CALL SelectUserInfoByUsername(?)", [username]);
if (query != null) {
const userInfo = new UserInfo();
populateUserInfoFromRowDataPacket(userInfo, query[0]);
populateUserInfoFromRowDataPacket(userInfo, query[0][0]);
return userInfo;
}

View file

@ -0,0 +1,72 @@
import { RowDataPacket } from "mysql2";
import Database from "../objects/Database";
import Shared from "../objects/Shared";
import UserModeInfo from "../objects/database/UserModeInfo";
import { Mode } from "fs";
import { RankingMode } from "../enums/RankingMode";
export default class UserModesInfoRepository {
private database:Database;
public constructor(shared:Shared) {
this.database = shared.database;
}
public async selectByUserIdModeId(id:number, mode:Mode) {
const query = await this.database.query("CALL SelectUserModesInfoByUserIdModeId(?,?)", [id, mode]);
if (query != null) {
const userModeInfo = new UserModeInfo();
populateUserModeInfoFromRowDataPacket(userModeInfo, query[0][0]);
return userModeInfo;
}
return null;
}
public async selectRankByIdModeIdRankingMode(id:number, mode:Mode, rankingMode:RankingMode) : Promise<number | null> {
let query:RowDataPacket[] | undefined;
switch (rankingMode) {
case RankingMode.RANKED_SCORE:
query = await this.database.query("CALL SelectUserScoreRankByIdModeId(?,?)", [id, mode]);
break;
case RankingMode.AVG_ACCURACY:
query = await this.database.query("CALL SelectUserAccRankByIdModeId(?,?)", [id, mode]);
break;
case RankingMode.PP:
default:
query = await this.database.query("CALL SelectUserPPRankByIdModeId(?,?)", [id, mode]);
break;
}
if (query != null && query.length != 0) {
return query[0][0].rank;
}
return null;
}
}
function populateUserModeInfoFromRowDataPacket(userModeInfo:UserModeInfo, rowDataPacket:RowDataPacket) {
userModeInfo.n = rowDataPacket["n"];
userModeInfo.user_id = rowDataPacket["user_id"];
userModeInfo.mode_id = rowDataPacket["mode_id"];
userModeInfo.count300 = rowDataPacket["count300"];
userModeInfo.count100 = rowDataPacket["count100"];
userModeInfo.count50 = rowDataPacket["count50"];
userModeInfo.countmiss = rowDataPacket["countmiss"];
userModeInfo.playcount = rowDataPacket["playcount"];
userModeInfo.total_score = rowDataPacket["total_score"];
userModeInfo.ranked_score = rowDataPacket["ranked_score"];
userModeInfo.pp_rank = rowDataPacket["pp_rank"];
userModeInfo.pp_raw = rowDataPacket["pp_raw"];
userModeInfo.count_rank_ss = rowDataPacket["count_rank_ss"];
userModeInfo.count_rank_s = rowDataPacket["count_rank_s"];
userModeInfo.count_rank_a = rowDataPacket["count_rank_a"];
userModeInfo.pp_country_rank = rowDataPacket["pp_country_rank"];
userModeInfo.playtime = rowDataPacket["playtime"];
userModeInfo.avg_accuracy = rowDataPacket["avg_accuracy"];
userModeInfo.level = rowDataPacket["level"];
userModeInfo.is_deleted = rowDataPacket["is_deleted"];
}