From eba82d20b7f3d9c032f0d164b5bf21d5486cc74d Mon Sep 17 00:00:00 2001 From: zkldi Date: Fri, 5 Nov 2021 05:21:16 +0000 Subject: [PATCH] KsHook support. --- .../src/server/router/ir/fervidex/router.ts | 18 +++- .../server/router/ir/kshook/sv3c/router.ts | 102 ++++++++++++++++++ 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 server/src/server/router/ir/kshook/sv3c/router.ts diff --git a/server/src/server/router/ir/fervidex/router.ts b/server/src/server/router/ir/fervidex/router.ts index 51ddb0ddc..49f80de2a 100644 --- a/server/src/server/router/ir/fervidex/router.ts +++ b/server/src/server/router/ir/fervidex/router.ts @@ -100,7 +100,7 @@ const RequireInf2ModelHeaderOrForceStatic: RequestHandler = async (req, res, nex }); } } catch (err) { - logger.debug(err); + logger.info(`Invalid softID from ${req[SYMBOL_TachiAPIAuth].userID!}.`, { err }); return res.status(400).json({ success: false, error: `Invalid X-Software-Model.`, @@ -215,6 +215,14 @@ router.post("/profile/submit", RequireInf2ModelHeaderOrForceStatic, async (req, (logger) => ParseFervidexStatic(req.body, headers, logger) ); + if (!responseData.body.success) { + // in-air rewrite description to error. + // @ts-expect-error Hack! + responseData.body.error = responseData.body.description; + // @ts-expect-error Hack! + delete responseData.body.description; + } + return res.status(responseData.statusCode).json(responseData.body); }); @@ -248,6 +256,14 @@ router.post("/score/submit", ValidateModelHeader, async (req, res) => { (logger) => ParseFervidexSingle(req.body, headers, logger) ); + if (!responseData.body.success) { + // in-air rewrite description to error. + // @ts-expect-error Hack! + responseData.body.error = responseData.body.description; + // @ts-expect-error Hack! + delete responseData.body.description; + } + return res.status(responseData.statusCode).json(responseData.body); }); diff --git a/server/src/server/router/ir/kshook/sv3c/router.ts b/server/src/server/router/ir/kshook/sv3c/router.ts new file mode 100644 index 000000000..856ff19e1 --- /dev/null +++ b/server/src/server/router/ir/kshook/sv3c/router.ts @@ -0,0 +1,102 @@ +import { Router, RequestHandler } from "express"; +import { MODEL_SDVX3_KONASTE } from "lib/constants/ea3id"; +import { SYMBOL_TachiAPIAuth } from "lib/constants/tachi"; +import CreateLogCtx from "lib/logger/logger"; +import { ExpressWrappedScoreImportMain } from "lib/score-import/framework/express-wrapper"; +import { ParseKsHookSV3C } from "lib/score-import/import-types/ir/kshook-sv3c/parser"; +import { ParseEA3SoftID } from "utils/ea3id"; +import { GetUserWithIDGuaranteed } from "utils/user"; + +const router: Router = Router({ mergeParams: true }); + +const logger = CreateLogCtx(__filename); + +const ValidateHeaders: RequestHandler = (req, res, next) => { + const agent = req.header("User-Agent"); + + if (!agent) { + logger.debug( + `Rejected KsHook client with no agent from user ${req[SYMBOL_TachiAPIAuth].userID!}.` + ); + return res.status(400).json({ + success: false, + error: `Invalid User-Agent.`, + }); + } + + if (!agent.startsWith("kshook/")) { + logger.info( + `Rejected KsHook client with invalid agent ${agent} from user ${req[SYMBOL_TachiAPIAuth] + .userID!}.` + ); + return res.status(400).json({ + success: false, + error: `Invalid User-Agent ${agent} - expected KsHook client.`, + }); + } + + // We don't currently need to check the version or anything i don't think. + // We should be good. + + const softID = req.header("X-Software-Model"); + + if (!softID) { + logger.debug( + `Recieved request without X-Software-Model from ${req[SYMBOL_TachiAPIAuth].userID!}.` + ); + return res.status(400).json({ + success: false, + error: `Invalid X-Software-Model.`, + }); + } + + try { + const modelInfo = ParseEA3SoftID(softID); + + if (modelInfo.model !== MODEL_SDVX3_KONASTE) { + logger.info( + `Recieved unexpected softID ${softID}. Expected ${MODEL_SDVX3_KONASTE} as model.` + ); + return res.status(400).json({ + success: false, + error: `Invalid softID ${softID}.`, + }); + } + } catch (err) { + logger.info(`Invalid softID from ${req[SYMBOL_TachiAPIAuth].userID!}.`, { err }); + return res.status(400).json({ + success: false, + error: `Invalid X-Software-Model.`, + }); + } + + return next(); +}; + +/** + * Saves a SDVX Konaste score. + * + * @name POST /ir/kshook/sv3c/score/save + */ +router.post("/score/save", async (req, res) => { + const userDoc = await GetUserWithIDGuaranteed(req[SYMBOL_TachiAPIAuth].userID!); + + const responseData = await ExpressWrappedScoreImportMain( + userDoc, + true, + "ir/kshook-sv3c", + (logger) => ParseKsHookSV3C(req.body, logger) + ); + + if (!responseData.body.success) { + // in-air rewrite description to error. + // @ts-expect-error Hack! + responseData.body.error = responseData.body.description; + // @ts-expect-error Hack! + delete responseData.body.description; + } + + return res.status(responseData.statusCode).json(responseData.body); +}); + +export default router;