mirror of
https://github.com/zkldi/Tachi.git
synced 2026-09-29 02:18:09 +03:00
Import Logger refactor
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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<integer> {
|
||||
|
||||
@@ -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<PublicUserDocument> {
|
||||
return db.users.findOne(
|
||||
{
|
||||
usernameLowercase: username.toLowerCase(),
|
||||
},
|
||||
{
|
||||
projection: PRIVATE_USER_RETURNS,
|
||||
projection: OMIT_PRIVATE_USER_RETURNS,
|
||||
}
|
||||
);
|
||||
) as Promise<PublicUserDocument>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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<PublicUserDocument> {
|
||||
return db.users.findOne(
|
||||
{
|
||||
id: userID,
|
||||
},
|
||||
{
|
||||
projection: OMIT_PRIVATE_USER_RETURNS,
|
||||
}
|
||||
) as Promise<PublicUserDocument>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
+2
-2
@@ -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";
|
||||
|
||||
@@ -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 });
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+10
-6
@@ -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;
|
||||
|
||||
+2
-2
@@ -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()}`);
|
||||
|
||||
|
||||
@@ -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<ScoreDocument["calculatedData"]> {
|
||||
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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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<G extends Game>(
|
||||
game: G,
|
||||
playtype: Playtypes[G],
|
||||
chart: ChartDocument,
|
||||
dryScore: DryScore
|
||||
dryScore: DryScore,
|
||||
logger: Logger
|
||||
): Promise<Record<string, number | null>> {
|
||||
let gameSpecific: Record<string, number | null> = {};
|
||||
|
||||
@@ -30,33 +32,36 @@ export async function CreateGameSpecific<G extends Game>(
|
||||
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;
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
@@ -25,4 +25,6 @@ export async function InsertQueue() {
|
||||
if (temp.length !== 0) {
|
||||
await db.scores.insert(temp);
|
||||
}
|
||||
|
||||
return temp.length;
|
||||
}
|
||||
|
||||
@@ -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<D, C>(
|
||||
userID: integer,
|
||||
iterableData: Iterable<D> | AsyncIterable<D>,
|
||||
ConverterFunction: ConverterFunction<D, C>,
|
||||
context: C
|
||||
context: C,
|
||||
logger: Logger
|
||||
): Promise<ImportProcessingInfo[]> {
|
||||
logger.verbose(`Starting Data Processing...`);
|
||||
|
||||
@@ -42,7 +41,7 @@ export async function ImportAllIterableData<D, C>(
|
||||
// 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<D, C>(
|
||||
userID: integer,
|
||||
data: D,
|
||||
ConverterFunction: ConverterFunction<D, C>,
|
||||
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<ScoreDocument | null> {
|
||||
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<ImportProcessingInfo | null> {
|
||||
// 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
|
||||
|
||||
@@ -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<string, unknown>
|
||||
body: Record<string, unknown>,
|
||||
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.`
|
||||
|
||||
@@ -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<D, C>(
|
||||
user: PublicUserDocument,
|
||||
importType: ImportTypes,
|
||||
idStrings: IDStrings[],
|
||||
idStrings: [IDStrings] & IDStrings[],
|
||||
iterableData: Iterable<D> | AsyncIterable<D>,
|
||||
ConverterFunction: ConverterFunction<D, C>,
|
||||
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<D, C>(
|
||||
const ImportDocument: KTBlackImportDocument = {
|
||||
importType,
|
||||
idStrings: idStrings,
|
||||
importInfo,
|
||||
importID,
|
||||
timeFinished: Date.now(),
|
||||
timeStarted,
|
||||
userID: user.id,
|
||||
};
|
||||
|
||||
return ImportDocument;
|
||||
}
|
||||
|
||||
@@ -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<string, Lamps["iidx:SP" | "iidx:DP"]> = 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<IIDXEamusementCSVData, IIDXEamusementCSVContext> = async (
|
||||
data,
|
||||
context
|
||||
context,
|
||||
logger: Logger
|
||||
): Promise<ConverterFnReturn[]> => {
|
||||
let ktchiSong = await FindSongOnTitleVersion("iidx", data.title, context.importVersion);
|
||||
|
||||
@@ -220,7 +222,7 @@ const ConverterFn: ConverterFunction<IIDXEamusementCSVData, IIDXEamusementCSVCon
|
||||
|
||||
// ts thinks ktchiSong might be null. It's not, though!
|
||||
let results = await Promise.all(
|
||||
data.scores.map((e) => EamScoreConverterWrapper(e, ktchiSong!, context, data))
|
||||
data.scores.map((e) => EamScoreConverterWrapper(e, ktchiSong!, context, data, logger))
|
||||
);
|
||||
|
||||
return results;
|
||||
|
||||
@@ -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<string, unknown>
|
||||
body: Record<string, unknown>,
|
||||
logger: Logger
|
||||
): ParserFunctionReturnsSync<IIDXEamusementCSVData, IIDXEamusementCSVContext> {
|
||||
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;
|
||||
|
||||
@@ -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.");
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
+6
-1
@@ -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<D, C> {
|
||||
(data: D, processContext: C): Promise<ConverterFunctionReturns>;
|
||||
(data: D, processContext: C, logger: Logger): Promise<ConverterFunctionReturns>;
|
||||
}
|
||||
|
||||
export interface ParserFunctionReturnsSync<D, C> {
|
||||
iterable: Iterable<D>;
|
||||
idStrings: [IDStrings] & IDStrings[];
|
||||
context: C;
|
||||
converter: ConverterFunction<D, C>;
|
||||
}
|
||||
|
||||
export type ParserFunctionReturns<D, C> =
|
||||
@@ -62,7 +65,9 @@ export type ParserFunctionReturns<D, C> =
|
||||
|
||||
export interface ParserFunctionReturnsAsync<D, C> {
|
||||
iterable: AsyncIterable<D>;
|
||||
idStrings: [IDStrings] & IDStrings[];
|
||||
context: C;
|
||||
converter: ConverterFunction<D, C>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user