Compare commits

..

No commits in common. "main" and "main" have entirely different histories.
main ... main

158 changed files with 2827 additions and 11069 deletions

View File

@ -1,12 +1,10 @@
{
"plugins": ["@typescript-eslint", "prettier", "import"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:import/recommended",
"plugin:import/typescript"
"plugin:@typescript-eslint/recommended-requiring-type-checking"
],
"plugins": ["@typescript-eslint", "prettier"],
"env": {
"browser": true,
"es6": true,
@ -21,26 +19,18 @@
"@typescript-eslint/no-unsafe-argument": "error",
"@typescript-eslint/no-unsafe-call": "error",
"@typescript-eslint/no-unsafe-assignment": "error",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-explicit-any": "error",
"no-loss-of-precision": "error",
"@typescript-eslint/no-unnecessary-condition": "error",
"@typescript-eslint/no-base-to-string": "off",
"no-case-declarations": "error",
"prettier/prettier": "error",
"no-mixed-spaces-and-tabs": "error",
"@typescript-eslint/require-await": "error",
"import/no-named-as-default-member": "off",
"import/no-cycle": "warn"
"require-await": "off",
"@typescript-eslint/require-await": "error"
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"settings": {
"import/extensions": [ ".ts" ],
"import/resolver": {
"typescript": true,
"node": true
}
}
}

View File

@ -14,12 +14,11 @@ jobs:
with:
node-version: ">=20.6.0"
- run: npm ci
- run: cp config-vanilla.json config.json
- run: cp config.json.example config.json
- run: npm run verify
- run: npm run lint:ci
- run: npm run prettier
- run: npm run update-translations
- run: npm run fix-imports
- name: Fail if there are uncommitted changes
run: |
if [[ -n "$(git status --porcelain)" ]]; then

View File

@ -2,4 +2,3 @@ src/routes/api.ts
static/webui/libs/
*.html
*.md
config-vanilla.json

View File

@ -7,6 +7,5 @@ WORKDIR /app
RUN npm i --omit=dev
RUN npm run build
RUN date '+%d %B %Y' > BUILD_DATE
ENTRYPOINT ["/app/docker-entrypoint.sh"]

View File

@ -10,7 +10,7 @@ To get an idea of what functionality you can expect to be missing [have a look t
## config.json
SpaceNinjaServer requires a `config.json`. To set it up, you can copy the [config-vanilla.json](config-vanilla.json), which has most cheats disabled.
SpaceNinjaServer requires a `config.json`. To set it up, you can copy the [config.json.example](config.json.example), which has most cheats disabled.
- `logger.level` can be `fatal`, `error`, `warn`, `info`, `http`, `debug`, or `trace`.
- `myIrcAddresses` can be used to point to an IRC server. If not provided, defaults to `[ myAddress ]`.

View File

@ -13,6 +13,11 @@
"skipTutorial": false,
"skipAllDialogue": false,
"unlockAllScans": false,
"infiniteCredits": false,
"infinitePlatinum": false,
"infiniteEndo": false,
"infiniteRegalAya": false,
"infiniteHelminthMaterials": false,
"claimingBlueprintRefundsIngredients": false,
"dontSubtractPurchaseCreditCost": false,
"dontSubtractPurchasePlatinumCost": false,
@ -65,33 +70,15 @@
"creditBoost": false,
"affinityBoost": false,
"resourceBoost": false,
"tennoLiveRelay": false,
"wolfHunt": false,
"longShadow": false,
"hallowedFlame": false,
"hallowedNightmares": false,
"hallowedNightmaresRewardsOverride": 0,
"proxyRebellion": false,
"proxyRebellionRewardsOverride": 0,
"starDays": true,
"galleonOfGhouls": 0,
"ghoulEmergenceOverride": null,
"plagueStarOverride": null,
"starDaysOverride": null,
"dogDaysOverride": null,
"dogDaysRewardsOverride": null,
"bellyOfTheBeast": false,
"bellyOfTheBeastProgressOverride": 0,
"eightClaw": false,
"eightClawProgressOverride": 0,
"eidolonOverride": "",
"vallisOverride": "",
"duviriOverride": "",
"nightwaveOverride": "",
"allTheFissures": "",
"circuitGameModes": null,
"darvoStockMultiplier": 1,
"varziaOverride": "",
"varziaFullyStocked": false
"darvoStockMultiplier": 1
},
"dev": {
"keepVendorsExpired": false

View File

@ -2,7 +2,7 @@
set -e
if [ ! -f conf/config.json ]; then
jq --arg value "mongodb://openwfagent:spaceninjaserver@mongodb:27017/" '.mongodbUrl = $value' /app/config-vanilla.json > /app/conf/config.json
jq --arg value "mongodb://openwfagent:spaceninjaserver@mongodb:27017/" '.mongodbUrl = $value' /app/config.json.example > /app/conf/config.json
fi
exec npm run start -- --configPath conf/config.json

2642
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -14,15 +14,12 @@
"dev": "node scripts/dev.js",
"dev:bun": "bun scripts/dev.js",
"verify": "tsgo --noEmit",
"verify:tsc": "tsc --noEmit",
"bun-run": "bun src/index.ts",
"lint": "eslint --ext .ts .",
"lint:ci": "eslint --ext .ts --rule \"prettier/prettier: off\" .",
"lint:fix": "eslint --fix --ext .ts .",
"prettier": "prettier --write .",
"update-translations": "cd scripts && node update-translations.js",
"fix-imports": "cd scripts && node fix-imports.js",
"fix": "npm run update-translations && npm run fix-imports && npm run prettier"
"update-translations": "cd scripts && node update-translations.js"
},
"license": "GNU",
"dependencies": {
@ -40,7 +37,7 @@
"ncp": "^2.0.0",
"typescript": "^5.5",
"undici": "^7.10.0",
"warframe-public-export-plus": "^0.5.80",
"warframe-public-export-plus": "^0.5.76",
"warframe-riven-info": "^0.1.2",
"winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0",
@ -50,8 +47,6 @@
"@typescript-eslint/eslint-plugin": "^8.28.0",
"@typescript-eslint/parser": "^8.28.0",
"eslint": "^8",
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-prettier": "^5.2.5",
"prettier": "^3.5.3",
"tree-kill": "^1.2.2"

View File

@ -1,46 +0,0 @@
/* eslint-disable */
const fs = require("fs");
const path = require("path");
const root = path.join(process.cwd(), "..");
function listFiles(dir) {
const entries = fs.readdirSync(dir, { withFileTypes: true });
let results = [];
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
results = results.concat(listFiles(fullPath));
} else {
results.push(fullPath);
}
}
return results;
}
const files = listFiles(path.join(root, "src"));
for (const file of files) {
let content;
try {
content = fs.readFileSync(file, "utf8");
} catch (e) {
continue;
}
const dir = path.dirname(file);
const fixedContent = content.replaceAll(/} from "([^"]+)";/g, (sub, importPath) => {
if (!importPath.startsWith("@/")) {
const fullImportPath = path.resolve(dir, importPath);
if (fs.existsSync(fullImportPath + ".ts")) {
const relative = path.relative(root, fullImportPath).replace(/\\/g, "/");
const fixedPath = "@/" + relative;
console.log(`${importPath} -> ${fixedPath}`);
return sub.split(importPath).join(fixedPath);
}
}
return sub;
});
if (content != fixedContent) {
fs.writeFileSync(file, fixedContent, "utf8");
}
}

View File

@ -1,22 +0,0 @@
import { getAccountIdForRequest } from "@/src/services/loginService";
import { getPersonalRooms } from "@/src/services/personalRoomsService";
import { RequestHandler } from "express";
export const apartmentController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const personalRooms = await getPersonalRooms(accountId, "Apartment");
const response: IApartmentResponse = {};
if (req.query.backdrop !== undefined) {
response.NewBackdropItem = personalRooms.Apartment.VideoWallBackdrop = req.query.backdrop as string;
}
if (req.query.soundscape !== undefined) {
response.NewSoundscapeItem = personalRooms.Apartment.Soundscape = req.query.soundscape as string;
}
await personalRooms.save();
res.json(response);
};
interface IApartmentResponse {
NewBackdropItem?: string;
NewSoundscapeItem?: string;
}

View File

@ -3,6 +3,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
import { RequestHandler } from "express";
import { IInventoryClient, IUpgradeClient } from "@/src/types/inventoryTypes/inventoryTypes";
import { addMods, getInventory } from "@/src/services/inventoryService";
import { config } from "@/src/services/configService";
export const artifactsController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
@ -23,6 +24,7 @@ export const artifactsController: RequestHandler = async (req, res) => {
if (itemIndex !== -1) {
Upgrades[itemIndex].UpgradeFingerprint = stringifiedUpgradeFingerprint;
inventory.markModified(`Upgrades.${itemIndex}.UpgradeFingerprint`);
} else {
itemIndex =
Upgrades.push({
@ -33,10 +35,10 @@ export const artifactsController: RequestHandler = async (req, res) => {
addMods(inventory, [{ ItemType, ItemCount: -1 }]);
}
if (!inventory.infiniteCredits) {
if (!config.infiniteCredits) {
inventory.RegularCredits -= Cost;
}
if (!inventory.infiniteEndo) {
if (!config.infiniteEndo) {
inventory.FusionPoints -= FusionPointCost;
}

View File

@ -14,17 +14,15 @@ import {
addRecipes,
occupySlot,
combineInventoryChanges,
addKubrowPetPrint,
addPowerSuit,
addEquipment
addKubrowPetPrint
} from "@/src/services/inventoryService";
import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { InventorySlot, IPendingRecipeDatabase } from "@/src/types/inventoryTypes/inventoryTypes";
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { InventorySlot, IPendingRecipeDatabase, Status } from "@/src/types/inventoryTypes/inventoryTypes";
import { toOid2 } from "@/src/helpers/inventoryHelpers";
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
import { IRecipe } from "warframe-public-export-plus";
import { config } from "@/src/services/configService";
import { EquipmentFeatures, IEquipmentClient, Status } from "@/src/types/equipmentTypes";
interface IClaimCompletedRecipeRequest {
RecipeIds: IOid[];
@ -126,122 +124,17 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
const pet = inventory.KubrowPets.id(pendingRecipe.KubrowPet!)!;
addKubrowPetPrint(inventory, pet, InventoryChanges);
} else if (recipe.secretIngredientAction != "SIA_UNBRAND") {
if (recipe.resultType == "/Lotus/Powersuits/Excalibur/ExcaliburUmbra") {
// Quite the special case here...
// We don't just get Umbra, but also Skiajati and Umbra Mods. Both items are max rank, potatoed, and with the mods are pre-installed.
// Source: https://wiki.warframe.com/w/The_Sacrifice, https://wiki.warframe.com/w/Excalibur/Umbra, https://wiki.warframe.com/w/Skiajati
const umbraModA = (
await addItem(
inventory,
"/Lotus/Upgrades/Mods/Sets/Umbra/WarframeUmbraModA",
1,
false,
undefined,
`{"lvl":5}`
)
).Upgrades![0];
const umbraModB = (
await addItem(
inventory,
"/Lotus/Upgrades/Mods/Sets/Umbra/WarframeUmbraModB",
1,
false,
undefined,
`{"lvl":5}`
)
).Upgrades![0];
const umbraModC = (
await addItem(
inventory,
"/Lotus/Upgrades/Mods/Sets/Umbra/WarframeUmbraModC",
1,
false,
undefined,
`{"lvl":5}`
)
).Upgrades![0];
const sacrificeModA = (
await addItem(
inventory,
"/Lotus/Upgrades/Mods/Sets/Sacrifice/MeleeSacrificeModA",
1,
false,
undefined,
`{"lvl":5}`
)
).Upgrades![0];
const sacrificeModB = (
await addItem(
inventory,
"/Lotus/Upgrades/Mods/Sets/Sacrifice/MeleeSacrificeModB",
1,
false,
undefined,
`{"lvl":5}`
)
).Upgrades![0];
InventoryChanges.Upgrades ??= [];
InventoryChanges.Upgrades.push(umbraModA, umbraModB, umbraModC, sacrificeModA, sacrificeModB);
await addPowerSuit(
InventoryChanges = {
...InventoryChanges,
...(await addItem(
inventory,
"/Lotus/Powersuits/Excalibur/ExcaliburUmbra",
{
Configs: [
{
Upgrades: [
"",
"",
"",
"",
"",
umbraModA.ItemId.$oid,
umbraModB.ItemId.$oid,
umbraModC.ItemId.$oid
]
}
],
XP: 900_000,
Features: EquipmentFeatures.DOUBLE_CAPACITY
},
InventoryChanges
);
inventory.XPInfo.push({
ItemType: "/Lotus/Powersuits/Excalibur/ExcaliburUmbra",
XP: 900_000
});
addEquipment(
inventory,
"Melee",
"/Lotus/Weapons/Tenno/Melee/Swords/UmbraKatana/UmbraKatana",
{
Configs: [
{ Upgrades: ["", "", "", "", "", "", sacrificeModA.ItemId.$oid, sacrificeModB.ItemId.$oid] }
],
XP: 450_000,
Features: EquipmentFeatures.DOUBLE_CAPACITY
},
InventoryChanges
);
inventory.XPInfo.push({
ItemType: "/Lotus/Weapons/Tenno/Melee/Swords/UmbraKatana/UmbraKatana",
XP: 450_000
});
} else {
InventoryChanges = {
...InventoryChanges,
...(await addItem(
inventory,
recipe.resultType,
recipe.num,
false,
undefined,
pendingRecipe.TargetFingerprint
))
};
}
recipe.resultType,
recipe.num,
false,
undefined,
pendingRecipe.TargetFingerprint
))
};
}
if (
config.claimingBlueprintRefundsIngredients &&

View File

@ -1,4 +1,4 @@
import { checkCalendarAutoAdvance, getCalendarProgress, getInventory } from "@/src/services/inventoryService";
import { checkCalendarChallengeCompletion, getCalendarProgress, getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
import { getWorldState } from "@/src/services/worldStateService";
@ -28,7 +28,7 @@ export const completeCalendarEventController: RequestHandler = async (req, res)
}
}
calendarProgress.SeasonProgress.LastCompletedDayIdx = dayIndex;
checkCalendarAutoAdvance(inventory, currentSeason);
checkCalendarChallengeCompletion(calendarProgress, currentSeason);
await inventory.save();
res.json({
InventoryChanges: inventoryChanges,

View File

@ -4,7 +4,8 @@ import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inven
import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { IVeiledRivenFingerprint } from "@/src/helpers/rivenHelper";
import { createUnveiledRivenFingerprint } from "@/src/helpers/rivenHelper";
import { ExportUpgrades } from "warframe-public-export-plus";
export const completeRandomModChallengeController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
@ -26,11 +27,10 @@ export const completeRandomModChallengeController: RequestHandler = async (req,
inventoryChanges.MiscItems = miscItemChanges;
}
// Complete the riven challenge
// Update riven fingerprint to a randomised unveiled state
const upgrade = inventory.Upgrades.id(request.ItemId)!;
const fp = JSON.parse(upgrade.UpgradeFingerprint!) as IVeiledRivenFingerprint;
fp.challenge.Progress = fp.challenge.Required;
upgrade.UpgradeFingerprint = JSON.stringify(fp);
const meta = ExportUpgrades[upgrade.ItemType];
upgrade.UpgradeFingerprint = JSON.stringify(createUnveiledRivenFingerprint(meta));
await inventory.save();

View File

@ -21,8 +21,7 @@ import {
updateCurrency
} from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { ITypeCount } from "@/src/types/commonTypes";
import { IFusionTreasure, IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
import { IFusionTreasure, IMiscItem, ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
import { RequestHandler } from "express";
export const contributeToVaultController: RequestHandler = async (req, res) => {

View File

@ -1,4 +1,5 @@
import { RequestHandler } from "express";
import { config } from "@/src/services/configService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory } from "@/src/services/inventoryService";
@ -8,7 +9,7 @@ export const creditsController: RequestHandler = async (req, res) => {
getAccountIdForRequest(req),
getInventory(
req.query.accountId as string,
"RegularCredits TradesRemaining PremiumCreditsFree PremiumCredits infiniteCredits infinitePlatinum"
"RegularCredits TradesRemaining PremiumCreditsFree PremiumCredits"
)
])
)[1];
@ -20,10 +21,10 @@ export const creditsController: RequestHandler = async (req, res) => {
PremiumCredits: inventory.PremiumCredits
};
if (inventory.infiniteCredits) {
if (config.infiniteCredits) {
response.RegularCredits = 999999999;
}
if (inventory.infinitePlatinum) {
if (config.infinitePlatinum) {
response.PremiumCreditsFree = 0;
response.PremiumCredits = 999999999;
}

View File

@ -88,6 +88,7 @@ export const crewShipFusionController: RequestHandler = async (req, res) => {
}
}
superiorItem.UpgradeFingerprint = JSON.stringify(fingerprint);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
inventoryChanges[category] = [superiorItem.toJSON() as any];
await inventory.save();

View File

@ -12,7 +12,7 @@ import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { getRandomInt } from "@/src/services/rngService";
import { IFingerprintStat } from "@/src/helpers/rivenHelper";
import { IEquipmentDatabase } from "@/src/types/equipmentTypes";
import { IEquipmentDatabase } from "@/src/types/inventoryTypes/commonInventoryTypes";
export const crewShipIdentifySalvageController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);

View File

@ -1,15 +1,12 @@
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { Guild } from "@/src/models/guildModel";
import { hasAccessToDojo, hasGuildPermission } from "@/src/services/guildService";
import { getInventory } from "@/src/services/inventoryService";
import { getAccountForRequest, getAccountIdForRequest } from "@/src/services/loginService";
import { GuildPermission } from "@/src/types/guildTypes";
import { getAccountForRequest } from "@/src/services/loginService";
import { logger } from "@/src/utils/logger";
import { RequestHandler } from "express";
export const customObstacleCourseLeaderboardController: RequestHandler = async (req, res) => {
const data = getJSONfromString<ICustomObstacleCourseLeaderboardRequest>(String(req.body));
const guild = (await Guild.findById(data.g, "DojoComponents Ranks"))!;
const guild = (await Guild.findById(data.g, "DojoComponents"))!;
const component = guild.DojoComponents.id(data.c)!;
if (req.query.act == "f") {
res.json({
@ -37,19 +34,6 @@ export const customObstacleCourseLeaderboardController: RequestHandler = async (
entry.r = ++r;
}
await guild.save();
res.status(200).end();
} else if (req.query.act == "c") {
// TOVERIFY: What clan permission is actually needed for this?
const accountId = await getAccountIdForRequest(req);
const inventory = await getInventory(accountId, "GuildId LevelKeys");
if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Decorator))) {
res.status(400).end();
return;
}
component.Leaderboard = undefined;
await guild.save();
res.status(200).end();
} else {
logger.debug(`data provided to ${req.path}: ${String(req.body)}`);

View File

@ -3,13 +3,11 @@ import {
getGuildForRequestEx,
hasAccessToDojo,
hasGuildPermission,
refundDojoDeco,
removeDojoDeco
} from "@/src/services/guildService";
import { getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { GuildPermission } from "@/src/types/guildTypes";
import { logger } from "@/src/utils/logger";
import { RequestHandler } from "express";
export const destroyDojoDecoController: RequestHandler = async (req, res) => {
@ -20,20 +18,9 @@ export const destroyDojoDecoController: RequestHandler = async (req, res) => {
res.json({ DojoRequestStatus: -1 });
return;
}
const request = JSON.parse(String(req.body)) as IDestroyDojoDecoRequest | IClearObstacleCourseRequest;
if ("DecoType" in request) {
removeDojoDeco(guild, request.ComponentId, request.DecoId);
} else if (request.Act == "cObst") {
const component = guild.DojoComponents.id(request.ComponentId)!;
if (component.Decos) {
for (const deco of component.Decos) {
refundDojoDeco(guild, component, deco);
}
component.Decos.splice(0, component.Decos.length);
}
} else {
logger.error(`unhandled destroyDojoDeco request`, request);
}
const request = JSON.parse(String(req.body)) as IDestroyDojoDecoRequest;
removeDojoDeco(guild, request.ComponentId, request.DecoId);
await guild.save();
res.json(await getDojoClient(guild, 0, request.ComponentId));
@ -44,8 +31,3 @@ interface IDestroyDojoDecoRequest {
ComponentId: string;
DecoId: string;
}
interface IClearObstacleCourseRequest {
ComponentId: string;
Act: "cObst" | "maybesomethingelsewedontknowabout";
}

View File

@ -72,7 +72,7 @@ export const dronesController: RequestHandler = async (req, res) => {
);
}
} else {
drone.ResourceCount = droneMeta.binCapacity * droneMeta.capacityMultipliers[resource.Rarity];
drone.ResourceCount = 1;
}
await inventory.save();
res.json({});

View File

@ -3,7 +3,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
import { addMiscItems, getInventory } from "@/src/services/inventoryService";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { getRecipe, WeaponTypeInternal } from "@/src/services/itemDataService";
import { EquipmentFeatures } from "@/src/types/equipmentTypes";
import { EquipmentFeatures } from "@/src/types/inventoryTypes/commonInventoryTypes";
export const evolveWeaponController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);

View File

@ -4,6 +4,7 @@ import { getInventory, addMiscItems, addEquipment, occupySlot } from "@/src/serv
import { IMiscItem, TFocusPolarity, TEquipmentKey, InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
import { logger } from "@/src/utils/logger";
import { ExportFocusUpgrades } from "warframe-public-export-plus";
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
export const focusController: RequestHandler = async (req, res) => {
@ -115,7 +116,7 @@ export const focusController: RequestHandler = async (req, res) => {
});
occupySlot(inventory, InventorySlot.AMPS, false);
await inventory.save();
res.json(inventoryChanges.OperatorAmps![0]);
res.json((inventoryChanges.OperatorAmps as IEquipmentClient[])[0]);
break;
}
case FocusOperation.UnbindUpgrade: {

View File

@ -2,14 +2,22 @@ import { RequestHandler } from "express";
import { ExportResources } from "warframe-public-export-plus";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { addFusionTreasures, addMiscItems, getInventory } from "@/src/services/inventoryService";
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
import { parseFusionTreasure } from "@/src/helpers/inventoryHelpers";
import { IFusionTreasure, IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
interface IFusionTreasureRequest {
oldTreasureName: string;
newTreasureName: string;
}
const parseFusionTreasure = (name: string, count: number): IFusionTreasure => {
const arr = name.split("_");
return {
ItemType: arr[0],
Sockets: parseInt(arr[1], 16),
ItemCount: count
};
};
export const fusionTreasuresController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const inventory = await getInventory(accountId);

View File

@ -6,8 +6,9 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
import { createGarden, getPersonalRooms } from "@/src/services/personalRoomsService";
import { IMongoDate } from "@/src/types/commonTypes";
import { IMissionReward } from "@/src/types/missionTypes";
import { IGardeningClient, IPersonalRoomsClient } from "@/src/types/personalRoomsTypes";
import { IPersonalRoomsClient } from "@/src/types/personalRoomsTypes";
import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { IGardeningClient } from "@/src/types/shipTypes";
import { RequestHandler } from "express";
import { dict_en, ExportResources } from "warframe-public-export-plus";

View File

@ -1,25 +0,0 @@
import { RequestHandler } from "express";
import { getAccountForRequest } from "@/src/services/loginService";
import { getInventory } from "@/src/services/inventoryService";
import { Guild } from "@/src/models/guildModel";
export const getGuildEventScoreController: RequestHandler = async (req, res) => {
const account = await getAccountForRequest(req);
const inventory = await getInventory(account._id.toString(), "GuildId");
const guild = await Guild.findById(inventory.GuildId);
const goalId = req.query.goalId as string;
if (guild && guild.GoalProgress && goalId) {
const goal = guild.GoalProgress.find(x => x.goalId.toString() == goalId);
if (goal) {
return res.json({
Tier: guild.Tier,
GoalProgress: {
Count: goal.Count,
Tag: goal.Tag,
_id: { $oid: goal.goalId }
}
});
}
}
return res.json({});
};

View File

@ -1,6 +1,6 @@
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
import { generateRewardSeed } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { generateRewardSeed } from "@/src/services/rngService";
import { RequestHandler } from "express";
export const getNewRewardSeedController: RequestHandler = async (req, res) => {

View File

@ -1,62 +0,0 @@
import { RequestHandler } from "express";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory } from "@/src/services/inventoryService";
import { EPOCH, getSeasonChallengePools, getWorldState, pushWeeklyActs } from "@/src/services/worldStateService";
import { unixTimesInMs } from "@/src/constants/timeConstants";
import { ISeasonChallenge } from "@/src/types/worldStateTypes";
import { ExportChallenges } from "warframe-public-export-plus";
export const getPastWeeklyChallengesController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const inventory = await getInventory(accountId, "SeasonChallengeHistory ChallengeProgress");
const worldState = getWorldState(undefined);
if (worldState.SeasonInfo) {
const pools = getSeasonChallengePools(worldState.SeasonInfo.AffiliationTag);
const nightwaveStartTimestamp = Number(worldState.SeasonInfo.Activation.$date.$numberLong);
const nightwaveSeason = worldState.SeasonInfo.Season;
const timeMs = worldState.Time * 1000;
const completedChallengesIds = new Set<string>();
inventory.SeasonChallengeHistory.forEach(challengeHistory => {
const entryNightwaveSeason = parseInt(challengeHistory.id.slice(0, 4), 10) - 1;
if (nightwaveSeason == entryNightwaveSeason) {
const meta = Object.entries(ExportChallenges).find(
([key]) => key.split("/").pop() === challengeHistory.challenge
);
if (meta) {
const [, challengeMeta] = meta;
const challengeProgress = inventory.ChallengeProgress.find(
c => c.Name === challengeHistory.challenge
);
if (challengeProgress && challengeProgress.Progress >= (challengeMeta.requiredCount ?? 1)) {
completedChallengesIds.add(challengeHistory.id);
}
}
}
});
const PastWeeklyChallenges: ISeasonChallenge[] = [];
let week = Math.trunc((timeMs - EPOCH) / unixTimesInMs.week) - 1;
while (EPOCH + week * unixTimesInMs.week >= nightwaveStartTimestamp && PastWeeklyChallenges.length < 3) {
const tempActs: ISeasonChallenge[] = [];
pushWeeklyActs(tempActs, pools, week, nightwaveStartTimestamp, nightwaveSeason);
for (const act of tempActs) {
if (!completedChallengesIds.has(act._id.$oid) && PastWeeklyChallenges.length < 3) {
if (act.Challenge.startsWith("/Lotus/Types/Challenges/Seasons/Weekly/SeasonWeeklyPermanent")) {
act.Permanent = true;
}
PastWeeklyChallenges.push(act);
}
}
week--;
}
res.json({ PastWeeklyChallenges: PastWeeklyChallenges });
}
};

View File

@ -3,9 +3,10 @@ import { config } from "@/src/services/configService";
import allShipFeatures from "@/static/fixed_responses/allShipFeatures.json";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { createGarden, getPersonalRooms } from "@/src/services/personalRoomsService";
import { IGetShipResponse, IPersonalRoomsClient } from "@/src/types/personalRoomsTypes";
import { getLoadout } from "@/src/services/loadoutService";
import { toOid } from "@/src/helpers/inventoryHelpers";
import { IGetShipResponse } from "@/src/types/shipTypes";
import { IPersonalRoomsClient } from "@/src/types/personalRoomsTypes";
import { getLoadout } from "@/src/services/loadoutService";
export const getShipController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
@ -25,7 +26,15 @@ export const getShipController: RequestHandler = async (req, res) => {
LoadOutInventory: { LoadOutPresets: loadout.toJSON() },
Ship: {
...personalRooms.Ship,
ShipId: toOid(personalRoomsDb.activeShipId)
ShipId: toOid(personalRoomsDb.activeShipId),
ShipInterior: {
Colors: personalRooms.ShipInteriorColors,
ShipAttachments: { HOOD_ORNAMENT: "" },
SkinFlavourItem: ""
},
FavouriteLoadoutId: personalRooms.Ship.FavouriteLoadoutId
? toOid(personalRooms.Ship.FavouriteLoadoutId)
: undefined
},
Apartment: personalRooms.Apartment,
TailorShop: personalRooms.TailorShop

View File

@ -1,13 +1,11 @@
import { RequestHandler } from "express";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { sendWsBroadcastTo } from "@/src/services/wsService";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { addMiscItems, getInventory } from "@/src/services/inventoryService";
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
import { ArtifactPolarity } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { ArtifactPolarity, EquipmentFeatures, IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { ExportRecipes } from "warframe-public-export-plus";
import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { EquipmentFeatures, IEquipmentClient } from "@/src/types/equipmentTypes";
interface IGildWeaponRequest {
ItemName: string;
@ -74,5 +72,4 @@ export const gildWeaponController: RequestHandler = async (req, res) => {
InventoryChanges: inventoryChanges,
AffiliationMods: affiliationMods
});
sendWsBroadcastTo(accountId, { update_inventory: true });
};

View File

@ -1,8 +1,7 @@
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { addLoreFragmentScans, addShipDecorations, getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { ITypeCount } from "@/src/types/commonTypes";
import { ILoreFragmentScan } from "@/src/types/inventoryTypes/inventoryTypes";
import { ILoreFragmentScan, ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
import { RequestHandler } from "express";
export const giveShipDecoAndLoreFragmentController: RequestHandler = async (req, res) => {

View File

@ -12,7 +12,7 @@ export const hubBlessingController: RequestHandler = async (req, res) => {
if (req.query.mode == "send") {
const inventory = await getInventory(accountId, "BlessingCooldown Boosters");
inventory.BlessingCooldown = new Date(Date.now() + 86400000);
addBooster(boosterType, 3 * 3600, inventory); // unfaithful, but current HUB server does not handle broadcasting, so this way users can bless themselves.
addBooster(boosterType, 3 * 3600, inventory);
await inventory.save();
let token = "";

View File

@ -13,8 +13,7 @@ import {
addItems,
combineInventoryChanges,
getEffectiveAvatarImageType,
getInventory,
updateCurrency
getInventory
} from "@/src/services/inventoryService";
import { logger } from "@/src/utils/logger";
import { ExportFlavour } from "warframe-public-export-plus";
@ -101,9 +100,6 @@ export const inboxController: RequestHandler = async (req, res) => {
}
}
}
if (message.RegularCredits) {
updateCurrency(inventory, -message.RegularCredits, false, inventoryChanges);
}
await inventory.save();
res.json({ InventoryChanges: inventoryChanges });
} else if (latestClientMessageId) {

View File

@ -15,6 +15,7 @@ import { getRecipe } from "@/src/services/itemDataService";
import { toMongoDate, version_compare } from "@/src/helpers/inventoryHelpers";
import { logger } from "@/src/utils/logger";
import { colorToShard } from "@/src/helpers/shardHelper";
import { config } from "@/src/services/configService";
import {
addInfestedFoundryXP,
applyCheatsToInfestedFoundry,
@ -72,7 +73,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
addMiscItems(inventory, miscItemChanges);
// consume resources
if (!inventory.infiniteHelminthMaterials) {
if (!config.infiniteHelminthMaterials) {
let type: string;
let count: number;
if (account.BuildLabel && version_compare(account.BuildLabel, "2025.05.20.10.18") < 0) {
@ -98,7 +99,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
await inventory.save();
const infestedFoundry = inventory.toJSON<IInventoryClient>().InfestedFoundry!;
applyCheatsToInfestedFoundry(inventory, infestedFoundry);
applyCheatsToInfestedFoundry(infestedFoundry);
res.json({
InventoryChanges: {
MiscItems: miscItemChanges,
@ -128,14 +129,13 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
case "c": {
// consume items
const inventory = await getInventory(account._id.toString());
if (inventory.infiniteHelminthMaterials) {
if (config.infiniteHelminthMaterials) {
res.status(400).end();
return;
}
const request = getJSONfromString<IHelminthFeedRequest>(String(req.body));
const inventory = await getInventory(account._id.toString());
inventory.InfestedFoundry ??= {};
inventory.InfestedFoundry.Resources ??= [];
@ -240,7 +240,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
}
await inventory.save();
const infestedFoundry = inventory.toJSON<IInventoryClient>().InfestedFoundry!;
applyCheatsToInfestedFoundry(inventory, infestedFoundry);
applyCheatsToInfestedFoundry(infestedFoundry);
res.json({
InventoryChanges: {
InfestedFoundry: infestedFoundry
@ -254,7 +254,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
const request = getJSONfromString<IHelminthSubsumeRequest>(String(req.body));
const inventory = await getInventory(account._id.toString());
const recipe = getRecipe(request.Recipe)!;
if (!inventory.infiniteHelminthMaterials) {
if (!config.infiniteHelminthMaterials) {
for (const ingredient of recipe.secretIngredients!) {
const resource = inventory.InfestedFoundry!.Resources!.find(x => x.ItemType == ingredient.ItemType);
if (resource) {
@ -280,7 +280,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
freeUpSlot(inventory, InventorySlot.SUITS);
await inventory.save();
const infestedFoundry = inventory.toJSON<IInventoryClient>().InfestedFoundry!;
applyCheatsToInfestedFoundry(inventory, infestedFoundry);
applyCheatsToInfestedFoundry(infestedFoundry);
res.json({
InventoryChanges: {
Recipes: recipeChanges,
@ -307,7 +307,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
const recipeChanges = handleSubsumeCompletion(inventory);
await inventory.save();
const infestedFoundry = inventory.toJSON<IInventoryClient>().InfestedFoundry!;
applyCheatsToInfestedFoundry(inventory, infestedFoundry);
applyCheatsToInfestedFoundry(infestedFoundry);
res.json({
InventoryChanges: {
...currencyChanges,
@ -328,7 +328,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
suit.UpgradesExpiry = upgradesExpiry;
const recipeChanges = addInfestedFoundryXP(inventory.InfestedFoundry!, 4800_00);
addRecipes(inventory, recipeChanges);
if (!inventory.infiniteHelminthMaterials) {
if (!config.infiniteHelminthMaterials) {
for (let i = 0; i != request.ResourceTypes.length; ++i) {
inventory.InfestedFoundry!.Resources!.find(x => x.ItemType == request.ResourceTypes[i])!.Count -=
request.ResourceCosts[i];
@ -338,7 +338,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
inventory.InfestedFoundry!.InvigorationsApplied += 1;
await inventory.save();
const infestedFoundry = inventory.toJSON<IInventoryClient>().InfestedFoundry!;
applyCheatsToInfestedFoundry(inventory, infestedFoundry);
applyCheatsToInfestedFoundry(infestedFoundry);
res.json({
SuitId: request.SuitId,
OffensiveUpgrade: request.OffensiveUpgradeType,

View File

@ -5,24 +5,16 @@ import { config } from "@/src/services/configService";
import allDialogue from "@/static/fixed_responses/allDialogue.json";
import { ILoadoutDatabase } from "@/src/types/saveLoadoutTypes";
import { IInventoryClient, IShipInventory, equipmentKeys } from "@/src/types/inventoryTypes/inventoryTypes";
import { IPolarity, ArtifactPolarity } from "@/src/types/inventoryTypes/commonInventoryTypes";
import {
eFaction,
ExportCustoms,
ExportFlavour,
ExportResources,
ExportVirtuals,
ICountedItem
} from "warframe-public-export-plus";
import { IPolarity, ArtifactPolarity, EquipmentFeatures } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { ExportCustoms, ExportFlavour, ExportResources, ExportVirtuals } from "warframe-public-export-plus";
import { applyCheatsToInfestedFoundry, handleSubsumeCompletion } from "@/src/services/infestedFoundryService";
import {
addEmailItem,
addItem,
addMiscItems,
allDailyAffiliationKeys,
checkCalendarAutoAdvance,
cleanupInventory,
createLibraryDailyTask,
generateRewardSeed,
getCalendarProgress
} from "@/src/services/inventoryService";
import { logger } from "@/src/utils/logger";
@ -36,10 +28,6 @@ import { toLegacyOid, toOid, version_compare } from "@/src/helpers/inventoryHelp
import { Inbox } from "@/src/models/inboxModel";
import { unixTimesInMs } from "@/src/constants/timeConstants";
import { DailyDeal } from "@/src/models/worldStateModel";
import { EquipmentFeatures } from "@/src/types/equipmentTypes";
import { generateRewardSeed } from "@/src/services/rngService";
import { getInvasionByOid, getWorldState } from "@/src/services/worldStateService";
import { createMessage } from "@/src/services/inboxService";
export const inventoryController: RequestHandler = async (request, response) => {
const account = await getAccountForRequest(request);
@ -122,61 +110,58 @@ export const inventoryController: RequestHandler = async (request, response) =>
}
}
// TODO: Setup CalendarProgress as part of 1999 mission completion?
if (inventory.CalendarProgress) {
const previousYearIteration = inventory.CalendarProgress.Iteration;
getCalendarProgress(inventory); // handle year rollover; the client expects to receive an inventory with an up-to-date CalendarProgress
const previousYearIteration = inventory.CalendarProgress?.Iteration;
// We need to do the following to ensure the in-game calendar does not break:
getCalendarProgress(inventory); // Keep the CalendarProgress up-to-date (at least for the current year iteration) (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/2364)
checkCalendarAutoAdvance(inventory, getWorldState().KnownCalendarSeasons[0]); // Skip birthday events for characters if we do not have them unlocked yet (https://onlyg.it/OpenWF/SpaceNinjaServer/issues/2424)
// also handle sending of kiss cinematic at year rollover
if (
inventory.CalendarProgress!.Iteration != previousYearIteration &&
inventory.DialogueHistory &&
inventory.DialogueHistory.Dialogues
) {
let kalymos = false;
for (const { dialogueName, kissEmail } of [
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/ArthurDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/ArthurKissEmailItem"
},
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/EleanorDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/EleanorKissEmailItem"
},
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/LettieDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/LettieKissEmailItem"
},
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/JabirDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/AmirKissEmailItem"
},
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/AoiDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/AoiKissEmailItem"
},
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/QuincyDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/QuincyKissEmailItem"
}
]) {
const dialogue = inventory.DialogueHistory.Dialogues.find(x => x.DialogueName == dialogueName);
if (dialogue) {
if (dialogue.Rank == 7) {
await addEmailItem(inventory, kissEmail);
kalymos = false;
break;
// also handle sending of kiss cinematic at year rollover
if (
inventory.CalendarProgress.Iteration != previousYearIteration &&
inventory.DialogueHistory &&
inventory.DialogueHistory.Dialogues
) {
let kalymos = false;
for (const { dialogueName, kissEmail } of [
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/ArthurDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/ArthurKissEmailItem"
},
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/EleanorDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/EleanorKissEmailItem"
},
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/LettieDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/LettieKissEmailItem"
},
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/JabirDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/AmirKissEmailItem"
},
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/AoiDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/AoiKissEmailItem"
},
{
dialogueName: "/Lotus/Types/Gameplay/1999Wf/Dialogue/QuincyDialogue_rom.dialogue",
kissEmail: "/Lotus/Types/Items/EmailItems/QuincyKissEmailItem"
}
if (dialogue.Rank == 6) {
kalymos = true;
]) {
const dialogue = inventory.DialogueHistory.Dialogues.find(x => x.DialogueName == dialogueName);
if (dialogue) {
if (dialogue.Rank == 7) {
await addEmailItem(inventory, kissEmail);
kalymos = false;
break;
}
if (dialogue.Rank == 6) {
kalymos = true;
}
}
}
}
if (kalymos) {
await addEmailItem(inventory, "/Lotus/Types/Items/EmailItems/KalymosKissEmailItem");
if (kalymos) {
await addEmailItem(inventory, "/Lotus/Types/Items/EmailItems/KalymosKissEmailItem");
}
}
}
@ -195,63 +180,6 @@ export const inventoryController: RequestHandler = async (request, response) =>
//await inventory.save();
}
for (let i = 0; i != inventory.QualifyingInvasions.length; ) {
const qi = inventory.QualifyingInvasions[i];
const invasion = getInvasionByOid(qi.invasionId.toString());
if (!invasion) {
logger.debug(`removing QualifyingInvasions entry for unknown invasion: ${qi.invasionId.toString()}`);
inventory.QualifyingInvasions.splice(i, 1);
continue;
}
if (invasion.Completed) {
let factionSidedWith: string | undefined;
let battlePay: ICountedItem[] | undefined;
if (qi.AttackerScore >= 3) {
factionSidedWith = invasion.Faction;
battlePay = invasion.AttackerReward.countedItems;
logger.debug(`invasion pay from ${factionSidedWith}`, { battlePay });
} else if (qi.DefenderScore >= 3) {
factionSidedWith = invasion.DefenderFaction;
battlePay = invasion.DefenderReward.countedItems;
logger.debug(`invasion pay from ${factionSidedWith}`, { battlePay });
}
if (factionSidedWith) {
if (battlePay) {
// Decoupling rewards from the inbox message because it may delete itself without being read
for (const item of battlePay) {
await addItem(inventory, item.ItemType, item.ItemCount);
}
await createMessage(account._id, [
{
sndr: eFaction.find(x => x.tag == factionSidedWith)?.name ?? factionSidedWith, // TOVERIFY
msg: `/Lotus/Language/G1Quests/${factionSidedWith}_InvasionThankyouMessageBody`,
sub: `/Lotus/Language/G1Quests/${factionSidedWith}_InvasionThankyouMessageSubject`,
countedAtt: battlePay,
attVisualOnly: true,
icon:
factionSidedWith == "FC_GRINEER"
? "/Lotus/Interface/Icons/Npcs/EliteRifleLancerAvatar.png" // Source: https://www.reddit.com/r/Warframe/comments/1aj4usx/battle_pay_worth_10_plat/, https://www.youtube.com/watch?v=XhNZ6ai6BOY
: "/Lotus/Interface/Icons/Npcs/CrewmanNormal.png", // My best source for this is https://www.youtube.com/watch?v=rxrCCFm73XE around 1:37
// TOVERIFY: highPriority?
endDate: new Date(Date.now() + 86400_000) // TOVERIFY: This type of inbox message seems to automatically delete itself. We'll just delete it after 24 hours, but it's not clear if this is correct.
}
]);
}
if (invasion.Faction != "FC_INFESTATION") {
// Sided with grineer -> opposed corpus -> send zanuka (harvester)
// Sided with corpus -> opposed grineer -> send g3 (death squad)
inventory[factionSidedWith != "FC_GRINEER" ? "DeathSquadable" : "Harvestable"] = true;
// TOVERIFY: Should this happen earlier?
// TOVERIFY: Should this send an (ephemeral) email?
}
}
logger.debug(`removing QualifyingInvasions entry for completed invasion: ${qi.invasionId.toString()}`);
inventory.QualifyingInvasions.splice(i, 1);
continue;
}
++i;
}
if (inventory.LastInventorySync) {
const lastSyncDuviriMood = Math.trunc(inventory.LastInventorySync.getTimestamp().getTime() / 7200000);
const currentDuviriMood = Math.trunc(Date.now() / 7200000);
@ -295,17 +223,17 @@ export const getInventoryResponse = async (
};
}
if (inventory.infiniteCredits) {
if (config.infiniteCredits) {
inventoryResponse.RegularCredits = 999999999;
}
if (inventory.infinitePlatinum) {
if (config.infinitePlatinum) {
inventoryResponse.PremiumCreditsFree = 0;
inventoryResponse.PremiumCredits = 999999999;
}
if (inventory.infiniteEndo) {
if (config.infiniteEndo) {
inventoryResponse.FusionPoints = 999999999;
}
if (inventory.infiniteRegalAya) {
if (config.infiniteRegalAya) {
inventoryResponse.PrimeTokens = 999999999;
}
@ -335,17 +263,6 @@ export const getInventoryResponse = async (
for (const uniqueName in ExportFlavour) {
inventoryResponse.FlavourItems.push({ ItemType: uniqueName });
}
} else if (config.worldState?.baroTennoConRelay) {
[
"/Lotus/Types/Items/Events/TennoConRelay2022EarlyAccess",
"/Lotus/Types/Items/Events/TennoConRelay2023EarlyAccess",
"/Lotus/Types/Items/Events/TennoConRelay2024EarlyAccess",
"/Lotus/Types/Items/Events/TennoConRelay2025EarlyAccess"
].forEach(uniqueName => {
if (!inventoryResponse.FlavourItems.some(x => x.ItemType == uniqueName)) {
inventoryResponse.FlavourItems.push({ ItemType: uniqueName });
}
});
}
if (config.unlockAllSkins) {
@ -450,7 +367,7 @@ export const getInventoryResponse = async (
}
if (inventoryResponse.InfestedFoundry) {
applyCheatsToInfestedFoundry(inventory, inventoryResponse.InfestedFoundry);
applyCheatsToInfestedFoundry(inventoryResponse.InfestedFoundry);
}
// Set 2FA enabled so trading post can be used

View File

@ -1,8 +1,9 @@
import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory, updateCurrency, updateSlots } from "@/src/services/inventoryService";
import { getInventory, updateCurrency } from "@/src/services/inventoryService";
import { RequestHandler } from "express";
import { updateSlots } from "@/src/services/inventoryService";
import { InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
import { exhaustive } from "@/src/utils/ts-utils";
import { logger } from "@/src/utils/logger";
/*
loadout slots are additionally purchased slots only
@ -22,44 +23,13 @@ export const inventorySlotsController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const body = JSON.parse(req.body as string) as IInventorySlotsRequest;
let price;
let amount;
switch (body.Bin) {
case InventorySlot.SUITS:
case InventorySlot.MECHSUITS:
case InventorySlot.PVE_LOADOUTS:
case InventorySlot.CREWMEMBERS:
price = 20;
amount = 1;
break;
case InventorySlot.SPACESUITS:
price = 12;
amount = 1;
break;
case InventorySlot.WEAPONS:
case InventorySlot.SPACEWEAPONS:
case InventorySlot.SENTINELS:
case InventorySlot.RJ_COMPONENT_AND_ARMAMENTS:
case InventorySlot.AMPS:
price = 12;
amount = 2;
break;
case InventorySlot.RIVENS:
price = 60;
amount = 3;
break;
default:
exhaustive(body.Bin);
throw new Error(`unexpected slot purchase of type ${body.Bin as string}`);
if (body.Bin != InventorySlot.SUITS && body.Bin != InventorySlot.PVE_LOADOUTS) {
logger.warn(`unexpected slot purchase of type ${body.Bin}, account may be overcharged`);
}
const inventory = await getInventory(accountId);
const currencyChanges = updateCurrency(inventory, price, true);
updateSlots(inventory, body.Bin, amount, amount);
const currencyChanges = updateCurrency(inventory, 20, true);
updateSlots(inventory, body.Bin, 1, 1);
await inventory.save();
res.json({ InventoryChanges: currencyChanges });

View File

@ -8,7 +8,7 @@ import { createAccount, createNonce, getUsernameFromEmail, isCorrectPassword } f
import { IDatabaseAccountJson, ILoginRequest, ILoginResponse } from "@/src/types/loginTypes";
import { logger } from "@/src/utils/logger";
import { version_compare } from "@/src/helpers/inventoryHelpers";
import { sendWsBroadcastTo } from "@/src/services/wsService";
import { sendWsBroadcastTo } from "@/src/services/webService";
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
@ -130,7 +130,7 @@ const createLoginResponse = (
resp.Groups = [];
}
if (version_compare(buildLabel, "2021.04.13.19.58") >= 0) {
resp.DTLS = 0; // bit 0 enables DTLS. if enabled, additional bits can be set, e.g. bit 2 to enable logging. on live, the value is 99.
resp.DTLS = 99;
}
if (version_compare(buildLabel, "2022.04.29.12.53") >= 0) {
resp.ClientType = account.ClientType;

View File

@ -9,7 +9,7 @@ import {
} from "@/src/services/loginRewardService";
import { getInventory } from "@/src/services/inventoryService";
import { config } from "@/src/services/configService";
import { sendWsBroadcastTo } from "@/src/services/wsService";
import { sendWsBroadcastTo } from "@/src/services/webService";
export const loginRewardsController: RequestHandler = async (req, res) => {
const account = await getAccountForRequest(req);

View File

@ -6,7 +6,7 @@ import {
} from "@/src/services/loginRewardService";
import { getAccountForRequest } from "@/src/services/loginService";
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
import { sendWsBroadcastTo } from "@/src/services/wsService";
import { sendWsBroadcastTo } from "@/src/services/webService";
import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { logger } from "@/src/utils/logger";
import { RequestHandler } from "express";

View File

@ -1,6 +1,6 @@
import { RequestHandler } from "express";
import { Account } from "@/src/models/loginModel";
import { sendWsBroadcastTo } from "@/src/services/wsService";
import { sendWsBroadcastTo } from "@/src/services/webService";
export const logoutController: RequestHandler = async (req, res) => {
if (!req.query.accountId) {

View File

@ -3,16 +3,11 @@ import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { getAccountForRequest } from "@/src/services/loginService";
import { IMissionInventoryUpdateRequest } from "@/src/types/requestTypes";
import { addMissionInventoryUpdates, addMissionRewards } from "@/src/services/missionInventoryUpdateService";
import { getInventory } from "@/src/services/inventoryService";
import { getInventoryResponse } from "@/src/controllers/api/inventoryController";
import { generateRewardSeed, getInventory } from "@/src/services/inventoryService";
import { getInventoryResponse } from "./inventoryController";
import { logger } from "@/src/utils/logger";
import {
IMissionInventoryUpdateResponse,
IMissionInventoryUpdateResponseBackToDryDock,
IMissionInventoryUpdateResponseRailjackInterstitial
} from "@/src/types/missionTypes";
import { sendWsBroadcastTo } from "@/src/services/wsService";
import { generateRewardSeed } from "@/src/services/rngService";
import { IMissionInventoryUpdateResponse } from "@/src/types/missionTypes";
import { sendWsBroadcastTo } from "@/src/services/webService";
/*
**** INPUT ****
@ -99,9 +94,11 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
inventory.RewardSeed = generateRewardSeed();
}
await inventory.save();
const inventoryResponse = await getInventoryResponse(inventory, true, account.BuildLabel);
//TODO: figure out when to send inventory. it is needed for many cases.
const deltas: IMissionInventoryUpdateResponseRailjackInterstitial = {
res.json({
InventoryJson: JSON.stringify(inventoryResponse),
InventoryChanges: inventoryChanges,
MissionRewards,
...credits,
@ -110,25 +107,7 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
SyndicateXPItemReward,
AffiliationMods,
ConquestCompletedMissionsCount
};
if (missionReport.RJ) {
logger.debug(`railjack interstitial request, sending only deltas`, deltas);
res.json(deltas);
} else if (missionReport.RewardInfo) {
logger.debug(`classic mission completion, sending everything`);
const inventoryResponse = await getInventoryResponse(inventory, true, account.BuildLabel);
res.json({
InventoryJson: JSON.stringify(inventoryResponse),
...deltas
} satisfies IMissionInventoryUpdateResponse);
} else {
logger.debug(`no reward info, assuming this wasn't a mission completion and we should just sync inventory`);
const inventoryResponse = await getInventoryResponse(inventory, true, account.BuildLabel);
res.json({
InventoryJson: JSON.stringify(inventoryResponse)
} satisfies IMissionInventoryUpdateResponseBackToDryDock);
}
} satisfies IMissionInventoryUpdateResponse);
sendWsBroadcastTo(account._id.toString(), { update_inventory: true });
};

View File

@ -1,6 +1,5 @@
import { RequestHandler } from "express";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { sendWsBroadcastTo } from "@/src/services/wsService";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import {
getInventory,
@ -16,9 +15,10 @@ import {
import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { getDefaultUpgrades } from "@/src/services/itemDataService";
import { modularWeaponTypes } from "@/src/helpers/modularWeaponHelper";
import { IEquipmentDatabase } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { getRandomInt } from "@/src/services/rngService";
import { ExportSentinels, ExportWeapons, IDefaultUpgrade } from "warframe-public-export-plus";
import { IEquipmentDatabase, Status } from "@/src/types/equipmentTypes";
import { Status } from "@/src/types/inventoryTypes/inventoryTypes";
interface IModularCraftRequest {
WeaponType: string;
@ -195,5 +195,4 @@ export const modularWeaponCraftingController: RequestHandler = async (req, res)
MiscItems: miscItemChanges
}
});
sendWsBroadcastTo(accountId, { update_inventory: true });
};

View File

@ -3,7 +3,7 @@ import { ExportWeapons } from "warframe-public-export-plus";
import { IMongoDate } from "@/src/types/commonTypes";
import { toMongoDate } from "@/src/helpers/inventoryHelpers";
import { SRng } from "@/src/services/rngService";
import { ArtifactPolarity } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { ArtifactPolarity, EquipmentFeatures } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import {
addEquipment,
@ -15,10 +15,8 @@ import {
} from "@/src/services/inventoryService";
import { getDefaultUpgrades } from "@/src/services/itemDataService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { sendWsBroadcastTo } from "@/src/services/wsService";
import { modularWeaponTypes } from "@/src/helpers/modularWeaponHelper";
import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { EquipmentFeatures } from "@/src/types/equipmentTypes";
export const modularWeaponSaleController: RequestHandler = async (req, res) => {
const partTypeToParts: Record<string, string[]> = {};
@ -69,7 +67,6 @@ export const modularWeaponSaleController: RequestHandler = async (req, res) => {
res.json({
InventoryChanges: inventoryChanges
});
sendWsBroadcastTo(accountId, { update_inventory: true });
} else {
throw new Error(`unknown modularWeaponSale op: ${String(req.query.op)}`);
}

View File

@ -3,7 +3,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory, updateCurrency } from "@/src/services/inventoryService";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
import { sendWsBroadcastTo } from "@/src/services/wsService";
import { sendWsBroadcastTo } from "@/src/services/webService";
interface INameWeaponRequest {
ItemName: string;

View File

@ -1,6 +1,7 @@
import { version_compare } from "@/src/helpers/inventoryHelpers";
import {
antivirusMods,
consumeModCharge,
decodeNemesisGuess,
encodeNemesisGuess,
getInfNodes,
@ -16,13 +17,12 @@ import {
parseUpgrade
} from "@/src/helpers/nemesisHelpers";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
import { addMods, freeUpSlot, getInventory } from "@/src/services/inventoryService";
import { freeUpSlot, getInventory } from "@/src/services/inventoryService";
import { getAccountForRequest } from "@/src/services/loginService";
import { SRng } from "@/src/services/rngService";
import { IMongoDate, IOid } from "@/src/types/commonTypes";
import { IEquipmentClient } from "@/src/types/equipmentTypes";
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
import {
IInnateDamageFingerprint,
IInventoryClient,
@ -36,7 +36,6 @@ import {
} from "@/src/types/inventoryTypes/inventoryTypes";
import { logger } from "@/src/utils/logger";
import { RequestHandler } from "express";
import { Types } from "mongoose";
export const nemesisController: RequestHandler = async (req, res) => {
const account = await getAccountForRequest(req);
@ -392,54 +391,3 @@ interface IKnife {
AttachedUpgrades: IUpgradeClient[];
HiddenWhenHolstered: boolean;
}
const consumeModCharge = (
response: IKnifeResponse,
inventory: TInventoryDatabaseDocument,
upgrade: { ItemId: IOid; ItemType: string },
dataknifeUpgrades: string[]
): void => {
response.UpgradeIds ??= [];
response.UpgradeTypes ??= [];
response.UpgradeFingerprints ??= [];
response.UpgradeNew ??= [];
response.HasKnife = true;
if (upgrade.ItemId.$oid != "000000000000000000000000") {
const dbUpgrade = inventory.Upgrades.id(upgrade.ItemId.$oid)!;
const fingerprint = JSON.parse(dbUpgrade.UpgradeFingerprint!) as { lvl: number };
fingerprint.lvl += 1;
dbUpgrade.UpgradeFingerprint = JSON.stringify(fingerprint);
response.UpgradeIds.push(upgrade.ItemId.$oid);
response.UpgradeTypes.push(upgrade.ItemType);
response.UpgradeFingerprints.push(fingerprint);
response.UpgradeNew.push(false);
} else {
const id = new Types.ObjectId();
inventory.Upgrades.push({
_id: id,
ItemType: upgrade.ItemType,
UpgradeFingerprint: `{"lvl":1}`
});
addMods(inventory, [
{
ItemType: upgrade.ItemType,
ItemCount: -1
}
]);
const dataknifeRawUpgradeIndex = dataknifeUpgrades.indexOf(upgrade.ItemType);
if (dataknifeRawUpgradeIndex != -1) {
dataknifeUpgrades[dataknifeRawUpgradeIndex] = id.toString();
} else {
logger.warn(`${upgrade.ItemType} not found in dataknife config`);
}
response.UpgradeIds.push(id.toString());
response.UpgradeTypes.push(upgrade.ItemType);
response.UpgradeFingerprints.push({ lvl: 1 });
response.UpgradeNew.push(true);
}
};

View File

@ -1,52 +1,25 @@
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { addConsumables, getInventory } from "@/src/services/inventoryService";
import { getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { IPlayerSkills } from "@/src/types/inventoryTypes/inventoryTypes";
import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { RequestHandler } from "express";
export const playerSkillsController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const inventory = await getInventory(accountId, "PlayerSkills Consumables");
const inventory = await getInventory(accountId, "PlayerSkills");
const request = getJSONfromString<IPlayerSkillsRequest>(String(req.body));
const oldRank: number = inventory.PlayerSkills[request.Skill as keyof IPlayerSkills];
const cost = (request.Pool == "LPP_DRIFTER" ? drifterCosts[oldRank] : 1 << oldRank) * 1000;
inventory.PlayerSkills[request.Pool as keyof IPlayerSkills] -= cost;
inventory.PlayerSkills[request.Skill as keyof IPlayerSkills]++;
const inventoryChanges: IInventoryChanges = {};
if (request.Skill == "LPS_COMMAND") {
if (inventory.PlayerSkills.LPS_COMMAND == 9) {
const consumablesChanges = [
{
ItemType: "/Lotus/Types/Restoratives/Consumable/CrewmateBall",
ItemCount: 1
}
];
addConsumables(inventory, consumablesChanges);
inventoryChanges.Consumables = consumablesChanges;
}
} else if (request.Skill == "LPS_DRIFT_RIDING") {
if (inventory.PlayerSkills.LPS_DRIFT_RIDING == 9) {
const consumablesChanges = [
{
ItemType: "/Lotus/Types/Restoratives/ErsatzSummon",
ItemCount: 1
}
];
addConsumables(inventory, consumablesChanges);
inventoryChanges.Consumables = consumablesChanges;
}
}
await inventory.save();
res.json({
Pool: request.Pool,
PoolInc: -cost,
Skill: request.Skill,
Rank: oldRank + 1,
InventoryChanges: inventoryChanges
Rank: oldRank + 1
});
};

View File

@ -11,7 +11,7 @@ export const projectionManagerController: RequestHandler = async (req, res) => {
const [era, category, currentQuality] = parseProjection(request.projectionType);
const upgradeCost = config.dontSubtractVoidTraces
? 0
: qualityNumberToCost[request.qualityTag] - qualityNumberToCost[qualityKeywordToNumber[currentQuality]];
: (request.qualityTag - qualityKeywordToNumber[currentQuality]) * 25;
const newProjectionType = findProjection(era, category, qualityNumberToKeyword[request.qualityTag]);
addMiscItems(inventory, [
{
@ -49,7 +49,6 @@ const qualityKeywordToNumber: Record<VoidProjectionQuality, number> = {
VPQ_GOLD: 2,
VPQ_PLATINUM: 3
};
const qualityNumberToCost = [0, 25, 50, 100];
// e.g. "/Lotus/Types/Game/Projections/T2VoidProjectionProteaPrimeDBronze" -> ["Lith", "W5", "VPQ_BRONZE"]
const parseProjection = (typeName: string): [string, string, VoidProjectionQuality] => {

View File

@ -3,7 +3,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
import { IPurchaseRequest } from "@/src/types/purchaseTypes";
import { handlePurchase } from "@/src/services/purchaseService";
import { getInventory } from "@/src/services/inventoryService";
import { sendWsBroadcastTo } from "@/src/services/wsService";
import { sendWsBroadcastTo } from "@/src/services/webService";
export const purchaseController: RequestHandler = async (req, res) => {
const purchaseRequest = JSON.parse(String(req.body)) as IPurchaseRequest;

View File

@ -1,7 +1,6 @@
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { getInventory, updateCurrency } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { sendWsBroadcastTo } from "@/src/services/wsService";
import { RequestHandler } from "express";
export const releasePetController: RequestHandler = async (req, res) => {
@ -20,7 +19,6 @@ export const releasePetController: RequestHandler = async (req, res) => {
await inventory.save();
res.json({ inventoryChanges }); // Not a mistake; it's "inventoryChanges" here.
sendWsBroadcastTo(accountId, { update_inventory: true });
};
interface IReleasePetRequest {

View File

@ -1,7 +1,7 @@
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { getInventory, updateCurrency } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { sendWsBroadcastTo } from "@/src/services/wsService";
import { sendWsBroadcastTo } from "@/src/services/webService";
import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { RequestHandler } from "express";

View File

@ -1,5 +0,0 @@
import { RequestHandler } from "express";
export const resetQuestProgressController: RequestHandler = (_req, res) => {
res.send("1").end();
};

View File

@ -1,7 +1,7 @@
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { Status } from "@/src/types/equipmentTypes";
import { Status } from "@/src/types/inventoryTypes/inventoryTypes";
import { RequestHandler } from "express";
export const retrievePetFromStasisController: RequestHandler = async (req, res) => {

View File

@ -2,7 +2,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { getInventory } from "@/src/services/inventoryService";
import { RequestHandler } from "express";
import { ISettings } from "@/src/types/inventoryTypes/inventoryTypes";
import { ISettings } from "../../types/inventoryTypes/inventoryTypes";
interface ISaveSettingsRequest {
Settings: ISettings;

View File

@ -9,16 +9,13 @@ import {
freeUpSlot,
combineInventoryChanges,
addCrewShipRawSalvage,
addFusionPoints,
addCrewShipFusionPoints,
addFusionTreasures
addFusionPoints
} from "@/src/services/inventoryService";
import { InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
import { ExportDojoRecipes } from "warframe-public-export-plus";
import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
import { sendWsBroadcastEx } from "@/src/services/wsService";
import { parseFusionTreasure } from "@/src/helpers/inventoryHelpers";
import { sendWsBroadcastTo } from "@/src/services/webService";
export const sellController: RequestHandler = async (req, res) => {
const payload = JSON.parse(String(req.body)) as ISellRequest;
@ -29,8 +26,6 @@ export const sellController: RequestHandler = async (req, res) => {
requiredFields.add("RegularCredits");
} else if (payload.SellCurrency == "SC_FusionPoints") {
requiredFields.add("FusionPoints");
} else if (payload.SellCurrency == "SC_CrewShipFusionPoints") {
requiredFields.add("CrewShipFusionPoints");
} else {
requiredFields.add("MiscItems");
}
@ -84,8 +79,6 @@ export const sellController: RequestHandler = async (req, res) => {
inventory.RegularCredits += payload.SellPrice;
} else if (payload.SellCurrency == "SC_FusionPoints") {
addFusionPoints(inventory, payload.SellPrice);
} else if (payload.SellCurrency == "SC_CrewShipFusionPoints") {
addCrewShipFusionPoints(inventory, payload.SellPrice);
} else if (payload.SellCurrency == "SC_PrimeBucks") {
addMiscItems(inventory, [
{
@ -297,17 +290,12 @@ export const sellController: RequestHandler = async (req, res) => {
]);
});
}
if (payload.Items.FusionTreasures) {
payload.Items.FusionTreasures.forEach(sellItem => {
addFusionTreasures(inventory, [parseFusionTreasure(sellItem.String, sellItem.Count * -1)]);
});
}
await inventory.save();
res.json({
inventoryChanges: inventoryChanges // "inventoryChanges" for this response instead of the usual "InventoryChanges"
});
sendWsBroadcastEx({ update_inventory: true }, accountId, parseInt(String(req.query.wsid)));
sendWsBroadcastTo(accountId, { update_inventory: true });
};
interface ISellRequest {
@ -334,7 +322,6 @@ interface ISellRequest {
CrewMembers?: ISellItem[];
CrewShipWeapons?: ISellItem[];
CrewShipWeaponSkins?: ISellItem[];
FusionTreasures?: ISellItem[];
};
SellPrice: number;
SellCurrency:
@ -343,8 +330,7 @@ interface ISellRequest {
| "SC_FusionPoints"
| "SC_DistillPoints"
| "SC_CrewShipFusionPoints"
| "SC_Resources"
| "somethingelsewemightnotknowabout";
| "SC_Resources";
buildLabel: string;
}

View File

@ -1,7 +1,7 @@
import { RequestHandler } from "express";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { getPersonalRooms } from "@/src/services/personalRoomsService";
import { TBootLocation } from "@/src/types/personalRoomsTypes";
import { TBootLocation } from "@/src/types/shipTypes";
import { getInventory } from "@/src/services/inventoryService";
export const setBootLocationController: RequestHandler = async (req, res) => {

View File

@ -1,5 +1,5 @@
import { getAccountIdForRequest } from "@/src/services/loginService";
import { IPictureFrameInfo, ISetPlacedDecoInfoRequest } from "@/src/types/personalRoomsTypes";
import { IPictureFrameInfo, ISetPlacedDecoInfoRequest } from "@/src/types/shipTypes";
import { RequestHandler } from "express";
import { handleSetPlacedDecoInfo } from "@/src/services/shipCustomizationsService";

View File

@ -1,6 +1,6 @@
import { getAccountIdForRequest } from "@/src/services/loginService";
import { setShipCustomizations } from "@/src/services/shipCustomizationsService";
import { ISetShipCustomizationsRequest } from "@/src/types/personalRoomsTypes";
import { ISetShipCustomizationsRequest } from "@/src/types/shipTypes";
import { logger } from "@/src/utils/logger";
import { RequestHandler } from "express";

View File

@ -3,7 +3,7 @@ import { RequestHandler } from "express";
import { getPersonalRooms } from "@/src/services/personalRoomsService";
import { IOid } from "@/src/types/commonTypes";
import { Types } from "mongoose";
import { IFavouriteLoadoutDatabase, TBootLocation } from "@/src/types/personalRoomsTypes";
import { IFavouriteLoadoutDatabase, TBootLocation } from "@/src/types/shipTypes";
export const setShipFavouriteLoadoutController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);

View File

@ -2,7 +2,7 @@ import { fromMongoDate, fromOid } from "@/src/helpers/inventoryHelpers";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { IEquipmentClient } from "@/src/types/equipmentTypes";
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { RequestHandler } from "express";
export const setSuitInfectionController: RequestHandler = async (req, res) => {

View File

@ -1,17 +1,20 @@
import { getAccountIdForRequest } from "@/src/services/loginService";
import { IShipDecorationsRequest, IResetShipDecorationsRequest } from "@/src/types/personalRoomsTypes";
import { IShipDecorationsRequest } from "@/src/types/shipTypes";
import { logger } from "@/src/utils/logger";
import { RequestHandler } from "express";
import { handleResetShipDecorations, handleSetShipDecorations } from "@/src/services/shipCustomizationsService";
import { handleSetShipDecorations } from "@/src/services/shipCustomizationsService";
export const shipDecorationsController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
if (req.query.reset == "1") {
const request = JSON.parse(req.body as string) as IResetShipDecorationsRequest;
const response = await handleResetShipDecorations(accountId, request);
res.send(response);
} else {
const shipDecorationsRequest = JSON.parse(req.body as string) as IShipDecorationsRequest;
const shipDecorationsRequest = JSON.parse(req.body as string) as IShipDecorationsRequest;
try {
const placedDecoration = await handleSetShipDecorations(accountId, shipDecorationsRequest);
res.send(placedDecoration);
} catch (error: unknown) {
if (error instanceof Error) {
logger.error(`error in shipDecorationsController: ${error.message}`);
res.status(400).json({ error: error.message });
}
}
};

View File

@ -6,7 +6,7 @@ import { IOid } from "@/src/types/commonTypes";
import { ExportSyndicates, ExportWeapons } from "warframe-public-export-plus";
import { logger } from "@/src/utils/logger";
import { IAffiliationMods, IInventoryChanges } from "@/src/types/purchaseTypes";
import { EquipmentFeatures } from "@/src/types/equipmentTypes";
import { EquipmentFeatures } from "@/src/types/inventoryTypes/commonInventoryTypes";
export const syndicateStandingBonusController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);

View File

@ -2,7 +2,7 @@ import { fromMongoDate, fromOid } from "@/src/helpers/inventoryHelpers";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { addMiscItem, getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { IEquipmentClient } from "@/src/types/equipmentTypes";
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { RequestHandler } from "express";
export const umbraController: RequestHandler = async (req, res) => {

View File

@ -10,7 +10,6 @@ import { logger } from "@/src/utils/logger";
export const updateChallengeProgressController: RequestHandler = async (req, res) => {
const challenges = getJSONfromString<IUpdateChallengeProgressRequest>(String(req.body));
const account = await getAccountForRequest(req);
logger.debug(`challenge report:`, challenges);
const inventory = await getInventory(
account._id.toString(),
@ -18,7 +17,7 @@ export const updateChallengeProgressController: RequestHandler = async (req, res
);
let affiliationMods: IAffiliationMods[] = [];
if (challenges.ChallengeProgress) {
affiliationMods = await addChallenges(
affiliationMods = addChallenges(
account,
inventory,
challenges.ChallengeProgress,

View File

@ -1,14 +1,19 @@
import { RequestHandler } from "express";
import { IUpgradesRequest } from "@/src/types/requestTypes";
import { ArtifactPolarity, IAbilityOverride } from "@/src/types/inventoryTypes/commonInventoryTypes";
import {
ArtifactPolarity,
IEquipmentDatabase,
EquipmentFeatures,
IAbilityOverride
} from "@/src/types/inventoryTypes/commonInventoryTypes";
import { IInventoryClient, IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { addMiscItems, addRecipes, getInventory, updateCurrency } from "@/src/services/inventoryService";
import { getRecipeByResult } from "@/src/services/itemDataService";
import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { addInfestedFoundryXP, applyCheatsToInfestedFoundry } from "@/src/services/infestedFoundryService";
import { sendWsBroadcastTo } from "@/src/services/wsService";
import { EquipmentFeatures, IEquipmentDatabase } from "@/src/types/equipmentTypes";
import { config } from "@/src/services/configService";
import { sendWsBroadcastTo } from "@/src/services/webService";
export const upgradesController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
@ -51,7 +56,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
const recipe = getRecipeByResult(operation.UpgradeRequirement)!;
for (const ingredient of recipe.ingredients) {
totalPercentagePointsConsumed += ingredient.ItemCount / 10;
if (!inventory.infiniteHelminthMaterials) {
if (!config.infiniteHelminthMaterials) {
inventory.InfestedFoundry!.Resources!.find(x => x.ItemType == ingredient.ItemType)!.Count -=
ingredient.ItemCount;
}
@ -68,7 +73,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
inventoryChanges.Recipes = recipeChanges;
inventoryChanges.InfestedFoundry = inventory.toJSON<IInventoryClient>().InfestedFoundry;
applyCheatsToInfestedFoundry(inventory, inventoryChanges.InfestedFoundry!);
applyCheatsToInfestedFoundry(inventoryChanges.InfestedFoundry!);
} else
switch (operation.UpgradeRequirement) {
case "/Lotus/Types/Items/MiscItems/OrokinReactor":

View File

@ -1,33 +0,0 @@
import { getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
import { RequestHandler } from "express";
export const abilityOverrideController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const request = req.body as IAbilityOverrideRequest;
if (request.category === "Suits") {
const inventory = await getInventory(accountId, request.category);
const item = inventory[request.category].id(request.oid);
if (item) {
if (request.action == "set") {
item.Configs[request.configIndex].AbilityOverride = request.AbilityOverride;
} else {
item.Configs[request.configIndex].AbilityOverride = undefined;
}
await inventory.save();
}
}
res.end();
};
interface IAbilityOverrideRequest {
category: TEquipmentKey;
oid: string;
action: "set" | "remove";
configIndex: number;
AbilityOverride: {
Ability: string;
Index: number;
};
}

View File

@ -1,7 +1,7 @@
import { applyClientEquipmentUpdates, getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { IOid } from "@/src/types/commonTypes";
import { IEquipmentClient } from "@/src/types/equipmentTypes";
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
import { RequestHandler } from "express";
import { ExportMisc } from "warframe-public-export-plus";

View File

@ -1,65 +0,0 @@
import { getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
import { RequestHandler } from "express";
export const changeModularPartsController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const request = req.body as IUpdateFingerPrintRequest;
const inventory = await getInventory(accountId, request.category);
const item = inventory[request.category].id(request.oid);
if (item) {
item.ModularParts = request.modularParts;
request.modularParts.forEach(part => {
const categoryMap = mapping[part];
if (categoryMap && categoryMap[request.category]) {
item.ItemType = categoryMap[request.category]!;
}
});
await inventory.save();
}
res.end();
};
interface IUpdateFingerPrintRequest {
category: TEquipmentKey;
oid: string;
modularParts: string[];
}
const mapping: Partial<Record<string, Partial<Record<TEquipmentKey, string>>>> = {
"/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelAPart": {
LongGuns: "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryShotgun",
Pistols: "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryShotgun"
},
"/Lotus/Weapons/Infested/Pistols/InfKitGun/Barrels/InfBarrelEgg/InfModularBarrelEggPart": {
LongGuns: "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryShotgun",
Pistols: "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryShotgun"
},
"/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelBPart": {
LongGuns: "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimary",
Pistols: "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondary"
},
"/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelCPart": {
LongGuns: "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimary",
Pistols: "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondary"
},
"/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelDPart": {
LongGuns: "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryBeam",
Pistols: "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryBeam"
},
"/Lotus/Weapons/Infested/Pistols/InfKitGun/Barrels/InfBarrelBeam/InfModularBarrelBeamPart": {
LongGuns: "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryBeam",
Pistols: "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryBeam"
},
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadA": {
MoaPets: "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetAPowerSuit"
},
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadB": {
MoaPets: "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetBPowerSuit"
},
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadC": {
MoaPets: "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetCPowerSuit"
}
};

View File

@ -1,8 +1,8 @@
import { RequestHandler } from "express";
import { config, syncConfigWithDatabase } from "@/src/services/configService";
import { config } from "@/src/services/configService";
import { getAccountForRequest, isAdministrator } from "@/src/services/loginService";
import { saveConfig } from "@/src/services/configWriterService";
import { sendWsBroadcastEx } from "@/src/services/wsService";
import { saveConfig } from "@/src/services/configWatcherService";
import { sendWsBroadcastExcept } from "@/src/services/webService";
export const getConfigController: RequestHandler = async (req, res) => {
const account = await getAccountForRequest(req);
@ -25,8 +25,7 @@ export const setConfigController: RequestHandler = async (req, res) => {
const [obj, idx] = configIdToIndexable(id);
obj[idx] = value;
}
sendWsBroadcastEx({ config_reloaded: true }, undefined, parseInt(String(req.query.wsid)));
syncConfigWithDatabase();
sendWsBroadcastExcept(parseInt(String(req.query.wsid)), { config_reloaded: true });
await saveConfig();
res.end();
} else {
@ -38,8 +37,6 @@ const configIdToIndexable = (id: string): [Record<string, boolean | string | num
let obj = config as unknown as Record<string, never>;
const arr = id.split(".");
while (arr.length > 1) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
obj[arr[0]] ??= {} as never;
obj = obj[arr[0]];
arr.splice(0, 1);
}

View File

@ -11,7 +11,6 @@ import { GuildMember } from "@/src/models/guildModel";
import { Leaderboard } from "@/src/models/leaderboardModel";
import { deleteGuild } from "@/src/services/guildService";
import { Friendship } from "@/src/models/friendModel";
import { sendWsBroadcastTo } from "@/src/services/wsService";
export const deleteAccountController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
@ -37,8 +36,5 @@ export const deleteAccountController: RequestHandler = async (req, res) => {
Ship.deleteMany({ ShipOwnerId: accountId }),
Stats.deleteOne({ accountOwnerId: accountId })
]);
sendWsBroadcastTo(accountId, { logged_out: true });
res.end();
};

View File

@ -1,34 +0,0 @@
import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory } from "@/src/services/inventoryService";
import { RequestHandler } from "express";
const DEFAULT_UPGRADE_EXPIRY_MS = 7 * 24 * 60 * 60 * 1000; // 7 days
export const editSuitInvigorationUpgradeController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const { oid, data } = req.body as {
oid: string;
data?: {
DefensiveUpgrade: string;
OffensiveUpgrade: string;
UpgradesExpiry?: number;
};
};
const inventory = await getInventory(accountId);
const suit = inventory.Suits.id(oid)!;
if (data) {
suit.DefensiveUpgrade = data.DefensiveUpgrade;
suit.OffensiveUpgrade = data.OffensiveUpgrade;
if (data.UpgradesExpiry) {
suit.UpgradesExpiry = new Date(data.UpgradesExpiry);
} else {
suit.UpgradesExpiry = new Date(Date.now() + DEFAULT_UPGRADE_EXPIRY_MS);
}
} else {
suit.DefensiveUpgrade = undefined;
suit.OffensiveUpgrade = undefined;
suit.UpgradesExpiry = undefined;
}
await inventory.save();
res.end();
};

View File

@ -1,7 +1,6 @@
import { RequestHandler } from "express";
import { getDict, getItemName, getString } from "@/src/services/itemDataService";
import {
ExportAbilities,
ExportArcanes,
ExportAvionics,
ExportBoosters,
@ -22,7 +21,6 @@ import {
TRelicQuality
} from "warframe-public-export-plus";
import allIncarnons from "@/static/fixed_responses/allIncarnonList.json";
import varzia from "@/static/fixed_responses/worldState/varzia.json";
interface ListedItem {
uniqueName: string;
@ -57,8 +55,6 @@ interface ItemLists {
EvolutionProgress: ListedItem[];
mods: ListedItem[];
Boosters: ListedItem[];
VarziaOffers: ListedItem[];
Abilities: ListedItem[];
//circuitGameModes: ListedItem[];
}
@ -95,9 +91,7 @@ const getItemListsController: RequestHandler = (req, response) => {
KubrowPets: [],
EvolutionProgress: [],
mods: [],
Boosters: [],
VarziaOffers: [],
Abilities: []
Boosters: []
/*circuitGameModes: [
{
uniqueName: "Survival",
@ -135,12 +129,6 @@ const getItemListsController: RequestHandler = (req, response) => {
name: getString(item.name, lang),
exalted: item.exalted
});
item.abilities.forEach(ability => {
res.Abilities.push({
uniqueName: ability.uniqueName,
name: getString(ability.name || uniqueName, lang)
});
});
}
for (const [uniqueName, item] of Object.entries(ExportSentinels)) {
if (item.productCategory == "Sentinels" || item.productCategory == "KubrowPets") {
@ -153,21 +141,18 @@ const getItemListsController: RequestHandler = (req, response) => {
}
for (const [uniqueName, item] of Object.entries(ExportWeapons)) {
if (item.partType) {
if (!uniqueName.split("/")[7]?.startsWith("PvPVariant")) {
// not a pvp variant
if (!uniqueName.startsWith("/Lotus/Types/Items/Deimos/")) {
res.ModularParts.push({
uniqueName,
name: getString(item.name, lang),
partType: item.partType
});
}
if (uniqueName.split("/")[5] != "SentTrainingAmplifier") {
res.miscitems.push({
uniqueName: uniqueName,
name: getString(item.name, lang)
});
}
if (!uniqueName.startsWith("/Lotus/Types/Items/Deimos/")) {
res.ModularParts.push({
uniqueName,
name: getString(item.name, lang),
partType: item.partType
});
}
if (uniqueName.split("/")[5] != "SentTrainingAmplifier") {
res.miscitems.push({
uniqueName: uniqueName,
name: getString(item.name, lang)
});
}
} else if (item.totalDamage !== 0) {
if (
@ -353,20 +338,6 @@ const getItemListsController: RequestHandler = (req, response) => {
});
}
for (const item of Object.values(varzia.primeDualPacks)) {
res.VarziaOffers.push({
uniqueName: item.ItemType,
name: getString(getItemName(item.ItemType) || "", lang)
});
}
for (const [uniqueName, ability] of Object.entries(ExportAbilities)) {
res.Abilities.push({
uniqueName,
name: getString(ability.name || uniqueName, lang)
});
}
response.json(res);
};

View File

@ -1,10 +1,8 @@
import { importInventory, importLoadOutPresets, importPersonalRooms } from "@/src/services/importService";
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 { getPersonalRooms } from "@/src/services/personalRoomsService";
import { IInventoryClient } from "@/src/types/inventoryTypes/inventoryTypes";
import { IGetShipResponse } from "@/src/types/personalRoomsTypes";
import { RequestHandler } from "express";
export const importController: RequestHandler = async (req, res) => {
@ -15,21 +13,15 @@ export const importController: RequestHandler = async (req, res) => {
importInventory(inventory, request.inventory);
await inventory.save();
if ("LoadOutPresets" in request.inventory && request.inventory.LoadOutPresets) {
if (request.inventory.LoadOutPresets) {
const loadout = await getLoadout(accountId);
importLoadOutPresets(loadout, request.inventory.LoadOutPresets);
await loadout.save();
}
if ("Ship" in request.inventory || "Apartment" in request.inventory || "TailorShop" in request.inventory) {
const personalRooms = await getPersonalRooms(accountId);
importPersonalRooms(personalRooms, request.inventory);
await personalRooms.save();
}
res.end();
};
interface IImportRequest {
inventory: Partial<IInventoryClient> | Partial<IGetShipResponse>;
inventory: Partial<IInventoryClient>;
}

View File

@ -1,7 +1,7 @@
import { RequestHandler } from "express";
import { getAccountForRequest, isAdministrator, isNameTaken } from "@/src/services/loginService";
import { config } from "@/src/services/configService";
import { saveConfig } from "@/src/services/configWriterService";
import { saveConfig } from "@/src/services/configWatcherService";
export const renameAccountController: RequestHandler = async (req, res) => {
const account = await getAccountForRequest(req);

View File

@ -1,18 +0,0 @@
import { getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { IAccountCheats } from "@/src/types/inventoryTypes/inventoryTypes";
import { RequestHandler } from "express";
export const setAccountCheatController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const payload = req.body as ISetAccountCheatRequest;
const inventory = await getInventory(accountId, payload.key);
inventory[payload.key] = payload.value;
await inventory.save();
res.end();
};
interface ISetAccountCheatRequest {
key: keyof IAccountCheats;
value: boolean;
}

View File

@ -1,5 +1,5 @@
import { args } from "@/src/helpers/commandLineArguments";
import { sendWsBroadcast } from "@/src/services/wsService";
import { sendWsBroadcast } from "@/src/services/webService";
import { RequestHandler } from "express";
export const webuiFileChangeDetectedController: RequestHandler = (req, res) => {

View File

@ -6,11 +6,13 @@ import { Account } from "@/src/models/loginModel";
import { Stats, TStatsDatabaseDocument } from "@/src/models/statsModel";
import { allDailyAffiliationKeys } from "@/src/services/inventoryService";
import { IMongoDate, IOid } from "@/src/types/commonTypes";
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
import {
IAffiliation,
IAlignment,
IChallengeProgress,
IDailyAffiliations,
ILoadoutConfigClient,
IMission,
IPlayerSkills,
ITypeXPItem
@ -21,8 +23,6 @@ import { ExportCustoms, ExportDojoRecipes } from "warframe-public-export-plus";
import { IStatsClient } from "@/src/types/statTypes";
import { toStoreItem } from "@/src/services/itemDataService";
import { FlattenMaps } from "mongoose";
import { IEquipmentClient } from "@/src/types/equipmentTypes";
import { ILoadoutConfigClient } from "@/src/types/saveLoadoutTypes";
const getProfileViewingDataByPlayerIdImpl = async (playerId: string): Promise<IProfileViewingData | undefined> => {
const account = await Account.findById(playerId, "DisplayName");
@ -141,7 +141,7 @@ export const getProfileViewingDataGetController: RequestHandler = async (req, re
}
}
} else {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
combinedStats[arrayName].push(entry as any);
}
}

View File

@ -1,7 +1,7 @@
import { IAccountCreation } from "@/src/types/customTypes";
import { IDatabaseAccountRequiredFields } from "@/src/types/loginTypes";
import crypto from "crypto";
import { isString, parseEmail, parseString } from "@/src/helpers/general";
import { isString, parseEmail, parseString } from "../general";
const getWhirlpoolHash = (rawPassword: string): string => {
const whirlpool = crypto.createHash("whirlpool");

View File

@ -9,11 +9,11 @@ export const isEmptyObject = (obj: object): boolean => {
};
*/
export const isString = (text: unknown): text is string => {
const isString = (text: unknown): text is string => {
return typeof text === "string" || text instanceof String;
};
export const parseString = (data: unknown): string => {
const parseString = (data: unknown): string => {
if (!isString(data)) {
throw new Error("data is not a string");
}
@ -21,11 +21,11 @@ export const parseString = (data: unknown): string => {
return data;
};
export const isNumber = (number: unknown): number is number => {
const isNumber = (number: unknown): number is number => {
return typeof number === "number" && !isNaN(number);
};
export const parseNumber = (data: unknown): number => {
const parseNumber = (data: unknown): number => {
if (!isNumber(data)) {
throw new Error("data is not a number");
}
@ -33,11 +33,11 @@ export const parseNumber = (data: unknown): number => {
return Number(data);
};
export const isDate = (date: string): boolean => {
const isDate = (date: string): boolean => {
return Date.parse(date) != 0;
};
export const parseDateNumber = (date: unknown): string => {
const parseDateNumber = (date: unknown): string => {
if (!isString(date) || !isDate(date)) {
throw new Error("date could not be parsed");
}
@ -45,18 +45,18 @@ export const parseDateNumber = (date: unknown): string => {
return date;
};
export const parseEmail = (email: unknown): string => {
const parseEmail = (email: unknown): string => {
if (!isString(email)) {
throw new Error("incorrect email");
}
return email;
};
export const isBoolean = (booleanCandidate: unknown): booleanCandidate is boolean => {
const isBoolean = (booleanCandidate: unknown): booleanCandidate is boolean => {
return typeof booleanCandidate === "boolean";
};
export const parseBoolean = (booleanCandidate: unknown): boolean => {
const parseBoolean = (booleanCandidate: unknown): boolean => {
if (!isBoolean(booleanCandidate)) {
throw new Error("argument was not a boolean");
}
@ -70,3 +70,5 @@ export const isObject = (objectCandidate: unknown): objectCandidate is Record<st
!Array.isArray(objectCandidate)
);
};
export { isString, isNumber, parseString, parseNumber, parseDateNumber, parseBoolean, parseEmail };

View File

@ -1,7 +1,6 @@
import { IMongoDate, IOid, IOidWithLegacySupport } from "@/src/types/commonTypes";
import { Types } from "mongoose";
import { TRarity } from "warframe-public-export-plus";
import { IFusionTreasure } from "@/src/types/inventoryTypes/inventoryTypes";
export const version_compare = (a: string, b: string): number => {
const a_digits = a
@ -52,20 +51,6 @@ export const fromMongoDate = (date: IMongoDate): Date => {
return new Date(parseInt(date.$date.$numberLong));
};
export const parseFusionTreasure = (name: string, count: number): IFusionTreasure => {
const arr = name.split("_");
return {
ItemType: arr[0],
Sockets: parseInt(arr[1], 16),
ItemCount: count
};
};
export type TTraitsPool = Record<
"Colors" | "EyeColors" | "FurPatterns" | "BodyTypes" | "Heads" | "Tails",
{ type: string; rarity: TRarity }[]
>;
export const kubrowWeights: Record<TRarity, number> = {
COMMON: 6,
UNCOMMON: 4,
@ -80,126 +65,126 @@ export const kubrowFurPatternsWeights: Record<TRarity, number> = {
LEGENDARY: 1
};
export const catbrowDetails: TTraitsPool = {
export const catbrowDetails = {
Colors: [
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorBaseA", rarity: "COMMON" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorBaseB", rarity: "COMMON" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorBaseC", rarity: "COMMON" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorBaseD", rarity: "COMMON" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorBaseA", rarity: "COMMON" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorBaseB", rarity: "COMMON" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorBaseC", rarity: "COMMON" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorBaseD", rarity: "COMMON" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorSecondaryA", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorSecondaryB", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorSecondaryC", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorSecondaryD", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorSecondaryA", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorSecondaryB", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorSecondaryC", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorSecondaryD", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorTertiaryA", rarity: "RARE" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorTertiaryB", rarity: "RARE" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorTertiaryC", rarity: "RARE" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorTertiaryD", rarity: "RARE" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorTertiaryA", rarity: "RARE" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorTertiaryB", rarity: "RARE" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorTertiaryC", rarity: "RARE" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorTertiaryD", rarity: "RARE" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorAccentsA", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorAccentsB", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorAccentsC", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorAccentsD", rarity: "LEGENDARY" }
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorAccentsA", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorAccentsB", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorAccentsC", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorAccentsD", rarity: "LEGENDARY" as TRarity }
],
EyeColors: [
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesA", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesB", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesC", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesD", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesE", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesF", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesG", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesH", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesI", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesJ", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesK", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesL", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesM", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesN", rarity: "LEGENDARY" }
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesA", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesB", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesC", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesD", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesE", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesF", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesG", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesH", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesI", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesJ", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesK", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesL", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesM", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesN", rarity: "LEGENDARY" as TRarity }
],
FurPatterns: [{ type: "/Lotus/Types/Game/CatbrowPet/Patterns/CatbrowPetPatternA", rarity: "COMMON" }],
FurPatterns: [{ type: "/Lotus/Types/Game/CatbrowPet/Patterns/CatbrowPetPatternA", rarity: "COMMON" as TRarity }],
BodyTypes: [
{ type: "/Lotus/Types/Game/CatbrowPet/BodyTypes/CatbrowPetRegularBodyType", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/CatbrowPet/BodyTypes/CatbrowPetRegularBodyType", rarity: "LEGENDARY" }
{ type: "/Lotus/Types/Game/CatbrowPet/BodyTypes/CatbrowPetRegularBodyType", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/BodyTypes/CatbrowPetRegularBodyType", rarity: "LEGENDARY" as TRarity }
],
Heads: [
{ type: "/Lotus/Types/Game/CatbrowPet/Heads/CatbrowHeadA", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Heads/CatbrowHeadB", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Heads/CatbrowHeadC", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Heads/CatbrowHeadD", rarity: "LEGENDARY" }
{ type: "/Lotus/Types/Game/CatbrowPet/Heads/CatbrowHeadA", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Heads/CatbrowHeadB", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Heads/CatbrowHeadC", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Heads/CatbrowHeadD", rarity: "LEGENDARY" as TRarity }
],
Tails: [
{ type: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailA", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailB", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailC", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailD", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailE", rarity: "LEGENDARY" }
{ type: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailA", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailB", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailC", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailD", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailE", rarity: "LEGENDARY" as TRarity }
]
};
export const kubrowDetails: TTraitsPool = {
export const kubrowDetails = {
Colors: [
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneA", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneB", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneC", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneD", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneE", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneF", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneG", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneH", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneA", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneB", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneC", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneD", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneE", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneF", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneG", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneH", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidA", rarity: "RARE" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidB", rarity: "RARE" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidC", rarity: "RARE" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidD", rarity: "RARE" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidE", rarity: "RARE" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidF", rarity: "RARE" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidG", rarity: "RARE" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidH", rarity: "RARE" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidA", rarity: "RARE" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidB", rarity: "RARE" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidC", rarity: "RARE" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidD", rarity: "RARE" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidE", rarity: "RARE" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidF", rarity: "RARE" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidG", rarity: "RARE" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidH", rarity: "RARE" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantA", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantB", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantC", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantD", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantE", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantF", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantG", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantH", rarity: "LEGENDARY" }
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantA", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantB", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantC", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantD", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantE", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantF", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantG", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantH", rarity: "LEGENDARY" as TRarity }
],
EyeColors: [
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesA", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesB", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesC", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesD", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesE", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesF", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesG", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesH", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesI", rarity: "LEGENDARY" }
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesA", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesB", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesC", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesD", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesE", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesF", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesG", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesH", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesI", rarity: "LEGENDARY" as TRarity }
],
FurPatterns: [
{ type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternB", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternA", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternB", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternA", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternC", rarity: "RARE" },
{ type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternD", rarity: "RARE" },
{ type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternC", rarity: "RARE" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternD", rarity: "RARE" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternE", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternF", rarity: "LEGENDARY" }
{ type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternE", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternF", rarity: "LEGENDARY" as TRarity }
],
BodyTypes: [
{ type: "/Lotus/Types/Game/KubrowPet/BodyTypes/KubrowPetRegularBodyType", rarity: "UNCOMMON" },
{ type: "/Lotus/Types/Game/KubrowPet/BodyTypes/KubrowPetHeavyBodyType", rarity: "LEGENDARY" },
{ type: "/Lotus/Types/Game/KubrowPet/BodyTypes/KubrowPetThinBodyType", rarity: "LEGENDARY" }
{ type: "/Lotus/Types/Game/KubrowPet/BodyTypes/KubrowPetRegularBodyType", rarity: "UNCOMMON" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/BodyTypes/KubrowPetHeavyBodyType", rarity: "LEGENDARY" as TRarity },
{ type: "/Lotus/Types/Game/KubrowPet/BodyTypes/KubrowPetThinBodyType", rarity: "LEGENDARY" as TRarity }
],
Heads: [],

View File

@ -1,4 +1,4 @@
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
import { TEquipmentKey } from "../types/inventoryTypes/inventoryTypes";
export const modularWeaponTypes: Record<string, TEquipmentKey> = {
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimary": "LongGuns",

View File

@ -1,9 +1,12 @@
import { ExportRegions, ExportWarframes } from "warframe-public-export-plus";
import { IInfNode, TNemesisFaction } from "@/src/types/inventoryTypes/inventoryTypes";
import { generateRewardSeed, getRewardAtPercentage, SRng } from "@/src/services/rngService";
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
import { IOid } from "@/src/types/commonTypes";
import { isArchwingMission } from "@/src/services/worldStateService";
import { getRewardAtPercentage, SRng } from "@/src/services/rngService";
import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel";
import { logger } from "../utils/logger";
import { IOid } from "../types/commonTypes";
import { Types } from "mongoose";
import { addMods, generateRewardSeed } from "../services/inventoryService";
import { isArchwingMission } from "../services/worldStateService";
type TInnateDamageTag =
| "InnateElectricityDamage"
@ -22,11 +25,8 @@ export interface INemesisManifest {
ephemeraTypes?: Record<TInnateDamageTag, string>;
firstKillReward: string;
firstConvertReward: string;
killMessageSubject: string;
killMessageBody: string;
convertMessageSubject: string;
convertMessageBody: string;
convertMessageIcon: string;
messageTitle: string;
messageBody: string;
minBuild: string;
}
@ -60,11 +60,8 @@ class KuvaLichManifest implements INemesisManifest {
};
firstKillReward = "/Lotus/StoreItems/Upgrades/Skins/Clan/LichKillerBadgeItem";
firstConvertReward = "/Lotus/StoreItems/Upgrades/Skins/Sigils/KuvaLichSigil";
killMessageSubject = "/Lotus/Language/Inbox/VanquishKuvaMsgTitle";
killMessageBody = "/Lotus/Language/Inbox/VanquishLichMsgBody";
convertMessageSubject = "/Lotus/Language/Kingpins/InboxKuvaConvertedSubject";
convertMessageBody = "/Lotus/Language/Kingpins/InboxKuvaConvertedBody";
convertMessageIcon = "/Lotus/Interface/Graphics/WorldStatePanel/Grineer.png";
messageTitle = "/Lotus/Language/Inbox/VanquishKuvaMsgTitle";
messageBody = "/Lotus/Language/Inbox/VanquishLichMsgBody";
minBuild = "2019.10.31.22.42"; // 26.0.0
}
@ -137,11 +134,8 @@ class LawyerManifest implements INemesisManifest {
};
firstKillReward = "/Lotus/StoreItems/Upgrades/Skins/Clan/CorpusLichBadgeItem";
firstConvertReward = "/Lotus/StoreItems/Upgrades/Skins/Sigils/CorpusLichSigil";
killMessageSubject = "/Lotus/Language/Inbox/VanquishLawyerMsgTitle";
killMessageBody = "/Lotus/Language/Inbox/VanquishLichMsgBody";
convertMessageSubject = "/Lotus/Language/Kingpins/InboxSisterConvertedSubject";
convertMessageBody = "/Lotus/Language/Kingpins/InboxSisterConvertedBody";
convertMessageIcon = "/Lotus/Interface/Graphics/WorldStatePanel/Corpus.png";
messageTitle = "/Lotus/Language/Inbox/VanquishLawyerMsgTitle";
messageBody = "/Lotus/Language/Inbox/VanquishLichMsgBody";
minBuild = "2021.07.05.17.03"; // 30.5.0
}
@ -175,11 +169,8 @@ class InfestedLichManfest implements INemesisManifest {
ephemeraChance = 0;
firstKillReward = "/Lotus/StoreItems/Upgrades/Skins/Sigils/InfLichVanquishedSigil";
firstConvertReward = "/Lotus/StoreItems/Upgrades/Skins/Sigils/InfLichConvertedSigil";
killMessageSubject = "/Lotus/Language/Inbox/VanquishBandMsgTitle";
killMessageBody = "/Lotus/Language/Inbox/VanquishBandMsgBody";
convertMessageSubject = "/Lotus/Language/Kingpins/InboxBandConvertedSubject";
convertMessageBody = "/Lotus/Language/Kingpins/InboxBandConvertedBody";
convertMessageIcon = "/Lotus/Interface/Graphics/WorldStatePanel/Infested.png";
messageTitle = "/Lotus/Language/Inbox/VanquishBandMsgTitle";
messageBody = "/Lotus/Language/Inbox/VanquishBandMsgBody";
minBuild = "2025.03.18.09.51"; // 38.5.0
}
@ -373,6 +364,57 @@ export const parseUpgrade = (
}
};
export const consumeModCharge = (
response: IKnifeResponse,
inventory: TInventoryDatabaseDocument,
upgrade: { ItemId: IOid; ItemType: string },
dataknifeUpgrades: string[]
): void => {
response.UpgradeIds ??= [];
response.UpgradeTypes ??= [];
response.UpgradeFingerprints ??= [];
response.UpgradeNew ??= [];
response.HasKnife = true;
if (upgrade.ItemId.$oid != "000000000000000000000000") {
const dbUpgrade = inventory.Upgrades.id(upgrade.ItemId.$oid)!;
const fingerprint = JSON.parse(dbUpgrade.UpgradeFingerprint!) as { lvl: number };
fingerprint.lvl += 1;
dbUpgrade.UpgradeFingerprint = JSON.stringify(fingerprint);
response.UpgradeIds.push(upgrade.ItemId.$oid);
response.UpgradeTypes.push(upgrade.ItemType);
response.UpgradeFingerprints.push(fingerprint);
response.UpgradeNew.push(false);
} else {
const id = new Types.ObjectId();
inventory.Upgrades.push({
_id: id,
ItemType: upgrade.ItemType,
UpgradeFingerprint: `{"lvl":1}`
});
addMods(inventory, [
{
ItemType: upgrade.ItemType,
ItemCount: -1
}
]);
const dataknifeRawUpgradeIndex = dataknifeUpgrades.indexOf(upgrade.ItemType);
if (dataknifeRawUpgradeIndex != -1) {
dataknifeUpgrades[dataknifeRawUpgradeIndex] = id.toString();
} else {
logger.warn(`${upgrade.ItemType} not found in dataknife config`);
}
response.UpgradeIds.push(id.toString());
response.UpgradeTypes.push(upgrade.ItemType);
response.UpgradeFingerprints.push({ lvl: 1 });
response.UpgradeNew.push(true);
}
};
export const getInnateDamageTag = (KillingSuit: string): TInnateDamageTag => {
return ExportWarframes[KillingSuit].nemesisUpgradeTag!;
};

View File

@ -1,17 +1,5 @@
import { SlotPurchase, SlotPurchaseName } from "@/src/types/purchaseTypes";
export const slotPurchaseNameToSlotName: SlotPurchase = {
SuitSlotItem: { name: "SuitBin", purchaseQuantity: 1 },
TwoSentinelSlotItem: { name: "SentinelBin", purchaseQuantity: 2 },
TwoWeaponSlotItem: { name: "WeaponBin", purchaseQuantity: 2 },
SpaceSuitSlotItem: { name: "SpaceSuitBin", purchaseQuantity: 1 },
TwoSpaceWeaponSlotItem: { name: "SpaceWeaponBin", purchaseQuantity: 2 },
MechSlotItem: { name: "MechBin", purchaseQuantity: 1 },
TwoOperatorWeaponSlotItem: { name: "OperatorAmpBin", purchaseQuantity: 2 },
RandomModSlotItem: { name: "RandomModBin", purchaseQuantity: 3 },
TwoCrewShipSalvageSlotItem: { name: "CrewShipSalvageBin", purchaseQuantity: 2 },
CrewMemberSlotItem: { name: "CrewMemberBin", purchaseQuantity: 1 }
};
import { slotPurchaseNameToSlotName } from "@/src/services/purchaseService";
import { SlotPurchaseName } from "@/src/types/purchaseTypes";
export const isSlotPurchaseName = (slotPurchaseName: string): slotPurchaseName is SlotPurchaseName => {
return slotPurchaseName in slotPurchaseNameToSlotName;

View File

@ -5,8 +5,8 @@ import { getRandomWeightedReward, IRngResult } from "@/src/services/rngService";
import { logger } from "@/src/utils/logger";
import { addMiscItems, combineInventoryChanges } from "@/src/services/inventoryService";
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { config } from "@/src/services/configService";
import { IInventoryChanges } from "../types/purchaseTypes";
import { config } from "../services/configService";
export const crackRelic = async (
inventory: TInventoryDatabaseDocument,
@ -23,16 +23,10 @@ export const crackRelic = async (
weights = { COMMON: 0, UNCOMMON: 0, RARE: 1, LEGENDARY: 0 };
}
logger.debug(`opening a relic of quality ${relic.quality}; rarity weights are`, weights);
let reward = getRandomWeightedReward(
const reward = getRandomWeightedReward(
ExportRewards[relic.rewardManifest][0] as { type: string; itemCount: number; rarity: TRarity }[], // rarity is nullable in PE+ typings, but always present for relics
weights
)!;
if (config.relicRewardItemCountMultiplier !== undefined && (config.relicRewardItemCountMultiplier ?? 1) != 1) {
reward = {
...reward,
itemCount: reward.itemCount * config.relicRewardItemCountMultiplier
};
}
logger.debug(`relic rolled`, reward);
participant.Reward = reward.type;
@ -49,7 +43,13 @@ export const crackRelic = async (
// Give reward
combineInventoryChanges(
inventoryChanges,
(await handleStoreItemAcquisition(reward.type, inventory, reward.itemCount)).InventoryChanges
(
await handleStoreItemAcquisition(
reward.type,
inventory,
reward.itemCount * (config.relicRewardItemCountMultiplier ?? 1)
)
).InventoryChanges
);
return reward;

View File

@ -1,5 +1,5 @@
import { IUpgrade } from "warframe-public-export-plus";
import { getRandomElement, getRandomInt, getRandomReward } from "@/src/services/rngService";
import { getRandomElement, getRandomInt, getRandomReward } from "../services/rngService";
export type RivenFingerprint = IVeiledRivenFingerprint | IUnveiledRivenFingerprint;

View File

@ -1,5 +1,5 @@
// First, init config.
import { config, configPath, loadConfig, syncConfigWithDatabase } from "@/src/services/configService";
import { config, configPath, loadConfig } from "@/src/services/configService";
import fs from "fs";
try {
loadConfig();
@ -7,7 +7,7 @@ try {
if (fs.existsSync("config.json")) {
console.log("Failed to load " + configPath + ": " + (e as Error).message);
} else {
console.log("Failed to load " + configPath + ". You can copy config-vanilla.json to create your config file.");
console.log("Failed to load " + configPath + ". You can copy config.json.example to create your config file.");
}
process.exit(1);
}
@ -18,23 +18,17 @@ logger.info("Starting up...");
// Proceed with normal startup: bring up config watcher service, validate config, connect to MongoDB, and finally start listening for HTTP.
import mongoose from "mongoose";
import path from "path";
import { JSONStringify } from "json-with-bigint";
import { startWebServer } from "@/src/services/webService";
import { validateConfig } from "@/src/services/configWatcherService";
import { updateWorldStateCollections } from "@/src/services/worldStateService";
import { repoDir } from "@/src/helpers/pathHelper";
import { startWebServer } from "./services/webService";
JSON.stringify = JSONStringify; // Patch JSON.stringify to work flawlessly with Bigints.
import { syncConfigWithDatabase, validateConfig } from "@/src/services/configWatcherService";
import { updateWorldStateCollections } from "./services/worldStateService";
// Patch JSON.stringify to work flawlessly with Bigints.
JSON.stringify = JSONStringify;
validateConfig();
fs.readFile(path.join(repoDir, "BUILD_DATE"), "utf-8", (err, data) => {
if (!err) {
logger.info(`Docker image was built on ${data.trim()}`);
}
});
mongoose
.connect(config.mongodbUrl)
.then(() => {

View File

@ -1,11 +1,16 @@
import { NextFunction, Request, Response } from "express";
import { logError } from "@/src/utils/logger";
import { logger } from "../utils/logger";
export const errorHandler = (err: Error, req: Request, res: Response, _next: NextFunction): void => {
if (err.message == "Invalid accountId-nonce pair") {
res.status(400).send("Log-in expired");
} else if (err.stack) {
const stackArr = err.stack.split("\n");
stackArr[0] += ` while processing ${req.path} request`;
logger.error(stackArr.join("\n"));
res.status(500).end();
} else {
logError(err, `processing ${req.path} request`);
logger.error(`uncaught error while processing ${req.path} request: ${err.message}`);
res.status(500).end();
}
};

View File

@ -1,25 +0,0 @@
import { Schema } from "mongoose";
import { IColor, IShipCustomization } from "@/src/types/inventoryTypes/commonInventoryTypes";
export const colorSchema = new Schema<IColor>(
{
t0: Number,
t1: Number,
t2: Number,
t3: Number,
en: Number,
e1: Number,
m0: Number,
m1: Number
},
{ _id: false }
);
export const shipCustomizationSchema = new Schema<IShipCustomization>(
{
SkinFlavourItem: String,
Colors: colorSchema,
ShipAttachments: { HOOD_ORNAMENT: String }
},
{ _id: false }
);

View File

@ -17,10 +17,8 @@ import {
GuildPermission
} from "@/src/types/guildTypes";
import { Document, Model, model, Schema, Types } from "mongoose";
import { fusionTreasuresSchema, typeCountSchema } from "@/src/models/inventoryModels/inventoryModel";
import { pictureFrameInfoSchema } from "@/src/models/personalRoomsModel";
import { IGoalProgressClient, IGoalProgressDatabase } from "@/src/types/inventoryTypes/inventoryTypes";
import { toOid } from "@/src/helpers/inventoryHelpers";
import { fusionTreasuresSchema, typeCountSchema } from "./inventoryModels/inventoryModel";
import { pictureFrameInfoSchema } from "./personalRoomsModel";
const dojoDecoSchema = new Schema<IDojoDecoDatabase>({
Type: String,
@ -176,28 +174,6 @@ const guildLogEntryNumberSchema = new Schema<IGuildLogEntryNumber>(
{ _id: false }
);
const goalProgressSchema = new Schema<IGoalProgressDatabase>(
{
Count: Number,
Tag: String,
goalId: Types.ObjectId
},
{ _id: false }
);
goalProgressSchema.set("toJSON", {
virtuals: true,
transform(_doc, obj: Record<string, any>) {
const db = obj as IGoalProgressDatabase;
const client = obj as IGoalProgressClient;
client._id = toOid(db.goalId);
delete obj.goalId;
delete obj.__v;
}
});
const guildSchema = new Schema<IGuildDatabase>(
{
Name: { type: String, required: true, unique: true },
@ -230,8 +206,7 @@ const guildSchema = new Schema<IGuildDatabase>(
RoomChanges: { type: [guildLogRoomChangeSchema], default: undefined },
TechChanges: { type: [guildLogEntryContributableSchema], default: undefined },
RosterActivity: { type: [guildLogEntryRosterSchema], default: undefined },
ClassChanges: { type: [guildLogEntryNumberSchema], default: undefined },
GoalProgress: { type: [goalProgressSchema], default: undefined }
ClassChanges: { type: [guildLogEntryNumberSchema], default: undefined }
},
{ id: false }
);

View File

@ -1,15 +1,12 @@
import { model, Schema, Types } from "mongoose";
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
import { typeCountSchema } from "@/src/models/inventoryModels/inventoryModel";
import { IMongoDate, IOid, ITypeCount } from "@/src/types/commonTypes";
import { IMongoDate, IOid } from "@/src/types/commonTypes";
import { ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
export interface IMessageClient
extends Omit<
IMessageDatabase,
"_id" | "globaUpgradeId" | "date" | "startDate" | "endDate" | "ownerId" | "attVisualOnly" | "expiry"
> {
extends Omit<IMessageDatabase, "_id" | "date" | "startDate" | "endDate" | "ownerId" | "attVisualOnly" | "expiry"> {
_id?: IOid;
globaUpgradeId?: IOid; // [sic]
date: IMongoDate;
startDate?: IMongoDate;
endDate?: IMongoDate;
@ -18,7 +15,6 @@ export interface IMessageClient
export interface IMessageDatabase extends IMessage {
ownerId: Types.ObjectId;
globaUpgradeId?: Types.ObjectId; // [sic]
date: Date; //created at
attVisualOnly?: boolean;
_id: Types.ObjectId;
@ -47,7 +43,6 @@ export interface IMessage {
acceptAction?: string;
declineAction?: string;
hasAccountAction?: boolean;
RegularCredits?: number;
}
export interface Arg {
@ -107,7 +102,6 @@ const giftSchema = new Schema<IGift>(
const messageSchema = new Schema<IMessageDatabase>(
{
ownerId: Schema.Types.ObjectId,
globaUpgradeId: Schema.Types.ObjectId,
sndr: String,
msg: String,
cinematic: String,
@ -140,8 +134,7 @@ const messageSchema = new Schema<IMessageDatabase>(
contextInfo: String,
acceptAction: String,
declineAction: String,
hasAccountAction: Boolean,
RegularCredits: Number
hasAccountAction: Boolean
},
{ id: false }
);
@ -152,7 +145,7 @@ messageSchema.virtual("messageId").get(function (this: IMessageDatabase) {
messageSchema.set("toJSON", {
virtuals: true,
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
const messageDatabase = returnedObject as IMessageDatabase;
const messageClient = returnedObject as IMessageClient;
@ -162,10 +155,6 @@ messageSchema.set("toJSON", {
delete returnedObject.attVisualOnly;
delete returnedObject.expiry;
if (messageDatabase.globaUpgradeId) {
messageClient.globaUpgradeId = toOid(messageDatabase.globaUpgradeId);
}
messageClient.date = toMongoDate(messageDatabase.date);
if (messageDatabase.startDate && messageDatabase.endDate) {

View File

@ -1,5 +1,6 @@
import { Document, Model, Schema, Types, model } from "mongoose";
import {
IFlavourItem,
IRawUpgrade,
IMiscItem,
IInventoryDatabase,
@ -9,6 +10,7 @@ import {
IDuviriInfo,
IPendingRecipeDatabase,
IPendingRecipeClient,
ITypeCount,
IFocusXP,
IFocusUpgrade,
ITypeXPItem,
@ -37,15 +39,25 @@ import {
IEvolutionProgress,
IEndlessXpProgressDatabase,
IEndlessXpProgressClient,
ICrewShipCustomization,
ICrewShipWeapon,
ICrewShipWeaponEmplacements,
IShipExterior,
IHelminthFoodRecord,
ICrewShipMembersDatabase,
IDialogueHistoryDatabase,
IDialogueDatabase,
IDialogueGift,
ICompletedDialogue,
IDialogueClient,
IUpgradeDatabase,
ICrewShipMemberDatabase,
ICrewShipMemberClient,
TEquipmentKey,
equipmentKeys,
IKubrowPetDetailsDatabase,
ITraits,
IKubrowPetDetailsClient,
IKubrowPetEggDatabase,
IKubrowPetEggClient,
ICustomMarkers,
@ -84,44 +96,32 @@ import {
IInvasionProgressClient,
IAccolades,
IHubNpcCustomization,
ILotusCustomization,
IEndlessXpReward,
IGoalProgressDatabase,
IGoalProgressClient,
IPersonalGoalProgressDatabase,
IPersonalGoalProgressClient,
IKubrowPetPrintClient,
IKubrowPetPrintDatabase
} from "@/src/types/inventoryTypes/inventoryTypes";
import { IOid, ITypeCount } from "@/src/types/commonTypes";
} from "../../types/inventoryTypes/inventoryTypes";
import { IOid } from "../../types/commonTypes";
import {
IAbilityOverride,
ICrewShipCustomization,
IFlavourItem,
IColor,
IItemConfig,
ILotusCustomization,
IOperatorConfigDatabase,
IPolarity
IPolarity,
IEquipmentDatabase,
IArchonCrystalUpgrade,
IEquipmentClient
} from "@/src/types/inventoryTypes/commonInventoryTypes";
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
import { EquipmentSelectionSchema, oidSchema } from "@/src/models/inventoryModels/loadoutModel";
import { EquipmentSelectionSchema, oidSchema } from "./loadoutModel";
import { ICountedStoreItem } from "warframe-public-export-plus";
import { colorSchema, shipCustomizationSchema } from "@/src/models/commonModel";
import {
IArchonCrystalUpgrade,
ICrewShipMemberClient,
ICrewShipMemberDatabase,
ICrewShipMembersDatabase,
ICrewShipWeapon,
ICrewShipWeaponEmplacements,
IEquipmentClient,
IEquipmentDatabase,
IKubrowPetDetailsClient,
IKubrowPetDetailsDatabase,
ITraits
} from "@/src/types/equipmentTypes";
export const typeCountSchema = new Schema<ITypeCount>({ ItemType: String, ItemCount: Number }, { _id: false });
typeCountSchema.set("toJSON", {
transform(_doc, obj: Record<string, any>) {
transform(_doc, obj) {
if (obj.ItemCount > 2147483647) {
obj.ItemCount = 2147483647;
} else if (obj.ItemCount < -2147483648) {
@ -166,6 +166,20 @@ const abilityOverrideSchema = new Schema<IAbilityOverride>(
{ _id: false }
);
export const colorSchema = new Schema<IColor>(
{
t0: Number,
t1: Number,
t2: Number,
t3: Number,
en: Number,
e1: Number,
m0: Number,
m1: Number
},
{ _id: false }
);
const operatorConfigSchema = new Schema<IOperatorConfigDatabase>(
{
Skins: [String],
@ -189,7 +203,7 @@ operatorConfigSchema.virtual("ItemId").get(function () {
operatorConfigSchema.set("toJSON", {
virtuals: true,
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
delete returnedObject._id;
delete returnedObject.__v;
}
@ -226,7 +240,7 @@ const ItemConfigSchema = new Schema<IItemConfig>(
);
ItemConfigSchema.set("toJSON", {
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
delete returnedObject.__v;
}
});
@ -261,7 +275,7 @@ RawUpgrades.virtual("LastAdded").get(function () {
RawUpgrades.set("toJSON", {
virtuals: true,
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
delete returnedObject._id;
delete returnedObject.__v;
}
@ -282,7 +296,7 @@ upgradeSchema.virtual("ItemId").get(function () {
upgradeSchema.set("toJSON", {
virtuals: true,
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
delete returnedObject._id;
delete returnedObject.__v;
}
@ -325,7 +339,7 @@ const crewMemberSchema = new Schema<ICrewMemberDatabase>(
crewMemberSchema.set("toJSON", {
virtuals: true,
transform(_doc, obj: Record<string, any>) {
transform(_doc, obj) {
const db = obj as ICrewMemberDatabase;
const client = obj as ICrewMemberClient;
@ -353,7 +367,7 @@ const FlavourItemSchema = new Schema(
);
FlavourItemSchema.set("toJSON", {
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
delete returnedObject._id;
delete returnedObject.__v;
}
@ -367,7 +381,7 @@ FlavourItemSchema.set("toJSON", {
);
MailboxSchema.set("toJSON", {
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
const mailboxDatabase = returnedObject as HydratedDocument<IMailboxDatabase, { __v?: number }>;
delete mailboxDatabase.__v;
(returnedObject as IMailboxClient).LastInboxId = toOid(mailboxDatabase.LastInboxId);
@ -386,7 +400,7 @@ const DuviriInfoSchema = new Schema<IDuviriInfo>(
);
DuviriInfoSchema.set("toJSON", {
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
delete returnedObject.__v;
}
});
@ -416,7 +430,7 @@ const droneSchema = new Schema<IDroneDatabase>(
);
droneSchema.set("toJSON", {
virtuals: true,
transform(_document, obj: Record<string, any>) {
transform(_document, obj) {
const client = obj as IDroneClient;
const db = obj as IDroneDatabase;
@ -445,7 +459,7 @@ const discoveredMarkerSchema = new Schema<IDiscoveredMarker>(
{ _id: false }
);
const personalGoalProgressSchema = new Schema<IGoalProgressDatabase>(
const personalGoalProgressSchema = new Schema<IPersonalGoalProgressDatabase>(
{
Best: Number,
Count: Number,
@ -457,9 +471,9 @@ const personalGoalProgressSchema = new Schema<IGoalProgressDatabase>(
personalGoalProgressSchema.set("toJSON", {
virtuals: true,
transform(_doc, obj: Record<string, any>) {
const db = obj as IGoalProgressDatabase;
const client = obj as IGoalProgressClient;
transform(_doc, obj) {
const db = obj as IPersonalGoalProgressDatabase;
const client = obj as IPersonalGoalProgressClient;
client._id = toOid(db.goalId);
@ -502,7 +516,7 @@ StepSequencersSchema.virtual("ItemId").get(function () {
StepSequencersSchema.set("toJSON", {
virtuals: true,
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
delete returnedObject._id;
delete returnedObject.__v;
}
@ -516,7 +530,7 @@ const kubrowPetEggSchema = new Schema<IKubrowPetEggDatabase>(
);
kubrowPetEggSchema.set("toJSON", {
virtuals: true,
transform(_document, obj: Record<string, any>) {
transform(_document, obj) {
const client = obj as IKubrowPetEggClient;
const db = obj as IKubrowPetEggDatabase;
@ -586,7 +600,7 @@ personalTechProjectSchema.virtual("ItemId").get(function () {
personalTechProjectSchema.set("toJSON", {
virtuals: true,
transform(_doc, ret: Record<string, any>) {
transform(_doc, ret, _options) {
delete ret._id;
delete ret.__v;
@ -687,7 +701,7 @@ const questKeysSchema = new Schema<IQuestKeyDatabase>(
);
questKeysSchema.set("toJSON", {
transform(_doc, ret: Record<string, any>) {
transform(_doc, ret, _options) {
const questKeysDatabase = ret as IQuestKeyDatabase;
if (questKeysDatabase.CompletionDate) {
@ -709,7 +723,7 @@ const invasionProgressSchema = new Schema<IInvasionProgressDatabase>(
);
invasionProgressSchema.set("toJSON", {
transform(_doc, obj: Record<string, any>) {
transform(_doc, obj) {
const db = obj as IInvasionProgressDatabase;
const client = obj as IInvasionProgressClient;
@ -748,7 +762,7 @@ weaponSkinsSchema.virtual("ItemId").get(function () {
weaponSkinsSchema.set("toJSON", {
virtuals: true,
transform(_doc, ret: Record<string, any>) {
transform(_doc, ret, _options) {
delete ret._id;
delete ret.__v;
}
@ -772,7 +786,7 @@ const periodicMissionCompletionsSchema = new Schema<IPeriodicMissionCompletionDa
);
periodicMissionCompletionsSchema.set("toJSON", {
transform(_doc, ret: Record<string, any>) {
transform(_doc, ret, _options) {
const periodicMissionCompletionDatabase = ret as IPeriodicMissionCompletionDatabase;
(periodicMissionCompletionDatabase as unknown as IPeriodicMissionCompletionResponse).date = toMongoDate(
@ -849,7 +863,7 @@ const endlessXpProgressSchema = new Schema<IEndlessXpProgressDatabase>(
);
endlessXpProgressSchema.set("toJSON", {
transform(_doc, ret: Record<string, any>) {
transform(_doc, ret) {
const db = ret as IEndlessXpProgressDatabase;
const client = ret as IEndlessXpProgressClient;
@ -882,9 +896,18 @@ const crewShipWeaponSchema = new Schema<ICrewShipWeapon>(
{ _id: false }
);
const shipExteriorSchema = new Schema<IShipExterior>(
{
SkinFlavourItem: String,
Colors: colorSchema,
ShipAttachments: { HOOD_ORNAMENT: String }
},
{ _id: false }
);
const crewShipCustomizationSchema = new Schema<ICrewShipCustomization>(
{
CrewshipInterior: shipCustomizationSchema
CrewshipInterior: shipExteriorSchema
},
{ _id: false }
);
@ -898,7 +921,7 @@ const crewShipMemberSchema = new Schema<ICrewShipMemberDatabase>(
);
crewShipMemberSchema.set("toJSON", {
virtuals: true,
transform(_doc, obj: Record<string, any>) {
transform(_doc, obj) {
const db = obj as ICrewShipMemberDatabase;
const client = obj as ICrewShipMemberClient;
if (db.ItemId) {
@ -951,7 +974,7 @@ const dialogueSchema = new Schema<IDialogueDatabase>(
);
dialogueSchema.set("toJSON", {
virtuals: true,
transform(_doc, ret: Record<string, any>) {
transform(_doc, ret) {
const db = ret as IDialogueDatabase;
const client = ret as IDialogueClient;
@ -997,7 +1020,7 @@ const kubrowPetPrintSchema = new Schema<IKubrowPetPrintDatabase>({
});
kubrowPetPrintSchema.set("toJSON", {
virtuals: true,
transform(_doc, obj: Record<string, any>) {
transform(_doc, obj) {
const db = obj as IKubrowPetPrintDatabase;
const client = obj as IKubrowPetPrintClient;
@ -1025,7 +1048,7 @@ const detailsSchema = new Schema<IKubrowPetDetailsDatabase>(
);
detailsSchema.set("toJSON", {
transform(_doc, returnedObject: Record<string, any>) {
transform(_doc, returnedObject) {
delete returnedObject.__v;
const db = returnedObject as IKubrowPetDetailsDatabase;
@ -1081,7 +1104,7 @@ EquipmentSchema.virtual("ItemId").get(function () {
EquipmentSchema.set("toJSON", {
virtuals: true,
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
delete returnedObject._id;
delete returnedObject.__v;
@ -1132,7 +1155,7 @@ pendingRecipeSchema.virtual("ItemId").get(function () {
pendingRecipeSchema.set("toJSON", {
virtuals: true,
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
delete returnedObject._id;
delete returnedObject.__v;
delete returnedObject.LongGuns;
@ -1170,7 +1193,7 @@ const infestedFoundrySchema = new Schema<IInfestedFoundryDatabase>(
);
infestedFoundrySchema.set("toJSON", {
transform(_doc, ret: Record<string, any>) {
transform(_doc, ret, _options) {
if (ret.AbilityOverrideUnlockCooldown) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
ret.AbilityOverrideUnlockCooldown = toMongoDate(ret.AbilityOverrideUnlockCooldown);
@ -1216,8 +1239,8 @@ const calenderProgressSchema = new Schema<ICalendarProgress>(
},
SeasonProgress: {
SeasonType: { type: String, required: true },
LastCompletedDayIdx: { type: Number, default: -1 },
LastCompletedChallengeDayIdx: { type: Number, default: -1 },
LastCompletedDayIdx: { type: Number, default: 0 },
LastCompletedChallengeDayIdx: { type: Number, default: 0 },
ActivatedChallenges: { type: [String], default: [] }
}
},
@ -1243,7 +1266,7 @@ const vendorPurchaseHistoryEntrySchema = new Schema<IVendorPurchaseHistoryEntryD
);
vendorPurchaseHistoryEntrySchema.set("toJSON", {
transform(_doc, obj: Record<string, any>) {
transform(_doc, obj) {
const db = obj as IVendorPurchaseHistoryEntryDatabase;
const client = obj as IVendorPurchaseHistoryEntryClient;
client.Expiry = toMongoDate(db.Expiry);
@ -1286,7 +1309,7 @@ const pendingCouponSchema = new Schema<IPendingCouponDatabase>(
);
pendingCouponSchema.set("toJSON", {
transform(_doc, ret: Record<string, any>) {
transform(_doc, ret, _options) {
(ret as IPendingCouponClient).Expiry = toMongoDate((ret as IPendingCouponDatabase).Expiry);
}
});
@ -1353,7 +1376,7 @@ const nemesisSchema = new Schema<INemesisDatabase>(
nemesisSchema.set("toJSON", {
virtuals: true,
transform(_doc, obj: Record<string, any>) {
transform(_doc, obj) {
const db = obj as INemesisDatabase;
const client = obj as INemesisClient;
@ -1383,7 +1406,7 @@ const lastSortieRewardSchema = new Schema<ILastSortieRewardDatabase>(
lastSortieRewardSchema.set("toJSON", {
virtuals: true,
transform(_doc, obj: Record<string, any>) {
transform(_doc, obj) {
const db = obj as ILastSortieRewardDatabase;
const client = obj as ILastSortieRewardClient;
@ -1425,14 +1448,6 @@ const hubNpcCustomizationSchema = new Schema<IHubNpcCustomization>(
const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
{
accountOwnerId: Schema.Types.ObjectId,
// SNS account cheats
infiniteCredits: Boolean,
infinitePlatinum: Boolean,
infiniteEndo: Boolean,
infiniteRegalAya: Boolean,
infiniteHelminthMaterials: Boolean,
SubscribedToEmails: { type: Number, default: 0 },
SubscribedToEmailsPersonalized: { type: Number, default: 0 },
RewardSeed: BigInt,
@ -1445,8 +1460,6 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
PremiumCreditsFree: { type: Number, default: 0 },
//Endo
FusionPoints: { type: Number, default: 0 },
//Dirac
CrewShipFusionPoints: { type: Number, default: 0 },
//Regal Aya
PrimeTokens: { type: Number, default: 0 },
@ -1800,7 +1813,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
);
inventorySchema.set("toJSON", {
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
delete returnedObject._id;
delete returnedObject.__v;
delete returnedObject.accountOwnerId;

View File

@ -1,5 +1,5 @@
import { IOid } from "@/src/types/commonTypes";
import { IEquipmentSelection } from "@/src/types/equipmentTypes";
import { IEquipmentSelection } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { ILoadoutConfigDatabase, ILoadoutDatabase } from "@/src/types/saveLoadoutTypes";
import { Document, Model, Schema, Types, model } from "mongoose";
@ -49,7 +49,7 @@ loadoutConfigSchema.virtual("ItemId").get(function () {
loadoutConfigSchema.set("toJSON", {
virtuals: true,
transform(_doc, ret: Record<string, any>) {
transform(_doc, ret, _options) {
delete ret._id;
delete ret.__v;
}
@ -62,7 +62,6 @@ export const loadoutSchema = new Schema<ILoadoutDatabase, loadoutModelType>({
NORMAL_PVP: [loadoutConfigSchema],
LUNARO: [loadoutConfigSchema],
OPERATOR: [loadoutConfigSchema],
GEAR: [loadoutConfigSchema],
KDRIVE: [loadoutConfigSchema],
DATAKNIFE: [loadoutConfigSchema],
MECH: [loadoutConfigSchema],
@ -72,7 +71,7 @@ export const loadoutSchema = new Schema<ILoadoutDatabase, loadoutModelType>({
});
loadoutSchema.set("toJSON", {
transform(_doc, ret: Record<string, any>) {
transform(_doc, ret, _options) {
delete ret._id;
delete ret.__v;
delete ret.loadoutOwnerId;
@ -89,7 +88,6 @@ type loadoutDocumentProps = {
NORMAL_PVP: Types.DocumentArray<ILoadoutConfigDatabase>;
LUNARO: Types.DocumentArray<ILoadoutConfigDatabase>;
OPERATOR: Types.DocumentArray<ILoadoutConfigDatabase>;
GEAR: Types.DocumentArray<ILoadoutConfigDatabase>;
KDRIVE: Types.DocumentArray<ILoadoutConfigDatabase>;
DATAKNIFE: Types.DocumentArray<ILoadoutConfigDatabase>;
MECH: Types.DocumentArray<ILoadoutConfigDatabase>;

View File

@ -1,5 +1,5 @@
import { Document, model, Schema, Types } from "mongoose";
import { ILeaderboardEntryDatabase } from "@/src/types/leaderboardTypes";
import { ILeaderboardEntryDatabase } from "../types/leaderboardTypes";
const leaderboardEntrySchema = new Schema<ILeaderboardEntryDatabase>(
{

View File

@ -32,7 +32,7 @@ const databaseAccountSchema = new Schema<IDatabaseAccountJson>(
);
databaseAccountSchema.set("toJSON", {
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
delete returnedObject._id;
delete returnedObject.__v;
},

View File

@ -1,22 +1,19 @@
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
import { colorSchema } from "@/src/models/inventoryModels/inventoryModel";
import { IOrbiter, IPersonalRoomsDatabase, PersonalRoomsModelType } from "@/src/types/personalRoomsTypes";
import {
IApartmentDatabase,
IFavouriteLoadoutDatabase,
IGardeningDatabase,
IOrbiterClient,
IOrbiterDatabase,
IPersonalRoomsDatabase,
IPictureFrameInfo,
IPlacedDecosDatabase,
IPlantClient,
IPlantDatabase,
IPlanterDatabase,
IPictureFrameInfo,
IRoom,
ITailorShopDatabase,
PersonalRoomsModelType
} from "@/src/types/personalRoomsTypes";
IApartmentDatabase,
IPlanterDatabase,
IPlantDatabase,
IPlantClient
} from "@/src/types/shipTypes";
import { Schema, Types, model } from "mongoose";
import { colorSchema, shipCustomizationSchema } from "@/src/models/commonModel";
export const pictureFrameInfoSchema = new Schema<IPictureFrameInfo>(
{
@ -55,7 +52,7 @@ placedDecosSchema.virtual("id").get(function (this: IPlacedDecosDatabase) {
placedDecosSchema.set("toJSON", {
virtuals: true,
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
delete returnedObject._id;
}
});
@ -78,7 +75,7 @@ const favouriteLoadoutSchema = new Schema<IFavouriteLoadoutDatabase>(
);
favouriteLoadoutSchema.set("toJSON", {
virtuals: true,
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
returnedObject.LoadoutId = toOid(returnedObject.LoadoutId);
}
@ -95,7 +92,7 @@ const plantSchema = new Schema<IPlantDatabase>(
plantSchema.set("toJSON", {
virtuals: true,
transform(_doc, obj: Record<string, any>) {
transform(_doc, obj) {
const client = obj as IPlantClient;
const db = obj as IPlantDatabase;
@ -122,9 +119,7 @@ const apartmentSchema = new Schema<IApartmentDatabase>(
{
Rooms: [roomSchema],
FavouriteLoadouts: [favouriteLoadoutSchema],
Gardening: gardeningSchema,
VideoWallBackdrop: String,
Soundscape: String
Gardening: gardeningSchema
},
{ _id: false }
);
@ -142,11 +137,10 @@ const apartmentDefault: IApartmentDatabase = {
}
};
const orbiterSchema = new Schema<IOrbiterDatabase>(
const orbiterSchema = new Schema<IOrbiter>(
{
Features: [String],
Rooms: [roomSchema],
ShipInterior: shipCustomizationSchema,
VignetteFish: { type: [String], default: undefined },
FavouriteLoadoutId: Schema.Types.ObjectId,
Wallpaper: String,
@ -156,18 +150,7 @@ const orbiterSchema = new Schema<IOrbiterDatabase>(
},
{ _id: false }
);
orbiterSchema.set("toJSON", {
virtuals: true,
transform(_doc, obj: Record<string, any>) {
const db = obj as IOrbiterDatabase;
const client = obj as IOrbiterClient;
if (db.FavouriteLoadoutId) {
client.FavouriteLoadoutId = toOid(db.FavouriteLoadoutId);
}
}
});
const orbiterDefault: IOrbiterDatabase = {
const orbiterDefault: IOrbiter = {
Features: ["/Lotus/Types/Items/ShipFeatureItems/EarthNavigationFeatureItem"], //TODO: potentially remove after missionstarting gear
Rooms: [
{ Name: "AlchemyRoom", MaxCapacity: 1600 },
@ -214,6 +197,7 @@ const tailorShopDefault: ITailorShopDatabase = {
export const personalRoomsSchema = new Schema<IPersonalRoomsDatabase>({
personalRoomsOwnerId: Schema.Types.ObjectId,
activeShipId: Schema.Types.ObjectId,
ShipInteriorColors: colorSchema,
Ship: { type: orbiterSchema, default: orbiterDefault },
Apartment: { type: apartmentSchema, default: apartmentDefault },
TailorShop: { type: tailorShopSchema, default: tailorShopDefault }

View File

@ -1,7 +1,7 @@
import { Document, Schema, Types, model } from "mongoose";
import { IShipDatabase } from "@/src/types/shipTypes";
import { IShipDatabase } from "../types/shipTypes";
import { toOid } from "@/src/helpers/inventoryHelpers";
import { colorSchema } from "@/src/models/commonModel";
import { colorSchema } from "@/src/models/inventoryModels/inventoryModel";
import { IShipInventory } from "@/src/types/inventoryTypes/inventoryTypes";
const shipSchema = new Schema<IShipDatabase>(
@ -22,7 +22,7 @@ shipSchema.virtual("ItemId").get(function () {
shipSchema.set("toJSON", {
virtuals: true,
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
const shipResponse = returnedObject as IShipInventory;
const shipDatabase = returnedObject as IShipDatabase;
delete returnedObject._id;

View File

@ -101,7 +101,7 @@ const statsSchema = new Schema<IStatsDatabase>({
});
statsSchema.set("toJSON", {
transform(_document, returnedObject: Record<string, any>) {
transform(_document, returnedObject) {
delete returnedObject._id;
delete returnedObject.__v;
delete returnedObject.accountOwnerId;

View File

@ -10,7 +10,6 @@ import { addPendingFriendController } from "@/src/controllers/api/addPendingFrie
import { addToAllianceController } from "@/src/controllers/api/addToAllianceController";
import { addToGuildController } from "@/src/controllers/api/addToGuildController";
import { adoptPetController } from "@/src/controllers/api/adoptPetController";
import { apartmentController } from "@/src/controllers/api/apartmentController";
import { arcaneCommonController } from "@/src/controllers/api/arcaneCommonController";
import { archonFusionController } from "@/src/controllers/api/archonFusionController";
import { artifactsController } from "@/src/controllers/api/artifactsController";
@ -62,12 +61,10 @@ import { getFriendsController } from "@/src/controllers/api/getFriendsController
import { getGuildContributionsController } from "@/src/controllers/api/getGuildContributionsController";
import { getGuildController } from "@/src/controllers/api/getGuildController";
import { getGuildDojoController } from "@/src/controllers/api/getGuildDojoController";
import { getGuildEventScoreController } from "@/src/controllers/api/getGuildEventScore";
import { getGuildLogController } from "@/src/controllers/api/getGuildLogController";
import { getIgnoredUsersController } from "@/src/controllers/api/getIgnoredUsersController";
import { getNewRewardSeedController } from "@/src/controllers/api/getNewRewardSeedController";
import { getProfileViewingDataPostController } from "@/src/controllers/dynamic/getProfileViewingDataController";
import { getPastWeeklyChallengesController } from "@/src/controllers/api/getPastWeeklyChallengesController";
import { getShipController } from "@/src/controllers/api/getShipController";
import { getVendorInfoController } from "@/src/controllers/api/getVendorInfoController";
import { getVoidProjectionRewardsController } from "@/src/controllers/api/getVoidProjectionRewardsController";
@ -115,7 +112,6 @@ import { removeFromGuildController } from "@/src/controllers/api/removeFromGuild
import { removeIgnoredUserController } from "@/src/controllers/api/removeIgnoredUserController";
import { renamePetController } from "@/src/controllers/api/renamePetController";
import { rerollRandomModController } from "@/src/controllers/api/rerollRandomModController";
import { resetQuestProgressController } from "@/src/controllers/api/resetQuestProgressController";
import { retrievePetFromStasisController } from "@/src/controllers/api/retrievePetFromStasisController";
import { saveDialogueController } from "@/src/controllers/api/saveDialogueController";
import { saveLoadoutController } from "@/src/controllers/api/saveLoadoutController";
@ -171,7 +167,6 @@ const apiRouter = express.Router();
// get
apiRouter.get("/abandonLibraryDailyTask.php", abandonLibraryDailyTaskController);
apiRouter.get("/abortDojoComponentDestruction.php", abortDojoComponentDestructionController);
apiRouter.get("/apartment.php", apartmentController);
apiRouter.get("/cancelGuildAdvertisement.php", cancelGuildAdvertisementController);
apiRouter.get("/changeDojoRoot.php", changeDojoRootController);
apiRouter.get("/changeGuildRank.php", changeGuildRankController);
@ -193,12 +188,10 @@ apiRouter.get("/getFriends.php", getFriendsController);
apiRouter.get("/getGuild.php", getGuildController);
apiRouter.get("/getGuildContributions.php", getGuildContributionsController);
apiRouter.get("/getGuildDojo.php", getGuildDojoController);
apiRouter.get("/getGuildEventScore.php", getGuildEventScoreController);
apiRouter.get("/getGuildLog.php", getGuildLogController);
apiRouter.get("/getIgnoredUsers.php", getIgnoredUsersController);
apiRouter.get("/getMessages.php", inboxController); // unsure if this is correct, but needed for U17
apiRouter.get("/getNewRewardSeed.php", getNewRewardSeedController);
apiRouter.get("/getPastWeeklyChallenges.php", getPastWeeklyChallengesController)
apiRouter.get("/getShip.php", getShipController);
apiRouter.get("/getShipDecos.php", (_req, res) => { res.end(); }); // needed to log in on U22.8
apiRouter.get("/getVendorInfo.php", getVendorInfoController);
@ -216,7 +209,6 @@ apiRouter.get("/questControl.php", questControlController);
apiRouter.get("/queueDojoComponentDestruction.php", queueDojoComponentDestructionController);
apiRouter.get("/removeFriend.php", removeFriendGetController);
apiRouter.get("/removeFromAlliance.php", removeFromAllianceController);
apiRouter.get("/resetQuestProgress.php", resetQuestProgressController);
apiRouter.get("/setActiveQuest.php", setActiveQuestController);
apiRouter.get("/setActiveShip.php", setActiveShipController);
apiRouter.get("/setAllianceGuildPermissions.php", setAllianceGuildPermissionsController);

View File

@ -15,7 +15,6 @@ import { webuiFileChangeDetectedController } from "@/src/controllers/custom/webu
import { completeAllMissionsController } from "@/src/controllers/custom/completeAllMissionsController";
import { addMissingHelminthBlueprintsController } from "@/src/controllers/custom/addMissingHelminthBlueprintsController";
import { abilityOverrideController } from "@/src/controllers/custom/abilityOverrideController";
import { createAccountController } from "@/src/controllers/custom/createAccountController";
import { createMessageController } from "@/src/controllers/custom/createMessageController";
import { addCurrencyController } from "@/src/controllers/custom/addCurrencyController";
@ -26,9 +25,6 @@ import { manageQuestsController } from "@/src/controllers/custom/manageQuestsCon
import { setEvolutionProgressController } from "@/src/controllers/custom/setEvolutionProgressController";
import { setBoosterController } from "@/src/controllers/custom/setBoosterController";
import { updateFingerprintController } from "@/src/controllers/custom/updateFingerprintController";
import { changeModularPartsController } from "@/src/controllers/custom/changeModularPartsController";
import { editSuitInvigorationUpgradeController } from "@/src/controllers/custom/editSuitInvigorationUpgradeController";
import { setAccountCheatController } from "@/src/controllers/custom/setAccountCheatController";
import { getConfigController, setConfigController } from "@/src/controllers/custom/configController";
@ -49,7 +45,6 @@ customRouter.get("/webuiFileChangeDetected", webuiFileChangeDetectedController);
customRouter.get("/completeAllMissions", completeAllMissionsController);
customRouter.get("/addMissingHelminthBlueprints", addMissingHelminthBlueprintsController);
customRouter.post("/abilityOverride", abilityOverrideController);
customRouter.post("/createAccount", createAccountController);
customRouter.post("/createMessage", createMessageController);
customRouter.post("/addCurrency", addCurrencyController);
@ -60,9 +55,6 @@ customRouter.post("/manageQuests", manageQuestsController);
customRouter.post("/setEvolutionProgress", setEvolutionProgressController);
customRouter.post("/setBooster", setBoosterController);
customRouter.post("/updateFingerprint", updateFingerprintController);
customRouter.post("/changeModularParts", changeModularPartsController);
customRouter.post("/editSuitInvigorationUpgrade", editSuitInvigorationUpgradeController);
customRouter.post("/setAccountCheat", setAccountCheatController);
customRouter.post("/getConfig", getConfigController);
customRouter.post("/setConfig", setConfigController);

View File

@ -2,7 +2,6 @@ import fs from "fs";
import path from "path";
import { repoDir } from "@/src/helpers/pathHelper";
import { args } from "@/src/helpers/commandLineArguments";
import { Inbox } from "@/src/models/inboxModel";
export interface IConfig {
mongodbUrl: string;
@ -20,6 +19,11 @@ export interface IConfig {
skipTutorial?: boolean;
skipAllDialogue?: boolean;
unlockAllScans?: boolean;
infiniteCredits?: boolean;
infinitePlatinum?: boolean;
infiniteEndo?: boolean;
infiniteRegalAya?: boolean;
infiniteHelminthMaterials?: boolean;
claimingBlueprintRefundsIngredients?: boolean;
dontSubtractPurchaseCreditCost?: boolean;
dontSubtractPurchasePlatinumCost?: boolean;
@ -76,25 +80,8 @@ export interface IConfig {
creditBoost?: boolean;
affinityBoost?: boolean;
resourceBoost?: boolean;
tennoLiveRelay?: boolean;
baroTennoConRelay?: boolean;
wolfHunt?: boolean;
longShadow?: boolean;
hallowedFlame?: boolean;
hallowedNightmares?: boolean;
hallowedNightmaresRewardsOverride?: number;
proxyRebellion?: boolean;
proxyRebellionRewardsOverride?: number;
starDays?: boolean;
galleonOfGhouls?: number;
ghoulEmergenceOverride?: boolean;
plagueStarOverride?: boolean;
starDaysOverride?: boolean;
dogDaysOverride?: boolean;
dogDaysRewardsOverride?: number;
bellyOfTheBeast?: boolean;
bellyOfTheBeastProgressOverride?: number;
eightClaw?: boolean;
eightClawProgressOverride?: number;
eidolonOverride?: string;
vallisOverride?: string;
duviriOverride?: string;
@ -102,8 +89,6 @@ export interface IConfig {
allTheFissures?: string;
circuitGameModes?: string[];
darvoStockMultiplier?: number;
varziaOverride?: string;
varziaFullyStocked?: boolean;
};
dev?: {
keepVendorsExpired?: boolean;
@ -126,26 +111,9 @@ export const loadConfig = (): void => {
// Set all values to undefined now so if the new config.json omits some fields that were previously present, it's correct in-memory.
for (const key of Object.keys(config)) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
(config as any)[key] = undefined;
}
Object.assign(config, newConfig);
};
export const syncConfigWithDatabase = (): void => {
// Event messages are deleted after endDate. Since we don't use beginDate/endDate and instead have config toggles, we need to delete the messages once those bools are false.
// Also, for some reason, I can't just do `Inbox.deleteMany(...)`; - it needs this whole circus.
if (!config.worldState?.creditBoost) {
void Inbox.deleteMany({ globaUpgradeId: "5b23106f283a555109666672" }).then(() => {});
}
if (!config.worldState?.affinityBoost) {
void Inbox.deleteMany({ globaUpgradeId: "5b23106f283a555109666673" }).then(() => {});
}
if (!config.worldState?.resourceBoost) {
void Inbox.deleteMany({ globaUpgradeId: "5b23106f283a555109666674" }).then(() => {});
}
if (!config.worldState?.galleonOfGhouls) {
void Inbox.deleteMany({ goalTag: "GalleonRobbery" }).then(() => {});
}
};

Some files were not shown because too many files have changed in this diff Show More