From 10282a25706fd63b4c10b4e50c8ee33e0a036fcd Mon Sep 17 00:00:00 2001 From: syntaxbullet Date: Tue, 23 Dec 2025 21:56:45 +0100 Subject: [PATCH] feat: Add admin command to create color roles and corresponding shop items. --- src/commands/admin/create_color.ts | 94 ++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 src/commands/admin/create_color.ts diff --git a/src/commands/admin/create_color.ts b/src/commands/admin/create_color.ts new file mode 100644 index 0000000..71b743d --- /dev/null +++ b/src/commands/admin/create_color.ts @@ -0,0 +1,94 @@ +import { createCommand } from "@/lib/utils"; +import { SlashCommandBuilder, PermissionFlagsBits, AttachmentBuilder } from "discord.js"; +import { config, saveConfig } from "@/lib/config"; +import { DrizzleClient } from "@/lib/DrizzleClient"; +import { items } from "@/db/schema"; +import { createSuccessEmbed, createErrorEmbed } from "@lib/embeds"; + +export const createColor = createCommand({ + data: new SlashCommandBuilder() + .setName("createcolor") + .setDescription("Create a new Color Role and corresponding Item") + .addStringOption(option => + option.setName("name") + .setDescription("The name of the role and item") + .setRequired(true) + ) + .addStringOption(option => + option.setName("color") + .setDescription("The hex color code (e.g. #FF0000)") + .setRequired(true) + ) + .addNumberOption(option => + option.setName("price") + .setDescription("Price of the item (Default: 500)") + .setRequired(false) + ) + .addStringOption(option => + option.setName("image") + .setDescription("Image URL for the item") + .setRequired(false) + ) + .setDefaultMemberPermissions(PermissionFlagsBits.Administrator), + execute: async (interaction) => { + await interaction.deferReply(); + + const name = interaction.options.getString("name", true); + const colorInput = interaction.options.getString("color", true); + const price = interaction.options.getNumber("price") || 500; + const imageUrl = interaction.options.getString("image") || "https://cdn.discordapp.com/attachments/1450061247365124199/1453122950822760559/Main_Chip_1.png"; + + // 1. Validate Color + const colorRegex = /^#([0-9A-F]{3}){1,2}$/i; + if (!colorRegex.test(colorInput)) { + await interaction.editReply({ embeds: [createErrorEmbed("Invalid Hex Color code. Format: #RRGGBB")] }); + return; + } + + try { + // 2. Create Role + const role = await interaction.guild?.roles.create({ + name: name, + color: colorInput as any, // Discord.js types are a bit strict on ColorResolvable, but string generally works or needs parsing + reason: `Created via /createcolor by ${interaction.user.tag}` + }); + + if (!role) { + throw new Error("Failed to create role."); + } + + // 3. Update Config + if (!config.colorRoles.includes(role.id)) { + config.colorRoles.push(role.id); + saveConfig(config); + } + + // 4. Create Item + await DrizzleClient.insert(items).values({ + name: `Color Role - ${name}`, + description: `Use this item to apply the ${name} color to your name.`, + type: "CONSUMABLE", + rarity: "Common", + price: BigInt(price), + iconUrl: "", + imageUrl: imageUrl, + usageData: { + consume: false, + effects: [{ type: "COLOR_ROLE", roleId: role.id }] + } as any + }); + + // 5. Success + await interaction.editReply({ + embeds: [createSuccessEmbed( + `**Role:** <@&${role.id}> (${colorInput})\n**Item:** Color Role - ${name}\n**Price:** ${price} 🪙`, + "✅ Color Role & Item Created" + )] + }); + + } catch (error: any) { + console.error("Error in createcolor:", error); + await interaction.editReply({ embeds: [createErrorEmbed(`Failed to create color role: ${error.message}`)] }); + } + } +});