Fix a bunch of linter errors
diff --git a/src/commands/user/_meta.ts b/src/commands/user/_meta.ts
index 6c14052..8677d79 100644
--- a/src/commands/user/_meta.ts
+++ b/src/commands/user/_meta.ts
@@ -1,4 +1,4 @@
 const name = "user";
 const description = "Commands for user info";
 
-export { name, description };
\ No newline at end of file
+export { name, description };
diff --git a/src/commands/user/about.ts b/src/commands/user/about.ts
index ede84b3..5f096ae 100644
--- a/src/commands/user/about.ts
+++ b/src/commands/user/about.ts
@@ -1,6 +1,18 @@
 import { LoadingEmbed } from "./../../utils/defaultEmbeds.js";
-import Discord, { CommandInteraction, GuildMember, Message, MessageActionRow, MessageActionRowComponent, MessageButton, MessageComponentInteraction, SelectMenuInteraction } from "discord.js";
-import { SelectMenuOption, SlashCommandSubcommandBuilder } from "@discordjs/builders";
+import Discord, {
+    CommandInteraction,
+    GuildMember,
+    Message,
+    MessageActionRow,
+    MessageActionRowComponent,
+    MessageButton,
+    MessageComponentInteraction,
+    SelectMenuInteraction
+} from "discord.js";
+import {
+    SelectMenuOption,
+    SlashCommandSubcommandBuilder
+} from "@discordjs/builders";
 import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../../utils/getEmojiByName.js";
 import generateKeyValueList from "../../utils/generateKeyValueList.js";
@@ -11,218 +23,320 @@
     builder
         .setName("about")
         .setDescription("Shows info about a user")
-        .addUserOption(option => option.setName("user").setDescription("The user to get info about | Default: Yourself"));
-
+        .addUserOption((option) =>
+            option
+                .setName("user")
+                .setDescription(
+                    "The user to get info about | Default: Yourself"
+                )
+        );
 
 class Embed {
     embed: Discord.MessageEmbed;
     title: string;
     description = "";
     pageId = 0;
-    setEmbed(embed: Discord.MessageEmbed) { this.embed = embed; return this; }
-    setTitle(title: string) { this.title = title; return this; }
-    setDescription(description: string) { this.description = description; return this; }
-    setPageId(pageId: number) { this.pageId = pageId; return this; }
+    setEmbed(embed: Discord.MessageEmbed) {
+        this.embed = embed;
+        return this;
+    }
+    setTitle(title: string) {
+        this.title = title;
+        return this;
+    }
+    setDescription(description: string) {
+        this.description = description;
+        return this;
+    }
+    setPageId(pageId: number) {
+        this.pageId = pageId;
+        return this;
+    }
 }
 
-
 const callback = async (interaction: CommandInteraction): Promise<void> => {
     const { renderUser, renderDelta } = client.logger;
-    const member = (interaction.options.getMember("user") || interaction.member) as Discord.GuildMember;
+    const member = (interaction.options.getMember("user") ||
+        interaction.member) as Discord.GuildMember;
     const flags: string[] = [];
-    if ([
-        "438733159748599813", // Pinea
-        "317731855317336067", // Mini
-        "261900651230003201", // Coded
-        "511655498676699136" // Zan
-    ].includes(member.user.id)) { flags.push("NUCLEUSDEVELOPER"); }
-    if ((await client.guilds.cache.get("684492926528651336")?.members.fetch())?.filter((m: GuildMember) => m.roles.cache.has("760896837866749972"))?.map((m: GuildMember) => m.id).includes(member.user.id)) { flags.push("CLICKSDEVELOPER"); }
-    member.user.flags.toArray().map(flag => {
+    if (
+        [
+            "438733159748599813", // Pinea
+            "317731855317336067", // Mini
+            "261900651230003201", // Coded
+            "511655498676699136" // Zan
+        ].includes(member.user.id)
+    ) {
+        flags.push("NUCLEUSDEVELOPER");
+    }
+    if (
+        (await client.guilds.cache.get("684492926528651336")?.members.fetch())
+            ?.filter((m: GuildMember) =>
+                m.roles.cache.has("760896837866749972")
+            )
+            ?.map((m: GuildMember) => m.id)
+            .includes(member.user.id)
+    ) {
+        flags.push("CLICKSDEVELOPER");
+    }
+    member.user.flags.toArray().map((flag) => {
         flags.push(flag.toString());
     });
-    if (member.user.bot === true) { flags.push("BOT"); }
+    if (member.user.bot) {
+        flags.push("BOT");
+    }
     // Check if they are boosting the server
-    if (member.premiumSince) { flags.push("BOOSTER"); }
+    if (member.premiumSince) {
+        flags.push("BOOSTER");
+    }
     const nameReplacements = {
-        "NUCLEUSDEVELOPER": "**Nucleus Developer**",
-        "CLICKSDEVELOPER": "Clicks Developer",
-        "HOUSE_BRAVERY": "Hypesquad Bravery",
-        "HOUSE_BRILLIANCE": "Hypesquad Brilliance",
-        "HOUSE_BALANCE": "Hypesquad Balance",
-        "HYPESQUAD_EVENTS": "Hypesquad Events",
-        "EARLY_SUPPORTER": "Early Supporter",
-        "BUGHUNTER_LEVEL_1": "Bug Hunter Level 1",
-        "BUGHUNTER_LEVEL_2": "Bug Hunter Level 2",
-        "PARTNERED_SERVER_OWNER": "Partnered Server Owner",
-        "DISCORD_EMPLOYEE": "Discord Staff",
-        "EARLY_VERIFIED_BOT_DEVELOPER": "Verified Bot Developer",
-        "BOT": "Bot",
-        "BOOSTER": "Server Booster"
+        NUCLEUSDEVELOPER: "**Nucleus Developer**",
+        CLICKSDEVELOPER: "Clicks Developer",
+        HOUSE_BRAVERY: "Hypesquad Bravery",
+        HOUSE_BRILLIANCE: "Hypesquad Brilliance",
+        HOUSE_BALANCE: "Hypesquad Balance",
+        HYPESQUAD_EVENTS: "Hypesquad Events",
+        EARLY_SUPPORTER: "Early Supporter",
+        BUGHUNTER_LEVEL_1: "Bug Hunter Level 1",
+        BUGHUNTER_LEVEL_2: "Bug Hunter Level 2",
+        PARTNERED_SERVER_OWNER: "Partnered Server Owner",
+        DISCORD_EMPLOYEE: "Discord Staff",
+        EARLY_VERIFIED_BOT_DEVELOPER: "Verified Bot Developer",
+        BOT: "Bot",
+        BOOSTER: "Server Booster"
     };
     const members = await interaction.guild.members.fetch();
     const membersArray = [...members.values()];
     membersArray.sort((a, b) => a.joinedTimestamp - b.joinedTimestamp);
-    const joinPos = membersArray.findIndex(m => m.id === member.user.id);
+    const joinPos = membersArray.findIndex((m) => m.id === member.user.id);
 
-    const roles = member.roles.cache.filter(r => r.id !== interaction.guild.id).sort();
+    const roles = member.roles.cache
+        .filter((r) => r.id !== interaction.guild.id)
+        .sort();
     let s = "";
     let count = 0;
     let ended = false;
-    roles.map(item => {
+    roles.map((item) => {
         if (ended) return;
         const string = `<@&${item.id}>, `;
-        if(s.length + string.length > 1000) {
+        if (s.length + string.length > 1000) {
             ended = true;
             s += `and ${roles.size - count} more`;
             return;
         }
-        count ++;
+        count++;
         s += string;
     });
-    if(s.length > 0 && !ended) s = s.slice(0, -2);
+    if (s.length > 0 && !ended) s = s.slice(0, -2);
 
     let perms = "";
     const permsArray = {
-        "ADMINISTRATOR": "Administrator",
-        "MANAGE_GUILD": "Manage Server",
-        "MANAGE_ROLES": "Manage Roles",
-        "MANAGE_CHANNELS": "Manage Channels",
-        "KICK_MEMBERS": "Kick Members",
-        "BAN_MEMBERS": "Ban Members",
-        "MODERATE_MEMBERS": "Moderate Members",
-        "MANAGE_NICKNAMES": "Manage Nicknames",
-        "MANAGE_WEBHOOKS": "Manage Webhooks",
-        "MANAGE_MESSAGES": "Manage Messages",
-        "VIEW_AUDIT_LOG": "View Audit Log",
-        "MENTION_EVERYONE": "Mention Everyone"
+        ADMINISTRATOR: "Administrator",
+        MANAGE_GUILD: "Manage Server",
+        MANAGE_ROLES: "Manage Roles",
+        MANAGE_CHANNELS: "Manage Channels",
+        KICK_MEMBERS: "Kick Members",
+        BAN_MEMBERS: "Ban Members",
+        MODERATE_MEMBERS: "Moderate Members",
+        MANAGE_NICKNAMES: "Manage Nicknames",
+        MANAGE_WEBHOOKS: "Manage Webhooks",
+        MANAGE_MESSAGES: "Manage Messages",
+        VIEW_AUDIT_LOG: "View Audit Log",
+        MENTION_EVERYONE: "Mention Everyone"
     };
-    Object.keys(permsArray).map(perm => {
-        const hasPerm = member.permissions.has(perm as Discord.PermissionString);
-        perms += `${getEmojiByName("CONTROL." + (hasPerm ? "TICK" : "CROSS"))} ${permsArray[perm]}\n`;
+    Object.keys(permsArray).map((perm) => {
+        const hasPerm = member.permissions.has(
+            perm as Discord.PermissionString
+        );
+        perms += `${getEmojiByName(
+            "CONTROL." + (hasPerm ? "TICK" : "CROSS")
+        )} ${permsArray[perm]}\n`;
     });
 
     let selectPaneOpen = false;
 
     const embeds = [
         new Embed()
-            .setEmbed(new EmojiEmbed()
-                .setTitle("User Info: General")
-                .setStatus("Success")
-                .setEmoji("MEMBER.JOIN")
-                .setDescription(
-                    flags.map(flag => {
-                        if (nameReplacements[flag]) {
-                            return getEmojiByName(`BADGES.${flag}`) + " " + nameReplacements[flag];
-                        }
-                    }).join("\n") + "\n\n" +
-                    generateKeyValueList({
-                        "member": renderUser(member.user),
-                        "nickname": member.nickname || "*None set*",
-                        "id": `\`${member.id}\``,
-                        "joined the server": renderDelta(member.joinedTimestamp),
-                        "joined discord": renderDelta(member.user.createdTimestamp),
-                        "boost status": member.premiumSince ? `Started boosting ${renderDelta(member.premiumSinceTimestamp)}` : "*Not boosting*",
-                        "join position": `${joinPos + 1}`
-                    })
-                )
-                .setThumbnail(member.user.displayAvatarURL({dynamic: true}))
-                .setImage((await member.user.fetch()).bannerURL({format: "gif"}))
-            ).setTitle("General").setDescription("General information about the user").setPageId(0),
+            .setEmbed(
+                new EmojiEmbed()
+                    .setTitle("User Info: General")
+                    .setStatus("Success")
+                    .setEmoji("MEMBER.JOIN")
+                    .setDescription(
+                        flags
+                            .map((flag) => {
+                                if (nameReplacements[flag]) {
+                                    return (
+                                        getEmojiByName(`BADGES.${flag}`) +
+                                        " " +
+                                        nameReplacements[flag]
+                                    );
+                                }
+                            })
+                            .join("\n") +
+                            "\n\n" +
+                            generateKeyValueList({
+                                member: renderUser(member.user),
+                                nickname: member.nickname || "*None set*",
+                                id: `\`${member.id}\``,
+                                "joined the server": renderDelta(
+                                    member.joinedTimestamp
+                                ),
+                                "joined discord": renderDelta(
+                                    member.user.createdTimestamp
+                                ),
+                                "boost status": member.premiumSince
+                                    ? `Started boosting ${renderDelta(
+                                          member.premiumSinceTimestamp
+                                      )}`
+                                    : "*Not boosting*",
+                                "join position": `${joinPos + 1}`
+                            })
+                    )
+                    .setThumbnail(
+                        member.user.displayAvatarURL({ dynamic: true })
+                    )
+                    .setImage(
+                        (await member.user.fetch()).bannerURL({ format: "gif" })
+                    )
+            )
+            .setTitle("General")
+            .setDescription("General information about the user")
+            .setPageId(0),
         new Embed()
-            .setEmbed(new EmojiEmbed()
-                .setTitle("User Info: Roles")
-                .setStatus("Success")
-                .setEmoji("GUILD.ROLES.CREATE")
-                .setDescription(
-                    generateKeyValueList({
-                        "member": renderUser(member.user),
-                        "id": `\`${member.id}\``,
-                        "roles": `${member.roles.cache.size - 1}`
-                    }) + "\n" +
-                    (s.length > 0 ? s : "*None*") + "\n"
-                )
-                .setThumbnail(member.user.displayAvatarURL({dynamic: true}))
-            ).setTitle("Roles").setDescription("Roles the user has").setPageId(1),
+            .setEmbed(
+                new EmojiEmbed()
+                    .setTitle("User Info: Roles")
+                    .setStatus("Success")
+                    .setEmoji("GUILD.ROLES.CREATE")
+                    .setDescription(
+                        generateKeyValueList({
+                            member: renderUser(member.user),
+                            id: `\`${member.id}\``,
+                            roles: `${member.roles.cache.size - 1}`
+                        }) +
+                            "\n" +
+                            (s.length > 0 ? s : "*None*") +
+                            "\n"
+                    )
+                    .setThumbnail(
+                        member.user.displayAvatarURL({ dynamic: true })
+                    )
+            )
+            .setTitle("Roles")
+            .setDescription("Roles the user has")
+            .setPageId(1),
         new Embed()
-            .setEmbed(new EmojiEmbed()
-                .setTitle("User Info: Key Permissions")
-                .setStatus("Success")
-                .setEmoji("GUILD.ROLES.CREATE")
-                .setDescription(
-                    generateKeyValueList({
-                        "member": renderUser(member.user),
-                        "id": `\`${member.id}\``
-                    }) + "\n" + perms
-                )
-                .setThumbnail(member.user.displayAvatarURL({dynamic: true}))
-            ).setTitle("Key Permissions").setDescription("Key permissions the user has").setPageId(2)
+            .setEmbed(
+                new EmojiEmbed()
+                    .setTitle("User Info: Key Permissions")
+                    .setStatus("Success")
+                    .setEmoji("GUILD.ROLES.CREATE")
+                    .setDescription(
+                        generateKeyValueList({
+                            member: renderUser(member.user),
+                            id: `\`${member.id}\``
+                        }) +
+                            "\n" +
+                            perms
+                    )
+                    .setThumbnail(
+                        member.user.displayAvatarURL({ dynamic: true })
+                    )
+            )
+            .setTitle("Key Permissions")
+            .setDescription("Key permissions the user has")
+            .setPageId(2)
     ];
-    const m = await interaction.reply({embeds: LoadingEmbed, fetchReply: true, ephemeral: true}) as Message;
+    const m = (await interaction.reply({
+        embeds: LoadingEmbed,
+        fetchReply: true,
+        ephemeral: true
+    })) as Message;
     let page = 0;
     let breakReason = "";
     while (true) {
         const em = new Discord.MessageEmbed(embeds[page].embed);
-        em.setDescription(em.description + "\n" + createPageIndicator(embeds.length, page));
+        em.setDescription(
+            em.description + "\n" + createPageIndicator(embeds.length, page)
+        );
         let selectPane = [];
 
         if (selectPaneOpen) {
             const options = [];
-            embeds.forEach(embed => {
-                options.push(new SelectMenuOption({
-                    label: embed.title,
-                    value: embed.pageId.toString(),
-                    description: embed.description || ""
-                }));
+            embeds.forEach((embed) => {
+                options.push(
+                    new SelectMenuOption({
+                        label: embed.title,
+                        value: embed.pageId.toString(),
+                        description: embed.description || ""
+                    })
+                );
             });
-            selectPane = [new MessageActionRow().addComponents([
-                new Discord.MessageSelectMenu()
-                    .addOptions(options)
-                    .setCustomId("page")
-                    .setMaxValues(1)
-                    .setPlaceholder("Choose a page...")
-            ])];
+            selectPane = [
+                new MessageActionRow().addComponents([
+                    new Discord.MessageSelectMenu()
+                        .addOptions(options)
+                        .setCustomId("page")
+                        .setMaxValues(1)
+                        .setPlaceholder("Choose a page...")
+                ])
+            ];
         }
         await interaction.editReply({
             embeds: [em],
-            components: selectPane.concat([new MessageActionRow().addComponents([
-                new MessageButton()
-                    .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
-                    .setStyle("SECONDARY")
-                    .setCustomId("left")
-                    .setDisabled(page === 0),
-                new MessageButton()
-                    .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
-                    .setStyle(selectPaneOpen ? "PRIMARY" : "SECONDARY")
-                    .setCustomId("select")
-                    .setDisabled(false),
-                new MessageButton()
-                    .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
-                    .setCustomId("right")
-                    .setStyle("SECONDARY")
-                    .setDisabled(page === embeds.length - 1),
-                new MessageButton()
-                    .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
-                    .setCustomId("close")
-                    .setStyle("DANGER")
-            ])])
+            components: selectPane.concat([
+                new MessageActionRow().addComponents([
+                    new MessageButton()
+                        .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
+                        .setStyle("SECONDARY")
+                        .setCustomId("left")
+                        .setDisabled(page === 0),
+                    new MessageButton()
+                        .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
+                        .setStyle(selectPaneOpen ? "PRIMARY" : "SECONDARY")
+                        .setCustomId("select")
+                        .setDisabled(false),
+                    new MessageButton()
+                        .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
+                        .setCustomId("right")
+                        .setStyle("SECONDARY")
+                        .setDisabled(page === embeds.length - 1),
+                    new MessageButton()
+                        .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
+                        .setCustomId("close")
+                        .setStyle("DANGER")
+                ])
+            ])
         });
         let i: MessageComponentInteraction;
         try {
-            i = await m.awaitMessageComponent({time: 300000});
-        } catch { breakReason = "Message timed out"; break; }
+            i = await m.awaitMessageComponent({ time: 300000 });
+        } catch {
+            breakReason = "Message timed out";
+            break;
+        }
         i.deferUpdate();
         if ((i.component as MessageActionRowComponent).customId === "left") {
             if (page > 0) page--;
             selectPaneOpen = false;
-        } else if ((i.component as MessageActionRowComponent).customId === "right") {
+        } else if (
+            (i.component as MessageActionRowComponent).customId === "right"
+        ) {
             if (page < embeds.length - 1) page++;
             selectPaneOpen = false;
-        } else if ((i.component as MessageActionRowComponent).customId === "select") {
+        } else if (
+            (i.component as MessageActionRowComponent).customId === "select"
+        ) {
             selectPaneOpen = !selectPaneOpen;
-        } else if ((i.component as MessageActionRowComponent).customId === "close") {
+        } else if (
+            (i.component as MessageActionRowComponent).customId === "close"
+        ) {
             breakReason = "Message closed";
             break;
-        } else if ((i.component as MessageActionRowComponent).customId === "page") {
+        } else if (
+            (i.component as MessageActionRowComponent).customId === "page"
+        ) {
             page = parseInt((i as SelectMenuInteraction).values[0]);
             selectPaneOpen = false;
         } else {
@@ -231,29 +345,40 @@
         }
     }
     const em = new Discord.MessageEmbed(embeds[page].embed);
-    em.setDescription(em.description + "\n" + createPageIndicator(embeds.length, page) + " | " + breakReason);
-    await interaction.editReply({embeds: [em], components: [new MessageActionRow().addComponents([
-        new MessageButton()
-            .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
-            .setStyle("SECONDARY")
-            .setCustomId("left")
-            .setDisabled(true),
-        new MessageButton()
-            .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
-            .setStyle("SECONDARY")
-            .setCustomId("select")
-            .setDisabled(true),
-        new MessageButton()
-            .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
-            .setCustomId("right")
-            .setStyle("SECONDARY")
-            .setDisabled(true),
-        new MessageButton()
-            .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
-            .setCustomId("close")
-            .setStyle("DANGER")
-            .setDisabled(true)
-    ])]});
+    em.setDescription(
+        em.description +
+            "\n" +
+            createPageIndicator(embeds.length, page) +
+            " | " +
+            breakReason
+    );
+    await interaction.editReply({
+        embeds: [em],
+        components: [
+            new MessageActionRow().addComponents([
+                new MessageButton()
+                    .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
+                    .setStyle("SECONDARY")
+                    .setCustomId("left")
+                    .setDisabled(true),
+                new MessageButton()
+                    .setEmoji(getEmojiByName("CONTROL.MENU", "id"))
+                    .setStyle("SECONDARY")
+                    .setCustomId("select")
+                    .setDisabled(true),
+                new MessageButton()
+                    .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
+                    .setCustomId("right")
+                    .setStyle("SECONDARY")
+                    .setDisabled(true),
+                new MessageButton()
+                    .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
+                    .setCustomId("close")
+                    .setStyle("DANGER")
+                    .setDisabled(true)
+            ])
+        ]
+    });
 };
 
 const check = () => {
diff --git a/src/commands/user/avatar.ts b/src/commands/user/avatar.ts
index 8f327a5..35c475f 100644
--- a/src/commands/user/avatar.ts
+++ b/src/commands/user/avatar.ts
@@ -9,29 +9,44 @@
     builder
         .setName("avatar")
         .setDescription("Shows the avatar of a user")
-        .addUserOption(option => option.setName("user").setDescription("The user to get the avatar of | Default: Yourself"));
+        .addUserOption((option) =>
+            option
+                .setName("user")
+                .setDescription(
+                    "The user to get the avatar of | Default: Yourself"
+                )
+        );
 
 const callback = async (interaction: CommandInteraction): Promise<void> => {
     const { renderUser } = client.logger;
-    const member = (interaction.options.getMember("user") || interaction.member) as Discord.GuildMember;
-    await interaction.reply({embeds: [new EmojiEmbed()
-        .setTitle("User Info")
-        .setStatus("Success")
-        .setEmoji("MEMBER.JOIN")
-        .setDescription(
-            generateKeyValueList({
-                "member": renderUser(member.user),
-                "url": member.user.displayAvatarURL({dynamic: true})
-            })
-        )
-        .setImage(await member.user.displayAvatarURL({dynamic: true}))
-    ], ephemeral: true, fetchReply: true});
+    const member = (interaction.options.getMember("user") ||
+        interaction.member) as Discord.GuildMember;
+    await interaction.reply({
+        embeds: [
+            new EmojiEmbed()
+                .setTitle("User Info")
+                .setStatus("Success")
+                .setEmoji("MEMBER.JOIN")
+                .setDescription(
+                    generateKeyValueList({
+                        member: renderUser(member.user),
+                        url: member.user.displayAvatarURL({ dynamic: true })
+                    })
+                )
+                .setImage(await member.user.displayAvatarURL({ dynamic: true }))
+        ],
+        ephemeral: true,
+        fetchReply: true
+    });
 };
 
-const check = (_interaction: CommandInteraction, _defaultCheck: WrappedCheck) => {
+const check = (
+    _interaction: CommandInteraction,
+    _defaultCheck: WrappedCheck
+) => {
     return true;
 };
 
 export { command };
 export { callback };
-export { check };
\ No newline at end of file
+export { check };
diff --git a/src/commands/user/track.ts b/src/commands/user/track.ts
index 4720032..e0e41e0 100644
--- a/src/commands/user/track.ts
+++ b/src/commands/user/track.ts
@@ -1,8 +1,17 @@
 import { LoadingEmbed } from "./../../utils/defaultEmbeds.js";
-import Discord, { CommandInteraction, GuildMember, Message, MessageActionRow, MessageButton } from "discord.js";
-import { SelectMenuOption, SlashCommandSubcommandBuilder } from "@discordjs/builders";
+import Discord, {
+    CommandInteraction,
+    GuildMember,
+    Message,
+    MessageActionRow,
+    MessageButton
+} from "discord.js";
+import {
+    SelectMenuOption,
+    SlashCommandSubcommandBuilder
+} from "@discordjs/builders";
 // eslint-disable-next-line @typescript-eslint/ban-ts-comment
-// @ts-ignore
+// @ts-expect-error
 import { WrappedCheck } from "jshaiku";
 import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../../utils/getEmojiByName.js";
@@ -13,24 +22,38 @@
     builder
         .setName("track")
         .setDescription("Moves a user along a role track")
-        .addUserOption(option => option.setName("user").setDescription("The user to manage").setRequired(true));
+        .addUserOption((option) =>
+            option
+                .setName("user")
+                .setDescription("The user to manage")
+                .setRequired(true)
+        );
 
-const generateFromTrack = (position: number, active: string | boolean, size: number, disabled: string | boolean) => {
+const generateFromTrack = (
+    position: number,
+    active: string | boolean,
+    size: number,
+    disabled: string | boolean
+) => {
     active = active ? "ACTIVE" : "INACTIVE";
     disabled = disabled ? "GREY." : "";
-    if (position === 0 && size === 1) return "TRACKS.SINGLE." + disabled + active;
-    if (position === size - 1) return "TRACKS.VERTICAL.BOTTOM." + disabled + active;
+    if (position === 0 && size === 1)
+        return "TRACKS.SINGLE." + disabled + active;
+    if (position === size - 1)
+        return "TRACKS.VERTICAL.BOTTOM." + disabled + active;
     if (position === 0) return "TRACKS.VERTICAL.TOP." + disabled + active;
     return "TRACKS.VERTICAL.MIDDLE." + disabled + active;
 };
 
-const callback = async (interaction: CommandInteraction): Promise<void | unknown> => {
+const callback = async (
+    interaction: CommandInteraction
+): Promise<void | unknown> => {
     const { renderUser } = client.logger;
     const member = interaction.options.getMember("user") as GuildMember;
     const guild = interaction.guild;
     if (!guild) return;
     const config = await client.database.guilds.read(guild.id);
-    await interaction.reply({embeds: LoadingEmbed, ephemeral: true});
+    await interaction.reply({ embeds: LoadingEmbed, ephemeral: true });
     let track = 0;
     let generated;
     const roles = await guild.roles.fetch();
@@ -38,119 +61,206 @@
     let managed: boolean;
     while (true) {
         const data = config.tracks[track];
-        if (data.manageableBy !== undefined) managed = data.manageableBy.some((element: string) => {return memberRoles.cache.has(element);});
-        else managed = false;
-        const dropdown = new Discord.MessageSelectMenu().addOptions(config.tracks.map((option, index) => {
-            const hasRoleInTrack = option.track.some((element: string) => {return memberRoles.cache.has(element);});
-            return new SelectMenuOption({
-                default: index === track,
-                label: option.name,
-                value: index.toString(),
-                description: option.track.length === 0 ? "No" : addPlural(option.track.length, "role"),
-                emoji: client.emojis.resolve(getEmojiByName("TRACKS.SINGLE." + (hasRoleInTrack ? "ACTIVE" : "INACTIVE"), "id"))
+        if (data.manageableBy !== undefined)
+            managed = data.manageableBy.some((element: string) => {
+                return memberRoles.cache.has(element);
             });
-        })).setCustomId("select").setMaxValues(1);
+        else managed = false;
+        const dropdown = new Discord.MessageSelectMenu()
+            .addOptions(
+                config.tracks.map((option, index) => {
+                    const hasRoleInTrack = option.track.some(
+                        (element: string) => {
+                            return memberRoles.cache.has(element);
+                        }
+                    );
+                    return new SelectMenuOption({
+                        default: index === track,
+                        label: option.name,
+                        value: index.toString(),
+                        description:
+                            option.track.length === 0
+                                ? "No"
+                                : addPlural(option.track.length, "role"),
+                        emoji: client.emojis.resolve(
+                            getEmojiByName(
+                                "TRACKS.SINGLE." +
+                                    (hasRoleInTrack ? "ACTIVE" : "INACTIVE"),
+                                "id"
+                            )
+                        )
+                    });
+                })
+            )
+            .setCustomId("select")
+            .setMaxValues(1);
         const allowed = [];
-        generated = "**Track:** " + data.name + "\n" + "**Member:** " + renderUser(member.user) + "\n";
-        generated += (data.nullable ? "Members do not need a role in this track" : "A role in this track is required") + "\n";
-        generated += (data.retainPrevious ? "When promoted, the user keeps previous roles" : "Members will lose their current role when promoted") + "\n";
-        generated += "\n" + data.track.map((role, index) => {
-            const allow = (roles.get(role).position >= (interaction.member as GuildMember).roles.highest.position) && !managed;
-            allowed.push(!allow);
-            return getEmojiByName(generateFromTrack(
-                index,
-                memberRoles.cache.has(role),
-                data.track.length,
-                allow
-            )) + " " +
-            roles.get(role).name + " [<@&" + roles.get(role).id + ">]";
-        }).join("\n");
+        generated =
+            "**Track:** " +
+            data.name +
+            "\n" +
+            "**Member:** " +
+            renderUser(member.user) +
+            "\n";
+        generated +=
+            (data.nullable
+                ? "Members do not need a role in this track"
+                : "A role in this track is required") + "\n";
+        generated +=
+            (data.retainPrevious
+                ? "When promoted, the user keeps previous roles"
+                : "Members will lose their current role when promoted") + "\n";
+        generated +=
+            "\n" +
+            data.track
+                .map((role, index) => {
+                    const allow =
+                        roles.get(role).position >=
+                            (interaction.member as GuildMember).roles.highest
+                                .position && !managed;
+                    allowed.push(!allow);
+                    return (
+                        getEmojiByName(
+                            generateFromTrack(
+                                index,
+                                memberRoles.cache.has(role),
+                                data.track.length,
+                                allow
+                            )
+                        ) +
+                        " " +
+                        roles.get(role).name +
+                        " [<@&" +
+                        roles.get(role).id +
+                        ">]"
+                    );
+                })
+                .join("\n");
         const selected = [];
         for (let i = 0; i < data.track.length; i++) {
-            if (memberRoles.cache.has(data.track[i])) selected.push(data.track[i]);
+            if (memberRoles.cache.has(data.track[i]))
+                selected.push(data.track[i]);
         }
         const conflict = data.retainPrevious ? false : selected.length > 1;
         let conflictDropdown;
         let currentRoleIndex;
         if (conflict) {
-            generated += `\n\n${getEmojiByName(`PUNISH.WARN.${managed ? "YELLOW" : "RED"}`)} This user has ${selected.length} roles from this track. `;
+            generated += `\n\n${getEmojiByName(
+                `PUNISH.WARN.${managed ? "YELLOW" : "RED"}`
+            )} This user has ${selected.length} roles from this track. `;
             conflictDropdown = [];
             if (
-                (roles.get(selected[0]).position < memberRoles.highest.position) || managed
+                roles.get(selected[0]).position <
+                    memberRoles.highest.position ||
+                managed
             ) {
-                generated +=  "In order to promote or demote this user, you must select which role the member should keep.";
-                selected.forEach(role => {
-                    conflictDropdown.push(new SelectMenuOption({
-                        label: roles.get(role).name,
-                        value: roles.get(role).id
-                    }));
+                generated +=
+                    "In order to promote or demote this user, you must select which role the member should keep.";
+                selected.forEach((role) => {
+                    conflictDropdown.push(
+                        new SelectMenuOption({
+                            label: roles.get(role).name,
+                            value: roles.get(role).id
+                        })
+                    );
                 });
-                conflictDropdown = [new Discord.MessageSelectMenu()
-                    .addOptions(conflictDropdown)
-                    .setCustomId("conflict")
-                    .setMaxValues(1)
-                    .setPlaceholder("Select a role to keep")];
+                conflictDropdown = [
+                    new Discord.MessageSelectMenu()
+                        .addOptions(conflictDropdown)
+                        .setCustomId("conflict")
+                        .setMaxValues(1)
+                        .setPlaceholder("Select a role to keep")
+                ];
             } else {
-                generated += "You don't have permission to manage one or more of the users roles, and therefore can't select one to keep.";
+                generated +=
+                    "You don't have permission to manage one or more of the users roles, and therefore can't select one to keep.";
             }
         } else {
-            currentRoleIndex = selected.length === 0 ? -1 : data.track.indexOf(selected[0].toString());
+            currentRoleIndex =
+                selected.length === 0
+                    ? -1
+                    : data.track.indexOf(selected[0].toString());
         }
-        const m = await interaction.editReply({embeds: [new EmojiEmbed()
-            .setEmoji("TRACKS.ICON")
-            .setTitle("Tracks")
-            .setDescription(`${generated}`)
-            .setStatus("Success")
-        ], components: [
-            new MessageActionRow().addComponents(dropdown)
-        ]
-            .concat(conflict && conflictDropdown.length ? [new MessageActionRow().addComponents(conflictDropdown)] : [])
-            .concat([
-                new MessageActionRow().addComponents([
-                    new MessageButton()
-                        .setEmoji(getEmojiByName("CONTROL.UP", "id"))
-                        .setLabel("Move up")
-                        .setCustomId("promote")
-                        .setStyle("SUCCESS")
-                        .setDisabled(conflict || currentRoleIndex === 0 || (currentRoleIndex === -1 ? false : !allowed[currentRoleIndex - 1])),
-                    new MessageButton()
-                        .setEmoji(getEmojiByName("CONTROL.DOWN", "id"))
-                        .setLabel("Move down")
-                        .setCustomId("demote")
-                        .setStyle("DANGER")
-                        .setDisabled(conflict || (
-                            data.nullable ? currentRoleIndex <= -1 :
-                                currentRoleIndex === data.track.length - 1 || currentRoleIndex <= -1
-                        ) || !allowed[currentRoleIndex])
+        const m = (await interaction.editReply({
+            embeds: [
+                new EmojiEmbed()
+                    .setEmoji("TRACKS.ICON")
+                    .setTitle("Tracks")
+                    .setDescription(`${generated}`)
+                    .setStatus("Success")
+            ],
+            components: [new MessageActionRow().addComponents(dropdown)]
+                .concat(
+                    conflict && conflictDropdown.length
+                        ? [
+                              new MessageActionRow().addComponents(
+                                  conflictDropdown
+                              )
+                          ]
+                        : []
+                )
+                .concat([
+                    new MessageActionRow().addComponents([
+                        new MessageButton()
+                            .setEmoji(getEmojiByName("CONTROL.UP", "id"))
+                            .setLabel("Move up")
+                            .setCustomId("promote")
+                            .setStyle("SUCCESS")
+                            .setDisabled(
+                                conflict ||
+                                    currentRoleIndex === 0 ||
+                                    (currentRoleIndex === -1
+                                        ? false
+                                        : !allowed[currentRoleIndex - 1])
+                            ),
+                        new MessageButton()
+                            .setEmoji(getEmojiByName("CONTROL.DOWN", "id"))
+                            .setLabel("Move down")
+                            .setCustomId("demote")
+                            .setStyle("DANGER")
+                            .setDisabled(
+                                conflict ||
+                                    (data.nullable
+                                        ? currentRoleIndex <= -1
+                                        : currentRoleIndex ===
+                                              data.track.length - 1 ||
+                                          currentRoleIndex <= -1) ||
+                                    !allowed[currentRoleIndex]
+                            )
+                    ])
                 ])
-            ])
-        }) as Message;
+        })) as Message;
         let component;
         try {
-            component = await m.awaitMessageComponent({time: 300000});
+            component = await m.awaitMessageComponent({ time: 300000 });
         } catch (e) {
             return;
         }
         component.deferUpdate();
         if (component.customId === "conflict") {
-            const rolesToRemove = selected.filter(role => role !== component.values[0]);
+            const rolesToRemove = selected.filter(
+                (role) => role !== component.values[0]
+            );
             await member.roles.remove(rolesToRemove);
         } else if (component.customId === "promote") {
             if (
-                currentRoleIndex === -1 ? allowed[data.track.length - 1] :
-                    allowed[currentRoleIndex - 1] && allowed[currentRoleIndex]
+                currentRoleIndex === -1
+                    ? allowed[data.track.length - 1]
+                    : allowed[currentRoleIndex - 1] && allowed[currentRoleIndex]
             ) {
                 if (currentRoleIndex === -1) {
                     await member.roles.add(data.track[data.track.length - 1]);
                 } else if (currentRoleIndex < data.track.length) {
-                    if (!data.retainPrevious) await member.roles.remove(data.track[currentRoleIndex]);
+                    if (!data.retainPrevious)
+                        await member.roles.remove(data.track[currentRoleIndex]);
                     await member.roles.add(data.track[currentRoleIndex - 1]);
                 }
             }
         } else if (component.customId === "demote") {
-            if(allowed[currentRoleIndex]) {
+            if (allowed[currentRoleIndex]) {
                 if (currentRoleIndex === data.track.length - 1) {
-                    if (data.nullable) await member.roles.remove(data.track[currentRoleIndex]);
+                    if (data.nullable)
+                        await member.roles.remove(data.track[currentRoleIndex]);
                 } else if (currentRoleIndex > -1) {
                     await member.roles.remove(data.track[currentRoleIndex]);
                     await member.roles.add(data.track[currentRoleIndex + 1]);
@@ -162,22 +272,32 @@
     }
 };
 
-const check = async (interaction: CommandInteraction, _defaultCheck: WrappedCheck) => {
-    const tracks = (await client.database.guilds.read(interaction.guild.id)).tracks;
+const check = async (
+    interaction: CommandInteraction,
+    _defaultCheck: WrappedCheck
+) => {
+    const tracks = (await client.database.guilds.read(interaction.guild.id))
+        .tracks;
     if (tracks.length === 0) throw "This server does not have any tracks";
-    const member = (interaction.member as GuildMember);
+    const member = interaction.member as GuildMember;
     // Allow the owner to promote anyone
     if (member.id === interaction.guild.ownerId) return true;
     // Check if the user can manage any of the tracks
     let managed = false;
     for (const element of tracks) {
         if (!element.track.manageableBy) continue;
-        if (!element.track.manageableBy.some(role => member.roles.cache.has(role))) continue;
+        if (
+            !element.track.manageableBy.some((role) =>
+                member.roles.cache.has(role)
+            )
+        )
+            continue;
         managed = true;
         break;
     }
     // Check if the user has manage_roles permission
-    if (!managed && ! member.permissions.has("MANAGE_ROLES")) throw "You do not have the *Manage Roles* permission";
+    if (!managed && !member.permissions.has("MANAGE_ROLES"))
+        throw "You do not have the *Manage Roles* permission";
     // Allow track
     return true;
 };
@@ -185,4 +305,3 @@
 export { command };
 export { callback };
 export { check };
-