diff --git a/.eslintrc b/.eslintrc index e23136179..3b7c142ab 100644 --- a/.eslintrc +++ b/.eslintrc @@ -24,7 +24,8 @@ "@typescript-eslint/no-unsafe-assignment": "warn", "@typescript-eslint/no-explicit-any": "warn", "@typescript-eslint/no-loss-of-precision": "warn", - "no-case-declarations": "warn" + "no-case-declarations": "warn", + "no-mixed-spaces-and-tabs": "warn" }, "parser": "@typescript-eslint/parser", "parserOptions": { diff --git a/src/controllers/api/getGuildDojoController.ts b/src/controllers/api/getGuildDojoController.ts index cf60ed136..a220bb7e1 100644 --- a/src/controllers/api/getGuildDojoController.ts +++ b/src/controllers/api/getGuildDojoController.ts @@ -1,7 +1,7 @@ import { RequestHandler } from "express"; import { Types } from "mongoose"; import { Guild } from "@/src/models/guildModel"; -import { IDojoClient } from "@/src/types/guildTypes"; +import { IDojoClient, IDojoComponentClient } from "@/src/types/guildTypes"; import { toOid, toMongoDate } from "@/src/helpers/inventoryHelpers"; export const getGuildDojoController: RequestHandler = async (req, res) => { @@ -39,13 +39,21 @@ export const getGuildDojoController: RequestHandler = async (req, res) => { DojoComponents: [] }; guild.DojoComponents.forEach(dojoComponent => { - dojo.DojoComponents.push({ + const clientComponent: IDojoComponentClient = { id: toOid(dojoComponent._id), pf: dojoComponent.pf, ppf: dojoComponent.ppf, - CompletionTime: toMongoDate(dojoComponent.CompletionTime), DecoCapacity: 600 - }); + }; + if (dojoComponent.pi) { + clientComponent.pi = toOid(dojoComponent.pi); + clientComponent.op = dojoComponent.op!; + clientComponent.pp = dojoComponent.pp!; + } + if (dojoComponent.CompletionTime) { + clientComponent.CompletionTime = toMongoDate(dojoComponent.CompletionTime); + } + dojo.DojoComponents.push(clientComponent); }); res.json(dojo); }; diff --git a/src/controllers/api/startDojoRecipeController.ts b/src/controllers/api/startDojoRecipeController.ts new file mode 100644 index 000000000..8b4104ac2 --- /dev/null +++ b/src/controllers/api/startDojoRecipeController.ts @@ -0,0 +1,28 @@ +import { RequestHandler } from "express"; +import { IDojoComponentClient } from "@/src/types/guildTypes"; +import { getGuildForRequest } from "@/src/services/guildService"; +import { Types } from "mongoose"; + +interface IStartDojoRecipeRequest { + PlacedComponent: IDojoComponentClient; + Revision: number; +} + +export const startDojoRecipeController: RequestHandler = async (req, res) => { + const guild = await getGuildForRequest(req); + // At this point, we know that a member of the guild is making this request. Assuming they are allowed to start a build. + const request = JSON.parse(req.body.toString()) as IStartDojoRecipeRequest; + guild.DojoComponents!.push({ + _id: new Types.ObjectId(), + pf: request.PlacedComponent.pf, + ppf: request.PlacedComponent.ppf, + pi: new Types.ObjectId(request.PlacedComponent.pi!.$oid), + op: request.PlacedComponent.op, + pp: request.PlacedComponent.pp, + CompletionTime: new Date(Date.now()) // TOOD: Omit this field & handle the "Collecting Materials" state. + }); + await guild.save(); + res.json({ + DojoRequestStatus: 0 + }); +}; diff --git a/src/models/guildModel.ts b/src/models/guildModel.ts index 157007a0c..b83a7d429 100644 --- a/src/models/guildModel.ts +++ b/src/models/guildModel.ts @@ -4,6 +4,9 @@ import { model, Schema } from "mongoose"; const dojoComponentSchema = new Schema({ pf: { type: String, required: true }, ppf: String, + pi: Schema.Types.ObjectId, + op: String, + pp: String, CompletionTime: Date }); diff --git a/src/routes/api.ts b/src/routes/api.ts index fc1a1ee24..bc8066be1 100644 --- a/src/routes/api.ts +++ b/src/routes/api.ts @@ -53,6 +53,7 @@ import { guildTechController } from "../controllers/api/guildTechController"; import { dojoController } from "@/src/controllers/api/dojoController"; import { getGuildDojoController } from "@/src/controllers/api/getGuildDojoController"; import { syndicateSacrificeController } from "../controllers/api/syndicateSacrificeController"; +import { startDojoRecipeController } from "@/src/controllers/api/startDojoRecipeController"; const apiRouter = express.Router(); @@ -116,5 +117,6 @@ apiRouter.post("/sell.php", sellController); apiRouter.post("/upgrades.php", upgradesController); apiRouter.post("/guildTech.php", guildTechController); apiRouter.post("/syndicateSacrifice.php", syndicateSacrificeController); +apiRouter.post("/startDojoRecipe.php", startDojoRecipeController); export { apiRouter }; diff --git a/src/services/guildService.ts b/src/services/guildService.ts new file mode 100644 index 000000000..35b697fcc --- /dev/null +++ b/src/services/guildService.ts @@ -0,0 +1,18 @@ +import { Request } from "express"; +import { getAccountIdForRequest } from "@/src/services/loginService"; +import { getInventory } from "@/src/services/inventoryService"; +import { Guild } from "@/src/models/guildModel"; + +export const getGuildForRequest = async (req: Request) => { + const accountId = await getAccountIdForRequest(req); + const inventory = await getInventory(accountId); + const guildId = req.query.guildId as string; + if (!inventory.GuildId || inventory.GuildId.toString() != guildId) { + throw new Error("Account is not in the guild that it has sent a request for"); + } + const guild = await Guild.findOne({ _id: guildId }); + if (!guild) { + throw new Error("Account thinks it is a in guild that doesn't exist"); + } + return guild; +}; diff --git a/src/types/guildTypes.ts b/src/types/guildTypes.ts index c969db6a4..fcf347131 100644 --- a/src/types/guildTypes.ts +++ b/src/types/guildTypes.ts @@ -1,5 +1,6 @@ import { Types } from "mongoose"; import { IOid, IMongoDate } from "@/src/types/commonTypes"; +import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes"; export interface IGuild { Name: string; @@ -31,13 +32,18 @@ export interface IDojoComponentClient { id: IOid; pf: string; ppf: string; - CompletionTime: IMongoDate; - DecoCapacity: number; + pi?: IOid; // Parent ID. N/A to root. + op?: string; // "Open Portal"? N/A to root. + pp?: string; // "Parent Portal"? N/A to root. + RegularCredits?: number; // "Collecting Materials" state: Number of credits that were donated. + MiscItems?: IMiscItem[]; // "Collecting Materials" state: Resources that were donated. + CompletionTime?: IMongoDate; + DecoCapacity?: number; } -export interface IDojoComponentDatabase { +export interface IDojoComponentDatabase + extends Omit { _id: Types.ObjectId; - pf: string; - ppf: string; - CompletionTime: Date; + pi?: Types.ObjectId; + CompletionTime?: Date; }