88 lines
3.5 KiB
TypeScript
88 lines
3.5 KiB
TypeScript
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";
|
|
|
|
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) {
|
|
await interaction.editReply({ embeds: [createErrorEmbed(error.message)] });
|
|
}
|
|
},
|
|
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 }))
|
|
);
|
|
}
|
|
});
|