mirror of
https://github.com/zkldi/Tachi.git
synced 2026-10-06 13:58:05 +03:00
rename all instances of ktchi to tachi and change how config works
This commit is contained in:
@@ -9,6 +9,9 @@ coverage
|
||||
.setup_env
|
||||
failed-tests.txt
|
||||
|
||||
# config files
|
||||
conf.json5
|
||||
|
||||
scripts/arc-db-sync/charts.json
|
||||
scripts/arc-db-sync/songs.json
|
||||
scripts/validate-database-errs/*
|
||||
|
||||
Vendored
+4
-4
@@ -1,6 +1,6 @@
|
||||
import { Session, SessionData } from "express-session";
|
||||
import { SYMBOL_KtchiData } from "../../src/lib/constants/ktchi";
|
||||
import { KtchiRequestData, KtchiSessionData } from "../../src/utils/types";
|
||||
import { SYMBOL_TachiData } from "../../src/lib/constants/tachi";
|
||||
import { TachiRequestData, TachiSessionData } from "../../src/utils/types";
|
||||
|
||||
export {};
|
||||
|
||||
@@ -8,7 +8,7 @@ export {};
|
||||
declare module "express-session" {
|
||||
// Inject additional properties on express-session
|
||||
interface SessionData {
|
||||
ktchi: KtchiSessionData;
|
||||
tachi: TachiSessionData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ declare global {
|
||||
interface Request {
|
||||
session: Session & Partial<SessionData>;
|
||||
|
||||
[SYMBOL_KtchiData]?: Partial<KtchiRequestData>;
|
||||
[SYMBOL_TachiData]?: Partial<TachiRequestData>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -54,7 +54,7 @@
|
||||
"express-session": "^1.17.2",
|
||||
"fast-json-stable-hash": "^1.0.2",
|
||||
"fast-xml-parser": "^3.19.0",
|
||||
"tachi-common": "github:zkldi/tachi-common",
|
||||
"json5": "^2.2.0",
|
||||
"mkdirp": "^1.0.4",
|
||||
"mongodb": "3.6.3",
|
||||
"monk": "^7.3.4",
|
||||
@@ -63,6 +63,7 @@
|
||||
"prudence": "^0.9.6",
|
||||
"redis": "^3.1.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"tachi-common": "github:zkldi/tachi-common",
|
||||
"typescript": "^4.3.2",
|
||||
"winston": "^3.3.3"
|
||||
},
|
||||
|
||||
Generated
+2
-1
@@ -33,6 +33,7 @@ specifiers:
|
||||
express-session: ^1.17.2
|
||||
fast-json-stable-hash: ^1.0.2
|
||||
fast-xml-parser: ^3.19.0
|
||||
json5: ^2.2.0
|
||||
mkdirp: ^1.0.4
|
||||
mongodb: 3.6.3
|
||||
monk: ^7.3.4
|
||||
@@ -64,6 +65,7 @@ dependencies:
|
||||
express-session: 1.17.2
|
||||
fast-json-stable-hash: 1.0.2
|
||||
fast-xml-parser: 3.19.0
|
||||
json5: 2.2.0
|
||||
mkdirp: 1.0.4
|
||||
mongodb: 3.6.3
|
||||
monk: 7.3.4
|
||||
@@ -2561,7 +2563,6 @@ packages:
|
||||
hasBin: true
|
||||
dependencies:
|
||||
minimist: 1.2.5
|
||||
dev: true
|
||||
|
||||
/jsprim/1.4.1:
|
||||
resolution: {integrity: sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { TierlistParent, Game } from "tachi-common";
|
||||
import { gameHuman, validPlaytypes } from "tachi-common/js/config";
|
||||
import db from "../../src/db/db";
|
||||
import db from "../../src/external/mongo/db";
|
||||
import MigrateRecords from "./migrate";
|
||||
|
||||
function ConvertFn(c: any): TierlistParent {
|
||||
|
||||
@@ -39,7 +39,7 @@ async function MergeIDs() {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const ktchiChart = await FindChartWithPTDFVersion(
|
||||
const tachiChart = await FindChartWithPTDFVersion(
|
||||
"iidx",
|
||||
song.id,
|
||||
playtype,
|
||||
@@ -47,7 +47,7 @@ async function MergeIDs() {
|
||||
version
|
||||
);
|
||||
|
||||
if (!ktchiChart) {
|
||||
if (!tachiChart) {
|
||||
logger.error(
|
||||
`Could not find chart ${songTitle} ${playtype} ${difficulty} ${version}.`
|
||||
);
|
||||
@@ -59,7 +59,7 @@ async function MergeIDs() {
|
||||
db.charts.iidx as unknown as ICollection<ChartDocument<"iidx:SP" | "iidx:DP">>
|
||||
).update(
|
||||
{
|
||||
_id: ktchiChart._id,
|
||||
_id: tachiChart._id,
|
||||
},
|
||||
{
|
||||
$set: {
|
||||
|
||||
@@ -60,24 +60,24 @@ async function UpdatePoyashiData() {
|
||||
|
||||
const [playtype, diff] = res;
|
||||
|
||||
const ktchiSong = await FindSongOnTitle("iidx", d.title);
|
||||
const tachiSong = await FindSongOnTitle("iidx", d.title);
|
||||
|
||||
if (!ktchiSong) {
|
||||
if (!tachiSong) {
|
||||
logger.warn(`Cannot find song ${d.title}?`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const ktchiChart = (await FindChartWithPTDFVersion(
|
||||
const tachiChart = (await FindChartWithPTDFVersion(
|
||||
"iidx",
|
||||
ktchiSong.id,
|
||||
tachiSong.id,
|
||||
playtype as "SP" | "DP",
|
||||
diff as Difficulties["iidx:DP" | "iidx:SP"],
|
||||
"28"
|
||||
)) as ChartDocument<"iidx:SP" | "iidx:DP">;
|
||||
|
||||
if (!ktchiChart) {
|
||||
if (!tachiChart) {
|
||||
logger.warn(
|
||||
`Cannot find chart ${ktchiSong.title} (${ktchiSong.id}) ${playtype}, ${diff}?`
|
||||
`Cannot find chart ${tachiSong.title} (${tachiSong.id}) ${playtype}, ${diff}?`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
@@ -86,21 +86,21 @@ async function UpdatePoyashiData() {
|
||||
|
||||
if (kavg < 0) {
|
||||
logger.warn(
|
||||
`${ktchiSong.title} (${playtype} ${diff}). Invalid kavg ${d.avg}, Skipping.`
|
||||
`${tachiSong.title} (${playtype} ${diff}). Invalid kavg ${d.avg}, Skipping.`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
const kesd = ESDCore.CalculateESD(
|
||||
config.judgementWindows.iidx.SP,
|
||||
kavg / (ktchiChart.data.notecount * 2)
|
||||
kavg / (tachiChart.data.notecount * 2)
|
||||
);
|
||||
|
||||
realData.push({
|
||||
coef: d.coef === -1 ? null : d.coef,
|
||||
kavg: Number(d.avg),
|
||||
wr: Number(d.wr),
|
||||
chartID: ktchiChart.chartID,
|
||||
chartID: tachiChart.chartID,
|
||||
kesd,
|
||||
});
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -26,7 +26,7 @@ import {
|
||||
BMSCourseDocument,
|
||||
} from "tachi-common";
|
||||
import monk from "monk";
|
||||
import { MONGO_BASE_URL } from "../../lib/env/env";
|
||||
import { MONGO_BASE_URL } from "../../lib/setup/config";
|
||||
import CreateLogCtx from "../../lib/logger/logger";
|
||||
import { OrphanScoreDocument } from "../../lib/score-import/import-types/common/types";
|
||||
|
||||
@@ -39,7 +39,7 @@ let dbName = "ktblackdb";
|
||||
|
||||
/* istanbul ignore next */
|
||||
if (process.env.NODE_ENV === "test") {
|
||||
if (process.env.KTBSV_PARALLEL_TESTS) {
|
||||
if (process.env.TACHI_PARALLEL_TESTS) {
|
||||
dbName = `test-ephemeral-${process.pid}`;
|
||||
} else {
|
||||
dbName = `testingdb`;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { KTCDN_ROOT } from "../env/env";
|
||||
import { KTCDN_ROOT } from "../setup/config";
|
||||
import CreateLogCtx from "../logger/logger";
|
||||
import { promisify } from "util";
|
||||
import mkdirp from "mkdirp";
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export const SYMBOL_KtchiData = Symbol("ktchi-request-patch");
|
||||
@@ -0,0 +1 @@
|
||||
export const SYMBOL_TachiData = Symbol("tachi-request-patch");
|
||||
Vendored
-32
@@ -1,32 +0,0 @@
|
||||
// barrel file for re-exporting env variables.
|
||||
import dotenv from "dotenv";
|
||||
dotenv.config();
|
||||
|
||||
const envVars = [
|
||||
"KTBSV_MONGO_BASE_URL",
|
||||
"KTBSV_LOG_LEVEL",
|
||||
"KTBSV_CAPTCHA_SECRET_KEY",
|
||||
"KTBSV_SESSION_SECRET",
|
||||
"KTBSV_FLO_API_URL",
|
||||
"KTBSV_EAG_API_URL",
|
||||
"KTBSV_ARC_API_URL",
|
||||
"KTBSV_ARC_AUTH_TOKEN",
|
||||
"KTCDN_ROOT",
|
||||
];
|
||||
|
||||
for (const eVar of envVars) {
|
||||
/* istanbul ignore next */
|
||||
if (!process.env[eVar]) {
|
||||
throw new Error(`${eVar} was not defined.`);
|
||||
}
|
||||
}
|
||||
|
||||
export const MONGO_BASE_URL = process.env.KTBSV_MONGO_BASE_URL!;
|
||||
export const LOG_LEVEL = process.env.KTBSV_LOG_LEVEL!;
|
||||
export const SESSION_SECRET = process.env.KTBSV_SESSION_SECRET!;
|
||||
export const CAPTCHA_SECRET_KEY = process.env.KTBSV_CAPTCHA_SECRET_KEY!;
|
||||
export const FLO_API_URL = process.env.KTBSV_FLO_API_URL!;
|
||||
export const EAG_API_URL = process.env.KTBSV_EAG_API_URL!;
|
||||
export const ARC_API_URL = process.env.KTBSV_ARC_API_URL!;
|
||||
export const ARC_AUTH_TOKEN = process.env.KTBSV_ARC_AUTH_TOKEN!;
|
||||
export const KTCDN_ROOT = process.env.KTCDN_ROOT!;
|
||||
@@ -13,8 +13,9 @@ export class ConverterFailure {
|
||||
}
|
||||
|
||||
/**
|
||||
* SkipScoreFailure - This score could not be processed because Kamaitachi does not
|
||||
* SkipScoreFailure - This score could not be processed because we do not
|
||||
* support it. This is not an error, but is not a success either.
|
||||
* An example scenario would be something like a 5KEY score being imported from SSS.
|
||||
*/
|
||||
export class SkipScoreFailure extends ConverterFailure {}
|
||||
|
||||
@@ -43,7 +44,7 @@ export class KTDataNotFoundFailure<T extends ImportTypes> extends ConverterFailu
|
||||
}
|
||||
|
||||
/**
|
||||
* InvalidScoreError - This score provided invalid data that Kamaitachi
|
||||
* InvalidScoreError - This score provided invalid data that we
|
||||
* can not accept.
|
||||
*/
|
||||
export class InvalidScoreFailure extends ConverterFailure {}
|
||||
|
||||
@@ -3,7 +3,7 @@ import nodeFetch from "../../../../../utils/fetch";
|
||||
import { TraverseKaiAPI } from "../../common/api-kai/traverse-api";
|
||||
import { ParserFunctionReturnsAsync } from "../../common/types";
|
||||
import { EmptyObject } from "../../../../../utils/types";
|
||||
import { ARC_API_URL, ARC_AUTH_TOKEN } from "../../../../env/env";
|
||||
import { ARC_API_URL, ARC_AUTH_TOKEN } from "../../../../setup/config";
|
||||
|
||||
export function ParseArcDDR(
|
||||
arcProfileID: string,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import nodeFetch from "../../../../../utils/fetch";
|
||||
import { HasOwnProperty } from "../../../../../utils/misc";
|
||||
import { IIDXClasses } from "../../../../constants/classes";
|
||||
import { ARC_API_URL } from "../../../../env/env";
|
||||
import { ARC_API_URL } from "../../../../setup/config";
|
||||
import { ClassHandler } from "../../../framework/user-game-stats/types";
|
||||
|
||||
export async function CreateArcIIDXClassHandler(
|
||||
|
||||
@@ -3,7 +3,7 @@ import nodeFetch from "../../../../../utils/fetch";
|
||||
import { TraverseKaiAPI } from "../../common/api-kai/traverse-api";
|
||||
import { ParserFunctionReturnsAsync } from "../../common/types";
|
||||
import { EmptyObject } from "../../../../../utils/types";
|
||||
import { ARC_API_URL, ARC_AUTH_TOKEN } from "../../../../env/env";
|
||||
import { ARC_API_URL, ARC_AUTH_TOKEN } from "../../../../setup/config";
|
||||
import { CreateArcIIDXClassHandler } from "./class-handler";
|
||||
|
||||
export async function ParseArcIIDX(
|
||||
|
||||
@@ -3,7 +3,7 @@ import nodeFetch from "../../../../../utils/fetch";
|
||||
import { TraverseKaiAPI } from "../../common/api-kai/traverse-api";
|
||||
import { ParserFunctionReturnsAsync } from "../../common/types";
|
||||
import { EmptyObject } from "../../../../../utils/types";
|
||||
import { ARC_API_URL, ARC_AUTH_TOKEN } from "../../../../env/env";
|
||||
import { ARC_API_URL, ARC_AUTH_TOKEN } from "../../../../setup/config";
|
||||
|
||||
export function ParseArcSDVX(
|
||||
arcProfileID: string,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { KaiAuthDocument } from "tachi-common";
|
||||
import { KaiContext } from "../types";
|
||||
import { TraverseKaiAPI } from "../traverse-api";
|
||||
import { ParserFunctionReturnsAsync } from "../../types";
|
||||
import { FLO_API_URL, EAG_API_URL } from "../../../../../env/env";
|
||||
import { FLO_API_URL, EAG_API_URL } from "../../../../../setup/config";
|
||||
|
||||
export function ParseKaiIIDX(
|
||||
service: "FLO" | "EAG",
|
||||
|
||||
@@ -4,7 +4,7 @@ import { KaiAuthDocument } from "tachi-common";
|
||||
import { KaiContext } from "../types";
|
||||
import { TraverseKaiAPI } from "../traverse-api";
|
||||
import { ParserFunctionReturnsAsync } from "../../types";
|
||||
import { EAG_API_URL, FLO_API_URL } from "../../../../../env/env";
|
||||
import { EAG_API_URL, FLO_API_URL } from "../../../../../setup/config";
|
||||
|
||||
export function ParseKaiSDVX(
|
||||
service: "FLO" | "EAG",
|
||||
|
||||
@@ -57,9 +57,9 @@ const ConvertEamIIDXCSV: ConverterFunction<IIDXEamusementCSVData, IIDXEamusement
|
||||
// @optimisable - This is actually a multi-fetch. Since eam-csv scores
|
||||
// are batched up into (song, chart1, chart2, chart3 ...) rows
|
||||
// we actually already have fetched this song a second ago.
|
||||
const ktchiSong = await FindSongOnTitle("iidx", data.title);
|
||||
const tachiSong = await FindSongOnTitle("iidx", data.title);
|
||||
|
||||
if (!ktchiSong) {
|
||||
if (!tachiSong) {
|
||||
throw new KTDataNotFoundFailure(
|
||||
`Could not find song for ${data.title}.`,
|
||||
importType,
|
||||
@@ -68,21 +68,21 @@ const ConvertEamIIDXCSV: ConverterFunction<IIDXEamusementCSVData, IIDXEamusement
|
||||
);
|
||||
}
|
||||
|
||||
const HUMANISED_CHART_TITLE = `${ktchiSong.title} (${context.playtype} ${eamScore.difficulty} [v${context.importVersion}])`;
|
||||
const HUMANISED_CHART_TITLE = `${tachiSong.title} (${context.playtype} ${eamScore.difficulty} [v${context.importVersion}])`;
|
||||
|
||||
if (isLegacyLeggendaria) {
|
||||
eamScore.difficulty = "LEGGENDARIA";
|
||||
}
|
||||
|
||||
const ktchiChart = (await FindChartWithPTDFVersion(
|
||||
const tachiChart = (await FindChartWithPTDFVersion(
|
||||
"iidx",
|
||||
ktchiSong.id,
|
||||
tachiSong.id,
|
||||
context.playtype,
|
||||
eamScore.difficulty,
|
||||
context.importVersion
|
||||
)) as ChartDocument<"iidx:SP" | "iidx:DP">;
|
||||
|
||||
if (!ktchiChart) {
|
||||
if (!tachiChart) {
|
||||
throw new KTDataNotFoundFailure(
|
||||
`Could not find chart for ${HUMANISED_CHART_TITLE}`,
|
||||
"file/eamusement-iidx-csv",
|
||||
@@ -96,7 +96,7 @@ const ConvertEamIIDXCSV: ConverterFunction<IIDXEamusementCSVData, IIDXEamusement
|
||||
`${HUMANISED_CHART_TITLE} - Invalid EX score of ${eamScore.exscore}`
|
||||
);
|
||||
|
||||
const MAX_EX = ktchiChart.data.notecount * 2;
|
||||
const MAX_EX = tachiChart.data.notecount * 2;
|
||||
|
||||
if (exscore > MAX_EX) {
|
||||
throw new InvalidScoreFailure(
|
||||
@@ -129,7 +129,7 @@ const ConvertEamIIDXCSV: ConverterFunction<IIDXEamusementCSVData, IIDXEamusement
|
||||
);
|
||||
}
|
||||
|
||||
const { percent, grade } = GenericGetGradeAndPercent("iidx", exscore, ktchiChart);
|
||||
const { percent, grade } = GenericGetGradeAndPercent("iidx", exscore, tachiChart);
|
||||
|
||||
const timestamp = ParseDateFromString(data.timestamp);
|
||||
|
||||
@@ -171,8 +171,8 @@ const ConvertEamIIDXCSV: ConverterFunction<IIDXEamusementCSVData, IIDXEamusement
|
||||
logger.info(`Skipped assigning BP for score. Had unexpected value of ${eamScore.bp}.`);
|
||||
}
|
||||
|
||||
// ts thinks ktchiSong might be null. It's not, though!
|
||||
return { chart: ktchiChart, dryScore, song: ktchiSong };
|
||||
// ts thinks tachiSong might be null. It's not, though!
|
||||
return { chart: tachiChart, dryScore, song: tachiSong };
|
||||
};
|
||||
|
||||
export default ConvertEamIIDXCSV;
|
||||
|
||||
@@ -7,10 +7,10 @@ import { InternalFailure } from "../../../framework/common/converter-failures";
|
||||
import {
|
||||
ConverterIRFervidex,
|
||||
SplitFervidexChartRef,
|
||||
KtchifyAssist,
|
||||
KtchifyGauge,
|
||||
KtchifyRandom,
|
||||
KtchifyRange,
|
||||
TachifyAssist,
|
||||
TachifyGauge,
|
||||
TachifyRandom,
|
||||
TachifyRange,
|
||||
} from "./converter";
|
||||
import { FervidexScore } from "./types";
|
||||
import deepmerge from "deepmerge";
|
||||
@@ -37,47 +37,47 @@ t.test("#SplitFervidexChartRef", (t) => {
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("#KtchifyAssist", (t) => {
|
||||
t.equal(KtchifyAssist("ASCR_LEGACY"), "FULL ASSIST");
|
||||
t.equal(KtchifyAssist("AUTO_SCRATCH"), "AUTO SCRATCH");
|
||||
t.equal(KtchifyAssist("FULL_ASSIST"), "FULL ASSIST");
|
||||
t.equal(KtchifyAssist("LEGACY_NOTE"), "LEGACY NOTE");
|
||||
t.equal(KtchifyAssist(null), "NO ASSIST");
|
||||
t.equal(KtchifyAssist(undefined), "NO ASSIST");
|
||||
t.test("#TachifyAssist", (t) => {
|
||||
t.equal(TachifyAssist("ASCR_LEGACY"), "FULL ASSIST");
|
||||
t.equal(TachifyAssist("AUTO_SCRATCH"), "AUTO SCRATCH");
|
||||
t.equal(TachifyAssist("FULL_ASSIST"), "FULL ASSIST");
|
||||
t.equal(TachifyAssist("LEGACY_NOTE"), "LEGACY NOTE");
|
||||
t.equal(TachifyAssist(null), "NO ASSIST");
|
||||
t.equal(TachifyAssist(undefined), "NO ASSIST");
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("#KtchifyGauge", (t) => {
|
||||
t.equal(KtchifyGauge("ASSISTED_EASY"), "ASSISTED EASY");
|
||||
t.equal(KtchifyGauge("EASY"), "EASY");
|
||||
t.equal(KtchifyGauge("HARD"), "HARD");
|
||||
t.equal(KtchifyGauge("EX_HARD"), "EX HARD");
|
||||
t.equal(KtchifyGauge(null), "NORMAL");
|
||||
t.equal(KtchifyGauge(undefined), "NORMAL");
|
||||
t.test("#TachifyGauge", (t) => {
|
||||
t.equal(TachifyGauge("ASSISTED_EASY"), "ASSISTED EASY");
|
||||
t.equal(TachifyGauge("EASY"), "EASY");
|
||||
t.equal(TachifyGauge("HARD"), "HARD");
|
||||
t.equal(TachifyGauge("EX_HARD"), "EX HARD");
|
||||
t.equal(TachifyGauge(null), "NORMAL");
|
||||
t.equal(TachifyGauge(undefined), "NORMAL");
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("#KtchifyRange", (t) => {
|
||||
t.equal(KtchifyRange("HIDDEN_PLUS"), "HIDDEN+");
|
||||
t.equal(KtchifyRange("LIFT"), "LIFT");
|
||||
t.equal(KtchifyRange("LIFT_SUD_PLUS"), "LIFT SUD+");
|
||||
t.equal(KtchifyRange("SUDDEN_PLUS"), "SUDDEN+");
|
||||
t.equal(KtchifyRange("SUD_PLUS_HID_PLUS"), "SUD+ HID+");
|
||||
t.equal(KtchifyRange(null), "NONE");
|
||||
t.equal(KtchifyRange(undefined), "NONE");
|
||||
t.test("#TachifyRange", (t) => {
|
||||
t.equal(TachifyRange("HIDDEN_PLUS"), "HIDDEN+");
|
||||
t.equal(TachifyRange("LIFT"), "LIFT");
|
||||
t.equal(TachifyRange("LIFT_SUD_PLUS"), "LIFT SUD+");
|
||||
t.equal(TachifyRange("SUDDEN_PLUS"), "SUDDEN+");
|
||||
t.equal(TachifyRange("SUD_PLUS_HID_PLUS"), "SUD+ HID+");
|
||||
t.equal(TachifyRange(null), "NONE");
|
||||
t.equal(TachifyRange(undefined), "NONE");
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("#KtchifyRandom", (t) => {
|
||||
t.equal(KtchifyRandom("MIRROR"), "MIRROR");
|
||||
t.equal(KtchifyRandom("R_RANDOM"), "R-RANDOM");
|
||||
t.equal(KtchifyRandom("S_RANDOM"), "S-RANDOM");
|
||||
t.equal(KtchifyRandom("RANDOM"), "RANDOM");
|
||||
t.equal(KtchifyRandom(null), "NONRAN");
|
||||
t.equal(KtchifyRandom(undefined), "NONRAN");
|
||||
t.test("#TachifyRandom", (t) => {
|
||||
t.equal(TachifyRandom("MIRROR"), "MIRROR");
|
||||
t.equal(TachifyRandom("R_RANDOM"), "R-RANDOM");
|
||||
t.equal(TachifyRandom("S_RANDOM"), "S-RANDOM");
|
||||
t.equal(TachifyRandom("RANDOM"), "RANDOM");
|
||||
t.equal(TachifyRandom(null), "NONRAN");
|
||||
t.equal(TachifyRandom(undefined), "NONRAN");
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
@@ -25,7 +25,7 @@ export const FERVIDEX_LAMP_LOOKUP = {
|
||||
7: "FULL COMBO",
|
||||
};
|
||||
|
||||
export function KtchifyAssist(
|
||||
export function TachifyAssist(
|
||||
assist: FervidexScore["option"]["assist"]
|
||||
): DryScore<"iidx:SP" | "iidx:DP">["scoreMeta"]["assist"] {
|
||||
switch (assist) {
|
||||
@@ -43,7 +43,7 @@ export function KtchifyAssist(
|
||||
}
|
||||
}
|
||||
|
||||
export function KtchifyGauge(
|
||||
export function TachifyGauge(
|
||||
gauge: FervidexScore["option"]["gauge"]
|
||||
): DryScore<"iidx:SP" | "iidx:DP">["scoreMeta"]["gauge"] {
|
||||
switch (gauge) {
|
||||
@@ -61,7 +61,7 @@ export function KtchifyGauge(
|
||||
}
|
||||
}
|
||||
|
||||
export function KtchifyRange(
|
||||
export function TachifyRange(
|
||||
gauge: FervidexScore["option"]["range"]
|
||||
): DryScore<"iidx:SP" | "iidx:DP">["scoreMeta"]["range"] {
|
||||
switch (gauge) {
|
||||
@@ -81,7 +81,7 @@ export function KtchifyRange(
|
||||
}
|
||||
}
|
||||
|
||||
export function KtchifyRandom(
|
||||
export function TachifyRandom(
|
||||
gauge: FervidexScore["option"]["style"]
|
||||
): DryScore<"iidx:SP" | "iidx:DP">["scoreMeta"]["random"] {
|
||||
switch (gauge) {
|
||||
@@ -209,10 +209,10 @@ export const ConverterIRFervidex: ConverterFunction<FervidexScore, FervidexConte
|
||||
},
|
||||
},
|
||||
scoreMeta: {
|
||||
assist: KtchifyAssist(data.option.assist),
|
||||
gauge: KtchifyGauge(data.option.gauge),
|
||||
random: KtchifyRandom(data.option.style),
|
||||
range: KtchifyRange(data.option.range),
|
||||
assist: TachifyAssist(data.option.assist),
|
||||
gauge: TachifyGauge(data.option.gauge),
|
||||
random: TachifyRandom(data.option.style),
|
||||
range: TachifyRange(data.option.range),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
// barrel file for re-exporting env variables.
|
||||
import dotenv from "dotenv";
|
||||
import JSON5 from "json5";
|
||||
import fs from "fs";
|
||||
import p from "prudence";
|
||||
import { FormatPrError } from "../../utils/prudence";
|
||||
import { integer } from "tachi-common";
|
||||
|
||||
dotenv.config(); // imports things like NODE_ENV from a local .env file if one is present.
|
||||
|
||||
// reads from $pwd/conf.json5
|
||||
const confFile = fs.readFileSync("./conf.json5", "utf-8");
|
||||
|
||||
const config = JSON5.parse(confFile);
|
||||
|
||||
function isValidURL(self: unknown) {
|
||||
if (typeof self !== "string") {
|
||||
return `Expected URL, received type ${typeof self}`;
|
||||
}
|
||||
|
||||
try {
|
||||
new URL(self);
|
||||
return true;
|
||||
} catch (err) {
|
||||
return `Invalid URL ${self}.`;
|
||||
}
|
||||
}
|
||||
|
||||
export interface TachiConfig {
|
||||
MONGO_BASE_URL: string;
|
||||
LOG_LEVEL: "debug" | "verbose" | "info" | "warn" | "error" | "severe" | "crit";
|
||||
CAPTCHA_SECRET_KEY: string;
|
||||
SESSION_SECRET: string;
|
||||
FLO_API_URL: string;
|
||||
EAG_API_URL: string;
|
||||
ARC_API_URL: string;
|
||||
ARC_AUTH_TOKEN: string;
|
||||
CDN_ROOT: string;
|
||||
TYPE: "ktchi" | "btchi";
|
||||
PORT: integer;
|
||||
INFO: {
|
||||
NAME: string;
|
||||
};
|
||||
}
|
||||
|
||||
const err = p(config, {
|
||||
MONGO_BASE_URL: "string",
|
||||
LOG_LEVEL: p.isIn("debug", "verbose", "info", "warn", "error", "severe", "crit"),
|
||||
CAPTCHA_SECRET_KEY: "string",
|
||||
SESSION_SECRET: "string",
|
||||
FLO_API_URL: isValidURL,
|
||||
EAG_API_URL: isValidURL,
|
||||
ARC_API_URL: isValidURL,
|
||||
ARC_AUTH_TOKEN: "string",
|
||||
CDN_ROOT: "string",
|
||||
PORT: p.isPositiveInteger,
|
||||
TYPE: p.isIn("ktchi", "btchi"),
|
||||
});
|
||||
|
||||
if (err) {
|
||||
throw FormatPrError(err, "Invalid conf.json5 file.");
|
||||
}
|
||||
|
||||
const KTCHI_INFO: TachiConfig["INFO"] = {
|
||||
NAME: "Kamaitachi",
|
||||
};
|
||||
|
||||
const BTCHI_INFO: TachiConfig["INFO"] = {
|
||||
NAME: "Bokutachi",
|
||||
};
|
||||
|
||||
if (config.TYPE === "ktchi") {
|
||||
config.INFO = KTCHI_INFO;
|
||||
} else {
|
||||
config.INFO = BTCHI_INFO;
|
||||
}
|
||||
|
||||
const tachiConfig = config as TachiConfig;
|
||||
|
||||
export const MONGO_BASE_URL = tachiConfig.MONGO_BASE_URL;
|
||||
export const LOG_LEVEL = tachiConfig.LOG_LEVEL;
|
||||
export const SESSION_SECRET = tachiConfig.SESSION_SECRET;
|
||||
export const CAPTCHA_SECRET_KEY = tachiConfig.CAPTCHA_SECRET_KEY;
|
||||
export const FLO_API_URL = tachiConfig.FLO_API_URL;
|
||||
export const EAG_API_URL = tachiConfig.EAG_API_URL;
|
||||
export const ARC_API_URL = tachiConfig.ARC_API_URL;
|
||||
export const ARC_AUTH_TOKEN = tachiConfig.ARC_AUTH_TOKEN;
|
||||
export const KTCDN_ROOT = tachiConfig.CDN_ROOT;
|
||||
export const CONF_INFO = tachiConfig.INFO;
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import CreateLogCtx from "./lib/logger/logger";
|
||||
import server from "./server/server";
|
||||
import serverConfig from "./server/server-config";
|
||||
import { LOG_LEVEL } from "./lib/env/env";
|
||||
import { LOG_LEVEL } from "./lib/setup/config";
|
||||
import { FormatVersion } from "./lib/constants/version";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
@@ -6,7 +6,7 @@ t.test("#RequireLoggedIn", (t) => {
|
||||
t.test("Should reject users that are not logged in.", async (t) => {
|
||||
const { res } = await expMiddlewareMock(RequireLoggedIn, {
|
||||
session: {
|
||||
ktchi: null,
|
||||
tachi: null,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -23,7 +23,7 @@ t.test("#RequireLoggedIn", (t) => {
|
||||
t.test("Should allow users that are logged in.", async (t) => {
|
||||
const { res } = await expMiddlewareMock(RequireLoggedIn, {
|
||||
session: {
|
||||
ktchi: {
|
||||
tachi: {
|
||||
userID: 1,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@ import CreateLogCtx from "../../lib/logger/logger";
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
export function RequireLoggedIn(req: Request, res: Response, next: NextFunction) {
|
||||
if (!req.session.ktchi?.userID) {
|
||||
if (!req.session.tachi?.userID) {
|
||||
logger.info(`Received unauthorised request from ${req.ip} from ${req.originalUrl}`);
|
||||
|
||||
return res.status(401).json({
|
||||
|
||||
@@ -12,7 +12,7 @@ import { GetNextCounterValue } from "../../../../../utils/db";
|
||||
import CreateLogCtx from "../../../../../lib/logger/logger";
|
||||
import { FormatUserDoc } from "../../../../../utils/user";
|
||||
import nodeFetch from "../../../../../utils/fetch";
|
||||
import { CAPTCHA_SECRET_KEY } from "../../../../../lib/env/env";
|
||||
import { CAPTCHA_SECRET_KEY } from "../../../../../lib/setup/config";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ router.post("/status", RequireLoggedIn, (req, res) =>
|
||||
success: true,
|
||||
description: "Logged In.",
|
||||
body: {
|
||||
userID: req.session.ktchi!.userID,
|
||||
userID: req.session.tachi!.userID,
|
||||
},
|
||||
})
|
||||
);
|
||||
@@ -56,8 +56,8 @@ router.post(
|
||||
}
|
||||
),
|
||||
async (req, res) => {
|
||||
if (req.session.ktchi?.userID) {
|
||||
logger.info(`Dual log-in attempted from ${req.session.ktchi.userID}`);
|
||||
if (req.session.tachi?.userID) {
|
||||
logger.info(`Dual log-in attempted from ${req.session.tachi.userID}`);
|
||||
return res.status(409).json({
|
||||
success: false,
|
||||
description: `You are already logged in as someone.`,
|
||||
@@ -107,7 +107,7 @@ router.post(
|
||||
});
|
||||
}
|
||||
|
||||
req.session.ktchi = {
|
||||
req.session.tachi = {
|
||||
userID: requestedUser.id,
|
||||
};
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ router.post(
|
||||
const inputParser = (logger: KtLogger) =>
|
||||
ResolveFileUploadData(importType, req.file, req.body, logger);
|
||||
|
||||
const userDoc = await GetUserWithIDGuaranteed(req.session.ktchi!.userID);
|
||||
const userDoc = await GetUserWithIDGuaranteed(req.session.tachi!.userID);
|
||||
|
||||
// The <any, any> here is deliberate - TS picks the IIDX-CSV generic values
|
||||
// for this function call because it sees them first
|
||||
|
||||
@@ -11,7 +11,7 @@ const router: Router = Router({ mergeParams: true });
|
||||
* @name POST /ir/barbatos/score/submit
|
||||
*/
|
||||
router.post("/score/submit", RequireLoggedIn, async (req, res) => {
|
||||
const userDoc = await GetUserWithIDGuaranteed(req.session.ktchi!.userID);
|
||||
const userDoc = await GetUserWithIDGuaranteed(req.session.tachi!.userID);
|
||||
|
||||
const responseData = await ExpressWrappedScoreImportMain(
|
||||
userDoc,
|
||||
|
||||
@@ -2,14 +2,14 @@ import t from "tap";
|
||||
import { ValidateAuthToken, ValidateIRClientVersion } from "./auth";
|
||||
import expMiddlewareMock from "express-request-mock";
|
||||
import ResetDBState from "../../../../test-utils/resets";
|
||||
import { SYMBOL_KtchiData } from "../../../../lib/constants/ktchi";
|
||||
import { SYMBOL_TachiData } from "../../../../lib/constants/tachi";
|
||||
import { CloseAllConnections } from "../../../../test-utils/close-connections";
|
||||
|
||||
t.test("#ValidateIRClientVersion", (t) => {
|
||||
t.test("Should reject clients that are not supported", async (t) => {
|
||||
const { res } = await expMiddlewareMock(ValidateIRClientVersion, {
|
||||
headers: {
|
||||
"X-KtchiIR-Version": "1.2.0",
|
||||
"X-TachiIR-Version": "1.2.0",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@ t.test("#ValidateIRClientVersion", (t) => {
|
||||
|
||||
t.equal(res.statusCode, 400);
|
||||
t.equal(json.success, false);
|
||||
t.match(json.description, /Invalid KtchiIR client version/u);
|
||||
t.match(json.description, /Invalid TachiIR client version/u);
|
||||
|
||||
t.end();
|
||||
});
|
||||
@@ -29,7 +29,7 @@ t.test("#ValidateIRClientVersion", (t) => {
|
||||
|
||||
t.equal(res.statusCode, 400);
|
||||
t.equal(json.success, false);
|
||||
t.match(json.description, /Invalid KtchiIR client version/u);
|
||||
t.match(json.description, /Invalid TachiIR client version/u);
|
||||
|
||||
t.end();
|
||||
});
|
||||
@@ -37,7 +37,7 @@ t.test("#ValidateIRClientVersion", (t) => {
|
||||
t.test("Should accept 2.0.0", async (t) => {
|
||||
const { res } = await expMiddlewareMock(ValidateIRClientVersion, {
|
||||
headers: {
|
||||
"X-KtchiIR-Version": "2.0.0",
|
||||
"X-TachiIR-Version": "2.0.0",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -106,9 +106,9 @@ t.test("#ValidateAuthToken", (t) => {
|
||||
t.equal(res.statusCode, 200);
|
||||
|
||||
t.hasStrict(
|
||||
req[SYMBOL_KtchiData]?.beatorajaAuthDoc,
|
||||
req[SYMBOL_TachiData]?.beatorajaAuthDoc,
|
||||
{ token: "token", userID: 1 },
|
||||
"Should attach the authDoc to the request KtchiData"
|
||||
"Should attach the authDoc to the request TachiData"
|
||||
);
|
||||
|
||||
t.end();
|
||||
|
||||
@@ -2,7 +2,7 @@ import { GenericAuthDocument } from "tachi-common";
|
||||
import { RequestHandler } from "express";
|
||||
import db from "../../../../external/mongo/db";
|
||||
import { SplitAuthorizationHeader } from "../../../../utils/misc";
|
||||
import { AssignToReqKtchiData } from "../../../../utils/req-ktchi-data";
|
||||
import { AssignToReqTachiData } from "../../../../utils/req-tachi-data";
|
||||
|
||||
export const ValidateAuthToken: RequestHandler = async (req, res, next) => {
|
||||
const header = req.header("Authorization");
|
||||
@@ -34,18 +34,18 @@ export const ValidateAuthToken: RequestHandler = async (req, res, next) => {
|
||||
});
|
||||
}
|
||||
|
||||
AssignToReqKtchiData(req, { beatorajaAuthDoc });
|
||||
AssignToReqTachiData(req, { beatorajaAuthDoc });
|
||||
|
||||
return next();
|
||||
};
|
||||
|
||||
export const ValidateIRClientVersion: RequestHandler = (req, res, next) => {
|
||||
const header = req.header("X-KtchiIR-Version");
|
||||
const header = req.header("X-TachiIR-Version");
|
||||
|
||||
if (header !== "2.0.0") {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
description: "Invalid KtchiIR client version.",
|
||||
description: "Invalid TachiIR client version.",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import t from "tap";
|
||||
import db from "../../../../../external/mongo/db";
|
||||
import ResetDBState from "../../../../../test-utils/resets";
|
||||
import { GetKTDataJSON } from "../../../../../test-utils/test-data";
|
||||
import { KtchiPBScoreToBeatorajaFormat } from "./convert-scores";
|
||||
import { TachiPBScoreToBeatorajaFormat } from "./convert-scores";
|
||||
import { ScoreDocument, PBScoreDocument } from "tachi-common";
|
||||
import { Random20Hex } from "../../../../../utils/misc";
|
||||
import deepmerge from "deepmerge";
|
||||
@@ -25,7 +25,7 @@ const pbScore = {
|
||||
userID: 1,
|
||||
} as unknown as PBScoreDocument<"bms:7K" | "bms:14K">;
|
||||
|
||||
t.test("#KtchiPBScoreToBeatorajaFormat", (t) => {
|
||||
t.test("#TachiPBScoreToBeatorajaFormat", (t) => {
|
||||
t.beforeEach(ResetDBState);
|
||||
t.beforeEach(async () => {
|
||||
await db.scores.insert(
|
||||
@@ -48,7 +48,7 @@ t.test("#KtchiPBScoreToBeatorajaFormat", (t) => {
|
||||
});
|
||||
|
||||
t.test("Should convert score.", async (t) => {
|
||||
const res = await KtchiPBScoreToBeatorajaFormat(pbScore, gazerChart, 1);
|
||||
const res = await TachiPBScoreToBeatorajaFormat(pbScore, gazerChart, 1);
|
||||
|
||||
t.strictSame(
|
||||
res,
|
||||
@@ -73,7 +73,7 @@ t.test("#KtchiPBScoreToBeatorajaFormat", (t) => {
|
||||
});
|
||||
|
||||
t.test("Should emplace username if requestingUserID is not the pbscore owner", async (t) => {
|
||||
const res = await KtchiPBScoreToBeatorajaFormat(pbScore, gazerChart, 2);
|
||||
const res = await TachiPBScoreToBeatorajaFormat(pbScore, gazerChart, 2);
|
||||
|
||||
t.strictSame(
|
||||
res,
|
||||
@@ -110,7 +110,7 @@ t.test("#KtchiPBScoreToBeatorajaFormat", (t) => {
|
||||
},
|
||||
} as ScoreDocument);
|
||||
|
||||
const res = await KtchiPBScoreToBeatorajaFormat(pbScore, gazerChart, 2);
|
||||
const res = await TachiPBScoreToBeatorajaFormat(pbScore, gazerChart, 2);
|
||||
|
||||
t.strictSame(
|
||||
res,
|
||||
@@ -147,7 +147,7 @@ t.test("#KtchiPBScoreToBeatorajaFormat", (t) => {
|
||||
},
|
||||
} as ScoreDocument);
|
||||
|
||||
const res = await KtchiPBScoreToBeatorajaFormat(
|
||||
const res = await TachiPBScoreToBeatorajaFormat(
|
||||
deepmerge(pbScore, { playtype: "14K" }),
|
||||
gazerChart,
|
||||
2
|
||||
@@ -178,7 +178,7 @@ t.test("#KtchiPBScoreToBeatorajaFormat", (t) => {
|
||||
t.test("Should throw severe if no lampPB exists.", async (t) => {
|
||||
await db.scores.remove({ scoreID: "mock_lampPB" });
|
||||
|
||||
t.rejects(() => KtchiPBScoreToBeatorajaFormat(pbScore, gazerChart, 2), {
|
||||
t.rejects(() => TachiPBScoreToBeatorajaFormat(pbScore, gazerChart, 2), {
|
||||
message: /User 1's PB on.*has no lampPB/u,
|
||||
} as any);
|
||||
|
||||
|
||||
@@ -39,14 +39,14 @@ export type BeatorajaIRScoreFormat = BeatorajaPartialScoreFormat & BeatorajaScor
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
/**
|
||||
* Converts a Kamaitachi Score PB into the beatoraja IR format.
|
||||
* Converts a Tachi Score PB into the beatoraja IR format.
|
||||
* @param pbScore - The PB score to convert.
|
||||
* @param chart - The chart document the PB score belongs to.
|
||||
* @param requestingUserID - The user who requested this conversion. This is
|
||||
* because beatoraja uses the empty string to dictate that the score was from
|
||||
* the requesting user.
|
||||
*/
|
||||
export async function KtchiPBScoreToBeatorajaFormat(
|
||||
export async function TachiPBScoreToBeatorajaFormat(
|
||||
pbScore: PBScoreDocument<"bms:7K" | "bms:14K">,
|
||||
chart: ChartDocument<"bms:7K" | "bms:14K">,
|
||||
requestingUserID: integer
|
||||
@@ -67,7 +67,7 @@ export async function KtchiPBScoreToBeatorajaFormat(
|
||||
);
|
||||
}
|
||||
|
||||
return KtchiScoreDataToBeatorajaFormat(
|
||||
return TachiScoreDataToBeatorajaFormat(
|
||||
pbScore,
|
||||
chart.data.hashSHA256,
|
||||
username,
|
||||
@@ -79,7 +79,7 @@ export async function KtchiPBScoreToBeatorajaFormat(
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts various data from Kamaitachi to the beatoraja format.
|
||||
* Converts various data from Tachi to the beatoraja format.
|
||||
* @param pbScore - The users PB Score document for this chart.
|
||||
* @param sha256 - The SHA256 for this chart.
|
||||
* @param username - The users name. Beatoraja uses the special value "" to indicate the user is the current player.
|
||||
@@ -89,7 +89,7 @@ export async function KtchiPBScoreToBeatorajaFormat(
|
||||
* @param random - What random modifier was used.
|
||||
* @returns A Beatoraja Score Document.
|
||||
*/
|
||||
function KtchiScoreDataToBeatorajaFormat(
|
||||
function TachiScoreDataToBeatorajaFormat(
|
||||
pbScore: PBScoreDocument<"bms:7K" | "bms:14K">,
|
||||
sha256: string,
|
||||
username: string,
|
||||
|
||||
@@ -35,7 +35,7 @@ t.test("GET /ir/beatoraja/charts/:chartSHA256/scores", (t) => {
|
||||
|
||||
const res = await mockApi
|
||||
.get(`/ir/beatoraja/charts/${GAZER_SHA256}/scores`)
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token");
|
||||
|
||||
t.equal(res.status, 200);
|
||||
@@ -46,7 +46,7 @@ t.test("GET /ir/beatoraja/charts/:chartSHA256/scores", (t) => {
|
||||
t.test("Should return 404 if chart doesnt exist", async (t) => {
|
||||
const res = await mockApi
|
||||
.get(`/ir/beatoraja/charts/INVALID/scores`)
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token");
|
||||
|
||||
t.equal(res.status, 404);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { ChartDocument, PBScoreDocument } from "tachi-common";
|
||||
import { Router, RequestHandler } from "express";
|
||||
import db from "../../../../../external/mongo/db";
|
||||
import { SYMBOL_KtchiData } from "../../../../../lib/constants/ktchi";
|
||||
import { KtchiPBScoreToBeatorajaFormat } from "./convert-scores";
|
||||
import { AssignToReqKtchiData } from "../../../../../utils/req-ktchi-data";
|
||||
import { SYMBOL_TachiData } from "../../../../../lib/constants/tachi";
|
||||
import { TachiPBScoreToBeatorajaFormat } from "./convert-scores";
|
||||
import { AssignToReqTachiData } from "../../../../../utils/req-tachi-data";
|
||||
|
||||
const router: Router = Router({ mergeParams: true });
|
||||
|
||||
@@ -19,7 +19,7 @@ const GetChartDocument: RequestHandler = async (req, res, next) => {
|
||||
});
|
||||
}
|
||||
|
||||
AssignToReqKtchiData(req, { beatorajaChartDoc: chart });
|
||||
AssignToReqTachiData(req, { beatorajaChartDoc: chart });
|
||||
|
||||
return next();
|
||||
};
|
||||
@@ -31,7 +31,7 @@ router.use(GetChartDocument);
|
||||
* @name GET /ir/beatoraja/chart/:chartSHA256/scores
|
||||
*/
|
||||
router.get("/scores", async (req, res) => {
|
||||
const chart = req[SYMBOL_KtchiData]!.beatorajaChartDoc!;
|
||||
const chart = req[SYMBOL_TachiData]!.beatorajaChartDoc!;
|
||||
|
||||
const scores = (await db["score-pbs"].find({
|
||||
chartID: chart.chartID,
|
||||
@@ -41,7 +41,7 @@ router.get("/scores", async (req, res) => {
|
||||
// @optimisable - This should be solved with a couple queries and a hashmap.
|
||||
const beatorajaScores = await Promise.all(
|
||||
scores.map((e) =>
|
||||
KtchiPBScoreToBeatorajaFormat(e, chart, req[SYMBOL_KtchiData]!.beatorajaAuthDoc!.userID)
|
||||
TachiPBScoreToBeatorajaFormat(e, chart, req[SYMBOL_TachiData]!.beatorajaAuthDoc!.userID)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ t.test("POST /ir/beatoraja/login", (t) => {
|
||||
username: "test_zkldi",
|
||||
password: "password",
|
||||
})
|
||||
.set("X-KtchiIR-Version", "2.0.0");
|
||||
.set("X-TachiIR-Version", "2.0.0");
|
||||
|
||||
t.equal(res.status, 200);
|
||||
t.match(res.body.body.token, /^[0-9a-f]{40}$/u, "Should return a 20 byte long token.");
|
||||
@@ -31,7 +31,7 @@ t.test("POST /ir/beatoraja/login", (t) => {
|
||||
username: "test_zkldi",
|
||||
password: "invalid",
|
||||
})
|
||||
.set("X-KtchiIR-Version", "2.0.0");
|
||||
.set("X-TachiIR-Version", "2.0.0");
|
||||
|
||||
t.equal(res.status, 401);
|
||||
t.equal(res.body.success, false);
|
||||
@@ -40,14 +40,14 @@ t.test("POST /ir/beatoraja/login", (t) => {
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should reject X-KtchiIR-Versions", async (t) => {
|
||||
t.test("Should reject X-TachiIR-Versions", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/login")
|
||||
.send({
|
||||
username: "test_zkldi",
|
||||
password: "password",
|
||||
})
|
||||
.set("X-KtchiIR-Version", "1.2.0");
|
||||
.set("X-TachiIR-Version", "1.2.0");
|
||||
|
||||
t.equal(res.status, 400);
|
||||
t.equal(res.body.success, false);
|
||||
@@ -72,7 +72,7 @@ t.test("POST /ir/beatoraja/login", (t) => {
|
||||
username: "invalid",
|
||||
password: "password",
|
||||
})
|
||||
.set("X-KtchiIR-Version", "2.0.0");
|
||||
.set("X-TachiIR-Version", "2.0.0");
|
||||
|
||||
t.equal(res.status, 404);
|
||||
t.equal(res.body.success, false);
|
||||
@@ -85,7 +85,7 @@ t.test("POST /ir/beatoraja/login", (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/login")
|
||||
.send({})
|
||||
.set("X-KtchiIR-Version", "2.0.0");
|
||||
.set("X-TachiIR-Version", "2.0.0");
|
||||
|
||||
t.equal(res.status, 400);
|
||||
t.equal(res.body.success, false);
|
||||
@@ -97,7 +97,7 @@ t.test("POST /ir/beatoraja/login", (t) => {
|
||||
username: { $where: "for(;;){}" },
|
||||
password: 123,
|
||||
})
|
||||
.set("X-KtchiIR-Version", "2.0.0");
|
||||
.set("X-TachiIR-Version", "2.0.0");
|
||||
|
||||
t.equal(res2.status, 400);
|
||||
t.equal(res2.body.success, false);
|
||||
@@ -117,7 +117,7 @@ t.test("POST /ir/beatoraja/submit-score", (t) => {
|
||||
t.test("Should import a valid score.", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/submit-score")
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token")
|
||||
.send(scoreReq);
|
||||
|
||||
@@ -154,7 +154,7 @@ t.test("POST /ir/beatoraja/submit-score", (t) => {
|
||||
t.test("Should return an error if invalid client.", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/submit-score")
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token")
|
||||
.send(deepmerge(scoreReq, { client: "INVALID" }));
|
||||
|
||||
@@ -169,7 +169,7 @@ t.test("POST /ir/beatoraja/submit-score", (t) => {
|
||||
t.test("Should return an error if invalid score.", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/submit-score")
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token")
|
||||
.send(deepmerge(scoreReq, { score: { exscore: -1 } }));
|
||||
|
||||
@@ -184,7 +184,7 @@ t.test("POST /ir/beatoraja/submit-score", (t) => {
|
||||
t.test("Should return an error if invalid chart.", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/submit-score")
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token")
|
||||
.send(deepmerge(scoreReq, { chart: { title: null } }));
|
||||
|
||||
@@ -258,7 +258,7 @@ t.test("POST /ir/beatoraja/submit-course", (t) => {
|
||||
t.test("Should accept a valid clear", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/submit-course")
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token")
|
||||
.send(courseScore);
|
||||
|
||||
@@ -276,7 +276,7 @@ t.test("POST /ir/beatoraja/submit-course", (t) => {
|
||||
t.test("Should silently reject a fail", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/submit-course")
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token")
|
||||
.send(deepmerge(courseScore, { score: { clear: "Failed" } }));
|
||||
|
||||
@@ -290,7 +290,7 @@ t.test("POST /ir/beatoraja/submit-course", (t) => {
|
||||
t.test("Should reject scores with no charts", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/submit-course")
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token")
|
||||
.send(deepmerge(courseScore, { course: { charts: [] } }, { arrayMerge: (d, s) => s }));
|
||||
|
||||
@@ -304,7 +304,7 @@ t.test("POST /ir/beatoraja/submit-course", (t) => {
|
||||
t.test("Should reject scores with invalid chart documents", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/submit-course")
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token")
|
||||
.send(deepmerge(courseScore, { course: { charts: [1, 2, 3, 4] } }));
|
||||
|
||||
@@ -318,7 +318,7 @@ t.test("POST /ir/beatoraja/submit-course", (t) => {
|
||||
t.test("Should reject scores with too many chart documents", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/submit-course")
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token")
|
||||
.send(
|
||||
deepmerge(courseScore, {
|
||||
@@ -336,7 +336,7 @@ t.test("POST /ir/beatoraja/submit-course", (t) => {
|
||||
t.test("Should reject scores not on LN mode", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/submit-course")
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token")
|
||||
.send(
|
||||
deepmerge(courseScore, {
|
||||
@@ -356,7 +356,7 @@ t.test("POST /ir/beatoraja/submit-course", (t) => {
|
||||
t.test("Should reject too few constraints", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/submit-course")
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token")
|
||||
.send(
|
||||
deepmerge(
|
||||
@@ -380,7 +380,7 @@ t.test("POST /ir/beatoraja/submit-course", (t) => {
|
||||
t.test("Should reject non-array constraints", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/submit-course")
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token")
|
||||
.send(
|
||||
deepmerge(
|
||||
@@ -404,7 +404,7 @@ t.test("POST /ir/beatoraja/submit-course", (t) => {
|
||||
t.test("Should reject too many constraints", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/submit-course")
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token")
|
||||
.send(
|
||||
deepmerge(
|
||||
@@ -428,7 +428,7 @@ t.test("POST /ir/beatoraja/submit-course", (t) => {
|
||||
t.test("Should reject invalid constraints", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/submit-course")
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token")
|
||||
.send(
|
||||
deepmerge(
|
||||
@@ -452,7 +452,7 @@ t.test("POST /ir/beatoraja/submit-course", (t) => {
|
||||
t.test("Should reject invalid constraints for 3", async (t) => {
|
||||
const res = await mockApi
|
||||
.post("/ir/beatoraja/submit-course")
|
||||
.set("X-KtchiIR-Version", "2.0.0")
|
||||
.set("X-TachiIR-Version", "2.0.0")
|
||||
.set("Authorization", "Bearer token")
|
||||
.send(
|
||||
deepmerge(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Router } from "express";
|
||||
import db from "../../../../external/mongo/db";
|
||||
import { SYMBOL_KtchiData } from "../../../../lib/constants/ktchi";
|
||||
import { SYMBOL_TachiData } from "../../../../lib/constants/tachi";
|
||||
import CreateLogCtx, { KtLogger } from "../../../../lib/logger/logger";
|
||||
import { ExpressWrappedScoreImportMain } from "../../../../lib/score-import/framework/express-wrapper";
|
||||
import { ParseBeatorajaSingle } from "../../../../lib/score-import/import-types/ir/beatoraja/parser";
|
||||
@@ -77,7 +77,7 @@ router.use(ValidateAuthToken);
|
||||
* @name POST /ir/beatoraja/submit-score
|
||||
*/
|
||||
router.post("/submit-score", async (req, res) => {
|
||||
const userDoc = await GetUserWithIDGuaranteed(req[SYMBOL_KtchiData]!.beatorajaAuthDoc!.userID);
|
||||
const userDoc = await GetUserWithIDGuaranteed(req[SYMBOL_TachiData]!.beatorajaAuthDoc!.userID);
|
||||
|
||||
const ParserFunction = (logger: KtLogger) => ParseBeatorajaSingle(req.body, logger);
|
||||
|
||||
@@ -220,7 +220,7 @@ router.post("/submit-course", async (req, res) => {
|
||||
});
|
||||
}
|
||||
|
||||
const userID = req[SYMBOL_KtchiData]!.beatorajaAuthDoc!.userID;
|
||||
const userID = req[SYMBOL_TachiData]!.beatorajaAuthDoc!.userID;
|
||||
|
||||
const result = await UpdateClassIfGreater(
|
||||
userID,
|
||||
|
||||
@@ -11,7 +11,7 @@ const router: Router = Router({ mergeParams: true });
|
||||
* @name POST /ir/chunitachi/score/submit
|
||||
*/
|
||||
router.post("/import", RequireLoggedIn, async (req, res) => {
|
||||
const userDoc = await GetUserWithIDGuaranteed(req.session.ktchi!.userID);
|
||||
const userDoc = await GetUserWithIDGuaranteed(req.session.tachi!.userID);
|
||||
|
||||
if (req.body?.head?.game !== "chunithm") {
|
||||
return res.status(400).json({
|
||||
|
||||
@@ -11,7 +11,7 @@ const router: Router = Router({ mergeParams: true });
|
||||
* @name POST /ir/direct-manual/import
|
||||
*/
|
||||
router.post("/import", RequireLoggedIn, async (req, res) => {
|
||||
const userDoc = await GetUserWithIDGuaranteed(req.session.ktchi!.userID);
|
||||
const userDoc = await GetUserWithIDGuaranteed(req.session.tachi!.userID);
|
||||
|
||||
const intent = req.header("X-User-Intent");
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ const ValidateFervidexHeader: RequestHandler = (req, res, next) => {
|
||||
|
||||
if (!agent) {
|
||||
logger.debug(
|
||||
`Rejected fervidex client with no agent from user ${req.session.ktchi!.userID}.`
|
||||
`Rejected fervidex client with no agent from user ${req.session.tachi!.userID}.`
|
||||
);
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
@@ -30,7 +30,7 @@ const ValidateFervidexHeader: RequestHandler = (req, res, next) => {
|
||||
if (!agent.startsWith("fervidex/")) {
|
||||
logger.info(
|
||||
`Rejected fervidex client with invalid agent ${agent} from user ${
|
||||
req.session.ktchi!.userID
|
||||
req.session.tachi!.userID
|
||||
}.`
|
||||
);
|
||||
return res.status(400).json({
|
||||
@@ -44,7 +44,7 @@ const ValidateFervidexHeader: RequestHandler = (req, res, next) => {
|
||||
if (!versions.every((e) => !Number.isNaN(e))) {
|
||||
logger.info(
|
||||
`Rejected fervidex client with agent ${agent} for NaN-like versions from user ${
|
||||
req.session.ktchi!.userID
|
||||
req.session.tachi!.userID
|
||||
}.`
|
||||
);
|
||||
return res.status(400).json({
|
||||
@@ -55,7 +55,7 @@ const ValidateFervidexHeader: RequestHandler = (req, res, next) => {
|
||||
|
||||
// version.minor
|
||||
if (versions[1] < 3) {
|
||||
logger.debug(`Rejected outdated fervidex client from user ${req.session.ktchi!.userID}.`);
|
||||
logger.debug(`Rejected outdated fervidex client from user ${req.session.tachi!.userID}.`);
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
description: `Versions of fervidex < 1.3.0 are not supported.`,
|
||||
@@ -69,7 +69,7 @@ const RequireInf2ModelHeader: RequestHandler = (req, res, next) => {
|
||||
const swModel = req.header("X-Software-Model");
|
||||
|
||||
if (!swModel) {
|
||||
logger.debug(`Rejected empty X-Software-Model from user ${req.session.ktchi!.userID}.`);
|
||||
logger.debug(`Rejected empty X-Software-Model from user ${req.session.tachi!.userID}.`);
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
description: `Invalid X-Software-Model.`,
|
||||
@@ -80,7 +80,7 @@ const RequireInf2ModelHeader: RequestHandler = (req, res, next) => {
|
||||
const softID = ParseEA3SoftID(swModel);
|
||||
|
||||
if (softID.model !== MODEL_INFINITAS_2) {
|
||||
logger.debug(`Rejected non-inf2 model from user ${req.session.ktchi!.userID}.`);
|
||||
logger.debug(`Rejected non-inf2 model from user ${req.session.tachi!.userID}.`);
|
||||
return res.status(400).send({
|
||||
success: false,
|
||||
description: "This endpoint is only available for INF2 clients.",
|
||||
@@ -101,7 +101,7 @@ const ValidateModelHeader: RequestHandler = (req, res, next) => {
|
||||
const swModel = req.header("X-Software-Model");
|
||||
|
||||
if (!swModel) {
|
||||
logger.debug(`Rejected empty X-Software Model from user ${req.session.ktchi!.userID}.`);
|
||||
logger.debug(`Rejected empty X-Software Model from user ${req.session.tachi!.userID}.`);
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
description: `Invalid X-Software-Model.`,
|
||||
@@ -125,7 +125,7 @@ const ValidateModelHeader: RequestHandler = (req, res, next) => {
|
||||
if (softID.ext !== EXT_HEROIC_VERSE) {
|
||||
logger.info(
|
||||
`Rejected invalid Software Model ${softID.ext} from user ${
|
||||
req.session.ktchi!.userID
|
||||
req.session.tachi!.userID
|
||||
}.`
|
||||
);
|
||||
return res.status(400).json({
|
||||
@@ -155,7 +155,7 @@ router.use(RequireLoggedIn, ValidateFervidexHeader, ValidateModelHeader);
|
||||
* @name POST /ir/fervidex/profile/submit
|
||||
*/
|
||||
router.post("/profile/submit", RequireInf2ModelHeader, async (req, res) => {
|
||||
const userDoc = await GetUserWithIDGuaranteed(req.session.ktchi!.userID);
|
||||
const userDoc = await GetUserWithIDGuaranteed(req.session.tachi!.userID);
|
||||
|
||||
const headers = {
|
||||
// guaranteed to exist because of RequireInf2ModelHeader
|
||||
@@ -180,7 +180,7 @@ router.post("/profile/submit", RequireInf2ModelHeader, async (req, res) => {
|
||||
* @name POST /ir/fervidex/score/submit
|
||||
*/
|
||||
router.post("/score/submit", ValidateModelHeader, async (req, res) => {
|
||||
const userDoc = await GetUserWithIDGuaranteed(req.session.ktchi!.userID);
|
||||
const userDoc = await GetUserWithIDGuaranteed(req.session.tachi!.userID);
|
||||
|
||||
const model = req.header("X-Software-Model");
|
||||
|
||||
@@ -243,7 +243,7 @@ router.post("/class/submit", ValidateModelHeader, async (req, res) => {
|
||||
const playtype: Playtypes["iidx"] = req.body.play_style === 0 ? "SP" : "DP";
|
||||
|
||||
const r = await UpdateClassIfGreater(
|
||||
req.session.ktchi!.userID,
|
||||
req.session.tachi!.userID,
|
||||
"iidx",
|
||||
playtype,
|
||||
"dan",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Router, RequestHandler } from "express";
|
||||
import { FindChartOnSHA256 } from "../../../../utils/queries/charts";
|
||||
import { SYMBOL_KtchiData } from "../../../../lib/constants/ktchi";
|
||||
import { SYMBOL_TachiData } from "../../../../lib/constants/tachi";
|
||||
import db from "../../../../external/mongo/db";
|
||||
import {
|
||||
ChartDocument,
|
||||
@@ -10,13 +10,13 @@ import {
|
||||
} from "tachi-common";
|
||||
import { AssertStrAsPositiveNonZeroInt } from "../../../../lib/score-import/framework/common/string-asserts";
|
||||
import CreateLogCtx, { KtLogger } from "../../../../lib/logger/logger";
|
||||
import { CreatePOSTScoresResponseBody, KtchiScoreToServerScore } from "./usc";
|
||||
import { CreatePOSTScoresResponseBody, TachiScoreToServerScore } from "./usc";
|
||||
import { ExpressWrappedScoreImportMain } from "../../../../lib/score-import/framework/express-wrapper";
|
||||
import { GetUserWithID } from "../../../../utils/user";
|
||||
import { ParseIRUSC } from "../../../../lib/score-import/import-types/ir/usc/parser";
|
||||
import { USCIR_MAX_LEADERBOARD_N } from "../../../../lib/constants/usc-ir";
|
||||
import { CreateMulterSingleUploadMiddleware } from "../../../middleware/multer-upload";
|
||||
import { AssignToReqKtchiData } from "../../../../utils/req-ktchi-data";
|
||||
import { AssignToReqTachiData } from "../../../../utils/req-tachi-data";
|
||||
import { StoreCDN } from "../../../../lib/cdn/cdn";
|
||||
import { ONE_MEGABYTE } from "../../../../lib/constants/filesize";
|
||||
import crypto from "crypto";
|
||||
@@ -70,7 +70,7 @@ const ValidateUSCRequest: RequestHandler = async (req, res, next) => {
|
||||
});
|
||||
}
|
||||
|
||||
AssignToReqKtchiData(req, { uscAuthDoc });
|
||||
AssignToReqTachiData(req, { uscAuthDoc });
|
||||
|
||||
return next();
|
||||
};
|
||||
@@ -97,7 +97,7 @@ router.get("/", (req, res) =>
|
||||
const RetrieveChart: RequestHandler = async (req, res, next) => {
|
||||
const chart = await FindChartOnSHA256("usc", req.params.chartHash);
|
||||
|
||||
AssignToReqKtchiData(req, {
|
||||
AssignToReqTachiData(req, {
|
||||
uscChartDoc: (chart ?? undefined) as ChartDocument<"usc:Single"> | undefined,
|
||||
});
|
||||
|
||||
@@ -110,7 +110,7 @@ const RetrieveChart: RequestHandler = async (req, res, next) => {
|
||||
* @name GET /ir/usc/charts/:chartHash
|
||||
*/
|
||||
router.get("/charts/:chartHash", RetrieveChart, (req, res) => {
|
||||
const chart = req[SYMBOL_KtchiData]!.uscChartDoc;
|
||||
const chart = req[SYMBOL_TachiData]!.uscChartDoc;
|
||||
|
||||
if (!chart) {
|
||||
return res.status(200).json({
|
||||
@@ -131,7 +131,7 @@ router.get("/charts/:chartHash", RetrieveChart, (req, res) => {
|
||||
* @name GET /ir/usc/charts/:chartHash/record
|
||||
*/
|
||||
router.get("/charts/:chartHash/record", RetrieveChart, async (req, res) => {
|
||||
const chart = req[SYMBOL_KtchiData]!.uscChartDoc;
|
||||
const chart = req[SYMBOL_TachiData]!.uscChartDoc;
|
||||
|
||||
// spec ambigious here
|
||||
|
||||
@@ -154,7 +154,7 @@ router.get("/charts/:chartHash/record", RetrieveChart, async (req, res) => {
|
||||
});
|
||||
}
|
||||
|
||||
const serverScore = await KtchiScoreToServerScore(serverRecord);
|
||||
const serverScore = await TachiScoreToServerScore(serverRecord);
|
||||
|
||||
return res.status(200).json({
|
||||
statusCode: STATUS_CODES.SUCCESS,
|
||||
@@ -169,7 +169,7 @@ router.get("/charts/:chartHash/record", RetrieveChart, async (req, res) => {
|
||||
* @name GET /ir/usc/charts/:chartHash/leaderboard
|
||||
*/
|
||||
router.get("/charts/:chartHash/leaderboard", RetrieveChart, async (req, res) => {
|
||||
const chart = req[SYMBOL_KtchiData]!.uscChartDoc!;
|
||||
const chart = req[SYMBOL_TachiData]!.uscChartDoc!;
|
||||
|
||||
if (!(typeof req.query.mode === "string" && ["best", "rivals"].includes(req.query.mode))) {
|
||||
return res.status(200).json({
|
||||
@@ -221,7 +221,7 @@ router.get("/charts/:chartHash/leaderboard", RetrieveChart, async (req, res) =>
|
||||
}
|
||||
)) as PBScoreDocument<"usc:Single">[];
|
||||
|
||||
const serverScores = await Promise.all(bestScores.map(KtchiScoreToServerScore));
|
||||
const serverScores = await Promise.all(bestScores.map(TachiScoreToServerScore));
|
||||
|
||||
return res.status(200).json({
|
||||
statusCode: STATUS_CODES.SUCCESS,
|
||||
@@ -262,10 +262,10 @@ router.post("/scores", async (req, res) => {
|
||||
});
|
||||
}
|
||||
|
||||
const userDoc = await GetUserWithID(req[SYMBOL_KtchiData]!.uscAuthDoc!.userID);
|
||||
const userDoc = await GetUserWithID(req[SYMBOL_TachiData]!.uscAuthDoc!.userID);
|
||||
|
||||
if (!userDoc) {
|
||||
logger.severe(`User ${req[SYMBOL_KtchiData]!.uscAuthDoc!.userID} as no parent userDoc?`);
|
||||
logger.severe(`User ${req[SYMBOL_TachiData]!.uscAuthDoc!.userID} as no parent userDoc?`);
|
||||
return res.status(200).json({
|
||||
statusCode: STATUS_CODES.SERVER_ERROR,
|
||||
description: "An internal server error has occured.",
|
||||
@@ -334,7 +334,7 @@ router.post(
|
||||
}
|
||||
|
||||
const correspondingScore = await db.scores.findOne({
|
||||
userID: req[SYMBOL_KtchiData]!.uscAuthDoc!.userID,
|
||||
userID: req[SYMBOL_TachiData]!.uscAuthDoc!.userID,
|
||||
game: "usc",
|
||||
scoreID: req.body.identifier,
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import t from "tap";
|
||||
import db from "../../../../external/mongo/db";
|
||||
import ResetDBState from "../../../../test-utils/resets";
|
||||
import { CreatePOSTScoresResponseBody, KtchiScoreToServerScore } from "./usc";
|
||||
import { CreatePOSTScoresResponseBody, TachiScoreToServerScore } from "./usc";
|
||||
import { ChartDocument, PBScoreDocument, ScoreDocument } from "tachi-common";
|
||||
import deepmerge from "deepmerge";
|
||||
import { CloseAllConnections } from "../../../../test-utils/close-connections";
|
||||
@@ -51,13 +51,13 @@ const mockScoreDocument = {
|
||||
},
|
||||
} as ScoreDocument;
|
||||
|
||||
t.test("#KtchiScoreToServerScore", (t) => {
|
||||
t.test("#TachiScoreToServerScore", (t) => {
|
||||
t.beforeEach(ResetDBState);
|
||||
|
||||
t.test("Should correctly convert a ktchiScore to a serverScore", async (t) => {
|
||||
t.test("Should correctly convert a tachiScore to a serverScore", async (t) => {
|
||||
await db.scores.insert(mockScoreDocument as ScoreDocument);
|
||||
|
||||
const res = await KtchiScoreToServerScore(mockScorePB);
|
||||
const res = await TachiScoreToServerScore(mockScorePB);
|
||||
|
||||
t.strictSame(
|
||||
res,
|
||||
@@ -82,7 +82,7 @@ t.test("#KtchiScoreToServerScore", (t) => {
|
||||
t.test("Should work for timestamped scores", async (t) => {
|
||||
await db.scores.insert(mockScoreDocument);
|
||||
|
||||
const res = await KtchiScoreToServerScore(
|
||||
const res = await TachiScoreToServerScore(
|
||||
deepmerge(mockScorePB, { timeAchieved: 1_621_844_762_995 })
|
||||
);
|
||||
|
||||
@@ -107,7 +107,7 @@ t.test("#KtchiScoreToServerScore", (t) => {
|
||||
});
|
||||
|
||||
t.test("Should throw if user document does not exist.", (t) => {
|
||||
t.rejects(() => KtchiScoreToServerScore(deepmerge(mockScorePB, { userID: 2 } as any)), {
|
||||
t.rejects(() => TachiScoreToServerScore(deepmerge(mockScorePB, { userID: 2 } as any)), {
|
||||
message: /User 2 from PB on chart.*has no user document\?/u,
|
||||
} as any);
|
||||
|
||||
@@ -115,7 +115,7 @@ t.test("#KtchiScoreToServerScore", (t) => {
|
||||
});
|
||||
|
||||
t.test("Should throw if scorePB document does not exist.", (t) => {
|
||||
t.rejects(() => KtchiScoreToServerScore(mockScorePB), {
|
||||
t.rejects(() => TachiScoreToServerScore(mockScorePB), {
|
||||
message:
|
||||
/Score USC_EXAMPLE_SCORE_PB_ID does not exist, but is referenced in 1's PBDoc on/u,
|
||||
} as any);
|
||||
|
||||
@@ -26,15 +26,15 @@ export const KT_LAMP_TO_USC: Record<
|
||||
* returns sentinel values in the case that certain
|
||||
* fields are null.
|
||||
*/
|
||||
export async function KtchiScoreToServerScore(
|
||||
ktchiScore: PBScoreDocument<"usc:Single">
|
||||
export async function TachiScoreToServerScore(
|
||||
tachiScore: PBScoreDocument<"usc:Single">
|
||||
): Promise<USCServerScore> {
|
||||
// @optimisable
|
||||
// Repeated calls to this may pre-emptively provide usernames
|
||||
// and score PBs.
|
||||
const userDoc = await db.users.findOne(
|
||||
{
|
||||
id: ktchiScore.userID,
|
||||
id: tachiScore.userID,
|
||||
},
|
||||
{
|
||||
projection: {
|
||||
@@ -45,35 +45,35 @@ export async function KtchiScoreToServerScore(
|
||||
|
||||
if (!userDoc) {
|
||||
logger.severe(
|
||||
`User ${ktchiScore.userID} from PB on chart ${ktchiScore.chartID} has no user document?`
|
||||
`User ${tachiScore.userID} from PB on chart ${tachiScore.chartID} has no user document?`
|
||||
);
|
||||
throw new Error(
|
||||
`User ${ktchiScore.userID} from PB on chart ${ktchiScore.chartID} has no user document?`
|
||||
`User ${tachiScore.userID} from PB on chart ${tachiScore.chartID} has no user document?`
|
||||
);
|
||||
}
|
||||
|
||||
const scorePB = (await db.scores.findOne({
|
||||
scoreID: ktchiScore.composedFrom.scorePB,
|
||||
scoreID: tachiScore.composedFrom.scorePB,
|
||||
})) as ScoreDocument<"usc:Single"> | null;
|
||||
|
||||
if (!scorePB) {
|
||||
logger.severe(
|
||||
`Score ${ktchiScore.composedFrom.scorePB} does not exist, but is referenced in ${ktchiScore.userID}'s PBDoc on ${ktchiScore.chartID}?`
|
||||
`Score ${tachiScore.composedFrom.scorePB} does not exist, but is referenced in ${tachiScore.userID}'s PBDoc on ${tachiScore.chartID}?`
|
||||
);
|
||||
|
||||
throw new Error(
|
||||
`Score ${ktchiScore.composedFrom.scorePB} does not exist, but is referenced in ${ktchiScore.userID}'s PBDoc on ${ktchiScore.chartID}?`
|
||||
`Score ${tachiScore.composedFrom.scorePB} does not exist, but is referenced in ${tachiScore.userID}'s PBDoc on ${tachiScore.chartID}?`
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
score: ktchiScore.scoreData.score,
|
||||
timestamp: MStoS(ktchiScore.timeAchieved ?? 0),
|
||||
crit: ktchiScore.scoreData.hitData.critical ?? 0,
|
||||
near: ktchiScore.scoreData.hitData.near ?? 0,
|
||||
error: ktchiScore.scoreData.hitData.miss ?? 0,
|
||||
ranking: ktchiScore.rankingData.rank,
|
||||
lamp: KT_LAMP_TO_USC[ktchiScore.scoreData.lamp],
|
||||
score: tachiScore.scoreData.score,
|
||||
timestamp: MStoS(tachiScore.timeAchieved ?? 0),
|
||||
crit: tachiScore.scoreData.hitData.critical ?? 0,
|
||||
near: tachiScore.scoreData.hitData.near ?? 0,
|
||||
error: tachiScore.scoreData.hitData.miss ?? 0,
|
||||
ranking: tachiScore.rankingData.rank,
|
||||
lamp: KT_LAMP_TO_USC[tachiScore.scoreData.lamp],
|
||||
username: userDoc.username,
|
||||
noteMod: scorePB.scoreMeta.noteMod ?? "NORMAL",
|
||||
gaugeMod: scorePB.scoreMeta.gaugeMod ?? "NORMAL",
|
||||
@@ -162,10 +162,10 @@ export async function CreatePOSTScoresResponseBody(
|
||||
)) as PBScoreDocument<"usc:Single">[];
|
||||
|
||||
const [score, serverRecord, adjacentAbove, adjacentBelow] = await Promise.all([
|
||||
KtchiScoreToServerScore(scorePB),
|
||||
KtchiScoreToServerScore(ktServerRecord),
|
||||
Promise.all(adjAbove.map(KtchiScoreToServerScore)),
|
||||
Promise.all(adjBelow.map(KtchiScoreToServerScore)),
|
||||
TachiScoreToServerScore(scorePB),
|
||||
TachiScoreToServerScore(ktServerRecord),
|
||||
Promise.all(adjAbove.map(TachiScoreToServerScore)),
|
||||
Promise.all(adjBelow.map(TachiScoreToServerScore)),
|
||||
]);
|
||||
|
||||
const originalScore = (await db.scores.findOne({
|
||||
|
||||
@@ -4,7 +4,7 @@ import CreateLogCtx from "../lib/logger/logger";
|
||||
import expressSession from "express-session";
|
||||
import { integer } from "tachi-common";
|
||||
import { RedisClient } from "../external/redis/redis";
|
||||
import { SESSION_SECRET } from "../lib/env/env";
|
||||
import { SESSION_SECRET } from "../lib/setup/config";
|
||||
import connectRedis from "connect-redis";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
@@ -7,7 +7,7 @@ import path from "path";
|
||||
import CreateLogCtx from "../lib/logger/logger";
|
||||
// im installing an entire library for rm rf...
|
||||
import rimraf from "rimraf";
|
||||
import { KTCDN_ROOT } from "../lib/env/env";
|
||||
import { KTCDN_ROOT } from "../lib/setup/config";
|
||||
|
||||
const logger = CreateLogCtx(__filename);
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import { SYMBOL_KtchiData } from "../lib/constants/ktchi";
|
||||
import { Request } from "express";
|
||||
import { KtchiRequestData } from "./types";
|
||||
import deepmerge from "deepmerge";
|
||||
|
||||
export function AssignToReqKtchiData(req: Request, data: Partial<KtchiRequestData>) {
|
||||
if (!req[SYMBOL_KtchiData]) {
|
||||
req[SYMBOL_KtchiData] = data;
|
||||
} else {
|
||||
req[SYMBOL_KtchiData] = deepmerge(req[SYMBOL_KtchiData]!, data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { SYMBOL_TachiData } from "../lib/constants/tachi";
|
||||
import { Request } from "express";
|
||||
import { TachiRequestData } from "./types";
|
||||
import deepmerge from "deepmerge";
|
||||
|
||||
export function AssignToReqTachiData(req: Request, data: Partial<TachiRequestData>) {
|
||||
if (!req[SYMBOL_TachiData]) {
|
||||
req[SYMBOL_TachiData] = data;
|
||||
} else {
|
||||
req[SYMBOL_TachiData] = deepmerge(req[SYMBOL_TachiData]!, data);
|
||||
}
|
||||
}
|
||||
@@ -3,26 +3,26 @@ import { integer, GenericAuthDocument, ChartDocument } from "tachi-common";
|
||||
declare module "express-session" {
|
||||
// Inject additional properties on express-session
|
||||
interface SessionData {
|
||||
ktchi: KtchiSessionData;
|
||||
tachi: TachiSessionData;
|
||||
}
|
||||
}
|
||||
|
||||
export interface KtchiSessionData {
|
||||
export interface TachiSessionData {
|
||||
userID: integer;
|
||||
}
|
||||
|
||||
export interface KTFailResponse {
|
||||
export interface TachiAPIFailResponse {
|
||||
success: false;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export interface KTSuccessResponse {
|
||||
export interface TachiAPISuccessResponse {
|
||||
success: true;
|
||||
description: string;
|
||||
body: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export type KTReponse = KTFailResponse | KTSuccessResponse;
|
||||
export type TachiAPIReponse = TachiAPIFailResponse | TachiAPISuccessResponse;
|
||||
|
||||
/**
|
||||
* Clarity type for empty objects - such as in context.
|
||||
@@ -30,9 +30,9 @@ export type KTReponse = KTFailResponse | KTSuccessResponse;
|
||||
export type EmptyObject = Record<string, never>;
|
||||
|
||||
/**
|
||||
* Data that may be monkey-patched onto req.ktchi. This holds things such as middleware results.
|
||||
* Data that may be monkey-patched onto req.tachi. This holds things such as middleware results.
|
||||
*/
|
||||
export interface KtchiRequestData {
|
||||
export interface TachiRequestData {
|
||||
uscAuthDoc?: GenericAuthDocument;
|
||||
uscChartDoc?: ChartDocument<"usc:Single">;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user