apps/bot/src/feats/tickets/lib/config.ts (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
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<string, ConfigOption>;
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"],
});
}
|