diff --git a/src/controllers/api/abortDojoComponentController.ts b/src/controllers/api/abortDojoComponentController.ts index 02c69cec..fbeb3670 100644 --- a/src/controllers/api/abortDojoComponentController.ts +++ b/src/controllers/api/abortDojoComponentController.ts @@ -9,7 +9,6 @@ export const abortDojoComponentController: RequestHandler = async (req, res) => const guild = await getGuildForRequestEx(req, inventory); const request = JSON.parse(String(req.body)) as IAbortDojoComponentRequest; - // TODO: Move already-contributed credits & items to the clan vault if (request.DecoId) { removeDojoDeco(guild, request.ComponentId, request.DecoId); } else { @@ -17,7 +16,7 @@ export const abortDojoComponentController: RequestHandler = async (req, res) => } await guild.save(); - res.json(getDojoClient(guild, 0, request.ComponentId)); + res.json(await getDojoClient(guild, 0, request.ComponentId)); }; interface IAbortDojoComponentRequest { diff --git a/src/controllers/api/abortDojoComponentDestructionController.ts b/src/controllers/api/abortDojoComponentDestructionController.ts new file mode 100644 index 00000000..1df71495 --- /dev/null +++ b/src/controllers/api/abortDojoComponentDestructionController.ts @@ -0,0 +1,12 @@ +import { getDojoClient, getGuildForRequest } from "@/src/services/guildService"; +import { RequestHandler } from "express"; + +export const abortDojoComponentDestructionController: RequestHandler = async (req, res) => { + const guild = await getGuildForRequest(req); + const componentId = req.query.componentId as string; + + guild.DojoComponents.id(componentId)!.DestructionTime = undefined; + + await guild.save(); + res.json(await getDojoClient(guild, 0, componentId)); +}; diff --git a/src/controllers/api/changeDojoRootController.ts b/src/controllers/api/changeDojoRootController.ts index d54e564a..d596aae3 100644 --- a/src/controllers/api/changeDojoRootController.ts +++ b/src/controllers/api/changeDojoRootController.ts @@ -58,7 +58,7 @@ export const changeDojoRootController: RequestHandler = async (req, res) => { await guild.save(); - res.json(getDojoClient(guild, 0)); + res.json(await getDojoClient(guild, 0)); }; interface INode { diff --git a/src/controllers/api/contributeToDojoComponentController.ts b/src/controllers/api/contributeToDojoComponentController.ts index bde6d6ff..40c6b59f 100644 --- a/src/controllers/api/contributeToDojoComponentController.ts +++ b/src/controllers/api/contributeToDojoComponentController.ts @@ -50,7 +50,7 @@ export const contributeToDojoComponentController: RequestHandler = async (req, r await guild.save(); await inventory.save(); res.json({ - ...getDojoClient(guild, 0, component._id), + ...(await getDojoClient(guild, 0, component._id)), InventoryChanges: inventoryChanges }); }; diff --git a/src/controllers/api/destroyDojoDecoController.ts b/src/controllers/api/destroyDojoDecoController.ts index d6884fe4..1b7ec1dd 100644 --- a/src/controllers/api/destroyDojoDecoController.ts +++ b/src/controllers/api/destroyDojoDecoController.ts @@ -6,10 +6,9 @@ export const destroyDojoDecoController: RequestHandler = async (req, res) => { const request = JSON.parse(String(req.body)) as IDestroyDojoDecoRequest; removeDojoDeco(guild, request.ComponentId, request.DecoId); - // TODO: The client says this is supposed to refund the resources to the clan vault, so we should probably do that. await guild.save(); - res.json(getDojoClient(guild, 0, request.ComponentId)); + res.json(await getDojoClient(guild, 0, request.ComponentId)); }; interface IDestroyDojoDecoRequest { diff --git a/src/controllers/api/dojoComponentRushController.ts b/src/controllers/api/dojoComponentRushController.ts index 3058f8ef..a19cfa7e 100644 --- a/src/controllers/api/dojoComponentRushController.ts +++ b/src/controllers/api/dojoComponentRushController.ts @@ -35,7 +35,7 @@ export const dojoComponentRushController: RequestHandler = async (req, res) => { await guild.save(); await inventory.save(); res.json({ - ...getDojoClient(guild, 0, component._id), + ...(await getDojoClient(guild, 0, component._id)), InventoryChanges: inventoryChanges }); }; diff --git a/src/controllers/api/getGuildDojoController.ts b/src/controllers/api/getGuildDojoController.ts index 560bf045..04d701be 100644 --- a/src/controllers/api/getGuildDojoController.ts +++ b/src/controllers/api/getGuildDojoController.ts @@ -24,5 +24,5 @@ export const getGuildDojoController: RequestHandler = async (req, res) => { await guild.save(); } - res.json(getDojoClient(guild, 0)); + res.json(await getDojoClient(guild, 0)); }; diff --git a/src/controllers/api/placeDecoInComponentController.ts b/src/controllers/api/placeDecoInComponentController.ts index d25ac548..b08a1700 100644 --- a/src/controllers/api/placeDecoInComponentController.ts +++ b/src/controllers/api/placeDecoInComponentController.ts @@ -30,7 +30,7 @@ export const placeDecoInComponentController: RequestHandler = async (req, res) = } await guild.save(); - res.json(getDojoClient(guild, 0, component._id)); + res.json(await getDojoClient(guild, 0, component._id)); }; interface IPlaceDecoInComponentRequest { diff --git a/src/controllers/api/queueDojoComponentDestructionController.ts b/src/controllers/api/queueDojoComponentDestructionController.ts index 2e30dc25..40ef89ec 100644 --- a/src/controllers/api/queueDojoComponentDestructionController.ts +++ b/src/controllers/api/queueDojoComponentDestructionController.ts @@ -1,12 +1,12 @@ -import { getDojoClient, getGuildForRequest, removeDojoRoom } from "@/src/services/guildService"; +import { getDojoClient, getGuildForRequest } from "@/src/services/guildService"; import { RequestHandler } from "express"; export const queueDojoComponentDestructionController: RequestHandler = async (req, res) => { const guild = await getGuildForRequest(req); const componentId = req.query.componentId as string; - removeDojoRoom(guild, componentId); + guild.DojoComponents.id(componentId)!.DestructionTime = new Date(Date.now() + 2 * 3600_000); await guild.save(); - res.json(getDojoClient(guild, 1)); + res.json(await getDojoClient(guild, 0, componentId)); }; diff --git a/src/controllers/api/setDojoComponentMessageController.ts b/src/controllers/api/setDojoComponentMessageController.ts index 255c4d2e..92931a54 100644 --- a/src/controllers/api/setDojoComponentMessageController.ts +++ b/src/controllers/api/setDojoComponentMessageController.ts @@ -12,7 +12,7 @@ export const setDojoComponentMessageController: RequestHandler = async (req, res component.Message = payload.Message; } await guild.save(); - res.json(getDojoClient(guild, 0, component._id)); + res.json(await getDojoClient(guild, 0, component._id)); }; type SetDojoComponentMessageRequest = { Name: string } | { Message: string }; diff --git a/src/controllers/api/startDojoRecipeController.ts b/src/controllers/api/startDojoRecipeController.ts index 0a0dfc66..30f4ed75 100644 --- a/src/controllers/api/startDojoRecipeController.ts +++ b/src/controllers/api/startDojoRecipeController.ts @@ -37,5 +37,5 @@ export const startDojoRecipeController: RequestHandler = async (req, res) => { component.CompletionTime = new Date(Date.now()); } await guild.save(); - res.json(getDojoClient(guild, 0)); + res.json(await getDojoClient(guild, 0)); }; diff --git a/src/routes/api.ts b/src/routes/api.ts index 72229b15..dcc9fddc 100644 --- a/src/routes/api.ts +++ b/src/routes/api.ts @@ -1,6 +1,7 @@ import express from "express"; import { abandonLibraryDailyTaskController } from "@/src/controllers/api/abandonLibraryDailyTaskController"; import { abortDojoComponentController } from "@/src/controllers/api/abortDojoComponentController"; +import { abortDojoComponentDestructionController } from "@/src/controllers/api/abortDojoComponentDestructionController"; import { activateRandomModController } from "@/src/controllers/api/activateRandomModController"; import { addFriendImageController } from "@/src/controllers/api/addFriendImageController"; import { arcaneCommonController } from "@/src/controllers/api/arcaneCommonController"; @@ -105,6 +106,7 @@ const apiRouter = express.Router(); // get apiRouter.get("/abandonLibraryDailyTask.php", abandonLibraryDailyTaskController); +apiRouter.get("/abortDojoComponentDestruction.php", abortDojoComponentDestructionController); apiRouter.get("/checkDailyMissionBonus.php", checkDailyMissionBonusController); apiRouter.get("/claimLibraryDailyTaskReward.php", claimLibraryDailyTaskRewardController); apiRouter.get("/credits.php", creditsController); diff --git a/src/services/guildService.ts b/src/services/guildService.ts index 19a273f2..64132376 100644 --- a/src/services/guildService.ts +++ b/src/services/guildService.ts @@ -7,6 +7,7 @@ import { IDojoClient, IDojoComponentClient } from "@/src/types/guildTypes"; import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers"; import { Types } from "mongoose"; import { ExportDojoRecipes } from "warframe-public-export-plus"; +import { logger } from "../utils/logger"; export const getGuildForRequest = async (req: Request): Promise => { const accountId = await getAccountIdForRequest(req); @@ -29,11 +30,11 @@ export const getGuildForRequestEx = async ( return guild; }; -export const getDojoClient = ( +export const getDojoClient = async ( guild: TGuildDatabaseDocument, status: number, componentId: Types.ObjectId | string | undefined = undefined -): IDojoClient => { +): Promise => { const dojo: IDojoClient = { _id: { $oid: guild._id.toString() }, Name: guild.Name, @@ -46,6 +47,7 @@ export const getDojoClient = ( DojoRequestStatus: status, DojoComponents: [] }; + const roomsToRemove: Types.ObjectId[] = []; guild.DojoComponents.forEach(dojoComponent => { if (!componentId || dojoComponent._id.equals(componentId)) { const clientComponent: IDojoComponentClient = { @@ -63,6 +65,13 @@ export const getDojoClient = ( } if (dojoComponent.CompletionTime) { clientComponent.CompletionTime = toMongoDate(dojoComponent.CompletionTime); + if (dojoComponent.DestructionTime) { + if (Date.now() >= dojoComponent.DestructionTime.getTime()) { + roomsToRemove.push(dojoComponent._id); + return; + } + clientComponent.DestructionTime = toMongoDate(dojoComponent.DestructionTime); + } } else { clientComponent.RegularCredits = dojoComponent.RegularCredits; clientComponent.MiscItems = dojoComponent.MiscItems; @@ -84,6 +93,13 @@ export const getDojoClient = ( dojo.DojoComponents.push(clientComponent); } }); + if (roomsToRemove.length) { + logger.debug(`removing now-destroyed rooms`, roomsToRemove); + for (const id of roomsToRemove) { + removeDojoRoom(guild, id); + } + await guild.save(); + } return dojo; }; @@ -92,7 +108,7 @@ export const scaleRequiredCount = (count: number): number => { return Math.max(1, Math.trunc(count / 100)); }; -export const removeDojoRoom = (guild: TGuildDatabaseDocument, componentId: string): void => { +export const removeDojoRoom = (guild: TGuildDatabaseDocument, componentId: Types.ObjectId | string): void => { const component = guild.DojoComponents.splice( guild.DojoComponents.findIndex(x => x._id.equals(componentId)), 1 @@ -102,9 +118,14 @@ export const removeDojoRoom = (guild: TGuildDatabaseDocument, componentId: strin guild.DojoCapacity -= meta.capacity; guild.DojoEnergy -= meta.energy; } + // TODO: Add resources spent to the clan vault }; -export const removeDojoDeco = (guild: TGuildDatabaseDocument, componentId: string, decoId: string): void => { +export const removeDojoDeco = ( + guild: TGuildDatabaseDocument, + componentId: Types.ObjectId | string, + decoId: string +): void => { const component = guild.DojoComponents.id(componentId)!; const deco = component.Decos!.splice( component.Decos!.findIndex(x => x._id.equals(decoId)), @@ -114,4 +135,5 @@ export const removeDojoDeco = (guild: TGuildDatabaseDocument, componentId: strin if (meta && meta.capacityCost) { component.DecoCapacity! += meta.capacityCost; } + // TODO: Add resources spent to the clan vault };