Much more typing
diff --git a/src/events/guildBanAdd.ts b/src/events/guildBanAdd.ts
index 17c4595..a05389f 100644
--- a/src/events/guildBanAdd.ts
+++ b/src/events/guildBanAdd.ts
@@ -1,14 +1,17 @@
+import type { GuildAuditLogsEntry, GuildBan } from 'discord.js';
 import { purgeByUser } from "../actions/tickets/delete.js";
 import { callback as statsChannelRemove } from "../reflex/statsChannelUpdate.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
 
 export const event = "guildBanAdd";
 
-export async function callback(client, ban) {
-    await statsChannelRemove(client, ban.user);
+export async function callback(client: HaikuClient, ban: GuildBan) {
+    await statsChannelRemove(client, undefined, ban.guild, ban.user);
     purgeByUser(ban.user.id, ban.guild);
-    const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = ban.user.client.logger;
+    const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = client.logger;
     const auditLog = await getAuditLog(ban.guild, "MEMBER_BAN_ADD");
-    const audit = auditLog.entries.filter((entry) => entry.target.id === ban.user.id).first();
+    const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === ban.user.id).first();
     if (audit.executor.id === client.user.id) return;
     await client.database.history.create("ban", ban.guild.id, ban.user, audit.executor, audit.reason);
     const data = {
diff --git a/src/events/guildBanRemove.ts b/src/events/guildBanRemove.ts
index 74b7c4e..86d6efe 100644
--- a/src/events/guildBanRemove.ts
+++ b/src/events/guildBanRemove.ts
@@ -1,14 +1,15 @@
+import type { GuildAuditLogsEntry, GuildBan } from 'discord.js';
 import { purgeByUser } from "../actions/tickets/delete.js";
-import { callback as statsChannelRemove } from "../reflex/statsChannelUpdate.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
 
 export const event = "guildBanRemove";
 
-export async function callback(client, ban) {
-    await statsChannelRemove(client, ban.user);
+export async function callback(client: HaikuClient, ban: GuildBan) {
     purgeByUser(ban.user.id, ban.guild);
-    const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = ban.user.client.logger;
+    const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = client.logger;
     const auditLog = await getAuditLog(ban.guild, "MEMBER_BAN_REMOVE");
-    const audit = auditLog.entries.filter((entry) => entry.target.id === ban.user.id).first();
+    const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === ban.user.id).first();
     if (audit.executor.id === client.user.id) return;
     await client.database.history.create("unban", ban.guild.id, ban.user, audit.executor, audit.reason);
     const data = {
diff --git a/src/events/guildMemberUpdate.ts b/src/events/guildMemberUpdate.ts
index 08730f2..1f21870 100644
--- a/src/events/guildMemberUpdate.ts
+++ b/src/events/guildMemberUpdate.ts
@@ -1,10 +1,14 @@
+import type { GuildAuditLogsEntry, GuildMember } from "discord.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+
 export const event = "guildMemberUpdate";
 
-export async function callback(client, before, after) {
+export async function callback(client: HaikuClient, before: GuildMember, after: GuildMember) {
     try {
-        const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = after.client.logger;
+        const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = client.logger;
         const auditLog = await getAuditLog(after.guild, "MEMBER_UPDATE");
-        const audit = auditLog.entries.filter((entry) => entry.target.id === after.id).first();
+        const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === after.id).first();
         if (audit.executor.id === client.user.id) return;
         if (before.nickname !== after.nickname) {
             await client.database.history.create(
@@ -13,8 +17,8 @@
                 after.user,
                 audit.executor,
                 null,
-                before.nickname || before.user.username,
-                after.nickname || after.user.username
+                before.nickname ?? before.user.username,
+                after.nickname ?? after.user.username
             );
             const data = {
                 meta: {
@@ -39,8 +43,8 @@
             };
             log(data);
         } else if (
-            before.communicationDisabledUntilTimestamp < new Date().getTime() &&
-            after.communicationDisabledUntil > new Date().getTime()
+            (before.communicationDisabledUntilTimestamp ?? 0) < new Date().getTime() &&
+            (after.communicationDisabledUntil ?? 0) > new Date().getTime() // TODO: test this
         ) {
             await client.database.history.create(
                 "mute",
diff --git a/src/events/guildUpdate.ts b/src/events/guildUpdate.ts
index a165770..ea9008d 100644
--- a/src/events/guildUpdate.ts
+++ b/src/events/guildUpdate.ts
@@ -1,14 +1,17 @@
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+import type { Guild, GuildAuditLogsEntry } from 'discord.js';
 import { callback as statsChannelUpdate } from "../reflex/statsChannelUpdate.js";
 
 export const event = "guildUpdate";
 
-export async function callback(client, before, after) {
-    await statsChannelUpdate(client, after.me);
-    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = after.client.logger;
+export async function callback(client: HaikuClient, before: Guild, after: Guild) {
+    await statsChannelUpdate(client, after.me!);
+    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
     const auditLog = await getAuditLog(after, "GUILD_UPDATE");
-    const audit = auditLog.entries.filter((entry) => entry.target.id === after.id).first();
+    const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === after.id).first();
     if (audit.executor.id === client.user.id) return;
-    const list = {};
+    const list: Record<string, ReturnType<typeof entry>> = {};
 
     const verificationLevels = {
         NONE: "Unrestricted",
@@ -28,32 +31,34 @@
         NONE: "None",
         ELEVATED: "Enabled"
     };
+    const beforeOwner = await before.fetchOwner()
+    const afterOwner = await after.fetchOwner()
 
-    if (before.name !== after.name) list.name = entry([before.name, after.name], `${before.name} -> ${after.name}`);
+    if (before.name !== after.name) list["name"] = entry([before.name, after.name], `${before.name} -> ${after.name}`);
     if (before.icon !== after.icon)
-        list.icon = entry([before.icon, after.icon], `[Before](${before.iconURL()}) -> [After](${after.iconURL()})`);
+        list["icon"] = entry([before.icon, after.icon], `[Before](${before.iconURL()}) -> [After](${after.iconURL()})`);
     if (before.splash !== after.splash)
-        list.splash = entry(
+        list["splash"] = entry(
             [before.splash, after.splash],
             `[Before](${before.splashURL()}) -> [After](${after.splashURL()})`
         );
     if (before.banner !== after.banner)
-        list.banner = entry(
+        list["banner"] = entry(
             [before.banner, after.banner],
             `[Before](${before.bannerURL()}) -> [After](${after.bannerURL()})`
         );
-    if (before.owner !== after.owner)
-        list.owner = entry(
-            [before.owner, after.owner],
-            `${renderUser(before.owner.user)} -> ${renderUser(after.owner.user)}`
+    if (beforeOwner !== afterOwner)
+        list["owner"] = entry(
+            [beforeOwner, afterOwner],
+            `${renderUser(beforeOwner.user)} -> ${renderUser(afterOwner.user)}`
         );
     if (before.verificationLevel !== after.verificationLevel)
-        list.verificationLevel = entry(
+        list["verificationLevel"] = entry(
             [verificationLevels[before.verificationLevel], verificationLevels[after.verificationLevel]],
             `${verificationLevels[before.verificationLevel]} -> ${verificationLevels[after.verificationLevel]}`
         );
     if (before.explicitContentFilter !== after.explicitContentFilter)
-        list.explicitContentFilter = entry(
+        list["explicitContentFilter"] = entry(
             [
                 explicitContentFilterLevels[before.explicitContentFilter],
                 explicitContentFilterLevels[after.explicitContentFilter]
@@ -69,8 +74,8 @@
         );
 
     if (!Object.keys(list).length) return;
-    list.updated = entry(new Date().getTime(), renderDelta(new Date().getTime()));
-    list.updatedBy = entry(audit.executor.id, renderUser(audit.executor));
+    list["updated"] = entry(new Date().getTime(), renderDelta(new Date().getTime()));
+    list["updatedBy"] = entry(audit.executor.id, renderUser(audit.executor));
     const data = {
         meta: {
             type: "guildUpdate",
diff --git a/src/events/interactionCreate.ts b/src/events/interactionCreate.ts
index 5b0aff1..9ee7bee 100644
--- a/src/events/interactionCreate.ts
+++ b/src/events/interactionCreate.ts
@@ -5,10 +5,13 @@
 import createTranscript from "../premium/createTranscript.js";
 import Fuse from "fuse.js";
 import { autocomplete as tagAutocomplete } from "../commands/tag.js";
+import type { AutocompleteInteraction, Interaction, MessageComponentInteraction } from "discord.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
 
 export const event = "interactionCreate";
 
-function getAutocomplete(typed: string, options: string[]): object[] {
+function getAutocomplete(typed: string, options: string[]): {name: string, value: string}[] {
     options = options.filter((option) => option.length <= 100); // thanks discord. 6000 character limit on slash command inputs but only 100 for autocomplete.
     if (!typed)
         return options
@@ -23,7 +26,7 @@
     return fuse.slice(0, 25).map((option) => ({ name: option.item, value: option.item }));
 }
 
-function generateStatsChannelAutocomplete(typed) {
+function generateStatsChannelAutocomplete(typed: string) {
     const validReplacements = ["serverName", "memberCount", "memberCount:bots", "memberCount:humans"];
     const autocompletions = [];
     const beforeLastOpenBracket = typed.match(/(.*){[^{}]{0,15}$/);
@@ -38,7 +41,7 @@
     }
     return getAutocomplete(typed, autocompletions);
 }
-function generateWelcomeMessageAutocomplete(typed) {
+function generateWelcomeMessageAutocomplete(typed: string) {
     const validReplacements = [
         "serverName",
         "memberCount",
@@ -61,14 +64,15 @@
     return getAutocomplete(typed, autocompletions);
 }
 
-async function interactionCreate(interaction) {
-    if (interaction.componentType === "BUTTON") {
-        switch (interaction.customId) {
+async function interactionCreate(interaction: Interaction) {
+    if (interaction.type === "MESSAGE_COMPONENT" && (interaction as MessageComponentInteraction).componentType === "BUTTON") {
+        const int = (interaction as MessageComponentInteraction)
+        switch (int.customId) {
             case "rolemenu": {
                 return await roleMenu(interaction);
             }
             case "verifybutton": {
-                return verify(interaction);
+                return verify(int);
             }
             case "createticket": {
                 return create(interaction);
@@ -77,32 +81,33 @@
                 return close(interaction);
             }
             case "createtranscript": {
-                return createTranscript(interaction);
+                return createTranscript(int);
             }
         }
     } else if (interaction.type === "APPLICATION_COMMAND_AUTOCOMPLETE") {
+        const int = (interaction as AutocompleteInteraction)
         switch (
-            `${interaction.commandName} ${interaction.options.getSubcommandGroup(
+            `${int.commandName} ${int.options.getSubcommandGroup(
                 false
-            )} ${interaction.options.getSubcommand(false)}`
+            )} ${int.options.getSubcommand(false)}`
         ) {
             case "tag null null": {
-                return interaction.respond(
-                    getAutocomplete(interaction.options.getString("tag"), await tagAutocomplete(interaction))
+                return int.respond(
+                    getAutocomplete(int.options.getString("tag") ?? "", await tagAutocomplete(int))
                 );
             }
             case "settings null stats": {
-                return interaction.respond(generateStatsChannelAutocomplete(interaction.options.getString("name")));
+                return int.respond(generateStatsChannelAutocomplete(int.options.getString("name") ?? ""));
             }
             case "settings null welcome": {
-                return interaction.respond(
-                    generateWelcomeMessageAutocomplete(interaction.options.getString("message"))
+                return int.respond(
+                    generateWelcomeMessageAutocomplete(int.options.getString("message") ?? "")
                 );
             }
         }
     }
 }
 
-export async function callback(client, interaction) {
+export async function callback(_client: HaikuClient, interaction: Interaction) {
     await interactionCreate(interaction);
 }
diff --git a/src/events/inviteCreate.ts b/src/events/inviteCreate.ts
index 7b23bb2..fb35b7e 100644
--- a/src/events/inviteCreate.ts
+++ b/src/events/inviteCreate.ts
@@ -1,10 +1,15 @@
+import type { GuildAuditLogsEntry, Invite } from "discord.js";
+// @ts-expect-error
 import humanizeDuration from "humanize-duration";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+
 export const event = "inviteCreate";
 
-export async function callback(client, invite) {
-    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = invite.client.logger;
+export async function callback(client: HaikuClient, invite: Invite) {
+    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger;
     const auditLog = await getAuditLog(invite.guild, "INVITE_CREATE");
-    const audit = auditLog.entries.filter((entry) => entry.target.id === invite.id).first();
+    const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === invite.inviterId).first();
     if (audit.executor.id === client.user.id) return;
     const data = {
         meta: {
@@ -23,7 +28,7 @@
             created: entry(invite.createdTimestamp, renderDelta(invite.createdTimestamp))
         },
         hidden: {
-            guild: invite.guild.id
+            guild: invite.guild!.id
         }
     };
     log(data);
diff --git a/src/events/inviteDelete.ts b/src/events/inviteDelete.ts
index 2cd3bc5..b07893a 100644
--- a/src/events/inviteDelete.ts
+++ b/src/events/inviteDelete.ts
@@ -1,10 +1,15 @@
+import type { GuildAuditLogsEntry, Invite } from "discord.js";
+// @ts-expect-error
 import humanizeDuration from "humanize-duration";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+
 export const event = "inviteDelete";
 
-export async function callback(client, invite) {
-    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = invite.client.logger;
+export async function callback(client: HaikuClient, invite: Invite) {
+    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger;
     const auditLog = await getAuditLog(invite.guild, "INVITE_DELETE");
-    const audit = auditLog.entries.filter((entry) => entry.target.id === invite.id).first();
+    const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === invite.inviterId).first();
     if (audit.executor.id === client.user.id) return;
     const data = {
         meta: {
@@ -23,7 +28,7 @@
             deleted: entry(new Date().getTime(), renderDelta(new Date().getTime()))
         },
         hidden: {
-            guild: invite.guild.id
+            guild: invite.guild!.id
         }
     };
     log(data);
diff --git a/src/events/memberJoin.ts b/src/events/memberJoin.ts
index ebc2934..786c4ec 100644
--- a/src/events/memberJoin.ts
+++ b/src/events/memberJoin.ts
@@ -1,13 +1,15 @@
+import type { GuildMember } from "discord.js";
 import { callback as statsChannelAdd } from "../reflex/statsChannelUpdate.js";
 import { callback as welcome } from "../reflex/welcome.js";
-import client from "../utils/client.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
 
 export const event = "guildMemberAdd";
 
-export async function callback(_, member) {
-    welcome(_, member);
-    statsChannelAdd(_, member);
-    const { log, NucleusColors, entry, renderUser, renderDelta } = member.client.logger;
+export async function callback(client: HaikuClient, member: GuildMember) {
+    welcome(client, member);
+    statsChannelAdd(client, member);
+    const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
     await client.database.history.create("join", member.guild.id, member.user, null, null);
     const data = {
         meta: {
diff --git a/src/events/memberLeave.ts b/src/events/memberLeave.ts
index 00f6d84..20845d5 100644
--- a/src/events/memberLeave.ts
+++ b/src/events/memberLeave.ts
@@ -1,14 +1,18 @@
+import type { GuildAuditLogsEntry, GuildMember } from "discord.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+
 import { purgeByUser } from "../actions/tickets/delete.js";
 import { callback as statsChannelRemove } from "../reflex/statsChannelUpdate.js";
 
 export const event = "guildMemberRemove";
 
-export async function callback(client, member) {
+export async function callback(client: HaikuClient, member: GuildMember) {
     purgeByUser(member.id, member.guild);
     await statsChannelRemove(client, member);
-    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = member.client.logger;
+    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
     const auditLog = await getAuditLog(member.guild, "MEMBER_KICK");
-    const audit = auditLog.entries.filter((entry) => entry.target.id === member.id).first();
+    const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === member.id).first();
     let type = "leave";
     if (audit) {
         if (audit.executor.id === client.user.id) return;
@@ -50,7 +54,7 @@
                 displayName: "Member Left",
                 calculateType: "guildMemberUpdate",
                 color: NucleusColors.red,
-                emoji: "MEMBER." + (member.bot ? "BOT." : "") + "LEAVE",
+                emoji: "MEMBER." + (member.user.bot ? "BOT." : "") + "LEAVE",
                 timestamp: new Date().getTime()
             },
             list: {
diff --git a/src/events/messageCreate.ts b/src/events/messageCreate.ts
index f690885..d0f059c 100644
--- a/src/events/messageCreate.ts
+++ b/src/events/messageCreate.ts
@@ -5,7 +5,7 @@
 import createLogException from "../utils/createLogException.js";
 import getEmojiByName from "../utils/getEmojiByName.js";
 import client from "../utils/client.js";
-import { callback as a } from "../reflex/statsChannelUpdate.js";
+import { callback as statsChannelUpdate } from "../reflex/statsChannelUpdate.js";
 import { Message, ThreadChannel } from "discord.js";
 
 export const event = "messageCreate";
@@ -15,7 +15,7 @@
     if (message.author.bot) return;
     if (message.channel.type === "DM") return;
     try {
-        await a(client, await message.guild.members.fetch(message.author.id));
+        await statsChannelUpdate(client, await message.guild.members.fetch(message.author.id));
     } catch (e) {
         console.log(e);
     }
diff --git a/src/events/messageDelete.ts b/src/events/messageDelete.ts
index 3a72876..f2301e0 100644
--- a/src/events/messageDelete.ts
+++ b/src/events/messageDelete.ts
@@ -1,17 +1,20 @@
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+import type { GuildAuditLogsEntry, Message } from "discord.js";
+
 export const event = "messageDelete";
 
-export async function callback(client, message) {
+export async function callback(client: HaikuClient, message: Message) {
     try {
         if (message.author.id === client.user.id) return;
-        if (client.noLog.includes(`${message.guild.id}/${message.channel.id}/${message.id}`)) return;
-        const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } =
-            message.channel.client.logger;
+        if (client.noLog.includes(`${message.id}/${message.channel.id}/${message.id}`)) return;
+        const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger;
         const auditLog = await getAuditLog(message.guild, "MEMBER_BAN_ADD");
-        const audit = auditLog.entries.filter((entry) => entry.target.id === message.author.id).first();
+        const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === message.author.id).first();
         if (audit) {
             if (audit.createdAt - 100 < new Date().getTime()) return;
         }
-        message.reference = message.reference || {};
+        const replyTo = message.reference;
         let content = message.cleanContent;
         content.replace("`", "\\`");
         if (content.length > 256) content = content.substring(0, 253) + "...";
@@ -23,7 +26,7 @@
                 ) ?? []
             ).length;
         let attachmentJump = "";
-        const config = (await client.database.guilds.read(message.guild.id)).logging.attachments.saved[
+        const config = (await client.database.guilds.read(message.guild!.id)).logging.attachments.saved[
             message.channel.id + message.id
         ];
         if (config) {
@@ -49,14 +52,14 @@
                 mentions: message.mentions.users.size,
                 attachments: entry(attachments, attachments + attachmentJump),
                 repliedTo: entry(
-                    message.reference.messageId || null,
-                    message.reference.messageId
-                        ? `[[Jump to message]](https://discord.com/channels/${message.guild.id}/${message.channel.id}/${message.reference.messageId})`
+                    replyTo,
+                    replyTo
+                        ? `[[Jump to message]](https://discord.com/channels/${message.guild!.id}/${message.channel.id}/${replyTo.messageId})`
                         : "None"
                 )
             },
             hidden: {
-                guild: message.channel.guild.id
+                guild: message.guild!.id
             }
         };
         log(data);
diff --git a/src/events/messageEdit.ts b/src/events/messageEdit.ts
index 1470832..89e69de 100644
--- a/src/events/messageEdit.ts
+++ b/src/events/messageEdit.ts
@@ -1,10 +1,14 @@
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+import type { Message, MessageReference } from "discord.js";
+
 export const event = "messageUpdate";
 
-export async function callback(client, oldMessage, newMessage) {
+export async function callback(client: HaikuClient, oldMessage: Message, newMessage: Message) {
     if (newMessage.author.id === client.user.id) return;
-    const { log, NucleusColors, entry, renderUser, renderDelta, renderNumberDelta, renderChannel } =
-        newMessage.channel.client.logger;
-    newMessage.reference = newMessage.reference || {};
+    if (!newMessage.guild) return;
+    const { log, NucleusColors, entry, renderUser, renderDelta, renderNumberDelta, renderChannel } = client.logger;
+    const replyTo: MessageReference | null = newMessage.reference;
     let newContent = newMessage.cleanContent.replaceAll("`", "‘");
     let oldContent = oldMessage.cleanContent.replaceAll("`", "‘");
     let attachmentJump = "";
@@ -37,8 +41,8 @@
                         renderDelta(new Date(newMessage.createdTimestamp))
                     ),
                     published: entry(
-                        new Date(newMessage.editedTimestamp),
-                        renderDelta(new Date(newMessage.editedTimestamp))
+                        new Date(newMessage.editedTimestamp!),
+                        renderDelta(new Date(newMessage.editedTimestamp!))
                     ),
                     mentions: renderNumberDelta(oldMessage.mentions.users.size, newMessage.mentions.users.size),
                     attachments: entry(
@@ -47,7 +51,7 @@
                     )
                 },
                 hidden: {
-                    guild: newMessage.channel.guild.id
+                    guild: newMessage.guild.id
                 }
             };
             return log(data);
@@ -87,14 +91,14 @@
                 renderNumberDelta(oldMessage.attachments.size, newMessage.attachments.size) + attachmentJump
             ),
             repliedTo: entry(
-                newMessage.reference.messageId || null,
-                newMessage.reference.messageId
-                    ? `[[Jump to message]](https://discord.com/channels/${newMessage.guild.id}/${newMessage.channel.id}/${newMessage.reference.messageId})`
+                replyTo,
+                replyTo
+                    ? `[[Jump to message]](https://discord.com/channels/${newMessage.guild.id}/${newMessage.channel.id}/${replyTo.messageId})`
                     : "None"
             )
         },
         hidden: {
-            guild: newMessage.channel.guild.id
+            guild: newMessage.guild.id
         }
     };
     log(data);
diff --git a/src/events/roleCreate.ts b/src/events/roleCreate.ts
index f1b0a91..e7a0a5c 100644
--- a/src/events/roleCreate.ts
+++ b/src/events/roleCreate.ts
@@ -1,10 +1,14 @@
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+import type { GuildAuditLogsEntry, Role } from "discord.js";
+
 export const event = "roleCreate";
 
-export async function callback(client, role) {
-    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderRole } = role.client.logger;
+export async function callback(client: HaikuClient, role: Role) {
+    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderRole } = client.logger;
     if (role.managed) return;
     const auditLog = await getAuditLog(role.guild, "ROLE_CREATE");
-    const audit = auditLog.entries.filter((entry) => entry.target.id === role.id).first();
+    const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === role.id).first();
     if (audit.executor.id === client.user.id) return;
     const data = {
         meta: {
diff --git a/src/events/roleDelete.ts b/src/events/roleDelete.ts
index 4807e7d..348f211 100644
--- a/src/events/roleDelete.ts
+++ b/src/events/roleDelete.ts
@@ -1,12 +1,15 @@
 import getEmojiByName from "../utils/getEmojiByName.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+import type { GuildAuditLogsEntry, Role } from "discord.js";
 
 export const event = "roleDelete";
 
-export async function callback(client, role) {
-    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = role.client.logger;
+export async function callback(client: HaikuClient, role: Role) {
+    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
     if (role.managed) return;
     const auditLog = await getAuditLog(role.guild, "ROLE_DELETE");
-    const audit = auditLog.entries.filter((entry) => entry.target.id === role.id).first();
+    const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === role.id).first();
     if (audit.executor.id === client.user.id) return;
     const data = {
         meta: {
diff --git a/src/events/roleUpdate.ts b/src/events/roleUpdate.ts
index 53bbdee..9b75fc0 100644
--- a/src/events/roleUpdate.ts
+++ b/src/events/roleUpdate.ts
@@ -1,15 +1,18 @@
+import type { Role } from "discord.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
 import getEmojiByName from "../utils/getEmojiByName.js";
 
 export const event = "roleUpdate";
 
-export async function callback(client, or, nr) {
+export async function callback(client: HaikuClient, or: Role, nr: Role) {
     const { getAuditLog, log, NucleusColors, entry, renderDelta, renderUser, renderRole } = client.logger;
 
     const auditLog = await getAuditLog(nr.guild, "ROLE_UPDATE");
     const audit = auditLog.entries.first();
     if (audit.executor.id === client.user.id) return;
 
-    const changes = {
+    const changes: Record<string, ReturnType<typeof entry>> = {
         roleId: entry(nr.id, `\`${nr.id}\``),
         role: entry(nr.id, renderRole(nr)),
         edited: entry(new Date().getTime(), renderDelta(new Date().getTime())),
@@ -21,14 +24,14 @@
     mentionable[1] = nr.mentionable ? `${getEmojiByName("CONTROL.TICK")} Yes` : `${getEmojiByName("CONTROL.CROSS")} No`;
     hoist[0] = or.hoist ? `${getEmojiByName("CONTROL.TICK")} Yes` : `${getEmojiByName("CONTROL.CROSS")} No`;
     hoist[1] = nr.hoist ? `${getEmojiByName("CONTROL.TICK")} Yes` : `${getEmojiByName("CONTROL.CROSS")} No`;
-    if (or.name !== nr.name) changes.name = entry([or.name, nr.name], `${or.name} -> ${nr.name}`);
+    if (or.name !== nr.name) changes["name"] = entry([or.name, nr.name], `${or.name} -> ${nr.name}`);
     if (or.position !== nr.position)
-        changes.position = entry([or.position, nr.position], `${or.position} -> ${nr.position}`);
-    if (or.hoist !== nr.hoist) changes.showInMemberList = entry([or.hoist, nr.hoist], `${hoist[0]} -> ${hoist[1]}`);
+        changes["position"] = entry([or.position, nr.position], `${or.position} -> ${nr.position}`);
+    if (or.hoist !== nr.hoist) changes["showInMemberList"] = entry([or.hoist, nr.hoist], `${hoist[0]} -> ${hoist[1]}`);
     if (or.mentionable !== nr.mentionable)
-        changes.mentionable = entry([or.mentionable, nr.mentionable], `${mentionable[0]} -> ${mentionable[1]}`);
+        changes["mentionable"] = entry([or.mentionable, nr.mentionable], `${mentionable[0]} -> ${mentionable[1]}`);
     if (or.hexColor !== nr.hexColor)
-        changes.color = entry([or.hexColor, nr.hexColor], `\`${or.hexColor}\` -> \`${nr.hexColor}\``);
+        changes["color"] = entry([or.hexColor, nr.hexColor], `\`${or.hexColor}\` -> \`${nr.hexColor}\``);
 
     if (Object.keys(changes).length === 4) return;
 
diff --git a/src/events/stickerCreate.ts b/src/events/stickerCreate.ts
index c538bde..01d6c2c 100644
--- a/src/events/stickerCreate.ts
+++ b/src/events/stickerCreate.ts
@@ -1,9 +1,13 @@
-export const event = "stickerCreate";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku"
+import type { GuildAuditLogsEntry, Sticker } from "discord.js";
 
-export async function callback(client, emoji) {
-    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = emoji.client.logger;
+export const event = "stickerDelete";
+
+export async function callback(client: HaikuClient, emoji: Sticker) {
+    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
     const auditLog = await getAuditLog(emoji.guild, "STICKER_CREATE");
-    const audit = auditLog.entries.filter((entry) => entry.target.id === emoji.id).first();
+    const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === emoji.id).first();
     if (audit.executor.id === client.user.id) return;
     const data = {
         meta: {
@@ -21,7 +25,7 @@
             created: entry(emoji.createdTimestamp, renderDelta(emoji.createdTimestamp))
         },
         hidden: {
-            guild: emoji.guild.id
+            guild: emoji.guild!.id
         }
     };
     log(data);
diff --git a/src/events/stickerDelete.ts b/src/events/stickerDelete.ts
index 7ac17ce..c9b3fab 100644
--- a/src/events/stickerDelete.ts
+++ b/src/events/stickerDelete.ts
@@ -1,9 +1,13 @@
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku"
+import type { GuildAuditLogsEntry, Sticker } from "discord.js";
+
 export const event = "stickerDelete";
 
-export async function callback(client, emoji) {
-    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = emoji.client.logger;
+export async function callback(client: HaikuClient, emoji: Sticker) {
+    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
     const auditLog = await getAuditLog(emoji.guild, "STICKER_DELETE");
-    const audit = auditLog.entries.filter((entry) => entry.target.id === emoji.id).first();
+    const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === emoji.id).first();
     if (audit.executor.id === client.user.id) return;
     const data = {
         meta: {
@@ -22,7 +26,7 @@
             deleted: entry(audit.createdTimestamp, renderDelta(audit.createdTimestamp))
         },
         hidden: {
-            guild: emoji.guild.id
+            guild: emoji.guild!.id
         }
     };
     log(data);
diff --git a/src/events/stickerUpdate.ts b/src/events/stickerUpdate.ts
index 662f981..c6e3b6e 100644
--- a/src/events/stickerUpdate.ts
+++ b/src/events/stickerUpdate.ts
@@ -1,17 +1,21 @@
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku"
+import type { Sticker } from "discord.js";
+
 export const event = "stickerUpdate";
 
-export async function callback(client, oe, ne) {
+export async function callback(client: HaikuClient, oe: Sticker, ne: Sticker) {
     const { getAuditLog, log, NucleusColors, entry, renderDelta, renderUser } = client.logger;
 
     if (oe.name === ne.name) return;
-    const auditLog = await getAuditLog(ne.guild, "EMOJI_UPDATE");
+    const auditLog = await getAuditLog(ne.guild, "STICKER_UPDATE");
     const audit = auditLog.entries.first();
     if (audit.executor.id === client.user.id) return;
 
     const changes = {
         stickerId: entry(ne.id, `\`${ne.id}\``),
         edited: entry(ne.createdTimestamp, renderDelta(ne.createdTimestamp)),
-        editedBy: entry(audit.executor.id, renderUser((await ne.guild.members.fetch(audit.executor.id)).user)),
+        editedBy: entry(audit.executor.id, renderUser((await ne.guild!.members.fetch(audit.executor.id)).user)),
         name: entry([oe.name, ne.name], `\`:${oe.name}:\` -> \`:${ne.name}:\``)
     };
     const data = {
@@ -25,7 +29,7 @@
         },
         list: changes,
         hidden: {
-            guild: ne.guild.id
+            guild: ne.guild!.id
         }
     };
     log(data);
diff --git a/src/events/threadCreate.ts b/src/events/threadCreate.ts
index da3cbae..e8849c9 100644
--- a/src/events/threadCreate.ts
+++ b/src/events/threadCreate.ts
@@ -1,11 +1,19 @@
+import type { GuildAuditLogsEntry, ThreadChannel } from "discord.js";
+// @ts-expect-error
 import humanizeDuration from "humanize-duration";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku"
 export const event = "threadCreate";
 
-export async function callback(client, thread) {
-    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = thread.client.logger;
+export async function callback(client: HaikuClient, thread: ThreadChannel) {
+    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger;
     const auditLog = await getAuditLog(thread.guild, "THREAD_CREATE");
-    const audit = auditLog.entries.filter((entry) => entry.target.id === thread.id).first();
+    const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === thread.id).first();
     if (audit.executor.id === client.user.id) return;
+    const category = thread.parent ? entry(
+        thread.parent.parent ? thread.parent.parent.name : "None",
+        thread.parent.parent ? renderChannel(thread.parent.parent) : "None"
+    ) : entry(null, "Uncategorised")
     const data = {
         meta: {
             type: "channelCreate",
@@ -19,13 +27,10 @@
             threadId: entry(thread.id, `\`${thread.id}\``),
             name: entry(thread.name, renderChannel(thread)),
             parentChannel: entry(thread.parentId, renderChannel(thread.parent)),
-            category: entry(
-                thread.parent.parent ? thread.parent.parent.name : "None",
-                thread.parent.parent ? renderChannel(thread.parent.parent) : "None"
-            ),
+            category: category,
             autoArchiveDuration: entry(
                 thread.autoArchiveDuration,
-                humanizeDuration(thread.autoArchiveDuration * 60 * 1000, {
+                humanizeDuration((thread.autoArchiveDuration ?? 0) * 60 * 1000, {
                     round: true
                 })
             ),
diff --git a/src/events/threadDelete.ts b/src/events/threadDelete.ts
index bfae11a..1908b7f 100644
--- a/src/events/threadDelete.ts
+++ b/src/events/threadDelete.ts
@@ -1,11 +1,19 @@
+import type { GuildAuditLogsEntry, ThreadChannel } from "discord.js";
+// @ts-expect-error
 import humanizeDuration from "humanize-duration";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku"
 export const event = "threadDelete";
 
-export async function callback(client, thread) {
-    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = thread.client.logger;
+export async function callback(client: HaikuClient, thread: ThreadChannel) {
+    const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger;
     const auditLog = await getAuditLog(thread.guild, "THREAD_UPDATE");
-    const audit = auditLog.entries.filter((entry) => entry.target.id === thread.id).first();
+    const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === thread.id).first();
     if (audit.executor.id === client.user.id) return;
+    const category = thread.parent ? entry(
+            thread.parent.parent ? thread.parent.parent.name : "None",
+            thread.parent.parent ? renderChannel(thread.parent.parent) : "None"
+        ) : entry(null, "Uncategorised")
     const data = {
         meta: {
             type: "channelDelete",
@@ -18,14 +26,11 @@
         list: {
             threadId: entry(thread.id, `\`${thread.id}\``),
             name: entry(thread.name, thread.name),
-            parentChannel: entry(thread.parentId, renderChannel(thread.parent)),
-            category: entry(
-                thread.parent.parent ? thread.parent.parent.name : "None",
-                thread.parent.parent ? renderChannel(thread.parent.parent) : "None"
-            ),
+            parentChannel: entry(thread.parentId, thread.parent ? renderChannel(thread.parent) : "*None*"),
+            category: category,
             autoArchiveDuration: entry(
                 thread.autoArchiveDuration,
-                humanizeDuration(thread.autoArchiveDuration * 60 * 1000, {
+                humanizeDuration((thread.autoArchiveDuration ?? 0) * 60 * 1000, {
                     round: true
                 })
             ),
diff --git a/src/premium/createTranscript.ts b/src/premium/createTranscript.ts
index c60bf23..57720bf 100644
--- a/src/premium/createTranscript.ts
+++ b/src/premium/createTranscript.ts
@@ -1,4 +1,4 @@
-import { CommandInteraction, GuildMember, Message, MessageActionRow, MessageButton, TextChannel } from "discord.js";
+import { CommandInteraction, GuildMember, Message, MessageActionRow, MessageButton, MessageComponentInteraction, TextChannel } from "discord.js";
 import EmojiEmbed from "../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../utils/getEmojiByName.js";
 import { PasteClient, Publicity, ExpireDate } from "pastebin-api";
@@ -7,7 +7,7 @@
 
 const pbClient = new PasteClient(config.pastebinApiKey);
 
-export default async function (interaction: CommandInteraction) {
+export default async function (interaction: CommandInteraction | MessageComponentInteraction) {
     if (interaction.channel === null) return;
     if (!(interaction.channel instanceof TextChannel)) return;
     const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
diff --git a/src/reflex/statsChannelUpdate.ts b/src/reflex/statsChannelUpdate.ts
index 644a75f..657e90d 100644
--- a/src/reflex/statsChannelUpdate.ts
+++ b/src/reflex/statsChannelUpdate.ts
@@ -1,3 +1,4 @@
+import type { Guild, User } from 'discord.js';
 // @ts-expect-error
 import type { HaikuClient } from "jshaiku";
 import type { GuildMember } from "discord.js";
@@ -9,28 +10,29 @@
     name: string;
 }
 
-export async function callback(client: HaikuClient, member: GuildMember) {
-    const guild = await client.guilds.fetch(member.guild.id);
+export async function callback(client: HaikuClient, member?: GuildMember, guild?: Guild, user?: User) {
+    if (!member && !guild) return;
+    guild = await client.guilds.fetch(member ? member.guild.id : guild!.id);
+    if (!guild) return;
+    user = user ?? member!.user
     const config = await client.database.guilds.read(guild.id);
     Object.entries(config.getKey("stats")).forEach(async ([channel, props]) => {
         if ((props as PropSchema).enabled) {
             let string = (props as PropSchema).name;
             if (!string) return;
-            string = await convertCurlyBracketString(string, member.id, member.displayName, guild.name, guild.members);
+            string = await convertCurlyBracketString(string, user!.id, user!.username, guild!.name, guild!.members);
             let fetchedChannel;
             try {
-                fetchedChannel = await guild.channels.fetch(channel);
+                fetchedChannel = await guild!.channels.fetch(channel);
             } catch (e) {
                 fetchedChannel = null;
             }
             if (!fetchedChannel) {
                 const deleted = config.getKey("stats")[channel];
-                console.log(`stats.${channel}`);
-                console.log(guild.id);
-                await client.database.guilds.write(guild.id, null, `stats.${channel}`);
+                await client.database.guilds.write(guild!.id, null, `stats.${channel}`);
                 return singleNotify(
                     "statsChannelDeleted",
-                    guild.id,
+                    guild!.id,
                     "One or more of your stats channels have been deleted. Please use `/settings stats` if you wish to add the channel again.\n" +
                         `The channels name was: ${deleted.name}`,
                     "Critical"
diff --git a/src/reflex/verify.ts b/src/reflex/verify.ts
index 37f8d6c..f28b291 100644
--- a/src/reflex/verify.ts
+++ b/src/reflex/verify.ts
@@ -1,5 +1,5 @@
 import { LoadingEmbed } from "./../utils/defaultEmbeds.js";
-import Discord, { CommandInteraction, GuildMember, Interaction, Permissions, Role } from "discord.js";
+import Discord, { CommandInteraction, GuildMember, Interaction, MessageComponentInteraction, Permissions, Role } from "discord.js";
 import EmojiEmbed from "../utils/generateEmojiEmbed.js";
 import fetch from "node-fetch";
 import { TestString, NSFWCheck } from "./scanners.js";
@@ -21,7 +21,7 @@
     return "\n\n" + createPageIndicator(5, i);
 }
 
-export default async function (interaction: CommandInteraction) {
+export default async function (interaction: CommandInteraction | MessageComponentInteraction) {
     const verify = client.verify;
     await interaction.reply({
         embeds: LoadingEmbed,