New edit and delete logs
diff --git a/src/events/interactionCreate.ts b/src/events/interactionCreate.ts
index b7eb745..3ead1c5 100644
--- a/src/events/interactionCreate.ts
+++ b/src/events/interactionCreate.ts
@@ -46,16 +46,60 @@
                     : false;
             return await modifySuggestion(interaction, value);
         }
-        if (interaction.customId === "log:edit") {
-            const attachment = interaction.message.embeds[0]?.image;
-            console.log(attachment)
+        if (interaction.customId === "log:message.edit") {
+            await interaction.channel?.messages.fetch({ message: interaction.message.id, force: true });
+            const attachment = interaction.message.embeds[0]?.image ?? interaction.message.attachments.first();
             if (!attachment) return;
-            const attachmentData = await (await fetch(attachment.url)).text()
-            console.log(attachmentData)
+            const attachmentData = await (await fetch(attachment.url)).text();
             const decoded = atob(attachmentData);
-            console.log("decoded", decoded)
-            const json = JSON.parse(decoded);
-            console.log("json", json)
+            const json = (
+                JSON.parse(decoded) as { data: { count: number; value: string; added?: boolean; removed?: boolean }[] }
+            ).data;
+            // "Before" is everything where added is false
+            // "After" is everything where removed is false
+            const before: string = json
+                .filter((d) => !d.added)
+                .map((d) => d.value)
+                .join("");
+            const after: string = json
+                .filter((d) => !d.removed)
+                .map((d) => d.value)
+                .join("");
+            const { renderDateFooter } = client.logger;
+            await interaction.reply({
+                embeds: [
+                    new EmojiEmbed()
+                        .setTitle("Before")
+                        .setDescription(before)
+                        .setStatus("Danger")
+                        .setEmoji("ICONS.OPP.ADD"),
+                    new EmojiEmbed()
+                        .setTitle("After")
+                        .setDescription(after)
+                        .setStatus("Success")
+                        .setEmoji("ICONS.ADD")
+                        .setFooter({ text: `Edited at ${renderDateFooter(interaction.message.createdTimestamp!)}` }) // Created timestamp of the log is when the edit was made
+                ],
+                ephemeral: true
+            });
+        } else if (interaction.customId === "log:message.delete") {
+            await interaction.channel?.messages.fetch({ message: interaction.message.id, force: true });
+            const attachment = interaction.message.embeds[0]?.image ?? interaction.message.attachments.first();
+            if (!attachment) return;
+            const attachmentData = await (await fetch(attachment.url)).text();
+            const decoded = atob(attachmentData);
+            const json = JSON.parse(decoded) as { data: string };
+            await interaction.reply({
+                embeds: [
+                    new EmojiEmbed()
+                        .setTitle("Message")
+                        .setDescription(json.data)
+                        .setStatus("Danger")
+                        .setEmoji("MESSAGE.DELETE")
+                        .setFooter({ text: `Deleted at ${client.logger.renderDateFooter(Date.now())}` })
+                ],
+                ephemeral: true
+            });
         }
         switch (interaction.customId) {
             case "rolemenu": {
diff --git a/src/events/messageDelete.ts b/src/events/messageDelete.ts
index b847400..8188a67 100644
--- a/src/events/messageDelete.ts
+++ b/src/events/messageDelete.ts
@@ -1,5 +1,6 @@
 import type { NucleusClient } from "../utils/client.js";
-import Discord, { AuditLogEvent, GuildAuditLogsEntry, Message, User } from "discord.js";
+import Discord, { AuditLogEvent, ButtonStyle, GuildAuditLogsEntry, Message, User } from "discord.js";
+import { imageDataEasterEgg } from "../utils/defaults.js";
 
 export const event = "messageDelete";
 
@@ -33,6 +34,7 @@
     if (config) {
         attachmentJump = ` [[View attachments]](${config})`;
     }
+    const imageData = JSON.stringify({ data: message.content, extra: imageDataEasterEgg }, null, 2);
     const data = {
         meta: {
             type: "messageDelete",
@@ -40,7 +42,9 @@
             calculateType: "messageDelete",
             color: NucleusColors.red,
             emoji: "MESSAGE.DELETE",
-            timestamp: Date.now()
+            timestamp: Date.now(),
+            imageData: imageData,
+            buttons: [{ buttonText: "View text", buttonId: "log:message.delete", buttonStyle: ButtonStyle.Secondary }]
         },
         separate: {
             start: content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*"
diff --git a/src/events/messageEdit.ts b/src/events/messageEdit.ts
index f61a873..35de994 100644
--- a/src/events/messageEdit.ts
+++ b/src/events/messageEdit.ts
@@ -3,6 +3,7 @@
 import type Discord from "discord.js";
 import * as diff from "diff";
 import addPlural from "../utils/plurals.js";
+import { imageDataEasterEgg } from "../utils/defaults.js";
 
 export const event = "messageUpdate";
 
@@ -10,16 +11,8 @@
     if (newMessage.author.id === client.user!.id) return;
     if (newMessage.author.bot) return;
     if (!newMessage.guild) return;
-    const {
-        log,
-        isLogging,
-        NucleusColors,
-        entry,
-        renderUser,
-        renderDelta,
-        renderNumberDelta,
-        renderChannel
-    } = client.logger;
+    const { log, isLogging, NucleusColors, entry, renderUser, renderDelta, renderNumberDelta, renderChannel } =
+        client.logger;
     const replyTo: MessageReference | null = newMessage.reference;
     const newContent = newMessage.cleanContent.replaceAll("`", "‘");
     const oldContent = oldMessage.cleanContent.replaceAll("`", "‘");
@@ -72,14 +65,15 @@
         return;
     }
     const differences = diff.diffChars(oldContent, newContent);
-    const charsAdded = (differences.filter((d) => d.added).map((d) => d.count)).reduce((a, b) => a! + b!, 0)!;
-    const charsRemoved = (differences.filter((d) => d.removed).map((d) => d.count)).reduce((a, b) => a! + b!, 0)!;
-    const imageData = JSON.stringify({data: differences, extra: "The image in this embed contains data about the below log.\n" +
-                        "It isn't designed to be read by humans, but you can decode " +
-                        "it with any base64 decoder, and then read it as JSON.\n" +
-                        "We use base 64 to get around people using virus tests and the file being blocked, and an image to have the embed hidden (files can't be suppressed)\n" +
-                        "If you've got to this point and are reading this hidden message, you should come and work with us " +
-                        "at https://discord.gg/w35pXdrxKW (Internal development server) and let us know how you got here."}, null, 2)
+    const charsAdded = differences
+        .filter((d) => d.added)
+        .map((d) => d.count)
+        .reduce((a, b) => a! + b!, 0)!;
+    const charsRemoved = differences
+        .filter((d) => d.removed)
+        .map((d) => d.count)
+        .reduce((a, b) => a! + b!, 0)!;
+    const imageData = JSON.stringify({ data: differences, extra: imageDataEasterEgg }, null, 2);
     const data = {
         meta: {
             type: "messageUpdate",
@@ -88,7 +82,7 @@
             color: NucleusColors.yellow,
             emoji: "MESSAGE.EDIT",
             timestamp: newMessage.editedTimestamp,
-            buttons: [{ buttonText: "View Changes", buttonStyle: ButtonStyle.Secondary, buttonId: `log:edit` }],
+            buttons: [{ buttonText: "View Changes", buttonStyle: ButtonStyle.Secondary, buttonId: `log:message.edit` }],
             imageData: imageData
         },
         separate: {
diff --git a/src/utils/database.ts b/src/utils/database.ts
index 1bb1904..96cd068 100644
--- a/src/utils/database.ts
+++ b/src/utils/database.ts
@@ -471,8 +471,12 @@
                         if (child.type === ComponentType.Button) {
                             obj.style = child.style;
                             obj.label = child.label ?? "";
-                        } else if (child.type > 2) {
-                            // FIXME: Can we write this more clearly to make it obvious what we mean by 2 here?
+                        } else if (
+                            child.type === ComponentType.StringSelect ||
+                            child.type === ComponentType.UserSelect ||
+                            child.type === ComponentType.ChannelSelect ||
+                            child.type === ComponentType.RoleSelect
+                        ) {
                             obj.placeholder = child.placeholder ?? "";
                         }
                         return obj;
diff --git a/src/utils/defaults.ts b/src/utils/defaults.ts
index 0d4c9e3..ec337f4 100644
--- a/src/utils/defaults.ts
+++ b/src/utils/defaults.ts
@@ -43,3 +43,10 @@
 export { Embed };
 
 export const unknownServerIcon = "";
+
+export const imageDataEasterEgg =
+    "The image in this embed contains data about the below log.\n" +
+    "It isn't designed to be read by humans, but you can decode it with any base64 decoder, and then read it as JSON.\n" +
+    "We use base 64 to get around people using virus tests and the file being blocked, and an image to have the embed hidden (files can't be suppressed)\n" +
+    "If you've got to this point and are reading this hidden message, you should come and work with us " +
+    "at https://discord.gg/w35pXdrxKW (Internal development server) and let us know how you got here!";
diff --git a/src/utils/log.ts b/src/utils/log.ts
index 2679fd6..b2b078d 100644
--- a/src/utils/log.ts
+++ b/src/utils/log.ts
@@ -16,7 +16,7 @@
         color: number;
         emoji: string;
         timestamp: number;
-        buttons?: { buttonText: string, buttonId: string, buttonStyle: Discord.ButtonStyle }[];
+        buttons?: { buttonText: string; buttonId: string; buttonStyle: Discord.ButtonStyle }[];
         imageData?: string;
     };
     list: Record<string | symbol | number, unknown>;
@@ -43,7 +43,7 @@
     red: 0xf27878,
     yellow: 0xf2d478,
     green: 0x68d49e,
-    blue: 0x72aef5,
+    blue: 0x72aef5
 };
 
 export const Logger = {
@@ -61,6 +61,13 @@
         t = Math.floor((t /= 1000));
         return `<t:${t}:R> (<t:${t}:D> at <t:${t}:T>)`;
     },
+    renderDateFooter(t: number) {
+        if (isNaN(t)) return "Unknown";
+        const date = new Date(t);
+        return `${date.getUTCFullYear()}-${
+            date.getUTCMonth() + 1
+        }-${date.getUTCDate()} at ${date.getUTCHours()}:${date.getUTCMinutes()}:${date.getUTCSeconds()} UTC`;
+    },
     renderNumberDelta(num1: number, num2: number) {
         const delta = num2 - num1;
         return `${num1} -> ${num2} (${delta > 0 ? "+" : ""}${delta})`;
@@ -119,7 +126,6 @@
                     description[key] = value;
                 }
             });
-            console.log("imageData", log.meta.imageData)
             if (channel) {
                 log.separate = log.separate ?? {};
                 const messageOptions: Parameters<Discord.TextChannel["send"]>[0] = {};
@@ -138,14 +144,14 @@
                         .setImage(log.meta.imageData ? "attachment://extra_log_data.json.base64" : null)
                 ];
                 if (log.meta.buttons) {
-                    const buttons = []
+                    const buttons = [];
                     for (const button of log.meta.buttons) {
                         buttons.push(
                             new Discord.ButtonBuilder()
                                 .setCustomId(button.buttonId)
                                 .setLabel(button.buttonText)
                                 .setStyle(button.buttonStyle)
-                        )
+                        );
                     }
                     components.addComponents(buttons);
                     messageOptions.components = [components];
@@ -153,7 +159,7 @@
                 if (log.meta.imageData) {
                     messageOptions.files = [
                         {
-                            attachment: Buffer.from(btoa(log.meta.imageData), "utf-8"),  // Use base 64 to prevent virus scanning (EICAR)Buffer.from(log.meta.imageData, "base64"),
+                            attachment: Buffer.from(btoa(log.meta.imageData), "utf-8"), // Use base 64 to prevent virus scanning (EICAR)
                             name: "extra_log_data.json.base64"
                         }
                     ];