feat: trade fish for standing #681
8
package-lock.json
generated
@ -12,7 +12,7 @@
|
|||||||
"copyfiles": "^2.4.1",
|
"copyfiles": "^2.4.1",
|
||||||
"express": "^5",
|
"express": "^5",
|
||||||
"mongoose": "^8.9.2",
|
"mongoose": "^8.9.2",
|
||||||
"warframe-public-export-plus": "^0.5.17",
|
"warframe-public-export-plus": "^0.5.18",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0"
|
"winston-daily-rotate-file": "^5.0.0"
|
||||||
@ -3778,9 +3778,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/warframe-public-export-plus": {
|
"node_modules/warframe-public-export-plus": {
|
||||||
"version": "0.5.17",
|
"version": "0.5.18",
|
||||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.17.tgz",
|
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.18.tgz",
|
||||||
"integrity": "sha512-AWOfUxDHz+UmpbA9ZUGLIrP+3eQOiVq9tw1FXgx7ySkJLEnZUsoi3wn0IFiavSy2iE6JQIyCiSIZCJQTaCV6kA=="
|
"integrity": "sha512-wUaW5Ua5tXHOYkKJxbealdCcTnRLUN7UCkvYOJEwlB/H14EBzDaqxg4engGqzbq4H8fmttyp3EUo4vazSaxZWg=="
|
||||||
},
|
},
|
||||||
"node_modules/warframe-riven-info": {
|
"node_modules/warframe-riven-info": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
"copyfiles": "^2.4.1",
|
"copyfiles": "^2.4.1",
|
||||||
"express": "^5",
|
"express": "^5",
|
||||||
"mongoose": "^8.9.2",
|
"mongoose": "^8.9.2",
|
||||||
"warframe-public-export-plus": "^0.5.17",
|
"warframe-public-export-plus": "^0.5.18",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0"
|
"winston-daily-rotate-file": "^5.0.0"
|
||||||
|
@ -6,30 +6,48 @@ import { RequestHandler } from "express";
|
|||||||
import { ExportResources } from "warframe-public-export-plus";
|
import { ExportResources } from "warframe-public-export-plus";
|
||||||
|
|
||||||
export const fishmongerController: RequestHandler = async (req, res) => {
|
export const fishmongerController: RequestHandler = async (req, res) => {
|
||||||
if (!req.query.dissect) {
|
|
||||||
throw new Error("expected fishmonger request to be for dissection");
|
|
||||||
}
|
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const inventory = await getInventory(accountId);
|
const inventory = await getInventory(accountId);
|
||||||
const body = getJSONfromString(String(req.body)) as IFishmongerRequest;
|
const body = getJSONfromString(String(req.body)) as IFishmongerRequest;
|
||||||
const miscItemChanges: IMiscItem[] = [];
|
const miscItemChanges: IMiscItem[] = [];
|
||||||
|
let syndicateTag: string | undefined;
|
||||||
|
let standingChange = 0;
|
||||||
for (const fish of body.Fish) {
|
for (const fish of body.Fish) {
|
||||||
for (const part of ExportResources[fish.ItemType].dissectionParts!) {
|
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);
|
const partItem = miscItemChanges.find(x => x.ItemType == part.ItemType);
|
||||||
if (partItem) {
|
if (partItem) {
|
||||||
partItem.ItemCount += part.ItemCount;
|
partItem.ItemCount += part.ItemCount * fish.ItemCount;
|
||||||
} else {
|
} else {
|
||||||
miscItemChanges.push(part);
|
miscItemChanges.push({ ItemType: part.ItemType, ItemCount: part.ItemCount * fish.ItemCount });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
|
} else {
|
||||||
|
syndicateTag = fishData.syndicateTag!;
|
||||||
|
standingChange += fishData.standingBonus! * fish.ItemCount;
|
||||||
|
}
|
||||||
miscItemChanges.push({ ItemType: fish.ItemType, ItemCount: fish.ItemCount * -1 });
|
miscItemChanges.push({ ItemType: fish.ItemType, ItemCount: fish.ItemCount * -1 });
|
||||||
}
|
}
|
||||||
addMiscItems(inventory, miscItemChanges);
|
addMiscItems(inventory, miscItemChanges);
|
||||||
|
if (standingChange && syndicateTag) {
|
||||||
![]() 💡 Codebase verification Based on the code analysis, I can now provide the final response: The non-null assertion on The code shows that
Recommend implementing the suggested null-safe approach:
🔗 Analysis chainEnsure safe usage of optional
Let me verify the safety concerns around the Let me search for more context about the Let me check for the actual data structure and initialization of Let me check the complete fishmongerController for more context about how dissectionParts is used. 🏁 Scripts executedThe following scripts were executed for the analysis: Error: No shell scripts found Script:
Length of output: 669 Script:
Length of output: 1806 Script:
Length of output: 150 Script:
Length of output: 2748 _:bulb: Codebase verification_
Based on the code analysis, I can now provide the final response:
**The non-null assertion on `dissectionParts` is potentially unsafe**
The code shows that `fishData` comes from `ExportResources[fish.ItemType]` which is imported from `warframe-public-export-plus`. The non-null assertion (`!`) on `dissectionParts` is risky because:
- There's no type checking or null check before accessing `dissectionParts`
- The property is only accessed when `dissect === "1"`, suggesting it's an optional operation
- The same pattern of using non-null assertions on optional properties is seen with `syndicateTag!` and `standingBonus!` in the else branch
Recommend implementing the suggested null-safe approach:
```typescript
if (req.query.dissect === "1") {
const parts = fishData.dissectionParts || [];
for (const part of parts) {
// ...
}
}
```
<details>
<summary>🔗 Analysis chain</summary>
**Ensure safe usage of optional `dissectionParts`**
The non-null assertion `fishData.dissectionParts!` assumes that `dissectionParts` is always defined. If there's a possibility of missing or empty dissection parts for new fish types, handle it gracefully to avoid runtime errors.
```diff
if (req.query.dissect === "1") {
- for (const part of fishData.dissectionParts!) {
+ const parts = fishData.dissectionParts || [];
+ for (const part of parts) {
...
}
}
```
---
Let me verify the safety concerns around the `dissectionParts` usage by examining the codebase.
---
Let me search for more context about the `ExportResources` type and its usage.
---
Let me check for the actual data structure and initialization of `ExportResources`.
---
Let me check the complete fishmongerController for more context about how dissectionParts is used.
</details>
<details>
<summary>🏁 Scripts executed</summary>
The following scripts were executed for the analysis:
Error: No shell scripts found
---
Script:
```shell
#!/bin/bash
# Find the type definition or interface for fishData to understand the dissectionParts property
ast-grep --pattern 'interface $_ {
$$$
dissectionParts$_
$$$
}'
# Also search for type declarations
ast-grep --pattern 'type $_ = {
$$$
dissectionParts$_
$$$
}'
# Look for other usages of dissectionParts to understand the pattern
rg "dissectionParts" -A 2 -B 2
```
Length of output: 669
---
Script:
```shell
#!/bin/bash
# Find the ExportResources type/interface definition
ast-grep --pattern 'type ExportResources = {
$$$
}'
ast-grep --pattern 'interface ExportResources {
$$$
}'
# Look for the ExportResources declaration/initialization
rg "ExportResources.*=" -A 5
# Look for any fish-related types or interfaces
ast-grep --pattern 'interface $Fish {
$$$
}'
ast-grep --pattern 'type $Fish = {
$$$
}'
```
Length of output: 1806
---
Script:
```shell
#!/bin/bash
# Look for files that might contain ExportResources data
fd "resources|exports" --type f
# Look for dissectionParts initialization or usage in resource files
rg -l "dissectionParts.*[=:]"
# Check for any fish or dissection related constants or configurations
rg -l "fish.*dissect|dissect.*fish" -i
```
Length of output: 150
---
Script:
```shell
#!/bin/bash
# Get the full content of fishmongerController
cat src/controllers/api/fishmongerController.ts
# Look for any test files related to fishmonger
fd "fishmonger.*test" --type f
# Look for any resource files with .json extension that might contain fish data
fd "\.(json|ts)$" --type f | rg -i "fish|resource"
```
Length of output: 2748
</details>
<!-- This is an auto-generated comment by CodeRabbit -->
|
|||||||
|
const syndicate = inventory.Affiliations.find(x => x.Tag == syndicateTag);
|
||||||
|
if (syndicate !== undefined) {
|
||||||
|
syndicate.Standing += standingChange;
|
||||||
|
} else {
|
||||||
|
inventory.Affiliations.push({
|
||||||
|
Tag: syndicateTag,
|
||||||
|
Standing: standingChange
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
res.json({
|
res.json({
|
||||||
InventoryChanges: {
|
InventoryChanges: {
|
||||||
MiscItems: miscItemChanges
|
MiscItems: miscItemChanges
|
||||||
}
|
},
|
||||||
|
SyndicateTag: syndicateTag,
|
||||||
|
StandingChange: standingChange
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
💡 Codebase verification
Based on the code analysis, I can now provide a final response:
Validation needed for
fishData
accessThe code immediately uses
fishData.dissectionParts
without checking iffishData
exists, which could cause runtime errors. The validation is particularly important because:ExportResources
is accessed with a dynamic keyfish.ItemType
dissectionParts
propertypurchaseService
andinventoryService
implement existence checks within
operator before accessingExportResources
src/controllers/api/fishmongerController.ts:16
: Add null check before accessingfishData
🔗 Analysis chain
Verify existence of
fishData
Accessing
ExportResources[fish.ItemType]
without any check can cause errors iffish.ItemType
is missing from the export or is undefined. Consider adding a validation step or fallback logic.Let me gather information about the
ExportResources
and its usage to verify this concern.Let me analyze the usage of
ExportResources
to understand if we need validation. I'll search for its usage patterns and error handling.🏁 Scripts executed
The following scripts were executed for the analysis:
Error: No shell scripts found
Script:
Length of output: 87233
Script:
Length of output: 11028