typing again
diff --git a/src/actions/createModActionTicket.ts b/src/actions/createModActionTicket.ts
index 0eca621..365c5e3 100644
--- a/src/actions/createModActionTicket.ts
+++ b/src/actions/createModActionTicket.ts
@@ -7,7 +7,7 @@
     guild: Discord.Guild,
     member: Discord.User,
     createdBy: Discord.User,
-    reason: string,
+    reason: string | null,
     customReason?: string
 ) {
     const config = await client.database.guilds.read(guild.id);
@@ -26,7 +26,7 @@
     });
     if (config.tickets.supportRole !== null) {
         overwrites.push({
-            id: guild.roles.cache.get(config.tickets.supportRole),
+            id: guild.roles.cache.get(config.tickets.supportRole)!,
             allow: ["VIEW_CHANNEL", "SEND_MESSAGES", "ATTACH_FILES", "ADD_REACTIONS", "READ_MESSAGE_HISTORY"],
             type: "role"
         });
diff --git a/src/commands/mod/ban.ts b/src/commands/mod/ban.ts
index 9a82970..3aea8c8 100644
--- a/src/commands/mod/ban.ts
+++ b/src/commands/mod/ban.ts
@@ -1,4 +1,4 @@
-import { CommandInteraction, GuildMember, MessageActionRow, MessageButton } from "discord.js";
+import { CommandInteraction, GuildMember, MessageActionRow, MessageButton, User } from "discord.js";
 import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import confirmationMessage from "../../utils/confirmationMessage.js";
 import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
@@ -26,143 +26,171 @@
     let reason = null;
     let notify = true;
     let confirmation;
-    let cancelled = false;
+    let chosen = false;
     let timedOut = false;
-    while (!timedOut && !cancelled) {
+    do {
         confirmation = await new confirmationMessage(interaction)
             .setEmoji("PUNISH.BAN.RED")
             .setTitle("Ban")
             .setDescription(
                 keyValueList({
                     user: renderUser(interaction.options.getUser("user")),
-                    reason: reason ? "\n> " + (reason ?? "").replaceAll("\n", "\n> ") : "*No reason provided*"
+                    reason: reason ? "\n> " + (reason).replaceAll("\n", "\n> ") : "*No reason provided*"
                 }) +
                     `The user **will${notify ? "" : " not"}** be notified\n` +
                     `${addPlurals(
-                        interaction.options.getInteger("delete") ? interaction.options.getInteger("delete") : 0,
+                        interaction.options.getNumber("delete") ?? 0,
                         "day"
                     )} of messages will be deleted\n\n` +
                     `Are you sure you want to ban <@!${(interaction.options.getMember("user") as GuildMember).id}>?`
             )
+            .addCustomBoolean(
+                "notify",
+                "Notify user",
+                false,
+                undefined,
+                null,
+                "ICONS.NOTIFY." + (notify ? "ON" : "OFF"),
+                notify
+            )
             .setColor("Danger")
             .addReasonButton(reason ?? "")
             .send(reason !== null);
         reason = reason ?? "";
         if (confirmation.cancelled) timedOut = true;
-        else if (confirmation.success) cancelled = true;
+        else if (confirmation.success !== undefined) chosen = true;
         else if (confirmation.newReason) reason = confirmation.newReason;
-        else if (confirmation.components) notify = confirmation.components.notify.active;
-    }
+        else if (confirmation.components) notify = confirmation.components["notify"]!.active;
+    } while (!timedOut && !chosen)
     if (timedOut) return;
-    let dmd = false;
-    let dm;
-    const config = await client.database.guilds.read(interaction.guild.id);
-    try {
-        if (notify) {
-            dm = await (interaction.options.getMember("user") as GuildMember).send({
+    if (confirmation.success) {
+        reason = reason.length ? reason : null
+        let dmd = false;
+        let dm;
+        const config = await client.database.guilds.read(interaction.guild!.id);
+        try {
+            if (notify) {
+                dm = await (interaction.options.getMember("user") as GuildMember).send({
+                    embeds: [
+                        new EmojiEmbed()
+                            .setEmoji("PUNISH.BAN.RED")
+                            .setTitle("Banned")
+                            .setDescription(
+                                `You have been banned in ${interaction.guild!.name}` + (reason ? ` for:\n> ${reason}` : ".")
+                            )
+                            .setStatus("Danger")
+                    ],
+                    components: [
+                        new MessageActionRow().addComponents(
+                            config.moderation.ban.text
+                                ? [
+                                    new MessageButton()
+                                        .setStyle("LINK")
+                                        .setLabel(config.moderation.ban.text)
+                                        .setURL(config.moderation.ban.link)
+                                ]
+                                : []
+                        )
+                    ]
+                });
+                dmd = true;
+            }
+        } catch {
+            dmd = false;
+        }
+        try {
+            const member = interaction.options.getMember("user") as GuildMember;
+            member.ban({
+                days: Number(interaction.options.getNumber("delete") ?? 0),
+                reason: reason ?? "No reason provided"
+            });
+            await client.database.history.create("ban", interaction.guild!.id, member.user, interaction.user, reason);
+            const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
+            const data = {
+                meta: {
+                    type: "memberBan",
+                    displayName: "Member Banned",
+                    calculateType: "guildMemberPunish",
+                    color: NucleusColors.red,
+                    emoji: "PUNISH.BAN.RED",
+                    timestamp: new Date().getTime()
+                },
+                list: {
+                    memberId: entry(member.user.id, `\`${member.user.id}\``),
+                    name: entry(member.user.id, renderUser(member.user)),
+                    banned: entry(new Date().getTime(), renderDelta(new Date().getTime())),
+                    bannedBy: entry(interaction.user.id, renderUser(interaction.user)),
+                    reason: entry(reason, reason ? `\n> ${reason}` : "*No reason provided.*"),
+                    accountCreated: entry(member.user.createdAt, renderDelta(member.user.createdAt)),
+                    serverMemberCount: interaction.guild!.memberCount
+                },
+                hidden: {
+                    guild: interaction.guild!.id
+                }
+            };
+            log(data);
+        } catch {
+            await interaction.editReply({
                 embeds: [
                     new EmojiEmbed()
                         .setEmoji("PUNISH.BAN.RED")
-                        .setTitle("Banned")
-                        .setDescription(
-                            `You have been banned in ${interaction.guild.name}` + (reason ? ` for:\n> ${reason}` : ".")
-                        )
+                        .setTitle("Ban")
+                        .setDescription("Something went wrong and the user was not banned")
                         .setStatus("Danger")
                 ],
-                components: [
-                    new MessageActionRow().addComponents(
-                        config.moderation.ban.text
-                            ? [
-                                  new MessageButton()
-                                      .setStyle("LINK")
-                                      .setLabel(config.moderation.ban.text)
-                                      .setURL(config.moderation.ban.link)
-                              ]
-                            : []
-                    )
-                ]
+                components: []
             });
-            dmd = true;
+            if (dmd && dm) await dm.delete();
+            return;
         }
-    } catch {
-        dmd = false;
-    }
-    try {
-        const member = interaction.options.getMember("user") as GuildMember;
-        member.ban({
-            days: Number(interaction.options.getNumber("delete") ?? 0),
-            reason: reason ?? "No reason provided"
-        });
-        await client.database.history.create("ban", interaction.guild.id, member.user, interaction.user, reason);
-        const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
-        const data = {
-            meta: {
-                type: "memberBan",
-                displayName: "Member Banned",
-                calculateType: "guildMemberPunish",
-                color: NucleusColors.red,
-                emoji: "PUNISH.BAN.RED",
-                timestamp: new Date().getTime()
-            },
-            list: {
-                memberId: entry(member.user.id, `\`${member.user.id}\``),
-                name: entry(member.user.id, renderUser(member.user)),
-                banned: entry(new Date().getTime(), renderDelta(new Date().getTime())),
-                bannedBy: entry(interaction.user.id, renderUser(interaction.user)),
-                reason: entry(reason, reason ? `\n> ${reason}` : "*No reason provided.*"),
-                accountCreated: entry(member.user.createdAt, renderDelta(member.user.createdAt)),
-                serverMemberCount: interaction.guild.memberCount
-            },
-            hidden: {
-                guild: interaction.guild.id
-            }
-        };
-        log(data);
-    } catch {
+        const failed = !dmd && notify;
         await interaction.editReply({
             embeds: [
                 new EmojiEmbed()
-                    .setEmoji("PUNISH.BAN.RED")
+                    .setEmoji(`PUNISH.BAN.${failed ? "YELLOW" : "GREEN"}`)
                     .setTitle("Ban")
-                    .setDescription("Something went wrong and the user was not banned")
-                    .setStatus("Danger")
+                    .setDescription("The member was banned" + (failed ? ", but could not be notified" : ""))
+                    .setStatus(failed ? "Warning" : "Success")
             ],
             components: []
         });
-        if (dmd) await dm.delete();
-        return;
+    } else {
+        await interaction.editReply({
+            embeds: [
+                new EmojiEmbed()
+                    .setEmoji("PUNISH.BAN.GREEN")
+                    .setTitle("Ban")
+                    .setDescription("No changes were made")
+                    .setStatus("Success")
+            ],
+            components: []
+        });
     }
-    const failed = !dmd && notify;
-    await interaction.editReply({
-        embeds: [
-            new EmojiEmbed()
-                .setEmoji(`PUNISH.BAN.${failed ? "YELLOW" : "GREEN"}`)
-                .setTitle("Ban")
-                .setDescription("The member was banned" + (failed ? ", but could not be notified" : ""))
-                .setStatus(failed ? "Warning" : "Success")
-        ],
-        components: []
-    });
 };
 
-const check = (interaction: CommandInteraction) => {
+const check = async (interaction: CommandInteraction) => {
     const member = interaction.member as GuildMember;
-    const me = interaction.guild.me!;
-    const apply = interaction.options.getMember("user") as GuildMember;
-    if (member === null || me === null || apply === null) throw new Error("That member is not in the server");
-    const memberPos = member.roles ? member.roles.highest.position : 0;
-    const mePos = me.roles ? me.roles.highest.position : 0;
-    const applyPos = apply.roles ? apply.roles.highest.position : 0;
+    const me = interaction.guild!.me!;
+    let apply = interaction.options.getUser("user") as User | GuildMember;
+    const memberPos = member.roles.cache.size > 1 ? member.roles.highest.position : 0;
+    const mePos = me.roles.cache.size > 1 ? me.roles.highest.position : 0;
+    let applyPos = 0
+    try {
+        apply = await interaction.guild!.members.fetch(apply.id) as GuildMember
+        applyPos = apply.roles.cache.size > 1 ? apply.roles.highest.position : 0;
+    } catch {
+        apply = apply as User
+    }
     // Do not allow banning the owner
-    if (member.id === interaction.guild.ownerId) throw new Error("You cannot ban the owner of the server");
+    if (member.id === interaction.guild!.ownerId) throw new Error("You cannot ban the owner of the server");
     // Check if Nucleus can ban the member
     if (!(mePos > applyPos)) throw new Error("I do not have a role higher than that member");
     // Check if Nucleus has permission to ban
     if (!me.permissions.has("BAN_MEMBERS")) throw new Error("I do not have the *Ban Members* permission");
     // Do not allow banning Nucleus
-    if (member.id === interaction.guild.me.id) throw new Error("I cannot ban myself");
+    if (member.id === interaction.guild!.me!.id) throw new Error("I cannot ban myself");
     // Allow the owner to ban anyone
-    if (member.id === interaction.guild.ownerId) return true;
+    if (member.id === interaction.guild!.ownerId) return true;
     // Check if the user has ban_members permission
     if (!member.permissions.has("BAN_MEMBERS")) throw new Error("You do not have the *Ban Members* permission");
     // Check if the user is below on the role list
diff --git a/src/commands/mod/info.ts b/src/commands/mod/info.ts
index da2d540..bc5dd14 100644
--- a/src/commands/mod/info.ts
+++ b/src/commands/mod/info.ts
@@ -8,6 +8,7 @@
     MessageButton,
     MessageComponentInteraction,
     ModalSubmitInteraction,
+    SelectMenuInteraction,
     TextInputComponent
 } from "discord.js";
 import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
@@ -256,7 +257,7 @@
         }
         i.deferUpdate();
         if (i.customId === "filter") {
-            filteredTypes = i.values;
+            filteredTypes = (i as SelectMenuInteraction).values;
             pageIndex = null;
             refresh = true;
         }
diff --git a/src/commands/mod/kick.ts b/src/commands/mod/kick.ts
index ef58067..3ca56a6 100644
--- a/src/commands/mod/kick.ts
+++ b/src/commands/mod/kick.ts
@@ -1,6 +1,7 @@
 import { CommandInteraction, GuildMember, MessageActionRow, MessageButton } from "discord.js";
+// @ts-expect-error
 import humanizeDuration from "humanize-duration";
-import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
+import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import confirmationMessage from "../../utils/confirmationMessage.js";
 import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
@@ -19,15 +20,15 @@
     let notify = true;
     let confirmation;
     let timedOut = false;
-    let success = false;
-    while (!timedOut && !success) {
+    let chosen = false;
+    while (!timedOut && !chosen) {
         confirmation = await new confirmationMessage(interaction)
             .setEmoji("PUNISH.KICK.RED")
             .setTitle("Kick")
             .setDescription(
                 keyValueList({
                     user: renderUser(interaction.options.getUser("user")),
-                    reason: reason ? "\n> " + (reason ?? "").replaceAll("\n", "\n> ") : "*No reason provided*"
+                    reason: reason ? "\n> " + (reason).replaceAll("\n", "\n> ") : "*No reason provided*"
                 }) +
                     `The user **will${notify ? "" : " not"}** be notified\n\n` +
                     `Are you sure you want to kick <@!${(interaction.options.getMember("user") as GuildMember).id}>?`
@@ -37,16 +38,16 @@
             .send(reason !== null);
         reason = reason ?? "";
         if (confirmation.cancelled) timedOut = true;
-        else if (confirmation.success) success = true;
+        else if (confirmation.success !== undefined) chosen = true;
         else if (confirmation.newReason) reason = confirmation.newReason;
         else if (confirmation.components) {
-            notify = confirmation.components.notify.active;
+            notify = confirmation.components["notify"]!.active;
         }
     }
     if (timedOut) return;
     let dmd = false;
     let dm;
-    const config = await client.database.guilds.read(interaction.guild.id);
+    const config = await client.database.guilds.read(interaction.guild!.id);
     try {
         if (notify) {
             dm = await (interaction.options.getMember("user") as GuildMember).send({
@@ -55,7 +56,7 @@
                         .setEmoji("PUNISH.KICK.RED")
                         .setTitle("Kicked")
                         .setDescription(
-                            `You have been kicked in ${interaction.guild.name}` + (reason ? ` for:\n> ${reason}` : ".")
+                            `You have been kicked in ${interaction.guild!.name}` + (reason ? ` for:\n> ${reason}` : ".")
                         )
                         .setStatus("Danger")
                 ],
@@ -80,8 +81,14 @@
     try {
         (interaction.options.getMember("user") as GuildMember).kick(reason ?? "No reason provided.");
         const member = interaction.options.getMember("user") as GuildMember;
-        await client.database.history.create("kick", interaction.guild.id, member.user, interaction.user, reason);
+        await client.database.history.create("kick", interaction.guild!.id, member.user, interaction.user, reason);
         const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
+        const timeInServer = member.joinedTimestamp ? entry(
+            new Date().getTime() - member.joinedTimestamp,
+            humanizeDuration(new Date().getTime() - member.joinedTimestamp, {
+                round: true
+            })
+        ) : entry(null, "*Unknown*")
         const data = {
             meta: {
                 type: "memberKick",
@@ -98,12 +105,7 @@
                 kicked: entry(new Date().getTime(), renderDelta(new Date().getTime())),
                 kickedBy: entry(interaction.user.id, renderUser(interaction.user)),
                 reason: entry(reason, reason ? `\n> ${reason}` : "*No reason provided.*"),
-                timeInServer: entry(
-                    new Date().getTime() - member.joinedTimestamp,
-                    humanizeDuration(new Date().getTime() - member.joinedTimestamp, {
-                        round: true
-                    })
-                ),
+                timeInServer: timeInServer,
                 accountCreated: entry(member.user.createdAt, renderDelta(member.user.createdAt)),
                 serverMemberCount: member.guild.memberCount
             },
@@ -123,7 +125,7 @@
             ],
             components: []
         });
-        if (dmd) await dm.delete();
+        if (dmd && dm) await dm.delete();
         return;
     }
     const failed = !dmd && notify;
@@ -141,22 +143,21 @@
 
 const check = (interaction: CommandInteraction) => {
     const member = interaction.member as GuildMember;
-    const me = interaction.guild.me!;
+    const me = interaction.guild!.me!;
     const apply = interaction.options.getMember("user") as GuildMember;
-    if (member === null || me === null || apply === null) throw new Error("That member is not in the server");
-    const memberPos = member.roles ? member.roles.highest.position : 0;
-    const mePos = me.roles ? me.roles.highest.position : 0;
-    const applyPos = apply.roles ? apply.roles.highest.position : 0;
+    const memberPos = member.roles.cache.size > 1 ? member.roles.highest.position : 0;
+    const mePos = me.roles.cache.size > 1 ? me.roles.highest.position : 0;
+    const applyPos = apply.roles.cache.size > 1 ? apply.roles.highest.position : 0;
     // Do not allow kicking the owner
-    if (member.id === interaction.guild.ownerId) throw new Error("You cannot kick the owner of the server");
+    if (member.id === interaction.guild!.ownerId) throw new Error("You cannot kick the owner of the server");
     // Check if Nucleus can kick the member
     if (!(mePos > applyPos)) throw new Error("I do not have a role higher than that member");
     // Check if Nucleus has permission to kick
     if (!me.permissions.has("KICK_MEMBERS")) throw new Error("I do not have the *Kick Members* permission");
     // Do not allow kicking Nucleus
-    if (member.id === interaction.guild.me.id) throw new Error("I cannot kick myself");
+    if (member.id === interaction.guild!.me!.id) throw new Error("I cannot kick myself");
     // Allow the owner to kick anyone
-    if (member.id === interaction.guild.ownerId) return true;
+    if (member.id === interaction.guild!.ownerId) return true;
     // Check if the user has kick_members permission
     if (!member.permissions.has("KICK_MEMBERS")) throw new Error("You do not have the *Kick Members* permission");
     // Check if the user is below on the role list
diff --git a/src/commands/mod/mute.ts b/src/commands/mod/mute.ts
index 327ecdf..2b01ffc 100644
--- a/src/commands/mod/mute.ts
+++ b/src/commands/mod/mute.ts
@@ -1,10 +1,11 @@
 import { LoadingEmbed } from "./../../utils/defaultEmbeds.js";
 import Discord, { CommandInteraction, GuildMember, Message, MessageActionRow, MessageButton } from "discord.js";
-import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
+import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../../utils/getEmojiByName.js";
 import confirmationMessage from "../../utils/confirmationMessage.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
+// @ts-expect-error
 import humanizeDuration from "humanize-duration";
 import client from "../../utils/client.js";
 import { areTicketsEnabled, create } from "../../actions/createModActionTicket.js";
@@ -56,7 +57,7 @@
         minutes: interaction.options.getInteger("minutes") ?? 0,
         seconds: interaction.options.getInteger("seconds") ?? 0
     };
-    const config = await client.database.guilds.read(interaction.guild.id);
+    const config = await client.database.guilds.read(interaction.guild!.id);
     let serverSettingsDescription = config.moderation.mute.timeout ? "given a timeout" : "";
     if (config.moderation.mute.role)
         serverSettingsDescription +=
@@ -158,13 +159,13 @@
         });
     }
     // TODO:[Modals] Replace this with a modal
-    let reason = null;
+    let reason: string | null = null;
     let notify = true;
     let createAppealTicket = false;
     let confirmation;
     let timedOut = false;
     let success = false;
-    while (!timedOut && !success) {
+    do {
         confirmation = await new confirmationMessage(interaction)
             .setEmoji("PUNISH.MUTE.RED")
             .setTitle("Mute")
@@ -174,7 +175,7 @@
                     time: `${humanizeDuration(muteTime * 1000, {
                         round: true
                     })}`,
-                    reason: reason ? "\n> " + (reason ?? "").replaceAll("\n", "\n> ") : "*No reason provided*"
+                    reason: reason ? "\n> " + (reason).replaceAll("\n", "\n> ") : "*No reason provided*"
                 }) +
                     "The user will be " +
                     serverSettingsDescription +
@@ -186,9 +187,9 @@
             .addCustomBoolean(
                 "appeal",
                 "Create appeal ticket",
-                !(await areTicketsEnabled(interaction.guild.id)),
+                !(await areTicketsEnabled(interaction.guild!.id)),
                 async () =>
-                    await create(interaction.guild, interaction.options.getUser("user"), interaction.user, reason),
+                    await create(interaction.guild!, interaction.options.getUser("user")!, interaction.user, reason),
                 "An appeal ticket will be created when Confirm is clicked",
                 "CONTROL.TICKET",
                 createAppealTicket
@@ -197,7 +198,7 @@
                 "notify",
                 "Notify user",
                 false,
-                null,
+                undefined,
                 null,
                 "ICONS.NOTIFY." + (notify ? "ON" : "OFF"),
                 notify
@@ -209,154 +210,165 @@
         if (confirmation.success) success = true;
         if (confirmation.newReason) reason = confirmation.newReason;
         if (confirmation.components) {
-            notify = confirmation.components.notify.active;
-            createAppealTicket = confirmation.components.appeal.active;
+            notify = confirmation.components["notify"]!.active;
+            createAppealTicket = confirmation.components["appeal"]!.active;
         }
-    }
+    } while (!timedOut && !success)
     if (timedOut) return;
     let dmd = false;
     let dm;
-    const config = await client.database.guilds.read(interaction.guild.id);
-    try {
-        if (notify) {
-            dm = await user.send({
+    if (confirmation.success) {
+        try {
+            if (notify) {
+                dm = await user.send({
+                    embeds: [
+                        new EmojiEmbed()
+                            .setEmoji("PUNISH.MUTE.RED")
+                            .setTitle("Muted")
+                            .setDescription(
+                                `You have been muted in ${interaction.guild!.name}` +
+                                    (reason
+                                        ? ` for:\n> ${reason}`
+                                        : ".\n\n" +
+                                        `You will be unmuted at: <t:${
+                                            Math.round(new Date().getTime() / 1000) + muteTime
+                                        }:D> at <t:${Math.round(new Date().getTime() / 1000) + muteTime}:T> (<t:${
+                                            Math.round(new Date().getTime() / 1000) + muteTime
+                                        }:R>)`) +
+                                    (confirmation.components!["appeal"]!.response
+                                        ? `You can appeal this here: <#${confirmation.components!["appeal"]!.response}>`
+                                        : "")
+                            )
+                            .setStatus("Danger")
+                    ],
+                    components: [
+                        new MessageActionRow().addComponents(
+                            config.moderation.mute.text
+                                ? [
+                                    new MessageButton()
+                                        .setStyle("LINK")
+                                        .setLabel(config.moderation.mute.text)
+                                        .setURL(config.moderation.mute.link)
+                                ]
+                                : []
+                        )
+                    ]
+                });
+                dmd = true;
+            }
+        } catch {
+            dmd = false;
+        }
+        const member = user;
+        let errors = 0;
+        try {
+            if (config.moderation.mute.timeout) {
+                await member.timeout(muteTime * 1000, reason || "No reason provided");
+                if (config.moderation.mute.role !== null) {
+                    await member.roles.add(config.moderation.mute.role);
+                    await client.database.eventScheduler.schedule("naturalUnmute", new Date().getTime() + muteTime * 1000, {
+                        guild: interaction.guild!.id,
+                        user: user.id,
+                        expires: new Date().getTime() + muteTime * 1000
+                    });
+                }
+            }
+        } catch {
+            errors++;
+        }
+        try {
+            if (config.moderation.mute.role !== null) {
+                await member.roles.add(config.moderation.mute.role);
+                await client.database.eventScheduler.schedule("unmuteRole", new Date().getTime() + muteTime * 1000, {
+                    guild: interaction.guild!.id,
+                    user: user.id,
+                    role: config.moderation.mute.role
+                });
+            }
+        } catch (e) {
+            console.log(e);
+            errors++;
+        }
+        if (errors === 2) {
+            await interaction.editReply({
                 embeds: [
                     new EmojiEmbed()
                         .setEmoji("PUNISH.MUTE.RED")
-                        .setTitle("Muted")
-                        .setDescription(
-                            `You have been muted in ${interaction.guild.name}` +
-                                (reason
-                                    ? ` for:\n> ${reason}`
-                                    : ".\n\n" +
-                                      `You will be unmuted at: <t:${
-                                          Math.round(new Date().getTime() / 1000) + muteTime
-                                      }:D> at <t:${Math.round(new Date().getTime() / 1000) + muteTime}:T> (<t:${
-                                          Math.round(new Date().getTime() / 1000) + muteTime
-                                      }:R>)`) +
-                                (confirmation.components.appeal.response
-                                    ? `You can appeal this here: <#${confirmation.components.appeal.response}>`
-                                    : "")
-                        )
+                        .setTitle("Mute")
+                        .setDescription("Something went wrong and the user was not muted")
                         .setStatus("Danger")
                 ],
-                components: [
-                    new MessageActionRow().addComponents(
-                        config.moderation.mute.text
-                            ? [
-                                  new MessageButton()
-                                      .setStyle("LINK")
-                                      .setLabel(config.moderation.mute.text)
-                                      .setURL(config.moderation.mute.link)
-                              ]
-                            : []
-                    )
-                ]
-            });
-            dmd = true;
+                components: []
+            }); // TODO: make this clearer
+            if (dmd && dm) await dm.delete();
+            return;
         }
-    } catch {
-        dmd = false;
-    }
-    const member = user;
-    let errors = 0;
-    try {
-        if (config.moderation.mute.timeout) {
-            await member.timeout(muteTime * 1000, reason || "No reason provided");
-            if (config.moderation.mute.role !== null) {
-                await member.roles.add(config.moderation.mute.role);
-                await client.database.eventScheduler.schedule("naturalUnmute", new Date().getTime() + muteTime * 1000, {
-                    guild: interaction.guild.id,
-                    user: user.id,
-                    expires: new Date().getTime() + muteTime * 1000
-                });
-            }
-        }
-    } catch {
-        errors++;
-    }
-    try {
-        if (config.moderation.mute.role !== null) {
-            await member.roles.add(config.moderation.mute.role);
-            await client.database.eventScheduler.schedule("unmuteRole", new Date().getTime() + muteTime * 1000, {
-                guild: interaction.guild.id,
-                user: user.id,
-                role: config.moderation.mute.role
-            });
-        }
-    } catch (e) {
-        console.log(e);
-        errors++;
-    }
-    if (errors === 2) {
+        await client.database.history.create("mute", interaction.guild!.id, member.user, interaction.user, reason);
+        const failed = !dmd && notify;
         await interaction.editReply({
             embeds: [
                 new EmojiEmbed()
-                    .setEmoji("PUNISH.MUTE.RED")
+                    .setEmoji(`PUNISH.MUTE.${failed ? "YELLOW" : "GREEN"}`)
                     .setTitle("Mute")
-                    .setDescription("Something went wrong and the user was not muted")
-                    .setStatus("Danger")
+                    .setDescription(
+                        "The member was muted" +
+                            (failed ? ", but could not be notified" : "") +
+                            (confirmation.components!["appeal"]!.response
+                                ? ` and an appeal ticket was opened in <#${confirmation.components!["appeal"]!.response}>`
+                                : "")
+                    )
+                    .setStatus(failed ? "Warning" : "Success")
             ],
             components: []
-        }); // TODO: make this clearer
-        if (dmd) await dm.delete();
-        return;
+        });
+        const data = {
+            meta: {
+                type: "memberMute",
+                displayName: "Member Muted",
+                calculateType: "guildMemberPunish",
+                color: NucleusColors.yellow,
+                emoji: "PUNISH.WARN.YELLOW",
+                timestamp: new Date().getTime()
+            },
+            list: {
+                memberId: entry(member.user.id, `\`${member.user.id}\``),
+                name: entry(member.user.id, renderUser(member.user)),
+                mutedUntil: entry(
+                    new Date().getTime() + muteTime * 1000,
+                    renderDelta(new Date().getTime() + muteTime * 1000)
+                ),
+                muted: entry(new Date().getTime(), renderDelta(new Date().getTime() - 1000)),
+                mutedBy: entry(interaction.member!.user.id, renderUser(interaction.member!.user)),
+                reason: entry(reason, reason ? reason : "*No reason provided*")
+            },
+            hidden: {
+                guild: interaction.guild!.id
+            }
+        };
+        log(data);
+    } else {
+        await interaction.editReply({
+            embeds: [
+                new EmojiEmbed()
+                    .setEmoji("PUNISH.BAN.GREEN")
+                    .setTitle("Softban")
+                    .setDescription("No changes were made")
+                    .setStatus("Success")
+            ],
+            components: []
+        });
     }
-    await client.database.history.create("mute", interaction.guild.id, member.user, interaction.user, reason);
-    const failed = !dmd && notify;
-    await interaction.editReply({
-        embeds: [
-            new EmojiEmbed()
-                .setEmoji(`PUNISH.MUTE.${failed ? "YELLOW" : "GREEN"}`)
-                .setTitle("Mute")
-                .setDescription(
-                    "The member was muted" +
-                        (failed ? ", but could not be notified" : "") +
-                        (confirmation.components.appeal.response
-                            ? ` and an appeal ticket was opened in <#${confirmation.components.appeal.response}>`
-                            : "")
-                )
-                .setStatus(failed ? "Warning" : "Success")
-        ],
-        components: []
-    });
-    const data = {
-        meta: {
-            type: "memberMute",
-            displayName: "Member Muted",
-            calculateType: "guildMemberPunish",
-            color: NucleusColors.yellow,
-            emoji: "PUNISH.WARN.YELLOW",
-            timestamp: new Date().getTime()
-        },
-        list: {
-            memberId: entry(member.user.id, `\`${member.user.id}\``),
-            name: entry(member.user.id, renderUser(member.user)),
-            mutedUntil: entry(
-                new Date().getTime() + muteTime * 1000,
-                renderDelta(new Date().getTime() + muteTime * 1000)
-            ),
-            muted: entry(new Date().getTime(), renderDelta(new Date().getTime() - 1000)),
-            mutedBy: entry(interaction.member.user.id, renderUser(interaction.member.user)),
-            reason: entry(reason, reason ? reason : "*No reason provided*")
-        },
-        hidden: {
-            guild: interaction.guild.id
-        }
-    };
-    log(data);
 };
 
 const check = (interaction: CommandInteraction) => {
     const member = interaction.member as GuildMember;
-    const me = interaction.guild.me!;
+    const me = interaction.guild!.me!;
     const apply = interaction.options.getMember("user") as GuildMember;
-    if (member === null || me === null || apply === null) throw new Error("That member is not in the server");
-    const memberPos = member.roles ? member.roles.highest.position : 0;
-    const mePos = me.roles ? me.roles.highest.position : 0;
-    const applyPos = apply.roles ? apply.roles.highest.position : 0;
+    const memberPos = member.roles.cache.size > 1 ? member.roles.highest.position : 0;
+    const mePos = me.roles.cache.size > 1 ? me.roles.highest.position : 0;
+    const applyPos = apply.roles.cache.size > 1 ? apply.roles.highest.position : 0;
     // Do not allow muting the owner
-    if (member.id === interaction.guild.ownerId) throw new Error("You cannot mute the owner of the server");
+    if (member.id === interaction.guild!.ownerId) throw new Error("You cannot mute the owner of the server");
     // Check if Nucleus can mute the member
     if (!(mePos > applyPos)) throw new Error("I do not have a role higher than that member");
     // Check if Nucleus has permission to mute
@@ -364,7 +376,7 @@
     // Do not allow muting Nucleus
     if (member.id === me.id) throw new Error("I cannot mute myself");
     // Allow the owner to mute anyone
-    if (member.id === interaction.guild.ownerId) return true;
+    if (member.id === interaction.guild!.ownerId) return true;
     // Check if the user has moderate_members permission
     if (!member.permissions.has("MODERATE_MEMBERS"))
         throw new Error("You do not have the *Moderate Members* permission");
diff --git a/src/commands/mod/nick.ts b/src/commands/mod/nick.ts
index ff1db23..9a101e8 100644
--- a/src/commands/mod/nick.ts
+++ b/src/commands/mod/nick.ts
@@ -169,9 +169,9 @@
     const me = interaction.guild.me!;
     const apply = interaction.options.getMember("user") as GuildMember;
     if (member === null || me === null || apply === null) throw new Error("That member is not in the server");
-    const memberPos = member.roles ? member.roles.highest.position : 0;
-    const mePos = me.roles ? me.roles.highest.position : 0;
-    const applyPos = apply.roles ? apply.roles.highest.position : 0;
+    const memberPos = member.roles.cache.size ? member.roles.highest.position : 0;
+    const mePos = me.roles.cache.size ? me.roles.highest.position : 0;
+    const applyPos = apply.roles.cache.size ? apply.roles.highest.position : 0;
     // Do not allow any changing of the owner
     if (member.id === interaction.guild.ownerId) throw new Error("You cannot change the owner's nickname");
     // Check if Nucleus can change the nickname
diff --git a/src/commands/mod/softban.ts b/src/commands/mod/softban.ts
index 463ec16..ba6ed37 100644
--- a/src/commands/mod/softban.ts
+++ b/src/commands/mod/softban.ts
@@ -149,9 +149,9 @@
     const me = interaction.guild.me!;
     const apply = interaction.options.getMember("user") as GuildMember;
     if (member === null || me === null || apply === null) throw new Error("That member is not in the server");
-    const memberPos = member.roles ? member.roles.highest.position : 0;
-    const mePos = me.roles ? me.roles.highest.position : 0;
-    const applyPos = apply.roles ? apply.roles.highest.position : 0;
+    const memberPos = member.roles.cache.size > 1 ? member.roles.highest.position : 0;
+    const mePos = me.roles.cache.size > 1 ? me.roles.highest.position : 0;
+    const applyPos = apply.roles.cache.size > 1 ? apply.roles.highest.position : 0;
     // Do not allow softbanning the owner
     if (member.id === interaction.guild.ownerId) throw new Error("You cannot softban the owner of the server");
     // Check if Nucleus can ban the member
diff --git a/src/commands/mod/unmute.ts b/src/commands/mod/unmute.ts
index fbe6d66..2dd3a2a 100644
--- a/src/commands/mod/unmute.ts
+++ b/src/commands/mod/unmute.ts
@@ -136,9 +136,9 @@
     const me = interaction.guild.me!;
     const apply = interaction.options.getMember("user") as GuildMember;
     if (member === null || me === null || apply === null) throw new Error("That member is not in the server");
-    const memberPos = member.roles ? member.roles.highest.position : 0;
-    const mePos = me.roles ? me.roles.highest.position : 0;
-    const applyPos = apply.roles ? apply.roles.highest.position : 0;
+    const memberPos = member.roles.cache.size > 1 ? member.roles.highest.position : 0;
+    const mePos = me.roles.cache.size > 1 ? me.roles.highest.position : 0;
+    const applyPos = apply.roles.cache.size > 1 ? apply.roles.highest.position : 0;
     // Do not allow unmuting the owner
     if (member.id === interaction.guild.ownerId) throw new Error("You cannot unmute the owner of the server");
     // Check if Nucleus can unmute the member
diff --git a/src/commands/mod/warn.ts b/src/commands/mod/warn.ts
index 50480fa..68c476b 100644
--- a/src/commands/mod/warn.ts
+++ b/src/commands/mod/warn.ts
@@ -21,7 +21,7 @@
     let confirmation;
     let timedOut = false;
     let success = false;
-    while (!timedOut && !success) {
+    do {
         confirmation = await new confirmationMessage(interaction)
             .setEmoji("PUNISH.WARN.RED")
             .setTitle("Warn")
@@ -57,13 +57,13 @@
             .send(reason !== null);
         reason = reason ?? "";
         if (confirmation.cancelled) timedOut = true;
-        else if (confirmation.success) success = true;
+        else if (confirmation.success !== undefined) success = true;
         else if (confirmation.newReason) reason = confirmation.newReason;
         else if (confirmation.components) {
             notify = confirmation.components.notify.active;
             createAppealTicket = confirmation.components.appeal.active;
         }
-    }
+    } while (!timedOut && !success)
     if (timedOut) return;
     if (confirmation.success) {
         let dmd = false;
@@ -294,7 +294,7 @@
     // Do not allow warning bots
     if (member.user.bot) throw new Error("I cannot warn bots");
     // Allow the owner to warn anyone
-    if (member.id === interaction.guild.ownerId) return true;
+    if (member.id === interaction.guild!.ownerId) return true;
     // Check if the user has moderate_members permission
     if (!member.permissions.has("MODERATE_MEMBERS"))
         throw new Error("You do not have the *Moderate Members* permission");
diff --git a/src/commands/settings/commands.ts b/src/commands/settings/commands.ts
index 294c0fd..6345ec3 100644
--- a/src/commands/settings/commands.ts
+++ b/src/commands/settings/commands.ts
@@ -34,16 +34,7 @@
             )
             .setColor("Danger")
             .send(true);
-        if (confirmation.cancelled)
-            return await interaction.editReply({
-                embeds: [
-                    new EmojiEmbed()
-                        .setTitle("Moderation Commands")
-                        .setDescription("No changes were made")
-                        .setStatus("Success")
-                        .setEmoji("GUILD.ROLES.CREATE")
-                ]
-            });
+        if (confirmation.cancelled) return
         if (confirmation.success) {
             await client.database.guilds.write(interaction.guild.id, {
                 ["moderation.mute.role"]: interaction.options.getRole("role").id
diff --git a/src/commands/settings/logs/attachment.ts b/src/commands/settings/logs/attachment.ts
index 843b391..9c9c02e 100644
--- a/src/commands/settings/logs/attachment.ts
+++ b/src/commands/settings/logs/attachment.ts
@@ -54,7 +54,7 @@
             });
         }
         const confirmation = await new confirmationMessage(interaction)
-            .setEmoji("CHANNEL.TEXT.EDIT")
+            .setEmoji("CHANNEL.TEXT.EDIT", "CHANNEL.TEXT.DELETE")
             .setTitle("Attachment Log Channel")
             .setDescription(
                 "This will be the channel all attachments will be sent to.\n\n" +
diff --git a/src/commands/settings/logs/channel.ts b/src/commands/settings/logs/channel.ts
index 206d282..49126d3 100644
--- a/src/commands/settings/logs/channel.ts
+++ b/src/commands/settings/logs/channel.ts
@@ -53,7 +53,7 @@
             });
         }
         const confirmation = await new confirmationMessage(interaction)
-            .setEmoji("CHANNEL.TEXT.EDIT")
+            .setEmoji("CHANNEL.TEXT.EDIT", "CHANNEL.TEXT.DELETE")
             .setTitle("Log Channel")
             .setDescription(`Are you sure you want to set the log channel to <#${channel.id}>?`)
             .setColor("Warning")
diff --git a/src/commands/settings/logs/staff.ts b/src/commands/settings/logs/staff.ts
index c7077cf..023a13e 100644
--- a/src/commands/settings/logs/staff.ts
+++ b/src/commands/settings/logs/staff.ts
@@ -56,7 +56,7 @@
             });
         }
         const confirmation = await new confirmationMessage(interaction)
-            .setEmoji("CHANNEL.TEXT.EDIT")
+            .setEmoji("CHANNEL.TEXT.EDIT", "CHANNEL.TEXT.DELETE")
             .setTitle("Staff Notifications Channel")
             .setDescription(
                 "This will be the channel all notifications, updates, user reports etc. will be sent to.\n\n" +
diff --git a/src/commands/settings/stats.ts b/src/commands/settings/stats.ts
index ab6022e..932605c 100644
--- a/src/commands/settings/stats.ts
+++ b/src/commands/settings/stats.ts
@@ -78,7 +78,7 @@
             newName = newName.toLowerCase().replace(/[\s]/g, "-");
         }
         const confirmation = await new confirmationMessage(interaction)
-            .setEmoji("CHANNEL.TEXT.EDIT")
+            .setEmoji("CHANNEL.TEXT.EDIT", "CHANNEL.TEXT.DELETE")
             .setTitle("Stats Channel")
             .setDescription(
                 `Are you sure you want to set <#${channel.id}> to a stats channel?\n\n*Preview: ${newName.replace(
diff --git a/src/commands/settings/tickets.ts b/src/commands/settings/tickets.ts
index 26fa66e..863c659 100644
--- a/src/commands/settings/tickets.ts
+++ b/src/commands/settings/tickets.ts
@@ -143,7 +143,7 @@
         }
 
         const confirmation = await new confirmationMessage(interaction)
-            .setEmoji("GUILD.TICKET.ARCHIVED")
+            .setEmoji("GUILD.TICKET.ARCHIVED", "GUILD.TICKET.CLOSE")
             .setTitle("Tickets")
             .setDescription(
                 (options.category ? `**Category:** ${options.category.name}\n` : "") +
@@ -151,10 +151,10 @@
                     (options.supportping ? `**Support Ping:** ${options.supportping.name}\n` : "") +
                     (options.enabled !== null
                         ? `**Enabled:** ${
-                              options.enabled
-                                  ? `${getEmojiByName("CONTROL.TICK")} Yes`
-                                  : `${getEmojiByName("CONTROL.CROSS")} No`
-                          }\n`
+                            options.enabled
+                                ? `${getEmojiByName("CONTROL.TICK")} Yes`
+                                : `${getEmojiByName("CONTROL.CROSS")} No`
+                        }\n`
                         : "") +
                     "\nAre you sure you want to apply these settings?"
             )
diff --git a/src/commands/settings/verify.ts b/src/commands/settings/verify.ts
index aa8227f..29beffe 100644
--- a/src/commands/settings/verify.ts
+++ b/src/commands/settings/verify.ts
@@ -62,7 +62,7 @@
             });
         }
         const confirmation = await new confirmationMessage(interaction)
-            .setEmoji("GUILD.ROLES.EDIT")
+            .setEmoji("GUILD.ROLES.EDIT", "GUILD.ROLES.DELETE")
             .setTitle("Verify Role")
             .setDescription(`Are you sure you want to set the verify role to <@&${role.id}>?`)
             .setColor("Warning")
diff --git a/src/commands/settings/welcome.ts b/src/commands/settings/welcome.ts
index 24ccefc..16857ac 100644
--- a/src/commands/settings/welcome.ts
+++ b/src/commands/settings/welcome.ts
@@ -95,7 +95,7 @@
         if (channel) options.channel = renderChannel(channel);
         if (message) options.message = "\n> " + message;
         const confirmation = await new confirmationMessage(interaction)
-            .setEmoji("GUILD.ROLES.EDIT")
+            .setEmoji("GUILD.ROLES.EDIT", "GUILD.ROLES.DELETE")
             .setTitle("Welcome Events")
             .setDescription(generateKeyValueList(options))
             .setColor("Warning")
diff --git a/src/commands/tags/create.ts b/src/commands/tags/create.ts
index 6d34258..b922da3 100644
--- a/src/commands/tags/create.ts
+++ b/src/commands/tags/create.ts
@@ -64,7 +64,7 @@
             ephemeral: true
         });
     const confirmation = await new confirmationMessage(interaction)
-        .setEmoji("PUNISH.NICKNAME.YELLOW")
+        .setEmoji("PUNISH.NICKNAME.YELLOW", "PUNISH.NICKNAME.RED")
         .setTitle("Tag create")
         .setDescription(
             keyValueList({
diff --git a/src/commands/tags/delete.ts b/src/commands/tags/delete.ts
index 69b4757..2fff637 100644
--- a/src/commands/tags/delete.ts
+++ b/src/commands/tags/delete.ts
@@ -27,7 +27,7 @@
             ephemeral: true
         });
     const confirmation = await new confirmationMessage(interaction)
-        .setEmoji("PUNISH.NICKNAME.YELLOW")
+        .setEmoji("PUNISH.NICKNAME.YELLOW", "PUNISH.NICKNAME.RED")
         .setTitle("Tag Delete")
         .setDescription(
             keyValueList({
diff --git a/src/commands/tags/edit.ts b/src/commands/tags/edit.ts
index b5431fd..376abbd 100644
--- a/src/commands/tags/edit.ts
+++ b/src/commands/tags/edit.ts
@@ -79,7 +79,7 @@
             ephemeral: true
         });
     const confirmation = await new confirmationMessage(interaction)
-        .setEmoji("PUNISH.NICKNAME.YELLOW")
+        .setEmoji("PUNISH.NICKNAME.YELLOW", "PUNISH.NICKNAME.RED")
         .setTitle("Tag Edit")
         .setDescription(
             keyValueList({
diff --git a/src/utils/confirmationMessage.ts b/src/utils/confirmationMessage.ts
index 58ab9d4..c805395 100644
--- a/src/utils/confirmationMessage.ts
+++ b/src/utils/confirmationMessage.ts
@@ -26,6 +26,8 @@
     interaction: CommandInteraction;
     title = "";
     emoji = "";
+    redEmoji: string | null = null;
+    timeoutText: string | null = null;
     description = "";
     color: "Danger" | "Warning" | "Success" = "Success";
     customButtons: Record<string, CustomBoolean<unknown>> = {};
@@ -40,12 +42,14 @@
         this.title = title;
         return this;
     }
-    setEmoji(emoji: string) {
+    setEmoji(emoji: string, redEmoji?: string) {
         this.emoji = emoji;
+        if (redEmoji) this.redEmoji = redEmoji; // TODO: go through all confirmation messages and change them to use this, and not do their own edits
         return this;
     }
-    setDescription(description: string) {
+    setDescription(description: string, timedOut?: string) {
         this.description = description;
+        if (timedOut) this.timeoutText = timedOut; // TODO also this
         return this;
     }
     setColor(color: "Danger" | "Warning" | "Success") {
@@ -256,13 +260,29 @@
         }
         const returnValue: Awaited<ReturnType<typeof this.send>> = {};
 
-        if (returnComponents) returnValue.components = this.customButtons;
+        if (returnComponents || success !== undefined) returnValue.components = this.customButtons;
         if (success !== undefined) returnValue.success = success;
-        if (cancelled) returnValue.cancelled = true;
+        if (cancelled) {
+            await this.timeoutError()
+            returnValue.cancelled = true;
+        }
         if (newReason) returnValue.newReason = newReason;
 
         return returnValue;
     }
+
+    async timeoutError(): Promise<void> {
+        await this.interaction.editReply({
+            embeds: [
+                new EmojiEmbed()
+                    .setTitle(this.title)
+                    .setDescription("We closed this message because it was not used for a while.")
+                    .setStatus("Danger")
+                    .setEmoji(this.redEmoji ?? this.emoji)
+            ],
+            components: []
+    })
+    }
 }
 
 export default confirmationMessage;