import type { Subcommand } from "@sapphire/plugin-subcommands"; import db, { eq, getGuildByDiscordId, guilds } from "@stealth-developers/db"; import { LabelBuilder, ModalBuilder, TextInputBuilder, TextInputStyle } from "discord.js"; import { errorMessage } from "@/lib"; import { configTextModal } from "../modals"; type GuildKeys = keyof typeof guilds.$inferSelect; type ConfigOptionBase = { key: GuildKeys; type: "channel" | "category" | "text"; }; type ChannelConfigOption = ConfigOptionBase & { type: "channel" }; type CategoryConfigOption = ConfigOptionBase & { type: "category" }; type TextConfigOption = ConfigOptionBase & { type: "text"; title: string; description: string }; type ConfigOption = ChannelConfigOption | CategoryConfigOption | TextConfigOption; const configOptions = { category: { type: "category", key: "ticketCategory" }, "transcript-channel": { type: "channel", key: "ticketLogChannel" }, "entrypoint-channel": { type: "channel", key: "ticketPromptChannel" }, prompt: { type: "text", key: "ticketPrompt", title: "Ticket Prompt", description: "Set the message sent in the entry point channel", }, greeting: { type: "text", key: "ticketGreeting", title: "Ticket Greeting", description: "Set the message sent in new tickets", }, } satisfies Record; type ConfigSubcommand = keyof typeof configOptions; export async function manageConfig(interaction: Subcommand.ChatInputCommandInteraction) { if (!interaction.inGuild()) return errorMessage(interaction, "This command can only be used in a server."); const sub = interaction.options.getSubcommand(true); const guild = await getGuildByDiscordId(interaction.guildId); if (!guild) return errorMessage(interaction, "Failed to update configuration: Guild not found."); if (!(sub in configOptions)) return errorMessage(interaction, "Invalid subcommand."); const subcommand = sub as ConfigSubcommand; const option = configOptions[subcommand]; if (!option) return errorMessage(interaction, "Invalid configuration option."); if (option.type === "text") { const targetKey = option.key; const customId = configTextModal.id({ key: targetKey }); const currentValue = guild[targetKey] ?? ""; const modal = new ModalBuilder().setCustomId(customId).setTitle(option.title); modal.addLabelComponents( new LabelBuilder() .setLabel(option.title) .setDescription(option.description) .setTextInputComponent( new TextInputBuilder() .setCustomId("text-value") .setStyle(TextInputStyle.Paragraph) .setValue(currentValue) .setRequired(true), ), ); return interaction.showModal(modal, { withResponse: true }); } const channel = interaction.options.getChannel("channel", option.type === "channel"); const category = interaction.options.getChannel("category", option.type === "category"); const [res] = await db .update(guilds) .set({ [option.key]: option.type === "channel" ? channel?.id : category?.id, }) .where(eq(guilds.id, guild.id)) .returning(); if (!res) return errorMessage(interaction, "Failed to update configuration."); return interaction.reply({ content: "Configuration updated successfully!", flags: ["Ephemeral"], }); }