diff --git a/server/src/lib/jobs/bms-table-sync.ts b/server/src/lib/jobs/bms-table-sync.ts index 6997dcc34..2bb36c377 100644 --- a/server/src/lib/jobs/bms-table-sync.ts +++ b/server/src/lib/jobs/bms-table-sync.ts @@ -2,30 +2,43 @@ import { LoadBMSTable } from "bms-table-loader"; import db from "external/mongo/db"; import CreateLogCtx from "lib/logger/logger"; +import { DeorphanIfInQueue } from "lib/orphan-queue/orphan-queue"; import { BMS_TABLES } from "tachi-common"; -import { CreateFolderID, InitaliseFolderChartLookup } from "utils/folder"; +import { InitaliseFolderChartLookup } from "utils/folder"; import { FormatBMSTables } from "utils/misc"; import type { BMSTableEntry } from "bms-table-loader"; import type { BMSTableInfo, ChartDocument } from "tachi-common"; const logger = CreateLogCtx(__filename); -async function ImportTableLevels(tableJSON: Array, prefix: string) { +async function ImportTableLevels( + tableJSON: Array, + prefix: string, + playtype: "7K" | "14K" +) { let failures = 0; let success = 0; const total = tableJSON.length; for (const td of tableJSON) { - const chart = (await db.charts.bms.findOne({ "data.hashMD5": td.md5 })) as ChartDocument< + let chart = (await db.charts.bms.findOne({ "data.hashMD5": td.md5 })) as ChartDocument< "bms:7K" | "bms:14K" > | null; if (!chart) { - logger.warn( - `No chart exists in table for ${td.md5} Possible title: ${td.title} ${prefix}${td.level}` - ); - failures++; - continue; + // didn't find it in the DB? + // try and find it in the BMS orphan-queue + chart = await DeorphanIfInQueue(`bms:${playtype}`, "bms", { + "chartDoc.data.hashMD5": td.md5, + }); + + if (!chart) { + logger.warn( + `No chart exists in table for ${td.md5} Possible title: ${td.title} ${prefix}${td.level}` + ); + failures++; + continue; + } } const tableFolders = chart.data.tableFolders.filter((e) => e.table !== prefix); @@ -65,7 +78,7 @@ export async function UpdateTable(tableInfo: BMSTableInfo) { const table = await LoadBMSTable(tableInfo.url); logger.info(`Bumping levels...`); - await ImportTableLevels(table.body, tableInfo.prefix); + await ImportTableLevels(table.body, tableInfo.prefix, tableInfo.playtype); logger.info(`Levels bumped.`); } diff --git a/server/src/lib/orphan-queue/orphan-queue.ts b/server/src/lib/orphan-queue/orphan-queue.ts index c75c0abae..6e6670986 100644 --- a/server/src/lib/orphan-queue/orphan-queue.ts +++ b/server/src/lib/orphan-queue/orphan-queue.ts @@ -3,6 +3,7 @@ import CreateLogCtx from "lib/logger/logger"; import { GetNextCounterValue } from "utils/db"; import { DedupeArr } from "utils/misc"; import type { FilterQuery } from "mongodb"; +import type { WithID } from "monk"; import type { ChartDocument, IDStrings, @@ -103,3 +104,44 @@ export async function HandleOrphanQueue( return null; } + +/** + * Forcefully deorphan a song/chart if it's in the queue and matches this criteria. + * + * Useful for something like BMS-Table-Sync, where we want to load anything in a table + * regardless of how many people have played the chart. + */ +export async function DeorphanIfInQueue( + idString: I, + game: IDStringToGame[I], + orphanMatchCriteria: FilterQuery> +): Promise | null> { + const orphanChart = (await db["orphan-chart-queue"].findOne( + { idString, ...orphanMatchCriteria }, + { + projectID: true, + } + )) as WithID> | null; + + if (!orphanChart) { + return null; + } + + const { songDoc, chartDoc } = orphanChart; + + logger.info(`Song ${songDoc.title} was unorphaned forcefully.`); + const songID = await GetNextCounterValue(`${game}-song-id`); + + logger.verbose(`${songDoc.title} has been assigned songID ${songID}.`); + + songDoc.id = songID; + chartDoc.songID = songID; + + await db.songs[game].insert(songDoc); + await db.charts[game].insert(chartDoc); + await db["orphan-chart-queue"].remove({ + _id: orphanChart._id, + }); + + return chartDoc; +}