diff --git a/src/lib/types.ts b/src/lib/types.ts index 731b1d8..d25cb88 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -15,8 +15,8 @@ export interface Event { export type ItemEffect = | { type: 'ADD_XP'; amount: number } | { type: 'ADD_BALANCE'; amount: number } - | { type: 'XP_BOOST'; multiplier: number; durationSeconds: number } - | { type: 'TEMP_ROLE'; roleId: string; durationSeconds: number } + | { type: 'XP_BOOST'; multiplier: number; durationSeconds?: number; durationMinutes?: number; durationHours?: number } + | { type: 'TEMP_ROLE'; roleId: string; durationSeconds?: number; durationMinutes?: number; durationHours?: number } | { type: 'REPLY_MESSAGE'; message: string }; export interface ItemUsageData { diff --git a/src/modules/inventory/inventory.service.ts b/src/modules/inventory/inventory.service.ts index ebba8e3..0ed5a22 100644 --- a/src/modules/inventory/inventory.service.ts +++ b/src/modules/inventory/inventory.service.ts @@ -7,6 +7,13 @@ import { config } from "@/lib/config"; import { withTransaction } from "@/lib/db"; import type { Transaction, ItemUsageData } from "@/lib/types"; +// Helper to extract duration in seconds +const getDuration = (effect: any): number => { + if (effect.durationHours) return effect.durationHours * 3600; + if (effect.durationMinutes) return effect.durationMinutes * 60; + return effect.durationSeconds || 60; // Default to 60s if nothing provided +}; + export const inventoryService = { addItem: async (userId: string, itemId: number, quantity: bigint = 1n, tx?: Transaction) => { return await withTransaction(async (txFn) => { @@ -171,7 +178,8 @@ export const inventoryService = { results.push(effect.message); break; case 'XP_BOOST': - const expiresAt = new Date(Date.now() + effect.durationSeconds * 1000); + const boostDuration = getDuration(effect); + const expiresAt = new Date(Date.now() + boostDuration * 1000); await txFn.insert(userTimers).values({ userId: BigInt(userId), type: 'EFFECT', @@ -182,10 +190,11 @@ export const inventoryService = { target: [userTimers.userId, userTimers.type, userTimers.key], set: { expiresAt: expiresAt, metadata: { multiplier: effect.multiplier } } }); - results.push(`XP Boost (${effect.multiplier}x) active for ${Math.floor(effect.durationSeconds / 60)}m`); + results.push(`XP Boost (${effect.multiplier}x) active for ${Math.floor(boostDuration / 60)}m`); break; case 'TEMP_ROLE': - const roleExpiresAt = new Date(Date.now() + effect.durationSeconds * 1000); + const roleDuration = getDuration(effect); + const roleExpiresAt = new Date(Date.now() + roleDuration * 1000); await txFn.insert(userTimers).values({ userId: BigInt(userId), type: 'ACCESS', @@ -196,9 +205,8 @@ export const inventoryService = { target: [userTimers.userId, userTimers.type, userTimers.key], set: { expiresAt: roleExpiresAt } }); - // Actual role assignment happens in the Command layer (or here if we had client, but service shouldn't depend on client ideally) - // We return a flag to let the interaction handler know it needs to assign a role. - results.push(`Temporary Role granted for ${Math.floor(effect.durationSeconds / 60)}m`); + // Actual role assignment happens in the Command layer + results.push(`Temporary Role granted for ${Math.floor(roleDuration / 60)}m`); break; } }