chore: some initial handling of legacy oid format #2033
@ -4,9 +4,9 @@
 | 
			
		||||
import { RequestHandler } from "express";
 | 
			
		||||
import { logger } from "@/src/utils/logger";
 | 
			
		||||
import { getRecipe } from "@/src/services/itemDataService";
 | 
			
		||||
import { IOid } from "@/src/types/commonTypes";
 | 
			
		||||
import { IOid, IOidWithLegacySupport } from "@/src/types/commonTypes";
 | 
			
		||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
			
		||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
			
		||||
import { getAccountForRequest } from "@/src/services/loginService";
 | 
			
		||||
import {
 | 
			
		||||
    getInventory,
 | 
			
		||||
    updateCurrency,
 | 
			
		||||
@ -18,7 +18,7 @@ import {
 | 
			
		||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
			
		||||
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
			
		||||
import { InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
			
		||||
import { toOid } from "@/src/helpers/inventoryHelpers";
 | 
			
		||||
import { toOid2 } from "@/src/helpers/inventoryHelpers";
 | 
			
		||||
 | 
			
		||||
interface IClaimCompletedRecipeRequest {
 | 
			
		||||
    RecipeIds: IOid[];
 | 
			
		||||
@ -26,10 +26,8 @@ interface IClaimCompletedRecipeRequest {
 | 
			
		||||
 | 
			
		||||
export const claimCompletedRecipeController: RequestHandler = async (req, res) => {
 | 
			
		||||
    const claimCompletedRecipeRequest = getJSONfromString<IClaimCompletedRecipeRequest>(String(req.body));
 | 
			
		||||
    const accountId = await getAccountIdForRequest(req);
 | 
			
		||||
    if (!accountId) throw new Error("no account id");
 | 
			
		||||
 | 
			
		||||
    const inventory = await getInventory(accountId);
 | 
			
		||||
    const account = await getAccountForRequest(req);
 | 
			
		||||
    const inventory = await getInventory(account._id.toString());
 | 
			
		||||
    const pendingRecipe = inventory.PendingRecipes.id(claimCompletedRecipeRequest.RecipeIds[0].$oid);
 | 
			
		||||
    if (!pendingRecipe) {
 | 
			
		||||
        throw new Error(`no pending recipe found with id ${claimCompletedRecipeRequest.RecipeIds[0].$oid}`);
 | 
			
		||||
@ -81,7 +79,7 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
 | 
			
		||||
    } else {
 | 
			
		||||
        logger.debug("Claiming Recipe", { recipe, pendingRecipe });
 | 
			
		||||
 | 
			
		||||
        let BrandedSuits: undefined | IOid[];
 | 
			
		||||
        let BrandedSuits: undefined | IOidWithLegacySupport[];
 | 
			
		||||
        if (recipe.secretIngredientAction == "SIA_SPECTRE_LOADOUT_COPY") {
 | 
			
		||||
            inventory.PendingSpectreLoadouts ??= [];
 | 
			
		||||
            inventory.SpectreLoadouts ??= [];
 | 
			
		||||
@ -106,7 +104,7 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
 | 
			
		||||
                inventory.BrandedSuits!.findIndex(x => x.equals(pendingRecipe.SuitToUnbrand)),
 | 
			
		||||
                1
 | 
			
		||||
            );
 | 
			
		||||
            BrandedSuits = [toOid(pendingRecipe.SuitToUnbrand!)];
 | 
			
		||||
            BrandedSuits = [toOid2(pendingRecipe.SuitToUnbrand!, account.BuildLabel)];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let InventoryChanges: IInventoryChanges = {};
 | 
			
		||||
 | 
			
		||||
@ -25,10 +25,10 @@ import { logger } from "@/src/utils/logger";
 | 
			
		||||
import { catBreadHash } from "@/src/helpers/stringHelpers";
 | 
			
		||||
import { Types } from "mongoose";
 | 
			
		||||
import { isNemesisCompatibleWithVersion } from "@/src/helpers/nemesisHelpers";
 | 
			
		||||
import { version_compare } from "@/src/services/worldStateService";
 | 
			
		||||
import { getPersonalRooms } from "@/src/services/personalRoomsService";
 | 
			
		||||
import { IPersonalRoomsClient } from "@/src/types/personalRoomsTypes";
 | 
			
		||||
import { Ship } from "@/src/models/shipModel";
 | 
			
		||||
import { toLegacyOid, version_compare } from "@/src/helpers/inventoryHelpers";
 | 
			
		||||
 | 
			
		||||
export const inventoryController: RequestHandler = async (request, response) => {
 | 
			
		||||
    const account = await getAccountForRequest(request);
 | 
			
		||||
@ -306,19 +306,34 @@ export const getInventoryResponse = async (
 | 
			
		||||
    // Set 2FA enabled so trading post can be used
 | 
			
		||||
    inventoryResponse.HWIDProtectEnabled = true;
 | 
			
		||||
 | 
			
		||||
    // Fix nemesis for older versions
 | 
			
		||||
    if (
 | 
			
		||||
        inventoryResponse.Nemesis &&
 | 
			
		||||
        buildLabel &&
 | 
			
		||||
        !isNemesisCompatibleWithVersion(inventoryResponse.Nemesis, buildLabel)
 | 
			
		||||
    ) {
 | 
			
		||||
        inventoryResponse.Nemesis = undefined;
 | 
			
		||||
    }
 | 
			
		||||
    if (buildLabel) {
 | 
			
		||||
        // Fix nemesis for older versions
 | 
			
		||||
        if (inventoryResponse.Nemesis && !isNemesisCompatibleWithVersion(inventoryResponse.Nemesis, buildLabel)) {
 | 
			
		||||
            inventoryResponse.Nemesis = undefined;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    if (buildLabel && version_compare(buildLabel, "2018.02.22.14.34") < 0) {
 | 
			
		||||
        const personalRoomsDb = await getPersonalRooms(inventory.accountOwnerId.toString());
 | 
			
		||||
        const personalRooms = personalRoomsDb.toJSON<IPersonalRoomsClient>();
 | 
			
		||||
        inventoryResponse.Ship = personalRooms.Ship;
 | 
			
		||||
        if (version_compare(buildLabel, "2018.02.22.14.34") < 0) {
 | 
			
		||||
            const personalRoomsDb = await getPersonalRooms(inventory.accountOwnerId.toString());
 | 
			
		||||
            const personalRooms = personalRoomsDb.toJSON<IPersonalRoomsClient>();
 | 
			
		||||
            inventoryResponse.Ship = personalRooms.Ship;
 | 
			
		||||
 | 
			
		||||
            if (version_compare(buildLabel, "2016.12.21.19.13") <= 0) {
 | 
			
		||||
                // U19.5 and below use $id instead of $oid
 | 
			
		||||
                for (const category of equipmentKeys) {
 | 
			
		||||
                    for (const item of inventoryResponse[category]) {
 | 
			
		||||
                        toLegacyOid(item.ItemId);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                for (const upgrade of inventoryResponse.Upgrades) {
 | 
			
		||||
                    toLegacyOid(upgrade.ItemId);
 | 
			
		||||
                }
 | 
			
		||||
                if (inventoryResponse.BrandedSuits) {
 | 
			
		||||
                    for (const id of inventoryResponse.BrandedSuits) {
 | 
			
		||||
                        toLegacyOid(id);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return inventoryResponse;
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@ import { Account } from "@/src/models/loginModel";
 | 
			
		||||
import { createAccount, isCorrectPassword, isNameTaken } from "@/src/services/loginService";
 | 
			
		||||
import { IDatabaseAccountJson, ILoginRequest, ILoginResponse } from "@/src/types/loginTypes";
 | 
			
		||||
import { logger } from "@/src/utils/logger";
 | 
			
		||||
import { version_compare } from "@/src/services/worldStateService";
 | 
			
		||||
import { version_compare } from "@/src/helpers/inventoryHelpers";
 | 
			
		||||
 | 
			
		||||
export const loginController: RequestHandler = async (request, response) => {
 | 
			
		||||
    const loginRequest = JSON.parse(String(request.body)) as ILoginRequest; // parse octet stream of json data to json object
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
import { version_compare } from "@/src/helpers/inventoryHelpers";
 | 
			
		||||
import { Alliance, Guild, GuildMember } from "@/src/models/guildModel";
 | 
			
		||||
import { hasGuildPermissionEx } from "@/src/services/guildService";
 | 
			
		||||
import { getInventory } from "@/src/services/inventoryService";
 | 
			
		||||
import { getAccountForRequest, getSuffixedName } from "@/src/services/loginService";
 | 
			
		||||
import { version_compare } from "@/src/services/worldStateService";
 | 
			
		||||
import { GuildPermission, ILongMOTD } from "@/src/types/guildTypes";
 | 
			
		||||
import { RequestHandler } from "express";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
import { applyClientEquipmentUpdates, getInventory } from "@/src/services/inventoryService";
 | 
			
		||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
			
		||||
import { IOid } from "@/src/types/commonTypes";
 | 
			
		||||
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
			
		||||
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
			
		||||
import { RequestHandler } from "express";
 | 
			
		||||
@ -11,7 +12,7 @@ export const addXpController: RequestHandler = async (req, res) => {
 | 
			
		||||
    const request = req.body as IAddXpRequest;
 | 
			
		||||
    for (const [category, gear] of Object.entries(request)) {
 | 
			
		||||
        for (const clientItem of gear) {
 | 
			
		||||
            const dbItem = inventory[category as TEquipmentKey].id(clientItem.ItemId.$oid);
 | 
			
		||||
            const dbItem = inventory[category as TEquipmentKey].id((clientItem.ItemId as IOid).$oid);
 | 
			
		||||
            if (dbItem) {
 | 
			
		||||
                if (dbItem.ItemType in ExportMisc.uniqueLevelCaps) {
 | 
			
		||||
                    if ((dbItem.Polarized ?? 0) < 5) {
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,46 @@
 | 
			
		||||
import { IMongoDate, IOid } from "@/src/types/commonTypes";
 | 
			
		||||
import { IMongoDate, IOid, IOidWithLegacySupport } from "@/src/types/commonTypes";
 | 
			
		||||
import { Types } from "mongoose";
 | 
			
		||||
import { TRarity } from "warframe-public-export-plus";
 | 
			
		||||
 | 
			
		||||
export const version_compare = (a: string, b: string): number => {
 | 
			
		||||
    const a_digits = a
 | 
			
		||||
        .split("/")[0]
 | 
			
		||||
        .split(".")
 | 
			
		||||
        .map(x => parseInt(x));
 | 
			
		||||
    const b_digits = b
 | 
			
		||||
        .split("/")[0]
 | 
			
		||||
        .split(".")
 | 
			
		||||
        .map(x => parseInt(x));
 | 
			
		||||
    for (let i = 0; i != a_digits.length; ++i) {
 | 
			
		||||
        if (a_digits[i] != b_digits[i]) {
 | 
			
		||||
            return a_digits[i] > b_digits[i] ? 1 : -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const toOid = (objectId: Types.ObjectId): IOid => {
 | 
			
		||||
    return { $oid: objectId.toString() } satisfies IOid;
 | 
			
		||||
    return { $oid: objectId.toString() };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function toOid2(objectId: Types.ObjectId, buildLabel: undefined): IOid;
 | 
			
		||||
export function toOid2(objectId: Types.ObjectId, buildLabel: string | undefined): IOidWithLegacySupport;
 | 
			
		||||
export function toOid2(objectId: Types.ObjectId, buildLabel: string | undefined): IOidWithLegacySupport {
 | 
			
		||||
    if (buildLabel && version_compare(buildLabel, "2016.12.21.19.13") <= 0) {
 | 
			
		||||
        return { $id: objectId.toString() };
 | 
			
		||||
    }
 | 
			
		||||
    return { $oid: objectId.toString() };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const toLegacyOid = (oid: IOidWithLegacySupport): void => {
 | 
			
		||||
    if (!("$id" in oid)) {
 | 
			
		||||
        oid.$id = oid.$oid;
 | 
			
		||||
        delete oid.$oid;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const fromOid = (oid: IOidWithLegacySupport): string => {
 | 
			
		||||
    return (oid.$oid ?? oid.$id)!;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const toMongoDate = (date: Date): IMongoDate => {
 | 
			
		||||
 | 
			
		||||
@ -6,9 +6,10 @@ import { logger } from "../utils/logger";
 | 
			
		||||
import { IOid } from "../types/commonTypes";
 | 
			
		||||
import { Types } from "mongoose";
 | 
			
		||||
import { addMods, generateRewardSeed } from "../services/inventoryService";
 | 
			
		||||
import { isArchwingMission, version_compare } from "../services/worldStateService";
 | 
			
		||||
import { isArchwingMission } from "../services/worldStateService";
 | 
			
		||||
import { fromStoreItem, toStoreItem } from "../services/itemDataService";
 | 
			
		||||
import { createMessage } from "../services/inboxService";
 | 
			
		||||
import { version_compare } from "./inventoryHelpers";
 | 
			
		||||
 | 
			
		||||
export const getInfNodes = (faction: string, rank: number): IInfNode[] => {
 | 
			
		||||
    const infNodes = [];
 | 
			
		||||
 | 
			
		||||
@ -70,6 +70,7 @@ import { createShip } from "./shipService";
 | 
			
		||||
import {
 | 
			
		||||
    catbrowDetails,
 | 
			
		||||
    fromMongoDate,
 | 
			
		||||
    fromOid,
 | 
			
		||||
    kubrowDetails,
 | 
			
		||||
    kubrowFurPatternsWeights,
 | 
			
		||||
    kubrowWeights,
 | 
			
		||||
@ -423,7 +424,7 @@ export const addItem = async (
 | 
			
		||||
                changes.push({
 | 
			
		||||
                    ItemType: egg.ItemType,
 | 
			
		||||
                    ExpirationDate: { $date: { $numberLong: "2000000000000" } },
 | 
			
		||||
                    ItemId: toOid(egg._id)
 | 
			
		||||
                    ItemId: toOid(egg._id) // TODO: Pass on buildLabel from purchaseService
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
            return {
 | 
			
		||||
@ -1491,9 +1492,9 @@ export const applyClientEquipmentUpdates = (
 | 
			
		||||
    const category = inventory[categoryName];
 | 
			
		||||
 | 
			
		||||
    gearArray.forEach(({ ItemId, XP, InfestationDate }) => {
 | 
			
		||||
        const item = category.id(ItemId.$oid);
 | 
			
		||||
        const item = category.id(fromOid(ItemId));
 | 
			
		||||
        if (!item) {
 | 
			
		||||
            throw new Error(`No item with id ${ItemId.$oid} in ${categoryName}`);
 | 
			
		||||
            throw new Error(`No item with id ${fromOid(ItemId)} in ${categoryName}`);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (XP) {
 | 
			
		||||
 | 
			
		||||
@ -62,6 +62,7 @@ import { getLiteSortie, getSortie, idToBountyCycle, idToDay, idToWeek, pushClass
 | 
			
		||||
import { config } from "./configService";
 | 
			
		||||
import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
 | 
			
		||||
import { ISyndicateMissionInfo } from "../types/worldStateTypes";
 | 
			
		||||
import { fromOid } from "../helpers/inventoryHelpers";
 | 
			
		||||
 | 
			
		||||
const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[] => {
 | 
			
		||||
    // For Spy missions, e.g. 3 vaults cracked = A, B, C
 | 
			
		||||
@ -399,7 +400,7 @@ export const addMissionInventoryUpdates = async (
 | 
			
		||||
                break;
 | 
			
		||||
            case "Upgrades":
 | 
			
		||||
                value.forEach(clientUpgrade => {
 | 
			
		||||
                    const upgrade = inventory.Upgrades.id(clientUpgrade.ItemId.$oid)!;
 | 
			
		||||
                    const upgrade = inventory.Upgrades.id(fromOid(clientUpgrade.ItemId))!;
 | 
			
		||||
                    upgrade.UpgradeFingerprint = clientUpgrade.UpgradeFingerprint; // primitive way to copy over the riven challenge progress
 | 
			
		||||
                });
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,7 @@ import {
 | 
			
		||||
    ISyndicateMissionInfo,
 | 
			
		||||
    IWorldState
 | 
			
		||||
} from "../types/worldStateTypes";
 | 
			
		||||
import { version_compare } from "../helpers/inventoryHelpers";
 | 
			
		||||
 | 
			
		||||
const sortieBosses = [
 | 
			
		||||
    "SORTIE_BOSS_HYENA",
 | 
			
		||||
@ -1239,20 +1240,3 @@ export const isArchwingMission = (node: IRegion): boolean => {
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const version_compare = (a: string, b: string): number => {
 | 
			
		||||
    const a_digits = a
 | 
			
		||||
        .split("/")[0]
 | 
			
		||||
        .split(".")
 | 
			
		||||
        .map(x => parseInt(x));
 | 
			
		||||
    const b_digits = b
 | 
			
		||||
        .split("/")[0]
 | 
			
		||||
        .split(".")
 | 
			
		||||
        .map(x => parseInt(x));
 | 
			
		||||
    for (let i = 0; i != a_digits.length; ++i) {
 | 
			
		||||
        if (a_digits[i] != b_digits[i]) {
 | 
			
		||||
            return a_digits[i] > b_digits[i] ? 1 : -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,11 @@ export interface IOid {
 | 
			
		||||
    $oid: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IOidWithLegacySupport {
 | 
			
		||||
    $oid?: string;
 | 
			
		||||
    $id?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IMongoDate {
 | 
			
		||||
    $date: {
 | 
			
		||||
        $numberLong: string;
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
import { IMongoDate, IOid } from "@/src/types/commonTypes";
 | 
			
		||||
import { IMongoDate, IOid, IOidWithLegacySupport } from "@/src/types/commonTypes";
 | 
			
		||||
import { Types } from "mongoose";
 | 
			
		||||
import {
 | 
			
		||||
    ICrewShipCustomization,
 | 
			
		||||
@ -92,7 +92,7 @@ export interface IEquipmentClient
 | 
			
		||||
        IEquipmentDatabase,
 | 
			
		||||
        "_id" | "InfestationDate" | "Expiry" | "UpgradesExpiry" | "UmbraDate" | "CrewMembers" | "Details"
 | 
			
		||||
    > {
 | 
			
		||||
    ItemId: IOid;
 | 
			
		||||
    ItemId: IOidWithLegacySupport;
 | 
			
		||||
    InfestationDate?: IMongoDate;
 | 
			
		||||
    Expiry?: IMongoDate;
 | 
			
		||||
    UpgradesExpiry?: IMongoDate;
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
/* eslint-disable @typescript-eslint/no-explicit-any */
 | 
			
		||||
import { Types } from "mongoose";
 | 
			
		||||
import { IOid, IMongoDate } from "../commonTypes";
 | 
			
		||||
import { IOid, IMongoDate, IOidWithLegacySupport } from "../commonTypes";
 | 
			
		||||
import {
 | 
			
		||||
    IColor,
 | 
			
		||||
    IItemConfig,
 | 
			
		||||
@ -371,7 +371,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
 | 
			
		||||
    EchoesHexConquestCacheScoreMission?: number;
 | 
			
		||||
    EchoesHexConquestActiveFrameVariants?: string[];
 | 
			
		||||
    EchoesHexConquestActiveStickers?: string[];
 | 
			
		||||
    BrandedSuits?: IOid[];
 | 
			
		||||
    BrandedSuits?: IOidWithLegacySupport[];
 | 
			
		||||
    LockedWeaponGroup?: ILockedWeaponGroupClient;
 | 
			
		||||
    HubNpcCustomizations?: IHubNpcCustomization[];
 | 
			
		||||
    Ship?: IOrbiter; // U22 and below, response only
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user