diff --git a/server/src/core/auth-core.ts b/server/src/core/auth-core.ts index 981b9fcf4..8caf633e3 100644 --- a/server/src/core/auth-core.ts +++ b/server/src/core/auth-core.ts @@ -9,10 +9,10 @@ import { import db from "../db"; import { GetNextCounterValue } from "./db-core"; import { InsertResult } from "monk"; -import createLogCtx from "../logger"; +import CreateLogCtx from "../logger"; import { FormatUserDoc } from "./user-core"; -const logger = createLogCtx("auth-core.ts"); +const logger = CreateLogCtx("auth-core.ts"); const BCRYPT_SALT_ROUNDS = 12; diff --git a/server/src/core/captcha-core.ts b/server/src/core/captcha-core.ts index b305c996f..cdecf3862 100644 --- a/server/src/core/captcha-core.ts +++ b/server/src/core/captcha-core.ts @@ -1,8 +1,8 @@ import nodeFetch from "../fetch"; -import createLogCtx from "../logger"; +import CreateLogCtx from "../logger"; import { CAPTCHA_SECRET_KEY } from "../secrets"; -const logger = createLogCtx("captcha-core.ts"); +const logger = CreateLogCtx("captcha-core.ts"); // shrug diff --git a/server/src/core/db-core.ts b/server/src/core/db-core.ts index c9d4dad8f..e6ad8da11 100644 --- a/server/src/core/db-core.ts +++ b/server/src/core/db-core.ts @@ -1,6 +1,6 @@ import db from "../db"; -import createLogCtx from "../logger"; -const logger = createLogCtx("db-core.ts"); +import CreateLogCtx from "../logger"; +const logger = CreateLogCtx("db-core.ts"); import { integer } from "../types"; export async function GetNextCounterValue(counterName: string): Promise { diff --git a/server/src/core/user-core.ts b/server/src/core/user-core.ts index 8fb92e85a..bd882c32f 100644 --- a/server/src/core/user-core.ts +++ b/server/src/core/user-core.ts @@ -1,7 +1,7 @@ -import { PrivateUserDocument, PublicUserDocument } from "kamaitachi-common"; +import { integer, PrivateUserDocument, PublicUserDocument } from "kamaitachi-common"; import db from "../db"; -const PRIVATE_USER_RETURNS = { +const OMIT_PRIVATE_USER_RETURNS = { password: 0, email: 0, // legacy protection - this field does not exist on user documents anymore, but it did, and it *did* hold personal information. @@ -13,15 +13,15 @@ const PRIVATE_USER_RETURNS = { * @param username The username of the user. * @returns PublicUserDocument */ -export function GetUserCaseInsensitive(username: string) { +export function GetUserCaseInsensitive(username: string): Promise { return db.users.findOne( { usernameLowercase: username.toLowerCase(), }, { - projection: PRIVATE_USER_RETURNS, + projection: OMIT_PRIVATE_USER_RETURNS, } - ); + ) as Promise; } /** @@ -44,6 +44,34 @@ export function FormatUserDoc(userdoc: PublicUserDocument) { return `${userdoc.username} (~${userdoc.id})`; } +/** + * Gets a user from their userID. + * @param userID The userID to retrieve the user document of. + * @returns PublicUserDocument + */ +export function GetUserWithID(userID: integer): Promise { + return db.users.findOne( + { + id: userID, + }, + { + projection: OMIT_PRIVATE_USER_RETURNS, + } + ) as Promise; +} + +/** + * GetUserWithID, but return personal information, too. + * @see GetUserWithID + * @param userID + * @returns PrivateUserDocument + */ +export function PRIVATEINFO_GetUserWithID(userID: integer) { + return db.users.findOne({ + id: userID, + }); +} + /** * Gets a user based on either their username case-insensitively, or a direct lookup of their ID. * This is used in URLs to resolve the passed user. @@ -59,7 +87,7 @@ export function ResolveUser(usernameOrID: string) { id: intID, }, { - projection: PRIVATE_USER_RETURNS, + projection: OMIT_PRIVATE_USER_RETURNS, } ); } @@ -69,7 +97,7 @@ export function ResolveUser(usernameOrID: string) { usernameLowercase: usernameOrID, }, { - projection: PRIVATE_USER_RETURNS, + projection: OMIT_PRIVATE_USER_RETURNS, } ); } diff --git a/server/src/db.ts b/server/src/db.ts index 55a9a11af..348bfd8a4 100644 --- a/server/src/db.ts +++ b/server/src/db.ts @@ -20,9 +20,9 @@ import { UserMilestoneDocument, } from "kamaitachi-common"; import monk, { ICollection } from "monk"; -import createLogCtx from "./logger"; +import CreateLogCtx from "./logger"; -const logger = createLogCtx("db.ts"); +const logger = CreateLogCtx("db.ts"); const url = process.env.NODE_ENV === "test" ? "localhost:27017/testingdb" : "localhost:27017/ktblackdb"; diff --git a/server/src/internal-api/auth/auth.ts b/server/src/internal-api/auth/auth.ts index bd783f044..675eca350 100644 --- a/server/src/internal-api/auth/auth.ts +++ b/server/src/internal-api/auth/auth.ts @@ -14,11 +14,11 @@ import { PRIVATEINFO_GetUserCaseInsensitive, } from "../../core/user-core"; import db from "../../db"; -import createLogCtx from "../../logger"; +import CreateLogCtx from "../../logger"; import prValidate from "../../middleware/prudence-validate"; import { RequireLoggedIn } from "../../middleware/require-logged-in"; -const logger = createLogCtx("auth.ts"); +const logger = CreateLogCtx("auth.ts"); const router = Router({ mergeParams: true }); diff --git a/server/src/internal-api/import/import.ts b/server/src/internal-api/import/import.ts index 1dd8d4bd5..658141f0e 100644 --- a/server/src/internal-api/import/import.ts +++ b/server/src/internal-api/import/import.ts @@ -2,14 +2,17 @@ import { Router, NextFunction, Request, Response } from "express"; import { FileUploadImportTypes } from "kamaitachi-common"; import multer, { MulterError } from "multer"; import Prudence from "prudence"; -import createLogCtx from "../../logger"; +import { GetUserWithID } from "../../core/user-core"; +import db from "../../db"; +import CreateLogCtx from "../../logger"; import prValidate from "../../middleware/prudence-validate"; import { RequireLoggedIn } from "../../middleware/require-logged-in"; import ScoreImportFatalError from "../../score-import/framework/core/score-import-error"; import { ResolveFileUploadData } from "../../score-import/framework/parsing/file-upload"; +import ScoreImportMain from "../../score-import/framework/score-import-main"; import serverConfig from "../../server-config"; -const logger = createLogCtx("import.ts"); +const logger = CreateLogCtx("import.ts"); const router = Router({ mergeParams: true }); @@ -57,10 +60,23 @@ router.post( } try { - let converterInfo = await ResolveFileUploadData( - req.body.importType as FileUploadImportTypes, + let importType = req.body.importType as FileUploadImportTypes; + let { iterable, idStrings, context, converter } = await ResolveFileUploadData( + importType, req.file, - req.body + req.body, + logger + ); + + const userDoc = await GetUserWithID(req.session.ktchi!.userID); + + let importDocument = await ScoreImportMain( + userDoc, + importType, + idStrings, + iterable, + converter, + context ); } catch (err) { if (err instanceof ScoreImportFatalError) { diff --git a/server/src/logger.ts b/server/src/logger.ts index 8ec25dc30..eccc42f59 100644 --- a/server/src/logger.ts +++ b/server/src/logger.ts @@ -1,7 +1,7 @@ import winston, { format, Logger, transports } from "winston"; import fs from "fs"; import path from "path"; -import { PublicUserDocument } from "kamaitachi-common"; +import { ImportTypes, PublicUserDocument } from "kamaitachi-common"; import { FormatUserDoc } from "./core/user-core"; const level = process.env.LOG_LEVEL ?? "info"; @@ -68,12 +68,16 @@ const logger = winston.createLogger({ transports: tports, }); -function createLogCtx(context: string) { - return logger.child({ context }); +function CreateLogCtx(context: string, lg = logger) { + return lg.child({ context }); } -export function createScoreLogger(user: PublicUserDocument, importID: string) { - return logger.child({ context: ["Score Import", FormatUserDoc(user)], importID }); +export function CreateScoreLogger( + user: PublicUserDocument, + importID: string, + importType: ImportTypes +) { + return logger.child({ context: ["Score Import", importType, FormatUserDoc(user)], importID }); } -export default createLogCtx; +export default CreateLogCtx; diff --git a/server/src/main.ts b/server/src/main.ts index 1ab9d950b..a823a8e8a 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -11,11 +11,11 @@ function FormatVersion() { return `v${[major, minor, patch].join(".")} (${name})`; } -import createLogCtx from "./logger"; +import CreateLogCtx from "./logger"; import server from "./server"; import serverConfig from "./server-config"; -const logger = createLogCtx("main.ts"); +const logger = CreateLogCtx("main.ts"); logger.info(`Booting Kamaitachi BLACK - ${FormatVersion()}`); diff --git a/server/src/score-import/framework/core/calculated-data/calculated-data.ts b/server/src/score-import/framework/core/calculated-data/calculated-data.ts index 36a685187..3098c4562 100644 --- a/server/src/score-import/framework/core/calculated-data/calculated-data.ts +++ b/server/src/score-import/framework/core/calculated-data/calculated-data.ts @@ -6,21 +6,23 @@ import { SongDocument, TierlistDataDocument, } from "kamaitachi-common"; -import { DryScore, integer } from "../../../../types"; +import { Logger } from "winston"; +import { DryScore } from "../../../../types"; import { CreateGameSpecific } from "./game-specific"; import { CalculateCHUNITHMRating, CalculateGITADORARating } from "./game-specific-stats"; export async function CreateCalculatedData( dryScore: DryScore, chart: ChartDocument, - song: SongDocument + song: SongDocument, + logger: Logger ): Promise { const game = dryScore.game; const playtype = chart.playtype; const [rating, gameSpecific] = await Promise.all([ CalculateRating(dryScore, game, playtype, chart), - CreateGameSpecific(game, playtype, chart, dryScore), + CreateGameSpecific(game, playtype, chart, dryScore, logger), ]); return { diff --git a/server/src/score-import/framework/core/calculated-data/game-specific-stats.ts b/server/src/score-import/framework/core/calculated-data/game-specific-stats.ts index a001aeda2..f28a60496 100644 --- a/server/src/score-import/framework/core/calculated-data/game-specific-stats.ts +++ b/server/src/score-import/framework/core/calculated-data/game-specific-stats.ts @@ -1,13 +1,17 @@ import { ChartDocument, ESDCore, integer } from "kamaitachi-common"; +import { Logger } from "winston"; import db from "../../../../db"; -import createLogCtx from "../../../../logger"; +import CreateLogCtx from "../../../../logger"; import { DryScore } from "../../../../types"; -const logger = createLogCtx("game-specific-stats.ts"); /** * Calculates the in-game CHUNITHM rating for a score. */ -export function CalculateCHUNITHMRating(dryScore: DryScore, chartData: ChartDocument) { +export function CalculateCHUNITHMRating( + dryScore: DryScore, + chartData: ChartDocument, + logger: Logger +) { let score = dryScore.scoreData.score; let levelBase = chartData.levelNum * 100; @@ -35,7 +39,11 @@ export function CalculateCHUNITHMRating(dryScore: DryScore, chartData: ChartDocu /** * Calculates the in-game GITADORA rating for a score. */ -export function CalculateGITADORARating(dryScore: DryScore, chartData: ChartDocument) { +export function CalculateGITADORARating( + dryScore: DryScore, + chartData: ChartDocument, + logger: Logger +) { let trueRating = (dryScore.scoreData.percent / 100) * chartData.levelNum * 20; let flooredRating = Math.floor(trueRating * 100) / 100; return flooredRating; @@ -69,7 +77,8 @@ export function CalculateBPI( wrEx: integer, yourEx: integer, max: integer, - powCoef: number | null + powCoef: number | null, + logger: Logger ) { powCoef ??= 1.175; const yourPGF = BPIPikaGreatFn(yourEx, max); @@ -100,7 +109,11 @@ export function CalculateBPI( * Calculates the percent of Kaidens you are ahead of with this score. * @returns Null, if this chart has no kaidens, a percent between 0 and 100, if there are. */ -export async function KaidenPercentile(scoreObj: DryScore, chartData: ChartDocument) { +export async function KaidenPercentile( + scoreObj: DryScore, + chartData: ChartDocument, + logger: Logger +) { let scoreCount = await db["iidx-eam-scores"].count({ chartID: chartData.chartID, }); @@ -121,7 +134,7 @@ export async function KaidenPercentile(scoreObj: DryScore, chartData: ChartDocum * An experimental statistic for determining how good a score is versus the Kaiden Average * For those who know what ESDC is (me), this is just ESDC(kesd, your esd). */ -export function CalculateKESDC(kaidenESD: number | null, yourESD: number) { +export function CalculateKESDC(kaidenESD: number | null, yourESD: number, logger: Logger) { if (!kaidenESD) { return null; } @@ -134,7 +147,7 @@ export function CalculateKESDC(kaidenESD: number | null, yourESD: number) { * https://life4ddr.com/requirements/#mfcpoints * @returns Null if this score was not eligible, a number otherwise. */ -export function CalculateMFCP(dryScore: DryScore, chartData: ChartDocument) { +export function CalculateMFCP(dryScore: DryScore, chartData: ChartDocument, logger: Logger) { if (dryScore.scoreData.lamp !== "MARVELOUS FULL COMBO") { return null; } @@ -200,7 +213,8 @@ const VF5LampCoefficients = { export function CalculateVF4( dryScore: DryScore<"sdvx", "Single", "sdvx:Single">, - chartData: ChartDocument + chartData: ChartDocument, + logger: Logger ) { const multiplier = 25; let level = chartData.levelNum; @@ -227,7 +241,8 @@ export function CalculateVF4( // idk if it's right, but it must be close enough. export function CalculateVF5( dryScore: DryScore<"sdvx", "Single", "sdvx:Single">, - chartData: ChartDocument + chartData: ChartDocument, + logger: Logger ) { let level = chartData.levelNum; diff --git a/server/src/score-import/framework/core/calculated-data/game-specific.ts b/server/src/score-import/framework/core/calculated-data/game-specific.ts index 70103870b..affdde587 100644 --- a/server/src/score-import/framework/core/calculated-data/game-specific.ts +++ b/server/src/score-import/framework/core/calculated-data/game-specific.ts @@ -1,4 +1,5 @@ -import { ChartDocument, Game, IIDXBPIData, Playtypes } from "kamaitachi-common"; +import { ChartDocument, Game, Playtypes } from "kamaitachi-common"; +import { Logger } from "winston"; import db from "../../../../db"; import { DryScore } from "../../../../types"; import { @@ -15,7 +16,8 @@ export async function CreateGameSpecific( game: G, playtype: Playtypes[G], chart: ChartDocument, - dryScore: DryScore + dryScore: DryScore, + logger: Logger ): Promise> { let gameSpecific: Record = {}; @@ -30,33 +32,36 @@ export async function CreateGameSpecific( BPIData.wr, dryScore.scoreData.score, chart.notedata.notecount * 2, - BPIData.coef + BPIData.coef, + logger ); gameSpecific.KESDC = dryScore.scoreData.esd === null ? null - : CalculateKESDC(BPIData.kesd, dryScore.scoreData.esd); + : CalculateKESDC(BPIData.kesd, dryScore.scoreData.esd, logger); } else { gameSpecific.BPI = null; gameSpecific.KESDC = null; } if (playtype === "SP") { - gameSpecific["K%"] = await KaidenPercentile(dryScore, chart); + gameSpecific["K%"] = await KaidenPercentile(dryScore, chart, logger); } } else if (game === "sdvx") { gameSpecific.VF4 = CalculateVF4( dryScore as DryScore<"sdvx", "Single", "sdvx:Single">, - chart as ChartDocument + chart as ChartDocument, + logger ); gameSpecific.VF5 = CalculateVF5( dryScore as DryScore<"sdvx", "Single", "sdvx:Single">, - chart as ChartDocument + chart as ChartDocument, + logger ); } else if (game === "ddr") { // either playtype - gameSpecific.MFCP = CalculateMFCP(dryScore, chart); + gameSpecific.MFCP = CalculateMFCP(dryScore, chart, logger); } return gameSpecific; diff --git a/server/src/score-import/framework/core/import-logger.ts b/server/src/score-import/framework/core/import-logger.ts new file mode 100644 index 000000000..e5a5ec79c --- /dev/null +++ b/server/src/score-import/framework/core/import-logger.ts @@ -0,0 +1,8 @@ +import { ImportTypes, PublicUserDocument } from "kamaitachi-common"; +import { CreateScoreLogger } from "../../../logger"; +import crypto from "crypto"; + +export function CreateImportLoggerAndID(userDoc: PublicUserDocument, importType: ImportTypes) { + const importID = crypto.randomBytes(20).toString("hex"); + return { logger: CreateScoreLogger(userDoc, importID, importType), importID }; +} diff --git a/server/src/score-import/framework/core/insert-score.ts b/server/src/score-import/framework/core/insert-score.ts index 53585e13a..2c2138d71 100644 --- a/server/src/score-import/framework/core/insert-score.ts +++ b/server/src/score-import/framework/core/insert-score.ts @@ -25,4 +25,6 @@ export async function InsertQueue() { if (temp.length !== 0) { await db.scores.insert(temp); } + + return temp.length; } diff --git a/server/src/score-import/framework/importing/score-importing.ts b/server/src/score-import/framework/importing/score-importing.ts index 88ba18075..3ecc3c93d 100644 --- a/server/src/score-import/framework/importing/score-importing.ts +++ b/server/src/score-import/framework/importing/score-importing.ts @@ -4,7 +4,6 @@ import { ScoreDocument, SongDocument, } from "kamaitachi-common"; -import createLogCtx from "../../../logger"; import { integer, DryScore, ConverterFunction, ConverterFnReturn } from "../../../types"; import HydrateScore from "../core/hydrate-score"; import { QueueScoreInsert } from "../core/insert-score"; @@ -16,8 +15,7 @@ import { } from "../core/converter-errors"; import { CreateScoreID } from "../core/score-id"; import db from "../../../db"; - -const logger = createLogCtx("score-processor.ts"); +import { Logger } from "winston"; /** * Processes the iterable data into the Kamaitachi database. @@ -31,7 +29,8 @@ export async function ImportAllIterableData( userID: integer, iterableData: Iterable | AsyncIterable, ConverterFunction: ConverterFunction, - context: C + context: C, + logger: Logger ): Promise { logger.verbose(`Starting Data Processing...`); @@ -42,7 +41,7 @@ export async function ImportAllIterableData( // An example would be making an api request after exhausting // the first set of data. for await (const data of iterableData) { - promises.push(ImportIterableDatapoint(userID, data, ConverterFunction, context)); + promises.push(ImportIterableDatapoint(userID, data, ConverterFunction, context, logger)); } // Due to the fact that ProcessIterableDatapoint may return an array instead of a single result @@ -93,15 +92,18 @@ export async function ImportIterableDatapoint( userID: integer, data: D, ConverterFunction: ConverterFunction, - context: C + context: C, + logger: Logger ) { - const converterReturns = await ConverterFunction(data, context); + const converterReturns = await ConverterFunction(data, context, logger); if (Array.isArray(converterReturns)) { - return Promise.all(converterReturns.map((e) => ImportFromConverterReturn(userID, e))); + return Promise.all( + converterReturns.map((e) => ImportFromConverterReturn(userID, e, logger)) + ); } - return ImportFromConverterReturn(userID, converterReturns); + return ImportFromConverterReturn(userID, converterReturns, logger); } /** @@ -116,7 +118,8 @@ async function HydrateAndInsertScore( userID: integer, dryScore: DryScore, chart: ChartDocument, - song: SongDocument + song: SongDocument, + logger: Logger ): Promise { const scoreID = CreateScoreID(userID, dryScore, chart.chartID); @@ -150,7 +153,8 @@ async function HydrateAndInsertScore( async function ImportFromConverterReturn( userID: integer, - cfnReturn: ConverterFnReturn // a single return, not an array! + cfnReturn: ConverterFnReturn, // a single return, not an array! + logger: Logger ): Promise { // null => processing didnt result in a score document, but not an error, no processing needed! if (cfnReturn === null) { @@ -195,7 +199,8 @@ async function ImportFromConverterReturn( userID, cfnReturn.dryScore, cfnReturn.chart, - cfnReturn.song + cfnReturn.song, + logger ); // This used to be a ScoreExists error. However, we never actually care about diff --git a/server/src/score-import/framework/parsing/file-upload.ts b/server/src/score-import/framework/parsing/file-upload.ts index 7b17f1271..78eabfbe8 100644 --- a/server/src/score-import/framework/parsing/file-upload.ts +++ b/server/src/score-import/framework/parsing/file-upload.ts @@ -1,9 +1,8 @@ import ParseEamusementCSV from "../../import-types/iidx-eamusement-csv/parser"; -import createLogCtx from "../../../logger"; +import CreateLogCtx from "../../../logger"; import ScoreImportFatalError from "../core/score-import-error"; import { FileUploadImportTypes } from "kamaitachi-common"; - -const logger = createLogCtx("file-upload.ts"); +import { Logger } from "winston"; /** * Resolves the data from a file upload into an iterable, @@ -18,11 +17,12 @@ const logger = createLogCtx("file-upload.ts"); export function ResolveFileUploadData( importType: FileUploadImportTypes, fileData: Express.Multer.File, - body: Record + body: Record, + logger: Logger ) { switch (importType) { case "iidx:eamusement-csv": - return ParseEamusementCSV(fileData, body); + return ParseEamusementCSV(fileData, body, logger); default: logger.error( `importType ${importType} made it into ResolveFileUploadData, but should have been rejected by Prudence.` diff --git a/server/src/score-import/framework/score-import-main.ts b/server/src/score-import/framework/score-import-main.ts index b78d258f2..1e8b9ccc5 100644 --- a/server/src/score-import/framework/score-import-main.ts +++ b/server/src/score-import/framework/score-import-main.ts @@ -1,35 +1,39 @@ import { IDStrings, - ImportDocument, ImportTypes, KTBlackImportDocument, PublicUserDocument, } from "kamaitachi-common"; -import { createScoreLogger } from "../../logger"; import { ConverterFunction } from "../../types"; import { InsertQueue } from "./core/insert-score"; import { ImportAllIterableData } from "./importing/score-importing"; -import crypto from "crypto"; +import { CreateImportLoggerAndID } from "./core/import-logger"; export default async function ScoreImportMain( user: PublicUserDocument, importType: ImportTypes, - idStrings: IDStrings[], + idStrings: [IDStrings] & IDStrings[], iterableData: Iterable | AsyncIterable, ConverterFunction: ConverterFunction, context: C ) { - const importID = crypto.randomBytes(20).toString("hex"); - - const logger = createScoreLogger(user, importID); + const timeStarted = Date.now(); + const { importID, logger } = CreateImportLoggerAndID(user, importType); // @todo: scope logger properly logger.verbose("Received import request."); - let importInfo = await ImportAllIterableData(user.id, iterableData, ConverterFunction, context); + let importInfo = await ImportAllIterableData( + user.id, + iterableData, + ConverterFunction, + context, + logger + ); // Empty anything in the score queue - await InsertQueue(); + let emptied = await InsertQueue(); + logger.verbose(`Emptied ${emptied} documents from score queue`); // Update user's rating information // @todo @@ -41,5 +45,12 @@ export default async function ScoreImportMain( const ImportDocument: KTBlackImportDocument = { importType, idStrings: idStrings, + importInfo, + importID, + timeFinished: Date.now(), + timeStarted, + userID: user.id, }; + + return ImportDocument; } diff --git a/server/src/score-import/import-types/iidx-eamusement-csv/converter.ts b/server/src/score-import/import-types/iidx-eamusement-csv/converter.ts index e43668218..5cb6ed397 100644 --- a/server/src/score-import/import-types/iidx-eamusement-csv/converter.ts +++ b/server/src/score-import/import-types/iidx-eamusement-csv/converter.ts @@ -1,5 +1,6 @@ import { config, ESDCore, Lamps, SongDocument } from "kamaitachi-common"; -import createLogCtx from "../../../logger"; +import { Logger } from "winston"; +import CreateLogCtx from "../../../logger"; import { DryScore, ConverterFunction, ConverterFnReturn } from "../../../types"; import { FindChartWithPTDF } from "../../database-lookup/chart-ptdf"; import { FindSongOnTitleVersion } from "../../database-lookup/song-title"; @@ -16,8 +17,6 @@ export interface DataTest { foo: string; } -const logger = createLogCtx("iidx:eamusement-csv/converter"); - const EAMUSEMENT_LAMP_RESOLVER: Map = new Map([ ["NO PLAY", "NO PLAY"], ["FULLCOMBO CLEAR", "FULL COMBO"], @@ -34,7 +33,8 @@ async function EamScoreConverter( eamScore: EamusementScoreData, ktchiSong: SongDocument, context: IIDXEamusementCSVContext, - data: IIDXEamusementCSVData + data: IIDXEamusementCSVData, + logger: Logger ) { const HUMANISED_SONG_TITLE = `${ktchiSong.title} (${context.playtype} ${eamScore.difficulty})`; if (!eamScore.level) { @@ -177,10 +177,11 @@ async function EamScoreConverterWrapper( eamScore: EamusementScoreData, song: SongDocument, context: IIDXEamusementCSVContext, - data: IIDXEamusementCSVData + data: IIDXEamusementCSVData, + logger: Logger ) { try { - let results = await EamScoreConverter(eamScore, song!, context, data); + let results = await EamScoreConverter(eamScore, song!, context, data, logger); if (!results) { return null; @@ -209,7 +210,8 @@ async function EamScoreConverterWrapper( const ConverterFn: ConverterFunction = async ( data, - context + context, + logger: Logger ): Promise => { let ktchiSong = await FindSongOnTitleVersion("iidx", data.title, context.importVersion); @@ -220,7 +222,7 @@ const ConverterFn: ConverterFunction EamScoreConverterWrapper(e, ktchiSong!, context, data)) + data.scores.map((e) => EamScoreConverterWrapper(e, ktchiSong!, context, data, logger)) ); return results; diff --git a/server/src/score-import/import-types/iidx-eamusement-csv/parser.ts b/server/src/score-import/import-types/iidx-eamusement-csv/parser.ts index 139e12854..4796a3034 100644 --- a/server/src/score-import/import-types/iidx-eamusement-csv/parser.ts +++ b/server/src/score-import/import-types/iidx-eamusement-csv/parser.ts @@ -1,11 +1,10 @@ import csvParse from "csv-parse/lib/sync"; -import createLogCtx from "../../../logger"; -import { integer, ParserFunctionReturnsSync } from "../../../types"; +import { Logger } from "winston"; +import { ParserFunctionReturnsSync } from "../../../types"; import ScoreImportFatalError from "../../framework/core/score-import-error"; +import ConverterFn from "./converter"; import { IIDXEamusementCSVContext, IIDXEamusementCSVData } from "./types"; -const logger = createLogCtx("iidx-eamusement-csv/parser.ts"); - const PRE_HV_HEADER_COUNT = 27; const HV_HEADER_COUNT = 41; @@ -47,7 +46,8 @@ enum EAM_VERSION_NAMES { */ function ParseEamusementCSV( fileData: Express.Multer.File, - body: Record + body: Record, + logger: Logger ): ParserFunctionReturnsSync { let playtype: "SP" | "DP"; @@ -221,7 +221,12 @@ function ParseEamusementCSV( logger.verbose(`Successfully Parsed with ${data.length} results.`); - return { iterable: data, context }; + return { + iterable: data, + context, + converter: ConverterFn, + idStrings: [`iidx:${context.playtype}`], + }; } export default ParseEamusementCSV; diff --git a/server/src/scripts/update-bpi-poyashi.ts b/server/src/scripts/update-bpi-poyashi.ts index a99fbb720..f94645fd5 100644 --- a/server/src/scripts/update-bpi-poyashi.ts +++ b/server/src/scripts/update-bpi-poyashi.ts @@ -7,10 +7,10 @@ import { config, Difficulties, ESDCore, IIDXBPIData } from "kamaitachi-common"; import { FindSongOnTitleVersion } from "../score-import/database-lookup/song-title"; import { FindChartWithPTDF } from "../score-import/database-lookup/chart-ptdf"; import db from "../db"; -import createLogCtx from "../logger"; +import CreateLogCtx from "../logger"; const program = new Command(); -const logger = createLogCtx("update-bpi-poyashi.ts"); +const logger = CreateLogCtx("update-bpi-poyashi.ts"); program.option("-f, --fetch", "Fetch the latest data from the poyashi repo."); diff --git a/server/src/server.ts b/server/src/server.ts index a6c51751c..9589c08d8 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -1,12 +1,12 @@ import express from "express"; import "express-async-errors"; -import createLogCtx from "./logger"; +import CreateLogCtx from "./logger"; import expressSession from "express-session"; import connectRedis from "connect-redis"; import redis from "redis"; import { SESSION_SECRET } from "./secrets"; -const logger = createLogCtx("server.ts"); +const logger = CreateLogCtx("server.ts"); const RedisStore = connectRedis(expressSession); logger.info("Created Redis Store"); diff --git a/server/src/types.ts b/server/src/types.ts index 0a258ecde..29e790a9d 100644 --- a/server/src/types.ts +++ b/server/src/types.ts @@ -7,6 +7,7 @@ import { ScoreDocument, SongDocument, } from "kamaitachi-common"; +import { Logger } from "winston"; import { ConverterFailure } from "./score-import/framework/core/converter-errors"; import { Converters } from "./score-import/import-types/import-types"; @@ -48,12 +49,14 @@ export type ConverterFnReturn = ConverterFailure | ConverterFnSuccessReturn | nu export type ConverterFunctionReturns = ConverterFnReturn | ConverterFnReturn[]; export interface ConverterFunction { - (data: D, processContext: C): Promise; + (data: D, processContext: C, logger: Logger): Promise; } export interface ParserFunctionReturnsSync { iterable: Iterable; + idStrings: [IDStrings] & IDStrings[]; context: C; + converter: ConverterFunction; } export type ParserFunctionReturns = @@ -62,7 +65,9 @@ export type ParserFunctionReturns = export interface ParserFunctionReturnsAsync { iterable: AsyncIterable; + idStrings: [IDStrings] & IDStrings[]; context: C; + converter: ConverterFunction; } /**