forked from OpenWF/SpaceNinjaServer
Compare commits
6 Commits
main
...
janisslsm/
Author | SHA1 | Date | |
---|---|---|---|
![]() |
225cd83cea | ||
![]() |
e824087034 | ||
![]() |
fd2027b071 | ||
![]() |
0af98bc6c2 | ||
![]() |
3403d496b4 | ||
![]() |
58b1cfc30f |
@ -1,5 +0,0 @@
|
||||
**/.dockerignore
|
||||
**/.git
|
||||
Dockerfile*
|
||||
.*
|
||||
docker-data/
|
4
.env.example
Normal file
4
.env.example
Normal file
@ -0,0 +1,4 @@
|
||||
# Docker may need a .env file for the following settings:
|
||||
DATABASE_PORT=27017
|
||||
DATABASE_USERNAME=root
|
||||
DATABASE_PASSWORD=database
|
@ -12,6 +12,7 @@
|
||||
},
|
||||
"rules": {
|
||||
"@typescript-eslint/explicit-function-return-type": "warn",
|
||||
"@typescript-eslint/explicit-module-boundary-types": "warn",
|
||||
"@typescript-eslint/restrict-template-expressions": "warn",
|
||||
"@typescript-eslint/restrict-plus-operands": "warn",
|
||||
"@typescript-eslint/no-unsafe-member-access": "warn",
|
||||
@ -22,13 +23,10 @@
|
||||
"@typescript-eslint/no-unsafe-assignment": "warn",
|
||||
"@typescript-eslint/no-explicit-any": "warn",
|
||||
"@typescript-eslint/no-loss-of-precision": "warn",
|
||||
"@typescript-eslint/no-unnecessary-condition": "warn",
|
||||
"no-case-declarations": "warn",
|
||||
"prettier/prettier": "error",
|
||||
"@typescript-eslint/semi": "error",
|
||||
"no-mixed-spaces-and-tabs": "error",
|
||||
"require-await": "off",
|
||||
"@typescript-eslint/require-await": "error"
|
||||
"no-mixed-spaces-and-tabs": "error"
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
|
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@ -17,5 +17,6 @@ jobs:
|
||||
node-version: ${{ matrix.version }}
|
||||
- run: npm ci
|
||||
- run: cp config.json.example config.json
|
||||
- run: echo '{"version":"","buildLabel":"","matchmakingBuildId":""}' > static/data/buildConfig.json
|
||||
- run: npm run build
|
||||
- run: npm run lint
|
||||
|
24
.github/workflows/docker.yml
vendored
24
.github/workflows/docker.yml
vendored
@ -1,24 +0,0 @@
|
||||
name: Build Docker image
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Docker buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Log in to container registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: openwf
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
openwf/spaceninjaserver:latest
|
||||
openwf/spaceninjaserver:${{ github.sha }}
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -15,7 +15,4 @@ yarn.lock
|
||||
/logs
|
||||
|
||||
# MongoDB VSCode extension playground scripts
|
||||
/database_scripts
|
||||
|
||||
# Default Docker directory
|
||||
/docker-data
|
||||
/database_scripts
|
19
.vscode/launch.json
vendored
19
.vscode/launch.json
vendored
@ -1,19 +0,0 @@
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Debug and Watch",
|
||||
"runtimeArgs": ["-r", "tsconfig-paths/register", "-r", "ts-node/register", "--watch-path", "src"],
|
||||
"args": ["${workspaceFolder}/src/index.ts"],
|
||||
"console": "integratedTerminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
//can use "console": "internalConsole" for VS Code's Debug Console. For that, forceConsole in logger.ts is needed to be true
|
||||
//"internalConsoleOptions": "openOnSessionStart" can be useful then
|
29
Dockerfile
29
Dockerfile
@ -1,28 +1,5 @@
|
||||
FROM node:18-alpine3.19
|
||||
FROM mongo as base
|
||||
|
||||
ENV APP_MONGODB_URL=mongodb://mongodb:27017/openWF
|
||||
ENV APP_MY_ADDRESS=localhost
|
||||
ENV APP_HTTP_PORT=80
|
||||
ENV APP_HTTPS_PORT=443
|
||||
ENV APP_AUTO_CREATE_ACCOUNT=true
|
||||
ENV APP_SKIP_STORY_MODE_CHOICE=true
|
||||
ENV APP_SKIP_TUTORIAL=true
|
||||
ENV APP_SKIP_ALL_DIALOGUE=true
|
||||
ENV APP_UNLOCK_ALL_SCANS=true
|
||||
ENV APP_UNLOCK_ALL_MISSIONS=true
|
||||
ENV APP_UNLOCK_ALL_QUESTS=true
|
||||
ENV APP_COMPLETE_ALL_QUESTS=true
|
||||
ENV APP_INFINITE_RESOURCES=true
|
||||
ENV APP_UNLOCK_ALL_SHIP_FEATURES=true
|
||||
ENV APP_UNLOCK_ALL_SHIP_DECORATIONS=true
|
||||
ENV APP_UNLOCK_ALL_FLAVOUR_ITEMS=true
|
||||
ENV APP_UNLOCK_ALL_SKINS=true
|
||||
ENV APP_UNIVERSAL_POLARITY_EVERYWHERE=true
|
||||
ENV APP_SPOOF_MASTERY_RANK=-1
|
||||
EXPOSE 27017
|
||||
|
||||
RUN apk add --no-cache bash sed wget jq
|
||||
|
||||
COPY . /app
|
||||
WORKDIR /app
|
||||
|
||||
ENTRYPOINT ["/app/docker-entrypoint.sh"]
|
||||
CMD ["mongod"]
|
@ -1,8 +1,3 @@
|
||||
# Space Ninja Server
|
||||
|
||||
More information for the moment here: [https://discord.gg/PNNZ3asUuY](https://discord.gg/PNNZ3asUuY)
|
||||
|
||||
## config.json
|
||||
|
||||
- `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 ]`.
|
||||
|
@ -1,24 +0,0 @@
|
||||
@echo off
|
||||
|
||||
echo Updating SpaceNinjaServer...
|
||||
git config remote.origin.url https://openwf.io/SpaceNinjaServer.git
|
||||
git fetch --prune
|
||||
git reset --hard origin/main
|
||||
|
||||
if exist static\data\0\ (
|
||||
echo Updating stripped assets...
|
||||
cd static\data\0\
|
||||
git pull
|
||||
cd ..\..\..\
|
||||
)
|
||||
|
||||
echo Updating dependencies...
|
||||
call npm i
|
||||
|
||||
call npm run build
|
||||
call npm run start
|
||||
|
||||
echo SpaceNinjaServer seems to have crashed.
|
||||
:a
|
||||
pause > nul
|
||||
goto a
|
@ -1,31 +1,26 @@
|
||||
{
|
||||
"mongodbUrl": "mongodb://127.0.0.1:27017/openWF",
|
||||
"mongodbUrl": "mongodb://127.0.0.1:27017/openWF_2013",
|
||||
"logger": {
|
||||
"files": true,
|
||||
"level": "trace"
|
||||
"level": "trace",
|
||||
"__valid_levels": "fatal, error, warn, info, http, debug, trace"
|
||||
},
|
||||
"myAddress": "localhost",
|
||||
"httpPort": 80,
|
||||
"httpsPort": 443,
|
||||
"administratorNames": [],
|
||||
"autoCreateAccount": true,
|
||||
"skipStoryModeChoice": true,
|
||||
"skipTutorial": true,
|
||||
"skipAllDialogue": true,
|
||||
"unlockAllScans": true,
|
||||
"unlockAllMissions": true,
|
||||
"infiniteCredits": true,
|
||||
"infinitePlatinum": true,
|
||||
"infiniteEndo": true,
|
||||
"infiniteRegalAya": true,
|
||||
"unlockAllQuests": true,
|
||||
"completeAllQuests": false,
|
||||
"infiniteResources": true,
|
||||
"unlockAllShipFeatures": true,
|
||||
"unlockAllShipDecorations": true,
|
||||
"unlockAllFlavourItems": true,
|
||||
"unlockAllSkins": true,
|
||||
"unlockAllCapturaScenes": true,
|
||||
"universalPolarityEverywhere": true,
|
||||
"unlockDoubleCapacityPotatoesEverywhere": true,
|
||||
"unlockExilusEverywhere": true,
|
||||
"unlockArcanesEverywhere": true,
|
||||
"noDailyStandingLimits": true,
|
||||
"spoofMasteryRank": -1
|
||||
}
|
||||
|
@ -1,43 +1,24 @@
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
spaceninjaserver:
|
||||
# build: .
|
||||
image: openwf/spaceninjaserver:latest
|
||||
environment:
|
||||
APP_MONGODB_URL: mongodb://openwfagent:spaceninjaserver@mongodb:27017/
|
||||
|
||||
# Following environment variables are set to default image values.
|
||||
# Uncomment to edit.
|
||||
|
||||
# APP_MY_ADDRESS: localhost
|
||||
# APP_HTTP_PORT: 80
|
||||
# APP_HTTPS_PORT: 443
|
||||
# APP_AUTO_CREATE_ACCOUNT: true
|
||||
# APP_SKIP_STORY_MODE_CHOICE: true
|
||||
# APP_SKIP_TUTORIAL: true
|
||||
# APP_SKIP_ALL_DIALOGUE: true
|
||||
# APP_UNLOCK_ALL_SCANS: true
|
||||
# APP_UNLOCK_ALL_MISSIONS: true
|
||||
# APP_UNLOCK_ALL_QUESTS: true
|
||||
# APP_COMPLETE_ALL_QUESTS: true
|
||||
# APP_INFINITE_RESOURCES: true
|
||||
# APP_UNLOCK_ALL_SHIP_FEATURES: true
|
||||
# APP_UNLOCK_ALL_SHIP_DECORATIONS: true
|
||||
# APP_UNLOCK_ALL_FLAVOUR_ITEMS: true
|
||||
# APP_UNLOCK_ALL_SKINS: true
|
||||
# APP_UNIVERSAL_POLARITY_EVERYWHERE: true
|
||||
# APP_SPOOF_MASTERY_RANK: -1
|
||||
volumes:
|
||||
- ./docker-data/static:/app/static/data
|
||||
- ./docker-data/logs:/app/logs
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
depends_on:
|
||||
- mongodb
|
||||
mongodb:
|
||||
image: docker.io/library/mongo:8.0.0-noble
|
||||
container_name: mongodb
|
||||
image: mongodb
|
||||
restart: always
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
target: base
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: openwfagent
|
||||
MONGO_INITDB_ROOT_PASSWORD: spaceninjaserver
|
||||
volumes:
|
||||
- ./docker-data/database:/data/db
|
||||
MONGO_INITDB_ROOT_USERNAME: ${DATABASE_USERNAME}
|
||||
MONGO_INITDB_ROOT_PASSWORD: ${DATABASE_PASSWORD}
|
||||
ports:
|
||||
- ${DATABASE_PORT}:${DATABASE_PORT}
|
||||
expose:
|
||||
- "${DATABASE_PORT}"
|
||||
networks:
|
||||
- docker
|
||||
|
||||
networks:
|
||||
docker:
|
||||
external: true
|
||||
|
@ -1,23 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Set up the configuration file using environment variables.
|
||||
echo '{
|
||||
"logger": {
|
||||
"files": true,
|
||||
"level": "trace",
|
||||
"__valid_levels": "fatal, error, warn, info, http, debug, trace"
|
||||
}
|
||||
}
|
||||
' > config.json
|
||||
|
||||
for config in $(env | grep "APP_")
|
||||
do
|
||||
var=$(echo "${config}" | tr '[:upper:]' '[:lower:]' | sed 's/app_//g' | sed -E 's/_([a-z])/\U\1/g' | sed 's/=.*//g')
|
||||
val=$(echo "${config}" | sed 's/.*=//g')
|
||||
jq --arg variable "$var" --arg value "$val" '.[$variable] += try [$value|fromjson][] catch $value' config.json > config.tmp
|
||||
mv config.tmp config.json
|
||||
done
|
||||
|
||||
npm install
|
||||
exec npm run dev
|
2184
package-lock.json
generated
2184
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
26
package.json
26
package.json
@ -9,32 +9,30 @@
|
||||
"build": "tsc && copyfiles static/webui/** build",
|
||||
"lint": "eslint --ext .ts .",
|
||||
"lint:fix": "eslint --fix --ext .ts .",
|
||||
"prettier": "prettier --write .",
|
||||
"update-translations": "cd scripts && node update-translations.js"
|
||||
"prettier": "prettier --write ."
|
||||
},
|
||||
"license": "GNU",
|
||||
"dependencies": {
|
||||
"copyfiles": "^2.4.1",
|
||||
"express": "^5",
|
||||
"mongoose": "^8.9.4",
|
||||
"warframe-public-export-plus": "^0.5.30",
|
||||
"warframe-riven-info": "^0.1.2",
|
||||
"winston": "^3.17.0",
|
||||
"express": "^5.0.0-beta.3",
|
||||
"mongoose": "^8.4.5",
|
||||
"warframe-public-export-plus": "^0.4.4",
|
||||
"warframe-riven-info": "^0.1.1",
|
||||
"winston": "^3.13.0",
|
||||
"winston-daily-rotate-file": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^5",
|
||||
"@types/express": "^4.17.20",
|
||||
"@types/morgan": "^1.9.9",
|
||||
"@typescript-eslint/eslint-plugin": "^7.18",
|
||||
"@typescript-eslint/parser": "^7.18",
|
||||
"@typescript-eslint/eslint-plugin": "^7.14",
|
||||
"@typescript-eslint/parser": "^7.14",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-plugin-prettier": "^5.2.3",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"morgan": "^1.10.0",
|
||||
"prettier": "^3.4.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"prettier": "^3.3.2",
|
||||
"ts-node-dev": "^2.0.0",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"typescript": ">=4.7.4 <5.6.0"
|
||||
"typescript": "^5.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.15.0",
|
||||
|
@ -1,46 +0,0 @@
|
||||
// Based on http://209.141.38.3/OpenWF/Translations/src/branch/main/update.php
|
||||
// Converted via ChatGPT-4o
|
||||
|
||||
const fs = require("fs");
|
||||
|
||||
function extractStrings(content) {
|
||||
const regex = /([a-zA-Z_]+): `([^`]*)`,/g;
|
||||
let matches;
|
||||
const strings = {};
|
||||
while ((matches = regex.exec(content)) !== null) {
|
||||
strings[matches[1]] = matches[2];
|
||||
}
|
||||
return strings;
|
||||
}
|
||||
|
||||
const source = fs.readFileSync("../static/webui/translations/en.js", "utf8");
|
||||
const sourceStrings = extractStrings(source);
|
||||
const sourceLines = source.split("\n");
|
||||
|
||||
fs.readdirSync("../static/webui/translations").forEach(file => {
|
||||
if (fs.lstatSync(`../static/webui/translations/${file}`).isFile() && file !== "en.js") {
|
||||
const content = fs.readFileSync(`../static/webui/translations/${file}`, "utf8");
|
||||
const targetStrings = extractStrings(content);
|
||||
const contentLines = content.split("\n");
|
||||
|
||||
const fileHandle = fs.openSync(`../static/webui/translations/${file}`, "w");
|
||||
fs.writeSync(fileHandle, contentLines[0] + "\n");
|
||||
|
||||
sourceLines.forEach(line => {
|
||||
const strings = extractStrings(line);
|
||||
if (Object.keys(strings).length > 0) {
|
||||
Object.entries(strings).forEach(([key, value]) => {
|
||||
if (targetStrings.hasOwnProperty(key)) {
|
||||
fs.writeSync(fileHandle, ` ${key}: \`${targetStrings[key]}\`,\n`);
|
||||
} else {
|
||||
fs.writeSync(fileHandle, ` ${key}: \`[UNTRANSLATED] ${value}\`,\n`);
|
||||
}
|
||||
});
|
||||
} else if (line.length) {
|
||||
fs.writeSync(fileHandle, line + "\n");
|
||||
}
|
||||
});
|
||||
|
||||
fs.closeSync(fileHandle);
|
||||
}
|
||||
});
|
43
src/app.ts
43
src/app.ts
@ -1,34 +1,65 @@
|
||||
import express from "express";
|
||||
|
||||
import bodyParser from "body-parser";
|
||||
import { unknownEndpointHandler } from "@/src/middleware/middleware";
|
||||
import { requestLogger } from "@/src/middleware/morgenMiddleware";
|
||||
import { errorHandler } from "@/src/middleware/errorHandler";
|
||||
|
||||
import { apiRouter } from "@/src/routes/api";
|
||||
//import { testRouter } from "@/src/routes/test";
|
||||
import { cacheRouter } from "@/src/routes/cache";
|
||||
import bodyParser from "body-parser";
|
||||
|
||||
import { steamPacksController } from "@/src/controllers/misc/steamPacksController";
|
||||
import { customRouter } from "@/src/routes/custom";
|
||||
import { dynamicController } from "@/src/routes/dynamic";
|
||||
import { payRouter } from "@/src/routes/pay";
|
||||
import { statsRouter } from "@/src/routes/stats";
|
||||
import { webuiRouter } from "@/src/routes/webui";
|
||||
import { connectDatabase } from "@/src/services/mongoService";
|
||||
import { registerLogFileCreationListener } from "@/src/utils/logger";
|
||||
import * as zlib from "zlib";
|
||||
|
||||
void registerLogFileCreationListener();
|
||||
void connectDatabase();
|
||||
|
||||
const app = express();
|
||||
|
||||
app.use(function (req, _res, next) {
|
||||
const buffer: Buffer[] = [];
|
||||
req.on("data", function (chunk: Buffer) {
|
||||
if (chunk !== undefined && chunk.length > 2 && chunk[0] == 0x1f && chunk[1] == 0x8b) {
|
||||
buffer.push(Buffer.from(chunk));
|
||||
}
|
||||
});
|
||||
|
||||
req.on("end", function () {
|
||||
zlib.gunzip(Buffer.concat(buffer), function (_err, dezipped) {
|
||||
if (typeof dezipped != "undefined") {
|
||||
req.body = dezipped.toString("utf-8");
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
app.use(bodyParser.raw());
|
||||
app.use(express.json({ limit: "4mb" }));
|
||||
app.use(express.json());
|
||||
app.use(bodyParser.text());
|
||||
app.use(requestLogger);
|
||||
//app.use(requestLogger);
|
||||
|
||||
app.use("/api", apiRouter);
|
||||
//app.use("/test", testRouter);
|
||||
app.use("/", cacheRouter);
|
||||
app.use("/custom", customRouter);
|
||||
app.use("/:id/dynamic", dynamicController);
|
||||
app.use("/pay", payRouter);
|
||||
|
||||
app.post("/pay/steamPacks.php", steamPacksController);
|
||||
app.use("/stats", statsRouter);
|
||||
|
||||
app.use("/", webuiRouter);
|
||||
|
||||
app.use(unknownEndpointHandler);
|
||||
app.use(errorHandler);
|
||||
|
||||
//app.use(errorHandler)
|
||||
|
||||
export { app };
|
||||
|
@ -1,98 +0,0 @@
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { addMods, getInventory } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getRandomElement, getRandomInt, getRandomReward, IRngResult } from "@/src/services/rngService";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { RequestHandler } from "express";
|
||||
import { ExportUpgrades } from "warframe-public-export-plus";
|
||||
|
||||
export const activateRandomModController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const request = getJSONfromString<IActiveRandomModRequest>(String(req.body));
|
||||
addMods(inventory, [
|
||||
{
|
||||
ItemType: request.ItemType,
|
||||
ItemCount: -1
|
||||
}
|
||||
]);
|
||||
const rivenType = getRandomElement(rivenRawToRealWeighted[request.ItemType]);
|
||||
const challenge = getRandomElement(ExportUpgrades[rivenType].availableChallenges!);
|
||||
const fingerprintChallenge: IRandomModChallenge = {
|
||||
Type: challenge.fullName,
|
||||
Progress: 0,
|
||||
Required: getRandomInt(challenge.countRange[0], challenge.countRange[1])
|
||||
};
|
||||
if (Math.random() < challenge.complicationChance) {
|
||||
const complicationsAsRngResults: IRngResult[] = [];
|
||||
for (const complication of challenge.complications) {
|
||||
complicationsAsRngResults.push({
|
||||
type: complication.fullName,
|
||||
itemCount: 1,
|
||||
probability: complication.weight
|
||||
});
|
||||
}
|
||||
fingerprintChallenge.Complication = getRandomReward(complicationsAsRngResults)!.type;
|
||||
logger.debug(
|
||||
`riven rolled challenge ${fingerprintChallenge.Type} with complication ${fingerprintChallenge.Complication}`
|
||||
);
|
||||
const complication = challenge.complications.find(x => x.fullName == fingerprintChallenge.Complication)!;
|
||||
fingerprintChallenge.Required *= complication.countMultiplier;
|
||||
} else {
|
||||
logger.debug(`riven rolled challenge ${fingerprintChallenge.Type}`);
|
||||
}
|
||||
const upgradeIndex =
|
||||
inventory.Upgrades.push({
|
||||
ItemType: rivenType,
|
||||
UpgradeFingerprint: JSON.stringify({ challenge: fingerprintChallenge })
|
||||
}) - 1;
|
||||
await inventory.save();
|
||||
res.json({
|
||||
NewMod: inventory.Upgrades[upgradeIndex].toJSON()
|
||||
});
|
||||
};
|
||||
|
||||
interface IActiveRandomModRequest {
|
||||
ItemType: string;
|
||||
}
|
||||
|
||||
interface IRandomModChallenge {
|
||||
Type: string;
|
||||
Progress: number;
|
||||
Required: number;
|
||||
Complication?: string;
|
||||
}
|
||||
|
||||
const rivenRawToRealWeighted: Record<string, string[]> = {
|
||||
"/Lotus/Upgrades/Mods/Randomized/RawArchgunRandomMod": [
|
||||
"/Lotus/Upgrades/Mods/Randomized/LotusArchgunRandomModRare"
|
||||
],
|
||||
"/Lotus/Upgrades/Mods/Randomized/RawMeleeRandomMod": [
|
||||
"/Lotus/Upgrades/Mods/Randomized/PlayerMeleeWeaponRandomModRare"
|
||||
],
|
||||
"/Lotus/Upgrades/Mods/Randomized/RawModularMeleeRandomMod": [
|
||||
"/Lotus/Upgrades/Mods/Randomized/LotusModularMeleeRandomModRare"
|
||||
],
|
||||
"/Lotus/Upgrades/Mods/Randomized/RawModularPistolRandomMod": [
|
||||
"/Lotus/Upgrades/Mods/Randomized/LotusModularPistolRandomModRare"
|
||||
],
|
||||
"/Lotus/Upgrades/Mods/Randomized/RawPistolRandomMod": ["/Lotus/Upgrades/Mods/Randomized/LotusPistolRandomModRare"],
|
||||
"/Lotus/Upgrades/Mods/Randomized/RawRifleRandomMod": ["/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare"],
|
||||
"/Lotus/Upgrades/Mods/Randomized/RawShotgunRandomMod": [
|
||||
"/Lotus/Upgrades/Mods/Randomized/LotusShotgunRandomModRare"
|
||||
],
|
||||
"/Lotus/Upgrades/Mods/Randomized/RawSentinelWeaponRandomMod": [
|
||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||
"/Lotus/Upgrades/Mods/Randomized/LotusShotgunRandomModRare",
|
||||
"/Lotus/Upgrades/Mods/Randomized/LotusPistolRandomModRare",
|
||||
"/Lotus/Upgrades/Mods/Randomized/PlayerMeleeWeaponRandomModRare"
|
||||
]
|
||||
};
|
@ -4,9 +4,10 @@ import { IUpdateGlyphRequest } from "@/src/types/requestTypes";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
const addFriendImageController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const json = getJSONfromString<IUpdateGlyphRequest>(String(req.body));
|
||||
const json = getJSONfromString(String(req.body)) as IUpdateGlyphRequest;
|
||||
const inventory = await getInventory(accountId);
|
||||
inventory.ActiveAvatarImageType = json.AvatarImageType;
|
||||
await inventory.save();
|
||||
|
@ -1,76 +0,0 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory, addMods } from "@/src/services/inventoryService";
|
||||
import { IOid } from "@/src/types/commonTypes";
|
||||
|
||||
export const arcaneCommonController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const json = getJSONfromString<IArcaneCommonRequest>(String(req.body));
|
||||
const inventory = await getInventory(accountId);
|
||||
const upgrade = inventory.Upgrades.id(json.arcane.ItemId.$oid);
|
||||
if (json.newRank == -1) {
|
||||
// Break down request?
|
||||
if (!upgrade || !upgrade.UpgradeFingerprint) {
|
||||
throw new Error(`Failed to find upgrade with OID ${json.arcane.ItemId.$oid}`);
|
||||
}
|
||||
|
||||
// Remove Upgrade
|
||||
inventory.Upgrades.pull({ _id: json.arcane.ItemId.$oid });
|
||||
|
||||
// Add RawUpgrades
|
||||
const numRawUpgradesToGive = arcaneLevelCounts[(JSON.parse(upgrade.UpgradeFingerprint) as { lvl: number }).lvl];
|
||||
addMods(inventory, [
|
||||
{
|
||||
ItemType: json.arcane.ItemType,
|
||||
ItemCount: numRawUpgradesToGive
|
||||
}
|
||||
]);
|
||||
|
||||
res.json({ upgradeId: json.arcane.ItemId.$oid, numConsumed: numRawUpgradesToGive });
|
||||
} else {
|
||||
// Upgrade request?
|
||||
let numConsumed = arcaneLevelCounts[json.newRank];
|
||||
let upgradeId = json.arcane.ItemId.$oid;
|
||||
if (upgrade) {
|
||||
// Have an existing Upgrade item?
|
||||
if (upgrade.UpgradeFingerprint) {
|
||||
const existingLevel = (JSON.parse(upgrade.UpgradeFingerprint) as { lvl: number }).lvl;
|
||||
numConsumed -= arcaneLevelCounts[existingLevel];
|
||||
}
|
||||
upgrade.UpgradeFingerprint = JSON.stringify({ lvl: json.newRank });
|
||||
} else {
|
||||
const newLength = inventory.Upgrades.push({
|
||||
ItemType: json.arcane.ItemType,
|
||||
UpgradeFingerprint: JSON.stringify({ lvl: json.newRank })
|
||||
});
|
||||
upgradeId = inventory.Upgrades[newLength - 1]._id.toString();
|
||||
}
|
||||
|
||||
// Remove RawUpgrades
|
||||
addMods(inventory, [
|
||||
{
|
||||
ItemType: json.arcane.ItemType,
|
||||
ItemCount: numConsumed * -1
|
||||
}
|
||||
]);
|
||||
|
||||
res.json({ newLevel: json.newRank, numConsumed, upgradeId });
|
||||
}
|
||||
await inventory.save();
|
||||
};
|
||||
|
||||
const arcaneLevelCounts = [0, 3, 6, 10, 15, 21];
|
||||
|
||||
interface IArcaneCommonRequest {
|
||||
arcane: {
|
||||
ItemType: string;
|
||||
ItemId: IOid;
|
||||
FromSKU: boolean;
|
||||
UpgradeFingerprint: string;
|
||||
PendingRerollFingerprint: string;
|
||||
ItemCount: number;
|
||||
LastAdded: IOid;
|
||||
};
|
||||
newRank: number;
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { addMiscItems, getInventory } from "@/src/services/inventoryService";
|
||||
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { colorToShard, combineColors, shardToColor } from "@/src/helpers/shardHelper";
|
||||
|
||||
export const archonFusionController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const request = JSON.parse(String(req.body)) as IArchonFusionRequest;
|
||||
const inventory = await getInventory(accountId);
|
||||
request.Consumed.forEach(x => {
|
||||
x.ItemCount *= -1;
|
||||
});
|
||||
addMiscItems(inventory, request.Consumed);
|
||||
const newArchons: IMiscItem[] = [];
|
||||
switch (request.FusionType) {
|
||||
case "AFT_ASCENT":
|
||||
newArchons.push({
|
||||
ItemType: request.Consumed[0].ItemType + "Mythic",
|
||||
ItemCount: 1
|
||||
});
|
||||
break;
|
||||
|
||||
case "AFT_COALESCENT":
|
||||
newArchons.push({
|
||||
ItemType:
|
||||
colorToShard[
|
||||
combineColors(
|
||||
shardToColor[request.Consumed[0].ItemType],
|
||||
shardToColor[request.Consumed[1].ItemType]
|
||||
)
|
||||
],
|
||||
ItemCount: 1
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`unknown archon fusion type: ${request.FusionType}`);
|
||||
}
|
||||
addMiscItems(inventory, newArchons);
|
||||
await inventory.save();
|
||||
res.json({
|
||||
NewArchons: newArchons
|
||||
});
|
||||
};
|
||||
|
||||
interface IArchonFusionRequest {
|
||||
Consumed: IMiscItem[];
|
||||
FusionType: string;
|
||||
StatResultType: "SRT_NEW_STAT"; // ???
|
||||
}
|
@ -1,70 +1,22 @@
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { upgradeMod } from "@/src/services/inventoryService";
|
||||
import { IArtifactsRequest } from "@/src/types/requestTypes";
|
||||
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) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
const artifactsController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const artifactsData = getJSONfromString<IArtifactsRequest>(String(req.body));
|
||||
|
||||
const { Upgrade, LevelDiff, Cost, FusionPointCost } = artifactsData;
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
const { Upgrades } = inventory;
|
||||
const { ItemType, UpgradeFingerprint, ItemId } = Upgrade;
|
||||
|
||||
const safeUpgradeFingerprint = UpgradeFingerprint || '{"lvl":0}';
|
||||
const parsedUpgradeFingerprint = JSON.parse(safeUpgradeFingerprint) as { lvl: number };
|
||||
parsedUpgradeFingerprint.lvl += LevelDiff;
|
||||
const stringifiedUpgradeFingerprint = JSON.stringify(parsedUpgradeFingerprint);
|
||||
|
||||
let itemIndex = Upgrades.findIndex(upgrade => upgrade._id.equals(ItemId.$oid));
|
||||
|
||||
if (itemIndex !== -1) {
|
||||
Upgrades[itemIndex].UpgradeFingerprint = stringifiedUpgradeFingerprint;
|
||||
inventory.markModified(`Upgrades.${itemIndex}.UpgradeFingerprint`);
|
||||
} else {
|
||||
itemIndex =
|
||||
Upgrades.push({
|
||||
UpgradeFingerprint: stringifiedUpgradeFingerprint,
|
||||
ItemType
|
||||
}) - 1;
|
||||
|
||||
addMods(inventory, [{ ItemType, ItemCount: -1 }]);
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-call
|
||||
const artifactsData = getJSONfromString(req.body.toString()) as IArtifactsRequest;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
const upgradeModId = await upgradeMod(artifactsData, accountId);
|
||||
res.send(upgradeModId);
|
||||
} catch (err) {
|
||||
console.error("Error parsing JSON data:", err);
|
||||
}
|
||||
|
||||
if (!config.infiniteCredits) {
|
||||
inventory.RegularCredits -= Cost;
|
||||
}
|
||||
if (!config.infiniteEndo) {
|
||||
inventory.FusionPoints -= FusionPointCost;
|
||||
}
|
||||
|
||||
if (artifactsData.LegendaryFusion) {
|
||||
addMods(inventory, [
|
||||
{
|
||||
ItemType: "/Lotus/Upgrades/Mods/Fusers/LegendaryModFuser",
|
||||
ItemCount: -1
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
const changedInventory = await inventory.save();
|
||||
const itemId = changedInventory.toJSON<IInventoryClient>().Upgrades[itemIndex].ItemId.$oid;
|
||||
|
||||
if (!itemId) {
|
||||
throw new Error("Item Id not found in upgradeMod");
|
||||
}
|
||||
|
||||
res.send(itemId);
|
||||
};
|
||||
|
||||
interface IArtifactsRequest {
|
||||
Upgrade: IUpgradeClient;
|
||||
LevelDiff: number;
|
||||
Cost: number;
|
||||
FusionPointCost: number;
|
||||
LegendaryFusion?: boolean;
|
||||
}
|
||||
export { artifactsController };
|
||||
|
@ -1,90 +0,0 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getDojoClient, getGuildForRequest } from "@/src/services/guildService";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { IDojoComponentDatabase } from "@/src/types/guildTypes";
|
||||
import { Types } from "mongoose";
|
||||
|
||||
export const changeDojoRootController: RequestHandler = async (req, res) => {
|
||||
const guild = await getGuildForRequest(req);
|
||||
// At this point, we know that a member of the guild is making this request. Assuming they are allowed to change the root.
|
||||
|
||||
const idToNode: Record<string, INode> = {};
|
||||
guild.DojoComponents!.forEach(x => {
|
||||
idToNode[x._id.toString()] = {
|
||||
component: x,
|
||||
parent: undefined,
|
||||
children: []
|
||||
};
|
||||
});
|
||||
|
||||
let oldRoot: INode | undefined;
|
||||
guild.DojoComponents!.forEach(x => {
|
||||
const node = idToNode[x._id.toString()];
|
||||
if (x.pi) {
|
||||
idToNode[x.pi.toString()].children.push(node);
|
||||
node.parent = idToNode[x.pi.toString()];
|
||||
} else {
|
||||
oldRoot = node;
|
||||
}
|
||||
});
|
||||
logger.debug("Old tree:\n" + treeToString(oldRoot!));
|
||||
|
||||
const newRoot = idToNode[req.query.newRoot as string];
|
||||
recursivelyTurnParentsIntoChildren(newRoot);
|
||||
newRoot.component.pi = undefined;
|
||||
newRoot.component.op = undefined;
|
||||
newRoot.component.pp = undefined;
|
||||
newRoot.parent = undefined;
|
||||
|
||||
// Don't even ask me why this is needed because I don't know either
|
||||
const stack: INode[] = [newRoot];
|
||||
let i = 0;
|
||||
const idMap: Record<string, Types.ObjectId> = {};
|
||||
while (stack.length != 0) {
|
||||
const top = stack.shift()!;
|
||||
idMap[top.component._id.toString()] = new Types.ObjectId(
|
||||
(++i).toString(16).padStart(8, "0") + top.component._id.toString().substr(8)
|
||||
);
|
||||
top.children.forEach(x => stack.push(x));
|
||||
}
|
||||
guild.DojoComponents!.forEach(x => {
|
||||
x._id = idMap[x._id.toString()];
|
||||
if (x.pi) {
|
||||
x.pi = idMap[x.pi.toString()];
|
||||
}
|
||||
});
|
||||
|
||||
logger.debug("New tree:\n" + treeToString(newRoot));
|
||||
|
||||
await guild.save();
|
||||
|
||||
res.json(getDojoClient(guild, 0));
|
||||
};
|
||||
|
||||
interface INode {
|
||||
component: IDojoComponentDatabase;
|
||||
parent: INode | undefined;
|
||||
children: INode[];
|
||||
}
|
||||
|
||||
const treeToString = (root: INode, depth: number = 0): string => {
|
||||
let str = " ".repeat(depth * 4) + root.component.pf + " (" + root.component._id.toString() + ")\n";
|
||||
root.children.forEach(x => {
|
||||
str += treeToString(x, depth + 1);
|
||||
});
|
||||
return str;
|
||||
};
|
||||
|
||||
const recursivelyTurnParentsIntoChildren = (node: INode): void => {
|
||||
if (node.parent!.parent) {
|
||||
recursivelyTurnParentsIntoChildren(node.parent!);
|
||||
}
|
||||
|
||||
node.parent!.component.pi = node.component._id;
|
||||
node.parent!.component.op = node.component.pp;
|
||||
node.parent!.component.pp = node.component.op;
|
||||
|
||||
node.parent!.parent = node;
|
||||
node.parent!.children.splice(node.parent!.children.indexOf(node), 1);
|
||||
node.children.push(node.parent!);
|
||||
};
|
@ -7,32 +7,30 @@ import { getRecipe } from "@/src/services/itemDataService";
|
||||
import { IOid } from "@/src/types/commonTypes";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import {
|
||||
getInventory,
|
||||
updateCurrency,
|
||||
addItem,
|
||||
addMiscItems,
|
||||
addRecipes,
|
||||
updateCurrencyByAccountId
|
||||
} from "@/src/services/inventoryService";
|
||||
import { getInventory, updateCurrency, addItem, addMiscItems, addRecipes } from "@/src/services/inventoryService";
|
||||
|
||||
export interface IClaimCompletedRecipeRequest {
|
||||
RecipeIds: IOid[];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const claimCompletedRecipeController: RequestHandler = async (req, res) => {
|
||||
const claimCompletedRecipeRequest = getJSONfromString<IClaimCompletedRecipeRequest>(String(req.body));
|
||||
const claimCompletedRecipeRequest = getJSONfromString(String(req.body)) as IClaimCompletedRecipeRequest;
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
if (!accountId) throw new Error("no account id");
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
const pendingRecipe = inventory.PendingRecipes.id(claimCompletedRecipeRequest.RecipeIds[0].$oid);
|
||||
const pendingRecipe = inventory.PendingRecipes.find(
|
||||
recipe => recipe._id?.toString() === claimCompletedRecipeRequest.RecipeIds[0].$id
|
||||
);
|
||||
if (!pendingRecipe) {
|
||||
throw new Error(`no pending recipe found with id ${claimCompletedRecipeRequest.RecipeIds[0].$oid}`);
|
||||
logger.error(`no pending recipe found with id ${claimCompletedRecipeRequest.RecipeIds[0].$id}`);
|
||||
throw new Error(`no pending recipe found with id ${claimCompletedRecipeRequest.RecipeIds[0].$id}`);
|
||||
}
|
||||
|
||||
//check recipe is indeed ready to be completed
|
||||
// if (pendingRecipe.CompletionDate > new Date()) {
|
||||
// logger.error(`recipe ${pendingRecipe._id} is not ready to be completed`);
|
||||
// throw new Error(`recipe ${pendingRecipe._id} is not ready to be completed`);
|
||||
// }
|
||||
|
||||
@ -41,12 +39,14 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
|
||||
|
||||
const recipe = getRecipe(pendingRecipe.ItemType);
|
||||
if (!recipe) {
|
||||
throw new Error(`no completed item found for recipe ${pendingRecipe._id.toString()}`);
|
||||
logger.error(`no completed item found for recipe ${pendingRecipe._id}`);
|
||||
throw new Error(`no completed item found for recipe ${pendingRecipe._id}`);
|
||||
}
|
||||
|
||||
if (req.query.cancel) {
|
||||
const currencyChanges = await updateCurrency(recipe.buildPrice * -1, false, accountId);
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
const currencyChanges = updateCurrency(inventory, recipe.buildPrice * -1, false);
|
||||
addMiscItems(inventory, recipe.ingredients);
|
||||
await inventory.save();
|
||||
|
||||
@ -57,30 +57,6 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
|
||||
});
|
||||
} else {
|
||||
logger.debug("Claiming Recipe", { recipe, pendingRecipe });
|
||||
|
||||
if (recipe.secretIngredientAction == "SIA_SPECTRE_LOADOUT_COPY") {
|
||||
const inventory = await getInventory(accountId);
|
||||
inventory.PendingSpectreLoadouts ??= [];
|
||||
inventory.SpectreLoadouts ??= [];
|
||||
|
||||
const pendingLoadoutIndex = inventory.PendingSpectreLoadouts.findIndex(
|
||||
x => x.ItemType == recipe.resultType
|
||||
);
|
||||
if (pendingLoadoutIndex != -1) {
|
||||
const loadoutIndex = inventory.SpectreLoadouts.findIndex(x => x.ItemType == recipe.resultType);
|
||||
if (loadoutIndex != -1) {
|
||||
inventory.SpectreLoadouts.splice(loadoutIndex, 1);
|
||||
}
|
||||
logger.debug(
|
||||
"moving spectre loadout from pending to active",
|
||||
inventory.toJSON().PendingSpectreLoadouts![pendingLoadoutIndex]
|
||||
);
|
||||
inventory.SpectreLoadouts.push(inventory.PendingSpectreLoadouts[pendingLoadoutIndex]);
|
||||
inventory.PendingSpectreLoadouts.splice(pendingLoadoutIndex, 1);
|
||||
await inventory.save();
|
||||
}
|
||||
}
|
||||
|
||||
let InventoryChanges = {};
|
||||
if (recipe.consumeOnUse) {
|
||||
const recipeChanges = [
|
||||
@ -99,15 +75,14 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
|
||||
if (req.query.rush) {
|
||||
InventoryChanges = {
|
||||
...InventoryChanges,
|
||||
...(await updateCurrencyByAccountId(recipe.skipBuildTimePrice, true, accountId))
|
||||
...(await updateCurrency(recipe.skipBuildTimePrice, true, accountId))
|
||||
};
|
||||
}
|
||||
const inventory = await getInventory(accountId);
|
||||
InventoryChanges = {
|
||||
...InventoryChanges,
|
||||
...(await addItem(inventory, recipe.resultType, recipe.num)).InventoryChanges
|
||||
};
|
||||
await inventory.save();
|
||||
res.json({ InventoryChanges });
|
||||
res.json({
|
||||
InventoryChanges: {
|
||||
...InventoryChanges,
|
||||
...(await addItem(accountId, recipe.resultType, recipe.num)).InventoryChanges
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -1,23 +0,0 @@
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const clearDialogueHistoryController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const request = JSON.parse(String(req.body)) as IClearDialogueRequest;
|
||||
if (inventory.DialogueHistory && inventory.DialogueHistory.Dialogues) {
|
||||
for (const dialogueName of request.Dialogues) {
|
||||
const index = inventory.DialogueHistory.Dialogues.findIndex(x => x.DialogueName == dialogueName);
|
||||
if (index != -1) {
|
||||
inventory.DialogueHistory.Dialogues.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
await inventory.save();
|
||||
res.end();
|
||||
};
|
||||
|
||||
interface IClearDialogueRequest {
|
||||
Dialogues: string[];
|
||||
}
|
@ -3,10 +3,12 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
|
||||
import { Guild } from "@/src/models/guildModel";
|
||||
import { ICreateGuildRequest } from "@/src/types/guildTypes";
|
||||
|
||||
export const createGuildController: RequestHandler = async (req, res) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
const createGuildController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const payload = getJSONfromString<ICreateGuildRequest>(String(req.body));
|
||||
const payload = getJSONfromString(String(req.body)) as ICreateGuildRequest;
|
||||
|
||||
// Create guild on database
|
||||
const guild = new Guild({
|
||||
@ -21,6 +23,7 @@ export const createGuildController: RequestHandler = async (req, res) => {
|
||||
inventory.GuildId = guild._id;
|
||||
|
||||
// Give clan key (TODO: This should only be a blueprint)
|
||||
inventory.LevelKeys ??= [];
|
||||
inventory.LevelKeys.push({
|
||||
ItemType: "/Lotus/Types/Keys/DojoKey",
|
||||
ItemCount: 1
|
||||
@ -32,6 +35,4 @@ export const createGuildController: RequestHandler = async (req, res) => {
|
||||
res.json(guild);
|
||||
};
|
||||
|
||||
interface ICreateGuildRequest {
|
||||
guildName: string;
|
||||
}
|
||||
export { createGuildController };
|
||||
|
@ -1,27 +0,0 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { config } from "@/src/services/configService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
|
||||
export const creditsController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
|
||||
const inventory = await getInventory(accountId, "RegularCredits TradesRemaining PremiumCreditsFree PremiumCredits");
|
||||
|
||||
const response = {
|
||||
RegularCredits: inventory.RegularCredits,
|
||||
TradesRemaining: inventory.TradesRemaining,
|
||||
PremiumCreditsFree: inventory.PremiumCreditsFree,
|
||||
PremiumCredits: inventory.PremiumCredits
|
||||
};
|
||||
|
||||
if (config.infiniteCredits) {
|
||||
response.RegularCredits = 999999999;
|
||||
}
|
||||
if (config.infinitePlatinum) {
|
||||
response.PremiumCreditsFree = 999999999;
|
||||
response.PremiumCredits = 999999999;
|
||||
}
|
||||
|
||||
res.json(response);
|
||||
};
|
@ -1,60 +0,0 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { TEndlessXpCategory } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
|
||||
export const endlessXpController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const payload = getJSONfromString<IEndlessXpRequest>(String(req.body));
|
||||
|
||||
inventory.EndlessXP ??= [];
|
||||
const entry = inventory.EndlessXP.find(x => x.Category == payload.Category);
|
||||
if (entry) {
|
||||
entry.Choices = payload.Choices;
|
||||
} else {
|
||||
inventory.EndlessXP.push({
|
||||
Category: payload.Category,
|
||||
Choices: payload.Choices
|
||||
});
|
||||
}
|
||||
await inventory.save();
|
||||
|
||||
res.json({
|
||||
NewProgress: {
|
||||
Category: payload.Category,
|
||||
Earn: 0,
|
||||
Claim: 0,
|
||||
BonusAvailable: {
|
||||
$date: {
|
||||
$numberLong: "9999999999999"
|
||||
}
|
||||
},
|
||||
Expiry: {
|
||||
$date: {
|
||||
$numberLong: "9999999999999"
|
||||
}
|
||||
},
|
||||
Choices: payload.Choices,
|
||||
PendingRewards: [
|
||||
{
|
||||
RequiredTotalXp: 190,
|
||||
Rewards: [
|
||||
{
|
||||
StoreItem: "/Lotus/StoreItems/Upgrades/Mods/Aura/PlayerHealthAuraMod",
|
||||
ItemCount: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
// ...
|
||||
]
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
interface IEndlessXpRequest {
|
||||
Mode: string; // "r"
|
||||
Category: TEndlessXpCategory;
|
||||
Choices: string[];
|
||||
}
|
@ -1,48 +1,32 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { addMiscItems, getInventory } from "@/src/services/inventoryService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { getRecipe, WeaponTypeInternal } from "@/src/services/itemDataService";
|
||||
import { WeaponTypeInternal } from "@/src/services/itemDataService";
|
||||
import { EquipmentFeatures } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const evolveWeaponController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const payload = getJSONfromString<IEvolveWeaponRequest>(String(req.body));
|
||||
const payload = getJSONfromString(String(req.body)) as IEvolveWeaponRequest;
|
||||
console.assert(payload.Action == "EWA_INSTALL");
|
||||
|
||||
const recipe = getRecipe(payload.Recipe)!;
|
||||
if (payload.Action == "EWA_INSTALL") {
|
||||
addMiscItems(
|
||||
inventory,
|
||||
recipe.ingredients.map(x => ({ ItemType: x.ItemType, ItemCount: x.ItemCount * -1 }))
|
||||
);
|
||||
// TODO: We should remove the Genesis item & its resources, but currently we don't know these "recipes".
|
||||
|
||||
const item = inventory[payload.Category].find(item => item._id.toString() == (req.query.ItemId as string))!;
|
||||
item.Features ??= 0;
|
||||
item.Features |= EquipmentFeatures.INCARNON_GENESIS;
|
||||
const item = inventory[payload.Category].find(item => item._id.toString() == (req.query.ItemId as string))!;
|
||||
item.Features ??= 0;
|
||||
item.Features |= EquipmentFeatures.INCARNON_GENESIS;
|
||||
|
||||
item.SkillTree = "0";
|
||||
item.SkillTree = "0";
|
||||
|
||||
inventory.EvolutionProgress ??= [];
|
||||
if (!inventory.EvolutionProgress.find(entry => entry.ItemType == payload.EvoType)) {
|
||||
inventory.EvolutionProgress.push({
|
||||
Progress: 0,
|
||||
Rank: 1,
|
||||
ItemType: payload.EvoType
|
||||
});
|
||||
}
|
||||
} else if (payload.Action == "EWA_UNINSTALL") {
|
||||
addMiscItems(inventory, [
|
||||
{
|
||||
ItemType: recipe.resultType,
|
||||
ItemCount: 1
|
||||
}
|
||||
]);
|
||||
|
||||
const item = inventory[payload.Category].find(item => item._id.toString() == (req.query.ItemId as string))!;
|
||||
item.Features! &= ~EquipmentFeatures.INCARNON_GENESIS;
|
||||
} else {
|
||||
throw new Error(`unexpected evolve weapon action: ${payload.Action}`);
|
||||
inventory.EvolutionProgress ??= [];
|
||||
if (!inventory.EvolutionProgress.find(entry => entry.ItemType == payload.EvoType)) {
|
||||
inventory.EvolutionProgress.push({
|
||||
Progress: 0,
|
||||
Rank: 1,
|
||||
ItemType: payload.EvoType
|
||||
});
|
||||
}
|
||||
|
||||
await inventory.save();
|
||||
@ -50,7 +34,7 @@ export const evolveWeaponController: RequestHandler = async (req, res) => {
|
||||
};
|
||||
|
||||
interface IEvolveWeaponRequest {
|
||||
Action: string;
|
||||
Action: "EWA_INSTALL";
|
||||
Category: WeaponTypeInternal;
|
||||
Recipe: string; // e.g. "/Lotus/Types/Items/MiscItems/IncarnonAdapters/UnlockerBlueprints/DespairIncarnonBlueprint"
|
||||
UninstallRecipe: "";
|
||||
|
@ -1,28 +1,31 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getSession } from "@/src/managers/sessionManager";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { IFindSessionRequest } from "@/src/types/session";
|
||||
|
||||
export const findSessionsController: RequestHandler = (_req, res) => {
|
||||
const req = JSON.parse(String(_req.body)) as IFindSessionRequest;
|
||||
logger.debug("FindSession Request ", req);
|
||||
//TODO: cleanup
|
||||
const findSessionsController: RequestHandler = (_req, res) => {
|
||||
const reqBody = JSON.parse(String(_req.body));
|
||||
logger.debug("FindSession Request ", { reqBody });
|
||||
const req = JSON.parse(String(_req.body));
|
||||
if (req.id != undefined) {
|
||||
logger.debug("Found ID");
|
||||
const session = getSession(req.id);
|
||||
const session = getSession(req.id as string);
|
||||
|
||||
if (session.length) res.json({ queryId: req.queryId, Sessions: session });
|
||||
if (session) res.json({ queryId: req.queryId, Sessions: session });
|
||||
else res.json({});
|
||||
} else if (req.originalSessionId != undefined) {
|
||||
logger.debug("Found OriginalSessionID");
|
||||
|
||||
const session = getSession(req.originalSessionId);
|
||||
if (session.length) res.json({ queryId: req.queryId, Sessions: session });
|
||||
const session = getSession(req.originalSessionId as string);
|
||||
if (session) res.json({ queryId: req.queryId, Sessions: session });
|
||||
else res.json({});
|
||||
} else {
|
||||
logger.debug("Found SessionRequest");
|
||||
|
||||
const session = getSession(req);
|
||||
if (session.length) res.json({ queryId: req.queryId, Sessions: session });
|
||||
const session = getSession(String(_req.body));
|
||||
if (session) res.json({ queryId: req.queryId, Sessions: session });
|
||||
else res.json({});
|
||||
}
|
||||
};
|
||||
|
||||
export { findSessionsController };
|
||||
|
@ -1,65 +0,0 @@
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { getMaxStanding } from "@/src/helpers/syndicateStandingHelper";
|
||||
import { addMiscItems, getInventory, getStandingLimit, updateStandingLimit } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { RequestHandler } from "express";
|
||||
import { ExportResources, ExportSyndicates } from "warframe-public-export-plus";
|
||||
|
||||
export const fishmongerController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const body = getJSONfromString<IFishmongerRequest>(String(req.body));
|
||||
const miscItemChanges: IMiscItem[] = [];
|
||||
let syndicateTag: string | undefined;
|
||||
let gainedStanding = 0;
|
||||
for (const fish of body.Fish) {
|
||||
const fishData = ExportResources[fish.ItemType];
|
||||
if (req.query.dissect == "1") {
|
||||
for (const part of fishData.dissectionParts!) {
|
||||
const partItem = miscItemChanges.find(x => x.ItemType == part.ItemType);
|
||||
if (partItem) {
|
||||
partItem.ItemCount += part.ItemCount * fish.ItemCount;
|
||||
} else {
|
||||
miscItemChanges.push({ ItemType: part.ItemType, ItemCount: part.ItemCount * fish.ItemCount });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
syndicateTag = fishData.syndicateTag!;
|
||||
gainedStanding += fishData.standingBonus! * fish.ItemCount;
|
||||
}
|
||||
miscItemChanges.push({ ItemType: fish.ItemType, ItemCount: fish.ItemCount * -1 });
|
||||
}
|
||||
addMiscItems(inventory, miscItemChanges);
|
||||
if (gainedStanding && syndicateTag) {
|
||||
let syndicate = inventory.Affiliations.find(x => x.Tag == syndicateTag);
|
||||
if (!syndicate) {
|
||||
syndicate = inventory.Affiliations[inventory.Affiliations.push({ Tag: syndicateTag, Standing: 0 }) - 1];
|
||||
}
|
||||
const syndicateMeta = ExportSyndicates[syndicateTag];
|
||||
|
||||
const max = getMaxStanding(syndicateMeta, syndicate.Title ?? 0);
|
||||
if (syndicate.Standing + gainedStanding > max) {
|
||||
gainedStanding = max - syndicate.Standing;
|
||||
}
|
||||
if (gainedStanding > getStandingLimit(inventory, syndicateMeta.dailyLimitBin)) {
|
||||
gainedStanding = getStandingLimit(inventory, syndicateMeta.dailyLimitBin);
|
||||
}
|
||||
|
||||
syndicate.Standing += gainedStanding;
|
||||
|
||||
updateStandingLimit(inventory, syndicateMeta.dailyLimitBin, gainedStanding);
|
||||
}
|
||||
await inventory.save();
|
||||
res.json({
|
||||
InventoryChanges: {
|
||||
MiscItems: miscItemChanges
|
||||
},
|
||||
SyndicateTag: syndicateTag,
|
||||
StandingChange: gainedStanding
|
||||
});
|
||||
};
|
||||
|
||||
interface IFishmongerRequest {
|
||||
Fish: IMiscItem[];
|
||||
}
|
@ -1,41 +1,19 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory, addMiscItems, addEquipment } from "@/src/services/inventoryService";
|
||||
import { IMiscItem, TFocusPolarity, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { IMiscItem, TFocusPolarity } 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";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const focusController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
switch (req.query.op) {
|
||||
default:
|
||||
logger.error("Unhandled focus op type: " + String(req.query.op));
|
||||
logger.debug(String(req.body));
|
||||
logger.error("Unhandled focus op type: " + req.query.op);
|
||||
logger.debug(req.body.toString());
|
||||
res.end();
|
||||
break;
|
||||
case FocusOperation.InstallLens: {
|
||||
const request = JSON.parse(String(req.body)) as ILensInstallRequest;
|
||||
const inventory = await getInventory(accountId);
|
||||
for (const item of inventory[request.Category]) {
|
||||
if (item._id.toString() == request.WeaponId) {
|
||||
item.FocusLens = request.LensType;
|
||||
addMiscItems(inventory, [
|
||||
{
|
||||
ItemType: request.LensType,
|
||||
ItemCount: -1
|
||||
} satisfies IMiscItem
|
||||
]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
await inventory.save();
|
||||
res.json({
|
||||
weaponId: request.WeaponId,
|
||||
lensType: request.LensType
|
||||
});
|
||||
break;
|
||||
}
|
||||
case FocusOperation.UnlockWay: {
|
||||
const focusType = (JSON.parse(String(req.body)) as IWayRequest).FocusType;
|
||||
const focusPolarity = focusTypeToPolarity(focusType);
|
||||
@ -70,7 +48,7 @@ export const focusController: RequestHandler = async (req, res) => {
|
||||
cost += ExportFocusUpgrades[focusType].baseFocusPointCost;
|
||||
inventory.FocusUpgrades.push({ ItemType: focusType, Level: 0 });
|
||||
}
|
||||
inventory.FocusXP![focusPolarity] -= cost;
|
||||
inventory.FocusXP[focusPolarity] -= cost;
|
||||
await inventory.save();
|
||||
res.json({
|
||||
FocusTypes: request.FocusTypes,
|
||||
@ -88,7 +66,7 @@ export const focusController: RequestHandler = async (req, res) => {
|
||||
const focusUpgradeDb = inventory.FocusUpgrades.find(entry => entry.ItemType == focusUpgrade.ItemType)!;
|
||||
focusUpgradeDb.Level = focusUpgrade.Level;
|
||||
}
|
||||
inventory.FocusXP![focusPolarity] -= cost;
|
||||
inventory.FocusXP[focusPolarity] -= cost;
|
||||
await inventory.save();
|
||||
res.json({
|
||||
FocusInfos: request.FocusInfos,
|
||||
@ -103,17 +81,15 @@ export const focusController: RequestHandler = async (req, res) => {
|
||||
"/Lotus/Weapons/Sentients/OperatorAmplifiers/SentTrainingAmplifier/SentAmpTrainingChassis",
|
||||
"/Lotus/Weapons/Sentients/OperatorAmplifiers/SentTrainingAmplifier/SentAmpTrainingBarrel"
|
||||
];
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventoryChanges = addEquipment(inventory, "OperatorAmps", request.StartingWeaponType, parts);
|
||||
await inventory.save();
|
||||
res.json((inventoryChanges.OperatorAmps as IEquipmentClient[])[0]);
|
||||
const result = await addEquipment("OperatorAmps", request.StartingWeaponType, accountId, parts);
|
||||
res.json(result);
|
||||
break;
|
||||
}
|
||||
case FocusOperation.UnbindUpgrade: {
|
||||
const request = JSON.parse(String(req.body)) as IUnbindUpgradeRequest;
|
||||
const focusPolarity = focusTypeToPolarity(request.FocusTypes[0]);
|
||||
const inventory = await getInventory(accountId);
|
||||
inventory.FocusXP![focusPolarity] -= 750_000 * request.FocusTypes.length;
|
||||
inventory.FocusXP[focusPolarity] -= 750_000 * request.FocusTypes.length;
|
||||
addMiscItems(inventory, [
|
||||
{
|
||||
ItemType: "/Lotus/Types/Gameplay/Eidolon/Resources/SentientShards/SentientShardBrilliantItem",
|
||||
@ -168,7 +144,6 @@ export const focusController: RequestHandler = async (req, res) => {
|
||||
};
|
||||
|
||||
enum FocusOperation {
|
||||
InstallLens = "1",
|
||||
UnlockWay = "2",
|
||||
UnlockUpgrade = "3",
|
||||
LevelUpUpgrade = "4",
|
||||
@ -211,12 +186,6 @@ interface ISentTrainingAmplifierRequest {
|
||||
StartingWeaponType: string;
|
||||
}
|
||||
|
||||
interface ILensInstallRequest {
|
||||
LensType: string;
|
||||
Category: TEquipmentKey;
|
||||
WeaponId: string;
|
||||
}
|
||||
|
||||
// Works for ways & upgrades
|
||||
const focusTypeToPolarity = (type: string): TFocusPolarity => {
|
||||
return ("AP_" + type.substr(1).split("/")[3].toUpperCase()) as TFocusPolarity;
|
||||
|
@ -1,49 +0,0 @@
|
||||
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 { 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);
|
||||
const request = JSON.parse(String(req.body)) as IFusionTreasureRequest;
|
||||
|
||||
const oldTreasure = parseFusionTreasure(request.oldTreasureName, -1);
|
||||
const newTreasure = parseFusionTreasure(request.newTreasureName, 1);
|
||||
|
||||
// Swap treasures
|
||||
addFusionTreasures(inventory, [oldTreasure]);
|
||||
addFusionTreasures(inventory, [newTreasure]);
|
||||
|
||||
// Remove consumed stars
|
||||
const miscItemChanges: IMiscItem[] = [];
|
||||
const filledSockets = newTreasure.Sockets & ~oldTreasure.Sockets;
|
||||
for (let i = 0; filledSockets >> i; ++i) {
|
||||
if ((filledSockets >> i) & 1) {
|
||||
//console.log("Socket", i, "has been filled with", ExportResources[oldTreasure.ItemType].sockets![i]);
|
||||
miscItemChanges.push({
|
||||
ItemType: ExportResources[oldTreasure.ItemType].sockets![i],
|
||||
ItemCount: -1
|
||||
});
|
||||
}
|
||||
}
|
||||
addMiscItems(inventory, miscItemChanges);
|
||||
|
||||
await inventory.save();
|
||||
res.end();
|
||||
};
|
@ -7,11 +7,11 @@ import { IGenericUpdate } from "@/src/types/genericUpdate";
|
||||
// This endpoint used to be /api/genericUpdate.php, but sometime around the Jade Shadows update, it was changed to /api/updateNodeIntros.php.
|
||||
// SpaceNinjaServer supports both endpoints right now.
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
const genericUpdateController: RequestHandler = async (request, response) => {
|
||||
const accountId = await getAccountIdForRequest(request);
|
||||
const update = getJSONfromString<IGenericUpdate>(String(request.body));
|
||||
await updateGeneric(update, accountId);
|
||||
response.json(update);
|
||||
const update = getJSONfromString(String(request.body)) as IGenericUpdate;
|
||||
response.json(await updateGeneric(update, accountId));
|
||||
};
|
||||
|
||||
export { genericUpdateController };
|
||||
|
29
src/controllers/api/getCreditsController.ts
Normal file
29
src/controllers/api/getCreditsController.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { config } from "@/src/services/configService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const getCreditsController: RequestHandler = async (req, res) => {
|
||||
let accountId;
|
||||
try {
|
||||
accountId = await getAccountIdForRequest(req);
|
||||
} catch (e) {
|
||||
res.status(400).send("Log-in expired");
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.infiniteResources) {
|
||||
res.json({
|
||||
RegularCredits: 999999999,
|
||||
PremiumCredits: 999999999
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
res.json({
|
||||
RegularCredits: inventory.RegularCredits,
|
||||
PremiumCredits: inventory.PremiumCredits
|
||||
});
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
import { Request, Response } from "express";
|
||||
|
||||
const getFriendsController = (_request: Request, response: Response): void => {
|
||||
const getFriendsController = (_request: Request, response: Response) => {
|
||||
response.writeHead(200, {
|
||||
//Connection: "keep-alive",
|
||||
//"Content-Encoding": "gzip",
|
||||
|
@ -1,72 +1,6 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
|
||||
import { Guild } from "@/src/models/guildModel";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { toOid } from "@/src/helpers/inventoryHelpers";
|
||||
|
||||
const getGuildController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await Inventory.findOne({ accountOwnerId: accountId });
|
||||
if (!inventory) {
|
||||
res.status(400).json({ error: "inventory was undefined" });
|
||||
return;
|
||||
}
|
||||
if (inventory.GuildId) {
|
||||
const guild = await Guild.findOne({ _id: inventory.GuildId });
|
||||
if (guild) {
|
||||
res.json({
|
||||
_id: toOid(guild._id),
|
||||
Name: guild.Name,
|
||||
Members: [
|
||||
{
|
||||
_id: { $oid: req.query.accountId },
|
||||
Rank: 0,
|
||||
Status: 0
|
||||
}
|
||||
],
|
||||
Ranks: [
|
||||
{
|
||||
Name: "/Lotus/Language/Game/Rank_Creator",
|
||||
Permissions: 16351
|
||||
},
|
||||
{
|
||||
Name: "/Lotus/Language/Game/Rank_Warlord",
|
||||
Permissions: 14303
|
||||
},
|
||||
{
|
||||
Name: "/Lotus/Language/Game/Rank_General",
|
||||
Permissions: 4318
|
||||
},
|
||||
{
|
||||
Name: "/Lotus/Language/Game/Rank_Officer",
|
||||
Permissions: 4314
|
||||
},
|
||||
{
|
||||
Name: "/Lotus/Language/Game/Rank_Leader",
|
||||
Permissions: 4106
|
||||
},
|
||||
{
|
||||
Name: "/Lotus/Language/Game/Rank_Sage",
|
||||
Permissions: 4304
|
||||
},
|
||||
{
|
||||
Name: "/Lotus/Language/Game/Rank_Soldier",
|
||||
Permissions: 4098
|
||||
},
|
||||
{
|
||||
Name: "/Lotus/Language/Game/Rank_Initiate",
|
||||
Permissions: 4096
|
||||
},
|
||||
{
|
||||
Name: "/Lotus/Language/Game/Rank_Utility",
|
||||
Permissions: 4096
|
||||
}
|
||||
],
|
||||
Tier: 1
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
const getGuildController: RequestHandler = (_, res) => {
|
||||
res.json({});
|
||||
};
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { Types } from "mongoose";
|
||||
import { Guild } from "@/src/models/guildModel";
|
||||
import { getDojoClient } from "@/src/services/guildService";
|
||||
import { IDojoClient, IDojoComponentClient } from "@/src/types/guildTypes";
|
||||
import { toOid, toMongoDate } from "@/src/helpers/inventoryHelpers";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const getGuildDojoController: RequestHandler = async (req, res) => {
|
||||
const guildId = req.query.guildId as string;
|
||||
|
||||
@ -25,5 +27,34 @@ export const getGuildDojoController: RequestHandler = async (req, res) => {
|
||||
await guild.save();
|
||||
}
|
||||
|
||||
res.json(getDojoClient(guild, 0));
|
||||
const dojo: IDojoClient = {
|
||||
_id: { $id: guildId },
|
||||
Name: guild.Name,
|
||||
Tier: 1,
|
||||
FixedContributions: true,
|
||||
DojoRevision: 1,
|
||||
RevisionTime: Math.round(Date.now() / 1000),
|
||||
Energy: 5,
|
||||
Capacity: 100,
|
||||
DojoRequestStatus: 0,
|
||||
DojoComponents: []
|
||||
};
|
||||
guild.DojoComponents.forEach(dojoComponent => {
|
||||
const clientComponent: IDojoComponentClient = {
|
||||
id: toOid(dojoComponent._id),
|
||||
pf: dojoComponent.pf,
|
||||
ppf: dojoComponent.ppf,
|
||||
DecoCapacity: 600
|
||||
};
|
||||
if (dojoComponent.pi) {
|
||||
clientComponent.pi = toOid(dojoComponent.pi);
|
||||
clientComponent.op = dojoComponent.op!;
|
||||
clientComponent.pp = dojoComponent.pp!;
|
||||
}
|
||||
if (dojoComponent.CompletionTime) {
|
||||
clientComponent.CompletionTime = toMongoDate(dojoComponent.CompletionTime);
|
||||
}
|
||||
dojo.DojoComponents.push(clientComponent);
|
||||
});
|
||||
res.json(dojo);
|
||||
};
|
||||
|
@ -4,32 +4,31 @@ import allShipFeatures from "@/static/fixed_responses/allShipFeatures.json";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getPersonalRooms } from "@/src/services/personalRoomsService";
|
||||
import { getShip } from "@/src/services/shipService";
|
||||
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { toOid } from "@/src/helpers/inventoryHelpers";
|
||||
import { IGetShipResponse } from "@/src/types/shipTypes";
|
||||
import { IPersonalRooms } from "@/src/types/personalRoomsTypes";
|
||||
import { getLoadout } from "@/src/services/loadoutService";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const getShipController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const personalRoomsDb = await getPersonalRooms(accountId);
|
||||
const personalRooms = personalRoomsDb.toJSON<IPersonalRooms>();
|
||||
const personalRooms = await getPersonalRooms(accountId);
|
||||
const loadout = await getLoadout(accountId);
|
||||
const ship = await getShip(personalRoomsDb.activeShipId, "ShipAttachments SkinFlavourItem");
|
||||
const ship = await getShip(personalRooms.activeShipId, "ShipInteriorColors ShipAttachments SkinFlavourItem");
|
||||
|
||||
const getShipResponse: IGetShipResponse = {
|
||||
ShipOwnerId: accountId,
|
||||
LoadOutInventory: { LoadOutPresets: loadout.toJSON() },
|
||||
Ship: {
|
||||
...personalRooms.Ship,
|
||||
ShipId: toOid(personalRoomsDb.activeShipId),
|
||||
...personalRooms.toJSON().Ship,
|
||||
ShipId: toOid(personalRooms.activeShipId),
|
||||
ShipInterior: {
|
||||
Colors: personalRooms.ShipInteriorColors,
|
||||
Colors: ship.ShipInteriorColors,
|
||||
ShipAttachments: ship.ShipAttachments,
|
||||
SkinFlavourItem: ship.SkinFlavourItem
|
||||
}
|
||||
},
|
||||
Apartment: personalRooms.Apartment,
|
||||
TailorShop: personalRooms.TailorShop
|
||||
Apartment: personalRooms.Apartment
|
||||
};
|
||||
|
||||
if (config.unlockAllShipFeatures) {
|
||||
@ -38,3 +37,14 @@ export const getShipController: RequestHandler = async (req, res) => {
|
||||
|
||||
res.json(getShipResponse);
|
||||
};
|
||||
|
||||
export const getLoadout = async (accountId: string) => {
|
||||
const loadout = await Loadout.findOne({ loadoutOwnerId: accountId });
|
||||
|
||||
if (!loadout) {
|
||||
logger.error(`loadout not found for account ${accountId}`);
|
||||
throw new Error("loadout not found");
|
||||
}
|
||||
|
||||
return loadout;
|
||||
};
|
||||
|
@ -1,14 +1,23 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getVendorManifestByTypeName } from "@/src/services/serversideVendorsService";
|
||||
import ArchimedeanVendorManifest from "@/static/fixed_responses/getVendorInfo/ArchimedeanVendorManifest.json";
|
||||
import MaskSalesmanManifest from "@/static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json";
|
||||
import ZarimanCommisionsManifestArchimedean from "@/static/fixed_responses/getVendorInfo/ZarimanCommisionsManifestArchimedean.json";
|
||||
|
||||
export const getVendorInfoController: RequestHandler = (req, res) => {
|
||||
if (typeof req.query.vendor == "string") {
|
||||
const manifest = getVendorManifestByTypeName(req.query.vendor);
|
||||
if (!manifest) {
|
||||
switch (req.query.vendor as string) {
|
||||
case "/Lotus/Types/Game/VendorManifests/Zariman/ArchimedeanVendorManifest":
|
||||
res.json(ArchimedeanVendorManifest);
|
||||
break;
|
||||
|
||||
case "/Lotus/Types/Game/VendorManifests/Ostron/MaskSalesmanManifest":
|
||||
res.json(MaskSalesmanManifest);
|
||||
break;
|
||||
|
||||
case "/Lotus/Types/Game/VendorManifests/Zariman/ZarimanCommisionsManifestArchimedean":
|
||||
res.json(ZarimanCommisionsManifestArchimedean);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown vendor: ${req.query.vendor}`);
|
||||
}
|
||||
res.json(manifest);
|
||||
} else {
|
||||
res.status(400).end();
|
||||
}
|
||||
};
|
||||
|
@ -1,98 +0,0 @@
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { addMiscItems, getInventory } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
||||
import { getRandomWeightedReward2 } from "@/src/services/rngService";
|
||||
import { ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { RequestHandler } from "express";
|
||||
import { ExportRelics, ExportRewards, TRarity } from "warframe-public-export-plus";
|
||||
|
||||
export const getVoidProjectionRewardsController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const data = getJSONfromString<IVoidProjectionRewardRequest>(String(req.body));
|
||||
const response: IVoidProjectionRewardResponse = {
|
||||
CurrentWave: data.CurrentWave,
|
||||
ParticipantInfo: data.ParticipantInfo,
|
||||
DifficultyTier: data.DifficultyTier
|
||||
};
|
||||
if (data.ParticipantInfo.QualifiesForReward) {
|
||||
const relic = ExportRelics[data.ParticipantInfo.VoidProjection];
|
||||
const weights = refinementToWeights[relic.quality];
|
||||
logger.debug(`opening a relic of quality ${relic.quality}; rarity weights are`, weights);
|
||||
const reward = getRandomWeightedReward2(
|
||||
ExportRewards[relic.rewardManifest][0] as { type: string; itemCount: number; rarity: TRarity }[], // rarity is nullable in PE+ typings, but always present for relics
|
||||
weights
|
||||
)!;
|
||||
logger.debug(`relic rolled`, reward);
|
||||
response.ParticipantInfo.Reward = reward.type;
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
// Remove relic
|
||||
addMiscItems(inventory, [
|
||||
{
|
||||
ItemType: data.ParticipantInfo.VoidProjection,
|
||||
ItemCount: -1
|
||||
}
|
||||
]);
|
||||
// Give reward
|
||||
await handleStoreItemAcquisition(reward.type, inventory, reward.itemCount);
|
||||
await inventory.save();
|
||||
}
|
||||
res.json(response);
|
||||
};
|
||||
|
||||
const refinementToWeights = {
|
||||
VPQ_BRONZE: {
|
||||
COMMON: 0.76,
|
||||
UNCOMMON: 0.22,
|
||||
RARE: 0.02,
|
||||
LEGENDARY: 0
|
||||
},
|
||||
VPQ_SILVER: {
|
||||
COMMON: 0.7,
|
||||
UNCOMMON: 0.26,
|
||||
RARE: 0.04,
|
||||
LEGENDARY: 0
|
||||
},
|
||||
VPQ_GOLD: {
|
||||
COMMON: 0.6,
|
||||
UNCOMMON: 0.34,
|
||||
RARE: 0.06,
|
||||
LEGENDARY: 0
|
||||
},
|
||||
VPQ_PLATINUM: {
|
||||
COMMON: 0.5,
|
||||
UNCOMMON: 0.4,
|
||||
RARE: 0.1,
|
||||
LEGENDARY: 0
|
||||
}
|
||||
};
|
||||
|
||||
interface IVoidProjectionRewardRequest {
|
||||
CurrentWave: number;
|
||||
ParticipantInfo: IParticipantInfo;
|
||||
VoidTier: string;
|
||||
DifficultyTier: number;
|
||||
VoidProjectionRemovalHash: string;
|
||||
}
|
||||
|
||||
interface IVoidProjectionRewardResponse {
|
||||
CurrentWave: number;
|
||||
ParticipantInfo: IParticipantInfo;
|
||||
DifficultyTier: number;
|
||||
}
|
||||
|
||||
interface IParticipantInfo {
|
||||
AccountId: string;
|
||||
Name: string;
|
||||
ChosenRewardOwner: string;
|
||||
MissionHash: string;
|
||||
VoidProjection: string;
|
||||
Reward: string;
|
||||
QualifiesForReward: boolean;
|
||||
HaveRewardResponse: boolean;
|
||||
RewardsMultiplier: number;
|
||||
RewardProjection: string;
|
||||
HardModeReward: ITypeCount;
|
||||
}
|
@ -24,19 +24,23 @@ interface IGildWeaponRequest {
|
||||
|
||||
// In export there no recipes for gild action, so reputation and ressources only consumed visually
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const gildWeaponController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const data = getJSONfromString<IGildWeaponRequest>(String(req.body));
|
||||
const data: IGildWeaponRequest = getJSONfromString(String(req.body));
|
||||
data.ItemId = String(req.query.ItemId);
|
||||
if (!modularWeaponCategory.includes(req.query.Category as WeaponTypeInternal | "Hoverboards")) {
|
||||
throw new Error(`Unknown modular weapon Category: ${String(req.query.Category)}`);
|
||||
throw new Error(`Unknown modular weapon Category: ${req.query.Category}`);
|
||||
}
|
||||
data.Category = req.query.Category as WeaponTypeInternal | "Hoverboards";
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
if (!inventory[data.Category]) {
|
||||
throw new Error(`Category ${req.query.Category} not found in inventory`);
|
||||
}
|
||||
const weaponIndex = inventory[data.Category].findIndex(x => String(x._id) === data.ItemId);
|
||||
if (weaponIndex === -1) {
|
||||
throw new Error(`Weapon with ${data.ItemId} not found in category ${String(req.query.Category)}`);
|
||||
throw new Error(`Weapon with ${data.ItemId} not found in category ${req.query.Category}`);
|
||||
}
|
||||
|
||||
const weapon = inventory[data.Category][weaponIndex];
|
||||
|
@ -1,38 +0,0 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { isEmptyObject, parseString } from "@/src/helpers/general";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { addKeyChainItems, getInventory } from "@/src/services/inventoryService";
|
||||
import { IGroup } from "@/src/types/loginTypes";
|
||||
import { updateQuestStage } from "@/src/services/questService";
|
||||
|
||||
export const giveKeyChainTriggeredItemsController: RequestHandler = async (req, res) => {
|
||||
const accountId = parseString(req.query.accountId);
|
||||
const keyChainInfo = getJSONfromString<IKeyChainRequest>((req.body as string).toString());
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventoryChanges = await addKeyChainItems(inventory, keyChainInfo);
|
||||
|
||||
if (isEmptyObject(inventoryChanges)) {
|
||||
throw new Error("inventory changes was empty after getting keychain items: should not happen");
|
||||
}
|
||||
// items were added: update quest stage's i (item was given)
|
||||
updateQuestStage(inventory, keyChainInfo, { i: true });
|
||||
|
||||
await inventory.save();
|
||||
res.send(inventoryChanges);
|
||||
|
||||
//TODO: Check whether Wishlist is used to track items which should exist uniquely in the inventory
|
||||
/*
|
||||
some items are added or removed (not sure) to the wishlist, in that case a
|
||||
WishlistChanges: ["/Lotus/Types/Items/ShipFeatureItems/ArsenalFeatureItem"],
|
||||
is added to the response, need to determine for which items this is the case and what purpose this has.
|
||||
*/
|
||||
//{"KeyChain":"/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain","ChainStage":0}
|
||||
//{"WishlistChanges":["/Lotus/Types/Items/ShipFeatureItems/ArsenalFeatureItem"],"MiscItems":[{"ItemType":"/Lotus/Types/Items/ShipFeatureItems/ArsenalFeatureItem","ItemCount":1}]}
|
||||
};
|
||||
|
||||
export interface IKeyChainRequest {
|
||||
KeyChain: string;
|
||||
ChainStage: number;
|
||||
Groups?: IGroup[];
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
import { IKeyChainRequest } from "@/src/controllers/api/giveKeyChainTriggeredItemsController";
|
||||
import { IMessage } from "@/src/models/inboxModel";
|
||||
import { createMessage } from "@/src/services/inboxService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { getKeyChainMessage } from "@/src/services/itemDataService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { updateQuestStage } from "@/src/services/questService";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const giveKeyChainTriggeredMessageController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const keyChainInfo = JSON.parse((req.body as Buffer).toString()) as IKeyChainRequest;
|
||||
|
||||
const keyChainMessage = getKeyChainMessage(keyChainInfo);
|
||||
|
||||
const message = {
|
||||
sndr: keyChainMessage.sender,
|
||||
msg: keyChainMessage.body,
|
||||
sub: keyChainMessage.title,
|
||||
att: keyChainMessage.attachments.length > 0 ? keyChainMessage.attachments : undefined,
|
||||
countedAtt: keyChainMessage.countedAttachments.length > 0 ? keyChainMessage.countedAttachments : undefined,
|
||||
icon: keyChainMessage.icon ?? "",
|
||||
transmission: keyChainMessage.transmission ?? "",
|
||||
highPriority: keyChainMessage.highPriority ?? false,
|
||||
r: false
|
||||
} satisfies IMessage;
|
||||
|
||||
await createMessage(accountId, [message]);
|
||||
|
||||
const inventory = await getInventory(accountId, "QuestKeys");
|
||||
updateQuestStage(inventory, keyChainInfo, { m: true });
|
||||
await inventory.save();
|
||||
|
||||
res.send(1);
|
||||
};
|
@ -1,45 +0,0 @@
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { addItem, getInventory } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { IOid } from "@/src/types/commonTypes";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const giveQuestKeyRewardController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const rewardRequest = getJSONfromString<IQuestKeyRewardRequest>((req.body as Buffer).toString());
|
||||
|
||||
if (Array.isArray(rewardRequest.reward)) {
|
||||
throw new Error("Multiple rewards not expected");
|
||||
}
|
||||
|
||||
const reward = rewardRequest.reward;
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventoryChanges = await addItem(inventory, reward.ItemType, reward.Amount);
|
||||
await inventory.save();
|
||||
res.json(inventoryChanges.InventoryChanges);
|
||||
//TODO: consider whishlist changes
|
||||
};
|
||||
|
||||
export interface IQuestKeyRewardRequest {
|
||||
reward: IQuestKeyReward;
|
||||
}
|
||||
|
||||
export interface IQuestKeyReward {
|
||||
RewardType: string;
|
||||
CouponType: string;
|
||||
Icon: string;
|
||||
ItemType: string;
|
||||
StoreItemType: string;
|
||||
ProductCategory: string;
|
||||
Amount: number;
|
||||
ScalingMultiplier: number;
|
||||
Durability: string;
|
||||
DisplayName: string;
|
||||
Duration: number;
|
||||
CouponSku: number;
|
||||
Syndicate: string;
|
||||
Milestones: any[];
|
||||
ChooseSetIndex: number;
|
||||
NewSystemReward: boolean;
|
||||
_id: IOid;
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { RequestHandler } from "express";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
|
||||
export const startLibraryPersonalTargetController: RequestHandler = async (req, res) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const giveStartingGearController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
inventory.LibraryPersonalTarget = req.query.target as string;
|
||||
inventory.ReceivedStartingGear = true;
|
||||
console.log(req.query);
|
||||
await inventory.save();
|
||||
res.json({
|
||||
IsQuest: false,
|
||||
Target: req.query.target
|
||||
});
|
||||
res.status(200);
|
||||
};
|
@ -1,127 +1,5 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getGuildForRequestEx } from "@/src/services/guildService";
|
||||
import { ExportDojoRecipes } from "warframe-public-export-plus";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { addMiscItems, addRecipes, getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
||||
|
||||
export const guildTechController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const guild = await getGuildForRequestEx(req, inventory);
|
||||
const data = JSON.parse(String(req.body)) as TGuildTechRequest;
|
||||
const action = data.Action.split(",")[0];
|
||||
if (action == "Sync") {
|
||||
res.json({
|
||||
TechProjects: guild.toJSON().TechProjects
|
||||
});
|
||||
} else if (action == "Start") {
|
||||
const recipe = ExportDojoRecipes.research[data.RecipeType!];
|
||||
guild.TechProjects ??= [];
|
||||
if (!guild.TechProjects.find(x => x.ItemType == data.RecipeType)) {
|
||||
guild.TechProjects.push({
|
||||
ItemType: data.RecipeType!,
|
||||
ReqCredits: scaleRequiredCount(recipe.price),
|
||||
ReqItems: recipe.ingredients.map(x => ({
|
||||
ItemType: x.ItemType,
|
||||
ItemCount: scaleRequiredCount(x.ItemCount)
|
||||
})),
|
||||
State: 0
|
||||
});
|
||||
}
|
||||
await guild.save();
|
||||
res.end();
|
||||
} else if (action == "Contribute") {
|
||||
const contributions = data as IGuildTechContributeFields;
|
||||
const techProject = guild.TechProjects!.find(x => x.ItemType == contributions.RecipeType)!;
|
||||
if (contributions.RegularCredits > techProject.ReqCredits) {
|
||||
contributions.RegularCredits = techProject.ReqCredits;
|
||||
}
|
||||
techProject.ReqCredits -= contributions.RegularCredits;
|
||||
const miscItemChanges = [];
|
||||
for (const miscItem of contributions.MiscItems) {
|
||||
const reqItem = techProject.ReqItems.find(x => x.ItemType == miscItem.ItemType);
|
||||
if (reqItem) {
|
||||
if (miscItem.ItemCount > reqItem.ItemCount) {
|
||||
miscItem.ItemCount = reqItem.ItemCount;
|
||||
}
|
||||
reqItem.ItemCount -= miscItem.ItemCount;
|
||||
miscItemChanges.push({
|
||||
ItemType: miscItem.ItemType,
|
||||
ItemCount: miscItem.ItemCount * -1
|
||||
});
|
||||
}
|
||||
}
|
||||
addMiscItems(inventory, miscItemChanges);
|
||||
const inventoryChanges: IInventoryChanges = {
|
||||
...updateCurrency(inventory, contributions.RegularCredits, false),
|
||||
MiscItems: miscItemChanges
|
||||
};
|
||||
|
||||
if (techProject.ReqCredits == 0 && !techProject.ReqItems.find(x => x.ItemCount > 0)) {
|
||||
// This research is now fully funded.
|
||||
techProject.State = 1;
|
||||
const recipe = ExportDojoRecipes.research[data.RecipeType!];
|
||||
techProject.CompletionDate = new Date(new Date().getTime() + recipe.time * 1000);
|
||||
}
|
||||
|
||||
await guild.save();
|
||||
await inventory.save();
|
||||
res.json({
|
||||
InventoryChanges: inventoryChanges
|
||||
});
|
||||
} else if (action == "Buy") {
|
||||
const purchase = data as IGuildTechBuyFields;
|
||||
const quantity = parseInt(data.Action.split(",")[1]);
|
||||
const inventory = await getInventory(accountId);
|
||||
const recipeChanges = [
|
||||
{
|
||||
ItemType: purchase.RecipeType,
|
||||
ItemCount: quantity
|
||||
}
|
||||
];
|
||||
addRecipes(inventory, recipeChanges);
|
||||
const currencyChanges = updateCurrency(
|
||||
inventory,
|
||||
ExportDojoRecipes.research[purchase.RecipeType].replicatePrice,
|
||||
false
|
||||
);
|
||||
await inventory.save();
|
||||
// Not a mistake: This response uses `inventoryChanges` instead of `InventoryChanges`.
|
||||
res.json({
|
||||
inventoryChanges: {
|
||||
...currencyChanges,
|
||||
Recipes: recipeChanges
|
||||
}
|
||||
});
|
||||
} else {
|
||||
throw new Error(`unknown guildTech action: ${data.Action}`);
|
||||
}
|
||||
};
|
||||
|
||||
type TGuildTechRequest = {
|
||||
Action: string;
|
||||
} & Partial<IGuildTechStartFields> &
|
||||
Partial<IGuildTechContributeFields>;
|
||||
|
||||
interface IGuildTechStartFields {
|
||||
Mode: "Guild";
|
||||
RecipeType: string;
|
||||
}
|
||||
|
||||
type IGuildTechBuyFields = IGuildTechStartFields;
|
||||
|
||||
interface IGuildTechContributeFields {
|
||||
ResearchId: "";
|
||||
RecipeType: string;
|
||||
RegularCredits: number;
|
||||
MiscItems: IMiscItem[];
|
||||
VaultCredits: number;
|
||||
VaultMiscItems: IMiscItem[];
|
||||
}
|
||||
|
||||
const scaleRequiredCount = (count: number): number => {
|
||||
// The recipes in the export are for Moon clans. For now we'll just assume we only have Ghost clans.
|
||||
return Math.max(1, Math.trunc(count / 100));
|
||||
export const guildTechController: RequestHandler = (_req, res) => {
|
||||
res.status(500).end(); // This is what I got for a fresh clan.
|
||||
};
|
||||
|
@ -4,6 +4,7 @@ import { createNewSession } from "@/src/managers/sessionManager";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { ISession } from "@/src/types/session";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
const hostSessionController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const hostSessionRequest = JSON.parse(req.body as string) as ISession;
|
||||
@ -11,7 +12,7 @@ const hostSessionController: RequestHandler = async (req, res) => {
|
||||
const session = createNewSession(hostSessionRequest, accountId);
|
||||
logger.debug(`New Session Created`, { session });
|
||||
|
||||
res.json({ sessionId: { $oid: session.sessionId }, rewardSeed: 99999999 });
|
||||
res.json({ sessionId: { $id: session.sessionId }, rewardSeed: 99999999 });
|
||||
};
|
||||
|
||||
export { hostSessionController };
|
||||
|
@ -1,87 +1,8 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { Inbox } from "@/src/models/inboxModel";
|
||||
import {
|
||||
createNewEventMessages,
|
||||
deleteAllMessagesRead,
|
||||
deleteMessageRead,
|
||||
getAllMessagesSorted,
|
||||
getMessage
|
||||
} from "@/src/services/inboxService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { addItems, getInventory } from "@/src/services/inventoryService";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { ExportGear } from "warframe-public-export-plus";
|
||||
import inbox from "@/static/fixed_responses/inbox.json";
|
||||
|
||||
export const inboxController: RequestHandler = async (req, res) => {
|
||||
const { deleteId, lastMessage: latestClientMessageId, messageId } = req.query;
|
||||
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
|
||||
if (deleteId) {
|
||||
if (deleteId === "DeleteAllRead") {
|
||||
await deleteAllMessagesRead(accountId);
|
||||
res.status(200).end();
|
||||
return;
|
||||
}
|
||||
|
||||
await deleteMessageRead(deleteId as string);
|
||||
res.status(200).end();
|
||||
} else if (messageId) {
|
||||
const message = await getMessage(messageId as string);
|
||||
message.r = true;
|
||||
const attachmentItems = message.att;
|
||||
const attachmentCountedItems = message.countedAtt;
|
||||
|
||||
if (!attachmentItems && !attachmentCountedItems) {
|
||||
await message.save();
|
||||
|
||||
res.status(200).end();
|
||||
return;
|
||||
}
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventoryChanges = {};
|
||||
if (attachmentItems) {
|
||||
await addItems(
|
||||
inventory,
|
||||
attachmentItems.map(attItem => ({
|
||||
ItemType: attItem,
|
||||
ItemCount: attItem in ExportGear ? (ExportGear[attItem].purchaseQuantity ?? 1) : 1
|
||||
})),
|
||||
inventoryChanges
|
||||
);
|
||||
}
|
||||
if (attachmentCountedItems) {
|
||||
await addItems(inventory, attachmentCountedItems, inventoryChanges);
|
||||
}
|
||||
await inventory.save();
|
||||
await message.save();
|
||||
|
||||
res.json({ InventoryChanges: inventoryChanges });
|
||||
} else if (latestClientMessageId) {
|
||||
await createNewEventMessages(req);
|
||||
const messages = await Inbox.find({ ownerId: accountId }).sort({ date: 1 });
|
||||
|
||||
const latestClientMessage = messages.find(m => m._id.toString() === latestClientMessageId);
|
||||
|
||||
if (!latestClientMessage) {
|
||||
logger.debug(`this should only happen after DeleteAllRead `);
|
||||
res.json({ Inbox: messages });
|
||||
return;
|
||||
}
|
||||
const newMessages = messages.filter(m => m.date > latestClientMessage.date);
|
||||
|
||||
if (newMessages.length === 0) {
|
||||
res.send("no-new");
|
||||
return;
|
||||
}
|
||||
|
||||
res.json({ Inbox: newMessages });
|
||||
} else {
|
||||
//newly created event messages must be newer than account.LatestEventMessageDate
|
||||
await createNewEventMessages(req);
|
||||
const messages = await getAllMessagesSorted(accountId);
|
||||
const inbox = messages.map(m => m.toJSON());
|
||||
res.json({ Inbox: inbox });
|
||||
}
|
||||
const inboxController: RequestHandler = (_req, res) => {
|
||||
res.json(inbox);
|
||||
};
|
||||
|
||||
export { inboxController };
|
||||
|
@ -1,30 +1,18 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { getInventory, addMiscItems, updateCurrency, addRecipes } from "@/src/services/inventoryService";
|
||||
import { getInventory, addMiscItems } from "@/src/services/inventoryService";
|
||||
import { IOid } from "@/src/types/commonTypes";
|
||||
import {
|
||||
IConsumedSuit,
|
||||
IHelminthFoodRecord,
|
||||
IInfestedFoundryDatabase,
|
||||
IMiscItem,
|
||||
ITypeCount
|
||||
} from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { ExportMisc, ExportRecipes } from "warframe-public-export-plus";
|
||||
import { getRecipe } from "@/src/services/itemDataService";
|
||||
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||
import { toMongoDate } from "@/src/helpers/inventoryHelpers";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { colorToShard } from "@/src/helpers/shardHelper";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const infestedFoundryController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
switch (req.query.mode) {
|
||||
case "s": {
|
||||
// shard installation
|
||||
const request = getJSONfromString<IShardInstallRequest>(String(req.body));
|
||||
const request = getJSONfromString(String(req.body)) as IShardInstallRequest;
|
||||
const inventory = await getInventory(accountId);
|
||||
const suit = inventory.Suits.find(suit => suit._id.toString() == request.SuitId.$oid)!;
|
||||
const suit = inventory.Suits.find(suit => suit._id.toString() == request.SuitId.$id)!;
|
||||
if (!suit.ArchonCrystalUpgrades || suit.ArchonCrystalUpgrades.length != 5) {
|
||||
suit.ArchonCrystalUpgrades = [{}, {}, {}, {}, {}];
|
||||
}
|
||||
@ -48,47 +36,9 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
|
||||
break;
|
||||
}
|
||||
|
||||
case "x": {
|
||||
// shard removal
|
||||
const request = getJSONfromString<IShardUninstallRequest>(String(req.body));
|
||||
const inventory = await getInventory(accountId);
|
||||
const suit = inventory.Suits.find(suit => suit._id.toString() == request.SuitId.$oid)!;
|
||||
|
||||
// refund shard
|
||||
const shard = Object.entries(colorToShard).find(
|
||||
([color]) => color == suit.ArchonCrystalUpgrades![request.Slot].Color
|
||||
)![1];
|
||||
const miscItemChanges = [
|
||||
{
|
||||
ItemType: shard,
|
||||
ItemCount: 1
|
||||
}
|
||||
];
|
||||
addMiscItems(inventory, miscItemChanges);
|
||||
|
||||
// remove from suit
|
||||
suit.ArchonCrystalUpgrades![request.Slot] = {};
|
||||
|
||||
// remove bile
|
||||
const bile = inventory.InfestedFoundry!.Resources!.find(
|
||||
x => x.ItemType == "/Lotus/Types/Items/InfestedFoundry/HelminthBile"
|
||||
)!;
|
||||
bile.Count -= 300;
|
||||
|
||||
await inventory.save();
|
||||
|
||||
res.json({
|
||||
InventoryChanges: {
|
||||
MiscItems: miscItemChanges,
|
||||
InfestedFoundry: inventory.toJSON().InfestedFoundry
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "n": {
|
||||
// name the beast
|
||||
const request = getJSONfromString<IHelminthNameRequest>(String(req.body));
|
||||
const request = getJSONfromString(String(req.body)) as IHelminthNameRequest;
|
||||
const inventory = await getInventory(accountId);
|
||||
inventory.InfestedFoundry ??= {};
|
||||
inventory.InfestedFoundry.Name = request.newName;
|
||||
@ -103,233 +53,13 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
|
||||
break;
|
||||
}
|
||||
|
||||
case "c": {
|
||||
// consume items
|
||||
const request = getJSONfromString<IHelminthFeedRequest>(String(req.body));
|
||||
const inventory = await getInventory(accountId);
|
||||
inventory.InfestedFoundry ??= {};
|
||||
inventory.InfestedFoundry.Resources ??= [];
|
||||
|
||||
const miscItemChanges: IMiscItem[] = [];
|
||||
let totalPercentagePointsGained = 0;
|
||||
|
||||
const currentUnixSeconds = Math.trunc(new Date().getTime() / 1000);
|
||||
|
||||
for (const contribution of request.ResourceContributions) {
|
||||
const snack = ExportMisc.helminthSnacks[contribution.ItemType];
|
||||
|
||||
// tally items for removal
|
||||
const change = miscItemChanges.find(x => x.ItemType == contribution.ItemType);
|
||||
if (change) {
|
||||
change.ItemCount -= snack.count;
|
||||
} else {
|
||||
miscItemChanges.push({ ItemType: contribution.ItemType, ItemCount: snack.count * -1 });
|
||||
}
|
||||
|
||||
if (snack.type == "/Lotus/Types/Items/InfestedFoundry/HelminthAppetiteCooldownReducer") {
|
||||
// sentinent apetite
|
||||
let mostDislikedSnackRecord: IHelminthFoodRecord = { ItemType: "", Date: 0 };
|
||||
for (const resource of inventory.InfestedFoundry.Resources) {
|
||||
if (resource.RecentlyConvertedResources) {
|
||||
for (const record of resource.RecentlyConvertedResources) {
|
||||
if (record.Date > mostDislikedSnackRecord.Date) {
|
||||
mostDislikedSnackRecord = record;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.debug("helminth eats sentient resource; most disliked snack:", {
|
||||
type: mostDislikedSnackRecord.ItemType,
|
||||
date: mostDislikedSnackRecord.Date
|
||||
});
|
||||
mostDislikedSnackRecord.Date = currentUnixSeconds + 24 * 60 * 60; // Possibly unfaithful
|
||||
continue;
|
||||
}
|
||||
|
||||
let resource = inventory.InfestedFoundry.Resources.find(x => x.ItemType == snack.type);
|
||||
if (!resource) {
|
||||
resource =
|
||||
inventory.InfestedFoundry.Resources[
|
||||
inventory.InfestedFoundry.Resources.push({ ItemType: snack.type, Count: 0 }) - 1
|
||||
];
|
||||
}
|
||||
|
||||
resource.RecentlyConvertedResources ??= [];
|
||||
let record = resource.RecentlyConvertedResources.find(x => x.ItemType == contribution.ItemType);
|
||||
if (!record) {
|
||||
record =
|
||||
resource.RecentlyConvertedResources[
|
||||
resource.RecentlyConvertedResources.push({ ItemType: contribution.ItemType, Date: 0 }) - 1
|
||||
];
|
||||
}
|
||||
|
||||
const hoursRemaining = (record.Date - currentUnixSeconds) / 3600;
|
||||
const apetiteFactor = apetiteModel(hoursRemaining) / 30;
|
||||
logger.debug(`helminth eating ${contribution.ItemType} (+${(snack.gain * 100).toFixed(0)}%)`, {
|
||||
hoursRemaining,
|
||||
apetiteFactor
|
||||
});
|
||||
if (hoursRemaining >= 18) {
|
||||
record.Date = currentUnixSeconds + 72 * 60 * 60; // Possibly unfaithful
|
||||
} else {
|
||||
record.Date = currentUnixSeconds + 24 * 60 * 60;
|
||||
}
|
||||
|
||||
totalPercentagePointsGained += snack.gain * 100 * apetiteFactor; // 30% would be gain=0.3, so percentage points is equal to gain * 100.
|
||||
resource.Count += Math.trunc(snack.gain * 1000 * apetiteFactor); // 30% would be gain=0.3 or Count=300, so Count=gain*1000.
|
||||
if (resource.Count > 1000) resource.Count = 1000;
|
||||
}
|
||||
|
||||
const recipeChanges = addInfestedFoundryXP(inventory.InfestedFoundry, 666 * totalPercentagePointsGained);
|
||||
addRecipes(inventory, recipeChanges);
|
||||
addMiscItems(inventory, miscItemChanges);
|
||||
await inventory.save();
|
||||
|
||||
res.json({
|
||||
InventoryChanges: {
|
||||
Recipes: recipeChanges,
|
||||
InfestedFoundry: {
|
||||
XP: inventory.InfestedFoundry.XP,
|
||||
Resources: inventory.InfestedFoundry.Resources,
|
||||
Slots: inventory.InfestedFoundry.Slots
|
||||
},
|
||||
MiscItems: miscItemChanges
|
||||
}
|
||||
});
|
||||
case "o": // offerings update
|
||||
// {"OfferingsIndex":540,"SuitTypes":["/Lotus/Powersuits/PaxDuviricus/PaxDuviricusBaseSuit","/Lotus/Powersuits/Nezha/NezhaBaseSuit","/Lotus/Powersuits/Devourer/DevourerBaseSuit"],"Extra":false}
|
||||
res.status(404).end();
|
||||
break;
|
||||
}
|
||||
|
||||
case "o": {
|
||||
// offerings update
|
||||
const request = getJSONfromString<IHelminthOfferingsUpdate>(String(req.body));
|
||||
const inventory = await getInventory(accountId);
|
||||
inventory.InfestedFoundry ??= {};
|
||||
inventory.InfestedFoundry.InvigorationIndex = request.OfferingsIndex;
|
||||
inventory.InfestedFoundry.InvigorationSuitOfferings = request.SuitTypes;
|
||||
if (request.Extra) {
|
||||
inventory.InfestedFoundry.InvigorationsApplied = 0;
|
||||
}
|
||||
await inventory.save();
|
||||
res.json({
|
||||
InventoryChanges: {
|
||||
InfestedFoundry: inventory.toJSON().InfestedFoundry
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "a": {
|
||||
// subsume warframe
|
||||
const request = getJSONfromString<IHelminthSubsumeRequest>(String(req.body));
|
||||
const inventory = await getInventory(accountId);
|
||||
const recipe = getRecipe(request.Recipe)!;
|
||||
for (const ingredient of recipe.secretIngredients!) {
|
||||
const resource = inventory.InfestedFoundry!.Resources!.find(x => x.ItemType == ingredient.ItemType);
|
||||
if (resource) {
|
||||
resource.Count -= ingredient.ItemCount;
|
||||
}
|
||||
}
|
||||
const suit = inventory.Suits.id(request.SuitId.$oid)!;
|
||||
inventory.Suits.pull(suit);
|
||||
const consumedSuit: IConsumedSuit = { s: suit.ItemType };
|
||||
if (suit.Configs && suit.Configs[0] && suit.Configs[0].pricol) {
|
||||
consumedSuit.c = suit.Configs[0].pricol;
|
||||
}
|
||||
if ((inventory.InfestedFoundry!.XP ?? 0) < 73125_00) {
|
||||
inventory.InfestedFoundry!.Slots!--;
|
||||
}
|
||||
inventory.InfestedFoundry!.ConsumedSuits ??= [];
|
||||
inventory.InfestedFoundry!.ConsumedSuits.push(consumedSuit);
|
||||
inventory.InfestedFoundry!.LastConsumedSuit = suit;
|
||||
inventory.InfestedFoundry!.AbilityOverrideUnlockCooldown = new Date(
|
||||
new Date().getTime() + 24 * 60 * 60 * 1000
|
||||
);
|
||||
const recipeChanges = addInfestedFoundryXP(inventory.InfestedFoundry!, 1600_00);
|
||||
addRecipes(inventory, recipeChanges);
|
||||
await inventory.save();
|
||||
res.json({
|
||||
InventoryChanges: {
|
||||
Recipes: recipeChanges,
|
||||
RemovedIdItems: [
|
||||
{
|
||||
ItemId: request.SuitId
|
||||
}
|
||||
],
|
||||
SuitBin: {
|
||||
count: -1,
|
||||
platinum: 0,
|
||||
Slots: 1
|
||||
},
|
||||
InfestedFoundry: inventory.toJSON().InfestedFoundry
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "r": {
|
||||
// rush subsume
|
||||
const inventory = await getInventory(accountId);
|
||||
const currencyChanges = updateCurrency(inventory, 50, true);
|
||||
const recipeChanges = handleSubsumeCompletion(inventory);
|
||||
await inventory.save();
|
||||
res.json({
|
||||
InventoryChanges: {
|
||||
...currencyChanges,
|
||||
Recipes: recipeChanges,
|
||||
InfestedFoundry: inventory.toJSON().InfestedFoundry
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "u": {
|
||||
const request = getJSONfromString<IHelminthInvigorationRequest>(String(req.body));
|
||||
const inventory = await getInventory(accountId);
|
||||
const suit = inventory.Suits.id(request.SuitId.$oid)!;
|
||||
const upgradesExpiry = new Date(new Date().getTime() + 7 * 24 * 60 * 60 * 1000);
|
||||
suit.OffensiveUpgrade = request.OffensiveUpgradeType;
|
||||
suit.DefensiveUpgrade = request.DefensiveUpgradeType;
|
||||
suit.UpgradesExpiry = upgradesExpiry;
|
||||
const recipeChanges = addInfestedFoundryXP(inventory.InfestedFoundry!, 4800_00);
|
||||
addRecipes(inventory, recipeChanges);
|
||||
for (let i = 0; i != request.ResourceTypes.length; ++i) {
|
||||
inventory.InfestedFoundry!.Resources!.find(x => x.ItemType == request.ResourceTypes[i])!.Count -=
|
||||
request.ResourceCosts[i];
|
||||
}
|
||||
inventory.InfestedFoundry!.InvigorationsApplied ??= 0;
|
||||
inventory.InfestedFoundry!.InvigorationsApplied += 1;
|
||||
await inventory.save();
|
||||
res.json({
|
||||
SuitId: request.SuitId,
|
||||
OffensiveUpgrade: request.OffensiveUpgradeType,
|
||||
DefensiveUpgrade: request.DefensiveUpgradeType,
|
||||
UpgradesExpiry: toMongoDate(upgradesExpiry),
|
||||
InventoryChanges: {
|
||||
Recipes: recipeChanges,
|
||||
InfestedFoundry: inventory.toJSON().InfestedFoundry
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "custom_unlockall": {
|
||||
const inventory = await getInventory(accountId);
|
||||
inventory.InfestedFoundry ??= {};
|
||||
inventory.InfestedFoundry.XP ??= 0;
|
||||
if (151875_00 > inventory.InfestedFoundry.XP) {
|
||||
const recipeChanges = addInfestedFoundryXP(
|
||||
inventory.InfestedFoundry,
|
||||
151875_00 - inventory.InfestedFoundry.XP
|
||||
);
|
||||
addRecipes(inventory, recipeChanges);
|
||||
await inventory.save();
|
||||
}
|
||||
res.end();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Error(`unhandled infestedFoundry mode: ${String(req.query.mode)}`);
|
||||
throw new Error(`unhandled infestedFoundry mode: ${req.query.mode}`);
|
||||
}
|
||||
};
|
||||
|
||||
@ -340,166 +70,21 @@ interface IShardInstallRequest {
|
||||
Color: string;
|
||||
}
|
||||
|
||||
interface IShardUninstallRequest {
|
||||
SuitId: IOid;
|
||||
Slot: number;
|
||||
}
|
||||
|
||||
interface IHelminthNameRequest {
|
||||
newName: string;
|
||||
}
|
||||
|
||||
interface IHelminthFeedRequest {
|
||||
ResourceContributions: {
|
||||
ItemType: string;
|
||||
Date: number; // unix timestamp
|
||||
}[];
|
||||
}
|
||||
|
||||
export const addInfestedFoundryXP = (infestedFoundry: IInfestedFoundryDatabase, delta: number): ITypeCount[] => {
|
||||
const recipeChanges: ITypeCount[] = [];
|
||||
infestedFoundry.XP ??= 0;
|
||||
const prevXP = infestedFoundry.XP;
|
||||
infestedFoundry.XP += delta;
|
||||
if (prevXP < 2250_00 && infestedFoundry.XP >= 2250_00) {
|
||||
infestedFoundry.Slots ??= 0;
|
||||
infestedFoundry.Slots += 3;
|
||||
}
|
||||
if (prevXP < 5625_00 && infestedFoundry.XP >= 5625_00) {
|
||||
recipeChanges.push({
|
||||
ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthShieldsBlueprint",
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
if (prevXP < 10125_00 && infestedFoundry.XP >= 10125_00) {
|
||||
recipeChanges.push({ ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthHackBlueprint", ItemCount: 1 });
|
||||
}
|
||||
if (prevXP < 15750_00 && infestedFoundry.XP >= 15750_00) {
|
||||
infestedFoundry.Slots ??= 0;
|
||||
infestedFoundry.Slots += 10;
|
||||
}
|
||||
if (prevXP < 22500_00 && infestedFoundry.XP >= 22500_00) {
|
||||
recipeChanges.push({
|
||||
ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthAmmoEfficiencyBlueprint",
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
if (prevXP < 30375_00 && infestedFoundry.XP >= 30375_00) {
|
||||
recipeChanges.push({ ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthStunBlueprint", ItemCount: 1 });
|
||||
}
|
||||
if (prevXP < 39375_00 && infestedFoundry.XP >= 39375_00) {
|
||||
infestedFoundry.Slots ??= 0;
|
||||
infestedFoundry.Slots += 20;
|
||||
}
|
||||
if (prevXP < 60750_00 && infestedFoundry.XP >= 60750_00) {
|
||||
recipeChanges.push({ ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthStatusBlueprint", ItemCount: 1 });
|
||||
}
|
||||
if (prevXP < 73125_00 && infestedFoundry.XP >= 73125_00) {
|
||||
infestedFoundry.Slots = 1;
|
||||
}
|
||||
if (prevXP < 86625_00 && infestedFoundry.XP >= 86625_00) {
|
||||
recipeChanges.push({
|
||||
ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthShieldArmorBlueprint",
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
if (prevXP < 101250_00 && infestedFoundry.XP >= 101250_00) {
|
||||
recipeChanges.push({
|
||||
ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthProcBlockBlueprint",
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
if (prevXP < 117000_00 && infestedFoundry.XP >= 117000_00) {
|
||||
recipeChanges.push({
|
||||
ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthEnergyShareBlueprint",
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
if (prevXP < 133875_00 && infestedFoundry.XP >= 133875_00) {
|
||||
recipeChanges.push({
|
||||
ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthMaxStatusBlueprint",
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
if (prevXP < 151875_00 && infestedFoundry.XP >= 151875_00) {
|
||||
recipeChanges.push({
|
||||
ItemType: "/Lotus/Types/Recipes/AbilityOverrides/HelminthTreasureBlueprint",
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
return recipeChanges;
|
||||
};
|
||||
|
||||
interface IHelminthSubsumeRequest {
|
||||
SuitId: IOid;
|
||||
Recipe: string;
|
||||
}
|
||||
|
||||
export const handleSubsumeCompletion = (inventory: TInventoryDatabaseDocument): ITypeCount[] => {
|
||||
const [recipeType] = Object.entries(ExportRecipes).find(
|
||||
([_recipeType, recipe]) =>
|
||||
recipe.secretIngredientAction == "SIA_WARFRAME_ABILITY" &&
|
||||
recipe.secretIngredients![0].ItemType == inventory.InfestedFoundry!.LastConsumedSuit!.ItemType
|
||||
)!;
|
||||
inventory.InfestedFoundry!.LastConsumedSuit = undefined;
|
||||
inventory.InfestedFoundry!.AbilityOverrideUnlockCooldown = undefined;
|
||||
const recipeChanges: ITypeCount[] = [
|
||||
{
|
||||
ItemType: recipeType,
|
||||
ItemCount: 1
|
||||
}
|
||||
];
|
||||
addRecipes(inventory, recipeChanges);
|
||||
return recipeChanges;
|
||||
};
|
||||
|
||||
interface IHelminthOfferingsUpdate {
|
||||
OfferingsIndex: number;
|
||||
SuitTypes: string[];
|
||||
Extra: boolean;
|
||||
}
|
||||
|
||||
interface IHelminthInvigorationRequest {
|
||||
SuitId: IOid;
|
||||
OffensiveUpgradeType: string;
|
||||
DefensiveUpgradeType: string;
|
||||
ResourceTypes: string[];
|
||||
ResourceCosts: number[];
|
||||
}
|
||||
|
||||
// A fitted model for observed apetite values. Likely slightly inaccurate.
|
||||
//
|
||||
// Hours remaining, percentage points gained (out of 30 total)
|
||||
// 0, 30
|
||||
// 5, 25.8
|
||||
// 10, 21.6
|
||||
// 12, 20
|
||||
// 16, 16.6
|
||||
// 17, 15.8
|
||||
// 18, 15
|
||||
// 20, 15
|
||||
// 24, 15
|
||||
// 36, 15
|
||||
// 40, 13.6
|
||||
// 47, 11.3
|
||||
// 48, 11
|
||||
// 50, 10.3
|
||||
// 60, 7
|
||||
// 70, 3.6
|
||||
// 71, 3.3
|
||||
// 72, 3
|
||||
const apetiteModel = (x: number): number => {
|
||||
if (x <= 0) {
|
||||
return 30;
|
||||
}
|
||||
if (x < 18) {
|
||||
return -0.84 * x + 30;
|
||||
}
|
||||
if (x <= 36) {
|
||||
return 15;
|
||||
}
|
||||
if (x < 71.9) {
|
||||
return -0.3327892 * x + 26.94135;
|
||||
}
|
||||
return 3;
|
||||
const colorToShard: Record<string, string> = {
|
||||
ACC_RED: "/Lotus/Types/Gameplay/NarmerSorties/ArchonCrystalAmar",
|
||||
ACC_RED_MYTHIC: "/Lotus/Types/Gameplay/NarmerSorties/ArchonCrystalAmarMythic",
|
||||
ACC_YELLOW: "/Lotus/Types/Gameplay/NarmerSorties/ArchonCrystalNira",
|
||||
ACC_YELLOW_MYTHIC: "/Lotus/Types/Gameplay/NarmerSorties/ArchonCrystalNiraMythic",
|
||||
ACC_BLUE: "/Lotus/Types/Gameplay/NarmerSorties/ArchonCrystalBoreal",
|
||||
ACC_BLUE_MYTHIC: "/Lotus/Types/Gameplay/NarmerSorties/ArchonCrystalBorealMythic",
|
||||
ACC_GREEN: "/Lotus/Types/Gameplay/NarmerSorties/ArchonCrystalGreen",
|
||||
ACC_GREEN_MYTHIC: "/Lotus/Types/Gameplay/NarmerSorties/ArchonCrystalGreenMythic",
|
||||
ACC_ORANGE: "/Lotus/Types/Gameplay/NarmerSorties/ArchonCrystalOrange",
|
||||
ACC_ORANGE_MYTHIC: "/Lotus/Types/Gameplay/NarmerSorties/ArchonCrystalOrangeMythic",
|
||||
ACC_PURPLE: "/Lotus/Types/Gameplay/NarmerSorties/ArchonCrystalViolet",
|
||||
ACC_PURPLE_MYTHIC: "/Lotus/Types/Gameplay/NarmerSorties/ArchonCrystalVioletMythic"
|
||||
};
|
||||
|
@ -1,149 +1,71 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getAccountForRequest } from "@/src/services/loginService";
|
||||
import { Inventory, TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { toInventoryResponse } from "@/src/helpers/inventoryHelpers";
|
||||
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
|
||||
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, EquipmentFeatures } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||
import {
|
||||
ExportCustoms,
|
||||
ExportFlavour,
|
||||
ExportRegions,
|
||||
ExportResources,
|
||||
ExportVirtuals
|
||||
} from "warframe-public-export-plus";
|
||||
import { handleSubsumeCompletion } from "./infestedFoundryController";
|
||||
import { allDailyAffiliationKeys } from "@/src/services/inventoryService";
|
||||
import { IInventoryDatabase } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
//import new_inventory from "@/static/fixed_responses/postTutorialInventory.json";
|
||||
|
||||
export const inventoryController: RequestHandler = async (request, response) => {
|
||||
const account = await getAccountForRequest(request);
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
const inventoryController: RequestHandler = async (request, response) => {
|
||||
let accountId;
|
||||
try {
|
||||
accountId = await getAccountIdForRequest(request);
|
||||
} catch (e) {
|
||||
response.status(400).send("Log-in expired");
|
||||
return;
|
||||
}
|
||||
|
||||
const inventory = await Inventory.findOne({ accountOwnerId: account._id.toString() });
|
||||
const inventory = await Inventory.findOne({ accountOwnerId: accountId });
|
||||
|
||||
if (!inventory) {
|
||||
response.status(400).json({ error: "inventory was undefined" });
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle daily reset
|
||||
const today: number = Math.trunc(new Date().getTime() / 86400000);
|
||||
if (account.LastLoginDay != today) {
|
||||
account.LastLoginDay = today;
|
||||
await account.save();
|
||||
//TODO: make a function that converts from database representation to client
|
||||
const inventoryJSON: IInventoryDatabase = inventory.toJSON();
|
||||
console.log(inventoryJSON.Ships);
|
||||
|
||||
for (const key of allDailyAffiliationKeys) {
|
||||
inventory[key] = 16000 + inventory.PlayerLevel * 500;
|
||||
}
|
||||
inventory.DailyFocus = 250000 + inventory.PlayerLevel * 5000;
|
||||
await inventory.save();
|
||||
}
|
||||
const inventoryResponse = toInventoryResponse(inventoryJSON);
|
||||
|
||||
if (
|
||||
inventory.InfestedFoundry &&
|
||||
inventory.InfestedFoundry.AbilityOverrideUnlockCooldown &&
|
||||
new Date() >= inventory.InfestedFoundry.AbilityOverrideUnlockCooldown
|
||||
) {
|
||||
handleSubsumeCompletion(inventory);
|
||||
await inventory.save();
|
||||
}
|
||||
|
||||
response.json(await getInventoryResponse(inventory, "xpBasedLevelCapDisabled" in request.query));
|
||||
};
|
||||
|
||||
export const getInventoryResponse = async (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
xpBasedLevelCapDisabled: boolean
|
||||
): Promise<IInventoryClient> => {
|
||||
const inventoryWithLoadOutPresets = await inventory.populate<{ LoadOutPresets: ILoadoutDatabase }>(
|
||||
"LoadOutPresets"
|
||||
);
|
||||
const inventoryWithLoadOutPresetsAndShips = await inventoryWithLoadOutPresets.populate<{ Ships: IShipInventory }>(
|
||||
"Ships"
|
||||
);
|
||||
const inventoryResponse = inventoryWithLoadOutPresetsAndShips.toJSON<IInventoryClient>();
|
||||
|
||||
if (config.infiniteCredits) {
|
||||
if (config.infiniteResources) {
|
||||
inventoryResponse.RegularCredits = 999999999;
|
||||
}
|
||||
if (config.infinitePlatinum) {
|
||||
inventoryResponse.PremiumCreditsFree = 999999999;
|
||||
inventoryResponse.PremiumCredits = 999999999;
|
||||
}
|
||||
if (config.infiniteEndo) {
|
||||
inventoryResponse.FusionPoints = 999999999;
|
||||
}
|
||||
if (config.infiniteRegalAya) {
|
||||
inventoryResponse.PrimeTokens = 999999999;
|
||||
}
|
||||
|
||||
if (config.skipAllDialogue) {
|
||||
inventoryResponse.TauntHistory = [
|
||||
{
|
||||
node: "TreasureTutorial",
|
||||
state: "TS_COMPLETED"
|
||||
}
|
||||
];
|
||||
for (const str of allDialogue) {
|
||||
addString(inventoryResponse.NodeIntrosCompleted, str);
|
||||
}
|
||||
}
|
||||
// if (config.unlockAllMissions) {
|
||||
// //inventoryResponse.Missions = allMissions;
|
||||
// //inventoryResponse.NodeIntrosCompleted.push("TeshinHardModeUnlocked");
|
||||
// }
|
||||
|
||||
if (config.unlockAllMissions) {
|
||||
inventoryResponse.Missions = [];
|
||||
for (const tag of Object.keys(ExportRegions)) {
|
||||
inventoryResponse.Missions.push({
|
||||
Completes: 1,
|
||||
Tier: 1,
|
||||
Tag: tag
|
||||
});
|
||||
}
|
||||
addString(inventoryResponse.NodeIntrosCompleted, "TeshinHardModeUnlocked");
|
||||
}
|
||||
// if (config.unlockAllMissions) {
|
||||
// //inventoryResponse.Missions = allMissions;
|
||||
// //addString(inventoryResponse.NodeIntrosCompleted, "TeshinHardModeUnlocked");
|
||||
// }
|
||||
|
||||
if (config.unlockAllShipDecorations) {
|
||||
inventoryResponse.ShipDecorations = [];
|
||||
for (const [uniqueName, item] of Object.entries(ExportResources)) {
|
||||
if (item.productCategory == "ShipDecorations") {
|
||||
inventoryResponse.ShipDecorations.push({ ItemType: uniqueName, ItemCount: 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (config.unlockAllFlavourItems) {
|
||||
// inventoryResponse.FlavourItems = [];
|
||||
// for (const uniqueName in ExportFlavour) {
|
||||
// inventoryResponse.FlavourItems.push({ ItemType: uniqueName });
|
||||
// }
|
||||
// }
|
||||
|
||||
if (config.unlockAllFlavourItems) {
|
||||
inventoryResponse.FlavourItems = [];
|
||||
for (const uniqueName in ExportFlavour) {
|
||||
inventoryResponse.FlavourItems.push({ ItemType: uniqueName });
|
||||
}
|
||||
}
|
||||
|
||||
if (config.unlockAllSkins) {
|
||||
const missingWeaponSkins = new Set(Object.keys(ExportCustoms));
|
||||
inventoryResponse.WeaponSkins.forEach(x => missingWeaponSkins.delete(x.ItemType));
|
||||
for (const uniqueName of missingWeaponSkins) {
|
||||
inventoryResponse.WeaponSkins.push({
|
||||
ItemId: {
|
||||
$oid: "ca70ca70ca70ca70" + catBreadHash(uniqueName).toString(16).padStart(8, "0")
|
||||
},
|
||||
ItemType: uniqueName
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (config.unlockAllCapturaScenes) {
|
||||
for (const uniqueName of Object.keys(ExportResources)) {
|
||||
if (resourceInheritsFrom(uniqueName, "/Lotus/Types/Items/MiscItems/PhotoboothTile")) {
|
||||
inventoryResponse.MiscItems.push({
|
||||
ItemType: uniqueName,
|
||||
ItemCount: 1
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (config.unlockAllSkins) {
|
||||
// inventoryResponse.WeaponSkins = [];
|
||||
// for (const uniqueName in ExportCustoms) {
|
||||
// inventoryResponse.WeaponSkins.push({
|
||||
// ItemId: {
|
||||
// $id: "000000000000000000000000"
|
||||
// },
|
||||
// ItemType: uniqueName
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
if (typeof config.spoofMasteryRank === "number" && config.spoofMasteryRank >= 0) {
|
||||
inventoryResponse.PlayerLevel = config.spoofMasteryRank;
|
||||
if (!xpBasedLevelCapDisabled) {
|
||||
if (!("xpBasedLevelCapDisabled" in request.query)) {
|
||||
// This client has not been patched to accept any mastery rank, need to fake the XP.
|
||||
inventoryResponse.XPInfo = [];
|
||||
let numFrames = getExpRequiredForMr(Math.min(config.spoofMasteryRank, 5030)) / 6000;
|
||||
@ -156,79 +78,18 @@ export const getInventoryResponse = async (
|
||||
}
|
||||
}
|
||||
|
||||
if (config.universalPolarityEverywhere) {
|
||||
const Polarity: IPolarity[] = [];
|
||||
for (let i = 0; i != 12; ++i) {
|
||||
Polarity.push({
|
||||
Slot: i,
|
||||
Value: ArtifactPolarity.Any
|
||||
});
|
||||
}
|
||||
for (const key of equipmentKeys) {
|
||||
if (key in inventoryResponse) {
|
||||
for (const equipment of inventoryResponse[key]) {
|
||||
equipment.Polarity = Polarity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.unlockDoubleCapacityPotatoesEverywhere) {
|
||||
for (const key of equipmentKeys) {
|
||||
if (key in inventoryResponse) {
|
||||
for (const equipment of inventoryResponse[key]) {
|
||||
equipment.Features ??= 0;
|
||||
equipment.Features |= EquipmentFeatures.DOUBLE_CAPACITY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.unlockExilusEverywhere) {
|
||||
for (const key of equipmentKeys) {
|
||||
if (key in inventoryResponse) {
|
||||
for (const equipment of inventoryResponse[key]) {
|
||||
equipment.Features ??= 0;
|
||||
equipment.Features |= EquipmentFeatures.UTILITY_SLOT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.unlockArcanesEverywhere) {
|
||||
for (const key of equipmentKeys) {
|
||||
if (key in inventoryResponse) {
|
||||
for (const equipment of inventoryResponse[key]) {
|
||||
equipment.Features ??= 0;
|
||||
equipment.Features |= EquipmentFeatures.ARCANE_SLOT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.noDailyStandingLimits) {
|
||||
for (const key of allDailyAffiliationKeys) {
|
||||
inventoryResponse[key] = 999_999;
|
||||
}
|
||||
}
|
||||
|
||||
// Fix for #380
|
||||
inventoryResponse.NextRefill = { $date: { $numberLong: "9999999999999" } };
|
||||
|
||||
// This determines if the "void fissures" tab is shown in navigation.
|
||||
inventoryResponse.HasOwnedVoidProjectionsPreviously = true;
|
||||
|
||||
// Omitting this field so opening the navigation resyncs the inventory which is more desirable for typical usage.
|
||||
//inventoryResponse.LastInventorySync = toOid(new Types.ObjectId());
|
||||
|
||||
return inventoryResponse;
|
||||
response.json(inventoryResponse);
|
||||
};
|
||||
|
||||
export const addString = (arr: string[], str: string): void => {
|
||||
/*
|
||||
const addString = (arr: string[], str: string): void => {
|
||||
if (!arr.find(x => x == str)) {
|
||||
arr.push(str);
|
||||
}
|
||||
};
|
||||
};*/
|
||||
|
||||
const getExpRequiredForMr = (rank: number): number => {
|
||||
if (rank <= 30) {
|
||||
@ -237,29 +98,4 @@ const getExpRequiredForMr = (rank: number): number => {
|
||||
return 2_250_000 + 147_500 * (rank - 30);
|
||||
};
|
||||
|
||||
const resourceInheritsFrom = (resourceName: string, targetName: string): boolean => {
|
||||
let parentName = resourceGetParent(resourceName);
|
||||
for (; parentName != undefined; parentName = resourceGetParent(parentName)) {
|
||||
if (parentName == targetName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const resourceGetParent = (resourceName: string): string | undefined => {
|
||||
if (resourceName in ExportResources) {
|
||||
return ExportResources[resourceName].parentName;
|
||||
}
|
||||
return ExportVirtuals[resourceName]?.parentName;
|
||||
};
|
||||
|
||||
// This is FNV1a-32 except operating under modulus 2^31 because JavaScript is stinky and likes producing negative integers out of nowhere.
|
||||
const catBreadHash = (name: string): number => {
|
||||
let hash = 2166136261;
|
||||
for (let i = 0; i != name.length; ++i) {
|
||||
hash = (hash ^ name.charCodeAt(i)) & 0x7fffffff;
|
||||
hash = (hash * 16777619) & 0x7fffffff;
|
||||
}
|
||||
return hash;
|
||||
};
|
||||
export { inventoryController };
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||
import { updateCurrency } from "@/src/services/inventoryService";
|
||||
import { RequestHandler } from "express";
|
||||
import { updateSlots } from "@/src/services/inventoryService";
|
||||
import { InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
@ -18,16 +18,19 @@ import { InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
number of frames = extra - slots + 2
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const inventorySlotsController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
//const body = JSON.parse(req.body as string) as IInventorySlotsRequest;
|
||||
|
||||
//console.log(body);
|
||||
|
||||
//TODO: check which slot was purchased because pvpBonus is also possible
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
const currencyChanges = updateCurrency(inventory, 20, true);
|
||||
updateSlots(inventory, InventorySlot.PVE_LOADOUTS, 1, 1);
|
||||
await inventory.save();
|
||||
const currencyChanges = await updateCurrency(20, true, accountId);
|
||||
await updateSlots(accountId, InventorySlot.PVE_LOADOUTS, 1, 1);
|
||||
|
||||
//console.log({ InventoryChanges: currencyChanges }, " added loadout changes:");
|
||||
|
||||
res.json({ InventoryChanges: currencyChanges });
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ const joinSessionController: RequestHandler = (_req, res) => {
|
||||
logger.debug(`JoinSession Request`, { reqBody });
|
||||
const req = JSON.parse(String(_req.body));
|
||||
const session = getSessionByID(req.sessionIds[0] as string);
|
||||
res.json({ rewardSeed: session?.rewardSeed, sessionId: { $oid: session?.sessionId } });
|
||||
res.json({ rewardSeed: session?.rewardSeed, sessionId: { $id: session?.sessionId } });
|
||||
};
|
||||
|
||||
export { joinSessionController };
|
||||
|
@ -1,51 +1,43 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
import { config } from "@/src/services/configService";
|
||||
import { buildConfig } from "@/src/services/buildConfigService";
|
||||
import buildConfig from "@/static/data/buildConfig.json";
|
||||
|
||||
import { toLoginRequest } from "@/src/helpers/loginHelpers";
|
||||
import { Account } from "@/src/models/loginModel";
|
||||
import { createAccount, isCorrectPassword, isNameTaken } from "@/src/services/loginService";
|
||||
import { IDatabaseAccountJson, ILoginRequest, ILoginResponse } from "@/src/types/loginTypes";
|
||||
import { DTLS, groups, HUB, platformCDNs } from "@/static/fixed_responses/login_static";
|
||||
import { createAccount, isCorrectPassword } from "@/src/services/loginService";
|
||||
import { ILoginResponse } from "@/src/types/loginTypes";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
|
||||
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
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
const loginController: RequestHandler = async (request, response) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-argument
|
||||
const body = JSON.parse(request.body); // parse octet stream of json data to json object
|
||||
const loginRequest = toLoginRequest(body);
|
||||
|
||||
const account = await Account.findOne({ email: loginRequest.email });
|
||||
const nonce = Math.round(Math.random() * Number.MAX_SAFE_INTEGER);
|
||||
|
||||
const buildLabel: string =
|
||||
typeof request.query.buildLabel == "string"
|
||||
? request.query.buildLabel.split(" ").join("+")
|
||||
: buildConfig.buildLabel;
|
||||
|
||||
if (!account && config.autoCreateAccount && loginRequest.ClientType != "webui") {
|
||||
try {
|
||||
const nameFromEmail = loginRequest.email.substring(0, loginRequest.email.indexOf("@"));
|
||||
let name = nameFromEmail;
|
||||
if (await isNameTaken(name)) {
|
||||
let suffix = 0;
|
||||
do {
|
||||
++suffix;
|
||||
name = nameFromEmail + suffix;
|
||||
} while (await isNameTaken(name));
|
||||
}
|
||||
const newAccount = await createAccount({
|
||||
email: loginRequest.email,
|
||||
password: loginRequest.password,
|
||||
DisplayName: name,
|
||||
CountryCode: loginRequest.lang.toUpperCase(),
|
||||
ClientType: loginRequest.ClientType,
|
||||
CrossPlatformAllowed: true,
|
||||
ForceLogoutVersion: 0,
|
||||
ConsentNeeded: false,
|
||||
TrackedSettings: [],
|
||||
Nonce: nonce,
|
||||
LatestEventMessageDate: new Date(0)
|
||||
DisplayName: loginRequest.email.substring(0, loginRequest.email.indexOf("@")),
|
||||
Nonce: nonce
|
||||
});
|
||||
logger.debug("created new account");
|
||||
response.json(createLoginResponse(newAccount, buildLabel));
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { email, password, ...databaseAccount } = newAccount;
|
||||
const newLoginResponse: ILoginResponse = {
|
||||
...databaseAccount,
|
||||
BuildLabel: buildConfig.buildLabel,
|
||||
NatHash: "0",
|
||||
SteamId: "0"
|
||||
};
|
||||
|
||||
response.json(newLoginResponse);
|
||||
return;
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error) {
|
||||
@ -63,34 +55,18 @@ export const loginController: RequestHandler = async (request, response) => {
|
||||
if (account.Nonce == 0 || loginRequest.ClientType != "webui") {
|
||||
account.Nonce = nonce;
|
||||
}
|
||||
if (loginRequest.ClientType != "webui") {
|
||||
account.CountryCode = loginRequest.lang.toUpperCase();
|
||||
}
|
||||
|
||||
await account.save();
|
||||
|
||||
response.json(createLoginResponse(account.toJSON(), buildLabel));
|
||||
const { email, password, ...databaseAccount } = account.toJSON();
|
||||
const newLoginResponse: ILoginResponse = {
|
||||
...databaseAccount,
|
||||
BuildLabel: buildConfig.buildLabel,
|
||||
NatHash: "0",
|
||||
SteamId: "0"
|
||||
};
|
||||
|
||||
response.json(newLoginResponse);
|
||||
};
|
||||
|
||||
const createLoginResponse = (account: IDatabaseAccountJson, buildLabel: string): ILoginResponse => {
|
||||
return {
|
||||
id: account.id,
|
||||
DisplayName: account.DisplayName,
|
||||
CountryCode: account.CountryCode,
|
||||
ClientType: account.ClientType,
|
||||
CrossPlatformAllowed: account.CrossPlatformAllowed,
|
||||
ForceLogoutVersion: account.ForceLogoutVersion,
|
||||
AmazonAuthToken: account.AmazonAuthToken,
|
||||
AmazonRefreshToken: account.AmazonRefreshToken,
|
||||
ConsentNeeded: account.ConsentNeeded,
|
||||
TrackedSettings: account.TrackedSettings,
|
||||
Nonce: account.Nonce,
|
||||
Groups: groups,
|
||||
platformCDNs: platformCDNs,
|
||||
NRS: [config.myAddress],
|
||||
DTLS: DTLS,
|
||||
IRC: config.myIrcAddresses ?? [config.myAddress],
|
||||
HUB: HUB,
|
||||
BuildLabel: buildLabel,
|
||||
MatchmakingBuildId: buildConfig.matchmakingBuildId
|
||||
};
|
||||
};
|
||||
export { loginController };
|
||||
|
@ -2,6 +2,7 @@ import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { Account } from "@/src/models/loginModel";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
const logoutController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const account = await Account.findOne({ _id: accountId });
|
||||
|
@ -1,12 +1,10 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { missionInventoryUpdate } from "@/src/services/inventoryService";
|
||||
import { combineRewardAndLootInventory, getRewards } from "@/src/services/missionInventoryUpdateService";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { getAccountIdForRequest } 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 "./inventoryController";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
|
||||
/*
|
||||
**** INPUT ****
|
||||
- [ ] crossPlaySetting
|
||||
@ -32,13 +30,13 @@ import { logger } from "@/src/utils/logger";
|
||||
- [ ] hosts
|
||||
- [x] ChallengeProgress
|
||||
- [ ] SeasonChallengeHistory
|
||||
- [ ] PS (anticheat data)
|
||||
- [ ] PS (Passive anti-cheat data which includes your username, module list, process list, and system name.)
|
||||
- [ ] ActiveDojoColorResearch
|
||||
- [x] RewardInfo
|
||||
- [ ] ReceivedCeremonyMsg
|
||||
- [ ] LastCeremonyResetDate
|
||||
- [ ] MissionPTS (Used to validate the mission/alive time above.)
|
||||
- [ ] RepHash
|
||||
- [ ] RepHash (A hash from the replication manager/RepMgr Unknown what it does.)
|
||||
- [ ] EndOfMatchUpload
|
||||
- [ ] ObjectiveReached
|
||||
- [ ] FpsAvg
|
||||
@ -46,40 +44,37 @@ import { logger } from "@/src/utils/logger";
|
||||
- [ ] FpsMax
|
||||
- [ ] FpsSamples
|
||||
*/
|
||||
//move credit calc in here, return MissionRewards: [] if no reward info
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const missionInventoryUpdateController: RequestHandler = async (req, res): Promise<void> => {
|
||||
const missionInventoryUpdateController: RequestHandler = async (req, res): Promise<void> => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const missionReport = getJSONfromString<IMissionInventoryUpdateRequest>((req.body as string).toString());
|
||||
logger.debug("mission report:", missionReport);
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventoryUpdates = addMissionInventoryUpdates(inventory, missionReport);
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-call
|
||||
const lootInventory = getJSONfromString(req.body.toString()) as IMissionInventoryUpdateRequest;
|
||||
|
||||
if (missionReport.MissionStatus !== "GS_SUCCESS") {
|
||||
await inventory.save();
|
||||
const inventoryResponse = await getInventoryResponse(inventory, true);
|
||||
logger.debug("missionInventoryUpdate with lootInventory =", lootInventory);
|
||||
|
||||
const { InventoryChanges, MissionRewards } = getRewards(lootInventory);
|
||||
|
||||
const { combinedInventoryChanges, TotalCredits, CreditsBonus, MissionCredits } = combineRewardAndLootInventory(
|
||||
InventoryChanges,
|
||||
lootInventory
|
||||
);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const InventoryJson = JSON.stringify(await missionInventoryUpdate(combinedInventoryChanges, accountId));
|
||||
res.json({
|
||||
InventoryJson: JSON.stringify(inventoryResponse),
|
||||
MissionRewards: []
|
||||
// InventoryJson, // this part will reset game data and missions will be locked
|
||||
MissionRewards,
|
||||
InventoryChanges,
|
||||
TotalCredits,
|
||||
CreditsBonus,
|
||||
MissionCredits
|
||||
});
|
||||
return;
|
||||
} catch (err) {
|
||||
console.error("Error parsing JSON data:", err);
|
||||
}
|
||||
|
||||
const { MissionRewards, inventoryChanges, credits } = await addMissionRewards(inventory, missionReport);
|
||||
|
||||
await inventory.save();
|
||||
const inventoryResponse = await getInventoryResponse(inventory, true);
|
||||
|
||||
//TODO: figure out when to send inventory. it is needed for many cases.
|
||||
res.json({
|
||||
InventoryJson: JSON.stringify(inventoryResponse),
|
||||
InventoryChanges: inventoryChanges,
|
||||
MissionRewards,
|
||||
...credits,
|
||||
...inventoryUpdates,
|
||||
FusionPoints: inventoryChanges?.FusionPoints
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
@ -92,3 +87,5 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
|
||||
- [x] InventoryChanges
|
||||
- [x] FusionPoints
|
||||
*/
|
||||
|
||||
export { missionInventoryUpdateController };
|
||||
|
@ -5,11 +5,7 @@ import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { getInventory, updateCurrency, addEquipment, addMiscItems } from "@/src/services/inventoryService";
|
||||
|
||||
const modularWeaponTypes: Record<string, TEquipmentKey> = {
|
||||
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimary": "LongGuns",
|
||||
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryBeam": "LongGuns",
|
||||
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryLauncher": "LongGuns",
|
||||
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryShotgun": "LongGuns",
|
||||
"/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimarySniper": "LongGuns",
|
||||
"/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondary": "Pistols",
|
||||
"/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryBeam": "Pistols",
|
||||
"/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryShotgun": "Pistols",
|
||||
@ -27,19 +23,26 @@ interface IModularCraftRequest {
|
||||
Parts: string[];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const modularWeaponCraftingController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const data = getJSONfromString<IModularCraftRequest>(String(req.body));
|
||||
const data = getJSONfromString(String(req.body)) as IModularCraftRequest;
|
||||
if (!(data.WeaponType in modularWeaponTypes)) {
|
||||
throw new Error(`unknown modular weapon type: ${data.WeaponType}`);
|
||||
}
|
||||
const category = modularWeaponTypes[data.WeaponType];
|
||||
const inventory = await getInventory(accountId);
|
||||
|
||||
// Give weapon
|
||||
const weapon = addEquipment(inventory, category, data.WeaponType, data.Parts);
|
||||
const weapon = await addEquipment(category, data.WeaponType, accountId, data.Parts);
|
||||
|
||||
// Remove credits & parts
|
||||
// Remove credits
|
||||
const currencyChanges = await updateCurrency(
|
||||
category == "Hoverboards" || category == "MoaPets" ? 5000 : 4000,
|
||||
false,
|
||||
accountId
|
||||
);
|
||||
|
||||
// Remove parts
|
||||
const miscItemChanges = [];
|
||||
for (const part of data.Parts) {
|
||||
miscItemChanges.push({
|
||||
@ -47,11 +50,7 @@ export const modularWeaponCraftingController: RequestHandler = async (req, res)
|
||||
ItemCount: -1
|
||||
});
|
||||
}
|
||||
const currencyChanges = updateCurrency(
|
||||
inventory,
|
||||
category == "Hoverboards" || category == "MoaPets" ? 5000 : 4000,
|
||||
false
|
||||
);
|
||||
const inventory = await getInventory(accountId);
|
||||
addMiscItems(inventory, miscItemChanges);
|
||||
await inventory.save();
|
||||
|
||||
|
@ -8,10 +8,11 @@ interface INameWeaponRequest {
|
||||
ItemName: string;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const nameWeaponController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const body = getJSONfromString<INameWeaponRequest>(String(req.body));
|
||||
const body = getJSONfromString(String(req.body)) as INameWeaponRequest;
|
||||
const item = inventory[req.query.Category as string as TEquipmentKey].find(
|
||||
item => item._id.toString() == (req.query.ItemId as string)
|
||||
)!;
|
||||
@ -20,9 +21,8 @@ export const nameWeaponController: RequestHandler = async (req, res) => {
|
||||
} else {
|
||||
item.ItemName = undefined;
|
||||
}
|
||||
const currencyChanges = updateCurrency(inventory, "webui" in req.query ? 0 : 15, true);
|
||||
await inventory.save();
|
||||
res.json({
|
||||
InventoryChanges: currencyChanges
|
||||
InventoryChanges: await updateCurrency("webui" in req.query ? 0 : 15, true, accountId)
|
||||
});
|
||||
};
|
||||
|
@ -1,31 +0,0 @@
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { IPlayerSkills } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const playerSkillsController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
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]++;
|
||||
await inventory.save();
|
||||
|
||||
res.json({
|
||||
Pool: request.Pool,
|
||||
PoolInc: -cost,
|
||||
Skill: request.Skill,
|
||||
Rank: oldRank + 1
|
||||
});
|
||||
};
|
||||
|
||||
interface IPlayerSkillsRequest {
|
||||
Pool: string;
|
||||
Skill: string;
|
||||
}
|
||||
|
||||
const drifterCosts = [20, 25, 30, 45, 65, 90, 125, 160, 205, 255];
|
@ -3,6 +3,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { addMiscItems, getInventory } from "@/src/services/inventoryService";
|
||||
import { ExportRelics, IRelic } from "warframe-public-export-plus";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const projectionManagerController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
|
@ -1,14 +1,12 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { IPurchaseRequest } from "@/src/types/purchaseTypes";
|
||||
import { toPurchaseRequest } from "@/src/helpers/purchaseHelpers";
|
||||
import { handlePurchase } from "@/src/services/purchaseService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const purchaseController: RequestHandler = async (req, res) => {
|
||||
const purchaseRequest = JSON.parse(String(req.body)) as IPurchaseRequest;
|
||||
const purchaseRequest = toPurchaseRequest(JSON.parse(String(req.body)));
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const response = await handlePurchase(purchaseRequest, inventory);
|
||||
await inventory.save();
|
||||
const response = await handlePurchase(purchaseRequest, accountId);
|
||||
res.json(response);
|
||||
};
|
||||
|
@ -1,19 +1,16 @@
|
||||
import { getDojoClient, getGuildForRequest } from "@/src/services/guildService";
|
||||
import { getGuildForRequest } from "@/src/services/guildService";
|
||||
import { RequestHandler } from "express";
|
||||
import { ExportDojoRecipes } from "warframe-public-export-plus";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const queueDojoComponentDestructionController: RequestHandler = async (req, res) => {
|
||||
const guild = await getGuildForRequest(req);
|
||||
const componentId = req.query.componentId as string;
|
||||
const component = guild.DojoComponents!.splice(
|
||||
guild.DojoComponents!.splice(
|
||||
guild.DojoComponents!.findIndex(x => x._id.toString() === componentId),
|
||||
1
|
||||
)[0];
|
||||
const room = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == component.pf);
|
||||
if (room) {
|
||||
guild.DojoCapacity -= room.capacity;
|
||||
guild.DojoEnergy -= room.energy;
|
||||
}
|
||||
);
|
||||
await guild.save();
|
||||
res.json(getDojoClient(guild, 1));
|
||||
res.json({
|
||||
DojoRequestStatus: 1
|
||||
});
|
||||
};
|
||||
|
@ -1,104 +1,9 @@
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { addMiscItems, getInventory } from "@/src/services/inventoryService";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { ExportUpgrades } from "warframe-public-export-plus";
|
||||
import { getRandomElement } from "@/src/services/rngService";
|
||||
|
||||
export const rerollRandomModController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const request = getJSONfromString<RerollRandomModRequest>(String(req.body));
|
||||
if ("ItemIds" in request) {
|
||||
const inventory = await getInventory(accountId, "Upgrades MiscItems");
|
||||
const upgrade = inventory.Upgrades.id(request.ItemIds[0])!;
|
||||
const fingerprint = JSON.parse(upgrade.UpgradeFingerprint!) as IUnveiledRivenFingerprint;
|
||||
|
||||
fingerprint.rerolls ??= 0;
|
||||
const kuvaCost = fingerprint.rerolls < rerollCosts.length ? rerollCosts[fingerprint.rerolls] : 3500;
|
||||
addMiscItems(inventory, [
|
||||
{
|
||||
ItemType: "/Lotus/Types/Items/MiscItems/Kuva",
|
||||
ItemCount: kuvaCost * -1
|
||||
}
|
||||
]);
|
||||
|
||||
fingerprint.rerolls++;
|
||||
upgrade.UpgradeFingerprint = JSON.stringify(fingerprint);
|
||||
|
||||
randomiseStats(upgrade.ItemType, fingerprint);
|
||||
upgrade.PendingRerollFingerprint = JSON.stringify(fingerprint);
|
||||
|
||||
await inventory.save();
|
||||
|
||||
res.json({
|
||||
changes: [
|
||||
{
|
||||
ItemId: { $oid: request.ItemIds[0] },
|
||||
UpgradeFingerprint: upgrade.UpgradeFingerprint,
|
||||
PendingRerollFingerprint: upgrade.PendingRerollFingerprint
|
||||
}
|
||||
],
|
||||
cost: kuvaCost
|
||||
});
|
||||
} else {
|
||||
const inventory = await getInventory(accountId, "Upgrades");
|
||||
const upgrade = inventory.Upgrades.id(request.ItemId)!;
|
||||
if (request.CommitReroll && upgrade.PendingRerollFingerprint) {
|
||||
upgrade.UpgradeFingerprint = upgrade.PendingRerollFingerprint;
|
||||
}
|
||||
upgrade.PendingRerollFingerprint = undefined;
|
||||
await inventory.save();
|
||||
res.send(upgrade.UpgradeFingerprint);
|
||||
}
|
||||
const rerollRandomModController: RequestHandler = (_req, res) => {
|
||||
logger.debug("RerollRandomMod Request", { info: _req.body.toString("hex").replace(/(.)(.)/g, "$1$2 ") });
|
||||
res.json({});
|
||||
};
|
||||
|
||||
const randomiseStats = (randomModType: string, fingerprint: IUnveiledRivenFingerprint): void => {
|
||||
const meta = ExportUpgrades[randomModType];
|
||||
|
||||
fingerprint.buffs = [];
|
||||
const numBuffs = 2 + Math.trunc(Math.random() * 2); // 2 or 3
|
||||
const buffEntries = meta.upgradeEntries!.filter(x => x.canBeBuff);
|
||||
for (let i = 0; i != numBuffs; ++i) {
|
||||
const buffIndex = Math.trunc(Math.random() * buffEntries.length);
|
||||
const entry = buffEntries[buffIndex];
|
||||
fingerprint.buffs.push({ Tag: entry.tag, Value: Math.trunc(Math.random() * 0x40000000) });
|
||||
buffEntries.splice(buffIndex, 1);
|
||||
}
|
||||
|
||||
fingerprint.curses = [];
|
||||
if (Math.random() < 0.5) {
|
||||
const entry = getRandomElement(
|
||||
meta.upgradeEntries!.filter(x => x.canBeCurse && !fingerprint.buffs.find(y => y.Tag == x.tag))
|
||||
);
|
||||
fingerprint.curses.push({ Tag: entry.tag, Value: Math.trunc(Math.random() * 0x40000000) });
|
||||
}
|
||||
};
|
||||
|
||||
type RerollRandomModRequest = LetsGoGamblingRequest | AwDangitRequest;
|
||||
|
||||
interface LetsGoGamblingRequest {
|
||||
ItemIds: string[];
|
||||
}
|
||||
|
||||
interface AwDangitRequest {
|
||||
ItemId: string;
|
||||
CommitReroll: boolean;
|
||||
}
|
||||
|
||||
interface IUnveiledRivenFingerprint {
|
||||
compat: string;
|
||||
lim: number;
|
||||
lvl: number;
|
||||
lvlReq: 0;
|
||||
rerolls?: number;
|
||||
pol: string;
|
||||
buffs: IRivenStat[];
|
||||
curses: IRivenStat[];
|
||||
}
|
||||
|
||||
interface IRivenStat {
|
||||
Tag: string;
|
||||
Value: number;
|
||||
}
|
||||
|
||||
const rerollCosts = [900, 1000, 1200, 1400, 1700, 2000, 2350, 2750, 3150];
|
||||
export { rerollRandomModController };
|
||||
|
@ -1,85 +0,0 @@
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { ICompletedDialogue } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const saveDialogueController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const request = JSON.parse(String(req.body)) as SaveDialogueRequest;
|
||||
if ("YearIteration" in request) {
|
||||
const inventory = await getInventory(accountId);
|
||||
if (inventory.DialogueHistory) {
|
||||
inventory.DialogueHistory.YearIteration = request.YearIteration;
|
||||
} else {
|
||||
inventory.DialogueHistory = { YearIteration: request.YearIteration };
|
||||
}
|
||||
await inventory.save();
|
||||
res.end();
|
||||
} else {
|
||||
const inventory = await getInventory(accountId);
|
||||
if (!inventory.DialogueHistory) {
|
||||
throw new Error("bad inventory state");
|
||||
}
|
||||
if (request.QueuedDialogues.length != 0 || request.OtherDialogueInfos.length != 0) {
|
||||
logger.error(`saveDialogue request not fully handled: ${String(req.body)}`);
|
||||
}
|
||||
inventory.DialogueHistory.Dialogues ??= [];
|
||||
let dialogue = inventory.DialogueHistory.Dialogues.find(x => x.DialogueName == request.DialogueName);
|
||||
if (!dialogue) {
|
||||
dialogue =
|
||||
inventory.DialogueHistory.Dialogues[
|
||||
inventory.DialogueHistory.Dialogues.push({
|
||||
Rank: 0,
|
||||
Chemistry: 0,
|
||||
AvailableDate: new Date(0),
|
||||
AvailableGiftDate: new Date(0),
|
||||
RankUpExpiry: new Date(0),
|
||||
BountyChemExpiry: new Date(0),
|
||||
Gifts: [],
|
||||
Booleans: [],
|
||||
Completed: [],
|
||||
DialogueName: request.DialogueName
|
||||
}) - 1
|
||||
];
|
||||
}
|
||||
dialogue.Rank = request.Rank;
|
||||
dialogue.Chemistry = request.Chemistry;
|
||||
//dialogue.QueuedDialogues = request.QueuedDialogues;
|
||||
for (const bool of request.Booleans) {
|
||||
dialogue.Booleans.push(bool);
|
||||
}
|
||||
for (const bool of request.ResetBooleans) {
|
||||
const index = dialogue.Booleans.findIndex(x => x == bool);
|
||||
if (index != -1) {
|
||||
dialogue.Booleans.splice(index, 1);
|
||||
}
|
||||
}
|
||||
dialogue.Completed.push(request.Data);
|
||||
const tomorrowAt0Utc = (Math.trunc(Date.now() / (86400 * 1000)) + 1) * 86400 * 1000;
|
||||
dialogue.AvailableDate = new Date(tomorrowAt0Utc);
|
||||
await inventory.save();
|
||||
res.json({
|
||||
InventoryChanges: [],
|
||||
AvailableDate: { $date: { $numberLong: tomorrowAt0Utc.toString() } }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
type SaveDialogueRequest = SaveYearIterationRequest | SaveCompletedDialogueRequest;
|
||||
|
||||
interface SaveYearIterationRequest {
|
||||
YearIteration: number;
|
||||
}
|
||||
|
||||
interface SaveCompletedDialogueRequest {
|
||||
DialogueName: string;
|
||||
Rank: number;
|
||||
Chemistry: number;
|
||||
CompletionType: number;
|
||||
QueuedDialogues: string[]; // unsure
|
||||
Booleans: string[];
|
||||
ResetBooleans: string[];
|
||||
Data: ICompletedDialogue;
|
||||
OtherDialogueInfos: string[]; // unsure
|
||||
}
|
@ -4,6 +4,7 @@ import { handleInventoryItemConfigChange } from "@/src/services/saveLoadoutServi
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const saveLoadoutController: RequestHandler = async (req, res) => {
|
||||
//validate here
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
|
@ -1,22 +0,0 @@
|
||||
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 "../../types/inventoryTypes/inventoryTypes";
|
||||
|
||||
interface ISaveSettingsRequest {
|
||||
Settings: ISettings;
|
||||
}
|
||||
|
||||
const saveSettingsController: RequestHandler = async (req, res): Promise<void> => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
|
||||
const settingResults = getJSONfromString<ISaveSettingsRequest>(String(req.body));
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
inventory.Settings = Object.assign(inventory.Settings, settingResults.Settings);
|
||||
await inventory.save();
|
||||
res.json(inventory.Settings);
|
||||
};
|
||||
|
||||
export { saveSettingsController };
|
@ -1,7 +1,9 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { ISellRequest } from "@/src/types/sellTypes";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory, addMods, addRecipes, addMiscItems, addConsumables } from "@/src/services/inventoryService";
|
||||
import { getInventory, addMods, addRecipes } from "@/src/services/inventoryService";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const sellController: RequestHandler = async (req, res) => {
|
||||
const payload = JSON.parse(String(req.body)) as ISellRequest;
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
@ -12,20 +14,6 @@ export const sellController: RequestHandler = async (req, res) => {
|
||||
inventory.RegularCredits += payload.SellPrice;
|
||||
} else if (payload.SellCurrency == "SC_FusionPoints") {
|
||||
inventory.FusionPoints += payload.SellPrice;
|
||||
} else if (payload.SellCurrency == "SC_PrimeBucks") {
|
||||
addMiscItems(inventory, [
|
||||
{
|
||||
ItemType: "/Lotus/Types/Items/MiscItems/PrimeBucks",
|
||||
ItemCount: payload.SellPrice
|
||||
}
|
||||
]);
|
||||
} else if (payload.SellCurrency == "SC_DistillPoints") {
|
||||
addMiscItems(inventory, [
|
||||
{
|
||||
ItemType: "/Lotus/Types/Items/MiscItems/DistillPoints",
|
||||
ItemCount: payload.SellPrice
|
||||
}
|
||||
]);
|
||||
} else {
|
||||
throw new Error("Unknown SellCurrency: " + payload.SellCurrency);
|
||||
}
|
||||
@ -51,51 +39,6 @@ export const sellController: RequestHandler = async (req, res) => {
|
||||
inventory.Melee.pull({ _id: sellItem.String });
|
||||
});
|
||||
}
|
||||
if (payload.Items.SpaceSuits) {
|
||||
payload.Items.SpaceSuits.forEach(sellItem => {
|
||||
inventory.SpaceSuits.pull({ _id: sellItem.String });
|
||||
});
|
||||
}
|
||||
if (payload.Items.SpaceGuns) {
|
||||
payload.Items.SpaceGuns.forEach(sellItem => {
|
||||
inventory.SpaceGuns.pull({ _id: sellItem.String });
|
||||
});
|
||||
}
|
||||
if (payload.Items.SpaceMelee) {
|
||||
payload.Items.SpaceMelee.forEach(sellItem => {
|
||||
inventory.SpaceMelee.pull({ _id: sellItem.String });
|
||||
});
|
||||
}
|
||||
if (payload.Items.Sentinels) {
|
||||
payload.Items.Sentinels.forEach(sellItem => {
|
||||
inventory.Sentinels.pull({ _id: sellItem.String });
|
||||
});
|
||||
}
|
||||
if (payload.Items.SentinelWeapons) {
|
||||
payload.Items.SentinelWeapons.forEach(sellItem => {
|
||||
inventory.SentinelWeapons.pull({ _id: sellItem.String });
|
||||
});
|
||||
}
|
||||
if (payload.Items.OperatorAmps) {
|
||||
payload.Items.OperatorAmps.forEach(sellItem => {
|
||||
inventory.OperatorAmps.pull({ _id: sellItem.String });
|
||||
});
|
||||
}
|
||||
if (payload.Items.Hoverboards) {
|
||||
payload.Items.Hoverboards.forEach(sellItem => {
|
||||
inventory.Hoverboards.pull({ _id: sellItem.String });
|
||||
});
|
||||
}
|
||||
if (payload.Items.Consumables) {
|
||||
const consumablesChanges = [];
|
||||
for (const sellItem of payload.Items.Consumables) {
|
||||
consumablesChanges.push({
|
||||
ItemType: sellItem.String,
|
||||
ItemCount: sellItem.Count * -1
|
||||
});
|
||||
}
|
||||
addConsumables(inventory, consumablesChanges);
|
||||
}
|
||||
if (payload.Items.Recipes) {
|
||||
const recipeChanges = [];
|
||||
for (const sellItem of payload.Items.Recipes) {
|
||||
@ -120,51 +63,7 @@ export const sellController: RequestHandler = async (req, res) => {
|
||||
}
|
||||
});
|
||||
}
|
||||
if (payload.Items.MiscItems) {
|
||||
payload.Items.MiscItems.forEach(sellItem => {
|
||||
addMiscItems(inventory, [
|
||||
{
|
||||
ItemType: sellItem.String,
|
||||
ItemCount: sellItem.Count * -1
|
||||
}
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
await inventory.save();
|
||||
res.json({});
|
||||
};
|
||||
|
||||
interface ISellRequest {
|
||||
Items: {
|
||||
Suits?: ISellItem[];
|
||||
LongGuns?: ISellItem[];
|
||||
Pistols?: ISellItem[];
|
||||
Melee?: ISellItem[];
|
||||
Consumables?: ISellItem[];
|
||||
Recipes?: ISellItem[];
|
||||
Upgrades?: ISellItem[];
|
||||
MiscItems?: ISellItem[];
|
||||
SpaceSuits?: ISellItem[];
|
||||
SpaceGuns?: ISellItem[];
|
||||
SpaceMelee?: ISellItem[];
|
||||
Sentinels?: ISellItem[];
|
||||
SentinelWeapons?: ISellItem[];
|
||||
OperatorAmps?: ISellItem[];
|
||||
Hoverboards?: ISellItem[];
|
||||
};
|
||||
SellPrice: number;
|
||||
SellCurrency:
|
||||
| "SC_RegularCredits"
|
||||
| "SC_PrimeBucks"
|
||||
| "SC_FusionPoints"
|
||||
| "SC_DistillPoints"
|
||||
| "SC_CrewShipFusionPoints"
|
||||
| "SC_Resources";
|
||||
buildLabel: string;
|
||||
}
|
||||
|
||||
interface ISellItem {
|
||||
String: string; // oid or uniqueName
|
||||
Count: number;
|
||||
}
|
||||
|
@ -1,18 +1,7 @@
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const setActiveQuestController: RequestHandler<
|
||||
Record<string, never>,
|
||||
undefined,
|
||||
undefined,
|
||||
{ quest: string | undefined }
|
||||
> = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const quest = req.query.quest;
|
||||
|
||||
const inventory = await getInventory(accountId, "ActiveQuest");
|
||||
inventory.ActiveQuest = quest ?? "";
|
||||
await inventory.save();
|
||||
res.status(200).end();
|
||||
const setActiveQuestController: RequestHandler = (_req, res) => {
|
||||
res.sendStatus(200);
|
||||
};
|
||||
|
||||
export { setActiveQuestController };
|
||||
|
@ -4,6 +4,7 @@ import { parseString } from "@/src/helpers/general";
|
||||
import { RequestHandler } from "express";
|
||||
import { Types } from "mongoose";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const setActiveShipController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const shipId = parseString(req.query.shipId);
|
||||
|
@ -2,23 +2,12 @@ import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getPersonalRooms } from "@/src/services/personalRoomsService";
|
||||
import { TBootLocation } from "@/src/types/shipTypes";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const setBootLocationController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const personalRooms = await getPersonalRooms(accountId);
|
||||
personalRooms.Ship.BootLocation = req.query.bootLocation as string as TBootLocation;
|
||||
await personalRooms.save();
|
||||
|
||||
if (personalRooms.Ship.BootLocation == "SHOP") {
|
||||
// Temp fix so the motorcycle in the backroom doesn't appear broken.
|
||||
// This code may be removed when quests are fully implemented.
|
||||
const inventory = await getInventory(accountId);
|
||||
if (inventory.Motorcycles.length == 0) {
|
||||
inventory.Motorcycles.push({ ItemType: "/Lotus/Types/Vehicles/Motorcycle/MotorcyclePowerSuit" });
|
||||
await inventory.save();
|
||||
}
|
||||
}
|
||||
|
||||
res.end();
|
||||
};
|
||||
|
@ -1,18 +0,0 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getDojoClient, getGuildForRequest } from "@/src/services/guildService";
|
||||
|
||||
export const setDojoComponentMessageController: RequestHandler = async (req, res) => {
|
||||
const guild = await getGuildForRequest(req);
|
||||
// At this point, we know that a member of the guild is making this request. Assuming they are allowed to change the message.
|
||||
const component = guild.DojoComponents!.find(x => x._id.equals(req.query.componentId as string))!;
|
||||
const payload = JSON.parse(String(req.body)) as SetDojoComponentMessageRequest;
|
||||
if ("Name" in payload) {
|
||||
component.Name = payload.Name;
|
||||
} else {
|
||||
component.Message = payload.Message;
|
||||
}
|
||||
await guild.save();
|
||||
res.json(getDojoClient(guild, 1));
|
||||
};
|
||||
|
||||
type SetDojoComponentMessageRequest = { Name: string } | { Message: string };
|
@ -1,17 +0,0 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
|
||||
export const setEquippedInstrumentController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const body = getJSONfromString<ISetEquippedInstrumentRequest>(String(req.body));
|
||||
inventory.EquippedInstrument = body.Instrument;
|
||||
await inventory.save();
|
||||
res.end();
|
||||
};
|
||||
|
||||
interface ISetEquippedInstrumentRequest {
|
||||
Instrument: string;
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { ISetPlacedDecoInfoRequest } from "@/src/types/shipTypes";
|
||||
import { RequestHandler } from "express";
|
||||
import { handleSetPlacedDecoInfo } from "@/src/services/shipCustomizationsService";
|
||||
|
||||
export const setPlacedDecoInfoController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const payload = JSON.parse(req.body as string) as ISetPlacedDecoInfoRequest;
|
||||
await handleSetPlacedDecoInfo(accountId, payload);
|
||||
res.end();
|
||||
};
|
@ -1,15 +1,14 @@
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { setShipCustomizations } from "@/src/services/shipCustomizationsService";
|
||||
import { ISetShipCustomizationsRequest } from "@/src/types/shipTypes";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const setShipCustomizationsController: RequestHandler = async (req, res) => {
|
||||
try {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const setShipCustomizationsRequest = JSON.parse(req.body as string) as ISetShipCustomizationsRequest;
|
||||
|
||||
const setShipCustomizationsResponse = await setShipCustomizations(accountId, setShipCustomizationsRequest);
|
||||
const setShipCustomizationsResponse = await setShipCustomizations(setShipCustomizationsRequest);
|
||||
res.json(setShipCustomizationsResponse);
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error) {
|
||||
|
@ -1,31 +0,0 @@
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { RequestHandler } from "express";
|
||||
import { getPersonalRooms } from "@/src/services/personalRoomsService";
|
||||
import { IOid } from "@/src/types/commonTypes";
|
||||
import { Types } from "mongoose";
|
||||
|
||||
export const setShipFavouriteLoadoutController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const personalRooms = await getPersonalRooms(accountId);
|
||||
const body = JSON.parse(String(req.body)) as ISetShipFavouriteLoadoutRequest;
|
||||
if (body.BootLocation != "SHOP") {
|
||||
throw new Error(`unexpected BootLocation: ${body.BootLocation}`);
|
||||
}
|
||||
const display = personalRooms.TailorShop.FavouriteLoadouts.find(x => x.Tag == body.TagName);
|
||||
if (display) {
|
||||
display.LoadoutId = new Types.ObjectId(body.FavouriteLoadoutId.$oid);
|
||||
} else {
|
||||
personalRooms.TailorShop.FavouriteLoadouts.push({
|
||||
Tag: body.TagName,
|
||||
LoadoutId: new Types.ObjectId(body.FavouriteLoadoutId.$oid)
|
||||
});
|
||||
}
|
||||
await personalRooms.save();
|
||||
res.json({});
|
||||
};
|
||||
|
||||
interface ISetShipFavouriteLoadoutRequest {
|
||||
BootLocation: string;
|
||||
FavouriteLoadoutId: IOid;
|
||||
TagName: string;
|
||||
}
|
@ -2,6 +2,7 @@ import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const setSupportedSyndicateController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
|
@ -4,10 +4,11 @@ import { getInventory } from "@/src/services/inventoryService";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { WeaponTypeInternal } from "@/src/services/itemDataService";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const setWeaponSkillTreeController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const payload = getJSONfromString<ISetWeaponSkillTreeRequest>(String(req.body));
|
||||
const payload = getJSONfromString(String(req.body)) as ISetWeaponSkillTreeRequest;
|
||||
|
||||
const item = inventory[req.query.Category as WeaponTypeInternal].find(
|
||||
item => item._id.toString() == (req.query.ItemId as string)
|
||||
|
@ -4,6 +4,7 @@ import { logger } from "@/src/utils/logger";
|
||||
import { RequestHandler } from "express";
|
||||
import { handleSetShipDecorations } from "@/src/services/shipCustomizationsService";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const shipDecorationsController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const shipDecorationsRequest = JSON.parse(req.body as string) as IShipDecorationsRequest;
|
||||
@ -13,7 +14,7 @@ export const shipDecorationsController: RequestHandler = async (req, res) => {
|
||||
res.send(placedDecoration);
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error) {
|
||||
logger.error(`error in shipDecorationsController: ${error.message}`);
|
||||
logger.error(`error in saveLoadoutController: ${error.message}`);
|
||||
res.status(400).json({ error: error.message });
|
||||
}
|
||||
}
|
||||
|
@ -1,34 +1,29 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { IDojoComponentClient } from "@/src/types/guildTypes";
|
||||
import { getDojoClient, getGuildForRequest } from "@/src/services/guildService";
|
||||
import { getGuildForRequest } from "@/src/services/guildService";
|
||||
import { Types } from "mongoose";
|
||||
import { ExportDojoRecipes } from "warframe-public-export-plus";
|
||||
|
||||
interface IStartDojoRecipeRequest {
|
||||
PlacedComponent: IDojoComponentClient;
|
||||
Revision: number;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const startDojoRecipeController: RequestHandler = async (req, res) => {
|
||||
const guild = await getGuildForRequest(req);
|
||||
// At this point, we know that a member of the guild is making this request. Assuming they are allowed to start a build.
|
||||
const request = JSON.parse(String(req.body)) as IStartDojoRecipeRequest;
|
||||
|
||||
const room = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == request.PlacedComponent.pf);
|
||||
if (room) {
|
||||
guild.DojoCapacity += room.capacity;
|
||||
guild.DojoEnergy += room.energy;
|
||||
}
|
||||
|
||||
guild.DojoComponents!.push({
|
||||
_id: new Types.ObjectId(),
|
||||
pf: request.PlacedComponent.pf,
|
||||
ppf: request.PlacedComponent.ppf,
|
||||
pi: new Types.ObjectId(request.PlacedComponent.pi!.$oid),
|
||||
pi: new Types.ObjectId(request.PlacedComponent.pi!.$id),
|
||||
op: request.PlacedComponent.op,
|
||||
pp: request.PlacedComponent.pp,
|
||||
CompletionTime: new Date(Date.now()) // TOOD: Omit this field & handle the "Collecting Materials" state.
|
||||
});
|
||||
await guild.save();
|
||||
res.json(getDojoClient(guild, 0));
|
||||
res.json({
|
||||
DojoRequestStatus: 0
|
||||
});
|
||||
};
|
||||
|
@ -1,106 +1,21 @@
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { startRecipe } from "@/src/services/recipeService";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { RequestHandler } from "express";
|
||||
import { getRecipe } from "@/src/services/itemDataService";
|
||||
import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||
import { unixTimesInMs } from "@/src/constants/timeConstants";
|
||||
import { Types } from "mongoose";
|
||||
import { ISpectreLoadout } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
|
||||
interface IStartRecipeRequest {
|
||||
RecipeName: string;
|
||||
Ids: string[];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const startRecipeController: RequestHandler = async (req, res) => {
|
||||
const startRecipeRequest = getJSONfromString<IStartRecipeRequest>(String(req.body));
|
||||
const startRecipeRequest = getJSONfromString(String(req.body)) as IStartRecipeRequest;
|
||||
logger.debug("StartRecipe Request", { startRecipeRequest });
|
||||
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
|
||||
const recipeName = startRecipeRequest.RecipeName;
|
||||
const recipe = getRecipe(recipeName);
|
||||
|
||||
if (!recipe) {
|
||||
throw new Error(`unknown recipe ${recipeName}`);
|
||||
}
|
||||
|
||||
const ingredientsInverse = recipe.ingredients.map(component => ({
|
||||
ItemType: component.ItemType,
|
||||
ItemCount: component.ItemCount * -1
|
||||
}));
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
updateCurrency(inventory, recipe.buildPrice, false);
|
||||
addMiscItems(inventory, ingredientsInverse);
|
||||
|
||||
//buildtime is in seconds
|
||||
const completionDate = new Date(Date.now() + recipe.buildTime * unixTimesInMs.second);
|
||||
|
||||
inventory.PendingRecipes.push({
|
||||
ItemType: recipeName,
|
||||
CompletionDate: completionDate,
|
||||
_id: new Types.ObjectId()
|
||||
});
|
||||
|
||||
if (recipe.secretIngredientAction == "SIA_SPECTRE_LOADOUT_COPY") {
|
||||
const spectreLoadout: ISpectreLoadout = {
|
||||
ItemType: recipe.resultType,
|
||||
Suits: "",
|
||||
LongGuns: "",
|
||||
Pistols: "",
|
||||
Melee: ""
|
||||
};
|
||||
for (
|
||||
let secretIngredientsIndex = 0;
|
||||
secretIngredientsIndex != recipe.secretIngredients!.length;
|
||||
++secretIngredientsIndex
|
||||
) {
|
||||
const type = recipe.secretIngredients![secretIngredientsIndex].ItemType;
|
||||
const oid = startRecipeRequest.Ids[recipe.ingredients.length + secretIngredientsIndex];
|
||||
if (oid == "ffffffffffffffffffffffff") {
|
||||
// user chose to preserve the active loadout
|
||||
break;
|
||||
}
|
||||
if (type == "/Lotus/Types/Game/PowerSuits/PlayerPowerSuit") {
|
||||
const item = inventory.Suits.id(oid)!;
|
||||
spectreLoadout.Suits = item.ItemType;
|
||||
} else if (type == "/Lotus/Weapons/Tenno/Pistol/LotusPistol") {
|
||||
const item = inventory.Pistols.id(oid)!;
|
||||
spectreLoadout.Pistols = item.ItemType;
|
||||
spectreLoadout.PistolsModularParts = item.ModularParts;
|
||||
} else if (type == "/Lotus/Weapons/Tenno/LotusLongGun") {
|
||||
const item = inventory.LongGuns.id(oid)!;
|
||||
spectreLoadout.LongGuns = item.ItemType;
|
||||
spectreLoadout.LongGunsModularParts = item.ModularParts;
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
console.assert(type == "/Lotus/Types/Game/LotusMeleeWeapon");
|
||||
const item = inventory.Melee.id(oid)!;
|
||||
spectreLoadout.Melee = item.ItemType;
|
||||
spectreLoadout.MeleeModularParts = item.ModularParts;
|
||||
}
|
||||
}
|
||||
if (
|
||||
spectreLoadout.Suits != "" &&
|
||||
spectreLoadout.LongGuns != "" &&
|
||||
spectreLoadout.Pistols != "" &&
|
||||
spectreLoadout.Melee != ""
|
||||
) {
|
||||
inventory.PendingSpectreLoadouts ??= [];
|
||||
const existingIndex = inventory.PendingSpectreLoadouts.findIndex(x => x.ItemType == recipe.resultType);
|
||||
if (existingIndex != -1) {
|
||||
inventory.PendingSpectreLoadouts.splice(existingIndex, 1);
|
||||
}
|
||||
inventory.PendingSpectreLoadouts.push(spectreLoadout);
|
||||
logger.debug("pending spectre loadout", spectreLoadout);
|
||||
}
|
||||
}
|
||||
|
||||
const newInventory = await inventory.save();
|
||||
|
||||
res.json({
|
||||
RecipeId: { $oid: newInventory.PendingRecipes[newInventory.PendingRecipes.length - 1]._id.toString() }
|
||||
});
|
||||
const newRecipeId = await startRecipe(startRecipeRequest.RecipeName, accountId);
|
||||
res.json(newRecipeId);
|
||||
};
|
||||
|
@ -3,6 +3,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { IStepSequencer } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const stepSequencersController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
|
@ -1,84 +1,25 @@
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { syndicateSacrifice } from "@/src/services/inventoryService";
|
||||
import { ISyndicateSacrifice } from "@/src/types/syndicateTypes";
|
||||
import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { ExportSyndicates, ISyndicateSacrifice } from "warframe-public-export-plus";
|
||||
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
|
||||
import { addMiscItems, combineInventoryChanges, getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
||||
|
||||
export const syndicateSacrificeController: RequestHandler = async (request, response) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
const syndicateSacrificeController: RequestHandler = async (request, response) => {
|
||||
const accountId = await getAccountIdForRequest(request);
|
||||
const inventory = await getInventory(accountId);
|
||||
const data = getJSONfromString<ISyndicateSacrificeRequest>(String(request.body));
|
||||
|
||||
let syndicate = inventory.Affiliations.find(x => x.Tag == data.AffiliationTag);
|
||||
if (!syndicate) {
|
||||
syndicate = inventory.Affiliations[inventory.Affiliations.push({ Tag: data.AffiliationTag, Standing: 0 }) - 1];
|
||||
}
|
||||
|
||||
const level = data.SacrificeLevel - (syndicate.Title ?? 0);
|
||||
const res: ISyndicateSacrificeResponse = {
|
||||
AffiliationTag: data.AffiliationTag,
|
||||
InventoryChanges: {},
|
||||
Level: data.SacrificeLevel,
|
||||
LevelIncrease: level <= 0 ? 1 : level,
|
||||
NewEpisodeReward: syndicate.Tag == "RadioLegionIntermission9Syndicate"
|
||||
};
|
||||
|
||||
const manifest = ExportSyndicates[data.AffiliationTag];
|
||||
let sacrifice: ISyndicateSacrifice | undefined;
|
||||
let reward: string | undefined;
|
||||
if (data.SacrificeLevel == 0) {
|
||||
sacrifice = manifest.initiationSacrifice;
|
||||
reward = manifest.initiationReward;
|
||||
syndicate.Initiated = true;
|
||||
} else {
|
||||
sacrifice = manifest.titles?.find(x => x.level == data.SacrificeLevel)?.sacrifice;
|
||||
}
|
||||
|
||||
if (sacrifice) {
|
||||
res.InventoryChanges = { ...updateCurrency(inventory, sacrifice.credits, false) };
|
||||
|
||||
const miscItemChanges = sacrifice.items.map(x => ({
|
||||
ItemType: x.ItemType,
|
||||
ItemCount: x.ItemCount * -1
|
||||
}));
|
||||
addMiscItems(inventory, miscItemChanges);
|
||||
res.InventoryChanges.MiscItems = miscItemChanges;
|
||||
}
|
||||
|
||||
syndicate.Title ??= 0;
|
||||
syndicate.Title += 1;
|
||||
|
||||
if (syndicate.Title > 0 && manifest.favours.length != 0) {
|
||||
syndicate.FreeFavorsEarned ??= [];
|
||||
if (!syndicate.FreeFavorsEarned.includes(syndicate.Title)) {
|
||||
syndicate.FreeFavorsEarned.push(syndicate.Title);
|
||||
const update = getJSONfromString(String(request.body)) as ISyndicateSacrifice;
|
||||
let reply = {};
|
||||
try {
|
||||
if (typeof update !== "object") {
|
||||
throw new Error("Invalid data format");
|
||||
}
|
||||
|
||||
reply = await syndicateSacrifice(update, accountId);
|
||||
} catch (err) {
|
||||
console.error("Error parsing JSON data:", err);
|
||||
}
|
||||
|
||||
if (reward) {
|
||||
combineInventoryChanges(
|
||||
res.InventoryChanges,
|
||||
(await handleStoreItemAcquisition(reward, inventory)).InventoryChanges
|
||||
);
|
||||
}
|
||||
|
||||
await inventory.save();
|
||||
|
||||
response.json(res);
|
||||
response.json(reply);
|
||||
};
|
||||
|
||||
interface ISyndicateSacrificeRequest {
|
||||
AffiliationTag: string;
|
||||
SacrificeLevel: number;
|
||||
AllowMultiple: boolean;
|
||||
}
|
||||
|
||||
interface ISyndicateSacrificeResponse {
|
||||
AffiliationTag: string;
|
||||
Level: number;
|
||||
LevelIncrease: number;
|
||||
InventoryChanges: IInventoryChanges;
|
||||
NewEpisodeReward: boolean;
|
||||
}
|
||||
export { syndicateSacrificeController };
|
||||
|
@ -1,72 +0,0 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { addMiscItems, getInventory, getStandingLimit, updateStandingLimit } from "@/src/services/inventoryService";
|
||||
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { IOid } from "@/src/types/commonTypes";
|
||||
import { ExportSyndicates } from "warframe-public-export-plus";
|
||||
import { getMaxStanding } from "@/src/helpers/syndicateStandingHelper";
|
||||
|
||||
export const syndicateStandingBonusController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const request = JSON.parse(String(req.body)) as ISyndicateStandingBonusRequest;
|
||||
|
||||
const syndicateMeta = ExportSyndicates[request.Operation.AffiliationTag];
|
||||
|
||||
let gainedStanding = 0;
|
||||
request.Operation.Items.forEach(item => {
|
||||
const medallion = (syndicateMeta.medallions ?? []).find(medallion => medallion.itemType == item.ItemType);
|
||||
if (medallion) {
|
||||
gainedStanding += medallion.standing * item.ItemCount;
|
||||
}
|
||||
|
||||
item.ItemCount *= -1;
|
||||
});
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
addMiscItems(inventory, request.Operation.Items);
|
||||
|
||||
let syndicate = inventory.Affiliations.find(x => x.Tag == request.Operation.AffiliationTag);
|
||||
if (!syndicate) {
|
||||
syndicate =
|
||||
inventory.Affiliations[
|
||||
inventory.Affiliations.push({ Tag: request.Operation.AffiliationTag, Standing: 0 }) - 1
|
||||
];
|
||||
}
|
||||
|
||||
const max = getMaxStanding(syndicateMeta, syndicate.Title ?? 0);
|
||||
if (syndicate.Standing + gainedStanding > max) {
|
||||
gainedStanding = max - syndicate.Standing;
|
||||
}
|
||||
|
||||
if (syndicateMeta.medallionsCappedByDailyLimit) {
|
||||
if (gainedStanding > getStandingLimit(inventory, syndicateMeta.dailyLimitBin)) {
|
||||
gainedStanding = getStandingLimit(inventory, syndicateMeta.dailyLimitBin);
|
||||
}
|
||||
updateStandingLimit(inventory, syndicateMeta.dailyLimitBin, gainedStanding);
|
||||
}
|
||||
|
||||
syndicate.Standing += gainedStanding;
|
||||
|
||||
await inventory.save();
|
||||
|
||||
res.json({
|
||||
InventoryChanges: {
|
||||
MiscItems: request.Operation.Items
|
||||
},
|
||||
AffiliationMods: [
|
||||
{
|
||||
Tag: request.Operation.AffiliationTag,
|
||||
Standing: gainedStanding
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
interface ISyndicateStandingBonusRequest {
|
||||
Operation: {
|
||||
AffiliationTag: string;
|
||||
AlternateBonusReward: ""; // ???
|
||||
Items: IMiscItem[];
|
||||
};
|
||||
ModularWeaponId: IOid; // Seems to just be "000000000000000000000000", also note there's a "Category" query field
|
||||
}
|
@ -2,20 +2,18 @@ import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { ITaunt } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const tauntHistoryController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const clientTaunt = JSON.parse(String(req.body)) as ITaunt;
|
||||
logger.debug(`updating taunt ${clientTaunt.node} to state ${clientTaunt.state}`);
|
||||
inventory.TauntHistory ??= [];
|
||||
const taunt = inventory.TauntHistory.find(x => x.node == clientTaunt.node);
|
||||
if (taunt) {
|
||||
taunt.state = clientTaunt.state;
|
||||
} else {
|
||||
if (req.body !== undefined) {
|
||||
const clientTaunt = JSON.parse(String(req.body)) as ITaunt;
|
||||
inventory.TauntHistory ??= [];
|
||||
inventory.TauntHistory.push(clientTaunt);
|
||||
await inventory.save();
|
||||
res.end();
|
||||
} else {
|
||||
res.json({});
|
||||
}
|
||||
await inventory.save();
|
||||
res.end();
|
||||
};
|
||||
|
@ -1,30 +1,24 @@
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { IMongoDate } from "@/src/types/commonTypes";
|
||||
import { RequestHandler } from "express";
|
||||
import { unixTimesInMs } from "@/src/constants/timeConstants";
|
||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
||||
|
||||
interface ITrainingResultsRequest {
|
||||
numLevelsGained: number;
|
||||
}
|
||||
|
||||
interface ITrainingResultsResponse {
|
||||
NewTrainingDate: IMongoDate;
|
||||
NewLevel: number;
|
||||
InventoryChanges: IInventoryChanges;
|
||||
InventoryChanges: any[];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
const trainingResultController: RequestHandler = async (req, res): Promise<void> => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
|
||||
const trainingResults = getJSONfromString<ITrainingResultsRequest>(String(req.body));
|
||||
|
||||
const numLevelsGained = parseInt(req.query.numLevelsGained as string);
|
||||
const inventory = await getInventory(accountId);
|
||||
console.log(req.query);
|
||||
inventory.TrainingDate = new Date(Date.now() + unixTimesInMs.day);
|
||||
|
||||
if (trainingResults.numLevelsGained == 1) {
|
||||
inventory.TrainingDate = new Date(Date.now() + unixTimesInMs.hour * 23);
|
||||
if (numLevelsGained == 1) {
|
||||
inventory.PlayerLevel += 1;
|
||||
}
|
||||
|
||||
@ -34,8 +28,8 @@ const trainingResultController: RequestHandler = async (req, res): Promise<void>
|
||||
NewTrainingDate: {
|
||||
$date: { $numberLong: changedinventory.TrainingDate.getTime().toString() }
|
||||
},
|
||||
NewLevel: trainingResults.numLevelsGained == 1 ? changedinventory.PlayerLevel : inventory.PlayerLevel,
|
||||
InventoryChanges: {}
|
||||
NewLevel: numLevelsGained == 1 ? changedinventory.PlayerLevel : inventory.PlayerLevel,
|
||||
InventoryChanges: []
|
||||
} satisfies ITrainingResultsResponse);
|
||||
};
|
||||
|
||||
|
@ -1,12 +0,0 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { updateShipFeature } from "@/src/services/personalRoomsService";
|
||||
import { IUnlockShipFeatureRequest } from "@/src/types/requestTypes";
|
||||
import { parseString } from "@/src/helpers/general";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const unlockShipFeatureController: RequestHandler = async (req, res) => {
|
||||
const accountId = parseString(req.query.accountId);
|
||||
const shipFeatureRequest = JSON.parse((req.body as string).toString()) as IUnlockShipFeatureRequest;
|
||||
await updateShipFeature(accountId, shipFeatureRequest.Feature);
|
||||
res.send([]);
|
||||
};
|
@ -4,8 +4,9 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { updateChallengeProgress } from "@/src/services/inventoryService";
|
||||
import { IUpdateChallengeProgressRequest } from "@/src/types/requestTypes";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
const updateChallengeProgressController: RequestHandler = async (req, res) => {
|
||||
const payload = getJSONfromString<IUpdateChallengeProgressRequest>(String(req.body));
|
||||
const payload = getJSONfromString(String(req.body)) as IUpdateChallengeProgressRequest;
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
|
||||
await updateChallengeProgress(payload, accountId);
|
||||
|
156
src/controllers/api/updateInventoryController.ts
Normal file
156
src/controllers/api/updateInventoryController.ts
Normal file
@ -0,0 +1,156 @@
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { RequestHandler } from "express";
|
||||
import { missionInventoryUpdate } from "@/src/services/inventoryService";
|
||||
import { combineRewardAndLootInventory } from "@/src/services/missionInventoryUpdateService";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { IMissionInventoryUpdateRequest } from "@/src/types/requestTypes";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const updateInventoryController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const lootInventory = getJSONfromString(req.body as string) as IMissionInventoryUpdateRequest;
|
||||
const { combinedInventoryChanges, TotalCredits, CreditsBonus, MissionCredits } = combineRewardAndLootInventory(
|
||||
lootInventory,
|
||||
lootInventory
|
||||
);
|
||||
|
||||
await missionInventoryUpdate(combinedInventoryChanges, accountId);
|
||||
|
||||
res.json({
|
||||
// InventoryJson, // this part will reset game data and missions will be locked
|
||||
combinedInventoryChanges,
|
||||
TotalCredits,
|
||||
CreditsBonus,
|
||||
MissionCredits
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
{
|
||||
"LongGuns" : [
|
||||
{
|
||||
"ItemType" : "",
|
||||
"ItemId" : {
|
||||
"$id" : ""
|
||||
},
|
||||
"XP" : 882,
|
||||
"UpgradeVer" : 0,
|
||||
"UnlockLevel" : 0,
|
||||
"ExtraCapacity" : 4,
|
||||
"ExtraRemaining" : 4
|
||||
}
|
||||
],
|
||||
"Pistols" : [
|
||||
{
|
||||
"ItemType" : "",
|
||||
"ItemId" : {
|
||||
"$id" : ""
|
||||
},
|
||||
"XP" : 0,
|
||||
"UpgradeVer" : 0,
|
||||
"UnlockLevel" : 0,
|
||||
"ExtraCapacity" : 4,
|
||||
"ExtraRemaining" : 4
|
||||
}
|
||||
],
|
||||
"Suits" : [
|
||||
{
|
||||
"ItemType" : "",
|
||||
"ItemId" : {
|
||||
"$id" : ""
|
||||
},
|
||||
"XP" : 982,
|
||||
"UpgradeVer" : 101,
|
||||
"UnlockLevel" : 0,
|
||||
"ExtraCapacity" : 4,
|
||||
"ExtraRemaining" : 4
|
||||
}
|
||||
],
|
||||
"Melee" : [
|
||||
{
|
||||
"ItemType" : "",
|
||||
"ItemId" : {
|
||||
"$id" : ""
|
||||
},
|
||||
"XP" : 0,
|
||||
"UpgradeVer" : 0,
|
||||
"UnlockLevel" : 0,
|
||||
"ExtraCapacity" : 4,
|
||||
"ExtraRemaining" : 4
|
||||
}
|
||||
],
|
||||
"WeaponSkins" : [],
|
||||
"Upgrades" : [],
|
||||
"Boosters" : [],
|
||||
"Robotics" : [],
|
||||
"Consumables" : [],
|
||||
"FlavourItems" : [],
|
||||
"MiscItems" : [],
|
||||
"Cards" : [],
|
||||
"Recipes" : [],
|
||||
"XPInfo" : [],
|
||||
"Sentinels" : [],
|
||||
"SentinelWeapons" : [],
|
||||
"SuitBin" : {
|
||||
"Slots" : 0,
|
||||
"Extra" : 0
|
||||
},
|
||||
"WeaponBin" : {
|
||||
"Slots" : 0,
|
||||
"Extra" : 0
|
||||
},
|
||||
"MiscBin" : {
|
||||
"Slots" : 0,
|
||||
"Extra" : 0
|
||||
},
|
||||
"SentinelBin" : {
|
||||
"Slots" : 0,
|
||||
"Extra" : 0
|
||||
},
|
||||
"RegularCredits" : 1304,
|
||||
"PremiumCredits" : 0,
|
||||
"PlayerXP" : 784,
|
||||
"AdditionalPlayerXP" : 0,
|
||||
"Rating" : 15,
|
||||
"PlayerLevel" : 0,
|
||||
"TrainingDate" : {
|
||||
"sec" : "",
|
||||
"usec" : ""
|
||||
},
|
||||
"AliveTime" : 193.78572,
|
||||
"Missions" : {
|
||||
"Tag" : "SolNode103",
|
||||
"Completes" : 1,
|
||||
"BestRating" : 0.2
|
||||
},
|
||||
"AssignedMissions" : [],
|
||||
"CompletedAlerts" : [],
|
||||
"DeathMarks" : [],
|
||||
"MissionReport" : {
|
||||
"HostId" : "",
|
||||
"MishStartTime" : "1725359860",
|
||||
"MishName" : "SolNode103",
|
||||
"PlayerReport" : {
|
||||
"ReporterId" : "",
|
||||
"FullReport" : true,
|
||||
"PlayerMishInfos" : [
|
||||
{
|
||||
"Pid" : "",
|
||||
"Creds" : 304,
|
||||
"CredBonus" : 1000,
|
||||
"Xp" : 784,
|
||||
"XpBonus" : 0,
|
||||
"SuitXpBonus" : 590,
|
||||
"PistolXpBonus" : 0,
|
||||
"RfileXpBonus" : 490,
|
||||
"MeleeXpBonus" : 0,
|
||||
"SentnlXPBonus" : 0,
|
||||
"SentnlWepXpBonus" : 0,
|
||||
"Rating" : 0.2,
|
||||
"Upgrades" : []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
@ -1,47 +0,0 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { parseString } from "@/src/helpers/general";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { updateQuestKey, IUpdateQuestRequest } from "@/src/services/questService";
|
||||
import { getQuestCompletionItems } from "@/src/services/itemDataService";
|
||||
import { addItems, getInventory } from "@/src/services/inventoryService";
|
||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const updateQuestController: RequestHandler = async (req, res) => {
|
||||
const accountId = parseString(req.query.accountId);
|
||||
const updateQuestRequest = getJSONfromString<IUpdateQuestRequest>((req.body as string).toString());
|
||||
|
||||
// updates should be made only to one quest key per request
|
||||
if (updateQuestRequest.QuestKeys.length > 1) {
|
||||
throw new Error(`quest keys array should only have 1 item, but has ${updateQuestRequest.QuestKeys.length}`);
|
||||
}
|
||||
|
||||
const inventory = await getInventory(accountId);
|
||||
|
||||
const updateQuestResponse: { CustomData?: string; InventoryChanges?: IInventoryChanges; MissionRewards: [] } = {
|
||||
MissionRewards: []
|
||||
};
|
||||
updateQuestKey(inventory, updateQuestRequest.QuestKeys);
|
||||
|
||||
if (updateQuestRequest.QuestKeys[0].Completed) {
|
||||
logger.debug(`completed quest ${updateQuestRequest.QuestKeys[0].ItemType} `);
|
||||
const questKeyName = updateQuestRequest.QuestKeys[0].ItemType;
|
||||
const questCompletionItems = getQuestCompletionItems(questKeyName);
|
||||
logger.debug(`quest completion items`, questCompletionItems);
|
||||
|
||||
if (questCompletionItems) {
|
||||
const inventoryChanges = await addItems(inventory, questCompletionItems);
|
||||
updateQuestResponse.InventoryChanges = inventoryChanges;
|
||||
}
|
||||
inventory.ActiveQuest = "";
|
||||
}
|
||||
|
||||
//TODO: might need to parse the custom data and add the associated items to inventory
|
||||
if (updateQuestRequest.QuestKeys[0].CustomData) {
|
||||
updateQuestResponse.CustomData = updateQuestRequest.QuestKeys[0].CustomData;
|
||||
}
|
||||
|
||||
await inventory.save();
|
||||
res.send(updateQuestResponse);
|
||||
};
|
@ -5,8 +5,8 @@ const updateSessionGetController: RequestHandler = (_req, res) => {
|
||||
res.json({});
|
||||
};
|
||||
const updateSessionPostController: RequestHandler = (_req, res) => {
|
||||
//console.log("UpdateSessions POST Request:", JSON.parse(String(_req.body)));
|
||||
//console.log("ReqID:", _req.query.sessionId as string);
|
||||
console.log("UpdateSessions POST Request:", JSON.parse(String(_req.body)));
|
||||
console.log("ReqID:", _req.query.sessionId as string);
|
||||
updateSession(_req.query.sessionId as string, String(_req.body));
|
||||
res.json({});
|
||||
};
|
||||
|
@ -4,12 +4,13 @@ import { updateTheme } from "@/src/services/inventoryService";
|
||||
import { IThemeUpdateRequest } from "@/src/types/requestTypes";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
const updateThemeController: RequestHandler = async (request, response) => {
|
||||
const accountId = await getAccountIdForRequest(request);
|
||||
const body = String(request.body);
|
||||
|
||||
try {
|
||||
const json = getJSONfromString<IThemeUpdateRequest>(body);
|
||||
const json = getJSONfromString(body) as IThemeUpdateRequest;
|
||||
if (typeof json !== "object") {
|
||||
throw new Error("Invalid data format");
|
||||
}
|
||||
|
@ -1,171 +1,34 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { IUpgradesRequest } from "@/src/types/requestTypes";
|
||||
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 } from "./infestedFoundryController";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
export const upgradesController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const payload = JSON.parse(String(req.body)) as IUpgradesRequest;
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventoryChanges: IInventoryChanges = {};
|
||||
for (const operation of payload.Operations) {
|
||||
if (
|
||||
operation.UpgradeRequirement == "/Lotus/Types/Items/MiscItems/ModSlotUnlocker" ||
|
||||
operation.UpgradeRequirement == "/Lotus/Types/Items/MiscItems/CustomizationSlotUnlocker"
|
||||
) {
|
||||
updateCurrency(inventory, 10, true);
|
||||
} else {
|
||||
addMiscItems(inventory, [
|
||||
{
|
||||
ItemType: operation.UpgradeRequirement,
|
||||
ItemCount: -1
|
||||
} satisfies IMiscItem
|
||||
]);
|
||||
console.log(req.body);
|
||||
for (const item of payload.UpgradesToAttach) {
|
||||
for (const upgrade of inventory.Upgrades) {
|
||||
if (upgrade._id?.toString() == item.ItemId.$id) {
|
||||
upgrade.UpgradeFingerprint = item.UpgradeFingerprint;
|
||||
upgrade.Slot = item.Slot;
|
||||
upgrade.ParentId = payload.Weapon.ItemId;
|
||||
}
|
||||
}
|
||||
|
||||
if (operation.OperationType == "UOT_ABILITY_OVERRIDE") {
|
||||
console.assert(payload.ItemCategory == "Suits");
|
||||
const suit = inventory.Suits.id(payload.ItemId.$oid)!;
|
||||
|
||||
let newAbilityOverride: IAbilityOverride | undefined;
|
||||
let totalPercentagePointsConsumed = 0;
|
||||
if (operation.UpgradeRequirement != "") {
|
||||
newAbilityOverride = {
|
||||
Ability: operation.UpgradeRequirement,
|
||||
Index: operation.PolarizeSlot
|
||||
};
|
||||
|
||||
const recipe = getRecipeByResult(operation.UpgradeRequirement)!;
|
||||
for (const ingredient of recipe.ingredients) {
|
||||
totalPercentagePointsConsumed += ingredient.ItemCount / 10;
|
||||
inventory.InfestedFoundry!.Resources!.find(x => x.ItemType == ingredient.ItemType)!.Count -=
|
||||
ingredient.ItemCount;
|
||||
}
|
||||
}
|
||||
|
||||
for (const entry of operation.PolarityRemap) {
|
||||
suit.Configs[entry.Slot] ??= {};
|
||||
suit.Configs[entry.Slot].AbilityOverride = newAbilityOverride;
|
||||
}
|
||||
|
||||
const recipeChanges = addInfestedFoundryXP(inventory.InfestedFoundry!, totalPercentagePointsConsumed * 8);
|
||||
addRecipes(inventory, recipeChanges);
|
||||
|
||||
inventoryChanges.Recipes = recipeChanges;
|
||||
inventoryChanges.InfestedFoundry = inventory.toJSON<IInventoryClient>().InfestedFoundry;
|
||||
} else
|
||||
switch (operation.UpgradeRequirement) {
|
||||
case "/Lotus/Types/Items/MiscItems/OrokinReactor":
|
||||
case "/Lotus/Types/Items/MiscItems/OrokinCatalyst":
|
||||
for (const item of inventory[payload.ItemCategory]) {
|
||||
if (item._id.toString() == payload.ItemId.$oid) {
|
||||
item.Features ??= 0;
|
||||
item.Features |= EquipmentFeatures.DOUBLE_CAPACITY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "/Lotus/Types/Items/MiscItems/UtilityUnlocker":
|
||||
case "/Lotus/Types/Items/MiscItems/WeaponUtilityUnlocker":
|
||||
for (const item of inventory[payload.ItemCategory]) {
|
||||
if (item._id.toString() == payload.ItemId.$oid) {
|
||||
item.Features ??= 0;
|
||||
item.Features |= EquipmentFeatures.UTILITY_SLOT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "/Lotus/Types/Items/MiscItems/HeavyWeaponCatalyst":
|
||||
console.assert(payload.ItemCategory == "SpaceGuns");
|
||||
for (const item of inventory[payload.ItemCategory]) {
|
||||
if (item._id.toString() == payload.ItemId.$oid) {
|
||||
item.Features ??= 0;
|
||||
item.Features |= EquipmentFeatures.GRAVIMAG_INSTALLED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "/Lotus/Types/Items/MiscItems/WeaponPrimaryArcaneUnlocker":
|
||||
case "/Lotus/Types/Items/MiscItems/WeaponSecondaryArcaneUnlocker":
|
||||
case "/Lotus/Types/Items/MiscItems/WeaponMeleeArcaneUnlocker":
|
||||
case "/Lotus/Types/Items/MiscItems/WeaponAmpArcaneUnlocker":
|
||||
for (const item of inventory[payload.ItemCategory]) {
|
||||
if (item._id.toString() == payload.ItemId.$oid) {
|
||||
item.Features ??= 0;
|
||||
item.Features |= EquipmentFeatures.ARCANE_SLOT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "/Lotus/Types/Items/MiscItems/Forma":
|
||||
case "/Lotus/Types/Items/MiscItems/FormaUmbra":
|
||||
case "/Lotus/Types/Items/MiscItems/FormaAura":
|
||||
case "/Lotus/Types/Items/MiscItems/FormaStance":
|
||||
for (const item of inventory[payload.ItemCategory]) {
|
||||
if (item._id.toString() == payload.ItemId.$oid) {
|
||||
item.XP = 0;
|
||||
setSlotPolarity(item, operation.PolarizeSlot, operation.PolarizeValue);
|
||||
item.Polarized ??= 0;
|
||||
item.Polarized += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "/Lotus/Types/Items/MiscItems/ModSlotUnlocker":
|
||||
for (const item of inventory[payload.ItemCategory]) {
|
||||
if (item._id.toString() == payload.ItemId.$oid) {
|
||||
item.ModSlotPurchases ??= 0;
|
||||
item.ModSlotPurchases += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "/Lotus/Types/Items/MiscItems/CustomizationSlotUnlocker":
|
||||
for (const item of inventory[payload.ItemCategory]) {
|
||||
if (item._id.toString() == payload.ItemId.$oid) {
|
||||
item.CustomizationSlotPurchases ??= 0;
|
||||
item.CustomizationSlotPurchases += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "":
|
||||
console.assert(operation.OperationType == "UOT_SWAP_POLARITY");
|
||||
for (const item of inventory[payload.ItemCategory]) {
|
||||
if (item._id.toString() == payload.ItemId.$oid) {
|
||||
for (let i = 0; i != operation.PolarityRemap.length; ++i) {
|
||||
if (operation.PolarityRemap[i].Slot != i) {
|
||||
setSlotPolarity(item, i, operation.PolarityRemap[i].Value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unsupported upgrade: " + operation.UpgradeRequirement);
|
||||
}
|
||||
}
|
||||
|
||||
for (const item of payload.UpgradesToDetach) {
|
||||
for (const upgrade of inventory.Upgrades) {
|
||||
if (upgrade._id?.toString() == item.ItemId.$id) {
|
||||
upgrade.UpgradeFingerprint = undefined;
|
||||
upgrade.Slot = undefined;
|
||||
upgrade.ParentId = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await inventory.save();
|
||||
res.json({ InventoryChanges: inventoryChanges });
|
||||
};
|
||||
|
||||
const setSlotPolarity = (item: IEquipmentDatabase, slot: number, polarity: ArtifactPolarity): void => {
|
||||
item.Polarity ??= [];
|
||||
const entry = item.Polarity.find(entry => entry.Slot == slot);
|
||||
if (entry) {
|
||||
entry.Value = polarity;
|
||||
} else {
|
||||
item.Polarity.push({ Slot: slot, Value: polarity });
|
||||
}
|
||||
res.json({});
|
||||
};
|
||||
|
@ -1,17 +0,0 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
|
||||
export const addCurrencyController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const request = req.body as IAddCurrencyRequest;
|
||||
inventory[request.currency] += request.delta;
|
||||
await inventory.save();
|
||||
res.end();
|
||||
};
|
||||
|
||||
interface IAddCurrencyRequest {
|
||||
currency: "RegularCredits" | "PremiumCredits" | "FusionPoints" | "PrimeTokens";
|
||||
delta: number;
|
||||
}
|
28
src/controllers/custom/addItemController.ts
Normal file
28
src/controllers/custom/addItemController.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { ItemType, toAddItemRequest } from "@/src/helpers/customHelpers/addItemHelpers";
|
||||
import { getWeaponType } from "@/src/services/itemDataService";
|
||||
import { addPowerSuit, addEquipment } from "@/src/services/inventoryService";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
const addItemController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const request = toAddItemRequest(req.body);
|
||||
|
||||
switch (request.type) {
|
||||
case ItemType.Powersuit:
|
||||
const powersuit = await addPowerSuit(request.InternalName, accountId);
|
||||
res.json(powersuit);
|
||||
return;
|
||||
case ItemType.Weapon:
|
||||
const weaponType = getWeaponType(request.InternalName);
|
||||
const weapon = await addEquipment(weaponType, request.InternalName, accountId);
|
||||
res.json(weapon);
|
||||
break;
|
||||
default:
|
||||
res.status(400).json({ error: "something went wrong" });
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
export { addItemController };
|
@ -1,19 +0,0 @@
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory, addItem } from "@/src/services/inventoryService";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const addItemsController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const requests = req.body as IAddItemRequest[];
|
||||
const inventory = await getInventory(accountId);
|
||||
for (const request of requests) {
|
||||
await addItem(inventory, request.ItemType, request.ItemCount);
|
||||
}
|
||||
await inventory.save();
|
||||
res.end();
|
||||
};
|
||||
|
||||
interface IAddItemRequest {
|
||||
ItemType: string;
|
||||
ItemCount: number;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
import { addGearExpByCategory, getInventory } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
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";
|
||||
|
||||
export const addXpController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const request = req.body as IAddXpRequest;
|
||||
for (const [category, gear] of Object.entries(request)) {
|
||||
for (const clientItem of gear) {
|
||||
const dbItem = inventory[category as TEquipmentKey].id(clientItem.ItemId.$oid);
|
||||
if (dbItem) {
|
||||
if (dbItem.ItemType in ExportMisc.uniqueLevelCaps) {
|
||||
if ((dbItem.Polarized ?? 0) < 5) {
|
||||
dbItem.Polarized = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
addGearExpByCategory(inventory, gear, category as TEquipmentKey);
|
||||
}
|
||||
await inventory.save();
|
||||
res.end();
|
||||
};
|
||||
|
||||
type IAddXpRequest = {
|
||||
[_ in TEquipmentKey]: IEquipmentClient[];
|
||||
};
|
@ -1,16 +1,15 @@
|
||||
import { toCreateAccount, toDatabaseAccount } from "@/src/helpers/customHelpers/customHelpers";
|
||||
import { createAccount, isNameTaken } from "@/src/services/loginService";
|
||||
import { createAccount } from "@/src/services/loginService";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
const createAccountController: RequestHandler = async (req, res) => {
|
||||
const createAccountData = toCreateAccount(req.body);
|
||||
if (await isNameTaken(createAccountData.DisplayName)) {
|
||||
res.status(409).json("Name already in use");
|
||||
} else {
|
||||
const databaseAccount = toDatabaseAccount(createAccountData);
|
||||
const account = await createAccount(databaseAccount);
|
||||
res.json(account);
|
||||
}
|
||||
const databaseAccount = toDatabaseAccount(createAccountData);
|
||||
|
||||
const account = await createAccount(databaseAccount);
|
||||
|
||||
res.json(account);
|
||||
};
|
||||
|
||||
export { createAccountController };
|
||||
|
@ -1,14 +0,0 @@
|
||||
import { createMessage, IMessageCreationTemplate } from "@/src/services/inboxService";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const createMessageController: RequestHandler = async (req, res) => {
|
||||
const message = req.body as (IMessageCreationTemplate & { ownerId: string })[] | undefined;
|
||||
|
||||
if (!message) {
|
||||
res.status(400).send("No message provided");
|
||||
return;
|
||||
}
|
||||
const savedMessages = await createMessage(message[0].ownerId, message);
|
||||
|
||||
res.json(savedMessages);
|
||||
};
|
@ -1,23 +0,0 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { Account } from "@/src/models/loginModel";
|
||||
import { Inbox } from "@/src/models/inboxModel";
|
||||
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
|
||||
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
|
||||
import { PersonalRooms } from "@/src/models/personalRoomsModel";
|
||||
import { Ship } from "@/src/models/shipModel";
|
||||
import { Stats } from "@/src/models/statsModel";
|
||||
|
||||
export const deleteAccountController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
await Promise.all([
|
||||
Account.deleteOne({ _id: accountId }),
|
||||
Inbox.deleteMany({ ownerId: accountId }),
|
||||
Inventory.deleteOne({ accountOwnerId: accountId }),
|
||||
Loadout.deleteOne({ loadoutOwnerId: accountId }),
|
||||
PersonalRooms.deleteOne({ personalRoomsOwnerId: accountId }),
|
||||
Ship.deleteOne({ ShipOwnerId: accountId }),
|
||||
Stats.deleteOne({ accountOwnerId: accountId })
|
||||
]);
|
||||
res.end();
|
||||
};
|
@ -1,14 +1,8 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { config } from "@/src/services/configService";
|
||||
import { getAccountForRequest, isAdministrator } from "@/src/services/loginService";
|
||||
|
||||
const getConfigDataController: RequestHandler = async (req, res) => {
|
||||
const account = await getAccountForRequest(req);
|
||||
if (isAdministrator(account)) {
|
||||
res.json(config);
|
||||
} else {
|
||||
res.status(401).end();
|
||||
}
|
||||
const getConfigDataController: RequestHandler = (_req, res) => {
|
||||
res.json(config);
|
||||
};
|
||||
|
||||
export { getConfigDataController };
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user