feat(webui): add "add missing warframes" & "add missing weapons" #775
@ -1,33 +0,0 @@
|
|||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
|
||||||
import { ItemType, toAddItemRequest } from "@/src/helpers/customHelpers/addItemHelpers";
|
|
||||||
import { getWeaponType } from "@/src/services/itemDataService";
|
|
||||||
import { addPowerSuit, addEquipment, getInventory } from "@/src/services/inventoryService";
|
|
||||||
import { RequestHandler } from "express";
|
|
||||||
|
|
||||||
const addItemController: RequestHandler = async (req, res) => {
|
|
||||||
const accountId = await getAccountIdForRequest(req);
|
|
||||||
const request = toAddItemRequest(req.body);
|
|
||||||
|
|
||||||
switch (request.type) {
|
|
||||||
case ItemType.Powersuit: {
|
|
||||||
const inventory = await getInventory(accountId);
|
|
||||||
const inventoryChanges = addPowerSuit(inventory, request.InternalName);
|
|
||||||
await inventory.save();
|
|
||||||
res.json(inventoryChanges);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case ItemType.Weapon: {
|
|
||||||
const inventory = await getInventory(accountId);
|
|
||||||
const weaponType = getWeaponType(request.InternalName);
|
|
||||||
const inventoryChanges = addEquipment(inventory, weaponType, request.InternalName);
|
|
||||||
await inventory.save();
|
|
||||||
res.json(inventoryChanges);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
res.status(400).json({ error: "something went wrong" });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export { addItemController };
|
|
33
src/controllers/custom/addItemsController.ts
Normal file
33
src/controllers/custom/addItemsController.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { getWeaponType } from "@/src/services/itemDataService";
|
||||||
|
import { addPowerSuit, addEquipment, getInventory } 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) {
|
||||||
|
switch (request.type) {
|
||||||
|
case ItemType.Powersuit:
|
||||||
|
addPowerSuit(inventory, request.internalName);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ItemType.Weapon:
|
||||||
|
addEquipment(inventory, getWeaponType(request.internalName), request.internalName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await inventory.save();
|
||||||
|
res.end();
|
||||||
|
};
|
||||||
|
|||||||
|
|
||||||
|
enum ItemType {
|
||||||
|
Powersuit = "Powersuit",
|
||||||
|
Weapon = "Weapon"
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IAddItemRequest {
|
||||||
|
type: ItemType;
|
||||||
|
internalName: string;
|
||||||
|
}
|
@ -1,46 +0,0 @@
|
|||||||
import { isString } from "@/src/helpers/general";
|
|
||||||
|
|
||||||
export enum ItemType {
|
|
||||||
Powersuit = "Powersuit",
|
|
||||||
Weapon = "Weapon"
|
|
||||||
}
|
|
||||||
|
|
||||||
export const isItemType = (itemType: string): itemType is ItemType => {
|
|
||||||
return Object.keys(ItemType).includes(itemType);
|
|
||||||
};
|
|
||||||
|
|
||||||
const parseItemType = (itemType: unknown): ItemType => {
|
|
||||||
if (!itemType || !isString(itemType) || !isItemType(itemType)) {
|
|
||||||
throw new Error("incorrect item type");
|
|
||||||
}
|
|
||||||
|
|
||||||
return itemType;
|
|
||||||
};
|
|
||||||
|
|
||||||
interface IAddItemRequest {
|
|
||||||
type: ItemType;
|
|
||||||
InternalName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const parseInternalItemName = (internalName: unknown): string => {
|
|
||||||
if (!isString(internalName)) {
|
|
||||||
throw new Error("incorrect internal name");
|
|
||||||
}
|
|
||||||
|
|
||||||
return internalName;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const toAddItemRequest = (body: unknown): IAddItemRequest => {
|
|
||||||
if (!body || typeof body !== "object") {
|
|
||||||
throw new Error("incorrect or missing add item request data");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("type" in body && "internalName" in body) {
|
|
||||||
return {
|
|
||||||
type: parseItemType(body.type),
|
|
||||||
InternalName: parseInternalItemName(body.internalName)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error("malformed add item request");
|
|
||||||
};
|
|
@ -8,7 +8,7 @@ import { deleteAccountController } from "@/src/controllers/custom/deleteAccountC
|
|||||||
import { renameAccountController } from "@/src/controllers/custom/renameAccountController";
|
import { renameAccountController } from "@/src/controllers/custom/renameAccountController";
|
||||||
|
|
||||||
import { createAccountController } from "@/src/controllers/custom/createAccountController";
|
import { createAccountController } from "@/src/controllers/custom/createAccountController";
|
||||||
import { addItemController } from "@/src/controllers/custom/addItemController";
|
import { addItemsController } from "@/src/controllers/custom/addItemsController";
|
||||||
|
|
||||||
import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
|
import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
|
||||||
import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
|
import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
|
||||||
@ -23,7 +23,7 @@ customRouter.get("/deleteAccount", deleteAccountController);
|
|||||||
customRouter.get("/renameAccount", renameAccountController);
|
customRouter.get("/renameAccount", renameAccountController);
|
||||||
|
|
||||||
customRouter.post("/createAccount", createAccountController);
|
customRouter.post("/createAccount", createAccountController);
|
||||||
customRouter.post("/addItem", addItemController);
|
customRouter.post("/addItems", addItemsController);
|
||||||
|
|
||||||
customRouter.get("/config", getConfigDataController);
|
customRouter.get("/config", getConfigDataController);
|
||||||
customRouter.post("/config", updateConfigDataController);
|
customRouter.post("/config", updateConfigDataController);
|
||||||
|
@ -82,11 +82,11 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div data-route="/webui/inventory" data-title="Inventory | OpenWF WebUI">
|
<div data-route="/webui/inventory" data-title="Inventory | OpenWF WebUI">
|
||||||
<p class="mb-4">
|
<p class="mb-3">
|
||||||
Note: Changes made here will only be reflected in-game when the game re-downloads your
|
Note: Changes made here will only be reflected in-game when the game re-downloads your
|
||||||
inventory. Visiting the navigation should be the easiest way to trigger that.
|
inventory. Visiting the navigation should be the easiest way to trigger that.
|
||||||
</p>
|
</p>
|
||||||
<div class="card mb-4">
|
<div class="card mb-3">
|
||||||
<h5 class="card-header">Add Items</h5>
|
<h5 class="card-header">Add Items</h5>
|
||||||
<form class="card-body input-group" onsubmit="doAcquireMiscItems();return false;">
|
<form class="card-body input-group" onsubmit="doAcquireMiscItems();return false;">
|
||||||
<input class="form-control" id="miscitem-count" type="number" min="1" value="1" />
|
<input class="form-control" id="miscitem-count" type="number" min="1" value="1" />
|
||||||
@ -94,9 +94,9 @@
|
|||||||
<button class="btn btn-primary" type="submit">Add</button>
|
<button class="btn btn-primary" type="submit">Add</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row g-3">
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-4">
|
<div class="card mb-3">
|
||||||
<h5 class="card-header">Warframes</h5>
|
<h5 class="card-header">Warframes</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form class="input-group mb-3" onsubmit="doAcquireWarframe();return false;">
|
<form class="input-group mb-3" onsubmit="doAcquireWarframe();return false;">
|
||||||
@ -108,9 +108,16 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card mb-3">
|
||||||
|
<h5 class="card-header">Bulk Actions</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<button class="btn btn-primary" onclick="addMissingWarframes();">Add Missing Warframes</button>
|
||||||
|
<button class="btn btn-primary" onclick="addMissingWeapons();">Add Missing Weapons</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-4">
|
<div class="card mb-3">
|
||||||
<h5 class="card-header">Weapons</h5>
|
<h5 class="card-header">Weapons</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form class="input-group mb-3" onsubmit="doAcquireWeapon();return false;">
|
<form class="input-group mb-3" onsubmit="doAcquireWeapon();return false;">
|
||||||
@ -128,7 +135,7 @@
|
|||||||
<div id="powersuit-route" data-route="~ /webui/powersuit/(.+)" data-title="Inventory | OpenWF WebUI">
|
<div id="powersuit-route" data-route="~ /webui/powersuit/(.+)" data-title="Inventory | OpenWF WebUI">
|
||||||
<h3 class="mb-0"></h3>
|
<h3 class="mb-0"></h3>
|
||||||
<p class="text-body-secondary"></p>
|
<p class="text-body-secondary"></p>
|
||||||
<div class="card mb-4">
|
<div class="card mb-3">
|
||||||
<h5 class="card-header">Archon Shard Slots</h5>
|
<h5 class="card-header">Archon Shard Slots</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<p>You can use these unlimited slots to apply a wide range of upgrades.</p>
|
<p>You can use these unlimited slots to apply a wide range of upgrades.</p>
|
||||||
@ -145,13 +152,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div data-route="/webui/mods" data-title="Mods | OpenWF WebUI">
|
<div data-route="/webui/mods" data-title="Mods | OpenWF WebUI">
|
||||||
<p class="mb-4">
|
<p class="mb-3">
|
||||||
Note: Changes made here will only be reflected in-game when the game re-downloads your
|
Note: Changes made here will only be reflected in-game when the game re-downloads your
|
||||||
inventory. Visiting the navigation should be the easiest way to trigger that.
|
inventory. Visiting the navigation should be the easiest way to trigger that.
|
||||||
</p>
|
</p>
|
||||||
<div class="row">
|
<div class="row g-3">
|
||||||
<div class="col-xxl-6">
|
<div class="col-xxl-6">
|
||||||
<div class="card mb-4">
|
<div class="card mb-3">
|
||||||
<h5 class="card-header">Add Riven</h5>
|
<h5 class="card-header">Add Riven</h5>
|
||||||
<form class="card-body" onsubmit="doAcquireRiven();return false;">
|
<form class="card-body" onsubmit="doAcquireRiven();return false;">
|
||||||
<select class="form-control mb-3" id="addriven-type">
|
<select class="form-control mb-3" id="addriven-type">
|
||||||
@ -168,7 +175,7 @@
|
|||||||
<a href="riven-tool/" target="_blank">Need help with the fingerprint?</a>
|
<a href="riven-tool/" target="_blank">Need help with the fingerprint?</a>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="card mb-4">
|
<div class="card mb-3">
|
||||||
<h5 class="card-header">Rivens</h5>
|
<h5 class="card-header">Rivens</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<table class="table table-hover w-100">
|
<table class="table table-hover w-100">
|
||||||
@ -178,7 +185,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xxl-6">
|
<div class="col-xxl-6">
|
||||||
<div class="card mb-4">
|
<div class="card mb-3">
|
||||||
<h5 class="card-header">Mods</h5>
|
<h5 class="card-header">Mods</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form class="input-group mb-3" onsubmit="doAcquireMod();return false;">
|
<form class="input-group mb-3" onsubmit="doAcquireMod();return false;">
|
||||||
@ -194,9 +201,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div data-route="/webui/cheats, /webui/settings" data-title="Cheats | OpenWF WebUI">
|
<div data-route="/webui/cheats, /webui/settings" data-title="Cheats | OpenWF WebUI">
|
||||||
<div class="row">
|
<div class="row g-3">
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
<div class="card mb-4">
|
<div class="card mb-3">
|
||||||
<h5 class="card-header">Server</h5>
|
<h5 class="card-header">Server</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div id="server-settings-no-perms" class="d-none">
|
<div id="server-settings-no-perms" class="d-none">
|
||||||
@ -283,7 +290,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
<div class="card mb-4">
|
<div class="card mb-3">
|
||||||
<h5 class="card-header">Account</h5>
|
<h5 class="card-header">Account</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<p><button class="btn btn-primary" onclick="doUnlockAllFocusSchools();">Unlock All Focus Schools</button></p>
|
<p><button class="btn btn-primary" onclick="doUnlockAllFocusSchools();">Unlock All Focus Schools</button></p>
|
||||||
@ -292,7 +299,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
<div class="card mb-4">
|
<div class="card mb-3">
|
||||||
<h5 class="card-header">Client</h5>
|
<h5 class="card-header">Client</h5>
|
||||||
<div id="client-cheats-nok" class="card-body">
|
<div id="client-cheats-nok" class="card-body">
|
||||||
Client cheats are currently unavailable. This could be because your client is not running or using a DLL without an HTTP interface.
|
Client cheats are currently unavailable. This could be because your client is not running or using a DLL without an HTTP interface.
|
||||||
|
@ -190,6 +190,7 @@ function updateInventory() {
|
|||||||
document.getElementById("warframe-list").innerHTML = "";
|
document.getElementById("warframe-list").innerHTML = "";
|
||||||
data.Suits.forEach(item => {
|
data.Suits.forEach(item => {
|
||||||
const tr = document.createElement("tr");
|
const tr = document.createElement("tr");
|
||||||
|
tr.setAttribute("data-item-type", item.ItemType);
|
||||||
{
|
{
|
||||||
const td = document.createElement("td");
|
const td = document.createElement("td");
|
||||||
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
|
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
|
||||||
@ -267,6 +268,7 @@ function updateInventory() {
|
|||||||
["LongGuns", "Pistols", "Melee"].forEach(category => {
|
["LongGuns", "Pistols", "Melee"].forEach(category => {
|
||||||
data[category].forEach(item => {
|
data[category].forEach(item => {
|
||||||
const tr = document.createElement("tr");
|
const tr = document.createElement("tr");
|
||||||
|
tr.setAttribute("data-item-type", item.ItemType);
|
||||||
{
|
{
|
||||||
const td = document.createElement("td");
|
const td = document.createElement("td");
|
||||||
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
|
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
|
||||||
@ -524,12 +526,14 @@ function doAcquireWarframe() {
|
|||||||
}
|
}
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz(() => {
|
||||||
const req = $.post({
|
const req = $.post({
|
||||||
url: "/custom/addItem?" + window.authz,
|
url: "/custom/addItems?" + window.authz,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
data: JSON.stringify({
|
data: JSON.stringify([
|
||||||
|
{
|
||||||
type: "Powersuit",
|
type: "Powersuit",
|
||||||
internalName: uniqueName
|
internalName: uniqueName
|
||||||
})
|
}
|
||||||
|
])
|
||||||
});
|
});
|
||||||
req.done(() => {
|
req.done(() => {
|
||||||
document.getElementById("warframe-to-acquire").value = "";
|
document.getElementById("warframe-to-acquire").value = "";
|
||||||
@ -550,12 +554,14 @@ function doAcquireWeapon() {
|
|||||||
}
|
}
|
||||||
revalidateAuthz(() => {
|
revalidateAuthz(() => {
|
||||||
const req = $.post({
|
const req = $.post({
|
||||||
url: "/custom/addItem?" + window.authz,
|
url: "/custom/addItems?" + window.authz,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
data: JSON.stringify({
|
data: JSON.stringify([
|
||||||
|
{
|
||||||
type: "Weapon",
|
type: "Weapon",
|
||||||
internalName: uniqueName
|
internalName: uniqueName
|
||||||
})
|
}
|
||||||
|
])
|
||||||
});
|
});
|
||||||
req.done(() => {
|
req.done(() => {
|
||||||
document.getElementById("weapon-to-acquire").value = "";
|
document.getElementById("weapon-to-acquire").value = "";
|
||||||
@ -568,6 +574,49 @@ $("#weapon-to-acquire").on("input", () => {
|
|||||||
$("#weapon-to-acquire").removeClass("is-invalid");
|
$("#weapon-to-acquire").removeClass("is-invalid");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function dispatchAddItemsRequestsBatch(requests) {
|
||||||
|
revalidateAuthz(() => {
|
||||||
|
const req = $.post({
|
||||||
|
url: "/custom/addItems?" + window.authz,
|
||||||
|
contentType: "application/json",
|
||||||
|
data: JSON.stringify(requests)
|
||||||
|
});
|
||||||
|
req.done(() => {
|
||||||
|
updateInventory();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMissingWarframes() {
|
||||||
|
const requests = [];
|
||||||
|
document.querySelectorAll("#datalist-warframes option").forEach(elm => {
|
||||||
|
if (!document.querySelector("#warframe-list [data-item-type='" + elm.getAttribute("data-key") + "']")) {
|
||||||
|
requests.push({ type: "Powersuit", internalName: elm.getAttribute("data-key") });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (
|
||||||
|
requests.length != 0 &&
|
||||||
|
window.confirm("Are you sure you want to add " + requests.length + " items to your account?")
|
||||||
|
) {
|
||||||
|
dispatchAddItemsRequestsBatch(requests);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMissingWeapons() {
|
||||||
|
const requests = [];
|
||||||
|
document.querySelectorAll("#datalist-weapons option").forEach(elm => {
|
||||||
|
if (!document.querySelector("#weapon-list [data-item-type='" + elm.getAttribute("data-key") + "']")) {
|
||||||
|
requests.push({ type: "Weapon", internalName: elm.getAttribute("data-key") });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (
|
||||||
|
requests.length != 0 &&
|
||||||
|
window.confirm("Are you sure you want to add " + requests.length + " items to your account?")
|
||||||
|
) {
|
||||||
|
dispatchAddItemsRequestsBatch(requests);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function addGearExp(category, oid, xp) {
|
function addGearExp(category, oid, xp) {
|
||||||
const data = {};
|
const data = {};
|
||||||
data[category] = [
|
data[category] = [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user
🛠️ Refactor suggestion
Consider adding error handling for invalid request bodies.
The controller lacks error handling for:
Consider adding error handling:
📝 Committable suggestion