feat: Introduced an admin listing command and shop interaction module, replacing the sell command, and added a type-checking script.

This commit is contained in:
syntaxbullet
2025-12-15 22:52:26 +01:00
parent 727b63b4dc
commit 1d4263e178
5 changed files with 122 additions and 125 deletions

View File

@@ -0,0 +1,77 @@
import { createCommand } from "@/lib/utils";
import {
SlashCommandBuilder,
EmbedBuilder,
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
type BaseGuildTextChannel,
PermissionFlagsBits,
MessageFlags
} from "discord.js";
import { inventoryService } from "@/modules/inventory/inventory.service";
import { createErrorEmbed, createWarningEmbed } from "@lib/embeds";
export const listing = createCommand({
data: new SlashCommandBuilder()
.setName("listing")
.setDescription("Post an item listing in the channel for users to buy")
.addNumberOption(option =>
option.setName("itemid")
.setDescription("The ID of the item to list")
.setRequired(true)
)
.addChannelOption(option =>
option.setName("channel")
.setDescription("The channel to post the listing in (defaults to current)")
.setRequired(false)
)
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator),
execute: async (interaction) => {
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
const itemId = interaction.options.getNumber("itemid", true);
const targetChannel = (interaction.options.getChannel("channel") as BaseGuildTextChannel) || interaction.channel as BaseGuildTextChannel;
if (!targetChannel || !targetChannel.isSendable()) {
await interaction.editReply({ content: "", embeds: [createErrorEmbed("Target channel is invalid or not sendable.")] });
return;
}
const item = await inventoryService.getItem(itemId);
if (!item) {
await interaction.editReply({ content: "", embeds: [createErrorEmbed(`Item with ID ${itemId} not found.`)] });
return;
}
if (!item.price) {
await interaction.editReply({ content: "", embeds: [createWarningEmbed(`Item "${item.name}" is not for sale (no price set).`)] });
return;
}
const embed = new EmbedBuilder()
.setTitle(`Shop: ${item.name}`)
.setDescription(item.description || "No description available.")
.addFields({ name: "Price", value: `${item.price} 🪙`, inline: true })
.setColor("Green")
.setThumbnail(item.iconUrl || null)
.setImage(item.imageUrl || null)
.setFooter({ text: "Click the button below to purchase instantly." });
const buyButton = new ButtonBuilder()
.setCustomId(`shop_buy_${item.id}`)
.setLabel(`Buy for ${item.price} 🪙`)
.setStyle(ButtonStyle.Success)
.setEmoji("🛒");
const actionRow = new ActionRowBuilder<ButtonBuilder>().addComponents(buyButton);
try {
await targetChannel.send({ embeds: [embed], components: [actionRow] });
await interaction.editReply({ content: `✅ Listing for **${item.name}** posted in ${targetChannel}.` });
} catch (error) {
console.error("Failed to send listing message:", error);
await interaction.editReply({ content: "", embeds: [createErrorEmbed("Failed to post the listing.")] });
}
}
});