import { createCommand } from "@/lib/utils"; import { SlashCommandBuilder, EmbedBuilder, MessageFlags } from "discord.js"; import { inventoryService } from "@/modules/inventory/inventory.service"; import { userService } from "@/modules/user/user.service"; import { createErrorEmbed, createSuccessEmbed } from "@lib/embeds"; import { inventory, items } from "@/db/schema"; import { eq, and, like } from "drizzle-orm"; import { DrizzleClient } from "@/lib/DrizzleClient"; import type { ItemUsageData } from "@/lib/types"; import { UserError } from "@/lib/errors"; export const use = createCommand({ data: new SlashCommandBuilder() .setName("use") .setDescription("Use an item from your inventory") .addNumberOption(option => option.setName("item") .setDescription("The item to use") .setRequired(true) .setAutocomplete(true) ), execute: async (interaction) => { await interaction.deferReply(); const itemId = interaction.options.getNumber("item", true); const user = await userService.getOrCreateUser(interaction.user.id, interaction.user.username); try { const result = await inventoryService.useItem(user.id, itemId); const usageData = result.usageData; if (usageData) { for (const effect of usageData.effects) { if (effect.type === 'TEMP_ROLE') { try { const member = await interaction.guild?.members.fetch(user.id); if (member) { await member.roles.add(effect.roleId); } } catch (e) { console.error("Failed to assign role in /use command:", e); result.results.push("⚠️ Failed to assign role (Check bot permissions)"); } } } } const embed = createSuccessEmbed( result.results.map(r => `• ${r}`).join("\n"), `Used ${result.usageData.effects.length > 0 ? 'Item' : 'Item'}` // Generic title, improves below ); embed.setTitle("Item Used!"); await interaction.editReply({ embeds: [embed] }); } catch (error: any) { if (error instanceof UserError) { await interaction.editReply({ embeds: [createErrorEmbed(error.message)] }); } else { console.error("Error using item:", error); await interaction.editReply({ embeds: [createErrorEmbed("An unexpected error occurred while using the item.")] }); } } }, autocomplete: async (interaction) => { const focusedValue = interaction.options.getFocused(); const userId = interaction.user.id; // Fetch owned items that match the search query // We join with items table to filter by name directly in the database const entries = await DrizzleClient.select({ quantity: inventory.quantity, item: items }) .from(inventory) .innerJoin(items, eq(inventory.itemId, items.id)) .where(and( eq(inventory.userId, BigInt(userId)), like(items.name, `%${focusedValue}%`) )) .limit(20); // Fetch up to 20 matching items const filtered = entries.filter(entry => { const usageData = entry.item.usageData as ItemUsageData | null; const isUsable = usageData && usageData.effects && usageData.effects.length > 0; return isUsable; }); await interaction.respond( filtered.map(entry => ({ name: `${entry.item.name} (${entry.quantity})`, value: entry.item.id })) ); } });