fixed settings commands, todo's
diff --git a/src/commands/settings/moderation.ts b/src/commands/settings/moderation.ts
new file mode 100644
index 0000000..ffd3063
--- /dev/null
+++ b/src/commands/settings/moderation.ts
@@ -0,0 +1,189 @@
+import { LoadingEmbed } from "../../utils/defaults.js";
+import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle, ButtonComponent, TextInputBuilder, Message, RoleSelectMenuBuilder } from "discord.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import getEmojiByName from "../../utils/getEmojiByName.js";
+import type { SlashCommandSubcommandBuilder } from "discord.js";
+import client from "../../utils/client.js";
+import { modalInteractionCollector } from "../../utils/dualCollector.js";
+
+const command = (builder: SlashCommandSubcommandBuilder) =>
+ builder
+ .setName("moderation")
+ .setDescription("Links and text shown to a user after a moderator action is performed")
+
+const callback = async (interaction: CommandInteraction): Promise<void> => {
+ await interaction.reply({
+ embeds: LoadingEmbed,
+ ephemeral: true,
+ fetchReply: true
+ });
+ let m: Message;
+ let timedOut = false;
+ while (!timedOut) {
+ const config = await client.database.guilds.read(interaction.guild!.id);
+ const moderation = config.moderation;
+ m = await interaction.editReply({
+ embeds: [
+ new EmojiEmbed()
+ .setTitle("Moderation Commands")
+ .setEmoji("PUNISH.BAN.GREEN")
+ .setStatus("Success")
+ .setDescription(
+ "These links are shown below the message sent in a user's DM when they are punished.\n\n" +
+ "**Mute Role:** " + (moderation.mute.role ? `<@&${moderation.mute.role}>` : "*None set*")
+ )
+ ],
+ components: [
+ new ActionRowBuilder<ButtonBuilder>().addComponents([
+ new ButtonBuilder()
+ .setLabel("Warn")
+ .setEmoji(getEmojiByName("PUNISH.WARN.YELLOW", "id"))
+ .setCustomId("warn")
+ .setStyle(ButtonStyle.Secondary),
+ new ButtonBuilder()
+ .setLabel("Mute")
+ .setEmoji(getEmojiByName("PUNISH.MUTE.YELLOW", "id"))
+ .setCustomId("mute")
+ .setStyle(ButtonStyle.Secondary),
+ new ButtonBuilder()
+ .setLabel("Nickname")
+ .setEmoji(getEmojiByName("PUNISH.NICKNAME.GREEN", "id"))
+ .setCustomId("nickname")
+ .setStyle(ButtonStyle.Secondary)
+ ]),
+ new ActionRowBuilder<ButtonBuilder>().addComponents([
+ new ButtonBuilder()
+ .setLabel("Kick")
+ .setEmoji(getEmojiByName("PUNISH.KICK.RED", "id"))
+ .setCustomId("kick")
+ .setStyle(ButtonStyle.Secondary),
+ new ButtonBuilder()
+ .setLabel("Softban")
+ .setEmoji(getEmojiByName("PUNISH.BAN.YELLOW", "id"))
+ .setCustomId("softban")
+ .setStyle(ButtonStyle.Secondary),
+ new ButtonBuilder()
+ .setLabel("Ban")
+ .setEmoji(getEmojiByName("PUNISH.BAN.RED", "id"))
+ .setCustomId("ban")
+ .setStyle(ButtonStyle.Secondary)
+ ]),
+ new ActionRowBuilder<ButtonBuilder>().addComponents([
+ new ButtonBuilder()
+ .setCustomId("timeout")
+ .setLabel("Mute timeout " + (moderation.mute.timeout ? "Enabled" : "Disabled"))
+ .setStyle(moderation.mute.timeout ? ButtonStyle.Success : ButtonStyle.Danger)
+ .setEmoji(getEmojiByName("CONTROL." + (moderation.mute.timeout ? "TICK" : "CROSS"), "id"))
+ ]),
+ new ActionRowBuilder<RoleSelectMenuBuilder>().addComponents(
+ new RoleSelectMenuBuilder()
+ .setCustomId("muteRole")
+ .setPlaceholder("Select a new mute role")
+ )
+ ]
+ });
+ let i;
+ try {
+ i = await m.awaitMessageComponent({
+ time: 300000,
+ filter: (i) => { return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id && i.message.id === m.id }
+ });
+ } catch (e) {
+ timedOut = true;
+ continue;
+ }
+ type modIDs = "mute" | "kick" | "ban" | "softban" | "warn" | "role";
+ let chosen = moderation[i.customId as modIDs];
+ if (i.isRoleSelectMenu()) {
+ await i.deferUpdate();
+ await client.database.guilds.write(interaction.guild!.id, {
+ "moderation.mute.role": i.values[0]!
+ });
+ continue;
+ } else if ((i.component as ButtonComponent).customId === "timeout") {
+ await i.deferUpdate();
+ await client.database.guilds.write(interaction.guild!.id, {
+ "moderation.mute.timeout": !moderation.mute.timeout
+ });
+ continue;
+ } else if (i.customId) {
+ await i.showModal(
+ new Discord.ModalBuilder()
+ .setCustomId("modal")
+ .setTitle(`Options for ${i.customId}`)
+ .addComponents(
+ new ActionRowBuilder<TextInputBuilder>().addComponents(
+ new TextInputBuilder()
+ .setCustomId("name")
+ .setLabel("Button text")
+ .setMaxLength(100)
+ .setRequired(false)
+ .setStyle(Discord.TextInputStyle.Short)
+ .setValue(chosen.text ?? "")
+ ).toJSON(),
+ new ActionRowBuilder<TextInputBuilder>().addComponents(
+ new TextInputBuilder()
+ .setCustomId("url")
+ .setLabel("URL - Type {id} to insert the user's ID")
+ .setMaxLength(2000)
+ .setRequired(false)
+ .setStyle(Discord.TextInputStyle.Short)
+ .setValue(chosen.link ?? "")
+ ).toJSON()
+ )
+ );
+ await interaction.editReply({
+ embeds: [
+ new EmojiEmbed()
+ .setTitle("Moderation Links")
+ .setDescription("Modal opened. If you can't see it, click back and try again.")
+ .setStatus("Success")
+ .setEmoji("GUILD.TICKET.OPEN")
+ ],
+ components: [
+ new ActionRowBuilder<ButtonBuilder>().addComponents([
+ new ButtonBuilder()
+ .setLabel("Back")
+ .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
+ .setStyle(ButtonStyle.Primary)
+ .setCustomId("back")
+ ])
+ ]
+ });
+ let out: Discord.ModalSubmitInteraction | null;
+ try {
+ out = await modalInteractionCollector(
+ m,
+ (m) => m.channel!.id === interaction.channel!.id,
+ (_) => true
+ ) as Discord.ModalSubmitInteraction | null;
+ } catch (e) {
+ continue;
+ }
+ if (!out || out.isButton()) continue
+ const buttonText = out.fields.getTextInputValue("name");
+ const buttonLink = out.fields.getTextInputValue("url").replace(/{id}/gi, "{id}");
+ const current = chosen;
+ if (current.text !== buttonText || current.link !== buttonLink) {
+ chosen = { text: buttonText, link: buttonLink };
+ await client.database.guilds.write(interaction.guild!.id, {
+ ["moderation." + i.customId]: {
+ text: buttonText,
+ link: buttonLink
+ }
+ });
+ }
+ }
+ }
+};
+
+const check = (interaction: CommandInteraction, _partial: boolean = false) => {
+ const member = interaction.member as Discord.GuildMember;
+ if (!member.permissions.has("ManageGuild"))
+ return "You must have the *Manage Server* permission to use this command";
+ return true;
+};
+
+export { command };
+export { callback };
+export { check };