Improve typing and delete an unnecessary file
diff --git a/src/utils/getCommandDataByName.ts b/src/utils/getCommandDataByName.ts
index 46f4362..70a2af6 100644
--- a/src/utils/getCommandDataByName.ts
+++ b/src/utils/getCommandDataByName.ts
@@ -1,22 +1,40 @@
 import type Discord from "discord.js";
 import client from "./client.js";
 
+/**
+* @param name The name of the command, not including a leading slash. This can be space or slash separated e.g. "mod/about" or "mod about"
+* @returns A string which when put into Discord will mention the command if the command exists or a codeblock with the command name if it does not
+*
+* @throws Will throw an error if as empty string is passed
+**/
 export const getCommandMentionByName = (name: string): string => {
     const split = name.replaceAll("/", " ").split(" ");
-    const commandName: string = split[0]!;
+    const commandName: string | undefined = split[0];
+    if (commandName === undefined) throw new RangeError(`Invalid command ${name} provided to getCommandByName`);
 
     const filterCommand = (command: Discord.ApplicationCommand) => command.name === commandName;
 
     const command = client.fetchedCommands.filter((c) => filterCommand(c));
-    if (command.size === 0) return `\`/${name.replaceAll("/", " ")}\``;
-    const commandID = command.first()!.id;
+    const commandID = command.first()?.id;
+
+    if (commandID === undefined) return `\`/${name.replaceAll("/", " ")}\``;
+
     return `</${split.join(" ")}:${commandID}>`;
 };
 
+/**
+* @param name The name of the command, not including a leading slash. This can be space or slash separated e.g. "mod/about" or "mod about"
+* @returns An object containing the command name, the command description and a string which when put into Discord will mention the command
+*
+* @throws Will throw an error if the command doesn't exist
+* @throws Will throw an error if as empty string is passed
+**/
 export const getCommandByName = (name: string): { name: string; description: string; mention: string } => {
     const split = name.replaceAll(" ", "/");
-    const command = client.commands["commands/" + split]!;
-    // console.log(command)
+    const command = client.commands["commands/" + split];
+
+    if (command === undefined) throw new RangeError(`Invalid command ${name} provided to getCommandByName`);
+
     const mention = getCommandMentionByName(name);
     return {
         name: command[1].name,
diff --git a/src/utils/migration/migration.ts b/src/utils/migration/migration.ts
deleted file mode 100644
index 6286465..0000000
--- a/src/utils/migration/migration.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import * as fs from "fs";
-import client from "../client.js";
-import _ from "lodash";
-
-const dir = "./data";
-const files = fs.readdirSync(dir);
-
-for (const file of files) {
-    // eslint-disable-next-line @typescript-eslint/no-explicit-any
-    let rsmData: any;
-    try {
-        rsmData = JSON.parse(fs.readFileSync(`${dir}/${file}`, "utf8"));
-    } catch {
-        continue;
-    }
-    if (!rsmData.version || rsmData.version < 3) continue;
-    const nucleusData = await client.database.guilds.readOld(rsmData.guild_info.id);
-    const rsmToNucleus = {
-        id: rsmData.guild_info.id,
-        version: 1,
-        singleEventNotifications: {},
-        filters: {
-            images: {
-                NSFW: rsmData.images?.nsfw,
-                size: rsmData.images?.toosmall
-            },
-            malware: null,
-            wordFilter: {
-                enabled: true,
-                words: {
-                    strict: rsmData.wordfilter?.strict,
-                    loose: rsmData.wordfilter?.soft
-                },
-                allowed: {
-                    users: rsmData.wordfilter?.ignore?.members,
-                    roles: rsmData.wordfilter?.ignore?.roles,
-                    channels: rsmData.wordfilter?.ignore?.channels
-                }
-            },
-            invite: {
-                enabled: rsmData.invite?.enabled,
-                allowed: {
-                    channels: rsmData.invite?.whitelist?.members,
-                    roles: rsmData.invite?.whitelist?.roles,
-                    users: rsmData.invite?.whitelist?.channels
-                }
-            }
-        },
-        welcome: {
-            enabled: true,
-            role: rsmData.welcome?.role,
-            channel: rsmData.welcome?.message?.channel,
-            message: rsmData.welcome?.message?.text ?? null
-        },
-        logging: {
-            logs: {
-                enabled: true,
-                channel: rsmData.log_info?.log_channel
-            },
-            staff: {
-                channel: rsmData.log_info?.staff
-            }
-        },
-        verify: {
-            enabled: true,
-            role: rsmData.verify_role
-        },
-        tickets: {
-            enabled: true,
-            category: rsmData.modmail?.cat,
-            supportRole: rsmData.modmail?.mention,
-            maxTickets: rsmData.modmail?.max
-        },
-        tags: rsmData.tags
-    } as Partial<ReturnType<typeof client.database.guilds.read>>;
-    // console.log(rsmToNucleus)
-    const merged = _.merge(nucleusData, rsmToNucleus);
-    // console.log(merged)
-    await client.database.guilds.write(merged.id!, merged);
-}
diff --git a/src/utils/types/recursivePartial.d.ts b/src/utils/types/recursivePartial.d.ts
new file mode 100644
index 0000000..4f5030b
--- /dev/null
+++ b/src/utils/types/recursivePartial.d.ts
@@ -0,0 +1,6 @@
+type RecursivePartial<T> = {
+  [P in keyof T]?:
+    T[P] extends (infer U)[] ? RecursivePartial<U>[] :
+    T[P] extends object ? RecursivePartial<T[P]> :
+    T[P];
+};