From 5c0130c4802fc5e093181083b85e32cbb99d7328 Mon Sep 17 00:00:00 2001 From: Ordis <134585663+OrdisPrime@users.noreply.github.com> Date: Wed, 19 Feb 2025 18:49:24 +0100 Subject: [PATCH 1/4] testingready --- .../giveKeyChainTriggeredItemsController.ts | 21 +--- .../giveKeyChainTriggeredMessageController.ts | 23 +--- .../custom/manageQuestsController.ts | 52 +++++---- src/models/inventoryModels/inventoryModel.ts | 1 + src/services/inventoryService.ts | 7 +- src/services/questService.ts | 100 ++++++++++++++++++ 6 files changed, 144 insertions(+), 60 deletions(-) diff --git a/src/controllers/api/giveKeyChainTriggeredItemsController.ts b/src/controllers/api/giveKeyChainTriggeredItemsController.ts index ef1e4700..4ce867d4 100644 --- a/src/controllers/api/giveKeyChainTriggeredItemsController.ts +++ b/src/controllers/api/giveKeyChainTriggeredItemsController.ts @@ -3,32 +3,17 @@ import { isEmptyObject, parseString } from "@/src/helpers/general"; import { getJSONfromString } from "@/src/helpers/stringHelpers"; import { addKeyChainItems, getInventory } from "@/src/services/inventoryService"; import { IGroup } from "@/src/types/loginTypes"; -import { updateQuestStage } from "@/src/services/questService"; +import { giveKeyChainItem, updateQuestStage } from "@/src/services/questService"; export const giveKeyChainTriggeredItemsController: RequestHandler = async (req, res) => { const accountId = parseString(req.query.accountId); const keyChainInfo = getJSONfromString((req.body as string).toString()); const inventory = await getInventory(accountId); - const inventoryChanges = await addKeyChainItems(inventory, keyChainInfo); - - if (isEmptyObject(inventoryChanges)) { - throw new Error("inventory changes was empty after getting keychain items: should not happen"); - } - // items were added: update quest stage's i (item was given) - updateQuestStage(inventory, keyChainInfo, { i: true }); - + const inventoryChanges = giveKeyChainItem(inventory, keyChainInfo); await inventory.save(); - res.send(inventoryChanges); - //TODO: Check whether Wishlist is used to track items which should exist uniquely in the inventory - /* - some items are added or removed (not sure) to the wishlist, in that case a - WishlistChanges: ["/Lotus/Types/Items/ShipFeatureItems/ArsenalFeatureItem"], - is added to the response, need to determine for which items this is the case and what purpose this has. - */ - //{"KeyChain":"/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain","ChainStage":0} - //{"WishlistChanges":["/Lotus/Types/Items/ShipFeatureItems/ArsenalFeatureItem"],"MiscItems":[{"ItemType":"/Lotus/Types/Items/ShipFeatureItems/ArsenalFeatureItem","ItemCount":1}]} + res.send(inventoryChanges); }; export interface IKeyChainRequest { diff --git a/src/controllers/api/giveKeyChainTriggeredMessageController.ts b/src/controllers/api/giveKeyChainTriggeredMessageController.ts index 0f699d42..dec4b8a1 100644 --- a/src/controllers/api/giveKeyChainTriggeredMessageController.ts +++ b/src/controllers/api/giveKeyChainTriggeredMessageController.ts @@ -1,34 +1,15 @@ import { IKeyChainRequest } from "@/src/controllers/api/giveKeyChainTriggeredItemsController"; -import { IMessage } from "@/src/models/inboxModel"; -import { createMessage } from "@/src/services/inboxService"; import { getInventory } from "@/src/services/inventoryService"; -import { getKeyChainMessage } from "@/src/services/itemDataService"; import { getAccountIdForRequest } from "@/src/services/loginService"; -import { updateQuestStage } from "@/src/services/questService"; +import { giveKeyChainMessage } from "@/src/services/questService"; import { RequestHandler } from "express"; export const giveKeyChainTriggeredMessageController: RequestHandler = async (req, res) => { const accountId = await getAccountIdForRequest(req); const keyChainInfo = JSON.parse((req.body as Buffer).toString()) as IKeyChainRequest; - const keyChainMessage = getKeyChainMessage(keyChainInfo); - - const message = { - sndr: keyChainMessage.sender, - msg: keyChainMessage.body, - sub: keyChainMessage.title, - att: keyChainMessage.attachments.length > 0 ? keyChainMessage.attachments : undefined, - countedAtt: keyChainMessage.countedAttachments.length > 0 ? keyChainMessage.countedAttachments : undefined, - icon: keyChainMessage.icon ?? "", - transmission: keyChainMessage.transmission ?? "", - highPriority: keyChainMessage.highPriority ?? false, - r: false - } satisfies IMessage; - - await createMessage(accountId, [message]); - const inventory = await getInventory(accountId, "QuestKeys"); - updateQuestStage(inventory, keyChainInfo, { m: true }); + await giveKeyChainMessage(inventory, accountId, keyChainInfo); await inventory.save(); res.send(1); diff --git a/src/controllers/custom/manageQuestsController.ts b/src/controllers/custom/manageQuestsController.ts index 504b4951..92f46212 100644 --- a/src/controllers/custom/manageQuestsController.ts +++ b/src/controllers/custom/manageQuestsController.ts @@ -1,7 +1,8 @@ import { addString } from "@/src/controllers/api/inventoryController"; +import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel"; import { getInventory } from "@/src/services/inventoryService"; import { getAccountIdForRequest } from "@/src/services/loginService"; -import { addQuestKey, IUpdateQuestRequest, updateQuestKey } from "@/src/services/questService"; +import { addQuestKey, completeQuest, IUpdateQuestRequest, updateQuestKey } from "@/src/services/questService"; import { IQuestStage } from "@/src/types/inventoryTypes/inventoryTypes"; import { logger } from "@/src/utils/logger"; import { RequestHandler } from "express"; @@ -23,7 +24,7 @@ export const manageQuestsController: RequestHandler = async (req, res) => { allQuestKeys.push(k); } } - const inventory = await getInventory(accountId, "QuestKeys NodeIntrosCompleted"); + const inventory = await getInventory(accountId); switch (operation) { case "updateKey": { @@ -40,21 +41,22 @@ export const manageQuestsController: RequestHandler = async (req, res) => { case "completeAll": { logger.info("completing all quests.."); for (const questKey of allQuestKeys) { - const chainStageTotal = ExportKeys[questKey].chainStages?.length ?? 0; - const Progress = Array(chainStageTotal).fill({ c: 0, i: true, m: true, b: [] } satisfies IQuestStage); - const inventoryQuestKey = inventory.QuestKeys.find(qk => qk.ItemType === questKey); - if (inventoryQuestKey) { - inventoryQuestKey.Completed = true; - inventoryQuestKey.Progress = Progress; - continue; - } - addQuestKey(inventory, { ItemType: questKey, Completed: true, unlock: true, Progress: Progress }); - } - inventory.ArchwingEnabled = true; - inventory.ActiveQuest = ""; + await completeQuest(inventory, questKey); - // Skip "Watch The Maker" - addString(inventory.NodeIntrosCompleted, "/Lotus/Levels/Cinematics/NewWarIntro/NewWarStageTwo.level"); + //Skip "Watch The Maker" + if (questKey === "/Lotus/Types/Keys/NewWarIntroQuest/NewWarIntroKeyChain") { + addString( + inventory.NodeIntrosCompleted, + "/Lotus/Levels/Cinematics/NewWarIntro/NewWarStageTwo.level" + ); + } + + if (questKey === "/Lotus/Types/Keys/ArchwingQuest/ArchwingQuestKeyChain") { + inventory.ArchwingEnabled = true; + } + } + + inventory.ActiveQuest = ""; break; } case "ResetAll": { @@ -63,14 +65,28 @@ export const manageQuestsController: RequestHandler = async (req, res) => { questKey.Completed = false; questKey.Progress = []; } + inventory.ActiveQuest = ""; break; } case "completeAllUnlocked": { logger.info("completing all unlocked quests.."); for (const questKey of inventory.QuestKeys) { - //if (!questKey.unlock) { continue; } - questKey.Completed = true; + console.log("size of questkeys", inventory.QuestKeys.length); + await completeQuest(inventory, questKey.ItemType); + + //Skip "Watch The Maker" + if (questKey.ItemType === "/Lotus/Types/Keys/NewWarIntroQuest/NewWarIntroKeyChain") { + addString( + inventory.NodeIntrosCompleted, + "/Lotus/Levels/Cinematics/NewWarIntro/NewWarStageTwo.level" + ); + } + + if (questKey.ItemType === "/Lotus/Types/Keys/ArchwingQuest/ArchwingQuestKeyChain") { + inventory.ArchwingEnabled = true; + } } + inventory.ActiveQuest = ""; break; } } diff --git a/src/models/inventoryModels/inventoryModel.ts b/src/models/inventoryModels/inventoryModel.ts index 5848600e..fe651349 100644 --- a/src/models/inventoryModels/inventoryModel.ts +++ b/src/models/inventoryModels/inventoryModel.ts @@ -1249,6 +1249,7 @@ export type InventoryDocumentProps = { KahlLoadOuts: Types.DocumentArray; PendingRecipes: Types.DocumentArray; WeaponSkins: Types.DocumentArray; + QuestKeys: Types.DocumentArray; } & { [K in TEquipmentKey]: Types.DocumentArray }; // eslint-disable-next-line @typescript-eslint/ban-types diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts index 1241d61c..c3604902 100644 --- a/src/services/inventoryService.ts +++ b/src/services/inventoryService.ts @@ -482,6 +482,9 @@ export const addItem = async ( break; } case "Keys": { + if (typeName === "/Lotus/Types/Keys/InfestedMicroplanetQuest/DoubleDefenseIntroEmailItem") { + break; + } inventory.QuestKeys.push({ ItemType: typeName }); return { InventoryChanges: { @@ -519,7 +522,7 @@ export const addItem = async ( } const errorMessage = `unable to add item: ${typeName}`; logger.error(errorMessage); - throw new Error(errorMessage); + return { InventoryChanges: { Error: [{ Error: errorMessage }] } }; }; export const addItems = async ( @@ -1154,7 +1157,5 @@ export const addKeyChainItems = async ( combineInventoryChanges(inventoryChanges, inventoryChangesDelta.InventoryChanges); } - await addItems(inventory, nonStoreItems); - return inventoryChanges; }; diff --git a/src/services/questService.ts b/src/services/questService.ts index 75316763..95e03b32 100644 --- a/src/services/questService.ts +++ b/src/services/questService.ts @@ -1,8 +1,14 @@ import { IKeyChainRequest } from "@/src/controllers/api/giveKeyChainTriggeredItemsController"; +import { isEmptyObject } from "@/src/helpers/general"; +import { IMessage } from "@/src/models/inboxModel"; import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel"; +import { createMessage } from "@/src/services/inboxService"; +import { addKeyChainItems, getInventory } from "@/src/services/inventoryService"; +import { getKeyChainMessage } from "@/src/services/itemDataService"; import { IInventoryDatabase, IQuestKeyDatabase, IQuestStage } from "@/src/types/inventoryTypes/inventoryTypes"; import { logger } from "@/src/utils/logger"; import { HydratedDocument } from "mongoose"; +import { ExportKeys } from "warframe-public-export-plus"; export interface IUpdateQuestRequest { QuestKeys: Omit[]; @@ -70,3 +76,97 @@ export const addQuestKey = (inventory: TInventoryDatabaseDocument, questKey: IQu } inventory.QuestKeys.push(questKey); }; + +export const completeQuest = async (inventory: TInventoryDatabaseDocument, questKey: string) => { + const chainStages = ExportKeys[questKey]?.chainStages; + + if (!chainStages) { + throw new Error(`Quest ${questKey} does not contain chain stages`); + } + + const chainStageTotal = ExportKeys[questKey].chainStages?.length ?? 0; + + const existingQuestKey = inventory.QuestKeys.find(qk => qk.ItemType === questKey); + + if (existingQuestKey?.Completed) { + return; + } + const Progress = Array(chainStageTotal).fill({ + c: 0, + i: false, + m: false, + b: [] + } satisfies IQuestStage); + + const completedQuestKey: IQuestKeyDatabase = { + ItemType: questKey, + Completed: true, + unlock: true, + Progress: Progress, + CompletionDate: new Date() + }; + + //overwrite current quest progress, might lead to multiple quest item rewards + if (existingQuestKey) { + existingQuestKey.overwrite(completedQuestKey); + //Object.assign(existingQuestKey, completedQuestKey); + } else { + addQuestKey(inventory, completedQuestKey); + } + + for (let i = 0; i < chainStageTotal; i++) { + if (chainStages[i].itemsToGiveWhenTriggered.length > 0) { + await giveKeyChainItem(inventory, { KeyChain: questKey, ChainStage: i }); + } + + if (chainStages[i].messageToSendWhenTriggered) { + await giveKeyChainMessage(inventory, inventory.accountOwnerId.toString(), { + KeyChain: questKey, + ChainStage: i + }); + } + } +}; + +export const giveKeyChainItem = async (inventory: TInventoryDatabaseDocument, keyChainInfo: IKeyChainRequest) => { + const inventoryChanges = await addKeyChainItems(inventory, keyChainInfo); + + if (isEmptyObject(inventoryChanges)) { + throw new Error("inventory changes was empty after getting keychain items: should not happen"); + } + // items were added: update quest stage's i (item was given) + updateQuestStage(inventory, keyChainInfo, { i: true }); + + //TODO: Check whether Wishlist is used to track items which should exist uniquely in the inventory + /* + some items are added or removed (not sure) to the wishlist, in that case a + WishlistChanges: ["/Lotus/Types/Items/ShipFeatureItems/ArsenalFeatureItem"], + is added to the response, need to determine for which items this is the case and what purpose this has. + */ + //{"KeyChain":"/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain","ChainStage":0} + //{"WishlistChanges":["/Lotus/Types/Items/ShipFeatureItems/ArsenalFeatureItem"],"MiscItems":[{"ItemType":"/Lotus/Types/Items/ShipFeatureItems/ArsenalFeatureItem","ItemCount":1}]} +}; + +export const giveKeyChainMessage = async ( + inventory: TInventoryDatabaseDocument, + accountId: string, + keyChainInfo: IKeyChainRequest +) => { + const keyChainMessage = getKeyChainMessage(keyChainInfo); + + const message = { + sndr: keyChainMessage.sender, + msg: keyChainMessage.body, + sub: keyChainMessage.title, + att: keyChainMessage.attachments.length > 0 ? keyChainMessage.attachments : undefined, + countedAtt: keyChainMessage.countedAttachments.length > 0 ? keyChainMessage.countedAttachments : undefined, + icon: keyChainMessage.icon ?? "", + transmission: keyChainMessage.transmission ?? "", + highPriority: keyChainMessage.highPriority ?? false, + r: false + } satisfies IMessage; + + await createMessage(accountId, [message]); + + updateQuestStage(inventory, keyChainInfo, { m: true }); +}; -- 2.47.2 From f89fe283324c617325b7c27225fd26af53d24de0 Mon Sep 17 00:00:00 2001 From: Ordis <134585663+OrdisPrime@users.noreply.github.com> Date: Wed, 19 Feb 2025 18:58:28 +0100 Subject: [PATCH 2/4] lint --- src/controllers/api/giveKeyChainTriggeredItemsController.ts | 6 +++--- src/controllers/custom/manageQuestsController.ts | 2 -- src/services/questService.ts | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/controllers/api/giveKeyChainTriggeredItemsController.ts b/src/controllers/api/giveKeyChainTriggeredItemsController.ts index 4ce867d4..8e391b01 100644 --- a/src/controllers/api/giveKeyChainTriggeredItemsController.ts +++ b/src/controllers/api/giveKeyChainTriggeredItemsController.ts @@ -1,9 +1,9 @@ import { RequestHandler } from "express"; -import { isEmptyObject, parseString } from "@/src/helpers/general"; +import { parseString } from "@/src/helpers/general"; import { getJSONfromString } from "@/src/helpers/stringHelpers"; -import { addKeyChainItems, getInventory } from "@/src/services/inventoryService"; +import { getInventory } from "@/src/services/inventoryService"; import { IGroup } from "@/src/types/loginTypes"; -import { giveKeyChainItem, updateQuestStage } from "@/src/services/questService"; +import { giveKeyChainItem } from "@/src/services/questService"; export const giveKeyChainTriggeredItemsController: RequestHandler = async (req, res) => { const accountId = parseString(req.query.accountId); diff --git a/src/controllers/custom/manageQuestsController.ts b/src/controllers/custom/manageQuestsController.ts index 92f46212..fc542248 100644 --- a/src/controllers/custom/manageQuestsController.ts +++ b/src/controllers/custom/manageQuestsController.ts @@ -1,9 +1,7 @@ import { addString } from "@/src/controllers/api/inventoryController"; -import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel"; import { getInventory } from "@/src/services/inventoryService"; import { getAccountIdForRequest } from "@/src/services/loginService"; import { addQuestKey, completeQuest, IUpdateQuestRequest, updateQuestKey } from "@/src/services/questService"; -import { IQuestStage } from "@/src/types/inventoryTypes/inventoryTypes"; import { logger } from "@/src/utils/logger"; import { RequestHandler } from "express"; import { ExportKeys } from "warframe-public-export-plus"; diff --git a/src/services/questService.ts b/src/services/questService.ts index 95e03b32..90088cb8 100644 --- a/src/services/questService.ts +++ b/src/services/questService.ts @@ -3,7 +3,7 @@ import { isEmptyObject } from "@/src/helpers/general"; import { IMessage } from "@/src/models/inboxModel"; import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel"; import { createMessage } from "@/src/services/inboxService"; -import { addKeyChainItems, getInventory } from "@/src/services/inventoryService"; +import { addKeyChainItems } from "@/src/services/inventoryService"; import { getKeyChainMessage } from "@/src/services/itemDataService"; import { IInventoryDatabase, IQuestKeyDatabase, IQuestStage } from "@/src/types/inventoryTypes/inventoryTypes"; import { logger } from "@/src/utils/logger"; -- 2.47.2 From bbb54f28fdb9d0f2b0008203c46b3e8d3e5a8d47 Mon Sep 17 00:00:00 2001 From: Ordis <134585663+OrdisPrime@users.noreply.github.com> Date: Wed, 19 Feb 2025 19:53:33 +0100 Subject: [PATCH 3/4] note --- src/services/questService.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/services/questService.ts b/src/services/questService.ts index 90088cb8..e51eb70a 100644 --- a/src/services/questService.ts +++ b/src/services/questService.ts @@ -126,6 +126,7 @@ export const completeQuest = async (inventory: TInventoryDatabaseDocument, quest }); } } + //TODO: handle quest completions }; export const giveKeyChainItem = async (inventory: TInventoryDatabaseDocument, keyChainInfo: IKeyChainRequest) => { -- 2.47.2 From 59ad58a968ef8965f5630e2ced8ef8934cfdef13 Mon Sep 17 00:00:00 2001 From: Ordis <134585663+OrdisPrime@users.noreply.github.com> Date: Wed, 19 Feb 2025 22:25:06 +0100 Subject: [PATCH 4/4] fix --- .../custom/manageQuestsController.ts | 22 +++++++++++++++++-- src/services/inventoryService.ts | 6 ++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/controllers/custom/manageQuestsController.ts b/src/controllers/custom/manageQuestsController.ts index fc542248..49283bf3 100644 --- a/src/controllers/custom/manageQuestsController.ts +++ b/src/controllers/custom/manageQuestsController.ts @@ -39,7 +39,16 @@ export const manageQuestsController: RequestHandler = async (req, res) => { case "completeAll": { logger.info("completing all quests.."); for (const questKey of allQuestKeys) { - await completeQuest(inventory, questKey); + try { + await completeQuest(inventory, questKey); + } catch (error) { + if (error instanceof Error) { + logger.error( + `Something went wrong completing quest ${questKey}, probably could not add some item` + ); + logger.error(error.message); + } + } //Skip "Watch The Maker" if (questKey === "/Lotus/Types/Keys/NewWarIntroQuest/NewWarIntroKeyChain") { @@ -70,7 +79,16 @@ export const manageQuestsController: RequestHandler = async (req, res) => { logger.info("completing all unlocked quests.."); for (const questKey of inventory.QuestKeys) { console.log("size of questkeys", inventory.QuestKeys.length); - await completeQuest(inventory, questKey.ItemType); + try { + await completeQuest(inventory, questKey.ItemType); + } catch (error) { + if (error instanceof Error) { + logger.error( + `Something went wrong completing quest ${questKey.ItemType}, probably could not add some item` + ); + logger.error(error.message); + } + } //Skip "Watch The Maker" if (questKey.ItemType === "/Lotus/Types/Keys/NewWarIntroQuest/NewWarIntroKeyChain") { diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts index 62ae920f..7719b2e8 100644 --- a/src/services/inventoryService.ts +++ b/src/services/inventoryService.ts @@ -367,7 +367,7 @@ export const addItem = async ( }; } if (typeName in ExportKeys) { - // Note: "/Lotus/Types/Keys/" contains some EmailItems and ShipFeatureItems + // Note: "/Lotus/Types/Keys/" contains some EmailItems inventory.QuestKeys.push({ ItemType: typeName }); return { InventoryChanges: { @@ -519,9 +519,7 @@ export const addItem = async ( } break; } - const errorMessage = `unable to add item: ${typeName}`; - logger.error(errorMessage); - return { InventoryChanges: { Error: [{ Error: errorMessage }] } }; + throw new Error(`unable to add item: ${typeName}`); }; export const addItems = async ( -- 2.47.2