Command registration (for mini)
diff --git a/package.json b/package.json
index d4a4025..affb107 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
         "immutable": "^4.1.0",
         "mongodb": "^4.7.0",
         "node-cron": "^3.0.0",
+        "node-fetch": "^3.3.0",
         "node-tesseract-ocr": "^2.2.1",
         "pastebin-api": "^5.1.1",
         "structured-clone": "^0.2.2",
diff --git a/src/commands/help.ts b/src/commands/help.ts
index 4295f9c..e85cf6b 100644
--- a/src/commands/help.ts
+++ b/src/commands/help.ts
@@ -1,7 +1,9 @@
-import { CommandInteraction } from "discord.js";
+import type { CommandInteraction } from "discord.js";
 import { SlashCommandBuilder } from "@discordjs/builders";
 
-const command = new SlashCommandBuilder().setName("help").setDescription("Shows help for commands");
+const command = new SlashCommandBuilder()
+    .setName("help")
+    .setDescription("Shows help for commands");
 
 const callback = async (interaction: CommandInteraction): Promise<void> => {
     interaction.reply("hel p D:"); // TODO: FINISH THIS FOR RELEASE
diff --git a/src/commands/verify.ts b/src/commands/verify.ts
index b9556a6..bf6a306 100644
--- a/src/commands/verify.ts
+++ b/src/commands/verify.ts
@@ -5,6 +5,7 @@
 const command = new SlashCommandBuilder().setName("verify").setDescription("Get verified in the server");
 
 const callback = async (interaction: CommandInteraction): Promise<void> => {
+    interaction.reply("boo")
     verify(interaction);
 };
 
diff --git a/src/config/default.json b/src/config/default.json
index 7f2fdbd..824f12c 100644
--- a/src/config/default.json
+++ b/src/config/default.json
@@ -50,6 +50,7 @@
         }
     },
     "verify": {
+        "enabled": false,
         "role": null
     },
     "tickets": {
diff --git a/src/events/channelCreate.ts b/src/events/channelCreate.ts
index f3a4785..b3cba33 100644
--- a/src/events/channelCreate.ts
+++ b/src/events/channelCreate.ts
@@ -1,6 +1,6 @@
 import type { GuildAuditLogsEntry } from "discord.js";
 import type { GuildBasedChannel } from "discord.js";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 export const event = "channelCreate";
 
 export async function callback(client: NucleusClient, channel: GuildBasedChannel) {
diff --git a/src/events/channelDelete.ts b/src/events/channelDelete.ts
index d92c994..2c48b02 100644
--- a/src/events/channelDelete.ts
+++ b/src/events/channelDelete.ts
@@ -6,12 +6,12 @@
     ThreadChannel,
     VoiceChannel
 } from "discord.js";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 import getEmojiByName from "../utils/getEmojiByName.js";
 
 export const event = "channelDelete";
 
-export async function callback(client: HaikuClient, channel: GuildBasedChannel) {
+export async function callback(client: NucleusClient, channel: GuildBasedChannel) {
     const { getAuditLog, log, NucleusColors, entry, renderDelta, renderUser } = client.logger;
 
     const auditLog = await getAuditLog(channel.guild, "CHANNEL_DELETE");
diff --git a/src/events/guildBanAdd.ts b/src/events/guildBanAdd.ts
index d1649a3..5fd0b49 100644
--- a/src/events/guildBanAdd.ts
+++ b/src/events/guildBanAdd.ts
@@ -1,11 +1,11 @@
 import type { GuildAuditLogsEntry, GuildBan } from "discord.js";
 import { purgeByUser } from "../actions/tickets/delete.js";
 import { callback as statsChannelRemove } from "../reflex/statsChannelUpdate.js";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 
 export const event = "guildBanAdd";
 
-export async function callback(client: HaikuClient, ban: GuildBan) {
+export async function callback(client: NucleusClient, ban: GuildBan) {
     await statsChannelRemove(client, undefined, ban.guild, ban.user);
     purgeByUser(ban.user.id, ban.guild);
     const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = client.logger;
diff --git a/src/events/guildBanRemove.ts b/src/events/guildBanRemove.ts
index 2c3fc7b..f9b427a 100644
--- a/src/events/guildBanRemove.ts
+++ b/src/events/guildBanRemove.ts
@@ -1,10 +1,10 @@
 import type { GuildAuditLogsEntry, GuildBan } from "discord.js";
 import { purgeByUser } from "../actions/tickets/delete.js";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 
 export const event = "guildBanRemove";
 
-export async function callback(client: HaikuClient, ban: GuildBan) {
+export async function callback(client: NucleusClient, ban: GuildBan) {
     purgeByUser(ban.user.id, ban.guild);
     const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = client.logger;
     const auditLog = await getAuditLog(ban.guild, "MEMBER_BAN_REMOVE");
diff --git a/src/events/guildCreate.ts b/src/events/guildCreate.ts
index b1adbaa..ff6c6b2 100644
--- a/src/events/guildCreate.ts
+++ b/src/events/guildCreate.ts
@@ -1,9 +1,9 @@
 import type { Guild } from "discord.js";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 import guide from "../reflex/guide.js";
 
 export const event = "guildCreate";
 
-export async function callback(_client: HaikuClient, guild: Guild) {
+export async function callback(_client: NucleusClient, guild: Guild) {
     guide(guild);
 }
diff --git a/src/events/guildMemberUpdate.ts b/src/events/guildMemberUpdate.ts
index 543d6ff..0ebfc3d 100644
--- a/src/events/guildMemberUpdate.ts
+++ b/src/events/guildMemberUpdate.ts
@@ -1,9 +1,9 @@
 import type { GuildAuditLogsEntry, GuildMember } from "discord.js";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 
 export const event = "guildMemberUpdate";
 
-export async function callback(client: HaikuClient, before: GuildMember, after: GuildMember) {
+export async function callback(client: NucleusClient, before: GuildMember, after: GuildMember) {
     try {
         const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = client.logger;
         const auditLog = await getAuditLog(after.guild, "MEMBER_UPDATE");
diff --git a/src/events/guildUpdate.ts b/src/events/guildUpdate.ts
index 703b2d9..e463007 100644
--- a/src/events/guildUpdate.ts
+++ b/src/events/guildUpdate.ts
@@ -1,10 +1,10 @@
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 import type { Guild, GuildAuditLogsEntry } from "discord.js";
 import { callback as statsChannelUpdate } from "../reflex/statsChannelUpdate.js";
 
 export const event = "guildUpdate";
 
-export async function callback(client: HaikuClient, before: Guild, after: Guild) {
+export async function callback(client: NucleusClient, 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");
diff --git a/src/events/interactionCreate.ts b/src/events/interactionCreate.ts
index 4feee82..ddc143b 100644
--- a/src/events/interactionCreate.ts
+++ b/src/events/interactionCreate.ts
@@ -6,7 +6,7 @@
 import Fuse from "fuse.js";
 import { autocomplete as tagAutocomplete } from "../commands/tag.js";
 import type { AutocompleteInteraction, Interaction, MessageComponentInteraction } from "discord.js";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 
 export const event = "interactionCreate";
 
@@ -102,6 +102,6 @@
     }
 }
 
-export async function callback(_client: HaikuClient, interaction: Interaction) {
+export async function callback(_client: NucleusClient, interaction: Interaction) {
     await interactionCreate(interaction);
 }
diff --git a/src/events/inviteCreate.ts b/src/events/inviteCreate.ts
index 76dfc1e..7dbf8a7 100644
--- a/src/events/inviteCreate.ts
+++ b/src/events/inviteCreate.ts
@@ -1,11 +1,11 @@
 import type { GuildAuditLogsEntry, Invite } from "discord.js";
 // @ts-expect-error
 import humanizeDuration from "humanize-duration";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 
 export const event = "inviteCreate";
 
-export async function callback(client: HaikuClient, invite: Invite) {
+export async function callback(client: NucleusClient, invite: Invite) {
     const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger;
     const auditLog = await getAuditLog(invite.guild, "INVITE_CREATE");
     const audit = auditLog.entries
diff --git a/src/events/inviteDelete.ts b/src/events/inviteDelete.ts
index cdc6828..e74ad15 100644
--- a/src/events/inviteDelete.ts
+++ b/src/events/inviteDelete.ts
@@ -1,11 +1,11 @@
 import type { GuildAuditLogsEntry, Invite } from "discord.js";
 // @ts-expect-error
 import humanizeDuration from "humanize-duration";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 
 export const event = "inviteDelete";
 
-export async function callback(client: HaikuClient, invite: Invite) {
+export async function callback(client: NucleusClient, invite: Invite) {
     const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger;
     const auditLog = await getAuditLog(invite.guild, "INVITE_DELETE");
     const audit = auditLog.entries
diff --git a/src/events/memberJoin.ts b/src/events/memberJoin.ts
index 95dfde2..93c9186 100644
--- a/src/events/memberJoin.ts
+++ b/src/events/memberJoin.ts
@@ -1,11 +1,11 @@
 import type { GuildMember } from "discord.js";
 import { callback as statsChannelAdd } from "../reflex/statsChannelUpdate.js";
 import { callback as welcome } from "../reflex/welcome.js";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 
 export const event = "guildMemberAdd";
 
-export async function callback(client: HaikuClient, member: GuildMember) {
+export async function callback(client: NucleusClient, member: GuildMember) {
     welcome(client, member);
     statsChannelAdd(client, member);
     const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
diff --git a/src/events/memberLeave.ts b/src/events/memberLeave.ts
index 8fa0c76..4731d58 100644
--- a/src/events/memberLeave.ts
+++ b/src/events/memberLeave.ts
@@ -1,12 +1,12 @@
 import type { GuildAuditLogsEntry, GuildMember } from "discord.js";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 
 import { purgeByUser } from "../actions/tickets/delete.js";
 import { callback as statsChannelRemove } from "../reflex/statsChannelUpdate.js";
 
 export const event = "guildMemberRemove";
 
-export async function callback(client: HaikuClient, member: GuildMember) {
+export async function callback(client: NucleusClient, member: GuildMember) {
     purgeByUser(member.id, member.guild);
     await statsChannelRemove(client, member);
     const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
diff --git a/src/events/messageCreate.ts b/src/events/messageCreate.ts
index 76b6855..3f85de6 100644
--- a/src/events/messageCreate.ts
+++ b/src/events/messageCreate.ts
@@ -1,4 +1,4 @@
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 import { LinkCheck, MalwareCheck, NSFWCheck, SizeCheck, TestString, TestImage } from "../reflex/scanners.js";
 import logAttachment from "../premium/attachmentLogs.js";
 import createLogException from "../utils/createLogException.js";
@@ -9,7 +9,7 @@
 
 export const event = "messageCreate";
 
-export async function callback(_client: HaikuClient, message: Message) {
+export async function callback(_client: NucleusClient, message: Message) {
     if (!message.guild) return;
     if (message.author.bot) return;
     if (message.channel.type === "DM") return;
diff --git a/src/events/messageDelete.ts b/src/events/messageDelete.ts
index bc668f1..ddeff96 100644
--- a/src/events/messageDelete.ts
+++ b/src/events/messageDelete.ts
@@ -1,9 +1,9 @@
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 import type { GuildAuditLogsEntry, Message } from "discord.js";
 
 export const event = "messageDelete";
 
-export async function callback(client: HaikuClient, message: Message) {
+export async function callback(client: NucleusClient, message: Message) {
     try {
         if (message.author.id === client.user.id) return;
         if (client.noLog.includes(`${message.id}/${message.channel.id}/${message.id}`)) return;
diff --git a/src/events/messageEdit.ts b/src/events/messageEdit.ts
index 4c482cc..37178a7 100644
--- a/src/events/messageEdit.ts
+++ b/src/events/messageEdit.ts
@@ -1,9 +1,9 @@
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 import type { Message, MessageReference } from "discord.js";
 
 export const event = "messageUpdate";
 
-export async function callback(client: HaikuClient, oldMessage: Message, newMessage: Message) {
+export async function callback(client: NucleusClient, oldMessage: Message, newMessage: Message) {
     if (newMessage.author.id === client.user.id) return;
     if (!newMessage.guild) return;
     const { log, NucleusColors, entry, renderUser, renderDelta, renderNumberDelta, renderChannel } = client.logger;
diff --git a/src/events/roleCreate.ts b/src/events/roleCreate.ts
index c8a32b1..25e9c98 100644
--- a/src/events/roleCreate.ts
+++ b/src/events/roleCreate.ts
@@ -1,9 +1,9 @@
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 import type { GuildAuditLogsEntry, Role } from "discord.js";
 
 export const event = "roleCreate";
 
-export async function callback(client: HaikuClient, role: Role) {
+export async function callback(client: NucleusClient, role: Role) {
     const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderRole } = client.logger;
     if (role.managed) return;
     const auditLog = await getAuditLog(role.guild, "ROLE_CREATE");
diff --git a/src/events/roleDelete.ts b/src/events/roleDelete.ts
index 1f71f25..4c89565 100644
--- a/src/events/roleDelete.ts
+++ b/src/events/roleDelete.ts
@@ -1,10 +1,10 @@
 import getEmojiByName from "../utils/getEmojiByName.js";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 import type { GuildAuditLogsEntry, Role } from "discord.js";
 
 export const event = "roleDelete";
 
-export async function callback(client: HaikuClient, role: Role) {
+export async function callback(client: NucleusClient, role: Role) {
     const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
     if (role.managed) return;
     const auditLog = await getAuditLog(role.guild, "ROLE_DELETE");
diff --git a/src/events/roleUpdate.ts b/src/events/roleUpdate.ts
index 357a22f..fc26d6c 100644
--- a/src/events/roleUpdate.ts
+++ b/src/events/roleUpdate.ts
@@ -1,10 +1,10 @@
 import type { Role } from "discord.js";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 import getEmojiByName from "../utils/getEmojiByName.js";
 
 export const event = "roleUpdate";
 
-export async function callback(client: HaikuClient, or: Role, nr: Role) {
+export async function callback(client: NucleusClient, or: Role, nr: Role) {
     const { getAuditLog, log, NucleusColors, entry, renderDelta, renderUser, renderRole } = client.logger;
 
     const auditLog = await getAuditLog(nr.guild, "ROLE_UPDATE");
diff --git a/src/events/stickerCreate.ts b/src/events/stickerCreate.ts
index b7a417c..295d48b 100644
--- a/src/events/stickerCreate.ts
+++ b/src/events/stickerCreate.ts
@@ -1,9 +1,9 @@
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 import type { GuildAuditLogsEntry, Sticker } from "discord.js";
 
 export const event = "stickerDelete";
 
-export async function callback(client: HaikuClient, emoji: Sticker) {
+export async function callback(client: NucleusClient, 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: GuildAuditLogsEntry) => entry.target!.id === emoji.id).first();
diff --git a/src/events/stickerDelete.ts b/src/events/stickerDelete.ts
index 8130d8a..fed99e6 100644
--- a/src/events/stickerDelete.ts
+++ b/src/events/stickerDelete.ts
@@ -1,9 +1,9 @@
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 import type { GuildAuditLogsEntry, Sticker } from "discord.js";
 
 export const event = "stickerDelete";
 
-export async function callback(client: HaikuClient, emoji: Sticker) {
+export async function callback(client: NucleusClient, 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: GuildAuditLogsEntry) => entry.target!.id === emoji.id).first();
diff --git a/src/events/stickerUpdate.ts b/src/events/stickerUpdate.ts
index 1421ec2..0ac000e 100644
--- a/src/events/stickerUpdate.ts
+++ b/src/events/stickerUpdate.ts
@@ -1,9 +1,9 @@
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 import type { Sticker } from "discord.js";
 
 export const event = "stickerUpdate";
 
-export async function callback(client: HaikuClient, oe: Sticker, ne: Sticker) {
+export async function callback(client: NucleusClient, oe: Sticker, ne: Sticker) {
     const { getAuditLog, log, NucleusColors, entry, renderDelta, renderUser } = client.logger;
 
     if (oe.name === ne.name) return;
diff --git a/src/events/threadCreate.ts b/src/events/threadCreate.ts
index f0f32e5..1f1b758 100644
--- a/src/events/threadCreate.ts
+++ b/src/events/threadCreate.ts
@@ -1,10 +1,10 @@
 import type { GuildAuditLogsEntry, ThreadChannel } from "discord.js";
 // @ts-expect-error
 import humanizeDuration from "humanize-duration";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 export const event = "threadCreate";
 
-export async function callback(client: HaikuClient, thread: ThreadChannel) {
+export async function callback(client: NucleusClient, 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: GuildAuditLogsEntry) => entry.target!.id === thread.id).first();
diff --git a/src/events/threadDelete.ts b/src/events/threadDelete.ts
index c166f86..cdc89ee 100644
--- a/src/events/threadDelete.ts
+++ b/src/events/threadDelete.ts
@@ -1,10 +1,10 @@
 import type { GuildAuditLogsEntry, ThreadChannel } from "discord.js";
 // @ts-expect-error
 import humanizeDuration from "humanize-duration";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 export const event = "threadDelete";
 
-export async function callback(client: HaikuClient, thread: ThreadChannel) {
+export async function callback(client: NucleusClient, 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: GuildAuditLogsEntry) => entry.target!.id === thread.id).first();
diff --git a/src/events/threadUpdate.ts b/src/events/threadUpdate.ts
index 20247d6..9125fcb 100644
--- a/src/events/threadUpdate.ts
+++ b/src/events/threadUpdate.ts
@@ -1,11 +1,11 @@
 import type { GuildAuditLogsEntry, ThreadChannel } from "discord.js";
 // @ts-expect-error
 import humanizeDuration from "humanize-duration";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 
 export const event = "threadUpdate";
 
-export async function callback(client: HaikuClient, before: ThreadChannel, after: ThreadChannel) {
+export async function callback(client: NucleusClient, before: ThreadChannel, after: ThreadChannel) {
     const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger;
     const auditLog = await getAuditLog(after.guild, "THREAD_UPDATE");
     const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === after.id).first();
diff --git a/src/events/webhookUpdate.ts b/src/events/webhookUpdate.ts
index e4e9659..a991c66 100644
--- a/src/events/webhookUpdate.ts
+++ b/src/events/webhookUpdate.ts
@@ -1,9 +1,9 @@
 import type { GuildAuditLogsEntry, Webhook } from "discord.js";
 import type Discord from "discord.js";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 export const event = "webhookUpdate";
 
-export async function callback(client: HaikuClient, channel: Discord.GuildChannel) {
+export async function callback(client: NucleusClient, channel: Discord.GuildChannel) {
     try {
         const { getAuditLog, log, NucleusColors, entry, renderUser, renderChannel, renderDelta } = client.logger;
         let auditLogCreate = getAuditLog(channel.guild, "WEBHOOK_CREATE");
diff --git a/src/premium/createTranscript.ts b/src/premium/createTranscript.ts
index f2358d8..6805017 100644
--- a/src/premium/createTranscript.ts
+++ b/src/premium/createTranscript.ts
@@ -11,10 +11,9 @@
 import EmojiEmbed from "../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../utils/getEmojiByName.js";
 import { PasteClient, Publicity, ExpireDate } from "pastebin-api";
-import config from "../config/main.json" assert { type: "json" };
 import client from "../utils/client.js";
 
-const pbClient = new PasteClient(config.pastebinApiKey);
+const pbClient = new PasteClient(client.config.pastebinApiKey);
 
 export default async function (interaction: CommandInteraction | MessageComponentInteraction) {
     if (interaction.channel === null) return;
diff --git a/src/reflex/statsChannelUpdate.ts b/src/reflex/statsChannelUpdate.ts
index cd1c8ef..d807267 100644
--- a/src/reflex/statsChannelUpdate.ts
+++ b/src/reflex/statsChannelUpdate.ts
@@ -1,5 +1,5 @@
 import type { Guild, User } from "discord.js";
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 import type { GuildMember } from "discord.js";
 import convertCurlyBracketString from "../utils/convertCurlyBracketString.js";
 import singleNotify from "../utils/singleNotify.js";
@@ -9,7 +9,7 @@
     name: string;
 }
 
-export async function callback(client: HaikuClient, member?: GuildMember, guild?: Guild, user?: User) {
+export async function callback(client: NucleusClient, member?: GuildMember, guild?: Guild, user?: User) {
     if (!member && !guild) return;
     guild = await client.guilds.fetch(member ? member.guild.id : guild!.id);
     if (!guild) return;
diff --git a/src/reflex/verify.ts b/src/reflex/verify.ts
index bbb0992..6458439 100644
--- a/src/reflex/verify.ts
+++ b/src/reflex/verify.ts
@@ -2,11 +2,10 @@
 import Discord, {
     CommandInteraction,
     GuildMember,
-    Interaction,
     MessageComponentInteraction,
-    Permissions,
     Role,
-    ButtonStyle
+    ButtonStyle,
+    PermissionsBitField
 } from "discord.js";
 import EmojiEmbed from "../utils/generateEmojiEmbed.js";
 import fetch from "node-fetch";
@@ -22,7 +21,7 @@
     uName: string;
     gName: string;
     gIcon: string;
-    interaction: Interaction;
+    interaction: Discord.MessageComponentInteraction;
 }
 
 function step(i: number) {
@@ -44,7 +43,7 @@
                     .setTitle("Verify")
                     .setDescription("Verify is not enabled on this server")
                     .setFooter({
-                        text: (interaction.member!.permissions as Permissions).has("MANAGE_GUILD")
+                        text: (interaction.member!.permissions as PermissionsBitField).has("ManageGuild")
                             ? "You can enable it by running /settings verify"
                             : ""
                     })
@@ -95,7 +94,7 @@
                     .setEmoji("CONTROL.BLOCKCROSS")
             ],
             components: [
-                new Discord.ActionRowBuilder().addComponents([
+                new Discord.ActionRowBuilder<Discord.ButtonBuilder>().addComponents([
                     new Discord.ButtonBuilder()
                         .setLabel("Check webpage")
                         .setStyle(ButtonStyle.Link)
@@ -120,9 +119,7 @@
         });
         if (
             await NSFWCheck(
-                (interaction.member as GuildMember).user.displayAvatarURL({
-                    format: "png"
-                })
+                (interaction.member as GuildMember).user.displayAvatarURL({extension: "png", forceStatic: true})
             )
         ) {
             return await interaction.editReply({
@@ -139,7 +136,7 @@
             });
         }
     }
-    if (config.filters.wordFilter) {
+    if (config.filters.wordFilter.enabled) {
         await interaction.editReply({
             embeds: [
                 new EmojiEmbed()
@@ -217,8 +214,8 @@
         rName: role.name,
         uName: interaction.member!.user.username,
         gName: interaction.guild!.name,
-        gIcon: interaction.guild!.iconURL({ format: "png" }),
-        interaction: interaction
+        gIcon: interaction.guild!.iconURL({ extension: "png", size: 256 }) ?? "https://assets-global.website-files.com/6257adef93867e50d84d30e2/636e0a6a49cf127bf92de1e2_icon_clyde_blurple_RGB.png",
+        interaction: interaction as MessageComponentInteraction
     };
     await interaction.editReply({
         embeds: [
@@ -229,7 +226,7 @@
                 .setEmoji("MEMBER.JOIN")
         ],
         components: [
-            new Discord.ActionRowBuilder().addComponents([
+            new Discord.ActionRowBuilder<Discord.ButtonBuilder>().addComponents([
                 new Discord.ButtonBuilder()
                     .setLabel("Verify")
                     .setStyle(ButtonStyle.Link)
diff --git a/src/reflex/welcome.ts b/src/reflex/welcome.ts
index 241185d..47ed140 100644
--- a/src/reflex/welcome.ts
+++ b/src/reflex/welcome.ts
@@ -1,10 +1,10 @@
-import type { HaikuClient } from "../utils/haiku/index.js";
+import type { NucleusClient } from "../utils/client.js";
 import convertCurlyBracketString from "../utils/convertCurlyBracketString.js";
 import client from "../utils/client.js";
 import EmojiEmbed from "../utils/generateEmojiEmbed.js";
 import { GuildChannel, GuildMember, BaseGuildTextChannel } from "discord.js";
 
-export async function callback(_client: HaikuClient, member: GuildMember) {
+export async function callback(_client: NucleusClient, member: GuildMember) {
     if (member.user.bot) return;
     const config = await client.database.guilds.read(member.guild.id);
     if (!config.welcome.enabled) return;
diff --git a/src/utils/client.ts b/src/utils/client.ts
index 7d608c7..6aa9b43 100644
--- a/src/utils/client.ts
+++ b/src/utils/client.ts
@@ -1,14 +1,16 @@
-import { Client } from 'discord.js';
+import Discord, { Client, Interaction } from 'discord.js';
 import { Logger } from "../utils/log.js";
 import Memory from "../utils/memory.js";
 import type { VerifySchema } from "../reflex/verify.js";
 import { Guilds, History, ModNotes, Premium } from "../utils/database.js";
 import EventScheduler from "../utils/eventScheduler.js";
 import type { RoleMenuSchema } from "../actions/roleMenu.js";
+import config from "../config/main.json" assert { type: "json" };
 
 
 class NucleusClient extends Client {
     logger = Logger;
+    config: typeof config = config;
     verify: Record<string, VerifySchema> = {};
     roleMenu: Record<string, RoleMenuSchema> = {};
     memory: Memory = new Memory() as Memory;
@@ -20,6 +22,14 @@
         premium: Premium;
         eventScheduler: EventScheduler;
     };
+    // commands: Record<string, {
+    //     command: Discord.SlashCommandBuilder |
+    //              ((builder: Discord.SlashCommandBuilder) => Discord.SlashCommandBuilder) |
+    //              Discord.SlashCommandSubcommandBuilder | ((builder: Discord.SlashCommandSubcommandBuilder) => Discord.SlashCommandSubcommandBuilder) | Discord.SlashCommandSubcommandGroupBuilder | ((builder: Discord.SlashCommandSubcommandGroupBuilder) => Discord.SlashCommandSubcommandGroupBuilder),
+    //     callback: (interaction: Interaction) => Promise<void>,
+    //     check: (interaction: Interaction) => Promise<boolean> | boolean
+    // }> = {};
+    commands: Discord.Collection<string, [Function, Function]> = new Discord.Collection();
 
     constructor(database: typeof NucleusClient.prototype.database) {
         super({ intents: 32767 });
diff --git a/src/utils/commandRegistration/getFilesInFolder.ts b/src/utils/commandRegistration/getFilesInFolder.ts
index a669065..d8a1298 100644
--- a/src/utils/commandRegistration/getFilesInFolder.ts
+++ b/src/utils/commandRegistration/getFilesInFolder.ts
@@ -1,23 +1,27 @@
 import fs from "fs";
 
-export default async function getSubcommandsInFolder(path: string) {
+export default async function getSubcommandsInFolder(path: string, indent: string = "") {
     const files = fs.readdirSync(path, { withFileTypes: true }).filter(
         file => !file.name.endsWith(".ts") && !file.name.endsWith(".map")
     );
     const subcommands = [];
     const subcommandGroups = [];
+    let errors = 0;
     for (const file of files) {
         if (file.name === "_meta.js") continue;
-        // If its a folder
-        if (file.isDirectory()) {
-            // Get the _meta.ts file
-            console.log(`│ ├─ Loading subcommand group ${file.name}}`)
-            subcommandGroups.push((await import(`../../../${path}/${file.name}/_meta.js`)).command);
-        } else if (file.name.endsWith(".js")) {
-            // If its a file
-            console.log(`│ ├─ Loading subcommand ${file.name}}`)
-            subcommands.push((await import(`../../../${path}/${file.name}`)).command);
+        try {
+            if (file.isDirectory()) {
+                // Get the _meta.ts file
+                subcommandGroups.push((await import(`../../../${path}/${file.name}/_meta.js`)).command);
+            } else if (file.name.endsWith(".js")) {
+                // If its a file
+                console.log(`│  ${indent}├─ Loading subcommand ${file.name}`)
+                subcommands.push((await import(`../../../${path}/${file.name}`)).command);
+            }
+        } catch (e) {
+            console.error(`│  ${indent}│  └─ Error loading ${file.name}: ${e}`);
+            errors++;
         }
     }
-    return {subcommands, subcommandGroups};
+    return {subcommands, subcommandGroups, errors};
 }
diff --git a/src/utils/commandRegistration/register.ts b/src/utils/commandRegistration/register.ts
index af0b5fc..a734921 100644
--- a/src/utils/commandRegistration/register.ts
+++ b/src/utils/commandRegistration/register.ts
@@ -1,9 +1,16 @@
-import { SlashCommandBuilder } from 'discord.js';
+import { Interaction, SlashCommandBuilder } from 'discord.js';
 import config from "../../config/main.json" assert { type: "json" };
 import client from "../client.js";
 import fs from "fs";
 
 
+const colours = {
+    red: "\x1b[31m",
+    green: "\x1b[32m",
+    yellow: "\x1b[33m",
+    none: "\x1b[0m"
+}
+
 async function registerCommands() {
     const developmentMode = config.enableDevelopment;
     const commands = [];
@@ -14,15 +21,18 @@
     console.log(`Registering ${files.length} commands`)
     let i = 0;
     for (const file of files) {
-        // Box drawing characters: | └ ─ ┌ ┐ ┘ ┬ ┤ ├ ┴ ┼
-        console.log(`├─ ${file.name}`)
+        const last = i === files.length - 1 ? "└" : "├";
         if (file.isDirectory()) {
+            console.log(`${last}─ ${colours.yellow}Loading subcommands of ${file.name}${colours.none}`)
             commands.push((await import(`../../../${config.commandsFolder}/${file.name}/_meta.js`)).command);
         } else if (file.name.endsWith(".js")) {
-            commands.push((await import(`../../../${config.commandsFolder}/${file.name}`)).command);
+            console.log(`${last}─ ${colours.yellow}Loading command ${file.name}${colours.none}`)
+            const fetched = (await import(`../../../${config.commandsFolder}/${file.name}`));
+            commands.push(fetched.command);
+            client.commands.set(fetched.command.name, [fetched.check, fetched.callback]);
         }
         i++;
-        console.log(`├─ Loaded ${file.name} [${i} / ${files.length}]`)
+        console.log(`${last.replace("└", " ").replace("├", "│")}  └─ ${colours.green}Loaded ${file.name} [${i} / ${files.length}]${colours.none}`)
     }
     console.log(`Loaded ${commands.length} commands, processing...`)
     const processed = []
@@ -39,11 +49,9 @@
 
     if (developmentMode) {
         const guild = await client.guilds.fetch(config.developmentGuildID);
-        guild.commands.set([])
         guild.commands.set(processed);
         console.log(`Commands registered in ${guild.name}`)
     } else {
-        client.application!.commands.set([])
         client.application!.commands.set(processed);
         console.log(`Commands registered globally`)
     }
@@ -51,11 +59,83 @@
 };
 
 async function registerEvents() {
-    // pass
+    console.log("Reading events")
+    const files = fs.readdirSync(config.eventsFolder, { withFileTypes: true }).filter(
+        file => !file.name.endsWith(".ts") && !file.name.endsWith(".map")
+    );
+    console.log(`Registering ${files.length} events`)
+    let i = 0;
+    let errors = 0;
+    for (const file of files) {
+        const last = i === files.length - 1 ? "└" : "├";
+        i++;
+        try {
+            console.log(`${last}─ ${colours.yellow}Loading event ${file.name}${colours.none}`)
+            const event = (await import(`../../../${config.eventsFolder}/${file.name}`));
+
+            client.on(event.event, event.callback.bind(null, client));
+
+            console.log(`${last.replace("└", " ").replace("├", "│")}  └─ ${colours.green}Loaded ${file.name} [${i} / ${files.length}]${colours.none}`)
+        } catch (e) {
+            errors++;
+            console.log(`${last.replace("└", " ").replace("├", "│")}  └─ ${colours.red}Failed to load ${file.name} [${i} / ${files.length}]${colours.none}`)
+        }
+    }
+    console.log(`Loaded ${files.length - errors} events (${errors} failed)`)
 };
 
+async function registerCommandHandler() {
+    client.on("interactionCreate", async (interaction: Interaction) => {
+        if (!interaction.isCommand()) return;
+
+        const commandName = interaction.commandName;
+        const subcommandGroupName = interaction.options.getSubcommandGroup(false);
+        const subcommandName = interaction.options.getSubcommand(false);
+
+        let fullCommandName = commandName + (subcommandGroupName ? ` ${subcommandGroupName}` : "") + (subcommandName ? ` ${subcommandName}` : "");
+
+        const command = this.commands.get(fullCommandName);
+        if (!command) return;
+
+        const sendErrorMessage = async (error: Error) => {
+            if (this.listenerCount("commandError")) {
+                return this.emit("commandError", interaction, error);
+            }
+            let method = (!interaction.deferred && !interaction.replied) ? interaction.reply.bind(interaction) : interaction.followUp.bind(interaction);
+            await method({
+                embeds: [
+                    new Embed()
+                        .setColor(0xff0000)
+                        .setTitle("I couldn't run that command")
+                        .setDescription(error.message ?? error.toString())
+                ]
+            , ephemeral: true});
+        }
+
+        try {
+            let hasPermission = await command.check(interaction);
+
+            if (!hasPermission) {
+                sendErrorMessage(new CheckFailedError("You don't have permission to run this command"));
+                return;
+            }
+        } catch (error) {
+            sendErrorMessage(error);
+            return;
+        }
+        try {
+            await command.callback(interaction);
+        } catch (error) {
+            this._error(error);
+            sendErrorMessage(error);
+            return;
+        }
+    });
+}
+
 export default async function register() {
-    console.log("> Registering commands")
     await registerCommands();
+    await registerCommandHandler();
     await registerEvents();
+    console.log(`${colours.green}Registered commands and events${colours.none}`)
 };
diff --git a/src/utils/commandRegistration/slashCommandBuilder.ts b/src/utils/commandRegistration/slashCommandBuilder.ts
index 719855f..c7ac55f 100644
--- a/src/utils/commandRegistration/slashCommandBuilder.ts
+++ b/src/utils/commandRegistration/slashCommandBuilder.ts
@@ -4,8 +4,17 @@
 import getSubcommandsInFolder from "./getFilesInFolder.js";
 
 
+const colours = {
+    red: "\x1b[31m",
+    green: "\x1b[32m",
+    none: "\x1b[0m"
+}
+
+
 export async function group(name: string, description: string, path: string) {
-    const fetched = await getSubcommandsInFolder(config.commandsFolder + "/" + path)
+    console.log(`│  ├─ Loading group ${name}`)
+    const fetched = await getSubcommandsInFolder(config.commandsFolder + "/" + path, "│  ")
+    console.log(`│  │  └─ ${fetched.errors ? colours.red : colours.green}Loaded ${fetched.subcommands.length} subcommands for ${name} (${fetched.errors} failed)${colours.none}`)
     return (subcommandGroup: SlashCommandSubcommandGroupBuilder) => {
         subcommandGroup
             .setName(name)
@@ -21,7 +30,7 @@
 
 export async function command(name: string, description: string, path: string) {
     const fetched = await getSubcommandsInFolder(config.commandsFolder + "/" + path);
-    console.log(`│ ├─ Loaded ${fetched.subcommands.length} subcommands and ${fetched.subcommandGroups.length} subcommand groups for ${name}`)
+    console.log(`│  ├─ ${fetched.errors ? colours.red : colours.green}Loaded ${fetched.subcommands.length} subcommands and ${fetched.subcommandGroups.length} subcommand groups for ${name} (${fetched.errors} failed)${colours.none}`)
     return (command: SlashCommandBuilder) => {
         command.setName(name)
         command.setDescription(description)