diff --git a/src/controllers/api/artifactsController.ts b/src/controllers/api/artifactsController.ts new file mode 100644 index 00000000..bb69d486 --- /dev/null +++ b/src/controllers/api/artifactsController.ts @@ -0,0 +1,23 @@ +import { upgradeMod } from "@/src/services/inventoryService"; +import { RequestHandler } from "express"; + +// eslint-disable-next-line @typescript-eslint/no-misused-promises +const artifactsController: RequestHandler = async (req, res) => { + const [data] = String(req.body).split("\n"); + const id = req.query.accountId as string; + + // TODO - salt check + + try { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const parsedData = JSON.parse(data); + + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + await upgradeMod(parsedData, id); + res.json({}); + } catch (err) { + console.error("Error parsing JSON data:", err); + } +}; + +export { artifactsController }; diff --git a/src/controllers/api/missionInventoryUpdateController.ts b/src/controllers/api/missionInventoryUpdateController.ts index 346ce085..3055fa87 100644 --- a/src/controllers/api/missionInventoryUpdateController.ts +++ b/src/controllers/api/missionInventoryUpdateController.ts @@ -83,6 +83,7 @@ const missionInventoryUpdateController: RequestHandler = async (req, res) => { - [x] CreditsBonus - [x] MissionCredits - [ ] InventoryChanges +- [ ] FusionPoints int */ export { missionInventoryUpdateController }; diff --git a/src/models/inventoryModel.ts b/src/models/inventoryModel.ts index f73dd1fb..a9b0ec3f 100644 --- a/src/models/inventoryModel.ts +++ b/src/models/inventoryModel.ts @@ -1,7 +1,7 @@ import { Model, Schema, Types, model } from "mongoose"; import { FlavourItem, RawUpgrade, MiscItem, IInventoryDatabase, Booster } from "../types/inventoryTypes/inventoryTypes"; import { Oid } from "../types/commonTypes"; -import { ISuitDatabase, ISuitDocument } from "@/src/types/inventoryTypes/SuitTypes"; +import { ISuitDatabase } from "@/src/types/inventoryTypes/SuitTypes"; import { IWeaponDatabase } from "@/src/types/inventoryTypes/weaponTypes"; const abilityOverrideSchema = new Schema({ @@ -71,6 +71,24 @@ const BoosterSchema = new Schema({ ItemType: String }); +const RawUpgrades = new Schema({ + ItemType: String, + UpgradeFingerprint: String, + PendingRerollFingerprint: String, + ItemCount: Number +}); + +RawUpgrades.set("toJSON", { + transform(_document, returnedObject) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call + returnedObject.ItemId = { $oid: returnedObject._id.toString() } satisfies Oid; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call + returnedObject.LastAdded = { $oid: returnedObject.__v.toString() } satisfies Oid; + delete returnedObject._id; + delete returnedObject.__v; + } +}); + WeaponSchema.set("toJSON", { transform(_document, returnedObject) { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call @@ -181,7 +199,7 @@ const inventorySchema = new Schema({ MiscItems: [Schema.Types.Mixed], ChallengesFixVersion: Number, ChallengeProgress: [Schema.Types.Mixed], - RawUpgrades: [Schema.Types.Mixed], + RawUpgrades: [RawUpgrades], ReceivedStartingGear: Boolean, Suits: [suitSchema], LongGuns: [WeaponSchema], @@ -344,7 +362,7 @@ type InventoryDocumentProps = { Boosters: Types.DocumentArray; }; -type InventoryModelType = Model; +type InventoryModelType = Model; const Inventory = model("Inventory", inventorySchema); diff --git a/src/routes/api.ts b/src/routes/api.ts index c52a8056..3308b6d6 100644 --- a/src/routes/api.ts +++ b/src/routes/api.ts @@ -29,6 +29,7 @@ import { updateSessionGetController, updateSessionPostController } from "@/src/c import { viewController } from "@/src/controllers/api/viewController"; import { joinSessionController } from "@/src/controllers/api/joinSessionController"; import { saveLoadoutController } from "@/src/controllers/api/saveLoadout"; +import { artifactsController } from "../controllers/api/artifactsController"; import express from "express"; @@ -58,6 +59,7 @@ apiRouter.get("/deleteSession.php", deleteSessionController); apiRouter.get("/logout.php", logoutController); // post +apiRouter.post("/artifacts.php", artifactsController); apiRouter.post("/findSessions.php", findSessionsController); // eslint-disable-next-line @typescript-eslint/no-misused-promises apiRouter.post("/purchase.php", purchaseController); diff --git a/src/services/inventoryService.ts b/src/services/inventoryService.ts index 490a0157..9741711a 100644 --- a/src/services/inventoryService.ts +++ b/src/services/inventoryService.ts @@ -5,13 +5,14 @@ import { Types } from "mongoose"; import { ISuitResponse } from "@/src/types/inventoryTypes/SuitTypes"; import { SlotType } from "@/src/types/purchaseTypes"; import { IWeaponResponse } from "@/src/types/inventoryTypes/weaponTypes"; -import { ChallengeProgress, FlavourItem, IInventoryDatabaseDocument } from "@/src/types/inventoryTypes/inventoryTypes"; import { - MissionInventoryUpdate, - MissionInventoryUpdateCard, - MissionInventoryUpdateGear, - MissionInventoryUpdateItem -} from "../types/missionInventoryUpdateType"; + ChallengeProgress, + FlavourItem, + IInventoryDatabaseDocument, + MiscItem, + RawUpgrade +} from "@/src/types/inventoryTypes/inventoryTypes"; +import { MissionInventoryUpdate, MissionInventoryUpdateGear } from "../types/missionInventoryUpdateType"; const createInventory = async (accountOwnerId: Types.ObjectId) => { try { @@ -130,21 +131,33 @@ const addGearExpByCategory = ( }); }; -const addItemsByCategory = ( - inventory: IInventoryDatabaseDocument, - itemsArray: (MissionInventoryUpdateItem | MissionInventoryUpdateCard)[] | undefined, - categoryName: "RawUpgrades" | "MiscItems" -) => { - const category = inventory[categoryName]; +const addMiscItems = (inventory: IInventoryDatabaseDocument, itemsArray: MiscItem[] | undefined) => { + const { MiscItems } = inventory; itemsArray?.forEach(({ ItemCount, ItemType }) => { - const itemIndex = category.findIndex(i => i.ItemType === ItemType); + const itemIndex = MiscItems.findIndex(i => i.ItemType === ItemType); if (itemIndex !== -1) { - category[itemIndex].ItemCount += ItemCount; - inventory.markModified(`${categoryName}.${itemIndex}.ItemCount`); + MiscItems[itemIndex].ItemCount += ItemCount; + inventory.markModified(`MiscItems.${itemIndex}.ItemCount`); } else { - category.push({ ItemCount, ItemType }); + MiscItems.push({ ItemCount, ItemType }); + } + }); +}; + +const addMods = (inventory: IInventoryDatabaseDocument, itemsArray: RawUpgrade[] | undefined) => { + const { RawUpgrades } = inventory; + itemsArray?.forEach(({ ItemType, ItemCount, UpgradeFingerprint }) => { + const itemIndex = RawUpgrades.findIndex( + i => i.ItemType === ItemType && i.UpgradeFingerprint === UpgradeFingerprint + ); + + if (itemIndex !== -1) { + RawUpgrades[itemIndex].ItemCount += ItemCount; + inventory.markModified(`RawUpgrades.${itemIndex}.ItemCount`); + } else { + RawUpgrades.push({ ItemCount, ItemType }); } }); }; @@ -171,7 +184,8 @@ export const missionInventoryUpdate = async (data: MissionInventoryUpdate, accou const { RawUpgrades, MiscItems, RegularCredits, ChallengeProgress } = data; const inventory = await getInventory(accountId); - // TODO - multipliers logic + // TODO - multipliers logic for mission reward (looted comes multiplied) + // credits inventory.RegularCredits += RegularCredits || 0; @@ -179,8 +193,8 @@ export const missionInventoryUpdate = async (data: MissionInventoryUpdate, accou gearKeys.forEach((key: GearKeysType) => addGearExpByCategory(inventory, data[key], key)); // other - addItemsByCategory(inventory, RawUpgrades, "RawUpgrades"); // TODO - check mods fusion level - addItemsByCategory(inventory, MiscItems, "MiscItems"); + addMods(inventory, RawUpgrades); + addMiscItems(inventory, MiscItems); addChallenges(inventory, ChallengeProgress); const changedInventory = await inventory.save(); @@ -206,4 +220,62 @@ export const addBooster = async (ItemType: string, time: number, accountId: stri await inventory.save(); }; +export const upgradeMod = async ( + { + Upgrade, + LevelDiff, + Cost, + FusionPointCost + }: { Upgrade: RawUpgrade; LevelDiff: number; Cost: number; FusionPointCost: number }, + accountId: string +): Promise => { + const inventory = await getInventory(accountId); + const { RawUpgrades } = inventory; + const { ItemCount, ItemType, UpgradeFingerprint } = Upgrade; + const itemIndex = RawUpgrades.findIndex( + i => i.ItemType === ItemType && i.UpgradeFingerprint === UpgradeFingerprint + ); + + const safeUpgradeFingerprint = UpgradeFingerprint || '{"lvl":0}'; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const parsedUpgradeFingerprint = JSON.parse(safeUpgradeFingerprint); + parsedUpgradeFingerprint.lvl += LevelDiff; + + if (!ItemCount) return; + + RawUpgrades[itemIndex].ItemCount--; + + if (RawUpgrades[itemIndex].ItemCount > 0) { + inventory.markModified(`RawUpgrades.${itemIndex}.ItemCount`); + } else { + RawUpgrades.splice(itemIndex, 1); + inventory.markModified(`RawUpgrades`); + } + + addMods(inventory, [{ ItemType, ItemCount: 1, UpgradeFingerprint: JSON.stringify(parsedUpgradeFingerprint) }]); + + inventory.RegularCredits -= Cost; + inventory.FusionPoints -= FusionPointCost; + + await inventory.save(); + // { + // "Upgrade": { + // ItemType: "/Lotus/Upgrades/Mods/Warframe/Beginner/AvatarShieldMaxModBeginner", + // ItemId: { + // $oid: "" + // }, + // UpgradeFingerprint: '{"lvl":1}', + // PendingRerollFingerprint: "", + // ItemCount: 2, + // LastAdded: { + // $oid: "64f01ab0c4dfa3a8ef090043" + // } + // } + // "LevelDiff": 1, + // "Consumed": [], + // "Cost": 483, + // "FusionPointCost": 10 + // } +}; + export { createInventory, addPowerSuit }; diff --git a/src/types/inventoryTypes/inventoryTypes.ts b/src/types/inventoryTypes/inventoryTypes.ts index b175dc64..36ffbdbd 100644 --- a/src/types/inventoryTypes/inventoryTypes.ts +++ b/src/types/inventoryTypes/inventoryTypes.ts @@ -377,11 +377,6 @@ export interface FlavourItem { ItemType: string; } -export interface RawUpgrade { - ItemCount: number; - ItemType: string; -} - export interface MiscItem { ItemCount: number; ItemType: string; @@ -928,9 +923,11 @@ export interface Progress { } export interface RawUpgrade { - ItemCount: number; - LastAdded?: Oid; ItemType: string; + ItemCount: number; + UpgradeFingerprint?: string; + PendingRerollFingerprint?: string; + LastAdded?: Oid; } export interface Scoop { diff --git a/src/types/missionInventoryUpdateType.ts b/src/types/missionInventoryUpdateType.ts index dcc88da0..74025ce7 100644 --- a/src/types/missionInventoryUpdateType.ts +++ b/src/types/missionInventoryUpdateType.ts @@ -1,14 +1,14 @@ -interface MongooseId{ +interface MongooseId { $oid: string; } -interface ExpireDate{ +interface ExpireDate { $date: { $numberLong: string; - } + }; } -export interface MissionInventoryUpdateGear{ +export interface MissionInventoryUpdateGear { ItemType: string; ItemName: string; ItemId: MongooseId; @@ -32,25 +32,25 @@ export interface MissionInventoryUpdateGear{ ArchonCrystalUpgrades: any[]; } -export interface MissionInventoryUpdateItem{ +export interface MissionInventoryUpdateItem { ItemCount: number; ItemType: string; } -export interface MissionInventoryUpdateCard extends MissionInventoryUpdateItem{ +export interface MissionInventoryUpdateCard extends MissionInventoryUpdateItem { ItemId: MongooseId; UpgradeFingerprint: string; PendingRerollFingerprint: string; LastAdded: MongooseId; } -interface MissionInventoryUpdateChallange{ +interface MissionInventoryUpdateChallange { Name: string; Progress: number; Completed: any[]; } -export interface MissionInventoryUpdate{ +export interface MissionInventoryUpdate { rewardsMultiplier?: number; ActiveBoosters?: any[]; LongGuns?: MissionInventoryUpdateGear[];