feat: basic implementation of endlessXp.php we can play The Circuit #596

Merged
Sainan merged 1 commits from endlessxp into main 2024-12-22 11:36:01 -08:00
4 changed files with 83 additions and 2 deletions

View File

@ -0,0 +1,60 @@
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(String(req.body)) as IEndlessXpRequest;
coderabbitai[bot] commented 2024-12-22 06:45:14 -08:00 (Migrated from github.com)
Review

⚠️ Potential issue

Add error handling and input validation.

The controller lacks error handling for potential failures and input validation.

Add try-catch and validation:

 export const endlessXpController: RequestHandler = async (req, res) => {
+    try {
+        if (!req.body) {
+            return res.status(400).json({ error: 'Missing request body' });
+        }
+
         const accountId = await getAccountIdForRequest(req);
+        if (!accountId) {
+            return res.status(401).json({ error: 'Unauthorized' });
+        }
+
         const inventory = await getInventory(accountId);
         const payload = getJSONfromString(String(req.body)) as IEndlessXpRequest;
+
+        if (!payload.Category || !Array.isArray(payload.Choices)) {
+            return res.status(400).json({ error: 'Invalid payload format' });
+        }
+    } catch (error) {
+        console.error('Error in endlessXpController:', error);
+        return res.status(500).json({ error: 'Internal server error' });
+    }

Committable suggestion skipped: line range outside the PR's diff.

_:warning: Potential issue_ **Add error handling and input validation.** The controller lacks error handling for potential failures and input validation. Add try-catch and validation: ```diff export const endlessXpController: RequestHandler = async (req, res) => { + try { + if (!req.body) { + return res.status(400).json({ error: 'Missing request body' }); + } + const accountId = await getAccountIdForRequest(req); + if (!accountId) { + return res.status(401).json({ error: 'Unauthorized' }); + } + const inventory = await getInventory(accountId); const payload = getJSONfromString(String(req.body)) as IEndlessXpRequest; + + if (!payload.Category || !Array.isArray(payload.Choices)) { + return res.status(400).json({ error: 'Invalid payload format' }); + } + } catch (error) { + console.error('Error in endlessXpController:', error); + return res.status(500).json({ error: 'Internal server error' }); + } ``` > Committable suggestion skipped: line range outside the PR's diff. <!-- This is an auto-generated comment by CodeRabbit -->
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
}
]
}
// ...
]
}
});
coderabbitai[bot] commented 2024-12-22 06:45:14 -08:00 (Migrated from github.com)
Review

⚠️ Potential issue

Add validation and remove hardcoded values.

The response contains hardcoded values which should be dynamic:

  • Earn/Claim values are set to 0
  • BonusAvailable/Expiry dates use hardcoded "9999999999999"
  • PendingRewards contains a hardcoded reward

Consider:

  1. Calculate Earn/Claim values based on user progress
  2. Use actual dates for BonusAvailable/Expiry
  3. Load PendingRewards from a configuration source
     res.json({
         NewProgress: {
             Category: payload.Category,
-            Earn: 0,
-            Claim: 0,
+            Earn: calculateEarnValue(inventory, payload.Category),
+            Claim: calculateClaimValue(inventory, payload.Category),
             BonusAvailable: {
                 $date: {
-                    $numberLong: "9999999999999"
+                    $numberLong: calculateBonusDate().toString()
                 }
             },
             Expiry: {
                 $date: {
-                    $numberLong: "9999999999999"
+                    $numberLong: calculateExpiryDate().toString()
                 }
             },
             Choices: payload.Choices,
-            PendingRewards: [
-                {
-                    RequiredTotalXp: 190,
-                    Rewards: [
-                        {
-                            StoreItem: "/Lotus/StoreItems/Upgrades/Mods/Aura/PlayerHealthAuraMod",
-                            ItemCount: 1
-                        }
-                    ]
-                }
-            ]
+            PendingRewards: await loadPendingRewards(payload.Category)
         }
     });

Committable suggestion skipped: line range outside the PR's diff.

_:warning: Potential issue_ **Add validation and remove hardcoded values.** The response contains hardcoded values which should be dynamic: - Earn/Claim values are set to 0 - BonusAvailable/Expiry dates use hardcoded "9999999999999" - PendingRewards contains a hardcoded reward Consider: 1. Calculate Earn/Claim values based on user progress 2. Use actual dates for BonusAvailable/Expiry 3. Load PendingRewards from a configuration source ```diff res.json({ NewProgress: { Category: payload.Category, - Earn: 0, - Claim: 0, + Earn: calculateEarnValue(inventory, payload.Category), + Claim: calculateClaimValue(inventory, payload.Category), BonusAvailable: { $date: { - $numberLong: "9999999999999" + $numberLong: calculateBonusDate().toString() } }, Expiry: { $date: { - $numberLong: "9999999999999" + $numberLong: calculateExpiryDate().toString() } }, Choices: payload.Choices, - PendingRewards: [ - { - RequiredTotalXp: 190, - Rewards: [ - { - StoreItem: "/Lotus/StoreItems/Upgrades/Mods/Aura/PlayerHealthAuraMod", - ItemCount: 1 - } - ] - } - ] + PendingRewards: await loadPendingRewards(payload.Category) } }); ``` > Committable suggestion skipped: line range outside the PR's diff. <!-- This is an auto-generated comment by CodeRabbit -->
};
interface IEndlessXpRequest {
Mode: string; // "r"
Category: TEndlessXpCategory;
Choices: string[];
}

View File

@ -37,7 +37,8 @@ import {
IPeriodicMissionCompletionDatabase,
IPeriodicMissionCompletionResponse,
ILoreFragmentScan,
IEvolutionProgress
IEvolutionProgress,
IEndlessXpProgress
} from "../../types/inventoryTypes/inventoryTypes";
import { IOid } from "../../types/commonTypes";
import {
@ -581,6 +582,14 @@ const evolutionProgressSchema = new Schema<IEvolutionProgress>(
{ _id: false }
);
const endlessXpProgressSchema = new Schema<IEndlessXpProgress>(
{
Category: String,
Choices: [String]
},
{ _id: false }
);
const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
{
accountOwnerId: Schema.Types.ObjectId,
@ -938,7 +947,9 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
//Zanuka
Harvestable: Boolean,
//Grustag three
DeathSquadable: Boolean
DeathSquadable: Boolean,
EndlessXP: { type: [endlessXpProgressSchema], default: undefined }
},
{ timestamps: { createdAt: "Created" } }
);

View File

@ -8,6 +8,7 @@ import { createGuildController } from "@/src/controllers/api/createGuildControll
import { deleteSessionController } from "@/src/controllers/api/deleteSessionController";
import { dojoController } from "@/src/controllers/api/dojoController";
import { dronesController } from "@/src/controllers/api/dronesController";
import { endlessXpController } from "@/src/controllers/api/endlessXpController";
import { evolveWeaponController } from "@/src/controllers/api/evolveWeaponController";
import { findSessionsController } from "@/src/controllers/api/findSessionsController";
import { focusController } from "@/src/controllers/api/focusController";
@ -108,6 +109,7 @@ apiRouter.post("/arcaneCommon.php", arcaneCommonController);
apiRouter.post("/artifacts.php", artifactsController);
apiRouter.post("/claimCompletedRecipe.php", claimCompletedRecipeController);
apiRouter.post("/createGuild.php", createGuildController);
apiRouter.post("/endlessXp.php", endlessXpController);
apiRouter.post("/evolveWeapon.php", evolveWeaponController);
apiRouter.post("/findSessions.php", findSessionsController);
apiRouter.post("/focus.php", focusController);

View File

@ -301,6 +301,7 @@ export interface IInventoryResponse {
PendingCoupon: IPendingCoupon;
Harvestable: boolean;
DeathSquadable: boolean;
EndlessXP?: IEndlessXpProgress[];
}
export interface IAffiliation {
@ -932,3 +933,10 @@ export interface IEvolutionProgress {
Rank: number;
ItemType: string;
}
export type TEndlessXpCategory = "EXC_NORMAL" | "EXC_HARD";
export interface IEndlessXpProgress {
Category: TEndlessXpCategory;
Choices: string[];
}