返回提交历史
Deleted
src/controllers/custom/addItemController.ts
+0
-33
Added
src/controllers/custom/addItemsController.ts
+33
-0
Deleted
src/helpers/customHelpers/addItemHelpers.ts
+0
-46
Modified
src/routes/custom.ts
+2
-2
Modified
static/webui/index.html
+22
-15
Modified
static/webui/script.js
+59
-10
XFEstudio/SpaceNinjaServer
feat(webui): add "add missing warframes" & "add missing weapons" (#775)
215b8397
代码差异
6 个文件
+116
-106
@@ -1,33 +0,0 @@
1
import { getAccountIdForRequest } from "@/src/services/loginService";
2
import { ItemType, toAddItemRequest } from "@/src/helpers/customHelpers/addItemHelpers";
3
import { getWeaponType } from "@/src/services/itemDataService";
4
import { addPowerSuit, addEquipment, getInventory } from "@/src/services/inventoryService";
5
import { RequestHandler } from "express";
6
7
const addItemController: RequestHandler = async (req, res) => {
8
const accountId = await getAccountIdForRequest(req);
9
const request = toAddItemRequest(req.body);
10
11
switch (request.type) {
12
case ItemType.Powersuit: {
13
const inventory = await getInventory(accountId);
14
const inventoryChanges = addPowerSuit(inventory, request.InternalName);
15
await inventory.save();
16
res.json(inventoryChanges);
17
return;
18
}
19
case ItemType.Weapon: {
20
const inventory = await getInventory(accountId);
21
const weaponType = getWeaponType(request.InternalName);
22
const inventoryChanges = addEquipment(inventory, weaponType, request.InternalName);
23
await inventory.save();
24
res.json(inventoryChanges);
25
break;
26
}
27
default:
28
res.status(400).json({ error: "something went wrong" });
29
break;
30
}
31
};
32
33
export { addItemController };
@@ -0,0 +1,33 @@
1
import { getAccountIdForRequest } from "@/src/services/loginService";
2
import { getWeaponType } from "@/src/services/itemDataService";
3
import { addPowerSuit, addEquipment, getInventory } from "@/src/services/inventoryService";
4
import { RequestHandler } from "express";
5
6
export const addItemsController: RequestHandler = async (req, res) => {
7
const accountId = await getAccountIdForRequest(req);
8
const requests = req.body as IAddItemRequest[];
9
const inventory = await getInventory(accountId);
10
for (const request of requests) {
11
switch (request.type) {
12
case ItemType.Powersuit:
13
addPowerSuit(inventory, request.internalName);
14
break;
15
16
case ItemType.Weapon:
17
addEquipment(inventory, getWeaponType(request.internalName), request.internalName);
18
break;
19
}
20
}
21
await inventory.save();
22
res.end();
23
};
24
25
enum ItemType {
26
Powersuit = "Powersuit",
27
Weapon = "Weapon"
28
}
29
30
interface IAddItemRequest {
31
type: ItemType;
32
internalName: string;
33
}
@@ -1,46 +0,0 @@
1
import { isString } from "@/src/helpers/general";
2
3
export enum ItemType {
4
Powersuit = "Powersuit",
5
Weapon = "Weapon"
6
}
7
8
export const isItemType = (itemType: string): itemType is ItemType => {
9
return Object.keys(ItemType).includes(itemType);
10
};
11
12
const parseItemType = (itemType: unknown): ItemType => {
13
if (!itemType || !isString(itemType) || !isItemType(itemType)) {
14
throw new Error("incorrect item type");
15
}
16
17
return itemType;
18
};
19
20
interface IAddItemRequest {
21
type: ItemType;
22
InternalName: string;
23
}
24
25
const parseInternalItemName = (internalName: unknown): string => {
26
if (!isString(internalName)) {
27
throw new Error("incorrect internal name");
28
}
29
30
return internalName;
31
};
32
33
export const toAddItemRequest = (body: unknown): IAddItemRequest => {
34
if (!body || typeof body !== "object") {
35
throw new Error("incorrect or missing add item request data");
36
}
37
38
if ("type" in body && "internalName" in body) {
39
return {
40
type: parseItemType(body.type),
41
InternalName: parseInternalItemName(body.internalName)
42
};
43
}
44
45
throw new Error("malformed add item request");
46
};
@@ -8,7 +8,7 @@ import { deleteAccountController } from "@/src/controllers/custom/deleteAccountC
8
8
import { renameAccountController } from "@/src/controllers/custom/renameAccountController";
9
9
10
10
import { createAccountController } from "@/src/controllers/custom/createAccountController";
11
import { addItemController } from "@/src/controllers/custom/addItemController";
11
import { addItemsController } from "@/src/controllers/custom/addItemsController";
12
12
13
13
import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
14
14
import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
@@ -23,7 +23,7 @@ customRouter.get("/deleteAccount", deleteAccountController);
23
23
customRouter.get("/renameAccount", renameAccountController);
24
24
25
25
customRouter.post("/createAccount", createAccountController);
26
customRouter.post("/addItem", addItemController);
26
customRouter.post("/addItems", addItemsController);
27
27
28
28
customRouter.get("/config", getConfigDataController);
29
29
customRouter.post("/config", updateConfigDataController);
@@ -82,11 +82,11 @@
82
82
</form>
83
83
</div>
84
84
<div data-route="/webui/inventory" data-title="Inventory | OpenWF WebUI">
85
<p class="mb-4">
85
<p class="mb-3">
86
86
Note: Changes made here will only be reflected in-game when the game re-downloads your
87
87
inventory. Visiting the navigation should be the easiest way to trigger that.
88
88
</p>
89
<div class="card mb-4">
89
<div class="card mb-3">
90
90
<h5 class="card-header">Add Items</h5>
91
91
<form class="card-body input-group" onsubmit="doAcquireMiscItems();return false;">
92
92
<input class="form-control" id="miscitem-count" type="number" min="1" value="1" />
@@ -94,9 +94,9 @@
94
94
<button class="btn btn-primary" type="submit">Add</button>
95
95
</form>
96
96
</div>
97
<div class="row">
97
<div class="row g-3">
98
98
<div class="col-lg-6">
99
<div class="card mb-4">
99
<div class="card mb-3">
100
100
<h5 class="card-header">Warframes</h5>
101
101
<div class="card-body">
102
102
<form class="input-group mb-3" onsubmit="doAcquireWarframe();return false;">
@@ -108,9 +108,16 @@
108
108
</table>
109
109
</div>
110
110
</div>
111
<div class="card mb-3">
112
<h5 class="card-header">Bulk Actions</h5>
113
<div class="card-body">
114
<button class="btn btn-primary" onclick="addMissingWarframes();">Add Missing Warframes</button>
115
<button class="btn btn-primary" onclick="addMissingWeapons();">Add Missing Weapons</button>
116
</div>
117
</div>
111
118
</div>
112
119
<div class="col-lg-6">
113
<div class="card mb-4">
120
<div class="card mb-3">
114
121
<h5 class="card-header">Weapons</h5>
115
122
<div class="card-body">
116
123
<form class="input-group mb-3" onsubmit="doAcquireWeapon();return false;">
@@ -128,7 +135,7 @@
128
135
<div id="powersuit-route" data-route="~ /webui/powersuit/(.+)" data-title="Inventory | OpenWF WebUI">
129
136
<h3 class="mb-0"></h3>
130
137
<p class="text-body-secondary"></p>
131
<div class="card mb-4">
138
<div class="card mb-3">
132
139
<h5 class="card-header">Archon Shard Slots</h5>
133
140
<div class="card-body">
134
141
<p>You can use these unlimited slots to apply a wide range of upgrades.</p>
@@ -145,13 +152,13 @@
145
152
</div>
146
153
</div>
147
154
<div data-route="/webui/mods" data-title="Mods | OpenWF WebUI">
148
<p class="mb-4">
155
<p class="mb-3">
149
156
Note: Changes made here will only be reflected in-game when the game re-downloads your
150
157
inventory. Visiting the navigation should be the easiest way to trigger that.
151
158
</p>
152
<div class="row">
159
<div class="row g-3">
153
160
<div class="col-xxl-6">
154
<div class="card mb-4">
161
<div class="card mb-3">
155
162
<h5 class="card-header">Add Riven</h5>
156
163
<form class="card-body" onsubmit="doAcquireRiven();return false;">
157
164
<select class="form-control mb-3" id="addriven-type">
@@ -168,7 +175,7 @@
168
175
<a href="riven-tool/" target="_blank">Need help with the fingerprint?</a>
169
176
</form>
170
177
</div>
171
<div class="card mb-4">
178
<div class="card mb-3">
172
179
<h5 class="card-header">Rivens</h5>
173
180
<div class="card-body">
174
181
<table class="table table-hover w-100">
@@ -178,7 +185,7 @@
178
185
</div>
179
186
</div>
180
187
<div class="col-xxl-6">
181
<div class="card mb-4">
188
<div class="card mb-3">
182
189
<h5 class="card-header">Mods</h5>
183
190
<div class="card-body">
184
191
<form class="input-group mb-3" onsubmit="doAcquireMod();return false;">
@@ -194,9 +201,9 @@
194
201
</div>
195
202
</div>
196
203
<div data-route="/webui/cheats, /webui/settings" data-title="Cheats | OpenWF WebUI">
197
<div class="row">
204
<div class="row g-3">
198
205
<div class="col-lg-4">
199
<div class="card mb-4">
206
<div class="card mb-3">
200
207
<h5 class="card-header">Server</h5>
201
208
<div class="card-body">
202
209
<div id="server-settings-no-perms" class="d-none">
@@ -283,7 +290,7 @@
283
290
</div>
284
291
</div>
285
292
<div class="col-lg-4">
286
<div class="card mb-4">
293
<div class="card mb-3">
287
294
<h5 class="card-header">Account</h5>
288
295
<div class="card-body">
289
296
<p><button class="btn btn-primary" onclick="doUnlockAllFocusSchools();">Unlock All Focus Schools</button></p>
@@ -292,7 +299,7 @@
292
299
</div>
293
300
</div>
294
301
<div class="col-lg-4">
295
<div class="card mb-4">
302
<div class="card mb-3">
296
303
<h5 class="card-header">Client</h5>
297
304
<div id="client-cheats-nok" class="card-body">
298
305
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() {
190
190
document.getElementById("warframe-list").innerHTML = "";
191
191
data.Suits.forEach(item => {
192
192
const tr = document.createElement("tr");
193
tr.setAttribute("data-item-type", item.ItemType);
193
194
{
194
195
const td = document.createElement("td");
195
196
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
@@ -267,6 +268,7 @@ function updateInventory() {
267
268
["LongGuns", "Pistols", "Melee"].forEach(category => {
268
269
data[category].forEach(item => {
269
270
const tr = document.createElement("tr");
271
tr.setAttribute("data-item-type", item.ItemType);
270
272
{
271
273
const td = document.createElement("td");
272
274
td.textContent = itemMap[item.ItemType]?.name ?? item.ItemType;
@@ -527,12 +529,14 @@ function doAcquireWarframe() {
527
529
}
528
530
revalidateAuthz(() => {
529
531
const req = $.post({
530
url: "/custom/addItem?" + window.authz,
532
url: "/custom/addItems?" + window.authz,
531
533
contentType: "application/json",
532
data: JSON.stringify({
533
type: "Powersuit",
534
internalName: uniqueName
535
})
534
data: JSON.stringify([
535
{
536
type: "Powersuit",
537
internalName: uniqueName
538
}
539
])
536
540
});
537
541
req.done(() => {
538
542
document.getElementById("warframe-to-acquire").value = "";
@@ -553,12 +557,14 @@ function doAcquireWeapon() {
553
557
}
554
558
revalidateAuthz(() => {
555
559
const req = $.post({
556
url: "/custom/addItem?" + window.authz,
560
url: "/custom/addItems?" + window.authz,
557
561
contentType: "application/json",
558
data: JSON.stringify({
559
type: "Weapon",
560
internalName: uniqueName
561
})
562
data: JSON.stringify([
563
{
564
type: "Weapon",
565
internalName: uniqueName
566
}
567
])
562
568
});
563
569
req.done(() => {
564
570
document.getElementById("weapon-to-acquire").value = "";
@@ -571,6 +577,49 @@ $("#weapon-to-acquire").on("input", () => {
571
577
$("#weapon-to-acquire").removeClass("is-invalid");
572
578
});
573
579
580
function dispatchAddItemsRequestsBatch(requests) {
581
revalidateAuthz(() => {
582
const req = $.post({
583
url: "/custom/addItems?" + window.authz,
584
contentType: "application/json",
585
data: JSON.stringify(requests)
586
});
587
req.done(() => {
588
updateInventory();
589
});
590
});
591
}
592
593
function addMissingWarframes() {
594
const requests = [];
595
document.querySelectorAll("#datalist-warframes option").forEach(elm => {
596
if (!document.querySelector("#warframe-list [data-item-type='" + elm.getAttribute("data-key") + "']")) {
597
requests.push({ type: "Powersuit", internalName: elm.getAttribute("data-key") });
598
}
599
});
600
if (
601
requests.length != 0 &&
602
window.confirm("Are you sure you want to add " + requests.length + " items to your account?")
603
) {
604
dispatchAddItemsRequestsBatch(requests);
605
}
606
}
607
608
function addMissingWeapons() {
609
const requests = [];
610
document.querySelectorAll("#datalist-weapons option").forEach(elm => {
611
if (!document.querySelector("#weapon-list [data-item-type='" + elm.getAttribute("data-key") + "']")) {
612
requests.push({ type: "Weapon", internalName: elm.getAttribute("data-key") });
613
}
614
});
615
if (
616
requests.length != 0 &&
617
window.confirm("Are you sure you want to add " + requests.length + " items to your account?")
618
) {
619
dispatchAddItemsRequestsBatch(requests);
620
}
621
}
622
574
623
function addGearExp(category, oid, xp) {
575
624
const data = {};
576
625
data[category] = [