mirror of
https://github.com/zkldi/Tachi.git
synced 2026-10-12 01:08:29 +03:00
@@ -1,9 +1,11 @@
|
||||
import db from "external/mongo/db";
|
||||
import { UserGameStats } from "tachi-common";
|
||||
import { ONE_DAY, ONE_YEAR } from "lib/constants/time";
|
||||
import { UserGameStats, ImportTypes, ImportDocument, Game } from "tachi-common";
|
||||
import t from "tap";
|
||||
import { CreateFakeAuthCookie } from "test-utils/fake-auth";
|
||||
import mockApi from "test-utils/mock-api";
|
||||
import ResetDBState from "test-utils/resets";
|
||||
import { Random20Hex } from "utils/misc";
|
||||
import { PasswordCompare } from "../../auth/auth";
|
||||
|
||||
t.test("GET /api/v1/users/:userID", (t) => {
|
||||
@@ -368,3 +370,90 @@ t.test("GET /api/v1/users/:userID/game-stats", (t) => {
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("GET /api/v1/users/:userID/recent-imports", async (t) => {
|
||||
t.beforeEach(ResetDBState);
|
||||
|
||||
function mkImport(
|
||||
game: Game,
|
||||
importType: ImportTypes,
|
||||
timeFinished: number,
|
||||
userIntent: boolean
|
||||
): ImportDocument {
|
||||
return {
|
||||
classDeltas: [],
|
||||
createdSessions: [],
|
||||
errors: [],
|
||||
game,
|
||||
importType,
|
||||
importID: Random20Hex(),
|
||||
goalInfo: [],
|
||||
idStrings: [],
|
||||
milestoneInfo: [],
|
||||
playtypes: [],
|
||||
scoreIDs: [],
|
||||
timeFinished,
|
||||
timeStarted: 0,
|
||||
userID: 1,
|
||||
userIntent,
|
||||
};
|
||||
}
|
||||
|
||||
t.test("Should work cross game and ignore imports without userIntent.", async (t) => {
|
||||
await db.imports.insert([
|
||||
mkImport("iidx", "api/arc-iidx", Date.now() - ONE_DAY, true),
|
||||
mkImport("iidx", "api/arc-iidx", Date.now() - ONE_DAY, true),
|
||||
mkImport("sdvx", "api/arc-sdvx", Date.now() - ONE_DAY, false),
|
||||
mkImport("iidx", "api/arc-iidx", Date.now() - ONE_DAY, false),
|
||||
mkImport("sdvx", "api/arc-sdvx", Date.now() - ONE_DAY, true),
|
||||
]);
|
||||
|
||||
const res = await mockApi.get("/api/v1/users/1/recent-imports");
|
||||
|
||||
t.equal(res.statusCode, 200);
|
||||
|
||||
t.strictSame(res.body.body, [
|
||||
{
|
||||
importType: "api/arc-iidx",
|
||||
count: 2,
|
||||
},
|
||||
{
|
||||
importType: "api/arc-sdvx",
|
||||
count: 1,
|
||||
},
|
||||
]);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test("Should ignore imports that were too long ago.", async (t) => {
|
||||
await db.imports.insert([
|
||||
mkImport("iidx", "api/arc-iidx", Date.now() - ONE_DAY, true),
|
||||
mkImport("iidx", "ir/fervidex", Date.now() - ONE_YEAR, true),
|
||||
mkImport("iidx", "ir/fervidex", Date.now() - ONE_YEAR, true),
|
||||
mkImport("iidx", "ir/fervidex", Date.now() - ONE_YEAR, true),
|
||||
mkImport("iidx", "ir/fervidex", Date.now() - ONE_YEAR, true),
|
||||
mkImport("sdvx", "api/arc-sdvx", Date.now() - ONE_DAY, true),
|
||||
mkImport("sdvx", "api/arc-sdvx", Date.now() - ONE_DAY, true),
|
||||
]);
|
||||
|
||||
const res = await mockApi.get("/api/v1/users/1/recent-imports");
|
||||
|
||||
t.equal(res.statusCode, 200);
|
||||
|
||||
t.strictSame(res.body.body, [
|
||||
{
|
||||
importType: "api/arc-sdvx",
|
||||
count: 2,
|
||||
},
|
||||
{
|
||||
importType: "api/arc-iidx",
|
||||
count: 1,
|
||||
},
|
||||
]);
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { Router } from "express";
|
||||
import db from "external/mongo/db";
|
||||
import { SYMBOL_TachiData } from "lib/constants/tachi";
|
||||
import { ONE_MONTH } from "lib/constants/time";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import p from "prudence";
|
||||
import prValidate from "server/middleware/prudence-validate";
|
||||
import { UserGameStats } from "tachi-common";
|
||||
import { ImportTypes, integer, UserGameStats } from "tachi-common";
|
||||
import { DeleteUndefinedProps, StripUrl } from "utils/misc";
|
||||
import { optNull, optNullFluffStrField } from "utils/prudence";
|
||||
import { optNullFluffStrField } from "utils/prudence";
|
||||
import {
|
||||
GetRecentlyViewedFoldersAnyGPT,
|
||||
GetRecentPlaycount,
|
||||
@@ -341,6 +342,38 @@ router.post(
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Get the recent import types this user has used.
|
||||
*/
|
||||
router.get("/recent-imports", async (req, res) => {
|
||||
const user = req[SYMBOL_TachiData]!.requestedUser!;
|
||||
|
||||
const recentImports = (await db.imports.aggregate([
|
||||
{
|
||||
$match: {
|
||||
userID: user.id,
|
||||
timeFinished: { $gt: Date.now() - ONE_MONTH },
|
||||
userIntent: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
$group: {
|
||||
_id: "$importType",
|
||||
count: { $sum: 1 },
|
||||
},
|
||||
},
|
||||
])) as { _id: ImportTypes; count: integer }[];
|
||||
|
||||
// rename _id to importType.
|
||||
const imports = recentImports.map((e) => ({ importType: e._id, count: e.count }));
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
description: `Found ${recentImports.length} imports.`,
|
||||
body: imports.sort((a, b) => b.count - a.count),
|
||||
});
|
||||
});
|
||||
|
||||
router.use("/games/:game/:playtype", gamePTRouter);
|
||||
router.use("/pfp", pfpRouter);
|
||||
router.use("/banner", bannerRouter);
|
||||
|
||||
Reference in New Issue
Block a user