Merge branch 'development' of ssh.pinea.dev:Pinea/Nucleus into development
diff --git a/TODO b/TODO
index 2a0d7be..3316dd2 100644
--- a/TODO
+++ b/TODO
@@ -1,2 +1,3 @@
 Server rules
-verificationRequired on welcome
\ No newline at end of file
+verificationRequired on welcome
+!!Premium
diff --git a/src/commands/mod/ban.ts b/src/commands/mod/ban.ts
index 0ee663f..e8309fb 100644
--- a/src/commands/mod/ban.ts
+++ b/src/commands/mod/ban.ts
@@ -5,6 +5,7 @@
 import addPlurals from "../../utils/plurals.js";
 import client from "../../utils/client.js";
 import { LinkWarningFooter } from "../../utils/defaults.js";
+import getEmojiByName from "../../utils/getEmojiByName.js";
 
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
@@ -133,6 +134,9 @@
                 accountCreated: entry(member.user.createdTimestamp, renderDelta(member.user.createdTimestamp)),
                 serverMemberCount: interaction.guild.memberCount
             },
+            separate: {
+                end: getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) + ` The user was ${notify ? "" : "not "}notified`
+            },
             hidden: {
                 guild: interaction.guild.id
             }
diff --git a/src/commands/mod/kick.ts b/src/commands/mod/kick.ts
index 9f1ee41..059bdb2 100644
--- a/src/commands/mod/kick.ts
+++ b/src/commands/mod/kick.ts
@@ -7,6 +7,7 @@
 import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
 import client from "../../utils/client.js";
+import getEmojiByName from "../../utils/getEmojiByName.js";
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
     builder
@@ -125,6 +126,9 @@
                 timeInServer: timeInServer,
                 serverMemberCount: member.guild.memberCount
             },
+            separate: {
+                end: getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) + ` The user was ${notify ? "" : "not "}notified`
+            },
             hidden: {
                 guild: member.guild.id
             }
diff --git a/src/commands/mod/mute.ts b/src/commands/mod/mute.ts
index 878d696..c795456 100644
--- a/src/commands/mod/mute.ts
+++ b/src/commands/mod/mute.ts
@@ -338,6 +338,9 @@
             mutedBy: entry(interaction.member!.user.id, renderUser(interaction.member!.user as Discord.User)),
             reason: entry(reason, reason ? reason : "*No reason provided*")
         },
+        separate: {
+            end: getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) + ` The user was ${notify ? "" : "not "}notified`
+        },
         hidden: {
             guild: interaction.guild.id
         }
diff --git a/src/commands/mod/nick.ts b/src/commands/mod/nick.ts
index 8fb1cc1..97f783a 100644
--- a/src/commands/mod/nick.ts
+++ b/src/commands/mod/nick.ts
@@ -6,6 +6,7 @@
 import keyValueList from "../../utils/generateKeyValueList.js";
 import client from "../../utils/client.js";
 import { areTicketsEnabled, create } from "../../actions/createModActionTicket.js";
+import getEmojiByName from "../../utils/getEmojiByName.js";
 
 
 const command = (builder: SlashCommandSubcommandBuilder) => builder
@@ -165,6 +166,9 @@
             updated: entry(Date.now(), renderDelta(Date.now())),
             updatedBy: entry(interaction.user.id, renderUser(interaction.user))
         },
+        separate: {
+            end: getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) + ` The user was ${notify ? "" : "not "}notified`
+        },
         hidden: {
             guild: interaction.guild!.id
         }
diff --git a/src/commands/mod/purge.ts b/src/commands/mod/purge.ts
index cabcb1e..8d49c3b 100644
--- a/src/commands/mod/purge.ts
+++ b/src/commands/mod/purge.ts
@@ -309,7 +309,7 @@
             }
         };
         log(data);
-        let out = "";
+        let out = "";  // TODO: messageException throughout this file
         messages.reverse().forEach((message) => {
             if (!message) {
                 out += "Unknown message\n\n"
diff --git a/src/commands/mod/softban.ts b/src/commands/mod/softban.ts
index fa9f11b..1b404c9 100644
--- a/src/commands/mod/softban.ts
+++ b/src/commands/mod/softban.ts
@@ -6,6 +6,7 @@
 import addPlurals from "../../utils/plurals.js";
 import client from "../../utils/client.js";
 import { LinkWarningFooter } from "../../utils/defaults.js";
+import getEmojiByName from "../../utils/getEmojiByName.js";
 
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
@@ -135,6 +136,9 @@
                 accountCreated: entry(member.user.createdTimestamp, renderDelta(member.user.createdTimestamp)),
                 serverMemberCount: interaction.guild.memberCount
             },
+            separate: {
+                end: getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) + ` The user was ${notify ? "" : "not "}notified`
+            },
             hidden: {
                 guild: interaction.guild.id
             }
diff --git a/src/commands/mod/unmute.ts b/src/commands/mod/unmute.ts
index 44f807d..8562c4c 100644
--- a/src/commands/mod/unmute.ts
+++ b/src/commands/mod/unmute.ts
@@ -4,6 +4,7 @@
 import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
 import client from "../../utils/client.js";
+import getEmojiByName from "../../utils/getEmojiByName.js";
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
     builder
@@ -113,6 +114,9 @@
             unmuted: entry(Date.now().toString(), renderDelta(Date.now())),
             unmutedBy: entry(interaction.user.id, renderUser(interaction.user))
         },
+        separate: {
+            end: getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) + ` The user was ${notify ? "" : "not "}notified`
+        },
         hidden: {
             guild: interaction.guild.id
         }
diff --git a/src/commands/mod/warn.ts b/src/commands/mod/warn.ts
index 35b5400..ea4f084 100644
--- a/src/commands/mod/warn.ts
+++ b/src/commands/mod/warn.ts
@@ -5,6 +5,7 @@
 import keyValueList from "../../utils/generateKeyValueList.js";
 import { create, areTicketsEnabled } from "../../actions/createModActionTicket.js";
 import client from "../../utils/client.js";
+import getEmojiByName from "../../utils/getEmojiByName.js";
 import { LinkWarningFooter } from "../../utils/defaults.js";
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
@@ -124,7 +125,10 @@
                 renderUser((interaction.options.getMember("user") as GuildMember).user)
             ),
             warnedBy: entry(interaction.member!.user.id, renderUser(interaction.member!.user as Discord.User)),
-            reason: reason ? `\n> ${reason}` : "*No reason provided*"
+            reason: reason ? reason : "*No reason provided*"
+        },
+        separate: {
+            end: getEmojiByName("ICONS.NOTIFY." + (notify ? "ON" : "OFF")) + ` The user was ${notify ? "" : "not "}notified`
         },
         hidden: {
             guild: interaction.guild.id
diff --git a/src/commands/nucleus/premium.ts b/src/commands/nucleus/premium.ts
index 354c303..026984d 100644
--- a/src/commands/nucleus/premium.ts
+++ b/src/commands/nucleus/premium.ts
@@ -3,28 +3,26 @@
 import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import client from "../../utils/client.js";
 import { LoadingEmbed } from "../../utils/defaults.js";
+import getEmojiByName from "../../utils/getEmojiByName.js";
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
     builder.setName("premium").setDescription("Information about Nucleus Premium");
-
+//TODO: Allow User to remove Premium
 const callback = async (interaction: CommandInteraction): Promise<void> => {
     await interaction.reply({embeds: LoadingEmbed, ephemeral: true})
-    const member = (await interaction.client.guilds.fetch("684492926528651336")).members.cache.get(interaction.user.id)
-    const firstDescription = "\n\nPremium allows your server to get access to extra features, for a fixed price per month.\nThis includes:\n" +
-        "- Attachment logs - Stores attachments so they can be viewed after a message is deleted.\n" +
-        "- Ticket Transcripts - Gives a link to view the history of a ticket after it has been closed.\n"
-    if(!member) {
+    const member = await (await interaction.client.guilds.fetch("684492926528651336")).members.fetch(interaction.user.id).catch(() => {
         interaction.editReply({ embeds: [
             new EmojiEmbed()
                 .setTitle("Premium")
-                .setDescription(
-                    `*You are not currently in the Clicks Server. To gain access to premium please join.*` + firstDescription
-                )
+                .setDescription(`*You are not currently in the Clicks Server. To gain access to premium please join.*` + firstDescription)
                 .setEmoji("NUCLEUS.LOGO")
                 .setStatus("Danger")
         ], components: [new ActionRowBuilder<ButtonBuilder>().addComponents(new ButtonBuilder().setStyle(ButtonStyle.Link).setLabel("Join").setURL("https://discord.gg/bPaNnxe"))] });
-        return;
-    }
+    })
+    if (!member) return;
+    const firstDescription = "\n\nPremium allows servers of your choice to get access to extra features for a fixed price per month.\nThis includes:\n" +
+        `${getEmojiByName("MOD.IMAGES.TOOSMALL")}  Attachment logs - Stores attachments so they can be viewed after a message is deleted.\n` +
+        `${getEmojiByName("GUILD.TICKET.ARCHIVED")}  Ticket Transcripts - Gives a link to view the history of a ticket after it has been closed.\n`
     const dbMember = await client.database.premium.fetchUser(interaction.user.id)
     let premium = `You do not have premium! You can't activate premium on any servers.`;
     let count = 0;
@@ -33,19 +31,47 @@
         premium = `You have Infinite Premium! You have been gifted this by the developers as a thank you. You can give premium to any and all servers you are in.`;
         count = 200;
     } else if (level === 1) {
-        premium = `You have Premium tier 1! You can give premium to ${1 - appliesTo.length} more servers.`;
+        premium = `You have Premium tier 1! You can give premium to ${1 - appliesTo.length} more server(s).`;
         count = 1;
     } else if (level === 2) {
-        premium = `You have Premium tier 2! You can give premium to ${3 - appliesTo.length} more servers.`;
+        premium = `You have Premium tier 2! You can give premium to ${3 - appliesTo.length} more server(s).`;
         count = 3;
     } else if (level === 3) {
-        premium = `You have Premium Mod! You can give premium to ${3 - appliesTo.length} more servers, as well as automatically giving premium to all servers you have a "manage" permission in.`
+        premium = `You have Premium Mod! You can give premium to ${3 - appliesTo.length} more server(s), as well as automatically giving premium to all servers you have a "manage" permission in.`
         count = 3;
     }
+    if (dbMember?.expiresAt) {
+        premium = `**You can't give servers premium anymore because your subscription ended or was cancelled.** To get premium again please subscribe in the Clicks server`
+        count = 0;
+    }
     const hasPremium = await client.database.premium.hasPremium(interaction.guild!.id);
     let premiumGuild = ""
-    if (hasPremium) {
-        premiumGuild = `\n\n**This server has premium!**`
+    if (hasPremium) { //FIXME: Check how user applied premium
+        premiumGuild = `**This server has premium! It was ${hasPremium[2] === 3 ? `automatically applied by <@${hasPremium[1]}>` : `given by <@${hasPremium[1]}>`}**\n\n`
+    }
+
+    const components: ActionRowBuilder<ButtonBuilder>[] = []
+    if (level === 0 || dbMember?.expiresAt) {
+        components.push(
+            new ActionRowBuilder<ButtonBuilder>()
+                .addComponents(
+                    new ButtonBuilder()
+                    .setStyle(ButtonStyle.Link)
+                    .setLabel("Join Clicks")
+                    .setURL("https://discord.gg/bPaNnxe")
+                )
+        )
+    } else {
+        components.push(
+            new ActionRowBuilder<ButtonBuilder>()
+                .addComponents(
+                    new ButtonBuilder()
+                        .setStyle(premiumGuild.length > 0 ? ButtonStyle.Secondary : ButtonStyle.Success)
+                        .setLabel(premiumGuild.length > 0 ? "This server has premium" : "Activate premium here")
+                        .setCustomId("premiumActivate")
+                        .setDisabled(count <= 0 || (hasPremium ? hasPremium[0] : false))
+                )
+        )
     }
 
     interaction.editReply({
@@ -53,21 +79,13 @@
             new EmojiEmbed()
                 .setTitle("Premium")
                 .setDescription(
-                    premium + firstDescription + premiumGuild
+                    premiumGuild + premium + firstDescription
                 )
                 .setEmoji("NUCLEUS.LOGO")
                 .setStatus("Danger")
+                // .setImage("") //TODO: Add image
         ],
-        components: [
-            new ActionRowBuilder<ButtonBuilder>()
-                .addComponents(
-                    new ButtonBuilder()
-                        .setStyle(ButtonStyle.Primary)
-                        .setLabel("Activate Premium here")
-                        .setCustomId("premiumActivate")
-                        .setDisabled(count <= 0 && hasPremium)
-                )
-        ]
+        components: components
     });
 
     const filter = (i: ButtonInteraction) => i.customId === "premiumActivate" && i.user.id === interaction.user.id;
diff --git a/src/commands/privacy.ts b/src/commands/privacy.ts
index 8803e25..46784f5 100644
--- a/src/commands/privacy.ts
+++ b/src/commands/privacy.ts
@@ -48,15 +48,13 @@
                 new EmojiEmbed()
                     .setTitle("Link scanning and Transcripts")
                     .setDescription(
-                        "**Facebook** - Facebook trackers include data such as your date of birth, and guess your age if not entered, your preferences, who you interact with and more.\n" +
-                            "**AMP** - AMP is a technology that allows websites to be served by Google. This means Google can store and track data, and are pushing this to as many pages as possible.\n\n" +
-                            "Transcripts allow you to store all messages sent in a channel. This is stored in our database along with the rest of the servers settings but is accessible by anyone with the link, so a leaked link could show all messages sent in the channel.\n"
+                            "Transcripts allow you to store all messages sent in a channel. Transcripts are stored in our database along with the rest of the server's settings but is accessible by anyone with the link, so a leaked link could show all messages sent in the channel.\n"
                     )
                     .setEmoji("NUCLEUS.LOGO")
                     .setStatus("Danger")
             )
             .setTitle("Link scanning and Transcripts")
-            .setDescription("Regarding Facebook and AMP filter types, and ticket transcripts")
+            .setDescription("Information about how links and images are scanned, and transcripts are stored")
             .setPageId(2)
     ].concat(
         (interaction.member as Discord.GuildMember).permissions.has("Administrator")
diff --git a/src/commands/settings/logs/attachment.ts b/src/commands/settings/logs/attachment.ts
index 8331043..c04c7cf 100644
--- a/src/commands/settings/logs/attachment.ts
+++ b/src/commands/settings/logs/attachment.ts
@@ -1,5 +1,5 @@
 import { LoadingEmbed } from "../../../utils/defaults.js";
-import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelSelectMenuBuilder } from "discord.js";
+import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelSelectMenuBuilder, ChannelType } from "discord.js";
 import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../../../utils/getEmojiByName.js";
 import type { SlashCommandSubcommandBuilder } from "discord.js";
@@ -38,6 +38,7 @@
                 new ChannelSelectMenuBuilder()
                     .setCustomId("channel")
                     .setPlaceholder("Select a channel")
+                    .setChannelTypes(ChannelType.GuildText)
             );
         const buttons = new ActionRowBuilder<ButtonBuilder>()
             .addComponents(
@@ -58,7 +59,7 @@
         const embed = new EmojiEmbed()
             .setTitle("Attachments")
             .setDescription(
-                `The channel to send all attachments from the server, allowing you to check them if they are deleted` +
+                `The channel to send all attachments from the server, allowing you to check them if they are deleted\n` +
                 `**Channel:** ${channel ? `<#${channel}>` : "*None*"}\n`
             )
             .setStatus("Success")
diff --git a/src/commands/settings/logs/warnings.ts b/src/commands/settings/logs/warnings.ts
index 24249a2..84772e6 100644
--- a/src/commands/settings/logs/warnings.ts
+++ b/src/commands/settings/logs/warnings.ts
@@ -1,5 +1,5 @@
 import { LoadingEmbed } from "../../../utils/defaults.js";
-import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelSelectMenuBuilder } from "discord.js";
+import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelSelectMenuBuilder, ChannelType } from "discord.js";
 import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../../../utils/getEmojiByName.js";
 import type { SlashCommandSubcommandBuilder } from "discord.js";
@@ -27,6 +27,7 @@
             new ChannelSelectMenuBuilder()
                 .setCustomId("channel")
                 .setPlaceholder("Select a channel")
+                .setChannelTypes(ChannelType.GuildText)
         );
         const buttons = new ActionRowBuilder<ButtonBuilder>()
             .addComponents(
diff --git a/src/config/emojis.json b/src/config/emojis.json
index 35743e1..ecf1858 100644
--- a/src/config/emojis.json
+++ b/src/config/emojis.json
@@ -28,7 +28,7 @@
         "REORDER": "1069323453909454890",
         "NOTIFY": {
             "ON": "1000726394579464232",
-            "OFF": "1000726363495477368"
+            "OFF": "1078058136092541008"
         },
         "OPP": {
             "ADD": "837355918831124500",
diff --git a/src/context/messages/purgeto.ts b/src/context/messages/purgeto.ts
index 4627bf2..02d5d2a 100644
--- a/src/context/messages/purgeto.ts
+++ b/src/context/messages/purgeto.ts
@@ -5,6 +5,7 @@
 import client from "../../utils/client.js";
 import getEmojiByName from '../../utils/getEmojiByName.js';
 import { JSONTranscriptFromMessageArray, JSONTranscriptToHumanReadable } from "../../utils/logTranscripts.js";
+import { messageException } from '../../utils/createTemporaryStorage.js';
 
 const command = new ContextMenuCommandBuilder()
     .setName("Purge up to here")
@@ -185,6 +186,7 @@
     };
     log(data);
     const messages: Message[] = deleted.map(m => m).filter(m => m instanceof Message).map(m => m as Message);
+    if (messages.length === 1) messageException(interaction.guild!.id, interaction.channel.id, messages[0]!.id)
     const transcript = JSONTranscriptToHumanReadable(JSONTranscriptFromMessageArray(messages)!);
     const attachmentObject = {
         attachment: Buffer.from(transcript),
diff --git a/src/context/users/userinfo.ts b/src/context/users/userinfo.ts
index 3b1a6bd..496f84e 100644
--- a/src/context/users/userinfo.ts
+++ b/src/context/users/userinfo.ts
@@ -5,6 +5,7 @@
     .setName("User info")
 
 const callback = async (interaction: UserContextMenuCommandInteraction) => {
+    console.log("callback")
     const guild = interaction.guild!
     let member = interaction.targetMember
     if (!member) member = await guild.members.fetch(interaction.targetId)
@@ -12,6 +13,7 @@
 }
 
 const check = async (_interaction: UserContextMenuCommandInteraction) => {
+    console.log("check")
     return true;
 }
 
diff --git a/src/events/guildMemberUpdate.ts b/src/events/guildMemberUpdate.ts
index 5788f61..721978f 100644
--- a/src/events/guildMemberUpdate.ts
+++ b/src/events/guildMemberUpdate.ts
@@ -7,6 +7,9 @@
 
 export async function callback(client: NucleusClient, before: GuildMember, after: GuildMember) {
     const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = client.logger;
+    if(before.guild.id === "684492926528651336") {
+        await client.database.premium.checkAllPremium(after)
+    }
 
     if(!before.roles.cache.equals(after.roles.cache)) {
         const auditLog = (await getAuditLog(after.guild, AuditLogEvent.MemberRoleUpdate))
diff --git a/src/events/webhookUpdate.ts b/src/events/webhookUpdate.ts
index fb18f48..004f754 100644
--- a/src/events/webhookUpdate.ts
+++ b/src/events/webhookUpdate.ts
@@ -13,16 +13,15 @@
         const { getAuditLog, isLogging, log, NucleusColors, entry, renderUser, renderChannel, renderDelta } = client.logger;
         if (!await isLogging(channel.guild.id, "webhookUpdate")) return;
         const auditCreate = (await getAuditLog(channel.guild, AuditLogEvent.WebhookCreate))
-            .filter((entry: GuildAuditLogsEntry) => (entry.target as Webhook)!.id === channel.id)[0]!;
-        const auditDelete = (await getAuditLog(channel.guild, AuditLogEvent.WebhookDelete))
-            .filter((entry: GuildAuditLogsEntry) => (entry.target as Webhook)!.id === channel.id)[0];
-        const auditUpdate = (await getAuditLog(channel.guild, AuditLogEvent.WebhookUpdate))
-            .filter((entry: GuildAuditLogsEntry) => (entry.target as Webhook)!.id === channel.id)[0];
-
-        if (!auditUpdate && !auditDelete) return;
+            .filter((entry: GuildAuditLogsEntry | null) => (entry?.target) ? (entry.target as Webhook)!.channelId === channel.id : false)[0];
+        const auditDelete = (await getAuditLog(channel.guild, AuditLogEvent.WebhookDelete, 0))
+            .filter((entry: GuildAuditLogsEntry | null) => (entry?.target) ? (entry.target as Webhook)!.channelId === channel.id : false)[0];
+        const auditUpdate = (await getAuditLog(channel.guild, AuditLogEvent.WebhookUpdate, 0))
+            .filter((entry: GuildAuditLogsEntry | null) => (entry?.target) ? (entry.target as Webhook)!.channelId === channel.id : false)[0];
+        if (!auditCreate && !auditUpdate && !auditDelete) return;
         let action: "Create" | "Update" | "Delete" = "Create";
         let list: Record<string, ReturnType<typeof entry> | string> = {};
-        const createTimestamp = auditCreate.createdTimestamp;
+        const createTimestamp = auditCreate ? auditCreate.createdTimestamp : 0;
         const deleteTimestamp = auditDelete ? auditDelete.createdTimestamp : 0;
         const updateTimestamp = auditUpdate ? auditUpdate.createdTimestamp : 0;
         if (updateTimestamp > createTimestamp && updateTimestamp > deleteTimestamp && auditUpdate) {
@@ -81,8 +80,8 @@
                 name: entry(before["name"]!, `${before["name"]}`),
                 channel: entry(before["channel_id"]!, renderChannel(await client.channels.fetch(before["channel_id"]!) as GuildChannel)),
                 createdBy: entry(
-                    auditCreate.executor!.id,
-                    renderUser((await channel.guild.members.fetch(auditCreate.executor!.id)).user)
+                    auditCreate!.executor!.id,
+                    renderUser((await channel.guild.members.fetch(auditCreate!.executor!.id)).user)
                 ),
                 created: entry(Date.now(), renderDelta(Date.now()))
             };
diff --git a/src/index.ts b/src/index.ts
index 3c132bc..12f6659 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -13,10 +13,9 @@
     } else {
         client.fetchedCommands = await client.application?.commands.fetch()!;
     }
-    setInterval(async () => {
-        await client.database.premium.checkAllPremium();
-    }, 1000 * 60 * 3);
+    await client.database.premium.checkAllPremium();
 });
+
 process.on("unhandledRejection", (err) => { console.error(err) });
 process.on("uncaughtException", (err) => { console.error(err) });
 
diff --git a/src/premium/createTranscript.ts b/src/premium/createTranscript.ts
index fb6dde7..88a8e6e 100644
--- a/src/premium/createTranscript.ts
+++ b/src/premium/createTranscript.ts
@@ -14,6 +14,7 @@
 import getEmojiByName from "../utils/getEmojiByName.js";
 import { PasteClient, Publicity, ExpireDate } from "pastebin-api";
 import client from "../utils/client.js";
+import { messageException } from '../utils/createTemporaryStorage.js';
 
 const pbClient = new PasteClient(client.config.pastebinApiKey);
 
@@ -95,6 +96,7 @@
         const deleted = await (interaction.channel as TextChannel).bulkDelete(fetched, true);
         deletedCount = deleted.size;
         messages = messages.concat(Array.from(deleted.values() as Iterable<Message>));
+        if (messages.length === 1) messageException(interaction.guild!.id, interaction.channel.id, messages[0]!.id)
     } while (deletedCount === 100);
 
     let out = "";
diff --git a/src/utils/client.ts b/src/utils/client.ts
index b05ef5f..857fb1d 100644
--- a/src/utils/client.ts
+++ b/src/utils/client.ts
@@ -32,14 +32,13 @@
         callback: (interaction: Interaction) => Promise<void>,
         check: (interaction: Interaction, partial: boolean) => Promise<boolean> | boolean,
         autocomplete: (interaction: AutocompleteInteraction) => Promise<string[]>
-    } | undefined,{name: string, description: string}]> = {};
+    } | undefined, {name: string, description: string}]> = {};
     fetchedCommands = new Collection<string, Discord.ApplicationCommand>();
     constructor(database: typeof NucleusClient.prototype.database) {
         super({ intents: 0b1100011011011111111111});
         this.database = database;
     }
 }
-
 const client = new NucleusClient({
     guilds: await new Guilds().setup(),
     history: new History(),
diff --git a/src/utils/commandRegistration/register.ts b/src/utils/commandRegistration/register.ts
index 1a19e2c..78e3b0f 100644
--- a/src/utils/commandRegistration/register.ts
+++ b/src/utils/commandRegistration/register.ts
@@ -111,7 +111,7 @@
             context.command.setNameLocalizations(context.nameLocalizations ?? {})
             commands.push(context.command);
 
-            client.commands["contextCommands/message/" + context.command.name] = context;
+            client.commands["contextCommands/message/" + context.command.name] = [context, {name: context.name ?? context.command.name, description: context.description ?? context.command.description}];
 
             console.log(`${last.replace("└", " ").replace("├", "│")}  └─ ${colors.green}Loaded ${file.name} [${i} / ${totalFiles}]${colors.none}`)
         } catch (e) {
@@ -181,6 +181,7 @@
 }
 
 async function execute(check: Function | undefined, callback: Function | undefined, data: CommandInteraction) {
+    console.log(client.commands["contextCommands/user/User info"])
     if (!callback) return;
     if (check) {
         let result;
@@ -197,7 +198,7 @@
                 .setColor(NucleusColors.red)
                 .setEmoji(getEmojiByName("CONTROL.BLOCKCROSS"))
             ], ephemeral: true});
-        };
+        }
     }
     callback(data);
 }
diff --git a/src/utils/database.ts b/src/utils/database.ts
index 239da13..e7336d0 100644
--- a/src/utils/database.ts
+++ b/src/utils/database.ts
@@ -1,3 +1,4 @@
+import type { GuildMember } from "discord.js";
 import type Discord from "discord.js";
 import { Collection, MongoClient } from "mongodb";
 import config from "../config/main.js";
@@ -245,11 +246,36 @@
         await this.premium.insertOne({ user: user, appliesTo: [], level: level });
     }
 
-    async hasPremium(guild: string) {
+    async hasPremium(guild: string): Promise<[boolean, string, number] | null> {
+        const entries = await this.premium.find({}).toArray();
+        const members = await (await client.guilds.fetch(guild)).members.fetch()
+        for(const {user} of entries) {
+            const member = members.get(user);
+            if(member) {
+                const modPerms = //TODO: Create list in config for perms
+                            member.permissions.has("Administrator") ||
+                            member.permissions.has("ManageChannels") ||
+                            member.permissions.has("ManageRoles") ||
+                            member.permissions.has("ManageEmojisAndStickers") ||
+                            member.permissions.has("ManageWebhooks") ||
+                            member.permissions.has("ManageGuild") ||
+                            member.permissions.has("KickMembers") ||
+                            member.permissions.has("BanMembers") ||
+                            member.permissions.has("ManageEvents") ||
+                            member.permissions.has("ManageMessages") ||
+                            member.permissions.has("ManageThreads")
+                const entry = entries.find(e => e.user === member.id);
+                if(entry && (entry.level === 3) && modPerms) return [true, member.id, entry.level];
+            }
+        }
         const entry = await this.premium.findOne({
-            appliesTo: { $in: [guild] }
+            appliesTo: {
+                $elemMatch: {
+                    $eq: guild
+                }
+            }
         });
-        return entry ? true : false;
+        return entry ? [true, entry.user, entry.level] : null;
     }
 
     async fetchUser(user: string): Promise<PremiumSchema | null> {
@@ -258,26 +284,55 @@
         return entry;
     }
 
-    async checkAllPremium() {
+    async checkAllPremium(member?: GuildMember) {
         const entries = await this.premium.find({}).toArray();
-        for(const {user, expiresAt} of entries) {
-            if(expiresAt) expiresAt < Date.now() ? await this.premium.deleteOne({user: user}) : null;
-            const member = await (await client.guilds.fetch("684492926528651336")).members.fetch(user)
-            let level: number = 0;
-            if (member.roles.cache.has("1066468879309750313")) {
+        if(member) {
+            const entry = entries.find(e => e.user === member.id);
+            if(entry) {
+                const expiresAt = entry.expiresAt;
+                if(expiresAt) expiresAt < Date.now() ? await this.premium.deleteOne({user: member.id}) : null;
+            }
+            const roles = member.roles;
+            let level = 0;
+            if (roles.cache.has("1066468879309750313")) {
                 level = 99;
-            } else if (member.roles.cache.has("1066465491713003520")) {
+            } else if (roles.cache.has("1066465491713003520")) {
                 level = 1;
-            } else if (member.roles.cache.has("1066439526496604194")) {
+            } else if (roles.cache.has("1066439526496604194")) {
                 level = 2;
-            } else if (member.roles.cache.has("1066464134322978912")) {
+            } else if (roles.cache.has("1066464134322978912")) {
                 level = 3;
             }
-
+            await this.updateUser(member.id, level);
             if (level > 0) {
-                await this.updateUser(user, level);
+                await this.premium.updateOne({ user: member.id }, {$unset: { expiresAt: ""}})
             } else {
-                await this.premium.updateOne({ user: user }, { expiresAt: (Date.now() + (1000*60*60*24*3)) })
+                await this.premium.updateOne({ user: member.id }, {$set: { expiresAt: (Date.now() + (1000*60*60*24*3)) }})
+            }
+        } else {
+            const members = await (await client.guilds.fetch('684492926528651336')).members.fetch();
+            for(const {roles, id} of members.values()) {
+                const entry = entries.find(e => e.user === id);
+                if(entry) {
+                    const expiresAt = entry.expiresAt;
+                    if(expiresAt) expiresAt < Date.now() ? await this.premium.deleteOne({user: id}) : null;
+                }
+                let level: number = 0;
+                if (roles.cache.has("1066468879309750313")) {
+                    level = 99;
+                } else if (roles.cache.has("1066465491713003520")) {
+                    level = 1;
+                } else if (roles.cache.has("1066439526496604194")) {
+                    level = 2;
+                } else if (roles.cache.has("1066464134322978912")) {
+                    level = 3;
+                }
+                await this.updateUser(id, level);
+                if (level > 0) {
+                    await this.premium.updateOne({ user: id }, {$unset: { expiresAt: ""}})
+                } else {
+                    await this.premium.updateOne({ user: id }, {$set: { expiresAt: (Date.now() + (1000*60*60*24*3)) }})
+                }
             }
         }
     }
diff --git a/src/utils/log.ts b/src/utils/log.ts
index 87549dd..c6416a1 100644
--- a/src/utils/log.ts
+++ b/src/utils/log.ts
@@ -72,8 +72,8 @@
         yellow: 0xf2d478,
         green: 0x68d49e
     },
-    async getAuditLog(guild: Discord.Guild, event: Discord.GuildAuditLogsResolvable): Promise<Discord.GuildAuditLogsEntry[]> {
-        await wait(250);
+    async getAuditLog(guild: Discord.Guild, event: Discord.GuildAuditLogsResolvable, delay?: number): Promise<Discord.GuildAuditLogsEntry[]> {
+        await wait(delay ?? 250);
         const auditLog = (await guild.fetchAuditLogs({ type: event })).entries.map(m => m)
         return auditLog as Discord.GuildAuditLogsEntry[];
     },