forked from OpenWF/SpaceNinjaServer
feat: import (#831)
This commit is contained in:
parent
ee0bee5d7b
commit
c9b48ace36
@ -44,7 +44,7 @@ export const arcaneCommonController: RequestHandler = async (req, res) => {
|
|||||||
ItemType: json.arcane.ItemType,
|
ItemType: json.arcane.ItemType,
|
||||||
UpgradeFingerprint: JSON.stringify({ lvl: json.newRank })
|
UpgradeFingerprint: JSON.stringify({ lvl: json.newRank })
|
||||||
});
|
});
|
||||||
upgradeId = inventory.Upgrades[newLength - 1]._id!.toString();
|
upgradeId = inventory.Upgrades[newLength - 1]._id.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove RawUpgrades
|
// Remove RawUpgrades
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import { ICrewShipSalvagedWeaponSkin } from "@/src/types/inventoryTypes/inventoryTypes";
|
import { IInventoryClient, IUpgradeClient } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import { addMods, getInventory } from "@/src/services/inventoryService";
|
import { addMods, getInventory } from "@/src/services/inventoryService";
|
||||||
import { config } from "@/src/services/configService";
|
import { config } from "@/src/services/configService";
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ export const artifactsController: RequestHandler = async (req, res) => {
|
|||||||
parsedUpgradeFingerprint.lvl += LevelDiff;
|
parsedUpgradeFingerprint.lvl += LevelDiff;
|
||||||
const stringifiedUpgradeFingerprint = JSON.stringify(parsedUpgradeFingerprint);
|
const stringifiedUpgradeFingerprint = JSON.stringify(parsedUpgradeFingerprint);
|
||||||
|
|
||||||
let itemIndex = Upgrades.findIndex(upgrade => upgrade._id?.equals(ItemId!.$oid));
|
let itemIndex = Upgrades.findIndex(upgrade => upgrade._id.equals(ItemId.$oid));
|
||||||
|
|
||||||
if (itemIndex !== -1) {
|
if (itemIndex !== -1) {
|
||||||
Upgrades[itemIndex].UpgradeFingerprint = stringifiedUpgradeFingerprint;
|
Upgrades[itemIndex].UpgradeFingerprint = stringifiedUpgradeFingerprint;
|
||||||
@ -58,7 +58,7 @@ export const artifactsController: RequestHandler = async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const changedInventory = await inventory.save();
|
const changedInventory = await inventory.save();
|
||||||
const itemId = changedInventory.toJSON().Upgrades[itemIndex]?.ItemId?.$oid;
|
const itemId = changedInventory.toJSON<IInventoryClient>().Upgrades[itemIndex].ItemId.$oid;
|
||||||
|
|
||||||
if (!itemId) {
|
if (!itemId) {
|
||||||
throw new Error("Item Id not found in upgradeMod");
|
throw new Error("Item Id not found in upgradeMod");
|
||||||
@ -68,7 +68,7 @@ export const artifactsController: RequestHandler = async (req, res) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
interface IArtifactsRequest {
|
interface IArtifactsRequest {
|
||||||
Upgrade: ICrewShipSalvagedWeaponSkin;
|
Upgrade: IUpgradeClient;
|
||||||
LevelDiff: number;
|
LevelDiff: number;
|
||||||
Cost: number;
|
Cost: number;
|
||||||
FusionPointCost: number;
|
FusionPointCost: number;
|
||||||
|
@ -4,10 +4,10 @@ import allShipFeatures from "@/static/fixed_responses/allShipFeatures.json";
|
|||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { getPersonalRooms } from "@/src/services/personalRoomsService";
|
import { getPersonalRooms } from "@/src/services/personalRoomsService";
|
||||||
import { getShip } from "@/src/services/shipService";
|
import { getShip } from "@/src/services/shipService";
|
||||||
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
|
|
||||||
import { toOid } from "@/src/helpers/inventoryHelpers";
|
import { toOid } from "@/src/helpers/inventoryHelpers";
|
||||||
import { IGetShipResponse } from "@/src/types/shipTypes";
|
import { IGetShipResponse } from "@/src/types/shipTypes";
|
||||||
import { IPersonalRooms } from "@/src/types/personalRoomsTypes";
|
import { IPersonalRooms } from "@/src/types/personalRoomsTypes";
|
||||||
|
import { getLoadout } from "@/src/services/loadoutService";
|
||||||
|
|
||||||
export const getShipController: RequestHandler = async (req, res) => {
|
export const getShipController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
@ -38,13 +38,3 @@ export const getShipController: RequestHandler = async (req, res) => {
|
|||||||
|
|
||||||
res.json(getShipResponse);
|
res.json(getShipResponse);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getLoadout = async (accountId: string) => {
|
|
||||||
const loadout = await Loadout.findOne({ loadoutOwnerId: accountId });
|
|
||||||
|
|
||||||
if (!loadout) {
|
|
||||||
throw new Error(`loadout not found for account ${accountId}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return loadout;
|
|
||||||
};
|
|
||||||
|
@ -6,7 +6,7 @@ import { IOid } from "@/src/types/commonTypes";
|
|||||||
import {
|
import {
|
||||||
IConsumedSuit,
|
IConsumedSuit,
|
||||||
IHelminthFoodRecord,
|
IHelminthFoodRecord,
|
||||||
IInfestedFoundry,
|
IInfestedFoundryDatabase,
|
||||||
IMiscItem,
|
IMiscItem,
|
||||||
ITypeCount
|
ITypeCount
|
||||||
} from "@/src/types/inventoryTypes/inventoryTypes";
|
} from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
@ -356,7 +356,7 @@ interface IHelminthFeedRequest {
|
|||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const addInfestedFoundryXP = (infestedFoundry: IInfestedFoundry, delta: number): ITypeCount[] => {
|
export const addInfestedFoundryXP = (infestedFoundry: IInfestedFoundryDatabase, delta: number): ITypeCount[] => {
|
||||||
const recipeChanges: ITypeCount[] = [];
|
const recipeChanges: ITypeCount[] = [];
|
||||||
infestedFoundry.XP ??= 0;
|
infestedFoundry.XP ??= 0;
|
||||||
const prevXP = infestedFoundry.XP;
|
const prevXP = infestedFoundry.XP;
|
||||||
|
@ -4,7 +4,7 @@ import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
|
|||||||
import { config } from "@/src/services/configService";
|
import { config } from "@/src/services/configService";
|
||||||
import allDialogue from "@/static/fixed_responses/allDialogue.json";
|
import allDialogue from "@/static/fixed_responses/allDialogue.json";
|
||||||
import { ILoadoutDatabase } from "@/src/types/saveLoadoutTypes";
|
import { ILoadoutDatabase } from "@/src/types/saveLoadoutTypes";
|
||||||
import { IInventoryResponse, IShipInventory, equipmentKeys } from "@/src/types/inventoryTypes/inventoryTypes";
|
import { IInventoryClient, IShipInventory, equipmentKeys } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import { IPolarity, ArtifactPolarity, EquipmentFeatures } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
import { IPolarity, ArtifactPolarity, EquipmentFeatures } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||||
import {
|
import {
|
||||||
ExportCustoms,
|
ExportCustoms,
|
||||||
@ -55,7 +55,7 @@ export const inventoryController: RequestHandler = async (request, response) =>
|
|||||||
const inventoryWithLoadOutPresetsAndShips = await inventoryWithLoadOutPresets.populate<{ Ships: IShipInventory }>(
|
const inventoryWithLoadOutPresetsAndShips = await inventoryWithLoadOutPresets.populate<{ Ships: IShipInventory }>(
|
||||||
"Ships"
|
"Ships"
|
||||||
);
|
);
|
||||||
const inventoryResponse = inventoryWithLoadOutPresetsAndShips.toJSON<IInventoryResponse>();
|
const inventoryResponse = inventoryWithLoadOutPresetsAndShips.toJSON<IInventoryClient>();
|
||||||
|
|
||||||
if (config.infiniteCredits) {
|
if (config.infiniteCredits) {
|
||||||
inventoryResponse.RegularCredits = 999999999;
|
inventoryResponse.RegularCredits = 999999999;
|
||||||
@ -147,8 +147,9 @@ export const inventoryController: RequestHandler = async (request, response) =>
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (config.unlockAllSkins) {
|
if (config.unlockAllSkins) {
|
||||||
inventoryResponse.WeaponSkins = [];
|
const missingWeaponSkins = new Set(Object.keys(ExportCustoms));
|
||||||
for (const uniqueName in ExportCustoms) {
|
inventoryResponse.WeaponSkins.forEach(x => missingWeaponSkins.delete(x.ItemType));
|
||||||
|
for (const uniqueName of missingWeaponSkins) {
|
||||||
inventoryResponse.WeaponSkins.push({
|
inventoryResponse.WeaponSkins.push({
|
||||||
ItemId: {
|
ItemId: {
|
||||||
$oid: "ca70ca70ca70ca70" + catBreadHash(uniqueName).toString(16).padStart(8, "0")
|
$oid: "ca70ca70ca70ca70" + catBreadHash(uniqueName).toString(16).padStart(8, "0")
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
EquipmentFeatures,
|
EquipmentFeatures,
|
||||||
IAbilityOverride
|
IAbilityOverride
|
||||||
} from "@/src/types/inventoryTypes/commonInventoryTypes";
|
} from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||||
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
import { IInventoryClient, IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { addMiscItems, addRecipes, getInventory, updateCurrency } from "@/src/services/inventoryService";
|
import { addMiscItems, addRecipes, getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||||
import { getRecipeByResult } from "@/src/services/itemDataService";
|
import { getRecipeByResult } from "@/src/services/itemDataService";
|
||||||
@ -62,7 +62,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
|
|||||||
addRecipes(inventory, recipeChanges);
|
addRecipes(inventory, recipeChanges);
|
||||||
|
|
||||||
inventoryChanges.Recipes = recipeChanges;
|
inventoryChanges.Recipes = recipeChanges;
|
||||||
inventoryChanges.InfestedFoundry = inventory.toJSON().InfestedFoundry;
|
inventoryChanges.InfestedFoundry = inventory.toJSON<IInventoryClient>().InfestedFoundry;
|
||||||
} else
|
} else
|
||||||
switch (operation.UpgradeRequirement) {
|
switch (operation.UpgradeRequirement) {
|
||||||
case "/Lotus/Types/Items/MiscItems/OrokinReactor":
|
case "/Lotus/Types/Items/MiscItems/OrokinReactor":
|
||||||
|
@ -2,6 +2,7 @@ import { RequestHandler } from "express";
|
|||||||
import { getDict, getItemName, getString } from "@/src/services/itemDataService";
|
import { getDict, getItemName, getString } from "@/src/services/itemDataService";
|
||||||
import {
|
import {
|
||||||
ExportArcanes,
|
ExportArcanes,
|
||||||
|
ExportAvionics,
|
||||||
ExportGear,
|
ExportGear,
|
||||||
ExportRecipes,
|
ExportRecipes,
|
||||||
ExportResources,
|
ExportResources,
|
||||||
@ -137,6 +138,13 @@ const getItemListsController: RequestHandler = (req, response) => {
|
|||||||
badItems[uniqueName] = true;
|
badItems[uniqueName] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const [uniqueName, upgrade] of Object.entries(ExportAvionics)) {
|
||||||
|
res.mods.push({
|
||||||
|
uniqueName,
|
||||||
|
name: getString(upgrade.name, lang),
|
||||||
|
fusionLimit: upgrade.fusionLimit
|
||||||
|
});
|
||||||
|
}
|
||||||
for (const [uniqueName, arcane] of Object.entries(ExportArcanes)) {
|
for (const [uniqueName, arcane] of Object.entries(ExportArcanes)) {
|
||||||
res.mods.push({
|
res.mods.push({
|
||||||
uniqueName,
|
uniqueName,
|
||||||
|
27
src/controllers/custom/importController.ts
Normal file
27
src/controllers/custom/importController.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { importInventory, importLoadOutPresets } from "@/src/services/importService";
|
||||||
|
import { getInventory } from "@/src/services/inventoryService";
|
||||||
|
import { getLoadout } from "@/src/services/loadoutService";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { IInventoryClient } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
|
export const importController: RequestHandler = async (req, res) => {
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const request = JSON.parse(String(req.body)) as IImportRequest;
|
||||||
|
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
importInventory(inventory, request.inventory);
|
||||||
|
await inventory.save();
|
||||||
|
|
||||||
|
if (request.inventory.LoadOutPresets) {
|
||||||
|
const loadout = await getLoadout(accountId);
|
||||||
|
importLoadOutPresets(loadout, request.inventory.LoadOutPresets);
|
||||||
|
await loadout.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
res.end();
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IImportRequest {
|
||||||
|
inventory: Partial<IInventoryClient>;
|
||||||
|
}
|
@ -2,11 +2,10 @@ import { Document, Model, Schema, Types, model } from "mongoose";
|
|||||||
import {
|
import {
|
||||||
IFlavourItem,
|
IFlavourItem,
|
||||||
IRawUpgrade,
|
IRawUpgrade,
|
||||||
ICrewShipSalvagedWeaponSkin,
|
|
||||||
IMiscItem,
|
IMiscItem,
|
||||||
IInventoryDatabase,
|
IInventoryDatabase,
|
||||||
IBooster,
|
IBooster,
|
||||||
IInventoryResponse,
|
IInventoryClient,
|
||||||
ISlots,
|
ISlots,
|
||||||
IMailbox,
|
IMailbox,
|
||||||
IDuviriInfo,
|
IDuviriInfo,
|
||||||
@ -14,7 +13,7 @@ import {
|
|||||||
IPendingRecipeResponse,
|
IPendingRecipeResponse,
|
||||||
ITypeCount,
|
ITypeCount,
|
||||||
IFocusXP,
|
IFocusXP,
|
||||||
IFocusUpgrades,
|
IFocusUpgrade,
|
||||||
ITypeXPItem,
|
ITypeXPItem,
|
||||||
IChallengeProgress,
|
IChallengeProgress,
|
||||||
IStepSequencer,
|
IStepSequencer,
|
||||||
@ -24,7 +23,7 @@ import {
|
|||||||
ISeasonChallenge,
|
ISeasonChallenge,
|
||||||
IPlayerSkills,
|
IPlayerSkills,
|
||||||
ISettings,
|
ISettings,
|
||||||
IInfestedFoundry,
|
IInfestedFoundryDatabase,
|
||||||
IHelminthResource,
|
IHelminthResource,
|
||||||
IConsumedSuit,
|
IConsumedSuit,
|
||||||
IQuestProgress,
|
IQuestProgress,
|
||||||
@ -43,7 +42,6 @@ import {
|
|||||||
ICrewShipCustomization,
|
ICrewShipCustomization,
|
||||||
ICrewShipWeapon,
|
ICrewShipWeapon,
|
||||||
ICrewShipMembersClient,
|
ICrewShipMembersClient,
|
||||||
ICrewShip,
|
|
||||||
ICrewShipPilotWeapon,
|
ICrewShipPilotWeapon,
|
||||||
IShipExterior,
|
IShipExterior,
|
||||||
IHelminthFoodRecord,
|
IHelminthFoodRecord,
|
||||||
@ -52,7 +50,9 @@ import {
|
|||||||
IDialogueDatabase,
|
IDialogueDatabase,
|
||||||
IDialogueGift,
|
IDialogueGift,
|
||||||
ICompletedDialogue,
|
ICompletedDialogue,
|
||||||
IDialogueClient
|
IDialogueClient,
|
||||||
|
IUpgradeDatabase,
|
||||||
|
ICrewShipDatabase
|
||||||
} from "../../types/inventoryTypes/inventoryTypes";
|
} from "../../types/inventoryTypes/inventoryTypes";
|
||||||
import { IOid } from "../../types/commonTypes";
|
import { IOid } from "../../types/commonTypes";
|
||||||
import {
|
import {
|
||||||
@ -62,7 +62,6 @@ import {
|
|||||||
IOperatorConfigDatabase,
|
IOperatorConfigDatabase,
|
||||||
IPolarity,
|
IPolarity,
|
||||||
IEquipmentDatabase,
|
IEquipmentDatabase,
|
||||||
IOperatorConfigClient,
|
|
||||||
IArchonCrystalUpgrade
|
IArchonCrystalUpgrade
|
||||||
} from "@/src/types/inventoryTypes/commonInventoryTypes";
|
} from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||||
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
|
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
|
||||||
@ -81,7 +80,7 @@ const focusXPSchema = new Schema<IFocusXP>(
|
|||||||
{ _id: false }
|
{ _id: false }
|
||||||
);
|
);
|
||||||
|
|
||||||
const focusUpgradesSchema = new Schema<IFocusUpgrades>(
|
const focusUpgradeSchema = new Schema<IFocusUpgrade>(
|
||||||
{
|
{
|
||||||
ItemType: String,
|
ItemType: String,
|
||||||
Level: Number,
|
Level: Number,
|
||||||
@ -288,7 +287,7 @@ RawUpgrades.set("toJSON", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const upgradesSchema = new Schema<ICrewShipSalvagedWeaponSkin>(
|
const upgradeSchema = new Schema<IUpgradeDatabase>(
|
||||||
{
|
{
|
||||||
UpgradeFingerprint: String,
|
UpgradeFingerprint: String,
|
||||||
PendingRerollFingerprint: { type: String, required: false },
|
PendingRerollFingerprint: { type: String, required: false },
|
||||||
@ -297,11 +296,11 @@ const upgradesSchema = new Schema<ICrewShipSalvagedWeaponSkin>(
|
|||||||
{ id: false }
|
{ id: false }
|
||||||
);
|
);
|
||||||
|
|
||||||
upgradesSchema.virtual("ItemId").get(function () {
|
upgradeSchema.virtual("ItemId").get(function () {
|
||||||
return toOid(this._id);
|
return toOid(this._id);
|
||||||
});
|
});
|
||||||
|
|
||||||
upgradesSchema.set("toJSON", {
|
upgradeSchema.set("toJSON", {
|
||||||
virtuals: true,
|
virtuals: true,
|
||||||
transform(_document, returnedObject) {
|
transform(_document, returnedObject) {
|
||||||
delete returnedObject._id;
|
delete returnedObject._id;
|
||||||
@ -493,7 +492,7 @@ const helminthResourceSchema = new Schema<IHelminthResource>(
|
|||||||
{ _id: false }
|
{ _id: false }
|
||||||
);
|
);
|
||||||
|
|
||||||
const infestedFoundrySchema = new Schema<IInfestedFoundry>(
|
const infestedFoundrySchema = new Schema<IInfestedFoundryDatabase>(
|
||||||
{
|
{
|
||||||
Name: String,
|
Name: String,
|
||||||
Resources: { type: [helminthResourceSchema], default: undefined },
|
Resources: { type: [helminthResourceSchema], default: undefined },
|
||||||
@ -695,7 +694,7 @@ crewShipMembersSchema.set("toJSON", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const crewShipSchema = new Schema<ICrewShip>({
|
const crewShipSchema = new Schema<ICrewShipDatabase>({
|
||||||
ItemType: { type: String, required: true },
|
ItemType: { type: String, required: true },
|
||||||
Configs: { type: [ItemConfigSchema], default: [] },
|
Configs: { type: [ItemConfigSchema], default: [] },
|
||||||
Weapon: { type: crewShipWeaponSchema, default: undefined },
|
Weapon: { type: crewShipWeaponSchema, default: undefined },
|
||||||
@ -837,7 +836,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
|||||||
//Curent active like Active school focuses is = "Zenurik"
|
//Curent active like Active school focuses is = "Zenurik"
|
||||||
FocusAbility: String,
|
FocusAbility: String,
|
||||||
//The treeways of the Focus school.(Active and passive Ability)
|
//The treeways of the Focus school.(Active and passive Ability)
|
||||||
FocusUpgrades: [focusUpgradesSchema],
|
FocusUpgrades: [focusUpgradeSchema],
|
||||||
|
|
||||||
//Achievement
|
//Achievement
|
||||||
ChallengeProgress: [challengeProgressSchema],
|
ChallengeProgress: [challengeProgressSchema],
|
||||||
@ -848,7 +847,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
|||||||
//Non Upgrade Mods Example:I have 999 item WeaponElectricityDamageMod (only "ItemCount"+"ItemType")
|
//Non Upgrade Mods Example:I have 999 item WeaponElectricityDamageMod (only "ItemCount"+"ItemType")
|
||||||
RawUpgrades: [RawUpgrades],
|
RawUpgrades: [RawUpgrades],
|
||||||
//Upgrade Mods\Riven\Arcane Example:"UpgradeFingerprint"+"ItemType"+""
|
//Upgrade Mods\Riven\Arcane Example:"UpgradeFingerprint"+"ItemType"+""
|
||||||
Upgrades: [upgradesSchema],
|
Upgrades: [upgradeSchema],
|
||||||
|
|
||||||
//Warframe
|
//Warframe
|
||||||
Suits: [EquipmentSchema],
|
Suits: [EquipmentSchema],
|
||||||
@ -1142,7 +1141,7 @@ inventorySchema.set("toJSON", {
|
|||||||
delete returnedObject.accountOwnerId;
|
delete returnedObject.accountOwnerId;
|
||||||
|
|
||||||
const inventoryDatabase = returnedObject as IInventoryDatabase;
|
const inventoryDatabase = returnedObject as IInventoryDatabase;
|
||||||
const inventoryResponse = returnedObject as IInventoryResponse;
|
const inventoryResponse = returnedObject as IInventoryClient;
|
||||||
|
|
||||||
inventoryResponse.TrainingDate = toMongoDate(inventoryDatabase.TrainingDate);
|
inventoryResponse.TrainingDate = toMongoDate(inventoryDatabase.TrainingDate);
|
||||||
inventoryResponse.Created = toMongoDate(inventoryDatabase.Created);
|
inventoryResponse.Created = toMongoDate(inventoryDatabase.Created);
|
||||||
@ -1164,12 +1163,12 @@ type InventoryDocumentProps = {
|
|||||||
OperatorAmps: Types.DocumentArray<IEquipmentDatabase>;
|
OperatorAmps: Types.DocumentArray<IEquipmentDatabase>;
|
||||||
FlavourItems: Types.DocumentArray<IFlavourItem>;
|
FlavourItems: Types.DocumentArray<IFlavourItem>;
|
||||||
RawUpgrades: Types.DocumentArray<IRawUpgrade>;
|
RawUpgrades: Types.DocumentArray<IRawUpgrade>;
|
||||||
Upgrades: Types.DocumentArray<ICrewShipSalvagedWeaponSkin>;
|
Upgrades: Types.DocumentArray<IUpgradeDatabase>;
|
||||||
MiscItems: Types.DocumentArray<IMiscItem>;
|
MiscItems: Types.DocumentArray<IMiscItem>;
|
||||||
Boosters: Types.DocumentArray<IBooster>;
|
Boosters: Types.DocumentArray<IBooster>;
|
||||||
OperatorLoadOuts: Types.DocumentArray<IOperatorConfigClient>;
|
OperatorLoadOuts: Types.DocumentArray<IOperatorConfigDatabase>;
|
||||||
SpecialItems: Types.DocumentArray<IEquipmentDatabase>;
|
SpecialItems: Types.DocumentArray<IEquipmentDatabase>;
|
||||||
AdultOperatorLoadOuts: Types.DocumentArray<IOperatorConfigClient>; //TODO: this should still contain _id
|
AdultOperatorLoadOuts: Types.DocumentArray<IOperatorConfigDatabase>;
|
||||||
MechSuits: Types.DocumentArray<IEquipmentDatabase>;
|
MechSuits: Types.DocumentArray<IEquipmentDatabase>;
|
||||||
Scoops: Types.DocumentArray<IEquipmentDatabase>;
|
Scoops: Types.DocumentArray<IEquipmentDatabase>;
|
||||||
DataKnives: Types.DocumentArray<IEquipmentDatabase>;
|
DataKnives: Types.DocumentArray<IEquipmentDatabase>;
|
||||||
@ -1185,7 +1184,7 @@ type InventoryDocumentProps = {
|
|||||||
Hoverboards: Types.DocumentArray<IEquipmentDatabase>;
|
Hoverboards: Types.DocumentArray<IEquipmentDatabase>;
|
||||||
MoaPets: Types.DocumentArray<IEquipmentDatabase>;
|
MoaPets: Types.DocumentArray<IEquipmentDatabase>;
|
||||||
WeaponSkins: Types.DocumentArray<IWeaponSkinDatabase>;
|
WeaponSkins: Types.DocumentArray<IWeaponSkinDatabase>;
|
||||||
CrewShips: Types.DocumentArray<ICrewShip>;
|
CrewShips: Types.DocumentArray<ICrewShipDatabase>;
|
||||||
CrewShipHarnesses: Types.DocumentArray<IEquipmentDatabase>;
|
CrewShipHarnesses: Types.DocumentArray<IEquipmentDatabase>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import { renameAccountController } from "@/src/controllers/custom/renameAccountC
|
|||||||
|
|
||||||
import { createAccountController } from "@/src/controllers/custom/createAccountController";
|
import { createAccountController } from "@/src/controllers/custom/createAccountController";
|
||||||
import { addItemsController } from "@/src/controllers/custom/addItemsController";
|
import { addItemsController } from "@/src/controllers/custom/addItemsController";
|
||||||
|
import { importController } from "@/src/controllers/custom/importController";
|
||||||
|
|
||||||
import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
|
import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
|
||||||
import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
|
import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
|
||||||
@ -24,6 +25,7 @@ customRouter.get("/renameAccount", renameAccountController);
|
|||||||
|
|
||||||
customRouter.post("/createAccount", createAccountController);
|
customRouter.post("/createAccount", createAccountController);
|
||||||
customRouter.post("/addItems", addItemsController);
|
customRouter.post("/addItems", addItemsController);
|
||||||
|
customRouter.post("/import", importController);
|
||||||
|
|
||||||
customRouter.get("/config", getConfigDataController);
|
customRouter.get("/config", getConfigDataController);
|
||||||
customRouter.post("/config", updateConfigDataController);
|
customRouter.post("/config", updateConfigDataController);
|
||||||
|
@ -34,6 +34,9 @@ webuiRouter.get("/webui/settings", (_req, res) => {
|
|||||||
webuiRouter.get("/webui/cheats", (_req, res) => {
|
webuiRouter.get("/webui/cheats", (_req, res) => {
|
||||||
res.sendFile(path.join(rootDir, "static/webui/index.html"));
|
res.sendFile(path.join(rootDir, "static/webui/index.html"));
|
||||||
});
|
});
|
||||||
|
webuiRouter.get("/webui/import", (_req, res) => {
|
||||||
|
res.sendFile(path.join(rootDir, "static/webui/index.html"));
|
||||||
|
});
|
||||||
|
|
||||||
// Serve static files
|
// Serve static files
|
||||||
webuiRouter.use("/webui", express.static(path.join(rootDir, "static/webui")));
|
webuiRouter.use("/webui", express.static(path.join(rootDir, "static/webui")));
|
||||||
|
247
src/services/importService.ts
Normal file
247
src/services/importService.ts
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
import { Types } from "mongoose";
|
||||||
|
import {
|
||||||
|
IEquipmentClient,
|
||||||
|
IEquipmentDatabase,
|
||||||
|
IOperatorConfigClient,
|
||||||
|
IOperatorConfigDatabase
|
||||||
|
} from "../types/inventoryTypes/commonInventoryTypes";
|
||||||
|
import { IMongoDate } from "../types/commonTypes";
|
||||||
|
import {
|
||||||
|
equipmentKeys,
|
||||||
|
ICrewShipClient,
|
||||||
|
ICrewShipDatabase,
|
||||||
|
ICrewShipMembersClient,
|
||||||
|
ICrewShipMembersDatabase,
|
||||||
|
IDialogueClient,
|
||||||
|
IDialogueDatabase,
|
||||||
|
IDialogueHistoryClient,
|
||||||
|
IDialogueHistoryDatabase,
|
||||||
|
IInfestedFoundryClient,
|
||||||
|
IInfestedFoundryDatabase,
|
||||||
|
IInventoryClient,
|
||||||
|
ILoadoutConfigClient,
|
||||||
|
ILoadOutPresets,
|
||||||
|
ISlots,
|
||||||
|
IUpgradeClient,
|
||||||
|
IUpgradeDatabase,
|
||||||
|
IWeaponSkinClient,
|
||||||
|
IWeaponSkinDatabase
|
||||||
|
} from "../types/inventoryTypes/inventoryTypes";
|
||||||
|
import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel";
|
||||||
|
import { ILoadoutConfigDatabase, ILoadoutDatabase } from "../types/saveLoadoutTypes";
|
||||||
|
|
||||||
|
const convertDate = (value: IMongoDate): Date => {
|
||||||
|
return new Date(parseInt(value.$date.$numberLong));
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertOptionalDate = (value: IMongoDate | undefined): Date | undefined => {
|
||||||
|
return value ? convertDate(value) : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertEquipment = (client: IEquipmentClient): IEquipmentDatabase => {
|
||||||
|
const { ItemId, ...rest } = client;
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
_id: new Types.ObjectId(ItemId.$oid),
|
||||||
|
InfestationDate: convertOptionalDate(client.InfestationDate),
|
||||||
|
Expiry: convertOptionalDate(client.Expiry),
|
||||||
|
UpgradesExpiry: convertOptionalDate(client.UpgradesExpiry)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertWeaponSkin = (client: IWeaponSkinClient): IWeaponSkinDatabase => {
|
||||||
|
const { ItemId, ...rest } = client;
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
_id: new Types.ObjectId(ItemId.$oid)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertUpgrade = (client: IUpgradeClient): IUpgradeDatabase => {
|
||||||
|
const { ItemId, ...rest } = client;
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
_id: new Types.ObjectId(ItemId.$oid)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertOperatorConfig = (client: IOperatorConfigClient): IOperatorConfigDatabase => {
|
||||||
|
const { ItemId, ...rest } = client;
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
_id: new Types.ObjectId(ItemId.$oid)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const replaceArray = <T>(arr: T[], replacement: T[]): void => {
|
||||||
|
arr.splice(0, arr.length);
|
||||||
|
replacement.forEach(x => {
|
||||||
|
arr.push(x);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const replaceSlots = (db: ISlots, client: ISlots): void => {
|
||||||
|
db.Extra = client.Extra;
|
||||||
|
db.Slots = client.Slots;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertCrewShipMembers = (client: ICrewShipMembersClient): ICrewShipMembersDatabase => {
|
||||||
|
return {
|
||||||
|
SLOT_A: client.SLOT_A ? new Types.ObjectId(client.SLOT_A.ItemId.$oid) : undefined,
|
||||||
|
SLOT_B: client.SLOT_B ? new Types.ObjectId(client.SLOT_B.ItemId.$oid) : undefined,
|
||||||
|
SLOT_C: client.SLOT_C ? new Types.ObjectId(client.SLOT_C.ItemId.$oid) : undefined
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertCrewShip = (client: ICrewShipClient): ICrewShipDatabase => {
|
||||||
|
const { ItemId, ...rest } = client;
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
_id: new Types.ObjectId(ItemId.$oid),
|
||||||
|
CrewMembers: client.CrewMembers ? convertCrewShipMembers(client.CrewMembers) : undefined
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertInfestedFoundry = (client: IInfestedFoundryClient): IInfestedFoundryDatabase => {
|
||||||
|
return {
|
||||||
|
...client,
|
||||||
|
LastConsumedSuit: client.LastConsumedSuit ? convertEquipment(client.LastConsumedSuit) : undefined,
|
||||||
|
AbilityOverrideUnlockCooldown: convertOptionalDate(client.AbilityOverrideUnlockCooldown)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertDialogue = (client: IDialogueClient): IDialogueDatabase => {
|
||||||
|
return {
|
||||||
|
...client,
|
||||||
|
AvailableDate: convertDate(client.AvailableDate),
|
||||||
|
AvailableGiftDate: convertDate(client.AvailableGiftDate),
|
||||||
|
RankUpExpiry: convertDate(client.RankUpExpiry),
|
||||||
|
BountyChemExpiry: convertDate(client.BountyChemExpiry)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertDialogueHistory = (client: IDialogueHistoryClient): IDialogueHistoryDatabase => {
|
||||||
|
return {
|
||||||
|
YearIteration: client.YearIteration,
|
||||||
|
Dialogues: client.Dialogues ? client.Dialogues.map(convertDialogue) : undefined
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const importInventory = (db: TInventoryDatabaseDocument, client: Partial<IInventoryClient>): void => {
|
||||||
|
for (const key of equipmentKeys) {
|
||||||
|
if (client[key]) {
|
||||||
|
replaceArray<IEquipmentDatabase>(db[key], client[key].map(convertEquipment));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (client.WeaponSkins) {
|
||||||
|
replaceArray<IWeaponSkinDatabase>(db.WeaponSkins, client.WeaponSkins.map(convertWeaponSkin));
|
||||||
|
}
|
||||||
|
if (client.Upgrades) {
|
||||||
|
replaceArray<IUpgradeDatabase>(db.Upgrades, client.Upgrades.map(convertUpgrade));
|
||||||
|
}
|
||||||
|
for (const key of ["RawUpgrades", "MiscItems"] as const) {
|
||||||
|
if (client[key]) {
|
||||||
|
db[key].splice(0, db[key].length);
|
||||||
|
client[key].forEach(x => {
|
||||||
|
db[key].push({
|
||||||
|
ItemType: x.ItemType,
|
||||||
|
ItemCount: x.ItemCount
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const key of ["OperatorLoadOuts", "AdultOperatorLoadOuts"] as const) {
|
||||||
|
if (client[key]) {
|
||||||
|
replaceArray<IOperatorConfigDatabase>(db[key], client[key].map(convertOperatorConfig));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const key of [
|
||||||
|
"SuitBin",
|
||||||
|
"WeaponBin",
|
||||||
|
"SentinelBin",
|
||||||
|
"SpaceSuitBin",
|
||||||
|
"SpaceWeaponBin",
|
||||||
|
"PvpBonusLoadoutBin",
|
||||||
|
"PveBonusLoadoutBin",
|
||||||
|
"RandomModBin",
|
||||||
|
"MechBin",
|
||||||
|
"CrewMemberBin",
|
||||||
|
"OperatorAmpBin",
|
||||||
|
"CrewShipSalvageBin"
|
||||||
|
] as const) {
|
||||||
|
if (client[key]) {
|
||||||
|
replaceSlots(db[key], client[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (client.UseAdultOperatorLoadout) {
|
||||||
|
db.UseAdultOperatorLoadout = client.UseAdultOperatorLoadout;
|
||||||
|
}
|
||||||
|
for (const key of [
|
||||||
|
"PlayerLevel",
|
||||||
|
"RegularCredits",
|
||||||
|
"PremiumCredits",
|
||||||
|
"PremiumCreditsFree",
|
||||||
|
"FusionPoints",
|
||||||
|
"PrimeTokens"
|
||||||
|
] as const) {
|
||||||
|
if (client[key]) {
|
||||||
|
db[key] = client[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const key of ["ThemeStyle", "ThemeBackground", "ThemeSounds", "EquippedInstrument", "FocusAbility"] as const) {
|
||||||
|
if (client[key]) {
|
||||||
|
db[key] = client[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const key of ["EquippedGear", "EquippedEmotes", "NodeIntrosCompleted"] as const) {
|
||||||
|
if (client[key]) {
|
||||||
|
db[key] = client[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (client.XPInfo) {
|
||||||
|
db.XPInfo = client.XPInfo;
|
||||||
|
}
|
||||||
|
if (client.CurrentLoadOutIds) {
|
||||||
|
db.CurrentLoadOutIds = client.CurrentLoadOutIds;
|
||||||
|
}
|
||||||
|
if (client.Affiliations) {
|
||||||
|
db.Affiliations = client.Affiliations;
|
||||||
|
}
|
||||||
|
if (client.FusionTreasures) {
|
||||||
|
db.FusionTreasures = client.FusionTreasures;
|
||||||
|
}
|
||||||
|
if (client.FocusUpgrades) {
|
||||||
|
db.FocusUpgrades = client.FocusUpgrades;
|
||||||
|
}
|
||||||
|
if (client.CrewShips) {
|
||||||
|
replaceArray<ICrewShipDatabase>(db.CrewShips, client.CrewShips.map(convertCrewShip));
|
||||||
|
}
|
||||||
|
if (client.InfestedFoundry) {
|
||||||
|
db.InfestedFoundry = convertInfestedFoundry(client.InfestedFoundry);
|
||||||
|
}
|
||||||
|
if (client.DialogueHistory) {
|
||||||
|
db.DialogueHistory = convertDialogueHistory(client.DialogueHistory);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertLoadOutConfig = (client: ILoadoutConfigClient): ILoadoutConfigDatabase => {
|
||||||
|
const { ItemId, ...rest } = client;
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
_id: new Types.ObjectId(ItemId.$oid)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const importLoadOutPresets = (db: ILoadoutDatabase, client: ILoadOutPresets): void => {
|
||||||
|
db.NORMAL = client.NORMAL.map(convertLoadOutConfig);
|
||||||
|
db.SENTINEL = client.SENTINEL.map(convertLoadOutConfig);
|
||||||
|
db.ARCHWING = client.ARCHWING.map(convertLoadOutConfig);
|
||||||
|
db.NORMAL_PVP = client.NORMAL_PVP.map(convertLoadOutConfig);
|
||||||
|
db.LUNARO = client.LUNARO.map(convertLoadOutConfig);
|
||||||
|
db.OPERATOR = client.OPERATOR.map(convertLoadOutConfig);
|
||||||
|
db.KDRIVE = client.KDRIVE.map(convertLoadOutConfig);
|
||||||
|
db.DATAKNIFE = client.DATAKNIFE.map(convertLoadOutConfig);
|
||||||
|
db.MECH = client.MECH.map(convertLoadOutConfig);
|
||||||
|
db.OPERATOR_ADULT = client.OPERATOR_ADULT.map(convertLoadOutConfig);
|
||||||
|
db.DRIFTER = client.DRIFTER.map(convertLoadOutConfig);
|
||||||
|
};
|
@ -78,8 +78,11 @@ export interface IEquipmentSelection {
|
|||||||
hide?: boolean;
|
hide?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEquipmentClient extends Omit<IEquipmentDatabase, "_id" | "UpgradesExpiry"> {
|
export interface IEquipmentClient
|
||||||
|
extends Omit<IEquipmentDatabase, "_id" | "InfestationDate" | "Expiry" | "UpgradesExpiry"> {
|
||||||
ItemId: IOid;
|
ItemId: IOid;
|
||||||
|
InfestationDate?: IMongoDate;
|
||||||
|
Expiry?: IMongoDate;
|
||||||
UpgradesExpiry?: IMongoDate;
|
UpgradesExpiry?: IMongoDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,12 +109,12 @@ export interface IEquipmentDatabase {
|
|||||||
CustomizationSlotPurchases?: number;
|
CustomizationSlotPurchases?: number;
|
||||||
UpgradeType?: string;
|
UpgradeType?: string;
|
||||||
UpgradeFingerprint?: string;
|
UpgradeFingerprint?: string;
|
||||||
InfestationDate?: IMongoDate;
|
InfestationDate?: Date;
|
||||||
InfestationDays?: number;
|
InfestationDays?: number;
|
||||||
InfestationType?: string;
|
InfestationType?: string;
|
||||||
ModularParts?: string[];
|
ModularParts?: string[];
|
||||||
UnlockLevel?: number;
|
UnlockLevel?: number;
|
||||||
Expiry?: IMongoDate;
|
Expiry?: Date;
|
||||||
SkillTree?: string;
|
SkillTree?: string;
|
||||||
OffensiveUpgrade?: string;
|
OffensiveUpgrade?: string;
|
||||||
DefensiveUpgrade?: string;
|
DefensiveUpgrade?: string;
|
||||||
|
@ -7,12 +7,14 @@ import {
|
|||||||
IItemConfig,
|
IItemConfig,
|
||||||
IOperatorConfigClient,
|
IOperatorConfigClient,
|
||||||
IEquipmentSelection,
|
IEquipmentSelection,
|
||||||
IEquipmentDatabase
|
IEquipmentDatabase,
|
||||||
|
IEquipmentClient,
|
||||||
|
IOperatorConfigDatabase
|
||||||
} from "@/src/types/inventoryTypes/commonInventoryTypes";
|
} from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||||
|
|
||||||
export interface IInventoryDatabase
|
export interface IInventoryDatabase
|
||||||
extends Omit<
|
extends Omit<
|
||||||
IInventoryResponse,
|
IInventoryClient,
|
||||||
| "TrainingDate"
|
| "TrainingDate"
|
||||||
| "LoadOutPresets"
|
| "LoadOutPresets"
|
||||||
| "Mailbox"
|
| "Mailbox"
|
||||||
@ -23,6 +25,15 @@ export interface IInventoryDatabase
|
|||||||
| "BlessingCooldown"
|
| "BlessingCooldown"
|
||||||
| "Ships"
|
| "Ships"
|
||||||
| "WeaponSkins"
|
| "WeaponSkins"
|
||||||
|
| "Upgrades"
|
||||||
|
| "CrewShipSalvagedWeaponSkins"
|
||||||
|
| "CrewShipWeaponSkins"
|
||||||
|
| "OperatorLoadOuts"
|
||||||
|
| "AdultOperatorLoadOuts"
|
||||||
|
| "CrewShips"
|
||||||
|
| "InfestedFoundry"
|
||||||
|
| "DialogueHistory"
|
||||||
|
| TEquipmentKey
|
||||||
> {
|
> {
|
||||||
accountOwnerId: Types.ObjectId;
|
accountOwnerId: Types.ObjectId;
|
||||||
Created: Date;
|
Created: Date;
|
||||||
@ -35,6 +46,28 @@ export interface IInventoryDatabase
|
|||||||
BlessingCooldown: Date;
|
BlessingCooldown: Date;
|
||||||
Ships: Types.ObjectId[];
|
Ships: Types.ObjectId[];
|
||||||
WeaponSkins: IWeaponSkinDatabase[];
|
WeaponSkins: IWeaponSkinDatabase[];
|
||||||
|
Upgrades: IUpgradeDatabase[];
|
||||||
|
CrewShipSalvagedWeaponSkins: IUpgradeDatabase[];
|
||||||
|
CrewShipWeaponSkins: IUpgradeDatabase[];
|
||||||
|
OperatorLoadOuts: IOperatorConfigDatabase[];
|
||||||
|
AdultOperatorLoadOuts: IOperatorConfigDatabase[];
|
||||||
|
CrewShips: ICrewShipDatabase[];
|
||||||
|
InfestedFoundry?: IInfestedFoundryDatabase;
|
||||||
|
DialogueHistory?: IDialogueHistoryDatabase;
|
||||||
|
|
||||||
|
Suits: IEquipmentDatabase[];
|
||||||
|
LongGuns: IEquipmentDatabase[];
|
||||||
|
Pistols: IEquipmentDatabase[];
|
||||||
|
Melee: IEquipmentDatabase[];
|
||||||
|
SpecialItems: IEquipmentDatabase[];
|
||||||
|
Sentinels: IEquipmentDatabase[];
|
||||||
|
SentinelWeapons: IEquipmentDatabase[];
|
||||||
|
SpaceSuits: IEquipmentDatabase[];
|
||||||
|
SpaceGuns: IEquipmentDatabase[];
|
||||||
|
SpaceMelee: IEquipmentDatabase[];
|
||||||
|
Hoverboards: IEquipmentDatabase[];
|
||||||
|
OperatorAmps: IEquipmentDatabase[];
|
||||||
|
MoaPets: IEquipmentDatabase[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IQuestKeyDatabase {
|
export interface IQuestKeyDatabase {
|
||||||
@ -46,12 +79,6 @@ export interface IQuestKeyDatabase {
|
|||||||
CompletionDate?: Date;
|
CompletionDate?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IFocusUpgrades {
|
|
||||||
ItemType: string;
|
|
||||||
Level: number;
|
|
||||||
IsUniversal: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ITypeCount {
|
export interface ITypeCount {
|
||||||
ItemType: string;
|
ItemType: string;
|
||||||
ItemCount: number;
|
ItemCount: number;
|
||||||
@ -126,7 +153,21 @@ export interface IDailyAffiliations {
|
|||||||
DailyAffiliationHex: number;
|
DailyAffiliationHex: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IInventoryResponse extends IDailyAffiliations {
|
export interface IInventoryClient extends IDailyAffiliations {
|
||||||
|
Suits: IEquipmentClient[];
|
||||||
|
LongGuns: IEquipmentClient[];
|
||||||
|
Pistols: IEquipmentClient[];
|
||||||
|
Melee: IEquipmentClient[];
|
||||||
|
SpecialItems: IEquipmentClient[];
|
||||||
|
Sentinels: IEquipmentClient[];
|
||||||
|
SentinelWeapons: IEquipmentClient[];
|
||||||
|
SpaceSuits: IEquipmentClient[];
|
||||||
|
SpaceGuns: IEquipmentClient[];
|
||||||
|
SpaceMelee: IEquipmentClient[];
|
||||||
|
Hoverboards: IEquipmentClient[];
|
||||||
|
OperatorAmps: IEquipmentClient[];
|
||||||
|
MoaPets: IEquipmentClient[];
|
||||||
|
|
||||||
Horses: IEquipmentDatabase[];
|
Horses: IEquipmentDatabase[];
|
||||||
DrifterMelee: IEquipmentDatabase[];
|
DrifterMelee: IEquipmentDatabase[];
|
||||||
DrifterGuns: IEquipmentDatabase[];
|
DrifterGuns: IEquipmentDatabase[];
|
||||||
@ -163,17 +204,13 @@ export interface IInventoryResponse extends IDailyAffiliations {
|
|||||||
ChallengeProgress: IChallengeProgress[];
|
ChallengeProgress: IChallengeProgress[];
|
||||||
RawUpgrades: IRawUpgrade[];
|
RawUpgrades: IRawUpgrade[];
|
||||||
ReceivedStartingGear: boolean;
|
ReceivedStartingGear: boolean;
|
||||||
Suits: IEquipmentDatabase[];
|
|
||||||
LongGuns: IEquipmentDatabase[];
|
|
||||||
Pistols: IEquipmentDatabase[];
|
|
||||||
Melee: IEquipmentDatabase[];
|
|
||||||
Ships: IShipInventory[];
|
Ships: IShipInventory[];
|
||||||
QuestKeys: IQuestKeyResponse[];
|
QuestKeys: IQuestKeyResponse[];
|
||||||
FlavourItems: IFlavourItem[];
|
FlavourItems: IFlavourItem[];
|
||||||
Scoops: IEquipmentDatabase[];
|
Scoops: IEquipmentDatabase[];
|
||||||
TrainingRetriesLeft: number;
|
TrainingRetriesLeft: number;
|
||||||
LoadOutPresets: ILoadOutPresets;
|
LoadOutPresets: ILoadOutPresets;
|
||||||
CurrentLoadOutIds: Array<any[] | IOid>;
|
CurrentLoadOutIds: IOid[]; // we store it in the database using this representation as well :/
|
||||||
Missions: IMission[];
|
Missions: IMission[];
|
||||||
RandomUpgradesIdentified?: number;
|
RandomUpgradesIdentified?: number;
|
||||||
LastRegionPlayed: TSolarMapRegion;
|
LastRegionPlayed: TSolarMapRegion;
|
||||||
@ -191,7 +228,7 @@ export interface IInventoryResponse extends IDailyAffiliations {
|
|||||||
Accolades?: {
|
Accolades?: {
|
||||||
Heirloom?: boolean;
|
Heirloom?: boolean;
|
||||||
};
|
};
|
||||||
Upgrades: ICrewShipSalvagedWeaponSkin[];
|
Upgrades: IUpgradeClient[];
|
||||||
EquippedGear: string[];
|
EquippedGear: string[];
|
||||||
DeathMarks: string[];
|
DeathMarks: string[];
|
||||||
FusionTreasures: IFusionTreasure[];
|
FusionTreasures: IFusionTreasure[];
|
||||||
@ -213,14 +250,9 @@ export interface IInventoryResponse extends IDailyAffiliations {
|
|||||||
Affiliations: IAffiliation[];
|
Affiliations: IAffiliation[];
|
||||||
QualifyingInvasions: any[];
|
QualifyingInvasions: any[];
|
||||||
FactionScores: number[];
|
FactionScores: number[];
|
||||||
SpaceSuits: IEquipmentDatabase[];
|
|
||||||
SpaceMelee: IEquipmentDatabase[];
|
|
||||||
SpaceGuns: IEquipmentDatabase[];
|
|
||||||
ArchwingEnabled: boolean;
|
ArchwingEnabled: boolean;
|
||||||
PendingSpectreLoadouts?: ISpectreLoadout[];
|
PendingSpectreLoadouts?: ISpectreLoadout[];
|
||||||
SpectreLoadouts?: ISpectreLoadout[];
|
SpectreLoadouts?: ISpectreLoadout[];
|
||||||
SentinelWeapons: IEquipmentDatabase[];
|
|
||||||
Sentinels: IEquipmentDatabase[];
|
|
||||||
EmailItems: ITypeCount[];
|
EmailItems: ITypeCount[];
|
||||||
CompletedSyndicates: string[];
|
CompletedSyndicates: string[];
|
||||||
FocusXP: IFocusXP;
|
FocusXP: IFocusXP;
|
||||||
@ -237,13 +269,11 @@ export interface IInventoryResponse extends IDailyAffiliations {
|
|||||||
CompletedJobs: ICompletedJob[];
|
CompletedJobs: ICompletedJob[];
|
||||||
FocusAbility: string;
|
FocusAbility: string;
|
||||||
FocusUpgrades: IFocusUpgrade[];
|
FocusUpgrades: IFocusUpgrade[];
|
||||||
OperatorAmps: IEquipmentDatabase[];
|
|
||||||
HasContributedToDojo?: boolean;
|
HasContributedToDojo?: boolean;
|
||||||
HWIDProtectEnabled?: boolean;
|
HWIDProtectEnabled?: boolean;
|
||||||
KubrowPetPrints: IKubrowPetPrint[];
|
KubrowPetPrints: IKubrowPetPrint[];
|
||||||
AlignmentReplay: IAlignment;
|
AlignmentReplay: IAlignment;
|
||||||
PersonalGoalProgress: IPersonalGoalProgress[];
|
PersonalGoalProgress: IPersonalGoalProgress[];
|
||||||
SpecialItems: IEquipmentDatabase[];
|
|
||||||
ThemeStyle: string;
|
ThemeStyle: string;
|
||||||
ThemeBackground: string;
|
ThemeBackground: string;
|
||||||
ThemeSounds: string;
|
ThemeSounds: string;
|
||||||
@ -252,12 +282,10 @@ export interface IInventoryResponse extends IDailyAffiliations {
|
|||||||
LoginMilestoneRewards: string[];
|
LoginMilestoneRewards: string[];
|
||||||
OperatorLoadOuts: IOperatorConfigClient[];
|
OperatorLoadOuts: IOperatorConfigClient[];
|
||||||
RecentVendorPurchases: Array<number | string>;
|
RecentVendorPurchases: Array<number | string>;
|
||||||
Hoverboards: IEquipmentDatabase[];
|
|
||||||
NodeIntrosCompleted: string[];
|
NodeIntrosCompleted: string[];
|
||||||
GuildId?: IOid;
|
GuildId?: IOid;
|
||||||
CompletedJobChains: ICompletedJobChain[];
|
CompletedJobChains: ICompletedJobChain[];
|
||||||
SeasonChallengeHistory: ISeasonChallenge[];
|
SeasonChallengeHistory: ISeasonChallenge[];
|
||||||
MoaPets: IEquipmentDatabase[];
|
|
||||||
EquippedInstrument?: string;
|
EquippedInstrument?: string;
|
||||||
InvasionChainProgress: IInvasionChainProgress[];
|
InvasionChainProgress: IInvasionChainProgress[];
|
||||||
DataKnives: IEquipmentDatabase[];
|
DataKnives: IEquipmentDatabase[];
|
||||||
@ -266,18 +294,18 @@ export interface IInventoryResponse extends IDailyAffiliations {
|
|||||||
LastNemesisAllySpawnTime?: IMongoDate;
|
LastNemesisAllySpawnTime?: IMongoDate;
|
||||||
Settings: ISettings;
|
Settings: ISettings;
|
||||||
PersonalTechProjects: IPersonalTechProject[];
|
PersonalTechProjects: IPersonalTechProject[];
|
||||||
CrewShips: ICrewShip[];
|
CrewShips: ICrewShipClient[];
|
||||||
PlayerSkills: IPlayerSkills;
|
PlayerSkills: IPlayerSkills;
|
||||||
CrewShipAmmo: IConsumable[];
|
CrewShipAmmo: IConsumable[];
|
||||||
CrewShipSalvagedWeaponSkins: ICrewShipSalvagedWeaponSkin[];
|
CrewShipSalvagedWeaponSkins: IUpgradeClient[];
|
||||||
CrewShipWeapons: ICrewShipWeapon[];
|
CrewShipWeapons: ICrewShipWeapon[];
|
||||||
CrewShipSalvagedWeapons: ICrewShipWeapon[];
|
CrewShipSalvagedWeapons: ICrewShipWeapon[];
|
||||||
CrewShipWeaponSkins: ICrewShipSalvagedWeaponSkin[];
|
CrewShipWeaponSkins: IUpgradeClient[];
|
||||||
TradeBannedUntil?: IMongoDate;
|
TradeBannedUntil?: IMongoDate;
|
||||||
PlayedParkourTutorial: boolean;
|
PlayedParkourTutorial: boolean;
|
||||||
SubscribedToEmailsPersonalized: number;
|
SubscribedToEmailsPersonalized: number;
|
||||||
MechSuits: IEquipmentDatabase[];
|
MechSuits: IEquipmentDatabase[];
|
||||||
InfestedFoundry?: IInfestedFoundry;
|
InfestedFoundry?: IInfestedFoundryClient;
|
||||||
BlessingCooldown: IMongoDate;
|
BlessingCooldown: IMongoDate;
|
||||||
CrewShipHarnesses: IEquipmentDatabase[];
|
CrewShipHarnesses: IEquipmentDatabase[];
|
||||||
CrewShipRawSalvage: IConsumable[];
|
CrewShipRawSalvage: IConsumable[];
|
||||||
@ -304,7 +332,7 @@ export interface IInventoryResponse extends IDailyAffiliations {
|
|||||||
Harvestable: boolean;
|
Harvestable: boolean;
|
||||||
DeathSquadable: boolean;
|
DeathSquadable: boolean;
|
||||||
EndlessXP?: IEndlessXpProgress[];
|
EndlessXP?: IEndlessXpProgress[];
|
||||||
DialogueHistory?: IDialogueHistoryDatabase;
|
DialogueHistory?: IDialogueHistoryClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAffiliation {
|
export interface IAffiliation {
|
||||||
@ -415,15 +443,18 @@ export interface ISlots {
|
|||||||
Slots: number;
|
Slots: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICrewShipSalvagedWeaponSkin {
|
export interface IUpgradeClient {
|
||||||
ItemType: string;
|
ItemType: string;
|
||||||
UpgradeFingerprint?: string;
|
UpgradeFingerprint?: string;
|
||||||
PendingRerollFingerprint?: string;
|
PendingRerollFingerprint?: string;
|
||||||
ItemId?: IOid;
|
ItemId: IOid;
|
||||||
_id?: Types.ObjectId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICrewShip {
|
export interface IUpgradeDatabase extends Omit<IUpgradeClient, "ItemId"> {
|
||||||
|
_id: Types.ObjectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICrewShipClient {
|
||||||
ItemType: string;
|
ItemType: string;
|
||||||
Configs: IItemConfig[];
|
Configs: IItemConfig[];
|
||||||
Weapon?: ICrewShipWeapon;
|
Weapon?: ICrewShipWeapon;
|
||||||
@ -432,6 +463,10 @@ export interface ICrewShip {
|
|||||||
RailjackImage?: IFlavourItem;
|
RailjackImage?: IFlavourItem;
|
||||||
CrewMembers?: ICrewShipMembersClient;
|
CrewMembers?: ICrewShipMembersClient;
|
||||||
ItemId: IOid;
|
ItemId: IOid;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICrewShipDatabase extends Omit<ICrewShipClient, "CrewMembers" | "ItemId"> {
|
||||||
|
CrewMembers?: ICrewShipMembersDatabase;
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -535,7 +570,7 @@ export interface IHelminthResource {
|
|||||||
RecentlyConvertedResources?: IHelminthFoodRecord[];
|
RecentlyConvertedResources?: IHelminthFoodRecord[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IInfestedFoundry {
|
export interface IInfestedFoundryClient {
|
||||||
Name?: string;
|
Name?: string;
|
||||||
Resources?: IHelminthResource[];
|
Resources?: IHelminthResource[];
|
||||||
Slots?: number;
|
Slots?: number;
|
||||||
@ -544,6 +579,12 @@ export interface IInfestedFoundry {
|
|||||||
InvigorationIndex?: number;
|
InvigorationIndex?: number;
|
||||||
InvigorationSuitOfferings?: string[];
|
InvigorationSuitOfferings?: string[];
|
||||||
InvigorationsApplied?: number;
|
InvigorationsApplied?: number;
|
||||||
|
LastConsumedSuit?: IEquipmentClient;
|
||||||
|
AbilityOverrideUnlockCooldown?: IMongoDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IInfestedFoundryDatabase
|
||||||
|
extends Omit<IInfestedFoundryClient, "LastConsumedSuit" | "AbilityOverrideUnlockCooldown"> {
|
||||||
LastConsumedSuit?: IEquipmentDatabase;
|
LastConsumedSuit?: IEquipmentDatabase;
|
||||||
AbilityOverrideUnlockCooldown?: Date;
|
AbilityOverrideUnlockCooldown?: Date;
|
||||||
}
|
}
|
||||||
@ -636,7 +677,7 @@ export interface ILibraryPersonalProgress {
|
|||||||
Completed: boolean;
|
Completed: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
//this needs to be checked against ILoadoutDatabase
|
// keep in sync with ILoadoutDatabase
|
||||||
export interface ILoadOutPresets {
|
export interface ILoadOutPresets {
|
||||||
NORMAL: ILoadoutConfigClient[];
|
NORMAL: ILoadoutConfigClient[];
|
||||||
NORMAL_PVP: ILoadoutConfigClient[];
|
NORMAL_PVP: ILoadoutConfigClient[];
|
||||||
@ -649,6 +690,7 @@ export interface ILoadOutPresets {
|
|||||||
DATAKNIFE: ILoadoutConfigClient[];
|
DATAKNIFE: ILoadoutConfigClient[];
|
||||||
MECH: ILoadoutConfigClient[];
|
MECH: ILoadoutConfigClient[];
|
||||||
OPERATOR_ADULT: ILoadoutConfigClient[];
|
OPERATOR_ADULT: ILoadoutConfigClient[];
|
||||||
|
DRIFTER: ILoadoutConfigClient[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum FocusSchool {
|
export enum FocusSchool {
|
||||||
@ -913,9 +955,10 @@ export interface ITaunt {
|
|||||||
|
|
||||||
export interface IWeaponSkinDatabase {
|
export interface IWeaponSkinDatabase {
|
||||||
ItemType: string;
|
ItemType: string;
|
||||||
|
_id: Types.ObjectId;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IWeaponSkinClient extends IWeaponSkinDatabase {
|
export interface IWeaponSkinClient extends Omit<IWeaponSkinDatabase, "_id"> {
|
||||||
ItemId: IOid;
|
ItemId: IOid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { IInfestedFoundry } from "./inventoryTypes/inventoryTypes";
|
import { IInfestedFoundryClient } from "./inventoryTypes/inventoryTypes";
|
||||||
|
|
||||||
export interface IPurchaseRequest {
|
export interface IPurchaseRequest {
|
||||||
PurchaseParams: IPurchaseParams;
|
PurchaseParams: IPurchaseParams;
|
||||||
@ -29,9 +29,9 @@ export interface ICurrencyChanges {
|
|||||||
|
|
||||||
export type IInventoryChanges = {
|
export type IInventoryChanges = {
|
||||||
[_ in SlotNames]?: IBinChanges;
|
[_ in SlotNames]?: IBinChanges;
|
||||||
} & ICurrencyChanges & { InfestedFoundry?: IInfestedFoundry } & Record<
|
} & ICurrencyChanges & { InfestedFoundry?: IInfestedFoundryClient } & Record<
|
||||||
string,
|
string,
|
||||||
IBinChanges | number | object[] | IInfestedFoundry
|
IBinChanges | number | object[] | IInfestedFoundryClient
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export interface IPurchaseResponse {
|
export interface IPurchaseResponse {
|
||||||
|
@ -54,18 +54,19 @@ export interface IConfigEntry {
|
|||||||
|
|
||||||
export interface ILoadoutClient extends Omit<ILoadoutDatabase, "_id" | "loadoutOwnerId"> {}
|
export interface ILoadoutClient extends Omit<ILoadoutDatabase, "_id" | "loadoutOwnerId"> {}
|
||||||
|
|
||||||
|
// keep in sync with ILoadOutPresets
|
||||||
export interface ILoadoutDatabase {
|
export interface ILoadoutDatabase {
|
||||||
NORMAL: ILoadoutEntry;
|
NORMAL: ILoadoutConfigDatabase[];
|
||||||
SENTINEL: ILoadoutEntry;
|
SENTINEL: ILoadoutConfigDatabase[];
|
||||||
ARCHWING: ILoadoutEntry;
|
ARCHWING: ILoadoutConfigDatabase[];
|
||||||
NORMAL_PVP: ILoadoutEntry;
|
NORMAL_PVP: ILoadoutConfigDatabase[];
|
||||||
LUNARO: ILoadoutEntry;
|
LUNARO: ILoadoutConfigDatabase[];
|
||||||
OPERATOR: ILoadoutEntry;
|
OPERATOR: ILoadoutConfigDatabase[];
|
||||||
KDRIVE: ILoadoutEntry;
|
KDRIVE: ILoadoutConfigDatabase[];
|
||||||
DATAKNIFE: ILoadoutEntry;
|
DATAKNIFE: ILoadoutConfigDatabase[];
|
||||||
MECH: ILoadoutEntry;
|
MECH: ILoadoutConfigDatabase[];
|
||||||
OPERATOR_ADULT: ILoadoutEntry;
|
OPERATOR_ADULT: ILoadoutConfigDatabase[];
|
||||||
DRIFTER: ILoadoutEntry;
|
DRIFTER: ILoadoutConfigDatabase[];
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
loadoutOwnerId: Types.ObjectId;
|
loadoutOwnerId: Types.ObjectId;
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,9 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="/webui/cheats" data-bs-dismiss="offcanvas" data-bs-target="#sidebar">Cheats</a>
|
<a class="nav-link" href="/webui/cheats" data-bs-dismiss="offcanvas" data-bs-target="#sidebar">Cheats</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/webui/import" data-bs-dismiss="offcanvas" data-bs-target="#sidebar">Import</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -493,6 +496,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div data-route="/webui/import" data-title="Import | OpenWF WebUI">
|
||||||
|
<p>You can provide a full or partial inventory response (client respresentation) here. All fields that are supported by the importer <b>will be overwritten</b> in your account.</p>
|
||||||
|
<textarea class="form-control" id="import-inventory"></textarea>
|
||||||
|
<button class="btn btn-primary mt-3" onclick="doImport();">Submit</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<datalist id="datalist-Suits"></datalist>
|
<datalist id="datalist-Suits"></datalist>
|
||||||
|
@ -215,7 +215,12 @@ function updateInventory() {
|
|||||||
const td = document.createElement("td");
|
const td = document.createElement("td");
|
||||||
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
|
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
|
||||||
if (item.ItemName) {
|
if (item.ItemName) {
|
||||||
td.textContent = item.ItemName + " (" + td.textContent + ")";
|
const pipeIndex = item.ItemName.indexOf("|");
|
||||||
|
if (pipeIndex != -1) {
|
||||||
|
td.textContent = item.ItemName.substr(1 + pipeIndex) + " " + td.textContent;
|
||||||
|
} else {
|
||||||
|
td.textContent = item.ItemName + " (" + td.textContent + ")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (item.ModularParts && item.ModularParts.length) {
|
if (item.ModularParts && item.ModularParts.length) {
|
||||||
td.textContent += " [";
|
td.textContent += " [";
|
||||||
@ -1083,3 +1088,18 @@ function doPopArchonCrystalUpgrade(type) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function doImport() {
|
||||||
|
revalidateAuthz(() => {
|
||||||
|
$.post({
|
||||||
|
url: "/custom/import?" + window.authz,
|
||||||
|
contentType: "text/plain",
|
||||||
|
data: JSON.stringify({
|
||||||
|
inventory: JSON.parse($("#import-inventory").val())
|
||||||
|
})
|
||||||
|
}).then(function () {
|
||||||
|
alert("Successfully imported.");
|
||||||
|
updateInventory();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user