Merge remote-tracking branch 'upstream/main' into inbox

This commit is contained in:
Master 2023-06-30 21:15:50 +08:00
commit 827c3285d2
27 changed files with 726 additions and 84 deletions

2
.gitignore vendored
View File

@ -2,5 +2,5 @@
/build
/.env
/static/data/*
/static/data/*.bin
yarn.lock

8
package-lock.json generated
View File

@ -11,7 +11,8 @@
"dependencies": {
"dotenv": "^16.1.3",
"express": "^5.0.0-beta.1",
"mongoose": "^7.1.1"
"mongoose": "^7.1.1",
"warframe-items": "1.1260.50"
},
"devDependencies": {
"@tsconfig/node20": "^1.0.0",
@ -3140,6 +3141,11 @@
"node": ">= 0.8"
}
},
"node_modules/warframe-items": {
"version": "1.1260.50",
"resolved": "https://registry.npmjs.org/warframe-items/-/warframe-items-1.1260.50.tgz",
"integrity": "sha512-03oNB6Yg61yUd7glewUUg0avnaGaAqc9oVPJk+1THFB0o/d4ppQSgL38yTUxMwmw0avCrqd+8z5TMrfXtvPDXQ=="
},
"node_modules/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",

View File

@ -14,7 +14,8 @@
"dependencies": {
"dotenv": "^16.1.3",
"express": "^5.0.0-beta.1",
"mongoose": "^7.1.1"
"mongoose": "^7.1.1",
"warframe-items": "1.1260.50"
},
"devDependencies": {
"@tsconfig/node20": "^1.0.0",

View File

@ -23,7 +23,7 @@ app.use(bodyParser.raw());
app.use(express.json());
app.use(bodyParser.text());
app.use(morgan("dev"));
app.use(requestLogger);
//app.use(requestLogger);
app.use("/api", apiRouter);
//app.use("/test", testRouter);

View File

@ -13,7 +13,6 @@ const inventoryController: RequestHandler = async (request: Request, response: R
response.status(400).json({ error: "accountId was not provided" });
return;
}
console.log(accountId);
const inventory = await Inventory.findOne({ accountOwnerId: accountId });

View File

@ -1,8 +1,13 @@
import purchase from "@/static/fixed_responses/purchase.json";
import { parseString } from "@/src/helpers/general";
import { toPurchaseRequest } from "@/src/helpers/purchaseHelpers";
import { handlePurchase } from "@/src/services/purchaseService";
import { Request, Response } from "express";
const purchaseController = (_req: Request, res: Response): void => {
res.json(purchase);
const purchaseController = async (req: Request, res: Response) => {
const purchaseRequest = toPurchaseRequest(JSON.parse(String(req.body)));
const accountId = parseString(req.query.accountId);
const response = await handlePurchase(purchaseRequest, accountId);
res.json(response);
};
export { purchaseController };

View File

@ -0,0 +1,13 @@
import { Inventory } from "@/src/models/inventoryModel";
import { RequestHandler } from "express";
import util from "util";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const saveLoadoutController: RequestHandler = async (req, res) => {
const body = JSON.parse(req.body);
console.log(util.inspect(body, { showHidden: false, depth: null, colors: true }));
res.sendStatus(200);
};
export { saveLoadoutController };

View File

@ -0,0 +1,26 @@
import { ItemType, toAddItemRequest } from "@/src/helpers/customHelpers/addItemHelpers";
import { getWeaponType } from "@/src/helpers/purchaseHelpers";
import { addPowerSuit, addWeapon } from "@/src/services/inventoryService";
import { RequestHandler } from "express";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const addItemController: RequestHandler = async (req, res) => {
const request = toAddItemRequest(req.body);
switch (request.type) {
case ItemType.Powersuit:
const powersuit = await addPowerSuit(request.InternalName, request.accountId);
res.json(powersuit);
return;
case ItemType.Weapon:
const weaponType = getWeaponType(request.InternalName);
const weapon = await addWeapon(weaponType, request.InternalName, request.accountId);
res.json(weapon);
break;
default:
res.status(400).json({ error: "something went wrong" });
break;
}
};
export { addItemController };

View File

@ -1,7 +1,8 @@
import { toCreateAccount, toDatabaseAccount } from "@/src/helpers/customHelpers";
import { toCreateAccount, toDatabaseAccount } from "@/src/helpers/customHelpers/customHelpers";
import { createAccount } from "@/src/services/loginService";
import { RequestHandler } from "express";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const createAccountController: RequestHandler = async (req, res) => {
const createAccountData = toCreateAccount(req.body);
const databaseAccount = toDatabaseAccount(createAccountData);

View File

@ -0,0 +1,55 @@
import { isString, parseString } from "@/src/helpers/general";
import { items } from "@/static/data/items";
export enum ItemType {
Powersuit = "Powersuit",
Weapon = "Weapon"
}
export const isItemType = (itemType: string): itemType is ItemType => {
return Object.keys(ItemType).includes(itemType);
};
const parseItemType = (itemType: unknown): ItemType => {
if (!itemType || !isString(itemType) || !isItemType(itemType)) {
throw new Error("incorrect item type");
}
return itemType;
};
interface IAddItemRequest {
type: ItemType;
InternalName: string;
accountId: string;
}
export const isInternalName = (internalName: string): boolean => {
const item = items.find(i => i.uniqueName === internalName);
return Boolean(item);
};
const parseInternalName = (internalName: unknown): string => {
if (!isString(internalName) || !isInternalName(internalName)) {
throw new Error("incorrect internal name");
}
return internalName;
};
const toAddItemRequest = (body: unknown): IAddItemRequest => {
if (!body || typeof body !== "object") {
throw new Error("incorrect or missing add item request data");
}
if ("type" in body && "internalName" in body && "accountId" in body) {
return {
type: parseItemType(body.type),
InternalName: parseInternalName(body.internalName),
accountId: parseString(body.accountId)
};
}
throw new Error("malformed add item request");
};
export { toAddItemRequest };

View File

@ -1,7 +1,7 @@
import { IAccountCreation } from "@/src/types/customTypes";
import { IDatabaseAccount } from "@/src/types/loginTypes";
import crypto from "crypto";
import { isString, parseEmail, parseString } from "./general";
import { isString, parseEmail, parseString } from "../general";
const getWhirlpoolHash = (rawPassword: string): string => {
const whirlpool = crypto.createHash("whirlpool");
@ -30,7 +30,6 @@ const toAccountCreation = (accountCreation: unknown): IAccountCreation => {
"CountryCode" in accountCreation
) {
const rawPassword = parsePassword(accountCreation.password);
console.log("email", accountCreation.email);
return {
email: parseEmail(accountCreation.email),
password: getWhirlpoolHash(rawPassword),

View File

@ -1,4 +1,4 @@
import { IInventoryDatabase, IInventoryResponse } from "@/src/types/inventoryTypes";
import { IInventoryDatabase, IInventoryResponse } from "@/src/types/inventoryTypes/inventoryTypes";
const toInventoryResponse = (inventoryDatabase: IInventoryDatabase): IInventoryResponse => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars

View File

@ -0,0 +1,59 @@
import { parseBoolean, parseNumber, parseString } from "@/src/helpers/general";
import { WeaponTypeInternal } from "@/src/services/inventoryService";
import { IPurchaseRequest } from "@/src/types/purchaseTypes";
import { weapons } from "@/static/data/items";
const toPurchaseRequest = (purchaseRequest: unknown): IPurchaseRequest => {
if (!purchaseRequest || typeof purchaseRequest !== "object") {
throw new Error("incorrect or missing purchase request data");
}
if (
"PurchaseParams" in purchaseRequest &&
"buildLabel" in purchaseRequest &&
purchaseRequest.PurchaseParams &&
typeof purchaseRequest.PurchaseParams === "object" &&
"Source" in purchaseRequest.PurchaseParams &&
"StoreItem" in purchaseRequest.PurchaseParams &&
"StorePage" in purchaseRequest.PurchaseParams &&
"SearchTerm" in purchaseRequest.PurchaseParams &&
"CurrentLocation" in purchaseRequest.PurchaseParams &&
"Quantity" in purchaseRequest.PurchaseParams &&
"UsePremium" in purchaseRequest.PurchaseParams &&
"ExpectedPrice" in purchaseRequest.PurchaseParams
) {
return {
PurchaseParams: {
Source: parseNumber(purchaseRequest.PurchaseParams.Source),
StoreItem: parseString(purchaseRequest.PurchaseParams.StoreItem),
StorePage: parseString(purchaseRequest.PurchaseParams.StorePage),
SearchTerm: parseString(purchaseRequest.PurchaseParams.SearchTerm),
CurrentLocation: parseString(purchaseRequest.PurchaseParams.CurrentLocation),
Quantity: parseNumber(purchaseRequest.PurchaseParams.Quantity),
UsePremium: parseBoolean(purchaseRequest.PurchaseParams.UsePremium),
ExpectedPrice: parseNumber(purchaseRequest.PurchaseParams.ExpectedPrice)
},
buildLabel: parseString(purchaseRequest.buildLabel)
};
}
throw new Error("invalid purchaseRequest");
};
const getWeaponType = (weaponName: string) => {
const weaponInfo = weapons.find(i => i.uniqueName === weaponName);
if (!weaponInfo) {
throw new Error(`unknown weapon ${weaponName}`);
}
const weaponType = weaponInfo.productCategory as WeaponTypeInternal;
if (!weaponType) {
throw new Error(`unknown weapon category for item ${weaponName}`);
}
return weaponType;
};
export { toPurchaseRequest, getWeaponType };

View File

@ -0,0 +1,18 @@
const getJSONfromString = (str: string): any => {
const jsonSubstring = str.substring(0, str.lastIndexOf("}") + 1);
return JSON.parse(jsonSubstring);
};
export const getSubstringFromKeyword = (str: string, keyword: string): string => {
const index = str.indexOf(keyword);
if (index == -1) {
throw new Error(`keyword ${keyword} not found in string ${str}`);
}
return str.substring(index);
};
export const getSubstringFromKeywordToKeyword = (str: string, keywordBegin: string, keywordEnd: string): string => {
const beginIndex = str.lastIndexOf(keywordBegin) + 1;
const endIndex = str.indexOf(keywordEnd);
return str.substring(beginIndex, endIndex + 1);
};

View File

@ -1,17 +1,13 @@
import { Schema, model } from "mongoose";
import { IInventoryDatabase, ISuitDatabase } from "../types/inventoryTypes";
import { Model, Schema, Types, model } from "mongoose";
import { FlavourItem, IInventoryDatabase } from "../types/inventoryTypes/inventoryTypes";
import { Oid } from "../types/commonTypes";
const polaritySchema = new Schema({
Slot: Number,
Value: String
});
import { ISuitDatabase, ISuitDocument } from "@/src/types/inventoryTypes/SuitTypes";
import { IWeaponDatabase } from "@/src/types/inventoryTypes/weaponTypes";
const abilityOverrideSchema = new Schema({
Ability: String,
Index: Number
});
const colorSchema = new Schema({
t0: Number,
t1: Number,
@ -23,6 +19,67 @@ const colorSchema = new Schema({
m1: Number
});
const longGunConfigSchema = new Schema({
Skins: [String],
pricol: colorSchema,
attcol: colorSchema,
eyecol: colorSchema,
sigcol: colorSchema,
Upgrades: [String],
Songs: [
{
m: String,
b: String,
p: String,
s: String
}
],
Name: String,
AbilityOverride: abilityOverrideSchema,
PvpUpgrades: [String],
ugly: Boolean
});
// longGunConfigSchema.set("toJSON", {
// transform(_document, returnedObject: ISuitDocument) {
// // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
// returnedObject.ItemId = { $oid: returnedObject._id.toString() } satisfies Oid;
// delete returnedObject._id;
// delete returnedObject.__v;
// }
// });
const WeaponSchema = new Schema({
ItemType: String,
Configs: [longGunConfigSchema],
UpgradeVer: Number,
XP: Number,
Features: Number,
Polarized: Number,
Polarity: Schema.Types.Mixed, //todo
FocusLens: String,
ModSlotPurchases: Number,
UpgradeType: Schema.Types.Mixed, //todo
UpgradeFingerprint: String,
ItemName: String,
ModularParts: [String],
UnlockLevel: Number
});
WeaponSchema.set("toJSON", {
transform(_document, returnedObject: ISuitDocument) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
returnedObject.ItemId = { $oid: returnedObject._id.toString() } satisfies Oid;
delete returnedObject._id;
delete returnedObject.__v;
}
});
const polaritySchema = new Schema({
Slot: Number,
Value: String
});
const suitConfigSchema = new Schema({
Skins: [String],
pricol: colorSchema,
@ -51,7 +108,7 @@ suitConfigSchema.set("toJSON", {
}
});
const suitSchema = new Schema({
const suitSchema = new Schema<ISuitDatabase>({
ItemType: String,
Configs: [suitConfigSchema],
UpgradeVer: Number,
@ -66,7 +123,7 @@ const suitSchema = new Schema({
});
suitSchema.set("toJSON", {
transform(_document, returnedObject) {
transform(_document, returnedObject: ISuitDocument) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
returnedObject.ItemId = { $oid: returnedObject._id.toString() } satisfies Oid;
delete returnedObject._id;
@ -74,7 +131,25 @@ suitSchema.set("toJSON", {
}
});
const inventorySchema = new Schema({
const slotsBinSchema = new Schema(
{
Slots: Number
},
{ _id: false }
);
const FlavourItemSchema = new Schema({
ItemType: String
});
FlavourItemSchema.set("toJSON", {
transform(_document, returnedObject: ISuitDocument) {
delete returnedObject._id;
delete returnedObject.__v;
}
});
const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>({
accountOwnerId: Schema.Types.ObjectId,
SubscribedToEmails: Number,
Created: Schema.Types.Mixed,
@ -83,9 +158,9 @@ const inventorySchema = new Schema({
PremiumCredits: Number,
PremiumCreditsFree: Number,
FusionPoints: Number,
SuitBin: Schema.Types.Mixed,
WeaponBin: Schema.Types.Mixed,
SentinelBin: Schema.Types.Mixed,
SuitBin: slotsBinSchema,
WeaponBin: slotsBinSchema,
SentinelBin: slotsBinSchema,
SpaceSuitBin: Schema.Types.Mixed,
SpaceWeaponBin: Schema.Types.Mixed,
PvpBonusLoadoutBin: Schema.Types.Mixed,
@ -104,12 +179,12 @@ const inventorySchema = new Schema({
RawUpgrades: [Schema.Types.Mixed],
ReceivedStartingGear: Boolean,
Suits: [suitSchema],
LongGuns: [Schema.Types.Mixed],
Pistols: [Schema.Types.Mixed],
Melee: [Schema.Types.Mixed],
LongGuns: [WeaponSchema],
Pistols: [WeaponSchema],
Melee: [WeaponSchema],
Ships: [Schema.Types.Mixed],
QuestKeys: [Schema.Types.Mixed],
FlavourItems: [Schema.Types.Mixed],
FlavourItems: [FlavourItemSchema],
Scoops: [Schema.Types.Mixed],
TrainingRetriesLeft: Number,
LoadOutPresets: Schema.Types.Mixed,
@ -253,7 +328,16 @@ inventorySchema.set("toJSON", {
}
});
const Suit = model<ISuitDatabase>("Suit", suitSchema);
const Inventory = model<IInventoryDatabase>("Inventory", inventorySchema);
type InventoryDocumentProps = {
Suits: Types.DocumentArray<ISuitDatabase>;
LongGuns: Types.DocumentArray<IWeaponDatabase>;
Pistols: Types.DocumentArray<IWeaponDatabase>;
Melee: Types.DocumentArray<IWeaponDatabase>;
FlavourItems: Types.DocumentArray<FlavourItem>;
};
export { Inventory, Suit };
type InventoryModelType = Model<IInventoryDatabase, {}, InventoryDocumentProps>;
const Inventory = model<IInventoryDatabase, InventoryModelType>("Inventory", inventorySchema);
export { Inventory };

View File

@ -1,17 +0,0 @@
import mongoose from "mongoose";
const accountSchema = new mongoose.Schema({
data: JSON
});
// personSchema.set("toJSON", {
// transform: (document, returnedObject:) => {
// returnedObject.id = returnedObject._id.toString();
// delete returnedObject._id;
// delete returnedObject.__v;
// },
// });
const Account = mongoose.model("account", accountSchema);
export { Account };

View File

@ -28,6 +28,7 @@ import { updateChallengeProgressController } from "@/src/controllers/api/updateC
import { updateSessionGetController, updateSessionPostController } from "@/src/controllers/api/updateSessionController";
import { viewController } from "@/src/controllers/api/viewController";
import { joinSessionController } from "@/src/controllers/api/joinSessionController";
import { saveLoadoutController } from "@/src/controllers/api/saveLoadout";
import express from "express";
@ -58,6 +59,7 @@ apiRouter.get("/logout.php", logoutController);
// post
apiRouter.post("/findSessions.php", findSessionsController);
// eslint-disable-next-line @typescript-eslint/no-misused-promises
apiRouter.post("/purchase.php", purchaseController);
apiRouter.post("/login.php", loginController);
apiRouter.post("/getAlliance.php", getAllianceController);
@ -68,4 +70,5 @@ apiRouter.post("/missionInventoryUpdate.php", missionInventoryUpdateController);
apiRouter.post("/genericUpdate.php", genericUpdateController);
apiRouter.post("/rerollRandomMod.php", rerollRandomModController);
apiRouter.post("/joinSession.php", joinSessionController);
apiRouter.post("/saveLoadout.php", saveLoadoutController);
export { apiRouter };

View File

@ -4,18 +4,14 @@ import config from "@/config.json";
const cacheRouter = express.Router();
cacheRouter.get("/B.Cache.Dx11.bin.*", (_req, res) => {
//console.log("asd", path.join(__dirname, "../data"));
res.sendFile("static/data/B.Cache.Dx11_33.0.6.bin", { root: "./" });
});
cacheRouter.get("/B.Cache.Windows_en.bin*", (_req, res) => {
//console.log("asd", path.join(__dirname, "../data"));
res.sendFile("static/data/B.Cache.Windows_en_33.0.10.bin", { root: "./" });
});
cacheRouter.get(/^\/origin\/([a-zA-Z0-9]+)\/H\.Cache\.bin.*$/, (_req, res) => {
// console.log("asd", path.join(__dirname, "../data"));
// console.log("asd", __dirname);
res.sendFile(`static/data/H.Cache_${config.version}.bin`, { root: "./" });
});

View File

@ -1,8 +1,10 @@
import { addItemController } from "@/src/controllers/custom/addItemController";
import { createAccountController } from "@/src/controllers/custom/createAccountController";
import express from "express";
const customRouter = express.Router();
customRouter.post("/createAccount", createAccountController);
customRouter.post("/addItem", addItemController);
export { customRouter };

View File

@ -2,6 +2,10 @@ import { Inventory } from "@/src/models/inventoryModel";
import new_inventory from "@/static/fixed_responses/postTutorialInventory.json";
import config from "@/config.json";
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 { FlavourItem } from "@/src/types/inventoryTypes/inventoryTypes";
const createInventory = async (accountOwnerId: Types.ObjectId) => {
try {
@ -22,4 +26,84 @@ const createInventory = async (accountOwnerId: Types.ObjectId) => {
}
};
export { createInventory };
//const updateInventory = async (accountOwnerId: Types.ObjectId, inventoryChanges: any) => {};
const getInventory = async (accountOwnerId: string) => {
const inventory = await Inventory.findOne({ accountOwnerId: accountOwnerId });
if (!inventory) {
throw new Error(`Didn't find an inventory for ${accountOwnerId}`);
}
return inventory;
};
const addPowerSuit = async (powersuitName: string, accountId: string): Promise<ISuitResponse> => {
const inventory = await getInventory(accountId);
const suitIndex = inventory.Suits.push({ ItemType: powersuitName, Configs: [], UpgradeVer: 101, XP: 0 });
const changedInventory = await inventory.save();
return changedInventory.Suits[suitIndex - 1].toJSON();
};
export const updateSlots = async (slotType: SlotType, accountId: string, slots: number) => {
const inventory = await getInventory(accountId);
switch (slotType) {
case SlotType.SUIT:
inventory.SuitBin.Slots += slots;
break;
case SlotType.WEAPON:
inventory.WeaponBin.Slots += slots;
break;
default:
throw new Error("invalid slot type");
}
await inventory.save();
};
export const updateCurrency = async (price: number, usePremium: boolean, accountId: string) => {
const currencyName = usePremium ? "PremiumCredits" : "RegularCredits";
const inventory = await getInventory(accountId);
inventory[currencyName] = inventory[currencyName] - price;
await inventory.save();
return { [currencyName]: -price };
};
export type WeaponTypeInternal = "LongGuns" | "Pistols" | "Melee";
export const addWeapon = async (
weaponType: WeaponTypeInternal,
weaponName: string,
accountId: string
): Promise<IWeaponResponse> => {
const inventory = await getInventory(accountId);
let weaponIndex;
switch (weaponType) {
case "LongGuns":
weaponIndex = inventory.LongGuns.push({ ItemType: weaponName, Configs: [], XP: 0 });
break;
case "Pistols":
weaponIndex = inventory.Pistols.push({ ItemType: weaponName, Configs: [], XP: 0 });
break;
case "Melee":
weaponIndex = inventory.Melee.push({ ItemType: weaponName, Configs: [], XP: 0 });
break;
default:
throw new Error("unknown weapon type");
}
const changedInventory = await inventory.save();
return changedInventory[weaponType][weaponIndex - 1].toJSON();
};
export const addCustomization = async (customizatonName: string, accountId: string): Promise<FlavourItem> => {
const inventory = await getInventory(accountId);
const flavourItemIndex = inventory.FlavourItems.push({ ItemType: customizatonName }) - 1;
const changedInventory = await inventory.save();
return changedInventory.FlavourItems[flavourItemIndex].toJSON(); //mongoose bug forces as FlavourItem
};
export { createInventory, addPowerSuit };

View File

@ -0,0 +1,116 @@
import { getWeaponType } from "@/src/helpers/purchaseHelpers";
import { getSubstringFromKeyword } from "@/src/helpers/stringHelpers";
import {
addCustomization,
addPowerSuit,
addWeapon,
updateCurrency,
updateSlots
} from "@/src/services/inventoryService";
import { IPurchaseRequest, IPurchaseResponse, SlotType } from "@/src/types/purchaseTypes";
export const getStoreItemCategory = (storeItem: string) => {
const storeItemString = getSubstringFromKeyword(storeItem, "StoreItems/");
const storeItemElements = storeItemString.split("/");
return storeItemElements[1];
};
export const getStoreItemTypesCategory = (typesItem: string) => {
const typesString = getSubstringFromKeyword(typesItem, "Types");
const typeElements = typesString.split("/");
if (typesItem.includes("StoreItems")) {
return typeElements[2];
}
return typeElements[1];
};
export const handlePurchase = async (purchaseRequest: IPurchaseRequest, accountId: string) => {
console.log(purchaseRequest);
const storeCategory = getStoreItemCategory(purchaseRequest.PurchaseParams.StoreItem);
const internalName = purchaseRequest.PurchaseParams.StoreItem.replace("/StoreItems", "");
console.log("Store category", storeCategory);
let purchaseResponse;
switch (storeCategory) {
case "Powersuits":
purchaseResponse = await handlePowersuitPurchase(internalName, accountId);
break;
case "Weapons":
purchaseResponse = await handleWeaponsPurchase(internalName, accountId);
break;
case "Types":
purchaseResponse = await handleTypesPurchase(internalName, accountId);
break;
default:
throw new Error(`unknown store category: ${storeCategory} not implemented or new`);
}
// const currencyResponse = await updateCurrency(
// purchaseRequest.PurchaseParams.ExpectedPrice,
// purchaseRequest.PurchaseParams.UsePremium,
// accountId
// );
// (purchaseResponse as IPurchaseResponse).InventoryChanges = {
// ...purchaseResponse.InventoryChanges,
// ...currencyResponse
// };
return purchaseResponse;
};
const handleWeaponsPurchase = async (weaponName: string, accountId: string) => {
const weaponType = getWeaponType(weaponName);
const addedWeapon = await addWeapon(weaponType, weaponName, accountId);
await updateSlots(SlotType.WEAPON, accountId, -1);
return {
InventoryChanges: {
WeaponBin: { count: 1, platinum: 0, Slots: -1 },
[weaponType]: [addedWeapon]
}
};
};
const handlePowersuitPurchase = async (powersuitName: string, accountId: string) => {
const suit = await addPowerSuit(powersuitName, accountId);
await updateSlots(SlotType.WEAPON, accountId, -1);
return {
InventoryChanges: {
SuitBin: {
count: 1,
platinum: 0,
Slots: -1
},
Suits: [suit]
}
};
};
const handleTypesPurchase = async (typesName: string, accountId: string) => {
const typeCategory = getStoreItemTypesCategory(typesName);
console.log("type category", typeCategory);
switch (typeCategory) {
case "SuitCustomizations":
return await handleSuitCustomizationsPurchase(typesName, accountId);
// case "Recipes":
// break;
// case "Sentinels":
// break;
default:
throw new Error(`unknown Types category: ${typeCategory} not implemented or new`);
}
};
const handleSuitCustomizationsPurchase = async (customizationName: string, accountId: string) => {
const customization = await addCustomization(customizationName, accountId);
return {
InventoryChanges: {
FlavourItems: [customization]
}
};
};

View File

@ -0,0 +1,44 @@
import { Oid } from "@/src/types/commonTypes";
import { AbilityOverride, Color, Polarity } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { Document } from "mongoose";
export interface ISuitDocument extends ISuitResponse, Document {}
export interface ISuitResponse extends ISuitDatabase {
ItemId: Oid;
}
export interface ISuitDatabase {
ItemType: string;
Configs: SuitConfig[];
UpgradeVer?: number;
XP?: number;
InfestationDate?: Date;
Features?: number;
Polarity?: Polarity[];
Polarized?: number;
ModSlotPurchases?: number;
FocusLens?: string;
UnlockLevel?: number;
}
export interface SuitConfig {
Skins?: string[];
pricol?: Color;
attcol?: Color;
eyecol?: Color;
sigcol?: Color;
Upgrades?: string[];
Songs?: Song[];
Name?: string;
AbilityOverride?: AbilityOverride;
PvpUpgrades?: string[];
ugly?: boolean;
}
export interface Song {
m?: string;
b?: string;
p?: string;
s: string;
}

View File

@ -0,0 +1,42 @@
export interface Polarity {
Slot: number;
Value: FocusSchool;
}
export enum FocusSchool {
ApAny = "AP_ANY",
ApAttack = "AP_ATTACK",
ApDefense = "AP_DEFENSE",
ApPower = "AP_POWER",
ApPrecept = "AP_PRECEPT",
ApTactic = "AP_TACTIC",
ApUmbra = "AP_UMBRA",
ApUniversal = "AP_UNIVERSAL",
ApWard = "AP_WARD"
}
export interface Color {
t0?: number;
t1?: number;
t2?: number;
t3?: number;
en?: number;
e1?: number;
m0?: number;
m1?: number;
}
export interface AbilityOverride {
Ability: string;
Index: number;
}
export interface SlotsBin {
Slots: number;
}
export interface sigcol {
t0: number;
t1: number;
en: number;
}

View File

@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Document, Types } from "mongoose";
import { ODate, Oid } from "./commonTypes";
import { Oid } from "./commonTypes";
export interface IInventoryDatabase extends IInventoryResponse {
accountOwnerId: Types.ObjectId;
@ -9,7 +9,7 @@ export interface IInventoryDatabase extends IInventoryResponse {
export interface IInventoryResponse {
SubscribedToEmails: number;
Created: ODate;
Created: Date;
RewardSeed: number;
RegularCredits: number;
PremiumCredits: number;
@ -53,7 +53,7 @@ export interface IInventoryResponse {
Recipes: Consumable[];
WeaponSkins: WeaponSkin[];
PendingRecipes: PendingRecipe[];
TrainingDate: ODate;
TrainingDate: Date;
PlayerLevel: number;
Upgrades: CrewShipSalvagedWeaponSkin[];
EquippedGear: string[];
@ -130,7 +130,7 @@ export interface IInventoryResponse {
InvasionChainProgress: InvasionChainProgress[];
DataKnives: DataKnife[];
NemesisHistory: NemesisHistory[];
LastNemesisAllySpawnTime: ODate;
LastNemesisAllySpawnTime: Date;
Settings: Settings;
PersonalTechProjects: PersonalTechProject[];
CrewShips: CrewShip[];
@ -141,7 +141,7 @@ export interface IInventoryResponse {
CrewShipWeapons: CrewShipWeapon[];
CrewShipSalvagedWeapons: CrewShipWeapon[];
CrewShipWeaponSkins: CrewShipSalvagedWeaponSkin[];
TradeBannedUntil: ODate;
TradeBannedUntil: Date;
PlayedParkourTutorial: boolean;
SubscribedToEmailsPersonalized: number;
MechBin: CrewMemberBinClass;
@ -149,7 +149,7 @@ export interface IInventoryResponse {
DailyAffiliationNecraloid: number;
MechSuits: MechSuit[];
InfestedFoundry: InfestedFoundry;
BlessingCooldown: ODate;
BlessingCooldown: Date;
CrewMemberBin: CrewMemberBinClass;
CrewShipHarnesses: CrewShipHarness[];
CrewShipRawSalvage: Consumable[];
@ -161,7 +161,7 @@ export interface IInventoryResponse {
NemesisAbandonedRewards: string[];
DailyAffiliationKahl: number;
LastInventorySync: Oid;
NextRefill: ODate;
NextRefill: Date;
ActiveLandscapeTraps: any[];
EvolutionProgress: any[];
RepVotes: any[];
@ -213,6 +213,10 @@ export interface Alignment {
Alignment: number;
}
export interface Date {
$date: { $numberLong: string };
}
export interface Booster {
ExpiryDate: number;
ItemType: string;
@ -273,7 +277,7 @@ export interface CrewMember {
ItemType: string;
NemesisFingerprint: number;
Seed: number;
HireDate: ODate;
HireDate: Date;
AssignedRole: number;
SkillEfficiency: SkillEfficiency;
WeaponConfigIdx: number;
@ -443,7 +447,7 @@ export interface Drone {
ItemType: string;
CurrentHP: number;
ItemId: Oid;
RepairStart?: ODate;
RepairStart?: Date;
}
export interface EmailItem {
@ -531,7 +535,7 @@ export interface InvasionChainProgress {
export interface KubrowPetEgg {
ItemType: KubrowPetEggItemType;
ExpirationDate: ODate;
ExpirationDate: Date;
ItemId: Oid;
}
@ -584,7 +588,7 @@ export interface KubrowPet {
Polarized?: number;
Polarity?: Polarity[];
Features?: number;
InfestationDate?: ODate;
InfestationDate?: Date;
InfestationDays?: number;
InfestationType?: string;
ItemId: Oid;
@ -604,7 +608,7 @@ export interface Details {
HasCollar: boolean;
PrintsRemaining: number;
Status: Status;
HatchDate: ODate;
HatchDate: Date;
DominantTraits: Traits;
RecessiveTraits: Traits;
IsMale: boolean;
@ -808,7 +812,7 @@ export interface Mission {
Completes: number;
Tier?: number;
Tag: string;
RewardsCooldownTime?: ODate;
RewardsCooldownTime?: Date;
}
export interface MoaPet {
@ -833,7 +837,7 @@ export interface NemesisHistory {
BirthNode: BirthNode;
Rank: number;
k: boolean;
d: ODate;
d: Date;
GuessHistory?: number[];
currentGuess?: number;
Traded?: boolean;
@ -887,13 +891,13 @@ export interface AbilityOverride {
}
export interface PendingCoupon {
Expiry: ODate;
Expiry: Date;
Discount: number;
}
export interface PendingRecipe {
ItemType: string;
CompletionDate: ODate;
CompletionDate: Date;
ItemId: Oid;
}
@ -952,7 +956,7 @@ export enum GivingSlotOrderInfo {
}
export interface PeriodicMissionCompletion {
date: ODate;
date: Date;
tag: string;
count?: number;
}
@ -971,7 +975,7 @@ export interface PersonalTechProject {
ReqCredits: number;
ItemType: string;
ReqItems: Consumable[];
CompletionDate?: ODate;
CompletionDate?: Date;
ItemId: Oid;
ProductCategory?: string;
CategoryItemId?: Oid;
@ -992,7 +996,7 @@ export interface QuestKey {
unlock?: boolean;
Completed?: boolean;
ItemType: string;
CompletionDate?: ODate;
CompletionDate?: Date;
}
export interface Progress {
@ -1166,7 +1170,7 @@ export interface ISuitDatabase {
Configs: SuitConfig[];
UpgradeVer?: number;
XP?: number;
InfestationDate?: ODate;
InfestationDate?: Date;
Features?: number;
Polarity?: Polarity[];
Polarized?: number;
@ -1211,15 +1215,15 @@ export interface WebFlags {
activeBuyPlat: number;
noShow2FA: boolean;
Tennocon2018Digital: boolean;
VisitPrimeAccess: ODate;
VisitTennocon2019: ODate;
enteredSC2019: ODate;
VisitPrimeVault: ODate;
VisitBuyPlatinum: ODate;
ClickedSku_640_Page__en_buyplatinum: ODate;
ClickedSku_640_Page__buyplatinum: ODate;
VisitStarterPack: ODate;
VisitPrimeAccess: Date;
VisitTennocon2019: Date;
enteredSC2019: Date;
VisitPrimeVault: Date;
VisitBuyPlatinum: Date;
ClickedSku_640_Page__en_buyplatinum: Date;
ClickedSku_640_Page__buyplatinum: Date;
VisitStarterPack: Date;
Tennocon2020Digital: boolean;
Anniversary2021: boolean;
HitDownloadBtn: ODate;
HitDownloadBtn: Date;
}

View File

@ -0,0 +1,39 @@
import { Oid } from "@/src/types/commonTypes";
import { Color, Polarity } from "@/src/types/inventoryTypes/commonInventoryTypes";
export interface IWeaponResponse extends IWeaponDatabase {
ItemId: Oid;
}
export interface IWeaponDatabase {
ItemType: string;
Configs: WeaponConfig[];
UpgradeVer?: number;
XP?: number;
Features?: number;
Polarized?: number;
Polarity?: Polarity[];
FocusLens?: string;
ModSlotPurchases?: number;
UpgradeType?: string;
UpgradeFingerprint?: string;
ItemName?: string;
ModularParts?: string[];
UnlockLevel?: number;
}
export interface WeaponConfig {
Skins?: string[];
pricol?: Color;
Upgrades?: string[];
attcol?: Color;
eyecol?: OperatorLoadOutSigcol;
Name?: string;
PvpUpgrades?: string[];
}
export interface OperatorLoadOutSigcol {
t0?: number;
t1?: number;
en?: number;
}

View File

@ -0,0 +1,45 @@
/* eslint-disable prettier/prettier */
import { ISuitDatabase } from "@/src/types/inventoryTypes/SuitTypes";
import { FlavourItem } from "@/src/types/inventoryTypes/inventoryTypes";
import { IWeaponResponse } from "@/src/types/inventoryTypes/weaponTypes";
export interface IPurchaseRequest {
PurchaseParams: IPurchaseParams;
buildLabel: string;
}
export interface IPurchaseParams {
Source: number;
StoreItem: string;
StorePage: string;
SearchTerm: string;
CurrentLocation: string;
Quantity: number;
UsePremium: boolean;
ExpectedPrice: number;
}
export interface IPurchaseResponse {
InventoryChanges: {
SuitBin?: IBinChanges;
WeaponBin?: IBinChanges;
Suits?: ISuitDatabase[];
LongGuns?: IWeaponResponse[];
Pistols?: IWeaponResponse[];
Melee?: IWeaponResponse[];
PremiumCredits?: number;
RegularCredits?: number;
FlavourItems?: FlavourItem[];
};
}
export type IBinChanges = {
count: number;
platinum: number;
Slots: number;
};
export enum SlotType {
SUIT = "SuitBin",
WEAPON = "WeaponBin"
}

18
static/data/items.ts Normal file
View File

@ -0,0 +1,18 @@
import Items, { Item, Weapon } from "warframe-items";
type MinWeapon = Omit<Weapon, "patchlogs">;
type MinItem = Omit<Item, "patchlogs">;
export const weapons: MinWeapon[] = (new Items({ category: ["Primary", "Secondary", "Melee"] }) as Weapon[]).map(
item => {
const next = { ...item };
delete next.patchlogs;
return next;
}
);
export const items: MinItem[] = new Items({ category: ["All"] }).map(item => {
const next = { ...item };
delete next.patchlogs;
return next;
});