mirror of
https://github.com/zkldi/Tachi.git
synced 2026-09-27 01:20:31 +03:00
Remove parentMilestones as a feature. Handle it through database queries instead.
This commit is contained in:
+1
-1
@@ -85,7 +85,7 @@
|
||||
"rimraf": "3.0.2",
|
||||
"safe-json-stringify": "1.2.0",
|
||||
"seq-logging": "1.1.1",
|
||||
"tachi-common": "0.7.14",
|
||||
"tachi-common": "0.7.15",
|
||||
"ts-node": "10.4.0",
|
||||
"tsconfig-paths": "3.12.0",
|
||||
"typescript": "4.5.5",
|
||||
|
||||
Generated
+4
-4
@@ -65,7 +65,7 @@ specifiers:
|
||||
safe-json-stringify: 1.2.0
|
||||
seq-logging: 1.1.1
|
||||
supertest: 6.2.2
|
||||
tachi-common: 0.7.14
|
||||
tachi-common: 0.7.15
|
||||
tap: 15.1.6
|
||||
ts-node: 10.4.0
|
||||
tsconfig-paths: 3.12.0
|
||||
@@ -112,7 +112,7 @@ dependencies:
|
||||
rimraf: 3.0.2
|
||||
safe-json-stringify: 1.2.0
|
||||
seq-logging: 1.1.1
|
||||
tachi-common: 0.7.14
|
||||
tachi-common: 0.7.15
|
||||
ts-node: 10.4.0_2615db9039ce432b4abf2fc39ef336ec
|
||||
tsconfig-paths: 3.12.0
|
||||
typescript: 4.5.5
|
||||
@@ -5363,8 +5363,8 @@ packages:
|
||||
engines: {node: '>= 0.4'}
|
||||
dev: true
|
||||
|
||||
/tachi-common/0.7.14:
|
||||
resolution: {integrity: sha512-RZfmSvCrITGm3jClZZc4JJAJwo6lUU+Wkq2+PAQh7gHdlR5OjVlTNDQr67F3F2KTagz6Sw4y1BDKw78j2aPl8Q==}
|
||||
/tachi-common/0.7.15:
|
||||
resolution: {integrity: sha512-rZNTYZFmDVUDcqaVJZAwLhH3Sskoks6Votc62JAOIrxVKEGu9JwGClEpU7YXtD4Uq2Qwt9ZesMtRatQ9rgcMcg==}
|
||||
dependencies:
|
||||
'@types/mongodb': 3.6.18
|
||||
dev: false
|
||||
|
||||
@@ -131,7 +131,6 @@ t.test("#GetRelevantGoals", (t) => {
|
||||
progressHuman: "NO DATA",
|
||||
timeSet: Date.now(),
|
||||
userID: 1,
|
||||
parentMilestones: [],
|
||||
}))
|
||||
);
|
||||
});
|
||||
@@ -194,7 +193,6 @@ t.test("#UpdateGoalsForUser", (t) => {
|
||||
timeAchieved: null,
|
||||
timeSet: 0,
|
||||
userID: 1,
|
||||
parentMilestones: [],
|
||||
};
|
||||
|
||||
t.test("Should correctly update goals when user achieves goal.", async (t) => {
|
||||
@@ -396,7 +394,6 @@ t.test("#ProcessGoal", (t) => {
|
||||
lastInteraction: null,
|
||||
outOf: 5,
|
||||
outOfHuman: "HARD CLEAR",
|
||||
parentMilestones: [],
|
||||
playtype: "SP",
|
||||
progress: 6,
|
||||
progressHuman: "EX HARD CLEAR",
|
||||
|
||||
@@ -11,6 +11,8 @@ import {
|
||||
PBScoreDocument,
|
||||
Playtypes,
|
||||
GoalSubscriptionDocument,
|
||||
MilestoneSubscriptionDocument,
|
||||
MilestoneDocument,
|
||||
} from "tachi-common";
|
||||
import { GetFolderChartIDs } from "utils/folder";
|
||||
import { CreateGoalTitle as CreateGoalName, ValidateGoalChartsAndCriteria } from "./goal-utils";
|
||||
@@ -283,7 +285,6 @@ export async function ConstructGoal(
|
||||
export async function SubscribeToGoal(
|
||||
userID: integer,
|
||||
goalDocument: GoalDocument,
|
||||
parentMilestone?: string,
|
||||
cancelIfAchieved = true
|
||||
) {
|
||||
const goalExists = await db.goals.findOne({ goalID: goalDocument.goalID });
|
||||
@@ -323,9 +324,6 @@ export async function SubscribeToGoal(
|
||||
lastInteraction: null,
|
||||
timeAchieved: result.achieved ? Date.now() : null,
|
||||
timeSet: Date.now(),
|
||||
// if this goal subscription came from a milestone, add the milestone to
|
||||
// the list of parents.
|
||||
parentMilestones: parentMilestone ? [parentMilestone] : [],
|
||||
game: goalDocument.game,
|
||||
playtype: goalDocument.playtype,
|
||||
goalID: goalDocument.goalID,
|
||||
@@ -337,3 +335,56 @@ export async function SubscribeToGoal(
|
||||
|
||||
return goalSub;
|
||||
}
|
||||
|
||||
export function GetMilestonesThatContainGoal(goalID: string) {
|
||||
return db.milestones.find({
|
||||
"milestoneData.goalID": goalID,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribing from a goal may not be legal, because the goal might be part of
|
||||
* a milestone the user is subscribed to. This function returns all milestones
|
||||
* and milestoneSubs that a goal is attached to.
|
||||
*
|
||||
* If this query matches none, an empty array is returned.
|
||||
*/
|
||||
export async function GetBlockingParentMilestoneSubs(
|
||||
goalSub: GoalSubscriptionDocument
|
||||
): Promise<(MilestoneSubscriptionDocument & { milestone: MilestoneDocument })[]> {
|
||||
const blockers = await db["milestone-subs"].aggregate([
|
||||
{
|
||||
// find all milestones that this user is subscribed to
|
||||
$match: {
|
||||
userID: goalSub.userID,
|
||||
game: goalSub.game,
|
||||
playtype: goalSub.playtype,
|
||||
},
|
||||
},
|
||||
{
|
||||
// look up the parent milestones
|
||||
$lookup: {
|
||||
from: "milestones",
|
||||
localField: "milestoneID",
|
||||
foreignField: "milestoneID",
|
||||
as: "parentMilestoneSubs",
|
||||
},
|
||||
},
|
||||
{
|
||||
// then project it onto the $milestone field. This will be null
|
||||
// if the milestone has no parent, which we hopefully won't have
|
||||
// to consider (illegal)
|
||||
$set: {
|
||||
milestone: { $arrayElemAt: ["$parentMilestoneSubs", 0] },
|
||||
},
|
||||
},
|
||||
{
|
||||
// then finally, filter to only milestones that pertain to this goal.
|
||||
$match: {
|
||||
"$milestone.milestoneData.goalID": goalSub.goalID,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
return blockers;
|
||||
}
|
||||
|
||||
@@ -230,25 +230,8 @@ export async function SubscribeToMilestone(
|
||||
// from result.goalResults ourselves.
|
||||
// evaluating goals is fairly cheap though.
|
||||
await Promise.all(
|
||||
result.goals.map(async (goal) => {
|
||||
const res = await SubscribeToGoal(userID, goal, milestone.milestoneID, false);
|
||||
|
||||
// If the user is already subscribed to this goal -- i.e. manually or as part
|
||||
// of another milestone
|
||||
// add this milestoneID to the list of parents instead.
|
||||
if (res === SubscribeFailReasons.ALREADY_SUBSCRIBED) {
|
||||
await db["goal-subs"].update(
|
||||
{
|
||||
userID,
|
||||
milestoneID: milestone.milestoneID,
|
||||
},
|
||||
{
|
||||
$push: {
|
||||
parentMilestones: milestone.milestoneID,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
result.goals.map((goal) => {
|
||||
SubscribeToGoal(userID, goal, milestone.milestoneID, false);
|
||||
})
|
||||
);
|
||||
|
||||
@@ -262,20 +245,7 @@ export async function SubscribeToMilestone(
|
||||
export async function UnsubscribeFromMilestone(userID: integer, milestone: MilestoneDocument) {
|
||||
const goalIDs = GetGoalIDsFromMilestone(milestone);
|
||||
|
||||
// Pull this milestone ID from all of the goalSubscriptions that have it.
|
||||
// since it's no longer going to be their parent.
|
||||
await db["goal-subs"].update(
|
||||
{
|
||||
goalID: { $in: goalIDs },
|
||||
userID,
|
||||
parentMilestones: milestone.milestoneID,
|
||||
},
|
||||
{
|
||||
$pull: {
|
||||
parentMilestones: milestone.milestoneID,
|
||||
},
|
||||
}
|
||||
);
|
||||
// TODO COME BACK HERE
|
||||
|
||||
// then, remove all of the ones that now have no parent blocking their demise.
|
||||
// that's pretty morbid, jesus christ.
|
||||
|
||||
@@ -2,7 +2,11 @@ import { RequestHandler, Router } from "express";
|
||||
import db from "external/mongo/db";
|
||||
import { SYMBOL_TachiData } from "lib/constants/tachi";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { EvaluatedGoalReturn, EvaluateGoalForUser } from "lib/targets/goals";
|
||||
import {
|
||||
EvaluatedGoalReturn,
|
||||
EvaluateGoalForUser,
|
||||
GetMilestonesThatContainGoal,
|
||||
} from "lib/targets/goals";
|
||||
import prValidate from "server/middleware/prudence-validate";
|
||||
import { FormatGame } from "tachi-common";
|
||||
import { GetMostSubscribedGoals } from "utils/db";
|
||||
@@ -66,9 +70,7 @@ router.get("/:goalID", ResolveGoalID, async (req, res) => {
|
||||
|
||||
const users = await GetUsersWithIDs(goalSubs.map((e) => e.userID));
|
||||
|
||||
const parentMilestones = await db.milestones.find({
|
||||
"milestoneData.goalID": goal.goalID,
|
||||
});
|
||||
const parentMilestones = await GetMilestonesThatContainGoal(goal.goalID);
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
|
||||
+2
-9
@@ -656,9 +656,7 @@ t.test("GET /api/v1/users/:userID/games/:game/:playtype/targets/goals/:goalID",
|
||||
await db.goals.insert(dupedGoal);
|
||||
await db["goal-subs"].insert(
|
||||
// @ts-expect-error Not sure why the types break here, but they do.
|
||||
dm(HC511UserGoal, {
|
||||
parentMilestones: [TestingIIDXSPMilestone.milestoneID],
|
||||
})
|
||||
dm(HC511UserGoal)
|
||||
);
|
||||
await db.milestones.insert(dm(TestingIIDXSPMilestone, {}));
|
||||
|
||||
@@ -739,12 +737,7 @@ t.test("DELETE /api/v1/users/:userID/games/:game/:playtype/targets/goals/:goalID
|
||||
|
||||
t.test("Should reject a goal deletion if goal has parent milestones.", async (t) => {
|
||||
await db.goals.insert(dupedGoal);
|
||||
await db["goal-subs"].insert(
|
||||
// @ts-expect-error deepmerge type error
|
||||
dm(dupedGoalSub, {
|
||||
parentMilestones: [TestingIIDXSPMilestone.milestoneID],
|
||||
})
|
||||
);
|
||||
await db["goal-subs"].insert(dm(dupedGoalSub, {}));
|
||||
|
||||
const res = await mockApi
|
||||
.delete(`/api/v1/users/1/games/iidx/SP/targets/goals/${dupedGoalSub.goalID}`)
|
||||
|
||||
+7
-3
@@ -4,7 +4,7 @@ import { SubscribeFailReasons } from "lib/constants/err-codes";
|
||||
import { SYMBOL_TachiData } from "lib/constants/tachi";
|
||||
import CreateLogCtx from "lib/logger/logger";
|
||||
import { ServerConfig } from "lib/setup/config";
|
||||
import { ConstructGoal, SubscribeToGoal } from "lib/targets/goals";
|
||||
import { ConstructGoal, GetBlockingParentMilestoneSubs, SubscribeToGoal } from "lib/targets/goals";
|
||||
import p from "prudence";
|
||||
import { RequirePermissions } from "server/middleware/auth";
|
||||
import prValidate from "server/middleware/prudence-validate";
|
||||
@@ -256,10 +256,14 @@ router.delete(
|
||||
|
||||
const goalSub = req[SYMBOL_TachiData]!.goalSubDoc!;
|
||||
|
||||
if (goalSub.parentMilestones.length) {
|
||||
const parentMilestones = await GetBlockingParentMilestoneSubs(goalSub);
|
||||
|
||||
if (parentMilestones.length) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
description: `This goal is part of a milestone you are subscribed to. It can only be removed by unsubscribing from the relevant milestones.`,
|
||||
description: `This goal is part of a milestone you are subscribed to. It can only be removed by unsubscribing from the relevant milestones: ${parentMilestones
|
||||
.map((e) => `'${e.milestone.name}'`)
|
||||
.join(", ")}.`,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -438,7 +438,6 @@ export const HC511UserGoal: GoalSubscriptionDocument = {
|
||||
progressHuman: "NO DATA",
|
||||
timeSet: 0,
|
||||
userID: 1,
|
||||
parentMilestones: [],
|
||||
};
|
||||
|
||||
export const TestingIIDXFolderSP10: FolderDocument = {
|
||||
|
||||
Reference in New Issue
Block a user