diff --git a/server/src/external/mongo/schemas.ts b/server/src/external/mongo/schemas.ts index d3e8fe286..4b9bd73a6 100644 --- a/server/src/external/mongo/schemas.ts +++ b/server/src/external/mongo/schemas.ts @@ -12,7 +12,7 @@ import { import { allIDStrings, allImportTypes } from "tachi-common/js/config/static-config"; import { IsValidGame, IsValidPlaytype } from "utils/misc"; import { optNull } from "utils/prudence"; -import { Databases } from "./db"; +import { StaticDatabases } from "./db"; // The idea of this file is to export a function for every database // that will validate that collection. @@ -133,59 +133,6 @@ const GetHitMeta = (game: Game): PrudenceSchema => { const PR_Random = p.isIn("NONRAN", "RANDOM", "R-RANDOM", "S-RANDOM", "MIRROR"); -const getPlaytype = (game: Game, self: unknown): Playtypes[Game] => { - if (!self || typeof self !== "object") { - throw new Error("Expected an object."); - } - - const gameConfig = GetGameConfig(game); - - const s = self as Record; - - const playtype = s.playtype as string; - if (!IsValidPlaytype(game, playtype)) { - throw new Error(`Expected any of ${gameConfig.validPlaytypes.join(", ")}`); - } - - return playtype; -}; - -const PR_SongDocument = (data: PrudenceSchema): PrudenceSchema => ({ - id: p.isPositiveInteger, - title: "string", - artist: "string", - searchTerms: ["string"], - altTitles: ["string"], - data, -}); - -const PR_ChartDocument = ( - game: Game, - playtype: Playtypes[Game], - data: PrudenceSchema -): PrudenceSchema => { - const gptConfig = GetGamePTConfig(game, playtype); - - return { - songID: p.isPositiveInteger, - chartID: "string", - rgcID: "?string", - level: "string", - levelNum: "number", - isPrimary: "boolean", - difficulty: p.isIn(gptConfig.difficulties), - playtype: p.is(playtype), - data, - tierlistInfo: Object.fromEntries( - gptConfig.tierlists.map((t) => [ - t, - p.optional({ text: "string", value: "number", individualDifference: "*boolean" }), - ]) - ), - versions: [p.isIn(gptConfig.supportedVersions)], - }; -}; - const GetScoreMeta = (game: Game, playtype: Playtypes[Game]): PrudenceSchema => { if (game === "iidx" && playtype === "SP") { return { @@ -231,7 +178,10 @@ const GetScoreMeta = (game: Game, playtype: Playtypes[Game]): PrudenceSchema => return {}; }; -export const DatabaseSchemas: Record = { +export const DatabaseSchemas: Record< + Exclude, + ValidatorFunction +> = { users: prSchemaify({ username: p.regex(/^[a-zA-Z_-][a-zA-Z0-9_-]{2,20}$/u), usernameLowercase: (self, parent) => self === (parent.username as string).toLowerCase(), @@ -281,28 +231,6 @@ export const DatabaseSchemas: Record = { accountID: "string", forImportType: p.isIn("api/arc-iidx", "api/arc-sdvx"), }), - "bms-course-lookup": prSchemaify({ - title: "string", - // Must be comprised of 4 md5 hashes, which are 32 chars long. - md5sums: (self) => { - if (typeof self !== "string") { - return "Expected a string"; - } - - if (self.length !== 32 * 4) { - return "Expected 32 * 4 characters (4 md5 hashes long)."; - } - - if (!self.match(/^[a-z0-9]*$/u)) { - return "Expected all chars to be in the range of a-z0-9."; - } - - return true; - }, - set: p.isIn("genocideDan", "stslDan"), - playtype: p.isIn("7K", "14K"), - value: p.isInteger, - }), "class-achievements": prSchemaify({ game: p.isIn(games), playtype: isValidPlaytype, @@ -492,36 +420,6 @@ export const DatabaseSchemas: Record = { counterName: "string", value: p.isPositiveInteger, }), - folders: prSchemaify({ - title: "string", - game: p.isIn(games), - playtype: isValidPlaytype, - folderID: "string", - inactive: "boolean", - searchTerms: ["string"], - type: p.isIn("songs", "charts", "static"), - data: (self, parent) => { - if (parent.type === "songs") { - return true; //temp. should be a song. - } else if (parent.type === "charts") { - return true; //temp. should be a chart. - } - - return ( - (Array.isArray(self) && self.every((r) => typeof r === "string")) || - "Expected an array of only strings." - ); - }, - }), - tables: prSchemaify({ - tableID: "string", - game: p.isIn(games), - playtype: isValidPlaytype, - title: "string", - description: "string", - folders: ["string"], - inactive: "boolean", - }), "user-settings": prSchemaify({ userID: p.isPositiveNonZeroInteger, preferences: { @@ -718,197 +616,6 @@ export const DatabaseSchemas: Record = { ), })(self); }, - "songs-bms": prSchemaify( - PR_SongDocument({ - genre: "?string", - subtitle: "?string", - subartist: "?string", - }) - ), - "songs-chunithm": prSchemaify( - PR_SongDocument({ - genre: "string", - displayVersion: "string", - }) - ), - "songs-ddr": prSchemaify( - PR_SongDocument({ - displayVersion: "string", - }) - ), - "songs-sdvx": prSchemaify( - PR_SongDocument({ - displayVersion: "string", - }) - ), - "songs-usc": prSchemaify(PR_SongDocument({})), - "songs-maimai": prSchemaify( - PR_SongDocument({ - titleJP: "string", - artistJP: "string", - displayVersion: "string", - }) - ), - "songs-museca": prSchemaify( - PR_SongDocument({ - titleJP: "string", - artistJP: "string", - displayVersion: "string", - }) - ), - "songs-gitadora": prSchemaify( - PR_SongDocument({ - isHot: "boolean", - }) - ), - "songs-iidx": prSchemaify( - PR_SongDocument({ - genre: "string", - displayVersion: "string", - }) - ), - "songs-wacca": prSchemaify( - PR_SongDocument({ - genre: "string", - displayVersion: "?string", - }) - ), - "songs-pms": prSchemaify( - PR_SongDocument({ - genre: "?string", - subtitle: "?string", - subartist: "?string", - }) - ), - "songs-popn": prSchemaify( - PR_SongDocument({ - genre: "string", - displayVersion: "?string", - }) - ), - "songs-jubeat": prSchemaify( - PR_SongDocument({ - displayVersion: "string", - }) - ), - "charts-iidx": (self) => { - const playtype = getPlaytype("iidx", self); - - return prSchemaify( - PR_ChartDocument("iidx", playtype, { - notecount: p.isPositiveNonZeroInteger, - inGameID: p.or(p.isPositiveNonZeroInteger, [p.isPositiveNonZeroInteger]), - arcChartID: "?string", - hashSHA256: "?string", - "2dxtraSet": "?string", - kaidenAverage: "?number", - worldRecord: "?number", - bpiCoefficient: "?number", - }) - )(self); - }, - "charts-bms": (self) => { - const playtype = getPlaytype("bms", self); - - return prSchemaify( - PR_ChartDocument("bms", playtype, { - notecount: p.isPositiveNonZeroInteger, - hashSHA256: "?string", - hashMD5: "?string", - tableFolders: [ - { - table: "string", - level: "string", - }, - ], - }) - )(self); - }, - "charts-chunithm": prSchemaify( - PR_ChartDocument("chunithm", "Single", { - inGameID: p.isPositiveInteger, - }) - ), - "charts-jubeat": prSchemaify( - PR_ChartDocument("jubeat", "Single", { - inGameID: p.isPositiveInteger, - isHardMode: "boolean", - }) - ), - "charts-gitadora": (self) => { - const playtype = getPlaytype("gitadora", self); - - return prSchemaify( - PR_ChartDocument("gitadora", playtype, { - inGameID: p.isPositiveInteger, - }) - )(self); - }, - "charts-ddr": (self) => { - const playtype = getPlaytype("ddr", self); - - return prSchemaify( - PR_ChartDocument("ddr", playtype, { - inGameID: "string", - songHash: "string", - }) - )(self); - }, - "charts-maimai": prSchemaify( - PR_ChartDocument("maimai", "Single", { - maxPercent: p.gt(0), - inGameID: p.isPositiveInteger, - inGameStrID: "string", - }) - ), - "charts-museca": prSchemaify( - PR_ChartDocument("museca", "Single", { - inGameID: p.isPositiveInteger, - }) - ), - "charts-sdvx": prSchemaify( - PR_ChartDocument("sdvx", "Single", { - inGameID: p.isPositiveInteger, - arcChartID: "?string", - }) - ), - "charts-usc": (self) => { - const playtype = getPlaytype("usc", self); - - return prSchemaify( - PR_ChartDocument("usc", playtype, { - hashSHA1: p.or("string", ["string"]), - isOfficial: "boolean", - }) - )(self); - }, - "charts-wacca": prSchemaify( - PR_ChartDocument("wacca", "Single", { - isHot: "boolean", - }) - ), - "charts-pms": (self) => { - const playtype = getPlaytype("pms", self); - - return prSchemaify( - PR_ChartDocument("pms", playtype, { - notecount: p.isPositiveNonZeroInteger, - hashSHA256: "?string", - hashMD5: "?string", - tableFolders: [ - { - table: "string", - level: "string", - }, - ], - }) - )(self); - }, - "charts-popn": prSchemaify( - PR_ChartDocument("popn", "9B", { - hashSHA256: "?string", - }) - ), goals: prSchemaify({ game: p.isIn(games), playtype: isValidPlaytype,