Added options for stats channels, moderation command buttons and fixed the updating of stats channels
diff --git a/TODO.json b/TODO.json
index d95afcb..44bb7e6 100644
--- a/TODO.json
+++ b/TODO.json
@@ -2,12 +2,7 @@
   "logging": {
     "logs": {
       "enabled": true,
-      "toLog": "3fffff",
-      "ignore": {
-        "users": [],
-        "roles": [],
-        "channels": []
-      }
+      "toLog": "3fffff"
     }
   },
   "filters": {
@@ -19,16 +14,8 @@
     "wordFilter": {
       "enabled": true,
       "words": {
-        "strict": [
-          "meat",
-          "noon"
-        ],
+        "strict": [],
         "loose": []
-      },
-      "allowed": {
-        "users": [],
-        "roles": [],
-        "channels": []
       }
     },
     "invite": {
@@ -42,51 +29,13 @@
     "pings": {
       "mass": 5,
       "everyone": true,
-      "roles": true,
-      "allowed": {
-        "roles": [],
-        "rolesToMention": [],
-        "users": [],
-        "channels": []
-      }
-    }
-  },
-  "moderation": {
-    "mute": {
-      "timeout": true,
-      "role": "934941408849186856",
-      "text": null,
-      "link": null
-    },
-    "kick": {
-      "text": null,
-      "link": null
-    },
-    "ban": {
-      "text": null,
-      "link": null
-    },
-    "softban": {
-      "text": null,
-      "link": null
-    },
-    "warn": {
-      "text": "Test",
-      "link": "https://google.com"
-    },
-    "role": {
-      "role": null
+      "roles": true
     }
   },
   "roleMenu": [],
-  "stats": [],
   "tracks": [],
   "welcome": {
     "enabled": false,
-    "verificationRequired": {
-      "message": null,
-      "role": null
-    },
     "welcomeRole": null,
     "channel": null,
     "message": null
diff --git a/src/commands/settings/commands.ts b/src/commands/settings/commands.ts
new file mode 100644
index 0000000..df2cdb4
--- /dev/null
+++ b/src/commands/settings/commands.ts
@@ -0,0 +1,144 @@
+import Discord, { CommandInteraction, MessageActionRow, MessageButton, TextInputComponent } from "discord.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import getEmojiByName from "../../utils/getEmojiByName.js";
+import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
+import { WrappedCheck } from "jshaiku";
+import client from "../../utils/client.js";
+import { modalInteractionCollector } from "../../utils/dualCollector.js";
+import confirmationMessage from "../../utils/confirmationMessage.js";
+import keyValueList from "../../utils/generateKeyValueList.js";
+
+const command = (builder: SlashCommandSubcommandBuilder) =>
+    builder
+    .setName("commands")
+    .setDescription("Links and text shown to a user after a moderator action is performed")
+    .addRoleOption(o => o.setName("role").setDescription("The role given when a member is muted"))
+
+const callback = async (interaction: CommandInteraction): Promise<any> => {
+    await interaction.reply({embeds: [new EmojiEmbed()
+        .setTitle("Loading")
+        .setStatus("Danger")
+        .setEmoji("NUCLEUS.LOADING")
+    ], ephemeral: true, fetchReply: true});
+    let m;
+    let clicked = "";
+    if (interaction.options.getRole("role")) {
+        let confirmation = await new confirmationMessage(interaction)
+            .setEmoji("GUILD.ROLES.DELETE")
+            .setTitle("Moderation Commands")
+            .setDescription(keyValueList({
+                role: `<@&${interaction.options.getRole("role").id}>`,
+            }))
+            .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.success) {
+            await client.database.guilds.write(interaction.guild.id, {["moderation.mute.role"]: interaction.options.getRole("role").id});
+        }
+    }
+    while (true) {
+        let config = await client.database.guilds.read(interaction.guild.id);
+        let moderation = config.getKey("moderation");
+        m = await interaction.editReply({embeds: [new EmojiEmbed()
+            .setTitle("Moderation Commands")
+            .setEmoji("PUNISH.BAN.GREEN")
+            .setStatus("Success")
+            .setDescription(
+                "These links are shown below the message sent in a user's DM when they are warned, banned, etc.\n\n" +
+                `**Mute Role:** ` + (moderation.mute.role ? `<@&${moderation.mute.role}>` : "*None set*")
+            )
+        ], components: [new MessageActionRow().addComponents([
+            new MessageButton().setLabel("Warn").setEmoji(getEmojiByName("PUNISH.WARN.YELLOW", "id")).setCustomId("warn").setStyle("SECONDARY"),
+            new MessageButton().setLabel("Mute").setEmoji(getEmojiByName("PUNISH.MUTE.YELLOW", "id")).setCustomId("mute").setStyle("SECONDARY"),
+            new MessageButton().setLabel("Nickname").setEmoji(getEmojiByName("PUNISH.NICKNAME.GREEN", "id")).setCustomId("nickname").setStyle("SECONDARY")
+        ]), new MessageActionRow().addComponents([
+            new MessageButton().setLabel("Kick").setEmoji(getEmojiByName("PUNISH.KICK.RED", "id")).setCustomId("kick").setStyle("SECONDARY"),
+            new MessageButton().setLabel("Softban").setEmoji(getEmojiByName("PUNISH.BAN.YELLOW", "id")).setCustomId("softban").setStyle("SECONDARY"),
+            new MessageButton().setLabel("Ban").setEmoji(getEmojiByName("PUNISH.BAN.RED", "id")).setCustomId("ban").setStyle("SECONDARY")
+        ]), new MessageActionRow().addComponents([
+            new MessageButton().setLabel(
+                clicked === "clearMuteRole" ? "Click again to confirm" : "Clear mute role"
+            ).setEmoji(getEmojiByName("CONTROL.CROSS", "id")).setCustomId("clearMuteRole").setStyle("DANGER").setDisabled(!moderation.mute.role),
+            new MessageButton()
+                .setCustomId("timeout")
+                .setLabel("Mute timeout " + (moderation.mute.timeout ? "Enabled" : "Disabled"))
+                .setStyle(moderation.mute.timeout ? "SUCCESS" : "DANGER")
+                .setEmoji(getEmojiByName("CONTROL." + (moderation.mute.timeout ? "TICK" : "CROSS"), "id"))
+        ])]});
+        let i;
+        try {
+            i = await m.awaitMessageComponent({ time: 300000 });
+        } catch (e) { return }
+        let chosen = moderation[i.customId] ?? {text: null, url: null};
+        if (i.component.customId === "clearMuteRole") {
+            if (clicked === "clearMuteRole") {
+                await client.database.guilds.write(interaction.guild.id, { moderation: { mute: { role: null } } });
+            } else { clicked = "clearMuteRole" }
+        } else { clicked = "" }
+        if (i.component.customId === "timeout") {
+            await i.deferUpdate()
+            await client.database.guilds.write(interaction.guild.id, { moderation: { mute: { timeout: !moderation.mute.timeout } } });
+        } else if (i.customId) {
+            await i.showModal(new Discord.Modal().setCustomId("modal").setTitle(`Options for ${i.customId}`).addComponents(
+                new MessageActionRow<TextInputComponent>().addComponents(new TextInputComponent()
+                    .setCustomId("name")
+                    .setLabel("Button text")
+                    .setMaxLength(100)
+                    .setRequired(false)
+                    .setStyle("SHORT")
+                    .setValue(chosen.text ?? "")
+                ),
+                new MessageActionRow<TextInputComponent>().addComponents(new TextInputComponent()
+                    .setCustomId("url")
+                    .setLabel("URL - Type {id} to insert the user's ID")
+                    .setMaxLength(2000)
+                    .setRequired(false)
+                    .setStyle("SHORT")
+                    .setValue(chosen.link ?? "")
+                )
+            ))
+            await interaction.editReply({
+                embeds: [new EmojiEmbed()
+                    .setTitle("Moderation Links")
+                    .setDescription("Modal opened. If you can't see it, click back and try again.")
+                    .setStatus("Success")
+                    .setEmoji("GUILD.TICKET.OPEN")
+                ], components: [new MessageActionRow().addComponents([new MessageButton()
+                    .setLabel("Back")
+                    .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
+                    .setStyle("PRIMARY")
+                    .setCustomId("back")
+                ])]
+            });
+            let out;
+            try {
+                out = await modalInteractionCollector(m, (m) => m.channel.id == interaction.channel.id, (m) => true)
+            } catch (e) { continue }
+            if (out.fields) {
+                let buttonText = out.fields.getTextInputValue("name");
+                let buttonLink = out.fields.getTextInputValue("url").replace(/{id}/gi, "{id}");
+                let current = chosen;
+                if (current.text !== buttonText || current.link !== buttonLink) {
+                    chosen = { text: buttonText, link: buttonLink };
+                    await client.database.guilds.write(interaction.guild.id, { ["moderation" + i.customId]: { text: buttonText, link: buttonLink }});
+                }
+            } else { continue }
+        }
+    }
+}
+
+
+const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
+    let member = (interaction.member as Discord.GuildMember)
+    if (!member.permissions.has("MANAGE_GUILD")) throw "You must have the Manage server permission to use this command"
+    return true;
+}
+
+export { command };
+export { callback };
+export { check };
\ No newline at end of file
diff --git a/src/commands/settings/logs/ignore.ts b/src/commands/settings/logs/ignore.ts
deleted file mode 100644
index 59f6621..0000000
--- a/src/commands/settings/logs/ignore.ts
+++ /dev/null
@@ -1,144 +0,0 @@
-import { ChannelType } from 'discord-api-types';
-import Discord, { CommandInteraction } from "discord.js";
-import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
-import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
-import { WrappedCheck } from "jshaiku";
-import confirmationMessage from '../../../utils/confirmationMessage.js';
-import keyValueList from '../../../utils/generateKeyValueList.js';
-import client from '../../../utils/client.js';
-
-const command = (builder: SlashCommandSubcommandBuilder) =>
-    builder
-    .setName("ignore")
-    .setDescription("Sets which users, channels and roles should be ignored")
-    .addStringOption(o => o.setName("action").setDescription("Add or remove from the list").addChoices([
-        ["Add", "add"], ["Remove", "remove"]
-    ]).setRequired(true))
-    .addChannelOption(o => o.setName("addchannel").setDescription("Add a channel that should be ignored").addChannelTypes([
-        ChannelType.GuildText, ChannelType.GuildVoice, ChannelType.GuildNews, ChannelType.GuildPublicThread, ChannelType.GuildPrivateThread, ChannelType.GuildNewsThread
-    ]))
-    .addUserOption(o => o.setName("adduser").setDescription("Add a user that should be ignored"))
-    .addRoleOption(o => o.setName("addrole").setDescription("Add a role that should be ignored"))
-
-const callback = async (interaction: CommandInteraction): Promise<any> => {
-    let channel = interaction.options.getChannel("addchannel")
-    let user = interaction.options.getUser("adduser")
-    let role = interaction.options.getRole("addrole")
-    await interaction.reply({embeds: [new EmojiEmbed()
-        .setTitle("Loading")
-        .setStatus("Danger")
-        .setEmoji("NUCLEUS.LOADING")
-    ], ephemeral: true, fetchReply: true});
-    if (channel || user || role) {
-        if (channel) {
-            try {
-                channel = interaction.guild.channels.cache.get(channel.id)
-            } catch {
-                return await interaction.editReply({embeds: [new EmojiEmbed()
-                    .setEmoji("CHANNEL.TEXT.DELETE")
-                    .setTitle("Logs > Ignore")
-                    .setDescription("The channel you provided is not a valid channel")
-                    .setStatus("Danger")
-                ]})
-            }
-            channel = channel as Discord.TextChannel
-            if (channel.guild.id != interaction.guild.id) {
-                return interaction.editReply({embeds: [new EmojiEmbed()
-                    .setTitle("Logs > Ignore")
-                    .setDescription(`You must choose a channel in this server`)
-                    .setStatus("Danger")
-                    .setEmoji("CHANNEL.TEXT.DELETE")
-                ]});
-            }
-        }
-        if (user) {
-            try {
-                user = interaction.guild.members.cache.get(user.id).user
-            } catch {
-                return await interaction.editReply({embeds: [new EmojiEmbed()
-                    .setEmoji("USER.DELETE")
-                    .setTitle("Logs > Ignore")
-                    .setDescription("The user you provided is not a valid user")
-                    .setStatus("Danger")
-                ]})
-            }
-            user = user as Discord.User
-        }
-        if (role) {
-            try {
-                role = interaction.guild.roles.cache.get(role.id)
-            } catch {
-                return await interaction.editReply({embeds: [new EmojiEmbed()
-                    .setEmoji("ROLE.DELETE")
-                    .setTitle("Logs > Ignore")
-                    .setDescription("The role you provided is not a valid role")
-                    .setStatus("Danger")
-                ]})
-            }
-            role = role as Discord.Role
-            if (role.guild.id != interaction.guild.id) {
-                return interaction.editReply({embeds: [new EmojiEmbed()
-                    .setTitle("Logs > Ignore")
-                    .setDescription(`You must choose a role in this server`)
-                    .setStatus("Danger")
-                    .setEmoji("ROLE.DELETE")
-                ]});
-            }
-        }
-        let changes = {}
-        if (channel) changes["channel"] = channel.id
-        if (user) changes["user"] = user.id
-        if (role) changes["role"] = role.id
-        let confirmation = await new confirmationMessage(interaction)
-            .setEmoji("NUCLEUS.COMMANDS.IGNORE")
-            .setTitle("Logs > Ignore")
-            .setDescription(keyValueList(changes)
-            + `Are you sure you want to **${interaction.options.getString("action") == "add" ? "add" : "remove"}** these to the ignore list?`)
-            .setColor("Warning")
-        .send(true)
-        if (confirmation.cancelled) return
-        if (confirmation.success) {
-            let data = client.database.guilds.read(interaction.guild.id)
-            if (channel) data.logging.logs.ignore.channels.concat([channel.id])
-            if (user) data.logging.logs.ignore.users.concat([user.id])
-            if (role) data.logging.logs.ignore.roles.concat([role.id])
-            if (interaction.options.getString("action") == "add") {
-                await client.database.guilds.append(interaction.guild.id, data)
-            } else {
-                await client.database.guilds.remove(interaction.guild.id, data)
-            }
-            const { log, NucleusColors, entry, renderUser, renderChannel } = client.logger
-            try {
-                let data = {
-                    meta:{
-                        type: 'logIgnoreUpdated',
-                        displayName: 'Ignored Groups Changed',
-                        calculateType: 'nucleusSettingsUpdated',
-                        color: NucleusColors.yellow,
-                        emoji: "CHANNEL.TEXT.EDIT",
-                        timestamp: new Date().getTime()
-                    },
-                    list: {
-                        memberId: entry(interaction.user.id, `\`${interaction.user.id}\``),
-                        changedBy: entry(interaction.user.id, renderUser(interaction.user)),
-                        channel: entry(channel.id, renderChannel(channel)),
-                    },
-                    hidden: {
-                        guild: interaction.guild.id
-                    }
-                }
-                log(data);
-            } catch {}
-        }
-    }
-}
-
-const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
-    let member = (interaction.member as Discord.GuildMember)
-    if (!member.permissions.has("MANAGE_GUILD")) throw "You must have the Manage Server permission to use this command"
-    return true;
-}
-
-export { command };
-export { callback };
-export { check };
\ No newline at end of file
diff --git a/src/commands/settings/stats/set.ts b/src/commands/settings/stats.ts
similarity index 62%
rename from src/commands/settings/stats/set.ts
rename to src/commands/settings/stats.ts
index 10c3011..3159e2d 100644
--- a/src/commands/settings/stats/set.ts
+++ b/src/commands/settings/stats.ts
@@ -1,33 +1,29 @@
 import { ChannelType } from 'discord-api-types';
-import Discord, { CommandInteraction, MessageActionRow, MessageButton } from "discord.js";
-import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
-import confirmationMessage from "../../../utils/confirmationMessage.js";
-import getEmojiByName from "../../../utils/getEmojiByName.js";
-import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
+import Discord, { AutocompleteInteraction, CommandInteraction, Message, MessageActionRow, MessageButton, MessageSelectMenu } from "discord.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import confirmationMessage from "../../utils/confirmationMessage.js";
+import getEmojiByName from "../../utils/getEmojiByName.js";
+import { SelectMenuOption, SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
-import client from "../../../utils/client.js";
-import convertCurlyBracketString from '../../../utils/convertCurlyBracketString.js';
-import {callback as statsChannelAddCallback} from "../../../reflex/statsChannelUpdate.js";
+import client from "../../utils/client.js";
+import convertCurlyBracketString from '../../utils/convertCurlyBracketString.js';
+import {callback as statsChannelAddCallback} from "../../reflex/statsChannelUpdate.js";
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
     builder
-    .setName("set")
-    .setDescription("Adds or edits a channel which will update when members join or leave")
-    .addChannelOption(option => option.setName("channel").setDescription("The channel to modify").addChannelTypes([
-        ChannelType.GuildNews, ChannelType.GuildText
-    ]).setRequired(true))
-    .addStringOption(option => option.setName("name").setDescription("The channel name").setRequired(true).setAutocomplete(true))
+    .setName("stats")
+    .setDescription("Controls channels which update when someone joins or leaves the server")
+    .addChannelOption(option => option.setName("channel").setDescription("The channel to modify"))
+    .addStringOption(option => option.setName("name").setDescription("The new channel name | Enter any text or use the extra variables like {memberCount}").setAutocomplete(true))
 
 const callback = async (interaction: CommandInteraction): Promise<any> => {
-    console.log(interaction.options.getString("name"))
     let m;
     m = await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Loading")
         .setStatus("Danger")
         .setEmoji("NUCLEUS.LOADING")
     ], ephemeral: true, fetchReply: true});
-    if (interaction.options.getChannel("channel")) {
-        let config = client.database.guilds.read(interaction.guild.id);
+    if (interaction.options.getString("name")) {
         let channel
         try {
             channel = interaction.options.getChannel("channel")
@@ -106,13 +102,47 @@
             ], components: []});
         }
         await statsChannelAddCallback(client, interaction.member);
-        return interaction.editReply({embeds: [new EmojiEmbed()
+    }
+    while (true) {
+        let config = await client.database.guilds.read(interaction.guild.id);
+        let stats = config.getKey("stats")
+        let selectMenu = new MessageSelectMenu()
+            .setCustomId("remove")
+            .setMinValues(1)
+            .setMaxValues(Math.max(1, Object.keys(stats).length))
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setTitle("Stats Channel")
-            .setDescription(`The stats channel has been set to <#${channel.id}>`)
+            .setDescription("The following channels update when someone joins or leaves the server. You can select a channel to remove it from the list.")
             .setStatus("Success")
             .setEmoji("CHANNEL.TEXT.CREATE")
-        ], components: []});
+        ], components: [
+            new MessageActionRow().addComponents(Object.keys(stats).length ? [
+                selectMenu.setPlaceholder("Select a stats channel to remove, stopping it updating").addOptions(Object.keys(stats).map(key => ({
+                    label: interaction.guild.channels.cache.get(key).name,
+                    value: key,
+                    description: `${stats[key].name}`,
+                })))
+            ] : [selectMenu.setPlaceholder("The server has no stats channels").setDisabled(true).setOptions([
+                {label: "*Placeholder*", value: "placeholder", description: "No stats channels"}
+            ])])
+        ]})
+        let i;
+        try {
+            i = await m.awaitMessageComponent({ time: 300000 });
+        } catch (e) { break }
+        i.deferUpdate()
+        if (i.customId === "remove") {
+            let toRemove = i.values;
+            console.log(toRemove.map(k => `stats.${k}`))
+            await client.database.guilds.write(interaction.guild.id, {}, toRemove.map(k => `stats.${k}`));
+        }
     }
+    await interaction.editReply({embeds: [new EmojiEmbed()
+        .setTitle("Stats Channel")
+        .setDescription("The following channels update when someone joins or leaves the server. You can select a channel to remove it from the list.")
+        .setStatus("Danger")
+        .setEmoji("CHANNEL.TEXT.DELETE")
+    ], components: []})
 }
 
 const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
@@ -123,4 +153,4 @@
 
 export { command };
 export { callback };
-export { check };
+export { check };
\ No newline at end of file
diff --git a/src/commands/settings/stats/_meta.ts b/src/commands/settings/stats/_meta.ts
deleted file mode 100644
index 7443a9e..0000000
--- a/src/commands/settings/stats/_meta.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-const name = "stats";
-const description = "Settings for stats channels";
-
-export { name, description };
\ No newline at end of file
diff --git a/src/commands/settings/stats/remove.ts b/src/commands/settings/stats/remove.ts
deleted file mode 100644
index 8e3a64a..0000000
--- a/src/commands/settings/stats/remove.ts
+++ /dev/null
@@ -1,120 +0,0 @@
-import { ChannelType } from 'discord-api-types';
-import Discord, { CommandInteraction, MessageActionRow, MessageButton } from "discord.js";
-import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
-import confirmationMessage from "../../../utils/confirmationMessage.js";
-import getEmojiByName from "../../../utils/getEmojiByName.js";
-import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
-import { WrappedCheck } from "jshaiku";
-import client from "../../../utils/client.js";
-
-const command = (builder: SlashCommandSubcommandBuilder) =>
-    builder
-    .setName("remove")
-    .setDescription("Stops updating channels when a member joins or leaves")
-    .addChannelOption(option => option.setName("channel").setDescription("The channel to stop updating").addChannelTypes([
-        ChannelType.GuildNews, ChannelType.GuildText
-    ]).setRequired(true))
-
-const callback = async (interaction: CommandInteraction): Promise<any> => {
-    let m;
-    m = await interaction.reply({embeds: [new EmojiEmbed()
-        .setTitle("Loading")
-        .setStatus("Danger")
-        .setEmoji("NUCLEUS.LOADING")
-    ], ephemeral: true, fetchReply: true});
-    if (interaction.options.getChannel("channel")) {
-        let config = client.database.guilds.read(interaction.guild.id);
-        let channel
-        try {
-            channel = interaction.options.getChannel("channel")
-        } catch {
-            return await interaction.editReply({embeds: [new EmojiEmbed()
-                .setEmoji("CHANNEL.TEXT.DELETE")
-                .setTitle("Stats Channel")
-                .setDescription("The channel you provided is not a valid channel")
-                .setStatus("Danger")
-            ]})
-        }
-        channel = channel as Discord.TextChannel
-        if (channel.guild.id != interaction.guild.id) {
-            return interaction.editReply({embeds: [new EmojiEmbed()
-                .setTitle("Stats Channel")
-                .setDescription(`You must choose a channel in this server`)
-                .setStatus("Danger")
-                .setEmoji("CHANNEL.TEXT.DELETE")
-            ]});
-        }
-        // check if the channel is not in the list
-        let allow = false;
-        for (let c of config.stats) { if (c.channel == channel.id) allow = true; }
-        if (!allow) {
-            return interaction.editReply({embeds: [new EmojiEmbed()
-                .setTitle("Stats Channel")
-                .setDescription(`That channel is not a stats channel`)
-                .setStatus("Danger")
-                .setEmoji("CHANNEL.TEXT.DELETE")
-            ]});
-        }
-        let confirmation = await new confirmationMessage(interaction)
-            .setEmoji("CHANNEL.TEXT.EDIT")
-            .setTitle("Stats Channel")
-            .setDescription(`Are you sure you want to stop <#${channel.id}> updating?`)
-            .setColor("Warning")
-            .setInverted(true)
-        .send(true)
-        if (confirmation.cancelled) return
-        if (confirmation.success) {
-            try {
-                let channel = interaction.options.getChannel("channel")
-                await client.database.guilds.write(interaction.guild.id, {}, [`stats.${channel.id}`]);
-                const { log, NucleusColors, entry, renderUser, renderChannel } = client.logger
-                try {
-                    let data = {
-                        meta:{
-                            type: 'statsChannelUpdate',
-                            displayName: 'Stats Channel Removed',
-                            calculateType: 'nucleusSettingsUpdated',
-                            color: NucleusColors.red,
-                            emoji: "CHANNEL.TEXT.EDIT",
-                            timestamp: new Date().getTime()
-                        },
-                        list: {
-                            memberId: entry(interaction.user.id, `\`${interaction.user.id}\``),
-                            changedBy: entry(interaction.user.id, renderUser(interaction.user)),
-                            channel: entry(channel.id, renderChannel(channel)),
-                        },
-                        hidden: {
-                            guild: interaction.guild.id
-                        }
-                    }
-                    log(data);
-                } catch {}
-            } catch (e) {
-                console.log(e)
-                return interaction.editReply({embeds: [new EmojiEmbed()
-                    .setTitle("Stats Channel")
-                    .setDescription(`Something went wrong and the stats channel could not be reset`)
-                    .setStatus("Danger")
-                    .setEmoji("CHANNEL.TEXT.DELETE")
-                ], components: []});
-            }
-        } else {
-            return interaction.editReply({embeds: [new EmojiEmbed()
-                .setTitle("Stats Channel")
-                .setDescription(`No changes were made`)
-                .setStatus("Success")
-                .setEmoji("CHANNEL.TEXT.CREATE")
-            ], components: []});
-        }
-    }
-}
-
-const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
-    let member = (interaction.member as Discord.GuildMember)
-    if (!member.permissions.has("MANAGE_GUILD")) throw "You must have the Manage Server permission to use this command"
-    return true;
-}
-
-export { command };
-export { callback };
-export { check };
diff --git a/src/commands/tags/delete.ts b/src/commands/tags/delete.ts
index 74ebb25..f531e93 100644
--- a/src/commands/tags/delete.ts
+++ b/src/commands/tags/delete.ts
@@ -40,8 +40,9 @@
         .setEmoji("PUNISH.NICKNAME.GREEN")
     ]});
     try {
-        await client.database.guilds.write(interaction.guild.id, null, [`tags.${name}`]);
+        await client.database.guilds.write(interaction.guild.id, null, ["tags." + name]);
     } catch (e) {
+        console.log(e)
         return await interaction.editReply({embeds: [new EmojiEmbed()
             .setTitle("Tag Delete")
             .setDescription("Something went wrong and the tag was not deleted")
diff --git a/src/config/default.json b/src/config/default.json
index 2f95e94..93b571f 100644
--- a/src/config/default.json
+++ b/src/config/default.json
@@ -15,11 +15,6 @@
             "words": {
                 "strict": [],
                 "loose": []
-            },
-            "allowed": {
-                "users": [],
-                "roles": [],
-                "channels": []
             }
         },
         "invite": {
@@ -33,21 +28,11 @@
         "pings": {
             "mass": 5,
             "everyone": true,
-            "roles": true,
-            "allowed": {
-                "roles": [],
-                "rolesToMention": [],
-                "users": [],
-                "channels": []
-            }
+            "roles": true
         }
     },
     "welcome": {
         "enabled": false,
-        "verificationRequired": {
-            "message": null,
-            "role": null
-        },
         "welcomeRole": null,
         "channel": null,
         "message": null
@@ -57,12 +42,7 @@
         "logs": {
             "enabled": true,
             "channel": null,
-            "toLog": "3fffff",
-            "ignore": {
-                "users": [],
-                "roles": [],
-                "channels": []
-            }
+            "toLog": "3fffff"
         },
         "staff": {
             "channel": null
@@ -107,8 +87,9 @@
             "text": null,
             "link": null
         },
-        "role": {
-            "role": null
+        "nickname": {
+            "text": null,
+            "link": null
         }
     },
     "tracks": [],
diff --git a/src/config/emojis.json b/src/config/emojis.json
index 7024a73..49c2b27 100644
--- a/src/config/emojis.json
+++ b/src/config/emojis.json
@@ -144,28 +144,28 @@
     "PUNISH": {
         "WARN": {
             "RED": "947433493384806430",
-            "GREEN": "947433504076091424",
-            "YELLOW": "729764054897524768"
+            "YELLOW": "729764054897524768",
+            "GREEN": "947433504076091424"
         },
         "KICK": {
             "RED": "729764053794422896",
-            "GREEN": "947428786692042764",
-            "YELLOW": "947429333289562132"
+            "YELLOW": "947429333289562132",
+            "GREEN": "947428786692042764"
         },
         "BAN": {
             "RED": "729764053861400637",
-            "GREEN": "947421674364629022",
-            "YELLOW": "729764053941223476"
+            "YELLOW": "729764053941223476",
+            "GREEN": "947421674364629022"
         },
         "UNBAN": {
-            "GREEN": "729263536840114216",
+            "RED": "972511610885255259",
             "YELLOW": "972511620343414794",
-            "RED": "972511610885255259"
+            "GREEN": "729263536840114216"
         },
         "MUTE": {
             "RED": "947555098974883910",
-            "GREEN": "947555107980066866",
-            "YELLOW": "729764053865463840"
+            "YELLOW": "729764053865463840",
+            "GREEN": "947555107980066866"
         },
         "SOFTBAN": "729764053941223476",
         "VOICEMUTE": "729764054855450697",
diff --git a/src/events/interactionCreate.ts b/src/events/interactionCreate.ts
index 900c774..eaf4fea 100644
--- a/src/events/interactionCreate.ts
+++ b/src/events/interactionCreate.ts
@@ -38,7 +38,7 @@
     } else if (interaction.type === "APPLICATION_COMMAND_AUTOCOMPLETE") {
         switch (`${interaction.commandName} ${interaction.options.getSubcommandGroup(false)} ${interaction.options.getSubcommand(false)}`) {
             case `tag null null`: { return interaction.respond(getAutocomplete(interaction.options.getString("tag"), (await tagAutocomplete(interaction)))) }
-            case `settings stats set`: { return interaction.respond(generateStatsChannelAutocomplete(interaction.options.getString("name"))) }
+            case `settings null stats`: { return interaction.respond(generateStatsChannelAutocomplete(interaction.options.getString("name"))) }
         }
     }
 }
diff --git a/src/events/memberJoin.ts b/src/events/memberJoin.ts
index 7bee084..109f226 100644
--- a/src/events/memberJoin.ts
+++ b/src/events/memberJoin.ts
@@ -7,6 +7,7 @@
 
 export async function callback(_, member) {
     try { welcome(_, member); } catch {}
+    try { statsChannelAdd(_, member, ); } catch {}
     try {
         const { log, NucleusColors, entry, renderUser, renderDelta } = member.client.logger
         try { await client.database.history.create("join", member.guild.id, member.user, null, null) } catch {}
@@ -32,5 +33,4 @@
         }
         log(data);
     } catch {}
-    try { statsChannelAdd(_, member, ); } catch {}
 }
diff --git a/src/reflex/statsChannelUpdate.ts b/src/reflex/statsChannelUpdate.ts
index 51d4329..7d04c8f 100644
--- a/src/reflex/statsChannelUpdate.ts
+++ b/src/reflex/statsChannelUpdate.ts
@@ -5,7 +5,6 @@
 interface PropSchema { enabled: boolean, name: string }
 
 export async function callback(_, member) {
-    console.log("UPDATING STATS CHANNEL")
     let guild = await client.guilds.fetch(member.guild.id)
     let config = await client.database.guilds.read(guild.id);
     Object.entries(config.getKey("stats")).forEach(async ([channel, props]) => {
diff --git a/src/utils/database.ts b/src/utils/database.ts
index 5b1d6d9..d24c7bf 100644
--- a/src/utils/database.ts
+++ b/src/utils/database.ts
@@ -43,12 +43,12 @@
     async write(guild: string, set: object = {}, unset: string[] = []) {
         let uo = {}
         for (let key of unset) {
-            uo[key] = "";
+            uo[key] = null;
         }
-        await this.guilds.updateOne({ id: guild }, {
-            $unset: uo,
-            $set: set
-        }, { upsert: true });
+        let out = {}
+        if (set) out["$set"] = set;
+        if (unset.length) out["$unset"] = uo;
+        await this.guilds.updateOne({ id: guild }, out, { upsert: true });
     }
 
     async append(guild: string, key: string, value: any) {
@@ -63,13 +63,13 @@
         }
     }
 
-    async remove(guild: string, key: string, value: any, innerKey?: string) {
+    async remove(guild: string, key: string, value: any, innerKey?: string | null) {
+        console.log(Array.isArray(value))
         if (innerKey) {
             await this.guilds.updateOne({ id: guild }, {
                 $pull: { [key]: { [innerKey]: { $eq: value } } }
             }, { upsert: true });
-        }
-        else if (Array.isArray(value)) {
+        } else if (Array.isArray(value)) {
             await this.guilds.updateOne({ id: guild }, {
                 $pullAll: { [key]: value }
             }, { upsert: true });