huge changes once again
diff --git a/ClicksMigratingProblems/randomPunishments.js b/ClicksMigratingProblems/randomPunishments.js
new file mode 100644
index 0000000..a2d9bf5
--- /dev/null
+++ b/ClicksMigratingProblems/randomPunishments.js
@@ -0,0 +1,26 @@
+import { MongoClient } from 'mongodb';
+
+const mongoClient = new MongoClient('mongodb://127.0.0.1:27017/local');
+await mongoClient.connect()
+const database = mongoClient.db("Nucleus");
+const collection = database.collection("history");
+
+for (let i = 0; i < 100; i++) {
+    // Select a type
+    let type = ["join", "unban", "leave", "ban", "softban", "kick", "mute", "purge", "warn", "nickname"][Math.floor(Math.random() * 9)];
+    // Select a random date in the last year
+    let date = new Date(new Date().getTime() - Math.floor(Math.random() * 31536000000));
+    // Add to database
+    await collection.insertOne({
+        type: type,
+        occurredAt: date,
+        user: "438733159748599813",
+        guild: "864185037078790195",
+        moderator: (["unban", "ban", "softban", "kick", "mute", "purge", "warn"].includes(type)) ? "438733159748599813" : null,
+        reason: (["unban", "ban", "softban", "kick", "mute", "purge", "warn"].includes(type)) ? "Test" : null,
+        before: (type == "nickname") ? "TestBefore" : null,
+        after: (type == "nickname") ? "TestAfter" : null,
+        amount: (type == "purge") ? Math.floor(Math.random() * 100) : null,
+    });
+    console.log("Inserted document " + i);
+}
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index 3e187f2..0000000
--- a/package-lock.json
+++ /dev/null
@@ -1,2920 +0,0 @@
-{
-  "name": "nucleus",
-  "version": "0.0.1",
-  "lockfileVersion": 2,
-  "requires": true,
-  "packages": {
-    "": {
-      "name": "nucleus",
-      "version": "0.0.1",
-      "license": "SEE LICENSE IN LICENSE",
-      "dependencies": {
-        "@discordjs/builders": "^0.12.0",
-        "@ungap/structured-clone": "^1.0.1",
-        "body-parser": "^1.20.0",
-        "discord.js": "^13.8.0",
-        "express": "^4.18.1",
-        "humanize": "^0.0.9",
-        "humanize-duration": "^3.27.1",
-        "jshaiku": "file:../haiku",
-        "json-diff": "^0.7.1",
-        "mongodb": "^4.7.0",
-        "node-tesseract": "^0.2.7",
-        "structured-clone": "^0.2.2",
-        "tesseract.js": "^2.1.5",
-        "typescript": "^4.5.5",
-        "unscan": "^1.1.2"
-      }
-    },
-    "../haiku": {
-      "name": "jshaiku",
-      "version": "1.0.0",
-      "license": "AGPL-3.0",
-      "dependencies": {
-        "@discordjs/builders": "^0.11.0",
-        "@discordjs/rest": "^0.2.0-canary.0",
-        "@types/node-cron": "^3.0.1",
-        "ansi-styles": "^6.1.0",
-        "chalk": "^5.0.0",
-        "discord-api-types": "^0.26.1",
-        "discord.js": "^13.8.0",
-        "node-cron": "^3.0.0"
-      },
-      "devDependencies": {
-        "@babel/core": "^7.16.7",
-        "@babel/preset-env": "^7.16.8",
-        "@babel/preset-typescript": "^7.16.7",
-        "@types/jest": "^27.4.0",
-        "babel-jest": "^27.4.6",
-        "jest": "^27.4.7",
-        "ts-node": "^10.4.0",
-        "typescript": "4.5.4"
-      }
-    },
-    "node_modules/@discordjs/builders": {
-      "version": "0.12.0",
-      "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.12.0.tgz",
-      "integrity": "sha512-Vx2MjUZd6QVo1uS2uWt708Fd6cHWGFblAvbpL5EBO+kLl0BADmPwwvts+YJ/VfSywed6Vsk6K2cEooR/Ytjhjw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@sindresorhus/is": "^4.3.0",
-        "discord-api-types": "^0.26.1",
-        "ts-mixer": "^6.0.0",
-        "tslib": "^2.3.1",
-        "zod": "^3.11.6"
-      },
-      "engines": {
-        "node": ">=16.9.0"
-      }
-    },
-    "node_modules/@discordjs/collection": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.7.0.tgz",
-      "integrity": "sha512-R5i8Wb8kIcBAFEPLLf7LVBQKBDYUL+ekb23sOgpkpyGT+V4P7V83wTxcsqmX+PbqHt4cEHn053uMWfRqh/Z/nA==",
-      "engines": {
-        "node": ">=16.9.0"
-      }
-    },
-    "node_modules/@sapphire/async-queue": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.3.1.tgz",
-      "integrity": "sha512-FFTlPOWZX1kDj9xCAsRzH5xEJfawg1lNoYAA+ecOWJMHOfiZYb1uXOI3ne9U4UILSEPwfE68p3T9wUHwIQfR0g==",
-      "engines": {
-        "node": ">=v14.0.0",
-        "npm": ">=7.0.0"
-      }
-    },
-    "node_modules/@sapphire/shapeshift": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.2.0.tgz",
-      "integrity": "sha512-asNgE5Ooil2/oGIAj6vZMoUc2ZFED0TGYD7jwvZsjHPQZBEh9ITj94ca4bCgiCR1s2ER/UjzykH+5wE3ebVZnQ==",
-      "engines": {
-        "node": ">=v15.0.0",
-        "npm": ">=7.0.0"
-      }
-    },
-    "node_modules/@sindresorhus/is": {
-      "version": "4.6.0",
-      "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
-      "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sindresorhus/is?sponsor=1"
-      }
-    },
-    "node_modules/@types/node": {
-      "version": "17.0.21",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz",
-      "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==",
-      "license": "MIT"
-    },
-    "node_modules/@types/node-fetch": {
-      "version": "2.6.1",
-      "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz",
-      "integrity": "sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==",
-      "license": "MIT",
-      "dependencies": {
-        "@types/node": "*",
-        "form-data": "^3.0.0"
-      }
-    },
-    "node_modules/@types/node-fetch/node_modules/form-data": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
-      "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
-      "license": "MIT",
-      "dependencies": {
-        "asynckit": "^0.4.0",
-        "combined-stream": "^1.0.8",
-        "mime-types": "^2.1.12"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/@types/webidl-conversions": {
-      "version": "6.1.1",
-      "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz",
-      "integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q==",
-      "license": "MIT"
-    },
-    "node_modules/@types/whatwg-url": {
-      "version": "8.2.1",
-      "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.1.tgz",
-      "integrity": "sha512-2YubE1sjj5ifxievI5Ge1sckb9k/Er66HyR2c+3+I6VDUUg1TLPdYYTEbQ+DjRkS4nTxMJhgWfSfMRD2sl2EYQ==",
-      "license": "MIT",
-      "dependencies": {
-        "@types/node": "*",
-        "@types/webidl-conversions": "*"
-      }
-    },
-    "node_modules/@types/ws": {
-      "version": "8.5.3",
-      "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
-      "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==",
-      "dependencies": {
-        "@types/node": "*"
-      }
-    },
-    "node_modules/@ungap/structured-clone": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.0.1.tgz",
-      "integrity": "sha512-zKVyTt6rELvPXYwcVPTJcPFtY0AckN5A7xWuc7owBqR0FdtuDYhE9MZZUi6IY1kZUQFSXV1B3UOOIyLkVHYd2w==",
-      "license": "ISC"
-    },
-    "node_modules/accepts": {
-      "version": "1.3.8",
-      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
-      "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
-      "license": "MIT",
-      "dependencies": {
-        "mime-types": "~2.1.34",
-        "negotiator": "0.6.3"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/array-flatten": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
-      "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
-      "license": "MIT"
-    },
-    "node_modules/asynckit": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
-      "license": "MIT"
-    },
-    "node_modules/balanced-match": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
-      "license": "MIT"
-    },
-    "node_modules/base64-js": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
-      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "license": "MIT"
-    },
-    "node_modules/blueimp-load-image": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/blueimp-load-image/-/blueimp-load-image-3.0.0.tgz",
-      "integrity": "sha512-Q9rFbd4ZUNvzSFmRXx9MoG0RwWwJeMjjEUbG7WIOJgUg22Jgkow0wL5b35B6qwiBscxACW9OHdrP5s2vQ3x8DQ==",
-      "license": "MIT"
-    },
-    "node_modules/bmp-js": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz",
-      "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=",
-      "license": "MIT"
-    },
-    "node_modules/body-parser": {
-      "version": "1.20.0",
-      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
-      "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
-      "license": "MIT",
-      "dependencies": {
-        "bytes": "3.1.2",
-        "content-type": "~1.0.4",
-        "debug": "2.6.9",
-        "depd": "2.0.0",
-        "destroy": "1.2.0",
-        "http-errors": "2.0.0",
-        "iconv-lite": "0.4.24",
-        "on-finished": "2.4.1",
-        "qs": "6.10.3",
-        "raw-body": "2.5.1",
-        "type-is": "~1.6.18",
-        "unpipe": "1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.8",
-        "npm": "1.2.8000 || >= 1.4.16"
-      }
-    },
-    "node_modules/brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-      "license": "MIT",
-      "dependencies": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "node_modules/bson": {
-      "version": "4.6.4",
-      "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.4.tgz",
-      "integrity": "sha512-TdQ3FzguAu5HKPPlr0kYQCyrYUYh8tFM+CMTpxjNzVzxeiJY00Rtuj3LXLHSgiGvmaWlZ8PE+4KyM2thqE38pQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "buffer": "^5.6.0"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/buffer": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
-      "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "base64-js": "^1.3.1",
-        "ieee754": "^1.1.13"
-      }
-    },
-    "node_modules/bytes": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
-      "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/call-bind": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
-      "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
-      "license": "MIT",
-      "dependencies": {
-        "function-bind": "^1.1.1",
-        "get-intrinsic": "^1.0.2"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/cli-color": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.1.tgz",
-      "integrity": "sha512-eBbxZF6fqPUNnf7CLAFOersUnyYzv83tHFLSlts+OAHsNendaqv2tHCq+/MO+b3Y+9JeoUlIvobyxG/Z8GNeOg==",
-      "license": "ISC",
-      "dependencies": {
-        "d": "^1.0.1",
-        "es5-ext": "^0.10.53",
-        "es6-iterator": "^2.0.3",
-        "memoizee": "^0.4.15",
-        "timers-ext": "^0.1.7"
-      },
-      "engines": {
-        "node": ">=0.10"
-      }
-    },
-    "node_modules/colors": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
-      "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.1.90"
-      }
-    },
-    "node_modules/combined-stream": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
-      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
-      "license": "MIT",
-      "dependencies": {
-        "delayed-stream": "~1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/commander": {
-      "version": "8.3.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
-      "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 12"
-      }
-    },
-    "node_modules/concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
-      "license": "MIT"
-    },
-    "node_modules/content-disposition": {
-      "version": "0.5.4",
-      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
-      "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
-      "license": "MIT",
-      "dependencies": {
-        "safe-buffer": "5.2.1"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/content-type": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
-      "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/cookie": {
-      "version": "0.5.0",
-      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
-      "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/cookie-signature": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
-      "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
-      "license": "MIT"
-    },
-    "node_modules/d": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
-      "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
-      "license": "ISC",
-      "dependencies": {
-        "es5-ext": "^0.10.50",
-        "type": "^1.0.1"
-      }
-    },
-    "node_modules/debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "2.0.0"
-      }
-    },
-    "node_modules/delayed-stream": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.4.0"
-      }
-    },
-    "node_modules/denque": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz",
-      "integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==",
-      "license": "Apache-2.0",
-      "engines": {
-        "node": ">=0.10"
-      }
-    },
-    "node_modules/depd": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
-      "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/destroy": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
-      "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8",
-        "npm": "1.2.8000 || >= 1.4.16"
-      }
-    },
-    "node_modules/difflib": {
-      "version": "0.2.4",
-      "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz",
-      "integrity": "sha1-teMDYabbAjF21WKJLbhZQKcY9H4=",
-      "dependencies": {
-        "heap": ">= 0.2.0"
-      }
-    },
-    "node_modules/discord-api-types": {
-      "version": "0.26.1",
-      "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.1.tgz",
-      "integrity": "sha512-T5PdMQ+Y1MEECYMV5wmyi9VEYPagEDEi4S0amgsszpWY0VB9JJ/hEvM6BgLhbdnKky4gfmZEXtEEtojN8ZKJQQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/discord.js": {
-      "version": "13.8.0",
-      "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.8.0.tgz",
-      "integrity": "sha512-EPAA/2VLycYN5wSzavqa4iJ6qj3UtQFtHw5TH/60Fj29ymfEsCQVn//o1mTpwDxzwb+rPIrWhkxKIGGnjfv0Iw==",
-      "dependencies": {
-        "@discordjs/builders": "^0.14.0",
-        "@discordjs/collection": "^0.7.0",
-        "@sapphire/async-queue": "^1.3.1",
-        "@types/node-fetch": "^2.6.1",
-        "@types/ws": "^8.5.3",
-        "discord-api-types": "^0.33.3",
-        "form-data": "^4.0.0",
-        "node-fetch": "^2.6.1",
-        "ws": "^8.7.0"
-      },
-      "engines": {
-        "node": ">=16.6.0",
-        "npm": ">=7.0.0"
-      }
-    },
-    "node_modules/discord.js/node_modules/@discordjs/builders": {
-      "version": "0.14.0",
-      "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.14.0.tgz",
-      "integrity": "sha512-+fqLIqa9wN3R+kvlld8sgG0nt04BAZxdCDP4t2qZ9TJsquLWA+xMtT8Waibb3d4li4AQS+IOfjiHAznv/dhHgQ==",
-      "dependencies": {
-        "@sapphire/shapeshift": "^3.1.0",
-        "@sindresorhus/is": "^4.6.0",
-        "discord-api-types": "^0.33.3",
-        "fast-deep-equal": "^3.1.3",
-        "ts-mixer": "^6.0.1",
-        "tslib": "^2.4.0"
-      },
-      "engines": {
-        "node": ">=16.9.0"
-      }
-    },
-    "node_modules/discord.js/node_modules/discord-api-types": {
-      "version": "0.33.5",
-      "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.33.5.tgz",
-      "integrity": "sha512-dvO5M52v7m7Dy96+XUnzXNsQ/0npsYpU6dL205kAtEDueswoz3aU3bh1UMoK4cQmcGtB1YRyLKqp+DXi05lzFg=="
-    },
-    "node_modules/dreamopt": {
-      "version": "0.8.0",
-      "resolved": "https://registry.npmjs.org/dreamopt/-/dreamopt-0.8.0.tgz",
-      "integrity": "sha1-W8yAvnCX5F/EicNCQFq2gUCowdk=",
-      "dependencies": {
-        "wordwrap": ">=0.0.2"
-      },
-      "engines": {
-        "node": ">=0.4.0"
-      }
-    },
-    "node_modules/ee-first": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
-      "license": "MIT"
-    },
-    "node_modules/encodeurl": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
-      "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/es5-ext": {
-      "version": "0.10.57",
-      "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.57.tgz",
-      "integrity": "sha512-L7cCNoPwTkAp7IBHxrKLsh7NKiVFkcdxlP9vbVw9QUvb7gF0Mz9bEBN0WY9xqdTjGF907EMT/iG013vnbqwu1Q==",
-      "hasInstallScript": true,
-      "license": "ISC",
-      "dependencies": {
-        "es6-iterator": "^2.0.3",
-        "es6-symbol": "^3.1.3",
-        "next-tick": "^1.1.0"
-      },
-      "engines": {
-        "node": ">=0.10"
-      }
-    },
-    "node_modules/es6-iterator": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
-      "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
-      "license": "MIT",
-      "dependencies": {
-        "d": "1",
-        "es5-ext": "^0.10.35",
-        "es6-symbol": "^3.1.1"
-      }
-    },
-    "node_modules/es6-symbol": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
-      "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
-      "license": "ISC",
-      "dependencies": {
-        "d": "^1.0.1",
-        "ext": "^1.1.2"
-      }
-    },
-    "node_modules/es6-weak-map": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz",
-      "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==",
-      "license": "ISC",
-      "dependencies": {
-        "d": "1",
-        "es5-ext": "^0.10.46",
-        "es6-iterator": "^2.0.3",
-        "es6-symbol": "^3.1.1"
-      }
-    },
-    "node_modules/escape-html": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-      "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
-      "license": "MIT"
-    },
-    "node_modules/etag": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-      "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/event-emitter": {
-      "version": "0.3.5",
-      "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
-      "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
-      "license": "MIT",
-      "dependencies": {
-        "d": "1",
-        "es5-ext": "~0.10.14"
-      }
-    },
-    "node_modules/express": {
-      "version": "4.18.1",
-      "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
-      "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
-      "license": "MIT",
-      "dependencies": {
-        "accepts": "~1.3.8",
-        "array-flatten": "1.1.1",
-        "body-parser": "1.20.0",
-        "content-disposition": "0.5.4",
-        "content-type": "~1.0.4",
-        "cookie": "0.5.0",
-        "cookie-signature": "1.0.6",
-        "debug": "2.6.9",
-        "depd": "2.0.0",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "etag": "~1.8.1",
-        "finalhandler": "1.2.0",
-        "fresh": "0.5.2",
-        "http-errors": "2.0.0",
-        "merge-descriptors": "1.0.1",
-        "methods": "~1.1.2",
-        "on-finished": "2.4.1",
-        "parseurl": "~1.3.3",
-        "path-to-regexp": "0.1.7",
-        "proxy-addr": "~2.0.7",
-        "qs": "6.10.3",
-        "range-parser": "~1.2.1",
-        "safe-buffer": "5.2.1",
-        "send": "0.18.0",
-        "serve-static": "1.15.0",
-        "setprototypeof": "1.2.0",
-        "statuses": "2.0.1",
-        "type-is": "~1.6.18",
-        "utils-merge": "1.0.1",
-        "vary": "~1.1.2"
-      },
-      "engines": {
-        "node": ">= 0.10.0"
-      }
-    },
-    "node_modules/ext": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz",
-      "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==",
-      "license": "ISC",
-      "dependencies": {
-        "type": "^2.5.0"
-      }
-    },
-    "node_modules/ext/node_modules/type": {
-      "version": "2.6.0",
-      "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz",
-      "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==",
-      "license": "ISC"
-    },
-    "node_modules/fast-deep-equal": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
-    },
-    "node_modules/file-type": {
-      "version": "12.4.2",
-      "resolved": "https://registry.npmjs.org/file-type/-/file-type-12.4.2.tgz",
-      "integrity": "sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/finalhandler": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
-      "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
-      "license": "MIT",
-      "dependencies": {
-        "debug": "2.6.9",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "on-finished": "2.4.1",
-        "parseurl": "~1.3.3",
-        "statuses": "2.0.1",
-        "unpipe": "~1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/form-data": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
-      "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
-      "license": "MIT",
-      "dependencies": {
-        "asynckit": "^0.4.0",
-        "combined-stream": "^1.0.8",
-        "mime-types": "^2.1.12"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/forwarded": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
-      "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/fresh": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
-      "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/fs.realpath": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
-      "license": "ISC"
-    },
-    "node_modules/function-bind": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
-      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
-      "license": "MIT"
-    },
-    "node_modules/get-intrinsic": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
-      "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
-      "license": "MIT",
-      "dependencies": {
-        "function-bind": "^1.1.1",
-        "has": "^1.0.3",
-        "has-symbols": "^1.0.1"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/glob": {
-      "version": "5.0.15",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
-      "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
-      "license": "ISC",
-      "dependencies": {
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "2 || 3",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/has": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
-      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
-      "license": "MIT",
-      "dependencies": {
-        "function-bind": "^1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.4.0"
-      }
-    },
-    "node_modules/has-symbols": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
-      "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/heap": {
-      "version": "0.2.7",
-      "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz",
-      "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==",
-      "license": "MIT"
-    },
-    "node_modules/http-errors": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
-      "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
-      "license": "MIT",
-      "dependencies": {
-        "depd": "2.0.0",
-        "inherits": "2.0.4",
-        "setprototypeof": "1.2.0",
-        "statuses": "2.0.1",
-        "toidentifier": "1.0.1"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/humanize": {
-      "version": "0.0.9",
-      "resolved": "https://registry.npmjs.org/humanize/-/humanize-0.0.9.tgz",
-      "integrity": "sha1-GZT/rs3+nEQe0r2sdFK3u0yeQaQ=",
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/humanize-duration": {
-      "version": "3.27.1",
-      "resolved": "https://registry.npmjs.org/humanize-duration/-/humanize-duration-3.27.1.tgz",
-      "integrity": "sha512-jCVkMl+EaM80rrMrAPl96SGG4NRac53UyI1o/yAzebDntEY6K6/Fj2HOjdPg8omTqIe5Y0wPBai2q5xXrIbarA==",
-      "license": "Unlicense"
-    },
-    "node_modules/iconv-lite": {
-      "version": "0.4.24",
-      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
-      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
-      "license": "MIT",
-      "dependencies": {
-        "safer-buffer": ">= 2.1.2 < 3"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/idb-keyval": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-3.2.0.tgz",
-      "integrity": "sha512-slx8Q6oywCCSfKgPgL0sEsXtPVnSbTLWpyiDcu6msHOyKOLari1TD1qocXVCft80umnkk3/Qqh3lwoFt8T/BPQ==",
-      "license": "Apache-2.0"
-    },
-    "node_modules/ieee754": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
-      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/inflight": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
-      "license": "ISC",
-      "dependencies": {
-        "once": "^1.3.0",
-        "wrappy": "1"
-      }
-    },
-    "node_modules/inherits": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-      "license": "ISC"
-    },
-    "node_modules/ip": {
-      "version": "1.1.8",
-      "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz",
-      "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==",
-      "license": "MIT"
-    },
-    "node_modules/ipaddr.js": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
-      "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.10"
-      }
-    },
-    "node_modules/is-electron": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.1.tgz",
-      "integrity": "sha512-r8EEQQsqT+Gn0aXFx7lTFygYQhILLCB+wn0WCDL5LZRINeLH/Rvw1j2oKodELLXYNImQ3CRlVsY8wW4cGOsyuw==",
-      "license": "MIT"
-    },
-    "node_modules/is-promise": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
-      "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==",
-      "license": "MIT"
-    },
-    "node_modules/is-url": {
-      "version": "1.2.4",
-      "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
-      "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==",
-      "license": "MIT"
-    },
-    "node_modules/jpeg-autorotate": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/jpeg-autorotate/-/jpeg-autorotate-7.1.1.tgz",
-      "integrity": "sha512-ewTZTG/QWOM0D5h/yKcQ3QgyrnQYsr3qmcS+bqoAwgQAY1KBa31aJ+q+FlElaxo/rSYqfF1ixf+8EIgluBkgTg==",
-      "license": "MIT",
-      "dependencies": {
-        "colors": "^1.4.0",
-        "glob": "^7.1.6",
-        "jpeg-js": "^0.4.2",
-        "piexifjs": "^1.0.6",
-        "yargs-parser": "^20.2.1"
-      },
-      "bin": {
-        "jpeg-autorotate": "src/cli.js"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/jpeg-autorotate/node_modules/glob": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
-      "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
-      "license": "ISC",
-      "dependencies": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.0.4",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      },
-      "engines": {
-        "node": "*"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/jpeg-js": {
-      "version": "0.4.3",
-      "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.3.tgz",
-      "integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/jshaiku": {
-      "resolved": "../haiku",
-      "link": true
-    },
-    "node_modules/json-diff": {
-      "version": "0.7.3",
-      "resolved": "https://registry.npmjs.org/json-diff/-/json-diff-0.7.3.tgz",
-      "integrity": "sha512-VBvNBt3cIrCBHa3gYbVsCFUEReqWZPf+Biq1ZtFdIiQ6rytRLDp3qvtrGv7z/iZDd1D4vXWpW7Nx1nP8muLzkg==",
-      "license": "MIT",
-      "dependencies": {
-        "cli-color": "^2.0.0",
-        "difflib": "~0.2.1",
-        "dreamopt": "~0.8.0"
-      },
-      "bin": {
-        "json-diff": "bin/json-diff.js"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/lru-queue": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz",
-      "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=",
-      "license": "MIT",
-      "dependencies": {
-        "es5-ext": "~0.10.2"
-      }
-    },
-    "node_modules/media-typer": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
-      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/memoizee": {
-      "version": "0.4.15",
-      "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz",
-      "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==",
-      "license": "ISC",
-      "dependencies": {
-        "d": "^1.0.1",
-        "es5-ext": "^0.10.53",
-        "es6-weak-map": "^2.0.3",
-        "event-emitter": "^0.3.5",
-        "is-promise": "^2.2.2",
-        "lru-queue": "^0.1.0",
-        "next-tick": "^1.1.0",
-        "timers-ext": "^0.1.7"
-      }
-    },
-    "node_modules/memory-pager": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
-      "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/merge-descriptors": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
-      "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
-      "license": "MIT"
-    },
-    "node_modules/methods": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
-      "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/mime": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
-      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
-      "license": "MIT",
-      "bin": {
-        "mime": "cli.js"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/mime-db": {
-      "version": "1.51.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
-      "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/mime-types": {
-      "version": "2.1.34",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
-      "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
-      "license": "MIT",
-      "dependencies": {
-        "mime-db": "1.51.0"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "license": "ISC",
-      "dependencies": {
-        "brace-expansion": "^1.1.7"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/mongodb": {
-      "version": "4.7.0",
-      "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.7.0.tgz",
-      "integrity": "sha512-HhVar6hsUeMAVlIbwQwWtV36iyjKd9qdhY+s4wcU8K6TOj4Q331iiMy+FoPuxEntDIijTYWivwFJkLv8q/ZgvA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "bson": "^4.6.3",
-        "denque": "^2.0.1",
-        "mongodb-connection-string-url": "^2.5.2",
-        "socks": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=12.9.0"
-      },
-      "optionalDependencies": {
-        "saslprep": "^1.0.3"
-      }
-    },
-    "node_modules/mongodb-connection-string-url": {
-      "version": "2.5.2",
-      "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.2.tgz",
-      "integrity": "sha512-tWDyIG8cQlI5k3skB6ywaEA5F9f5OntrKKsT/Lteub2zgwSUlhqEN2inGgBTm8bpYJf8QYBdA/5naz65XDpczA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@types/whatwg-url": "^8.2.1",
-        "whatwg-url": "^11.0.0"
-      }
-    },
-    "node_modules/ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
-      "license": "MIT"
-    },
-    "node_modules/negotiator": {
-      "version": "0.6.3",
-      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
-      "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/next-tick": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
-      "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==",
-      "license": "ISC"
-    },
-    "node_modules/node-fetch": {
-      "version": "2.6.7",
-      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
-      "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
-      "license": "MIT",
-      "dependencies": {
-        "whatwg-url": "^5.0.0"
-      },
-      "engines": {
-        "node": "4.x || >=6.0.0"
-      },
-      "peerDependencies": {
-        "encoding": "^0.1.0"
-      },
-      "peerDependenciesMeta": {
-        "encoding": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/node-fetch/node_modules/tr46": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
-      "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=",
-      "license": "MIT"
-    },
-    "node_modules/node-fetch/node_modules/whatwg-url": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
-      "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
-      "license": "MIT",
-      "dependencies": {
-        "tr46": "~0.0.3",
-        "webidl-conversions": "^3.0.0"
-      }
-    },
-    "node_modules/node-tesseract": {
-      "version": "0.2.7",
-      "resolved": "https://registry.npmjs.org/node-tesseract/-/node-tesseract-0.2.7.tgz",
-      "integrity": "sha1-yPAvuDUaQnByc1d4wFGYI/JgG4Q=",
-      "license": "MIT",
-      "dependencies": {
-        "glob": "^5.0.10",
-        "node-uuid": "^1.4.1"
-      }
-    },
-    "node_modules/node-uuid": {
-      "version": "1.4.8",
-      "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz",
-      "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=",
-      "bin": {
-        "uuid": "bin/uuid"
-      }
-    },
-    "node_modules/object-inspect": {
-      "version": "1.12.0",
-      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
-      "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==",
-      "license": "MIT",
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/on-finished": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
-      "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
-      "license": "MIT",
-      "dependencies": {
-        "ee-first": "1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/once": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
-      "license": "ISC",
-      "dependencies": {
-        "wrappy": "1"
-      }
-    },
-    "node_modules/opencollective-postinstall": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
-      "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==",
-      "license": "MIT",
-      "bin": {
-        "opencollective-postinstall": "index.js"
-      }
-    },
-    "node_modules/parseurl": {
-      "version": "1.3.3",
-      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
-      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/path-is-absolute": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/path-to-regexp": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
-      "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
-      "license": "MIT"
-    },
-    "node_modules/piexifjs": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/piexifjs/-/piexifjs-1.0.6.tgz",
-      "integrity": "sha512-0wVyH0cKohzBQ5Gi2V1BuxYpxWfxF3cSqfFXfPIpl5tl9XLS5z4ogqhUCD20AbHi0h9aJkqXNJnkVev6gwh2ag==",
-      "license": "MIT"
-    },
-    "node_modules/proxy-addr": {
-      "version": "2.0.7",
-      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
-      "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
-      "license": "MIT",
-      "dependencies": {
-        "forwarded": "0.2.0",
-        "ipaddr.js": "1.9.1"
-      },
-      "engines": {
-        "node": ">= 0.10"
-      }
-    },
-    "node_modules/punycode": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
-      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/qs": {
-      "version": "6.10.3",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
-      "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
-      "license": "BSD-3-Clause",
-      "dependencies": {
-        "side-channel": "^1.0.4"
-      },
-      "engines": {
-        "node": ">=0.6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/range-parser": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
-      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/raw-body": {
-      "version": "2.5.1",
-      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
-      "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
-      "license": "MIT",
-      "dependencies": {
-        "bytes": "3.1.2",
-        "http-errors": "2.0.0",
-        "iconv-lite": "0.4.24",
-        "unpipe": "1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/regenerator-runtime": {
-      "version": "0.13.9",
-      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
-      "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
-      "license": "MIT"
-    },
-    "node_modules/resolve-url": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
-      "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
-      "license": "MIT"
-    },
-    "node_modules/safe-buffer": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "license": "MIT"
-    },
-    "node_modules/safer-buffer": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
-      "license": "MIT"
-    },
-    "node_modules/saslprep": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
-      "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "sparse-bitfield": "^3.0.3"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/send": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
-      "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
-      "license": "MIT",
-      "dependencies": {
-        "debug": "2.6.9",
-        "depd": "2.0.0",
-        "destroy": "1.2.0",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "etag": "~1.8.1",
-        "fresh": "0.5.2",
-        "http-errors": "2.0.0",
-        "mime": "1.6.0",
-        "ms": "2.1.3",
-        "on-finished": "2.4.1",
-        "range-parser": "~1.2.1",
-        "statuses": "2.0.1"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/send/node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-      "license": "MIT"
-    },
-    "node_modules/serve-static": {
-      "version": "1.15.0",
-      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
-      "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
-      "license": "MIT",
-      "dependencies": {
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "parseurl": "~1.3.3",
-        "send": "0.18.0"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/setprototypeof": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
-      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
-      "license": "ISC"
-    },
-    "node_modules/side-channel": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
-      "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
-      "license": "MIT",
-      "dependencies": {
-        "call-bind": "^1.0.0",
-        "get-intrinsic": "^1.0.2",
-        "object-inspect": "^1.9.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/smart-buffer": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
-      "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 6.0.0",
-        "npm": ">= 3.0.0"
-      }
-    },
-    "node_modules/socks": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz",
-      "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==",
-      "license": "MIT",
-      "dependencies": {
-        "ip": "^1.1.5",
-        "smart-buffer": "^4.2.0"
-      },
-      "engines": {
-        "node": ">= 10.13.0",
-        "npm": ">= 3.0.0"
-      }
-    },
-    "node_modules/sparse-bitfield": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
-      "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
-      "license": "MIT",
-      "optional": true,
-      "dependencies": {
-        "memory-pager": "^1.0.2"
-      }
-    },
-    "node_modules/statuses": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
-      "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/structured-clone": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/structured-clone/-/structured-clone-0.2.2.tgz",
-      "integrity": "sha1-rJK2vjGVimQ9sw8TNavGobAt/cI=",
-      "license": "MIT"
-    },
-    "node_modules/tesseract.js": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/tesseract.js/-/tesseract.js-2.1.5.tgz",
-      "integrity": "sha512-7CIS3SWr7TXpeaH9+HS7iUtVbCfPFYOO3p6rkRAkdtsOtrbz6496x59na6SCbFAIaZulQxy8BjwSu3qL3AoDRg==",
-      "hasInstallScript": true,
-      "license": "Apache-2.0",
-      "dependencies": {
-        "blueimp-load-image": "^3.0.0",
-        "bmp-js": "^0.1.0",
-        "file-type": "^12.4.1",
-        "idb-keyval": "^3.2.0",
-        "is-electron": "^2.2.0",
-        "is-url": "^1.2.4",
-        "jpeg-autorotate": "^7.1.1",
-        "node-fetch": "^2.6.0",
-        "opencollective-postinstall": "^2.0.2",
-        "regenerator-runtime": "^0.13.3",
-        "resolve-url": "^0.2.1",
-        "tesseract.js-core": "^2.2.0",
-        "zlibjs": "^0.3.1"
-      }
-    },
-    "node_modules/tesseract.js-core": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/tesseract.js-core/-/tesseract.js-core-2.2.0.tgz",
-      "integrity": "sha512-a8L+OJTbUipBsEDsJhDPlnLB0TY1MkTZqw5dqUwmiDSjUzwvU7HWLg/2+WDRulKUi4LE+7PnHlaBlW0k+V0U0w==",
-      "license": "Apache License 2.0"
-    },
-    "node_modules/timers-ext": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz",
-      "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==",
-      "license": "ISC",
-      "dependencies": {
-        "es5-ext": "~0.10.46",
-        "next-tick": "1"
-      }
-    },
-    "node_modules/toidentifier": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
-      "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.6"
-      }
-    },
-    "node_modules/tr46": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
-      "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
-      "license": "MIT",
-      "dependencies": {
-        "punycode": "^2.1.1"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/ts-mixer": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.1.tgz",
-      "integrity": "sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg=="
-    },
-    "node_modules/tslib": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
-      "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
-    },
-    "node_modules/type": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
-      "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
-      "license": "ISC"
-    },
-    "node_modules/type-is": {
-      "version": "1.6.18",
-      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
-      "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
-      "license": "MIT",
-      "dependencies": {
-        "media-typer": "0.3.0",
-        "mime-types": "~2.1.24"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/typescript": {
-      "version": "4.6.2",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz",
-      "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==",
-      "license": "Apache-2.0",
-      "bin": {
-        "tsc": "bin/tsc",
-        "tsserver": "bin/tsserver"
-      },
-      "engines": {
-        "node": ">=4.2.0"
-      }
-    },
-    "node_modules/unpipe": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
-      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/unscan": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/unscan/-/unscan-1.1.2.tgz",
-      "integrity": "sha512-a5RcGaBFMO9l78QWKffeWUo2cvfqUv05JCXuphE8MFOA92qyqp1Da7isnR+zjJspi45+yS8tTSuhd0vV3asWdA==",
-      "license": "MIT",
-      "dependencies": {
-        "commander": "^8.3.0",
-        "form-data": "^4.0.0",
-        "node-fetch": "^2.6.5"
-      },
-      "bin": {
-        "unscan": "bin/unscan.js"
-      }
-    },
-    "node_modules/utils-merge": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
-      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.4.0"
-      }
-    },
-    "node_modules/vary": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
-      "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/webidl-conversions": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
-      "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=",
-      "license": "BSD-2-Clause"
-    },
-    "node_modules/whatwg-url": {
-      "version": "11.0.0",
-      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
-      "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
-      "license": "MIT",
-      "dependencies": {
-        "tr46": "^3.0.0",
-        "webidl-conversions": "^7.0.0"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/whatwg-url/node_modules/webidl-conversions": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
-      "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
-      "license": "BSD-2-Clause",
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/wordwrap": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
-      "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
-      "license": "MIT"
-    },
-    "node_modules/wrappy": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
-      "license": "ISC"
-    },
-    "node_modules/ws": {
-      "version": "8.8.0",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.0.tgz",
-      "integrity": "sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ==",
-      "engines": {
-        "node": ">=10.0.0"
-      },
-      "peerDependencies": {
-        "bufferutil": "^4.0.1",
-        "utf-8-validate": "^5.0.2"
-      },
-      "peerDependenciesMeta": {
-        "bufferutil": {
-          "optional": true
-        },
-        "utf-8-validate": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/yargs-parser": {
-      "version": "20.2.9",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
-      "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
-      "license": "ISC",
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/zlibjs": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/zlibjs/-/zlibjs-0.3.1.tgz",
-      "integrity": "sha1-UBl+2yihxCymWcyLTmqd3W1ERVQ=",
-      "license": "MIT",
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/zod": {
-      "version": "3.13.4",
-      "resolved": "https://registry.npmjs.org/zod/-/zod-3.13.4.tgz",
-      "integrity": "sha512-LZRucWt4j/ru5azOkJxCfpR87IyFDn8h2UODdqvXzZLb3K7bb9chUrUIGTy3BPsr8XnbQYfQ5Md5Hu2OYIo1mg==",
-      "license": "MIT",
-      "funding": {
-        "url": "https://github.com/sponsors/colinhacks"
-      }
-    }
-  },
-  "dependencies": {
-    "@discordjs/builders": {
-      "version": "0.12.0",
-      "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.12.0.tgz",
-      "integrity": "sha512-Vx2MjUZd6QVo1uS2uWt708Fd6cHWGFblAvbpL5EBO+kLl0BADmPwwvts+YJ/VfSywed6Vsk6K2cEooR/Ytjhjw==",
-      "requires": {
-        "@sindresorhus/is": "^4.3.0",
-        "discord-api-types": "^0.26.1",
-        "ts-mixer": "^6.0.0",
-        "tslib": "^2.3.1",
-        "zod": "^3.11.6"
-      }
-    },
-    "@discordjs/collection": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.7.0.tgz",
-      "integrity": "sha512-R5i8Wb8kIcBAFEPLLf7LVBQKBDYUL+ekb23sOgpkpyGT+V4P7V83wTxcsqmX+PbqHt4cEHn053uMWfRqh/Z/nA=="
-    },
-    "@sapphire/async-queue": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.3.1.tgz",
-      "integrity": "sha512-FFTlPOWZX1kDj9xCAsRzH5xEJfawg1lNoYAA+ecOWJMHOfiZYb1uXOI3ne9U4UILSEPwfE68p3T9wUHwIQfR0g=="
-    },
-    "@sapphire/shapeshift": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/@sapphire/shapeshift/-/shapeshift-3.2.0.tgz",
-      "integrity": "sha512-asNgE5Ooil2/oGIAj6vZMoUc2ZFED0TGYD7jwvZsjHPQZBEh9ITj94ca4bCgiCR1s2ER/UjzykH+5wE3ebVZnQ=="
-    },
-    "@sindresorhus/is": {
-      "version": "4.6.0",
-      "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
-      "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="
-    },
-    "@types/node": {
-      "version": "17.0.21",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz",
-      "integrity": "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ=="
-    },
-    "@types/node-fetch": {
-      "version": "2.6.1",
-      "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz",
-      "integrity": "sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==",
-      "requires": {
-        "@types/node": "*",
-        "form-data": "^3.0.0"
-      },
-      "dependencies": {
-        "form-data": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
-          "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
-          "requires": {
-            "asynckit": "^0.4.0",
-            "combined-stream": "^1.0.8",
-            "mime-types": "^2.1.12"
-          }
-        }
-      }
-    },
-    "@types/webidl-conversions": {
-      "version": "6.1.1",
-      "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz",
-      "integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q=="
-    },
-    "@types/whatwg-url": {
-      "version": "8.2.1",
-      "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.1.tgz",
-      "integrity": "sha512-2YubE1sjj5ifxievI5Ge1sckb9k/Er66HyR2c+3+I6VDUUg1TLPdYYTEbQ+DjRkS4nTxMJhgWfSfMRD2sl2EYQ==",
-      "requires": {
-        "@types/node": "*",
-        "@types/webidl-conversions": "*"
-      }
-    },
-    "@types/ws": {
-      "version": "8.5.3",
-      "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
-      "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==",
-      "requires": {
-        "@types/node": "*"
-      }
-    },
-    "@ungap/structured-clone": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.0.1.tgz",
-      "integrity": "sha512-zKVyTt6rELvPXYwcVPTJcPFtY0AckN5A7xWuc7owBqR0FdtuDYhE9MZZUi6IY1kZUQFSXV1B3UOOIyLkVHYd2w=="
-    },
-    "accepts": {
-      "version": "1.3.8",
-      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
-      "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
-      "requires": {
-        "mime-types": "~2.1.34",
-        "negotiator": "0.6.3"
-      }
-    },
-    "array-flatten": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
-      "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
-    },
-    "asynckit": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
-    },
-    "balanced-match": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
-    },
-    "base64-js": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
-      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
-    },
-    "blueimp-load-image": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/blueimp-load-image/-/blueimp-load-image-3.0.0.tgz",
-      "integrity": "sha512-Q9rFbd4ZUNvzSFmRXx9MoG0RwWwJeMjjEUbG7WIOJgUg22Jgkow0wL5b35B6qwiBscxACW9OHdrP5s2vQ3x8DQ=="
-    },
-    "bmp-js": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz",
-      "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM="
-    },
-    "body-parser": {
-      "version": "1.20.0",
-      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
-      "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
-      "requires": {
-        "bytes": "3.1.2",
-        "content-type": "~1.0.4",
-        "debug": "2.6.9",
-        "depd": "2.0.0",
-        "destroy": "1.2.0",
-        "http-errors": "2.0.0",
-        "iconv-lite": "0.4.24",
-        "on-finished": "2.4.1",
-        "qs": "6.10.3",
-        "raw-body": "2.5.1",
-        "type-is": "~1.6.18",
-        "unpipe": "1.0.0"
-      }
-    },
-    "brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-      "requires": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "bson": {
-      "version": "4.6.4",
-      "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.4.tgz",
-      "integrity": "sha512-TdQ3FzguAu5HKPPlr0kYQCyrYUYh8tFM+CMTpxjNzVzxeiJY00Rtuj3LXLHSgiGvmaWlZ8PE+4KyM2thqE38pQ==",
-      "requires": {
-        "buffer": "^5.6.0"
-      }
-    },
-    "buffer": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
-      "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
-      "requires": {
-        "base64-js": "^1.3.1",
-        "ieee754": "^1.1.13"
-      }
-    },
-    "bytes": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
-      "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="
-    },
-    "call-bind": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
-      "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
-      "requires": {
-        "function-bind": "^1.1.1",
-        "get-intrinsic": "^1.0.2"
-      }
-    },
-    "cli-color": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.1.tgz",
-      "integrity": "sha512-eBbxZF6fqPUNnf7CLAFOersUnyYzv83tHFLSlts+OAHsNendaqv2tHCq+/MO+b3Y+9JeoUlIvobyxG/Z8GNeOg==",
-      "requires": {
-        "d": "^1.0.1",
-        "es5-ext": "^0.10.53",
-        "es6-iterator": "^2.0.3",
-        "memoizee": "^0.4.15",
-        "timers-ext": "^0.1.7"
-      }
-    },
-    "colors": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
-      "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
-    },
-    "combined-stream": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
-      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
-      "requires": {
-        "delayed-stream": "~1.0.0"
-      }
-    },
-    "commander": {
-      "version": "8.3.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
-      "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="
-    },
-    "concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
-    },
-    "content-disposition": {
-      "version": "0.5.4",
-      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
-      "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
-      "requires": {
-        "safe-buffer": "5.2.1"
-      }
-    },
-    "content-type": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
-      "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
-    },
-    "cookie": {
-      "version": "0.5.0",
-      "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
-      "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="
-    },
-    "cookie-signature": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
-      "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
-    },
-    "d": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
-      "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
-      "requires": {
-        "es5-ext": "^0.10.50",
-        "type": "^1.0.1"
-      }
-    },
-    "debug": {
-      "version": "2.6.9",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-      "requires": {
-        "ms": "2.0.0"
-      }
-    },
-    "delayed-stream": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
-    },
-    "denque": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz",
-      "integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ=="
-    },
-    "depd": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
-      "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
-    },
-    "destroy": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
-      "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
-    },
-    "difflib": {
-      "version": "0.2.4",
-      "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz",
-      "integrity": "sha1-teMDYabbAjF21WKJLbhZQKcY9H4=",
-      "requires": {
-        "heap": ">= 0.2.0"
-      }
-    },
-    "discord-api-types": {
-      "version": "0.26.1",
-      "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.1.tgz",
-      "integrity": "sha512-T5PdMQ+Y1MEECYMV5wmyi9VEYPagEDEi4S0amgsszpWY0VB9JJ/hEvM6BgLhbdnKky4gfmZEXtEEtojN8ZKJQQ=="
-    },
-    "discord.js": {
-      "version": "13.8.0",
-      "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.8.0.tgz",
-      "integrity": "sha512-EPAA/2VLycYN5wSzavqa4iJ6qj3UtQFtHw5TH/60Fj29ymfEsCQVn//o1mTpwDxzwb+rPIrWhkxKIGGnjfv0Iw==",
-      "requires": {
-        "@discordjs/builders": "^0.14.0",
-        "@discordjs/collection": "^0.7.0",
-        "@sapphire/async-queue": "^1.3.1",
-        "@types/node-fetch": "^2.6.1",
-        "@types/ws": "^8.5.3",
-        "discord-api-types": "^0.33.3",
-        "form-data": "^4.0.0",
-        "node-fetch": "^2.6.1",
-        "ws": "^8.7.0"
-      },
-      "dependencies": {
-        "@discordjs/builders": {
-          "version": "0.14.0",
-          "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.14.0.tgz",
-          "integrity": "sha512-+fqLIqa9wN3R+kvlld8sgG0nt04BAZxdCDP4t2qZ9TJsquLWA+xMtT8Waibb3d4li4AQS+IOfjiHAznv/dhHgQ==",
-          "requires": {
-            "@sapphire/shapeshift": "^3.1.0",
-            "@sindresorhus/is": "^4.6.0",
-            "discord-api-types": "^0.33.3",
-            "fast-deep-equal": "^3.1.3",
-            "ts-mixer": "^6.0.1",
-            "tslib": "^2.4.0"
-          }
-        },
-        "discord-api-types": {
-          "version": "0.33.5",
-          "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.33.5.tgz",
-          "integrity": "sha512-dvO5M52v7m7Dy96+XUnzXNsQ/0npsYpU6dL205kAtEDueswoz3aU3bh1UMoK4cQmcGtB1YRyLKqp+DXi05lzFg=="
-        }
-      }
-    },
-    "dreamopt": {
-      "version": "0.8.0",
-      "resolved": "https://registry.npmjs.org/dreamopt/-/dreamopt-0.8.0.tgz",
-      "integrity": "sha1-W8yAvnCX5F/EicNCQFq2gUCowdk=",
-      "requires": {
-        "wordwrap": ">=0.0.2"
-      }
-    },
-    "ee-first": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
-    },
-    "encodeurl": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
-      "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
-    },
-    "es5-ext": {
-      "version": "0.10.57",
-      "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.57.tgz",
-      "integrity": "sha512-L7cCNoPwTkAp7IBHxrKLsh7NKiVFkcdxlP9vbVw9QUvb7gF0Mz9bEBN0WY9xqdTjGF907EMT/iG013vnbqwu1Q==",
-      "requires": {
-        "es6-iterator": "^2.0.3",
-        "es6-symbol": "^3.1.3",
-        "next-tick": "^1.1.0"
-      }
-    },
-    "es6-iterator": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
-      "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
-      "requires": {
-        "d": "1",
-        "es5-ext": "^0.10.35",
-        "es6-symbol": "^3.1.1"
-      }
-    },
-    "es6-symbol": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
-      "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
-      "requires": {
-        "d": "^1.0.1",
-        "ext": "^1.1.2"
-      }
-    },
-    "es6-weak-map": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz",
-      "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==",
-      "requires": {
-        "d": "1",
-        "es5-ext": "^0.10.46",
-        "es6-iterator": "^2.0.3",
-        "es6-symbol": "^3.1.1"
-      }
-    },
-    "escape-html": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
-      "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
-    },
-    "etag": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
-      "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
-    },
-    "event-emitter": {
-      "version": "0.3.5",
-      "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
-      "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
-      "requires": {
-        "d": "1",
-        "es5-ext": "~0.10.14"
-      }
-    },
-    "express": {
-      "version": "4.18.1",
-      "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
-      "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
-      "requires": {
-        "accepts": "~1.3.8",
-        "array-flatten": "1.1.1",
-        "body-parser": "1.20.0",
-        "content-disposition": "0.5.4",
-        "content-type": "~1.0.4",
-        "cookie": "0.5.0",
-        "cookie-signature": "1.0.6",
-        "debug": "2.6.9",
-        "depd": "2.0.0",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "etag": "~1.8.1",
-        "finalhandler": "1.2.0",
-        "fresh": "0.5.2",
-        "http-errors": "2.0.0",
-        "merge-descriptors": "1.0.1",
-        "methods": "~1.1.2",
-        "on-finished": "2.4.1",
-        "parseurl": "~1.3.3",
-        "path-to-regexp": "0.1.7",
-        "proxy-addr": "~2.0.7",
-        "qs": "6.10.3",
-        "range-parser": "~1.2.1",
-        "safe-buffer": "5.2.1",
-        "send": "0.18.0",
-        "serve-static": "1.15.0",
-        "setprototypeof": "1.2.0",
-        "statuses": "2.0.1",
-        "type-is": "~1.6.18",
-        "utils-merge": "1.0.1",
-        "vary": "~1.1.2"
-      }
-    },
-    "ext": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz",
-      "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==",
-      "requires": {
-        "type": "^2.5.0"
-      },
-      "dependencies": {
-        "type": {
-          "version": "2.6.0",
-          "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz",
-          "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ=="
-        }
-      }
-    },
-    "fast-deep-equal": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
-    },
-    "file-type": {
-      "version": "12.4.2",
-      "resolved": "https://registry.npmjs.org/file-type/-/file-type-12.4.2.tgz",
-      "integrity": "sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg=="
-    },
-    "finalhandler": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
-      "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
-      "requires": {
-        "debug": "2.6.9",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "on-finished": "2.4.1",
-        "parseurl": "~1.3.3",
-        "statuses": "2.0.1",
-        "unpipe": "~1.0.0"
-      }
-    },
-    "form-data": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
-      "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
-      "requires": {
-        "asynckit": "^0.4.0",
-        "combined-stream": "^1.0.8",
-        "mime-types": "^2.1.12"
-      }
-    },
-    "forwarded": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
-      "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
-    },
-    "fresh": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
-      "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
-    },
-    "fs.realpath": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
-    },
-    "function-bind": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
-      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
-    },
-    "get-intrinsic": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
-      "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
-      "requires": {
-        "function-bind": "^1.1.1",
-        "has": "^1.0.3",
-        "has-symbols": "^1.0.1"
-      }
-    },
-    "glob": {
-      "version": "5.0.15",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
-      "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
-      "requires": {
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "2 || 3",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      }
-    },
-    "has": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
-      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
-      "requires": {
-        "function-bind": "^1.1.1"
-      }
-    },
-    "has-symbols": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
-      "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
-    },
-    "heap": {
-      "version": "0.2.7",
-      "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz",
-      "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg=="
-    },
-    "http-errors": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
-      "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
-      "requires": {
-        "depd": "2.0.0",
-        "inherits": "2.0.4",
-        "setprototypeof": "1.2.0",
-        "statuses": "2.0.1",
-        "toidentifier": "1.0.1"
-      }
-    },
-    "humanize": {
-      "version": "0.0.9",
-      "resolved": "https://registry.npmjs.org/humanize/-/humanize-0.0.9.tgz",
-      "integrity": "sha1-GZT/rs3+nEQe0r2sdFK3u0yeQaQ="
-    },
-    "humanize-duration": {
-      "version": "3.27.1",
-      "resolved": "https://registry.npmjs.org/humanize-duration/-/humanize-duration-3.27.1.tgz",
-      "integrity": "sha512-jCVkMl+EaM80rrMrAPl96SGG4NRac53UyI1o/yAzebDntEY6K6/Fj2HOjdPg8omTqIe5Y0wPBai2q5xXrIbarA=="
-    },
-    "iconv-lite": {
-      "version": "0.4.24",
-      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
-      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
-      "requires": {
-        "safer-buffer": ">= 2.1.2 < 3"
-      }
-    },
-    "idb-keyval": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-3.2.0.tgz",
-      "integrity": "sha512-slx8Q6oywCCSfKgPgL0sEsXtPVnSbTLWpyiDcu6msHOyKOLari1TD1qocXVCft80umnkk3/Qqh3lwoFt8T/BPQ=="
-    },
-    "ieee754": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
-      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
-    },
-    "inflight": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
-      "requires": {
-        "once": "^1.3.0",
-        "wrappy": "1"
-      }
-    },
-    "inherits": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
-    },
-    "ip": {
-      "version": "1.1.8",
-      "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz",
-      "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg=="
-    },
-    "ipaddr.js": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
-      "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
-    },
-    "is-electron": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.1.tgz",
-      "integrity": "sha512-r8EEQQsqT+Gn0aXFx7lTFygYQhILLCB+wn0WCDL5LZRINeLH/Rvw1j2oKodELLXYNImQ3CRlVsY8wW4cGOsyuw=="
-    },
-    "is-promise": {
-      "version": "2.2.2",
-      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
-      "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
-    },
-    "is-url": {
-      "version": "1.2.4",
-      "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
-      "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww=="
-    },
-    "jpeg-autorotate": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/jpeg-autorotate/-/jpeg-autorotate-7.1.1.tgz",
-      "integrity": "sha512-ewTZTG/QWOM0D5h/yKcQ3QgyrnQYsr3qmcS+bqoAwgQAY1KBa31aJ+q+FlElaxo/rSYqfF1ixf+8EIgluBkgTg==",
-      "requires": {
-        "colors": "^1.4.0",
-        "glob": "^7.1.6",
-        "jpeg-js": "^0.4.2",
-        "piexifjs": "^1.0.6",
-        "yargs-parser": "^20.2.1"
-      },
-      "dependencies": {
-        "glob": {
-          "version": "7.2.0",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
-          "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
-          "requires": {
-            "fs.realpath": "^1.0.0",
-            "inflight": "^1.0.4",
-            "inherits": "2",
-            "minimatch": "^3.0.4",
-            "once": "^1.3.0",
-            "path-is-absolute": "^1.0.0"
-          }
-        }
-      }
-    },
-    "jpeg-js": {
-      "version": "0.4.3",
-      "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.3.tgz",
-      "integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q=="
-    },
-    "jshaiku": {
-      "version": "file:../haiku",
-      "requires": {
-        "@babel/core": "^7.16.7",
-        "@babel/preset-env": "^7.16.8",
-        "@babel/preset-typescript": "^7.16.7",
-        "@discordjs/builders": "^0.11.0",
-        "@discordjs/rest": "^0.2.0-canary.0",
-        "@types/jest": "^27.4.0",
-        "@types/node-cron": "^3.0.1",
-        "ansi-styles": "^6.1.0",
-        "babel-jest": "^27.4.6",
-        "chalk": "^5.0.0",
-        "discord-api-types": "^0.26.1",
-        "discord.js": "^13.8.0",
-        "jest": "^27.4.7",
-        "node-cron": "^3.0.0",
-        "ts-node": "^10.4.0",
-        "typescript": "4.5.4"
-      }
-    },
-    "json-diff": {
-      "version": "0.7.3",
-      "resolved": "https://registry.npmjs.org/json-diff/-/json-diff-0.7.3.tgz",
-      "integrity": "sha512-VBvNBt3cIrCBHa3gYbVsCFUEReqWZPf+Biq1ZtFdIiQ6rytRLDp3qvtrGv7z/iZDd1D4vXWpW7Nx1nP8muLzkg==",
-      "requires": {
-        "cli-color": "^2.0.0",
-        "difflib": "~0.2.1",
-        "dreamopt": "~0.8.0"
-      }
-    },
-    "lru-queue": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz",
-      "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=",
-      "requires": {
-        "es5-ext": "~0.10.2"
-      }
-    },
-    "media-typer": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
-      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
-    },
-    "memoizee": {
-      "version": "0.4.15",
-      "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz",
-      "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==",
-      "requires": {
-        "d": "^1.0.1",
-        "es5-ext": "^0.10.53",
-        "es6-weak-map": "^2.0.3",
-        "event-emitter": "^0.3.5",
-        "is-promise": "^2.2.2",
-        "lru-queue": "^0.1.0",
-        "next-tick": "^1.1.0",
-        "timers-ext": "^0.1.7"
-      }
-    },
-    "memory-pager": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
-      "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
-      "optional": true
-    },
-    "merge-descriptors": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
-      "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
-    },
-    "methods": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
-      "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
-    },
-    "mime": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
-      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
-    },
-    "mime-db": {
-      "version": "1.51.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
-      "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
-    },
-    "mime-types": {
-      "version": "2.1.34",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
-      "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
-      "requires": {
-        "mime-db": "1.51.0"
-      }
-    },
-    "minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "requires": {
-        "brace-expansion": "^1.1.7"
-      }
-    },
-    "mongodb": {
-      "version": "4.7.0",
-      "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.7.0.tgz",
-      "integrity": "sha512-HhVar6hsUeMAVlIbwQwWtV36iyjKd9qdhY+s4wcU8K6TOj4Q331iiMy+FoPuxEntDIijTYWivwFJkLv8q/ZgvA==",
-      "requires": {
-        "bson": "^4.6.3",
-        "denque": "^2.0.1",
-        "mongodb-connection-string-url": "^2.5.2",
-        "saslprep": "^1.0.3",
-        "socks": "^2.6.2"
-      }
-    },
-    "mongodb-connection-string-url": {
-      "version": "2.5.2",
-      "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.2.tgz",
-      "integrity": "sha512-tWDyIG8cQlI5k3skB6ywaEA5F9f5OntrKKsT/Lteub2zgwSUlhqEN2inGgBTm8bpYJf8QYBdA/5naz65XDpczA==",
-      "requires": {
-        "@types/whatwg-url": "^8.2.1",
-        "whatwg-url": "^11.0.0"
-      }
-    },
-    "ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
-    },
-    "negotiator": {
-      "version": "0.6.3",
-      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
-      "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
-    },
-    "next-tick": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
-      "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
-    },
-    "node-fetch": {
-      "version": "2.6.7",
-      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
-      "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
-      "requires": {
-        "whatwg-url": "^5.0.0"
-      },
-      "dependencies": {
-        "tr46": {
-          "version": "0.0.3",
-          "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
-          "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
-        },
-        "whatwg-url": {
-          "version": "5.0.0",
-          "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
-          "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
-          "requires": {
-            "tr46": "~0.0.3",
-            "webidl-conversions": "^3.0.0"
-          }
-        }
-      }
-    },
-    "node-tesseract": {
-      "version": "0.2.7",
-      "resolved": "https://registry.npmjs.org/node-tesseract/-/node-tesseract-0.2.7.tgz",
-      "integrity": "sha1-yPAvuDUaQnByc1d4wFGYI/JgG4Q=",
-      "requires": {
-        "glob": "^5.0.10",
-        "node-uuid": "^1.4.1"
-      }
-    },
-    "node-uuid": {
-      "version": "1.4.8",
-      "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz",
-      "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc="
-    },
-    "object-inspect": {
-      "version": "1.12.0",
-      "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
-      "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g=="
-    },
-    "on-finished": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
-      "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
-      "requires": {
-        "ee-first": "1.1.1"
-      }
-    },
-    "once": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
-      "requires": {
-        "wrappy": "1"
-      }
-    },
-    "opencollective-postinstall": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz",
-      "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q=="
-    },
-    "parseurl": {
-      "version": "1.3.3",
-      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
-      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
-    },
-    "path-is-absolute": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
-    },
-    "path-to-regexp": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
-      "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
-    },
-    "piexifjs": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/piexifjs/-/piexifjs-1.0.6.tgz",
-      "integrity": "sha512-0wVyH0cKohzBQ5Gi2V1BuxYpxWfxF3cSqfFXfPIpl5tl9XLS5z4ogqhUCD20AbHi0h9aJkqXNJnkVev6gwh2ag=="
-    },
-    "proxy-addr": {
-      "version": "2.0.7",
-      "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
-      "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
-      "requires": {
-        "forwarded": "0.2.0",
-        "ipaddr.js": "1.9.1"
-      }
-    },
-    "punycode": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
-      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
-    },
-    "qs": {
-      "version": "6.10.3",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
-      "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
-      "requires": {
-        "side-channel": "^1.0.4"
-      }
-    },
-    "range-parser": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
-      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
-    },
-    "raw-body": {
-      "version": "2.5.1",
-      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
-      "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
-      "requires": {
-        "bytes": "3.1.2",
-        "http-errors": "2.0.0",
-        "iconv-lite": "0.4.24",
-        "unpipe": "1.0.0"
-      }
-    },
-    "regenerator-runtime": {
-      "version": "0.13.9",
-      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
-      "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
-    },
-    "resolve-url": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
-      "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
-    },
-    "safe-buffer": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
-    },
-    "safer-buffer": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
-    },
-    "saslprep": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
-      "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
-      "optional": true,
-      "requires": {
-        "sparse-bitfield": "^3.0.3"
-      }
-    },
-    "send": {
-      "version": "0.18.0",
-      "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
-      "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
-      "requires": {
-        "debug": "2.6.9",
-        "depd": "2.0.0",
-        "destroy": "1.2.0",
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "etag": "~1.8.1",
-        "fresh": "0.5.2",
-        "http-errors": "2.0.0",
-        "mime": "1.6.0",
-        "ms": "2.1.3",
-        "on-finished": "2.4.1",
-        "range-parser": "~1.2.1",
-        "statuses": "2.0.1"
-      },
-      "dependencies": {
-        "ms": {
-          "version": "2.1.3",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-          "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
-        }
-      }
-    },
-    "serve-static": {
-      "version": "1.15.0",
-      "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
-      "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
-      "requires": {
-        "encodeurl": "~1.0.2",
-        "escape-html": "~1.0.3",
-        "parseurl": "~1.3.3",
-        "send": "0.18.0"
-      }
-    },
-    "setprototypeof": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
-      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
-    },
-    "side-channel": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
-      "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
-      "requires": {
-        "call-bind": "^1.0.0",
-        "get-intrinsic": "^1.0.2",
-        "object-inspect": "^1.9.0"
-      }
-    },
-    "smart-buffer": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
-      "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="
-    },
-    "socks": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz",
-      "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==",
-      "requires": {
-        "ip": "^1.1.5",
-        "smart-buffer": "^4.2.0"
-      }
-    },
-    "sparse-bitfield": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
-      "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
-      "optional": true,
-      "requires": {
-        "memory-pager": "^1.0.2"
-      }
-    },
-    "statuses": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
-      "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
-    },
-    "structured-clone": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/structured-clone/-/structured-clone-0.2.2.tgz",
-      "integrity": "sha1-rJK2vjGVimQ9sw8TNavGobAt/cI="
-    },
-    "tesseract.js": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/tesseract.js/-/tesseract.js-2.1.5.tgz",
-      "integrity": "sha512-7CIS3SWr7TXpeaH9+HS7iUtVbCfPFYOO3p6rkRAkdtsOtrbz6496x59na6SCbFAIaZulQxy8BjwSu3qL3AoDRg==",
-      "requires": {
-        "blueimp-load-image": "^3.0.0",
-        "bmp-js": "^0.1.0",
-        "file-type": "^12.4.1",
-        "idb-keyval": "^3.2.0",
-        "is-electron": "^2.2.0",
-        "is-url": "^1.2.4",
-        "jpeg-autorotate": "^7.1.1",
-        "node-fetch": "^2.6.0",
-        "opencollective-postinstall": "^2.0.2",
-        "regenerator-runtime": "^0.13.3",
-        "resolve-url": "^0.2.1",
-        "tesseract.js-core": "^2.2.0",
-        "zlibjs": "^0.3.1"
-      }
-    },
-    "tesseract.js-core": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/tesseract.js-core/-/tesseract.js-core-2.2.0.tgz",
-      "integrity": "sha512-a8L+OJTbUipBsEDsJhDPlnLB0TY1MkTZqw5dqUwmiDSjUzwvU7HWLg/2+WDRulKUi4LE+7PnHlaBlW0k+V0U0w=="
-    },
-    "timers-ext": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz",
-      "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==",
-      "requires": {
-        "es5-ext": "~0.10.46",
-        "next-tick": "1"
-      }
-    },
-    "toidentifier": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
-      "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
-    },
-    "tr46": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
-      "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
-      "requires": {
-        "punycode": "^2.1.1"
-      }
-    },
-    "ts-mixer": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.1.tgz",
-      "integrity": "sha512-hvE+ZYXuINrx6Ei6D6hz+PTim0Uf++dYbK9FFifLNwQj+RwKquhQpn868yZsCtJYiclZF1u8l6WZxxKi+vv7Rg=="
-    },
-    "tslib": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
-      "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="
-    },
-    "type": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
-      "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
-    },
-    "type-is": {
-      "version": "1.6.18",
-      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
-      "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
-      "requires": {
-        "media-typer": "0.3.0",
-        "mime-types": "~2.1.24"
-      }
-    },
-    "typescript": {
-      "version": "4.6.2",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz",
-      "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg=="
-    },
-    "unpipe": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
-      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
-    },
-    "unscan": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/unscan/-/unscan-1.1.2.tgz",
-      "integrity": "sha512-a5RcGaBFMO9l78QWKffeWUo2cvfqUv05JCXuphE8MFOA92qyqp1Da7isnR+zjJspi45+yS8tTSuhd0vV3asWdA==",
-      "requires": {
-        "commander": "^8.3.0",
-        "form-data": "^4.0.0",
-        "node-fetch": "^2.6.5"
-      }
-    },
-    "utils-merge": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
-      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
-    },
-    "vary": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
-      "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
-    },
-    "webidl-conversions": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
-      "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
-    },
-    "whatwg-url": {
-      "version": "11.0.0",
-      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
-      "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
-      "requires": {
-        "tr46": "^3.0.0",
-        "webidl-conversions": "^7.0.0"
-      },
-      "dependencies": {
-        "webidl-conversions": {
-          "version": "7.0.0",
-          "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
-          "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="
-        }
-      }
-    },
-    "wordwrap": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
-      "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
-    },
-    "wrappy": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
-    },
-    "ws": {
-      "version": "8.8.0",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.0.tgz",
-      "integrity": "sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ==",
-      "requires": {}
-    },
-    "yargs-parser": {
-      "version": "20.2.9",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
-      "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="
-    },
-    "zlibjs": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/zlibjs/-/zlibjs-0.3.1.tgz",
-      "integrity": "sha1-UBl+2yihxCymWcyLTmqd3W1ERVQ="
-    },
-    "zod": {
-      "version": "3.13.4",
-      "resolved": "https://registry.npmjs.org/zod/-/zod-3.13.4.tgz",
-      "integrity": "sha512-LZRucWt4j/ru5azOkJxCfpR87IyFDn8h2UODdqvXzZLb3K7bb9chUrUIGTy3BPsr8XnbQYfQ5Md5Hu2OYIo1mg=="
-    }
-  }
-}
diff --git a/package.json b/package.json
index 39257d9..56f7dc2 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
     "@discordjs/builders": "^0.12.0",
     "@ungap/structured-clone": "^1.0.1",
     "body-parser": "^1.20.0",
-    "discord.js": "^13.8.0",
+    "discord.js": "13.8.1",
     "express": "^4.18.1",
     "humanize": "^0.0.9",
     "humanize-duration": "^3.27.1",
@@ -11,6 +11,7 @@
     "json-diff": "^0.7.1",
     "mongodb": "^4.7.0",
     "node-tesseract": "^0.2.7",
+    "opencv.js": "^1.2.1",
     "structured-clone": "^0.2.2",
     "tesseract.js": "^2.1.5",
     "typescript": "^4.5.5",
diff --git a/src/api/index.ts b/src/api/index.ts
index 07131ff..f5424b3 100644
--- a/src/api/index.ts
+++ b/src/api/index.ts
@@ -1,7 +1,7 @@
 import { HaikuClient } from 'jshaiku';
 import express from 'express';
 import bodyParser from 'body-parser';
-import generateEmojiEmbed from "../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../utils/generateEmojiEmbed.js";
 import structuredClone from '@ungap/structured-clone';
 
 
@@ -27,7 +27,7 @@
 
             let interaction = client.verify[code].interaction;
             if (interaction) {
-                interaction.editReply({embeds: [new generateEmojiEmbed()
+                interaction.editReply({embeds: [new EmojiEmbed()
                     .setTitle("Verify")
                     .setDescription(`Verification complete`)
                     .setStatus("Success")
@@ -45,7 +45,7 @@
         try {
             let interaction = client.verify[code].interaction;
             if (interaction) {
-                interaction.editReply({embeds: [new generateEmojiEmbed()
+                interaction.editReply({embeds: [new EmojiEmbed()
                     .setTitle("Verify")
                     .setDescription(`Verify was opened in another tab or window, please complete the CAPTCHA there to continue`)
                     .setStatus("Success")
diff --git a/src/automations/createModActionTicket.ts b/src/automations/createModActionTicket.ts
index a9a5a27..fad9a62 100644
--- a/src/automations/createModActionTicket.ts
+++ b/src/automations/createModActionTicket.ts
@@ -1,10 +1,10 @@
 import Discord, { MessageActionRow, MessageButton } from 'discord.js';
-import generateEmojiEmbed from '../utils/generateEmojiEmbed.js';
+import EmojiEmbed from '../utils/generateEmojiEmbed.js';
 import getEmojiByName from "../utils/getEmojiByName.js";
 import client from "../utils/client.js";
 
 export async function create(guild: Discord.Guild, member: Discord.User, createdBy: Discord.User, reason: string) {
-    let config = await client.database.read(guild.id);
+    let config = await client.database.guilds.read(guild.id);
     // @ts-ignore
     const { log, NucleusColors, entry, renderUser, renderChannel, renderDelta } = client.logger
     let overwrites = [{
@@ -48,7 +48,7 @@
                 }
             }
         )
-        await c.send({ embeds: [new generateEmojiEmbed()
+        await c.send({ embeds: [new EmojiEmbed()
             .setTitle("New Ticket")
             .setDescription(
                 `Ticket created by a Moderator\n` +
@@ -83,12 +83,12 @@
                 guild: guild.id
             }
         }
-        log(data, client);
+        log(data);
     } catch (e) { console.log(e); return null }
     return c.id
 }
 
 export async function areTicketsEnabled(guild: string) {
-    let config = await client.database.read(guild);
+    let config = await client.database.guilds.read(guild);
     return config.tickets.enabled;
 }
\ No newline at end of file
diff --git a/src/automations/guide.ts b/src/automations/guide.ts
index 2a686b9..8e0e6cd 100644
--- a/src/automations/guide.ts
+++ b/src/automations/guide.ts
@@ -1,6 +1,6 @@
 import { SelectMenuOption } from '@discordjs/builders';
 import Discord, { MessageActionRow, MessageButton } from "discord.js";
-import generateEmojiEmbed from "../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../utils/getEmojiByName.js";
 import createPageIndicator from "../utils/createPageIndicator.js";
 
@@ -20,7 +20,7 @@
     c = c ? c : guild.channels.cache.find(ch => ch.type === "GUILD_TEXT" && ch.permissionsFor(guild.roles.everyone).has("SEND_MESSAGES") && ch.permissionsFor(guild.me).has("EMBED_LINKS"));
     let pages = [
         new Embed()
-            .setEmbed(new generateEmojiEmbed()
+            .setEmbed(new EmojiEmbed()
                 .setTitle("Welcome to Nucleus")
                 .setDescription(
                     "Thanks for adding Nucleus to your server\n\n" +
@@ -31,7 +31,7 @@
                 .setStatus("Danger")
             ).setTitle("Welcome").setDescription("About Nucleus").setPageId(0),
         new Embed()
-            .setEmbed(new generateEmojiEmbed()
+            .setEmbed(new EmojiEmbed()
                 .setTitle("Logging")
                 .setDescription(
                     "Nucleus can log server events and keep you informed with what content is being posted to your server.\n" +
@@ -45,7 +45,7 @@
                 .setStatus("Danger")
             ).setTitle("Logging").setDescription("Logging, staff warning logs etc.").setPageId(1),
         new Embed()
-            .setEmbed(new generateEmojiEmbed()
+            .setEmbed(new EmojiEmbed()
                 .setTitle("Moderation")
                 .setDescription(
                     "Nucleus has a number of commands that can be used to moderate your server.\n" +
@@ -63,7 +63,7 @@
             .setStatus("Danger")
             ).setTitle("Moderation").setDescription("Basic moderation commands").setPageId(2),
         new Embed()
-            .setEmbed(new generateEmojiEmbed()
+            .setEmbed(new EmojiEmbed()
                 .setTitle("Verify")
                 .setDescription(
                     "Nucleus has a verification system that allows users to prove they aren't bots.\n" +
@@ -75,7 +75,7 @@
                 .setStatus("Danger")
             ).setTitle("Verify").setDescription("Captcha verification system").setPageId(3),
         new Embed()
-            .setEmbed(new generateEmojiEmbed()
+            .setEmbed(new EmojiEmbed()
                 .setTitle("Content Scanning")
                 .setDescription(
                     "Nucleus has a content scanning system that automatically scans links and images sent by users.\n" +
@@ -86,7 +86,7 @@
                 .setStatus("Danger")
             ).setTitle("Content Scanning").setDescription("Content (NSFW, malware, scams) scanning").setPageId(4),
         new Embed()
-            .setEmbed(new generateEmojiEmbed()
+            .setEmbed(new EmojiEmbed()
                 .setTitle("Tickets")
                 .setDescription(
                     "Nucleus has a ticket system that allows users to create tickets and have a support team respond to them.\n" +
@@ -98,7 +98,7 @@
                 .setStatus("Danger")
             ).setTitle("Tickets").setDescription("Ticket system").setPageId(5),
         new Embed()
-            .setEmbed(new generateEmojiEmbed()
+            .setEmbed(new EmojiEmbed()
                 .setTitle("Tags")
                 .setDescription(
                     "Add a tag system to your server with the `/tag` and `/tags` commands.\n" +
@@ -114,7 +114,7 @@
     let m;
     if (interaction) {
         m = await interaction.reply({embeds: [
-            new generateEmojiEmbed()
+            new EmojiEmbed()
                 .setTitle("Welcome")
                 .setDescription(`One moment...`)
                 .setStatus("Danger")
@@ -122,7 +122,7 @@
         ], fetchReply: true, ephemeral: true});
     } else {
         m = await c.send({embeds: [
-            new generateEmojiEmbed()
+            new EmojiEmbed()
                 .setTitle("Welcome")
                 .setDescription(`One moment...`)
                 .setStatus("Danger")
diff --git a/src/automations/roleMenu.ts b/src/automations/roleMenu.ts
index b13f949..e82c82c 100644
--- a/src/automations/roleMenu.ts
+++ b/src/automations/roleMenu.ts
@@ -1,24 +1,24 @@
 import { Message, MessageButton } from "discord.js";
-import generateEmojiEmbed from '../utils/generateEmojiEmbed.js'
+import EmojiEmbed from '../utils/generateEmojiEmbed.js'
 import { MessageActionRow, MessageSelectMenu } from 'discord.js';
 import getEmojiByName from "../utils/getEmojiByName.js";
 import client from "../utils/client.js";
 
 export async function callback(interaction) {
-    let config = await client.database.read(interaction.guild.id);
-    if (!config.roleMenu.enabled) return await interaction.reply({embeds: [new generateEmojiEmbed()
+    let config = await client.database.guilds.read(interaction.guild.id);
+    if (!config.roleMenu.enabled) return await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Roles")
         .setDescription("Self roles are currently disabled. Please contact a staff member or try again later.")
         .setStatus("Danger")
         .setEmoji("CONTROL.BLOCKCROSS")
     ], ephemeral: true})
-    if (config.roleMenu.options.length === 0) return await interaction.reply({embeds: [new generateEmojiEmbed()
+    if (config.roleMenu.options.length === 0) return await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Roles")
         .setDescription("There are no roles available. Please contact a staff member or try again later.")
         .setStatus("Danger")
         .setEmoji("CONTROL.BLOCKCROSS")
     ], ephemeral: true})
-    await interaction.reply({embeds: [new generateEmojiEmbed()
+    await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Roles")
         .setDescription("Loading...")
         .setStatus("Success")
@@ -49,7 +49,7 @@
             interaction: interaction
         };
         m = await interaction.editReply({
-            embeds: [new generateEmojiEmbed()
+            embeds: [new EmojiEmbed()
                 .setTitle("Roles")
                 .setDescription("Select how to choose your roles")
                 .setStatus("Success")
@@ -75,7 +75,7 @@
         let object = config.roleMenu.options[i];
         let m = await interaction.editReply({
             embeds: [
-                new generateEmojiEmbed()
+                new EmojiEmbed()
                     .setTitle("Roles")
                     .setEmoji("GUILD.GREEN")
                     .setDescription(`**${object.name}**` + (object.description ? `\n${object.description}` : ``) +
@@ -115,7 +115,7 @@
         if (component.customId == "rolemenu") {
             rolesToAdd = rolesToAdd.concat(component.values)
         } else if (component.customId == "cancel") {
-            return await interaction.editReply({embeds: [new generateEmojiEmbed()
+            return await interaction.editReply({embeds: [new EmojiEmbed()
                 .setTitle("Roles")
                 .setDescription("Cancelled. No changes were made.")
                 .setStatus("Danger")
@@ -131,14 +131,14 @@
         await interaction.member.roles.remove(rolesToRemove)
         await interaction.member.roles.add(rolesToAdd)
     } catch (e) {
-        return await interaction.reply({embeds: [new generateEmojiEmbed()
+        return await interaction.reply({embeds: [new EmojiEmbed()
             .setTitle("Roles")
             .setDescription("Something went wrong and your roles were not added. Please contact a staff member or try again later.")
             .setStatus("Danger")
             .setEmoji("GUILD.RED")
         ], components: []})
     }
-    await interaction.editReply({embeds: [new generateEmojiEmbed()
+    await interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Roles")
         .setDescription("Roles have been added. You may close this message.")
         .setStatus("Success")
diff --git a/src/automations/statsChannelAdd.ts b/src/automations/statsChannelAdd.ts
index 01dfef1..32de0ff 100644
--- a/src/automations/statsChannelAdd.ts
+++ b/src/automations/statsChannelAdd.ts
@@ -3,7 +3,7 @@
 import client from '../utils/client.js';
 
 export async function callback(_, member) {
-    let config = await client.database.read(member.guild.id);
+    let config = await client.database.guilds.read(member.guild.id);
 
     config.stats.forEach(async element => {
         if (element.enabled) {
diff --git a/src/automations/statsChannelRemove.ts b/src/automations/statsChannelRemove.ts
index fee0d2d..da4f43b 100644
--- a/src/automations/statsChannelRemove.ts
+++ b/src/automations/statsChannelRemove.ts
@@ -3,7 +3,7 @@
 import singleNotify from '../utils/singleNotify.js';
 
 export async function callback(_, member) {
-    let config = await client.database.read(member.guild.id);
+    let config = await client.database.guilds.read(member.guild.id);
 
     config.stats.forEach(async element => {
         if (element.enabled) {
diff --git a/src/automations/tickets/create.ts b/src/automations/tickets/create.ts
index 06e7e07..8eee3b2 100644
--- a/src/automations/tickets/create.ts
+++ b/src/automations/tickets/create.ts
@@ -1,7 +1,7 @@
 import Discord, { MessageActionRow, MessageButton } from "discord.js";
 import { tickets, toHexArray } from "../../utils/calculate.js";
 import client from "../../utils/client.js";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../../utils/getEmojiByName.js";
 
 function capitalize(s: string) {
@@ -12,9 +12,9 @@
 export default async function (interaction) {
     const { log, NucleusColors, entry, renderUser, renderChannel, renderDelta } = client.logger
 
-    let config = await client.database.read(interaction.guild.id);
+    let config = await client.database.guilds.read(interaction.guild.id);
     if (!config.tickets.enabled || !config.tickets.category) {
-        return await interaction.reply({embeds: [new generateEmojiEmbed()
+        return await interaction.reply({embeds: [new EmojiEmbed()
             .setTitle("Tickets are disabled")
             .setDescription("Please enable tickets in the configuration to use this command.")
             .setStatus("Danger")
@@ -32,7 +32,7 @@
         }
     });
     if (count >= config.tickets.maxTickets) {
-        return await interaction.reply({embeds: [new generateEmojiEmbed()
+        return await interaction.reply({embeds: [new EmojiEmbed()
             .setTitle("Create Ticket")
             .setDescription(`You have reached the maximum amount of tickets (${config.tickets.maxTickets}). Please close one of your active tickets before creating a new one.`)
             .setStatus("Danger")
@@ -41,7 +41,7 @@
     }
     let ticketTypes;
     let custom = false
-    if (config.tickets.customTypes) { ticketTypes = config.tickets.customTypes; custom = true }
+    if (config.tickets.customTypes && config.tickets.useCustom) { ticketTypes = config.tickets.customTypes; custom = true }
     else if (config.tickets.types) ticketTypes = toHexArray(config.tickets.types, tickets);
     else ticketTypes = [];
     let chosenType;
@@ -65,7 +65,7 @@
         for (let i = 0; i < formattedTicketTypes.length; i += 5) {
             splitFormattedTicketTypes.push(new MessageActionRow().addComponents(formattedTicketTypes.slice(i, i + 5)));
         }
-        let m = await interaction.reply({embeds: [new generateEmojiEmbed()
+        let m = await interaction.reply({embeds: [new EmojiEmbed()
             .setTitle("Create Ticket")
             .setDescription("Select a ticket type")
             .setStatus("Success")
@@ -99,7 +99,7 @@
         for (let i = 0; i < formattedTicketTypes.length; i += 5) {
             splitFormattedTicketTypes.push(new MessageActionRow().addComponents(formattedTicketTypes.slice(i, i + 5)));
         }
-        component.update({embeds: [new generateEmojiEmbed()
+        component.update({embeds: [new EmojiEmbed()
             .setTitle("Create Ticket")
             .setDescription("Select a ticket type")
             .setStatus("Success")
@@ -107,7 +107,7 @@
         ], components: splitFormattedTicketTypes});
     } else {
         chosenType = null
-        await interaction.reply({embeds: [new generateEmojiEmbed()
+        await interaction.reply({embeds: [new EmojiEmbed()
             .setTitle("Create Ticket")
             .setEmoji("GUILD.TICKET.OPEN")
         ], ephemeral: true, components: splitFormattedTicketTypes})
@@ -141,7 +141,7 @@
             reason: "Creating ticket"
         })
     } catch (e) {
-        return await interaction.editReply({embeds: [new generateEmojiEmbed()
+        return await interaction.editReply({embeds: [new EmojiEmbed()
             .setTitle("Create Ticket")
             .setDescription("Failed to create ticket")
             .setStatus("Danger")
@@ -161,7 +161,7 @@
         let content = interaction.options ? interaction.options.getString("message") || "" : "";
         if (content) content = `**Message:**\n> ${content}\n`;
         let emoji = custom ? "" : getEmojiByName("TICKETS." + chosenType.toUpperCase());
-        await c.send({ embeds: [new generateEmojiEmbed()
+        await c.send({ embeds: [new EmojiEmbed()
             .setTitle("New Ticket")
             .setDescription(
                 `Ticket created by <@${interaction.member.user.id}>\n` +
@@ -195,9 +195,9 @@
                 guild: interaction.guild.id
             }
         }
-        log(data, client);
+        log(data);
     } catch (e) { console.log(e)}
-    await interaction.editReply({embeds: [new generateEmojiEmbed()
+    await interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Create Ticket")
         .setDescription(`Ticket created. You can view it here: <#${c.id}>`)
         .setStatus("Success")
diff --git a/src/automations/tickets/delete.ts b/src/automations/tickets/delete.ts
index a974b2e..3df284b 100644
--- a/src/automations/tickets/delete.ts
+++ b/src/automations/tickets/delete.ts
@@ -1,18 +1,18 @@
 import Discord, { MessageButton, MessageActionRow } from "discord.js";
 import client from "../../utils/client.js";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../../utils/getEmojiByName.js";
 
 export default async function (interaction) {
     // @ts-ignore
     const { log, NucleusColors, entry, renderUser, renderChannel, renderDelta } = client.logger
 
-    let config = await client.database.read(interaction.guild.id);
+    let config = await client.database.guilds.read(interaction.guild.id);
     let thread = false; let threadChannel
     if (interaction.channel instanceof Discord.ThreadChannel) thread = true; threadChannel = interaction.channel as Discord.ThreadChannel
     let channel = (interaction.channel as Discord.TextChannel)
     if (!channel.parent || config.tickets.category != channel.parent.id || (thread ? (threadChannel.parent.parent.id != config.tickets.category) : false)) {
-        return interaction.reply({embeds: [new generateEmojiEmbed()
+        return interaction.reply({embeds: [new EmojiEmbed()
             .setTitle("Deleting Ticket...")
             .setDescription("This ticket is not in your tickets category, so cannot be deleted. You cannot run close in a thread.")
             .setStatus("Danger")
@@ -21,7 +21,7 @@
     }
     let status = channel.topic.split(" ")[1];
     if (status == "Archived") {
-        await interaction.reply({embeds: [new generateEmojiEmbed()
+        await interaction.reply({embeds: [new EmojiEmbed()
             .setTitle("Delete Ticket")
             .setDescription("Your ticket is being deleted...")
             .setStatus("Danger")
@@ -45,11 +45,11 @@
                 guild: interaction.guild.id
             }
         }
-        log(data, client);
+        log(data);
         interaction.channel.delete();
         return;
     } else if (status == "Active") {
-        await interaction.reply({embeds: [new generateEmojiEmbed()
+        await interaction.reply({embeds: [new EmojiEmbed()
             .setTitle("Close Ticket")
             .setDescription("Your ticket is being closed...")
             .setStatus("Warning")
@@ -95,8 +95,8 @@
                 guild: interaction.guild.id
             }
         }
-        log(data, client);
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        log(data);
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setTitle("Close Ticket")
             .setDescription("This ticket has been closed.\nType `/ticket close` again to delete it.")
             .setStatus("Warning")
@@ -112,7 +112,7 @@
 }
 
 async function purgeByUser(member, guild) {
-    let config = await client.database.read(guild.id);
+    let config = await client.database.guilds.read(guild.id);
     if (!config.tickets.category) return;
     let tickets = guild.channels.cache.get(config.tickets.category);
     if (!tickets) return;
@@ -147,7 +147,7 @@
                     guild: guild.id
                 }
             }
-            log(data, member.client);
+            log(data);
         } catch {}
     }
 }
diff --git a/src/automations/unscan.ts b/src/automations/unscan.ts
index d3a2a18..940a1fe 100644
--- a/src/automations/unscan.ts
+++ b/src/automations/unscan.ts
@@ -1,5 +1,4 @@
 import * as scan from '../utils/scanners.js'
-import process from 'tesseract.js'
 
 export async function LinkCheck(message): Promise<boolean> {
     let links = message.content.match(/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/gi) ?? []
@@ -7,11 +6,15 @@
     const promises = links.map(async element => {
         try {
             if (element.match(/https?:\/\/[a-zA-Z]+\.?discord(app)?\.(com|net)\/?/)) return // Also matches discord.net, not enough of a bug
+            console.log(1.1)
             element = await scan.testLink(element)
+            console.log(1.2)
         } catch {}
         detections.push({tags: element.tags || [], safe: element.safe})
     });
+    console.log(1)
     await Promise.all(promises);
+    console.log(2)
     let types = [
         "PHISHING",  "DATING",            "TRACKERS",    "ADVERTISEMENTS", "FACEBOOK",
         "AMP",       "FACEBOOK TRACKERS", "IP GRABBERS", "PORN",
@@ -21,9 +24,10 @@
     let detectionsTypes = detections.map(element => {
         let type = types.find(type => element.tags.includes(type))
         if (type) return type
-        if (!element.safe) return "UNSAFE"
+        // if (!element.safe) return "UNSAFE"
         return undefined
     }).filter(element => element !== undefined)
+    console.log(detectionsTypes)
     return detectionsTypes.length > 0
 }
 
diff --git a/src/automations/verify.ts b/src/automations/verify.ts
index f84ba20..ed24d25 100644
--- a/src/automations/verify.ts
+++ b/src/automations/verify.ts
@@ -1,5 +1,5 @@
 import Discord, { GuildMember } from "discord.js";
-import generateEmojiEmbed from "../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../utils/generateEmojiEmbed.js";
 import fetch from "node-fetch";
 import { TestString, NSFWCheck } from "../automations/unscan.js";
 import createPageIndicator from "../utils/createPageIndicator.js";
@@ -11,28 +11,28 @@
 
 export default async function(interaction) {
     let verify = client.verify
-    await interaction.reply({embeds: [new generateEmojiEmbed()
+    await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Loading")
         .setDescription(step(-1))
         .setStatus("Danger")
         .setEmoji("NUCLEUS.LOADING")
     ], ephemeral: true, fetchReply: true});
-    let config = await client.database.read(interaction.guild.id);
-    if ((!config.verify.enabled ) || (!config.verify.role)) return interaction.editReply({embeds: [new generateEmojiEmbed()
+    let config = await client.database.guilds.read(interaction.guild.id);
+    if ((!config.verify.enabled ) || (!config.verify.role)) return interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Verify")
         .setDescription(`Verify is not enabled on this server`)
         .setStatus("Danger")
         .setEmoji("CONTROL.BLOCKCROSS")
     ], ephemeral: true, fetchReply: true});
     if ((interaction.member as GuildMember).roles.cache.has(config.verify.role)) {
-        return await interaction.editReply({embeds: [new generateEmojiEmbed()
+        return await interaction.editReply({embeds: [new EmojiEmbed()
             .setTitle("Verify")
             .setDescription(`You already have the <@&${config.verify.role}> role` + step(0))
             .setStatus("Danger")
             .setEmoji("CONTROL.BLOCKCROSS")
         ]});
     }
-    await interaction.editReply({embeds: [new generateEmojiEmbed()
+    await interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Verify")
         .setDescription(`Checking our servers are up` + step(0))
         .setStatus("Warning")
@@ -41,7 +41,7 @@
     try {
         let status = await fetch(client.config.baseUrl).then(res => res.status);
         if (status != 200) {
-            return await interaction.editReply({embeds: [new generateEmojiEmbed()
+            return await interaction.editReply({embeds: [new EmojiEmbed()
                 .setTitle("Verify")
                 .setDescription(`Our servers appear to be down, please try again later` + step(0))
                 .setStatus("Danger")
@@ -49,7 +49,7 @@
             ]});
         }
     } catch {
-        return await interaction.editReply({embeds: [new generateEmojiEmbed()
+        return await interaction.editReply({embeds: [new EmojiEmbed()
             .setTitle("Verify")
             .setDescription(`Our servers appear to be down, please try again later` + step(0))
             .setStatus("Danger")
@@ -66,14 +66,14 @@
         ])]});
     }
     if (config.filters.images.NSFW) {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setTitle("Verify")
             .setDescription(`Checking your avatar is safe for work` + step(1))
             .setStatus("Warning")
             .setEmoji("NUCLEUS.LOADING")
         ]});
         if (await NSFWCheck((interaction.member as GuildMember).user.avatarURL({format: "png"}))) {
-            return await interaction.editReply({embeds: [new generateEmojiEmbed()
+            return await interaction.editReply({embeds: [new EmojiEmbed()
                 .setTitle("Verify")
                 .setDescription(`Your avatar was detected as NSFW, which we do not allow in this server.\nPlease contact one of our staff members if you believe this is a mistake` + step(1))
                 .setStatus("Danger")
@@ -82,14 +82,14 @@
         }
     }
     if (config.filters.wordFilter) {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setTitle("Verify")
             .setDescription(`Checking your name is allowed` + step(2))
             .setStatus("Warning")
             .setEmoji("NUCLEUS.LOADING")
         ]});
         if (TestString((interaction.member as Discord.GuildMember).displayName, config.filters.wordFilter.words.loose, config.filters.wordFilter.words.strict) != "none") {
-            return await interaction.editReply({embeds: [new generateEmojiEmbed()
+            return await interaction.editReply({embeds: [new EmojiEmbed()
                 .setTitle("Verify")
                 .setDescription(`Your name contained a word we do not allow in this server.\nPlease contact one of our staff members if you believe this is a mistake` + step(2))
                 .setStatus("Danger")
@@ -97,7 +97,7 @@
             ]});
         }
     }
-    await interaction.editReply({embeds: [new generateEmojiEmbed()
+    await interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Verify")
         .setDescription(`One moment...` + step(3))
         .setStatus("Warning")
@@ -129,7 +129,7 @@
         gIcon: interaction.guild.iconURL({format: "png"}),
         interaction: interaction
     }
-    await interaction.editReply({embeds: [new generateEmojiEmbed()
+    await interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Verify")
         .setDescription(`Looking good!\nClick the button below to get verified` + step(4))
         .setStatus("Success")
diff --git a/src/automations/welcome.ts b/src/automations/welcome.ts
index 11c4844..5b80fbd 100644
--- a/src/automations/welcome.ts
+++ b/src/automations/welcome.ts
@@ -4,7 +4,7 @@
 
 export async function callback(_, member) {
     if (member.bot) return
-    let config = await client.database.read(member.guild.id);
+    let config = await client.database.guilds.read(member.guild.id);
     if (!config.welcome.enabled) return
 
     if (!config.welcome.verificationRequired.role) {
diff --git a/src/commands/categorisationTest.ts b/src/commands/categorisationTest.ts
index 4a28841..a6c7479 100644
--- a/src/commands/categorisationTest.ts
+++ b/src/commands/categorisationTest.ts
@@ -1,21 +1,22 @@
 import { CommandInteraction, MessageActionRow, MessageButton, MessageSelectMenu } from "discord.js";
-import { SelectMenuComponent, SelectMenuOption, SlashCommandBuilder } from "@discordjs/builders";
+import { SlashCommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
-import generateEmojiEmbed from "../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../utils/generateEmojiEmbed.js";
 import generateKeyValueList, { toCapitals } from "../utils/generateKeyValueList.js";
 import getEmojiByName from "../utils/getEmojiByName.js";
+import client from "../utils/client.js"
 
 const command = new SlashCommandBuilder()
     .setName("categorise")
     .setDescription("Categorises your servers channels")
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
     const { renderChannel } = client.logger
 
     let channels = interaction.guild.channels.cache.filter(c => c.type !== "GUILD_CATEGORY");
     let categorised = {}
 
-    await interaction.reply({embeds: [new generateEmojiEmbed()
+    await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Loading...")
         .setEmoji("NUCLEUS.LOADING")
         .setStatus("Success")
@@ -40,7 +41,7 @@
             }
         }
 
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setTitle("Categorise")
             .setDescription(generateKeyValueList({
                 channel: renderChannel(c),
diff --git a/src/commands/mod/ban.ts b/src/commands/mod/ban.ts
index 8b17db3..4581c0f 100644
--- a/src/commands/mod/ban.ts
+++ b/src/commands/mod/ban.ts
@@ -2,7 +2,7 @@
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
 import confirmationMessage from "../../utils/confirmationMessage.js";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
 import addPlurals from "../../utils/plurals.js";
 import client from "../../utils/client.js";
@@ -18,13 +18,14 @@
     )
     .addIntegerOption(option => option.setName("delete").setDescription("The days of messages to delete | Default 0").setMinValue(0).setMaxValue(7).setRequired(false))
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
+    const { renderUser } = client.logger
     // TODO:[Modals] Replace this with a modal
     let confirmation = await new confirmationMessage(interaction)
         .setEmoji("PUNISH.BAN.RED")
         .setTitle("Ban")
         .setDescription(keyValueList({
-            "user": `<@!${(interaction.options.getMember("user") as GuildMember).id}> (${(interaction.options.getMember("user") as GuildMember).user.username})`,
+            "user": renderUser(interaction.options.getUser("user")),
             "reason": `\n> ${interaction.options.getString("reason") ? interaction.options.getString("reason") : "*No reason provided*"}`
         })
         + `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n`
@@ -35,11 +36,11 @@
     if (confirmation.success) {
         let dmd = false
         let dm;
-        let config = await client.database.read(interaction.guild.id);
+        let config = await client.database.guilds.read(interaction.guild.id);
         try {
             if (interaction.options.getString("notify") != "no") {
                 dm = await (interaction.options.getMember("user") as GuildMember).send({
-                    embeds: [new generateEmojiEmbed()
+                    embeds: [new EmojiEmbed()
                         .setEmoji("PUNISH.BAN.RED")
                         .setTitle("Banned")
                         .setDescription(`You have been banned in ${interaction.guild.name}` +
@@ -57,13 +58,13 @@
         } catch {}
         try {
             let member = (interaction.options.getMember("user") as GuildMember)
-            let reason = interaction.options.getString("reason") ?? "No reason provided"
+            let reason = interaction.options.getString("reason")
             member.ban({
                 days: Number(interaction.options.getInteger("delete") ?? 0),
-                reason: reason
+                reason: reason ?? "No reason provided"
             })
-            // @ts-ignore
-            const { log, NucleusColors, entry, renderUser, renderDelta } = interaction.user.client.logger
+            try { await client.database.history.create("ban", interaction.guild.id, member.user, interaction.user, reason) } catch {}
+            const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger
             let data = {
                 meta: {
                     type: 'memberBan',
@@ -86,9 +87,9 @@
                     guild: interaction.guild.id
                 }
             }
-            log(data, member.user.client);
+            log(data);
         } catch {
-            await interaction.editReply({embeds: [new generateEmojiEmbed()
+            await interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji("PUNISH.BAN.RED")
                 .setTitle(`Ban`)
                 .setDescription("Something went wrong and the user was not banned")
@@ -98,14 +99,14 @@
             return
         }
         let failed = (dmd == false && interaction.options.getString("notify") != "no")
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji(`PUNISH.BAN.${failed ? "YELLOW" : "GREEN"}`)
             .setTitle(`Ban`)
             .setDescription("The member was banned" + (failed ? ", but could not be notified" : ""))
             .setStatus(failed ? "Warning" : "Success")
         ], components: []})
     } else {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji("PUNISH.BAN.GREEN")
             .setTitle(`Ban`)
             .setDescription("No changes were made")
@@ -125,13 +126,13 @@
     // Check if Nucleus can ban the member
     if (! (mePos > applyPos)) throw "I do not have a role higher than that member"
     // Check if Nucleus has permission to ban
-    if (! me.permissions.has("BAN_MEMBERS")) throw "I do not have the `ban_members` permission";
+    if (! me.permissions.has("BAN_MEMBERS")) throw "I do not have the Ban members permission";
     // Do not allow banning Nucleus
     if (member.id == interaction.guild.me.id) throw "I cannot ban myself"
     // Allow the owner to ban anyone
     if (member.id == interaction.guild.ownerId) return true
     // Check if the user has ban_members permission
-    if (! member.permissions.has("BAN_MEMBERS")) throw "You do not have the `ban_members` permission";
+    if (! member.permissions.has("BAN_MEMBERS")) throw "You do not have the Ban members permission";
     // Check if the user is below on the role list
     if (! (memberPos > applyPos)) throw "You do not have a role higher than that member"
     // Allow ban
diff --git a/src/commands/mod/info.ts b/src/commands/mod/info.ts
new file mode 100644
index 0000000..c3a4388
--- /dev/null
+++ b/src/commands/mod/info.ts
@@ -0,0 +1,285 @@
+import { HistorySchema } from '../../utils/database';
+import Discord, { CommandInteraction, GuildMember, MessageActionRow, MessageButton, TextInputComponent } from "discord.js";
+import { SlashCommandSubcommandBuilder, SelectMenuOption } from "@discordjs/builders";
+import { WrappedCheck } from "jshaiku";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import getEmojiByName from "../../utils/getEmojiByName.js";
+import client from "../../utils/client.js";
+import { modalInteractionCollector } from '../../utils/dualCollector.js';
+import pageIndicator from '../../utils/createPageIndicator.js';
+
+const command = (builder: SlashCommandSubcommandBuilder) =>
+    builder
+    .setName("info")
+    .setDescription("Shows moderator information about a user")
+    .addUserOption(option => option.setName("user").setDescription("The user to get information about").setRequired(true))
+
+
+const types = {
+    "warn": {emoji: "PUNISH.WARN.YELLOW", text: "Warned"},
+    "mute": {emoji: "PUNISH.MUTE.YELLOW", text: "Muted"},
+    "join": {emoji: "MEMBER.JOIN", text: "Joined"},
+    "leave": {emoji: "MEMBER.LEAVE", text: "Left"},
+    "kick": {emoji: "MEMBER.KICK", text: "Kicked"},
+    "softban": {emoji: "PUNISH.SOFTBAN", text: "Softbanned"},
+    "ban": {emoji: "MEMBER.BAN", text: "Banned"},
+    "unban": {emoji: "MEMBER.UNBAN", text: "Unbanned"},
+    "purge": {emoji: "PUNISH.CLEARHISTORY", text: "Messages cleared"},
+    "nickname": {emoji: "PUNISH.NICKNAME.YELLOW", text: "Nickname changed"}
+}
+
+function historyToString(history: HistorySchema) {
+    let s = `${getEmojiByName(types[history.type].emoji)} ${
+        history.amount ? (history.amount + " ") : ""
+    }${
+        types[history.type].text
+    } on <t:${Math.round(history.occurredAt.getTime() / 1000)}:F>`;
+    if (history.moderator) { s += ` by <@${history.moderator}>`; }
+    if (history.reason) { s += `\n**Reason:**\n> ${history.reason}`; }
+    if (history.before) { s += `\n**Before:**\n> ${history.before}`; }
+    if (history.after) { s += `\n**After:**\n> ${history.after}`; }
+    return s + "\n";
+}
+
+
+class TimelineSection {
+    name: string;
+    content: {data: HistorySchema, rendered: string}[] = []
+
+    addContent = (content: {data: HistorySchema, rendered: string}) => { this.content.push(content); return this; }
+    contentLength = () => { return this.content.reduce((acc, cur) => acc + cur.rendered.length, 0); };
+    generateName = () => {
+        let first = Math.round(this.content[0].data.occurredAt.getTime() / 1000)
+        let last = Math.round(this.content[this.content.length - 1].data.occurredAt.getTime() / 1000)
+        if (first === last) { return this.name = `<t:${first}:F>`; }
+        return this.name = `<t:${first}:F> - <t:${last}:F>`;
+    }
+}
+
+const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
+
+async function showHistory(member, interaction: CommandInteraction) {
+    let currentYear = new Date().getFullYear();
+    let pageIndex = null;
+    let m, history, current;
+    let refresh = true;
+    let filteredTypes = [];
+    let openFilterPane = false;
+    while (true) {
+        if (refresh) {
+            history = await client.database.history.read(member.guild.id, member.id, currentYear);
+            history = history.sort((a, b) => b.occurredAt.getTime() - a.occurredAt.getTime()).reverse();
+            if (openFilterPane) {
+                let tempFilteredTypes = filteredTypes
+                if (filteredTypes.length === 0) { tempFilteredTypes = Object.keys(types); }
+                history = history.filter(h => tempFilteredTypes.includes(h.type))
+            };
+            refresh = false;
+        }
+        let groups: TimelineSection[] = []
+        if (history.length > 0) {
+            current = new TimelineSection()
+            history.forEach(event => {
+                if (current.contentLength() + historyToString(event).length > 2000 || current.content.length === 5) {
+                    groups.push(current);
+                    current.generateName();
+                    current = new TimelineSection();
+                }
+                current.addContent({data: event, rendered: historyToString(event)});
+            });
+            current.generateName();
+            groups.push(current);
+            if (pageIndex === null) { pageIndex = groups.length - 1; }
+        }
+        let components = (
+            openFilterPane ? [
+            new MessageActionRow().addComponents([new Discord.MessageSelectMenu().setOptions(
+                Object.entries(types).map(([key, value]) => ({
+                        label: value.text,
+                        value: key,
+                        default: filteredTypes.includes(key),
+                        emoji: client.emojis.resolve(getEmojiByName(value.emoji, "id"))
+                }))
+            ).setMinValues(1).setMaxValues(Object.keys(types).length).setCustomId("filter").setPlaceholder("Select at least one event")])
+        ] : []).concat([
+            new MessageActionRow().addComponents([
+                new MessageButton()
+                    .setCustomId("prevYear")
+                    .setLabel((currentYear - 1).toString())
+                    .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
+                    .setStyle("SECONDARY"),
+                new MessageButton()
+                    .setCustomId("prevPage")
+                    .setLabel("Previous page")
+                    .setStyle("PRIMARY"),
+                new MessageButton()
+                    .setCustomId("today")
+                    .setLabel("Today")
+                    .setStyle("PRIMARY"),
+                new MessageButton()
+                    .setCustomId("nextPage")
+                    .setLabel("Next page")
+                    .setStyle("PRIMARY")
+                    .setDisabled(pageIndex >= groups.length - 1 && currentYear === new Date().getFullYear()),
+                new MessageButton()
+                    .setCustomId("nextYear")
+                    .setLabel((currentYear + 1).toString())
+                    .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
+                    .setStyle("SECONDARY")
+                    .setDisabled(currentYear === new Date().getFullYear()),
+            ]), new MessageActionRow().addComponents([
+                new MessageButton()
+                    .setLabel("Mod notes")
+                    .setCustomId("modNotes")
+                    .setStyle("PRIMARY")
+                    .setEmoji(getEmojiByName("ICONS.EDIT", "id")),
+                new MessageButton()
+                    .setLabel("Filter")
+                    .setCustomId("openFilter")
+                    .setStyle(openFilterPane ? "SUCCESS" : "PRIMARY")
+                    .setEmoji(getEmojiByName("ICONS.FILTER", "id"))
+            ])
+        ])
+        let end = "\n\nJanuary " + currentYear.toString() + pageIndicator(
+            Math.max(groups.length, 1),
+            groups.length === 0 ? 1 : pageIndex
+        ) + (currentYear == new Date().getFullYear() ? monthNames[new Date().getMonth()] : "December"
+        ) + " " + currentYear.toString()
+        if (groups.length > 0) {
+            let toRender = groups[Math.min(pageIndex, groups.length - 1)]
+            m = await interaction.editReply({embeds: [new EmojiEmbed()
+                .setEmoji("MEMBER.JOIN")
+                .setTitle("Moderation history for " + member.user.username)
+                .setDescription(`**${toRender.name}**\n\n` + toRender.content.map(c => c.rendered).join("\n") + end)
+                .setStatus("Success")
+                .setFooter({text: (openFilterPane && filteredTypes.length) ? "Filters are currently enabled" : ""})
+            ], components: components});
+        } else {
+            m = await interaction.editReply({embeds: [new EmojiEmbed()
+                .setEmoji("MEMBER.JOIN")
+                .setTitle("Moderation history for " + member.user.username)
+                .setDescription(`**${currentYear}**\n\n*No events*` + `\n\n` + end)
+                .setStatus("Success")
+                .setFooter({text: (openFilterPane && filteredTypes.length) ? "Filters are currently enabled" : ""})
+            ], components: components});
+        }
+        let i;
+        try {
+            i = await m.awaitMessageComponent({ time: 300000 });
+        } catch (e) {
+            interaction.editReply({embeds: [new EmojiEmbed()
+                .setEmoji("MEMBER.JOIN")
+                .setTitle("Moderation history for " + member.user.username)
+                .setDescription(m.embeds[0].description)
+                .setStatus("Danger")
+                .setFooter({text: "Message timed out"})
+            ]});
+            return 0
+        }
+        i.deferUpdate()
+        if (i.customId === "filter") {
+            filteredTypes = i.values;
+            pageIndex = null;
+            refresh = true;
+        }
+        if (i.customId === "prevYear") { currentYear--; pageIndex = null; refresh = true; }
+        if (i.customId === "nextYear") { currentYear++; pageIndex = null; refresh = true; }
+        if (i.customId === "prevPage") {
+            pageIndex--;
+            if (pageIndex < 0) { pageIndex = null; currentYear--; refresh = true; }
+        }
+        if (i.customId === "nextPage") {
+            pageIndex++;
+            if (pageIndex >= groups.length) { pageIndex = 0; currentYear++; refresh = true; }
+        }
+        if (i.customId === "today") { currentYear = new Date().getFullYear(); pageIndex = null; refresh = true; }
+        if (i.customId === "modNotes") { return 1 }
+        if (i.customId === "openFilter") { openFilterPane = !openFilterPane; refresh = true }
+    }
+}
+
+
+const callback = async (interaction: CommandInteraction): Promise<any> => {
+    let m;
+    let member = (interaction.options.getMember("user")) as Discord.GuildMember;
+    await interaction.reply({embeds: [new EmojiEmbed()
+        .setEmoji("NUCLEUS.LOADING")
+        .setTitle("Downloading data...")
+        .setStatus("Success")
+    ], ephemeral: true, fetchReply: true});
+    let note;
+    let firstLoad = true;
+    while (true) {
+        note = await client.database.notes.read(member.guild.id, member.id);
+        if (firstLoad && !note) { await showHistory(member, interaction); }
+        firstLoad = false;
+        m = await interaction.editReply({embeds: [new EmojiEmbed()
+            .setEmoji("MEMBER.JOIN")
+            .setTitle("Mod notes for " + member.user.username)
+            .setDescription(note ? note : "*No note set*")
+            .setStatus("Success")
+        ], components: [new MessageActionRow().addComponents([
+            new MessageButton()
+                .setLabel(`${note ? "Modify" : "Create"} note`)
+                .setStyle("PRIMARY")
+                .setCustomId("modify")
+                .setEmoji(getEmojiByName("ICONS.EDIT", "id")),
+            new MessageButton()
+                .setLabel("View moderation history")
+                .setStyle("PRIMARY")
+                .setCustomId("history")
+                .setEmoji(getEmojiByName("ICONS.HISTORY", "id"))
+        ])]});
+        let i;
+        try {
+            i = await m.awaitMessageComponent({ time: 300000 });
+        } catch (e) { return }
+        if (i.customId === "modify") {
+            await i.showModal(new Discord.Modal().setCustomId("modal").setTitle(`Editing moderator note`).addComponents(
+                // @ts-ignore
+                new MessageActionRow().addComponents(new TextInputComponent()
+                    .setCustomId("note")
+                    .setLabel("Note")
+                    .setMaxLength(4000)
+                    .setRequired(false)
+                    .setStyle("PARAGRAPH")
+                    .setValue(note ? note : "")
+                )
+            ))
+            await interaction.editReply({
+                embeds: [new EmojiEmbed()
+                    .setTitle("Mod notes for " + member.user.username)
+                    .setDescription("Modal opened. If you can't see it, click back and try again.")
+                    .setStatus("Success")
+                    .setEmoji("GUILD.TICKET.OPEN")
+                ], components: [new MessageActionRow().addComponents([new MessageButton()
+                    .setLabel("Back")
+                    .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
+                    .setStyle("PRIMARY")
+                    .setCustomId("back")
+                ])]
+            });
+            let out;
+            try {
+                out = await modalInteractionCollector(m, (m) => m.channel.id == interaction.channel.id, (m) => m.customId == "modify")
+            } catch (e) { continue }
+            if (out.fields) {
+                let toAdd = out.fields.getTextInputValue("note") || null;
+                await client.database.notes.create(member.guild.id, member.id, toAdd);
+            } else { continue }
+        } else if (i.customId === "history") {
+            i.deferUpdate();
+            if (!await showHistory(member, interaction) ) return
+        }
+    }
+}
+
+const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
+    let member = (interaction.member as GuildMember)
+    if (! member.permissions.has("MODERATE_MEMBERS")) throw "You do not have the Moderate members permission";
+    return true
+}
+
+export { command };
+export { callback };
+export { check };
\ No newline at end of file
diff --git a/src/commands/mod/kick.ts b/src/commands/mod/kick.ts
index 20fbc01..97ead7b 100644
--- a/src/commands/mod/kick.ts
+++ b/src/commands/mod/kick.ts
@@ -3,7 +3,7 @@
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
 import confirmationMessage from "../../utils/confirmationMessage.js";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
 import client from "../../utils/client.js";
 
@@ -17,13 +17,14 @@
         .addChoices([["Yes", "yes"], ["No", "no"]])
     )
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
+    const { renderUser } = client.logger
     // TODO:[Modals] Replace this with a modal
     let confirmation = await new confirmationMessage(interaction)
         .setEmoji("PUNISH.KICK.RED")
         .setTitle("Kick")
         .setDescription(keyValueList({
-            "user": `<@!${(interaction.options.getMember("user") as GuildMember).id}> (${(interaction.options.getMember("user") as GuildMember).user.username})`,
+            "user": renderUser(interaction.options.getUser("user")),
             "reason": `\n> ${interaction.options.getString("reason") ? interaction.options.getString("reason") : "*No reason provided*"}`
         })
         + `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n\n`
@@ -33,11 +34,11 @@
     if (confirmation.success) {
         let dmd = false
         let dm;
-        let config = await client.database.read(interaction.guild.id);
+        let config = await client.database.guilds.read(interaction.guild.id);
         try {
             if (interaction.options.getString("notify") != "no") {
                 dm = await (interaction.options.getMember("user") as GuildMember).send({
-                    embeds: [new generateEmojiEmbed()
+                    embeds: [new EmojiEmbed()
                         .setEmoji("PUNISH.KICK.RED")
                         .setTitle("Kicked")
                         .setDescription(`You have been kicked in ${interaction.guild.name}` +
@@ -57,8 +58,9 @@
             (interaction.options.getMember("user") as GuildMember).kick(interaction.options.getString("reason") ?? "No reason provided.")
             let member = (interaction.options.getMember("user") as GuildMember)
             let reason = interaction.options.getString("reason") ?? null
+            try { await client.database.history.create("kick", interaction.guild.id, member.user, interaction.user, reason) } catch {}
             // @ts-ignore
-            const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = member.client.logger
+            const { log, NucleusColors, entry, renderUser, renderDelta } = member.client.logger
             let data = {
                 meta: {
                     type: 'memberKick',
@@ -83,9 +85,9 @@
                     guild: member.guild.id
                 }
             }
-            log(data, member.client);
+            log(data);
         } catch {
-            await interaction.editReply({embeds: [new generateEmojiEmbed()
+            await interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji("PUNISH.KICK.RED")
                 .setTitle(`Kick`)
                 .setDescription("Something went wrong and the user was not kicked")
@@ -95,14 +97,14 @@
             return
         }
         let failed = (dmd == false && interaction.options.getString("notify") != "no")
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji(`PUNISH.KICK.${failed ? "YELLOW" : "GREEN"}`)
             .setTitle(`Kick`)
             .setDescription("The member was kicked" + (failed ? ", but could not be notified" : ""))
             .setStatus(failed ? "Warning" : "Success")
         ], components: []})
     } else {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji("PUNISH.KICK.GREEN")
             .setTitle(`Kick`)
             .setDescription("No changes were made")
@@ -122,13 +124,13 @@
     // Check if Nucleus can kick the member
     if (! (mePos > applyPos)) throw "I do not have a role higher than that member"
     // Check if Nucleus has permission to kick
-    if (! me.permissions.has("KICK_MEMBERS")) throw "I do not have the `kick_members` permission";
+    if (! me.permissions.has("KICK_MEMBERS")) throw "I do not have the Kick members permission";
     // Do not allow kicking Nucleus
     if (member.id == interaction.guild.me.id) throw "I cannot kick myself"
     // Allow the owner to kick anyone
     if (member.id == interaction.guild.ownerId) return true
     // Check if the user has kick_members permission
-    if (! member.permissions.has("KICK_MEMBERS")) throw "You do not have the `kick_members` permission";
+    if (! member.permissions.has("KICK_MEMBERS")) throw "You do not have the Kick members permission";
     // Check if the user is below on the role list
     if (! (memberPos > applyPos)) throw "You do not have a role higher than that member"
     // Allow kick
diff --git a/src/commands/mod/mute.ts b/src/commands/mod/mute.ts
index 79beeb3..5f42b27 100644
--- a/src/commands/mod/mute.ts
+++ b/src/commands/mod/mute.ts
@@ -1,7 +1,7 @@
 import Discord, { CommandInteraction, GuildMember, MessageActionRow, MessageButton } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../../utils/getEmojiByName.js";
 import confirmationMessage from "../../utils/confirmationMessage.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
@@ -31,14 +31,14 @@
         minutes: interaction.options.getInteger("minutes") || 0,
         seconds: interaction.options.getInteger("seconds") || 0
     }
-    let config = await client.database.read(interaction.guild.id)
+    let config = await client.database.guilds.read(interaction.guild.id)
     let serverSettingsDescription = (config.moderation.mute.timeout ? "given a timeout" : "")
     if (config.moderation.mute.role) serverSettingsDescription += (serverSettingsDescription ? " and " : "") + `given the <@&${config.moderation.mute.role}> role`
 
     let muteTime = (time.days * 24 * 60 * 60) + (time.hours * 60 * 60) + (time.minutes * 60) + time.seconds
     if (muteTime == 0) {
         let m = await interaction.reply({embeds: [
-            new generateEmojiEmbed()
+            new EmojiEmbed()
                 .setEmoji("PUNISH.MUTE.GREEN")
                 .setTitle("Mute")
                 .setDescription("How long should the user be muted")
@@ -93,7 +93,7 @@
             component = await (m as Discord.Message).awaitMessageComponent({filter: (m) => m.user.id === interaction.user.id, time: 300000});
         } catch { return }
         component.deferUpdate();
-        if (component.customId == "cancel") return interaction.editReply({embeds: [new generateEmojiEmbed()
+        if (component.customId == "cancel") return interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji("PUNISH.MUTE.RED")
             .setTitle("Mute")
             .setDescription("Mute cancelled")
@@ -111,7 +111,7 @@
         }
     } else {
         await interaction.reply({embeds: [
-            new generateEmojiEmbed()
+            new EmojiEmbed()
                 .setEmoji("PUNISH.MUTE.GREEN")
                 .setTitle("Mute")
                 .setDescription("Loading...")
@@ -123,7 +123,7 @@
         .setEmoji("PUNISH.MUTE.RED")
         .setTitle("Mute")
         .setDescription(keyValueList({
-            "user": `<@!${user.id}> (${user.user.username})`,
+            "user": renderUser(user),
             "time": `${humanizeDuration(muteTime * 1000, {round: true})}`,
             "reason": `\n> ${reason ? reason : "*No reason provided*"}`
         })
@@ -135,11 +135,11 @@
     if (confirmation.success) {
         let dmd = false
         let dm;
-        let config = await client.database.read(interaction.guild.id);
+        let config = await client.database.guilds.read(interaction.guild.id);
         try {
             if (interaction.options.getString("notify") != "no") {
                 dm = await (interaction.options.getMember("user") as GuildMember).send({
-                    embeds: [new generateEmojiEmbed()
+                    embeds: [new EmojiEmbed()
                         .setEmoji("PUNISH.MUTE.RED")
                         .setTitle("Muted")
                         .setDescription(`You have been muted in ${interaction.guild.name}` +
@@ -156,15 +156,16 @@
                 dmd = true
             }
         } catch {}
+        let member = (interaction.options.getMember("user") as GuildMember)
         try {
             if (config.moderation.mute.timeout) {
-                (interaction.options.getMember("user") as GuildMember).timeout(muteTime * 1000, interaction.options.getString("reason") || "No reason provided")
+                member.timeout(muteTime * 1000, interaction.options.getString("reason") || "No reason provided")
             }
             if (config.moderation.mute.role) {
-                (interaction.options.getMember("user") as GuildMember).roles.add(config.moderation.mute.role)
+                member.roles.add(config.moderation.mute.role)
             }
         } catch {
-            await interaction.editReply({embeds: [new generateEmojiEmbed()
+            await interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji("PUNISH.MUTE.RED")
                 .setTitle(`Mute`)
                 .setDescription("Something went wrong and the user was not mute")
@@ -173,8 +174,9 @@
             if (dmd) await dm.delete()
             return
         }
+        try { await client.database.history.create("mute", interaction.guild.id, member.user, interaction.user, reason) } catch {}
         let failed = (dmd == false && interaction.options.getString("notify") != "no")
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji(`PUNISH.MUTE.${failed ? "YELLOW" : "GREEN"}`)
             .setTitle(`Mute`)
             .setDescription("The member was muted" + (failed ? ", but could not be notified" : ""))
@@ -190,7 +192,7 @@
                 timestamp: new Date().getTime()
             },
             list: {
-                user: entry((interaction.options.getMember("user") as GuildMember).user.id, renderUser((interaction.options.getMember("user") as GuildMember).user)),
+                user: entry(member.user.id, renderUser(member.user)),
                 mutedBy: entry(interaction.member.user.id, renderUser(interaction.member.user)),
                 time: entry(muteTime, `${humanizeDuration(muteTime * 1000, {round: true})}`),
                 reason: (interaction.options.getString("reason") ? `\n> ${interaction.options.getString("reason")}` : "No reason provided")
@@ -199,9 +201,9 @@
                 guild: interaction.guild.id
             }
         }
-        log(data, client);
+        log(data);
     } else {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji("PUNISH.MUTE.GREEN")
             .setTitle(`Mute`)
             .setDescription("No changes were made")
@@ -221,7 +223,7 @@
     // Check if Nucleus can mute the member
     if (! (mePos > applyPos)) throw "I do not have a role higher than that member"
     // Check if Nucleus has permission to mute
-    if (! me.permissions.has("MODERATE_MEMBERS")) throw "I do not have the `moderate_members` permission";
+    if (! me.permissions.has("MODERATE_MEMBERS")) throw "I do not have the Moderate members permission";
     // Do not allow the user to have admin or be the owner
     if (apply.permissions.has("ADMINISTRATOR") || (interaction.options.getMember("user") as GuildMember).id == interaction.guild.ownerId) throw "You cannot mute an admin or the owner"
     // Do not allow muting Nucleus
@@ -229,7 +231,7 @@
     // Allow the owner to mute anyone
     if (member.id == interaction.guild.ownerId) return true
     // Check if the user has moderate_members permission
-    if (! member.permissions.has("MODERATE_MEMBERS")) throw "You do not have the `moderate_members` permission";
+    if (! member.permissions.has("MODERATE_MEMBERS")) throw "You do not have the Moderate members permission";
     // Check if the user is below on the role list
     if (! (memberPos > applyPos)) throw "You do not have a role higher than that member"
     // Allow mute
diff --git a/src/commands/mod/nick.ts b/src/commands/mod/nick.ts
index c09e197..e154277 100644
--- a/src/commands/mod/nick.ts
+++ b/src/commands/mod/nick.ts
@@ -2,9 +2,10 @@
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
 import confirmationMessage from "../../utils/confirmationMessage.js";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
 import { create, areTicketsEnabled } from "../../automations/createModActionTicket.js";
+import client from "../../utils/client.js"
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
     builder
@@ -16,13 +17,14 @@
         .addChoices([["Yes", "yes"], ["No", "no"]])
     )
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
+    const { renderUser } = client.logger
     // TODO:[Modals] Replace this with a modal
     let confirmation = await new confirmationMessage(interaction)
         .setEmoji("PUNISH.NICKNAME.RED")
         .setTitle("Nickname")
         .setDescription(keyValueList({
-            "user": `<@!${(interaction.options.getMember("user") as GuildMember).id}> (${(interaction.options.getMember("user") as GuildMember).user.username})`,
+            "user": renderUser(interaction.options.getUser("user")),
             "new nickname": `${interaction.options.getString("name") ? interaction.options.getString("name") : "*No nickname*"}`
         })
         + `The user **will${interaction.options.getString("notify") == "yes" ? '' : ' not'}** be notified\n\n`
@@ -39,7 +41,7 @@
         try {
             if (interaction.options.getString("notify") == "yes") {
                 dm = await (interaction.options.getMember("user") as GuildMember).send({
-                    embeds: [new generateEmojiEmbed()
+                    embeds: [new EmojiEmbed()
                         .setEmoji("PUNISH.NICKNAME.RED")
                         .setTitle("Nickname changed")
                         .setDescription(`Your nickname was ${interaction.options.getString("name") ? "changed" : "cleared"} in ${interaction.guild.name}.` +
@@ -56,6 +58,9 @@
             let before = member.nickname
             let nickname = interaction.options.getString("name")
             member.setNickname(nickname ?? null, "Nucleus Nickname command")
+            try { await client.database.history.create(
+                "nickname", interaction.guild.id, member.user, interaction.user,
+                null, before, nickname) } catch {}
             // @ts-ignore
             const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = client.logger
             let data = {
@@ -78,9 +83,9 @@
                     guild: interaction.guild.id
                 }
             }
-            log(data, client);
+            log(data);
         } catch {
-            await interaction.editReply({embeds: [new generateEmojiEmbed()
+            await interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji("PUNISH.NICKNAME.RED")
                 .setTitle(`Nickname`)
                 .setDescription("Something went wrong and the users nickname could not be changed.")
@@ -90,14 +95,14 @@
             return
         }
         let failed = (dmd == false && interaction.options.getString("notify") == "yes")
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji(`PUNISH.NICKNAME.${failed ? "YELLOW" : "GREEN"}`)
             .setTitle(`Nickname`)
             .setDescription("The members nickname was changed" + (failed ? ", but was not notified" : "") + (confirmation.response ? ` and an appeal ticket was opened in <#${confirmation.response}>` : ``))
             .setStatus(failed ? "Warning" : "Success")
         ], components: []})
     } else {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji("PUNISH.NICKNAME.GREEN")
             .setTitle(`Nickname`)
             .setDescription("No changes were made")
@@ -117,11 +122,11 @@
     // Check if Nucleus can change the nickname
     if (! (mePos > applyPos)) throw "I do not have a role higher than that member"
     // Check if Nucleus has permission to change the nickname
-    if (! me.permissions.has("MANAGE_NICKNAMES")) throw "I do not have the `manage_nicknames` permission";
+    if (! me.permissions.has("MANAGE_NICKNAMES")) throw "I do not have the Manage nicknames permission";
     // Allow the owner to change anyone's nickname
     if (member.id == interaction.guild.ownerId) return true
     // Check if the user has manage_nicknames permission
-    if (! member.permissions.has("MANAGE_NICKNAMES")) throw "You do not have the `manage_nicknames` permission";
+    if (! member.permissions.has("MANAGE_NICKNAMES")) throw "You do not have the Manage nicknames permission";
     // Allow changing your own nickname
     if (member == apply) return true
     // Check if the user is below on the role list
diff --git a/src/commands/mod/purge.ts b/src/commands/mod/purge.ts
index c6a44b3..9aab260 100644
--- a/src/commands/mod/purge.ts
+++ b/src/commands/mod/purge.ts
@@ -2,9 +2,10 @@
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
 import confirmationMessage from "../../utils/confirmationMessage.js";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
 import getEmojiByName from "../../utils/getEmojiByName.js";
+import client from "../../utils/client.js";
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
     builder
@@ -25,7 +26,7 @@
     if (!(["GUILD_TEXT", "GUILD_NEWS", "GUILD_NEWS_THREAD", "GUILD_PUBLIC_THREAD", "GUILD_PRIVATE_THREAD"].includes(channel.type.toString()))) {
         return await interaction.reply({
             embeds: [
-                new generateEmojiEmbed()
+                new EmojiEmbed()
                     .setEmoji("CHANNEL.PURGE.RED")
                     .setTitle("Purge")
                     .setDescription("You cannot purge this channel")
@@ -39,7 +40,7 @@
     if ( !interaction.options.getInteger("amount") ) {
         await interaction.reply({
             embeds: [
-                new generateEmojiEmbed()
+                new EmojiEmbed()
                     .setEmoji("CHANNEL.PURGE.RED")
                     .setTitle("Purge")
                     .setDescription("Select how many messages to delete")
@@ -53,7 +54,7 @@
         while (true) {
             let m = await interaction.editReply({
                 embeds: [
-                    new generateEmojiEmbed()
+                    new EmojiEmbed()
                         .setEmoji("CHANNEL.PURGE.RED")
                         .setTitle("Purge")
                         .setDescription("Select how many messages to delete. You can continue clicking until all messages are cleared.")
@@ -118,7 +119,7 @@
         }
         if (deleted.length === 0) return await interaction.editReply({
             embeds: [
-                new generateEmojiEmbed()
+                new EmojiEmbed()
                     .setEmoji("CHANNEL.PURGE.RED")
                     .setTitle("Purge")
                     .setDescription("No messages were deleted")
@@ -126,10 +127,13 @@
             ],
             components: []
         })
+        if (user) {
+            try { await client.database.history.create("purge", interaction.guild.id, user, interaction.options.getString("reason"), null, null, deleted.length) } catch {}
+        }
         let attachmentObject;
         try {
             // @ts-ignore
-            const { log, NucleusColors, entry, renderUser, renderChannel } = interaction.user.client.logger
+            const { log, NucleusColors, entry, renderUser, renderChannel } = client.logger
             let data = {
                 meta: {
                     type: 'channelPurge',
@@ -149,7 +153,7 @@
                     guild: interaction.guild.id
                 }
             }
-            log(data, interaction.user.client);
+            log(data);
             let out = ""
             deleted.reverse().forEach(message => {
                 out += `${message.author.username}#${message.author.discriminator} (${message.author.id}) [${new Date(message.createdTimestamp).toISOString()}]\n`
@@ -163,7 +167,7 @@
                 description: "Purge log"
             }
         } catch {}
-        let m = await interaction.editReply({embeds: [new generateEmojiEmbed()
+        let m = await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji(`CHANNEL.PURGE.GREEN`)
             .setTitle(`Purge`)
             .setDescription("Messages cleared")
@@ -180,14 +184,14 @@
             component = await (m as Discord.Message).awaitMessageComponent({filter: (m) => m.user.id === interaction.user.id, time: 300000});
         } catch {}
         if (component && component.customId === "download") {
-            interaction.editReply({embeds: [new generateEmojiEmbed()
+            interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji("CHANNEL.PURGE.GREEN")
                 .setTitle(`Purge`)
                 .setDescription("Uploaded")
                 .setStatus("Success")
             ], components: [], files: [attachmentObject]})
         } else {
-            interaction.editReply({embeds: [new generateEmojiEmbed()
+            interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji("CHANNEL.PURGE.GREEN")
                 .setTitle(`Purge`)
                 .setDescription("Messages cleared")
@@ -218,17 +222,20 @@
                     messages = await (channel as TextChannel).bulkDelete(toDelete, true);
                 }
             } catch(e) {
-                await interaction.editReply({embeds: [new generateEmojiEmbed()
+                await interaction.editReply({embeds: [new EmojiEmbed()
                     .setEmoji("CHANNEL.PURGE.RED")
                     .setTitle(`Purge`)
                     .setDescription("Something went wrong and no messages were deleted")
                     .setStatus("Danger")
                 ], components: []})
             }
+            if (user) {
+                try { await client.database.history.create("purge", interaction.guild.id, user, interaction.options.getString("reason"), null, null, messages.size) } catch {}
+            }
             let attachmentObject;
             try {
                 // @ts-ignore
-                const { log, NucleusColors, entry, renderUser, renderChannel } = interaction.user.client.logger
+                const { log, NucleusColors, entry, renderUser, renderChannel } = client.logger
                 let data = {
                     meta: {
                         type: 'channelPurge',
@@ -248,7 +255,7 @@
                         guild: interaction.guild.id
                     }
                 }
-                log(data, interaction.user.client);
+                log(data);
                 let out = ""
                 messages.reverse().forEach(message => {
                     out += `${message.author.username}#${message.author.discriminator} (${message.author.id}) [${new Date(message.createdTimestamp).toISOString()}]\n`
@@ -262,7 +269,7 @@
                     description: `Purge log`
                 }
             } catch {}
-            let m = await interaction.editReply({embeds: [new generateEmojiEmbed()
+            let m = await interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji(`CHANNEL.PURGE.GREEN`)
                 .setTitle(`Purge`)
                 .setDescription("Messages cleared")
@@ -279,14 +286,14 @@
                 component = await (m as Discord.Message).awaitMessageComponent({filter: (m) => m.user.id === interaction.user.id, time: 300000});
             } catch {}
             if (component && component.customId === "download") {
-                interaction.editReply({embeds: [new generateEmojiEmbed()
+                interaction.editReply({embeds: [new EmojiEmbed()
                     .setEmoji("CHANNEL.PURGE.GREEN")
                     .setTitle(`Purge`)
                     .setDescription("Transcript uploaded above")
                     .setStatus("Success")
                 ], components: [], files: [attachmentObject]})
             } else {
-                interaction.editReply({embeds: [new generateEmojiEmbed()
+                interaction.editReply({embeds: [new EmojiEmbed()
                     .setEmoji("CHANNEL.PURGE.GREEN")
                     .setTitle(`Purge`)
                     .setDescription("Messages cleared")
@@ -294,7 +301,7 @@
                 ], components: []})
             }
         } else {
-            await interaction.editReply({embeds: [new generateEmojiEmbed()
+            await interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji("CHANNEL.PURGE.GREEN")
                 .setTitle(`Purge`)
                 .setDescription("No changes were made")
@@ -310,9 +317,9 @@
     // Allow the owner to purge
     if (member.id == interaction.guild.ownerId) return true
     // Check if the user has manage_messages permission
-    if (! member.permissions.has("MANAGE_MESSAGES")) throw "You do not have the `manage_messages` permission";
+    if (! member.permissions.has("MANAGE_MESSAGES")) throw "You do not have the Manage messages permission";
     // Check if nucleus has the manage_messages permission
-    if (! me.permissions.has("MANAGE_MESSAGES")) throw "I do not have the `manage_messages` permission";
+    if (! me.permissions.has("MANAGE_MESSAGES")) throw "I do not have the Manage messages permission";
     // Allow warn
     return true
 }
diff --git a/src/commands/mod/slowmode.ts b/src/commands/mod/slowmode.ts
index 2498746..d9a8421 100644
--- a/src/commands/mod/slowmode.ts
+++ b/src/commands/mod/slowmode.ts
@@ -4,7 +4,8 @@
 import { WrappedCheck } from "jshaiku";
 import keyValueList from "../../utils/generateKeyValueList.js";
 import confirmationMessage from "../../utils/confirmationMessage.js";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
+
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
     builder
@@ -18,11 +19,11 @@
         ["1 hour", "3600"], ["2 hours", "7200"], ["6 hours", "21600"]
     ]))
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
     let time = parseInt(interaction.options.getString("time") ?? "0");
     if (time === 0 && (interaction.channel as TextChannel).rateLimitPerUser === 0) { time = 10 }
     let confirmation = await new confirmationMessage(interaction)
-        .setEmoji("CHANNEL.SLOWMODE.RED")
+        .setEmoji("CHANNEL.SLOWMODE.OFF")
         .setTitle("Slowmode")
         .setDescription(keyValueList({
             "time": time ? humanizeDuration(time * 1000, { round: true }) : "No delay",
@@ -34,22 +35,22 @@
         try {
             (interaction.channel as TextChannel).setRateLimitPerUser(time)
         } catch (e) {
-            await interaction.editReply({embeds: [new generateEmojiEmbed()
-                .setEmoji("CHANNEL.SLOWMODE.RED")
+            await interaction.editReply({embeds: [new EmojiEmbed()
+                .setEmoji("CHANNEL.SLOWMODE.OFF")
                 .setTitle(`Slowmode`)
                 .setDescription("Something went wrong while setting the slowmode")
                 .setStatus("Danger")
             ], components: []})
         }
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
-            .setEmoji(`CHANNEL.SLOWMODE.GREEN`)
+        await interaction.editReply({embeds: [new EmojiEmbed()
+            .setEmoji(`CHANNEL.SLOWMODE.ON`)
             .setTitle(`Slowmode`)
             .setDescription("The channel slowmode was set successfully")
             .setStatus("Success")
         ], components: []})
     } else {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
-            .setEmoji("CHANNEL.SLOWMODE.GREEN")
+        await interaction.editReply({embeds: [new EmojiEmbed()
+            .setEmoji("CHANNEL.SLOWMODE.ON")
             .setTitle(`Slowmode`)
             .setDescription("No changes were made")
             .setStatus("Success")
@@ -60,9 +61,9 @@
 const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
     let member = (interaction.member as GuildMember)
     // Check if Nucleus can set the slowmode
-    if (! interaction.guild.me.permissions.has("MANAGE_CHANNELS")) throw "I do not have the `manage_channels` permission";
+    if (! interaction.guild.me.permissions.has("MANAGE_CHANNELS")) throw "I do not have the Manage channels permission";
     // Check if the user has manage_channel permission
-    if (! member.permissions.has("MANAGE_CHANNELS")) throw "You do not have the `manage_channels` permission";
+    if (! member.permissions.has("MANAGE_CHANNELS")) throw "You do not have the Manage channels permission";
     // Allow slowmode
     return true
 }
diff --git a/src/commands/mod/softban.ts b/src/commands/mod/softban.ts
index 5a01287..ea4a447 100644
--- a/src/commands/mod/softban.ts
+++ b/src/commands/mod/softban.ts
@@ -2,7 +2,7 @@
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
 import confirmationMessage from "../../utils/confirmationMessage.js";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
 import client from "../../utils/client.js";
 import addPlural from "../../utils/plurals.js";
@@ -18,13 +18,14 @@
     )
     .addIntegerOption(option => option.setName("delete").setDescription("The days of messages to delete | Default 0").setMinValue(0).setMaxValue(7).setRequired(false))
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
+    const { renderUser } = client.logger
     // TODO:[Modals] Replace this with a modal
     let confirmation = await new confirmationMessage(interaction)
         .setEmoji("PUNISH.BAN.RED")
         .setTitle("Softban")
         .setDescription(keyValueList({
-            "user": `<@!${(interaction.options.getMember("user") as GuildMember).id}> (${(interaction.options.getMember("user") as GuildMember).user.username})`,
+            "user": renderUser(interaction.options.getUser("user")),
             "reason": `\n> ${interaction.options.getString("reason") ? interaction.options.getString("reason") : "*No reason provided*"}`
         })
         + `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n`
@@ -34,11 +35,11 @@
     .send()
     if (confirmation.success) {
         let dmd = false;
-        let config = await client.database.read(interaction.guild.id);
+        let config = await client.database.guilds.read(interaction.guild.id);
         try {
             if (interaction.options.getString("notify") != "no") {
                 await (interaction.options.getMember("user") as GuildMember).send({
-                    embeds: [new generateEmojiEmbed()
+                    embeds: [new EmojiEmbed()
                         .setEmoji("PUNISH.BAN.RED")
                         .setTitle("Softbanned")
                         .setDescription(`You have been softbanned from ${interaction.guild.name}` +
@@ -54,29 +55,31 @@
                 dmd = true
             }
         } catch {}
+        let member = (interaction.options.getMember("user") as GuildMember)
         try {
-            await (interaction.options.getMember("user") as GuildMember).ban({
+            await member.ban({
                 days: Number(interaction.options.getInteger("delete") ?? 0),
                 reason: interaction.options.getString("reason")
             });
-            await interaction.guild.members.unban(interaction.options.getMember("user") as GuildMember, "Softban");
+            await interaction.guild.members.unban(member, "Softban");
         } catch {
-            await interaction.editReply({embeds: [new generateEmojiEmbed()
+            await interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji("PUNISH.BAN.RED")
                 .setTitle(`Softban`)
                 .setDescription("Something went wrong and the user was not softbanned")
                 .setStatus("Danger")
             ], components: []})
         }
+        try { await client.database.history.create("softban", interaction.guild.id, member.user, interaction.options.getString("reason")) } catch {}
         let failed = (dmd == false && interaction.options.getString("notify") != "no")
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji(`PUNISH.BAN.${failed ? "YELLOW" : "GREEN"}`)
             .setTitle(`Softban`)
             .setDescription("The member was softbanned" + (failed ? ", but could not be notified" : ""))
             .setStatus(failed ? "Warning" : "Success")
         ], components: []})
     } else {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji("PUNISH.BAN.GREEN")
             .setTitle(`Softban`)
             .setDescription("No changes were made")
@@ -96,13 +99,13 @@
     // Check if Nucleus can ban the member
     if (! (mePos > applyPos)) throw "I do not have a role higher than that member"
     // Check if Nucleus has permission to ban
-    if (!me.permissions.has("BAN_MEMBERS")) throw "I do not have the `ban_members` permission";
+    if (!me.permissions.has("BAN_MEMBERS")) throw "I do not have the Ban members permission";
     // Do not allow softbanning Nucleus
     if (member.id == me.id) throw "I cannot softban myself"
     // Allow the owner to ban anyone
     if (member.id == interaction.guild.ownerId) return true
     // Check if the user has ban_members permission
-    if (! member.permissions.has("BAN_MEMBERS")) throw "You do not have the `ban_members` permission";
+    if (! member.permissions.has("BAN_MEMBERS")) throw "You do not have the Ban members permission";
     // Check if the user is below on the role list
     if (! (memberPos > applyPos)) throw "You do not have a role higher than that member"
     // Allow softban
diff --git a/src/commands/mod/unban.ts b/src/commands/mod/unban.ts
index f7bf74f..7f605d9 100644
--- a/src/commands/mod/unban.ts
+++ b/src/commands/mod/unban.ts
@@ -1,9 +1,10 @@
 import { CommandInteraction, GuildMember, User } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
 import confirmationMessage from "../../utils/confirmationMessage.js";
+import client from "../../utils/client.js";
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
     builder
@@ -11,14 +12,14 @@
     .setDescription("Unbans a user")
     .addStringOption(option => option.setName("user").setDescription("The user to unban (Username or ID)").setRequired(true))
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
     let bans = await interaction.guild.bans.fetch()
     let user = interaction.options.getString("user")
     let resolved = bans.find(ban => ban.user.id == user)
     if (!resolved) resolved = bans.find(ban => ban.user.username.toLowerCase() == user.toLowerCase())
     if (!resolved) resolved = bans.find(ban => ban.user.tag.toLowerCase() == user.toLowerCase())
     if (!resolved) {
-        return interaction.reply({embeds: [new generateEmojiEmbed()
+        return interaction.reply({embeds: [new EmojiEmbed()
             .setTitle("Unban")
             .setDescription(`Could not find any user called \`${user}\``)
             .setEmoji("PUNISH.UNBAN.RED")
@@ -39,8 +40,9 @@
         try {
             await interaction.guild.members.unban(resolved.user as User, "Unban");
             let member = (resolved.user as User)
+            try { await client.database.history.create("unban", interaction.guild.id, member, interaction.user) } catch {}
             // @ts-ignore
-            const { log, NucleusColors, entry, renderUser, renderDelta } = interaction.user.client.logger
+            const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger
             let data = {
                 meta: {
                     type: 'memberUnban',
@@ -61,23 +63,23 @@
                     guild: interaction.guild.id
                 }
             }
-            log(data, member.client);
+            log(data);
         } catch {
-            await interaction.editReply({embeds: [new generateEmojiEmbed()
+            await interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji("PUNISH.UNBAN.RED")
                 .setTitle(`Unban`)
                 .setDescription("Something went wrong and the user was not unbanned")
                 .setStatus("Danger")
             ], components: []})
         }
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji(`PUNISH.UNBAN.GREEN`)
             .setTitle(`Unban`)
             .setDescription("The member was unbanned")
             .setStatus("Success")
         ], components: []})
     } else {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji("PUNISH.UNBAN.GREEN")
             .setTitle(`Unban`)
             .setDescription("No changes were made")
@@ -90,11 +92,11 @@
     let member = (interaction.member as GuildMember)
     let me = (interaction.guild.me as GuildMember)
     // Check if Nucleus can unban members
-    if (! me.permissions.has("BAN_MEMBERS")) throw "I do not have the `ban_members` permission";
+    if (! me.permissions.has("BAN_MEMBERS")) throw "I do not have the Ban members permission";
     // Allow the owner to unban anyone
     if (member.id == interaction.guild.ownerId) return true
     // Check if the user has ban_members permission
-    if (! member.permissions.has("BAN_MEMBERS")) throw "You do not have the `ban_members` permission";
+    if (! member.permissions.has("BAN_MEMBERS")) throw "You do not have the Ban members permission";
     // Allow unban
     return true
 }
diff --git a/src/commands/mod/unmute.ts b/src/commands/mod/unmute.ts
index 2a98c54..5a1b67c 100644
--- a/src/commands/mod/unmute.ts
+++ b/src/commands/mod/unmute.ts
@@ -2,8 +2,9 @@
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
 import confirmationMessage from "../../utils/confirmationMessage.js";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
+import client from "../../utils/client.js";
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
     builder
@@ -15,13 +16,14 @@
         .addChoices([["Yes", "yes"], ["No", "no"]])
     )
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
+    const { renderUser } = client.logger
     // TODO:[Modals] Replace this with a modal
     let confirmation =  await new confirmationMessage(interaction)
         .setEmoji("PUNISH.MUTE.RED")
         .setTitle("Unmute")
         .setDescription(keyValueList({
-            "user": `<@!${(interaction.options.getMember("user") as GuildMember).id}> (${(interaction.options.getMember("user") as GuildMember).user.username})`,
+            "user": renderUser(interaction.options.getUser("user")),
             "reason": `\n> ${interaction.options.getString("reason") ? interaction.options.getString("reason") : "*No reason provided*"}`
         })
         + `The user **will${interaction.options.getString("notify") === "yes" ? '' : ' not'}** be notified\n\n`
@@ -34,7 +36,7 @@
         try {
             if (interaction.options.getString("notify") != "no") {
                 dm = await (interaction.options.getMember("user") as GuildMember).send({
-                    embeds: [new generateEmojiEmbed()
+                    embeds: [new EmojiEmbed()
                         .setEmoji("PUNISH.MUTE.GREEN")
                         .setTitle("Unmuted")
                         .setDescription(`You have been unmuted in ${interaction.guild.name}` +
@@ -48,7 +50,7 @@
         try {
             (interaction.options.getMember("user") as GuildMember).timeout(0, interaction.options.getString("reason") || "No reason provided")
         } catch {
-            await interaction.editReply({embeds: [new generateEmojiEmbed()
+            await interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji("PUNISH.MUTE.RED")
                 .setTitle(`Unmute`)
                 .setDescription("Something went wrong and the user was not unmuted")
@@ -57,15 +59,16 @@
             if (dmd) await dm.delete()
             return
         }
+        try { await client.database.history.create("unmute", interaction.guild.id, (interaction.options.getMember("user") as GuildMember).user, interaction.user, interaction.options.getString("reason")) } catch {}
         let failed = (dmd == false && interaction.options.getString("notify") != "no")
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji(`PUNISH.MUTE.${failed ? "YELLOW" : "GREEN"}`)
             .setTitle(`Unmute`)
             .setDescription("The member was unmuted" + (failed ? ", but could not be notified" : ""))
             .setStatus(failed ? "Warning" : "Success")
         ], components: []})
     } else {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji("PUNISH.MUTE.GREEN")
             .setTitle(`Unmute`)
             .setDescription("No changes were made")
@@ -85,13 +88,13 @@
     // Check if Nucleus can unmute the member
     if (! (mePos > applyPos)) throw "I do not have a role higher than that member"
     // Check if Nucleus has permission to unmute
-    if (! me.permissions.has("MODERATE_MEMBERS")) throw "I do not have the `moderate_members` permission";
+    if (! me.permissions.has("MODERATE_MEMBERS")) throw "I do not have the Moderate members permission";
     // Do not allow the user to have admin or be the owner
     if (apply.permissions.has("ADMINISTRATOR") || apply.id == interaction.guild.ownerId) throw "You cannot unmute an admin or the owner"
     // Allow the owner to unmute anyone
     if (member.id == interaction.guild.ownerId) return true
     // Check if the user has moderate_members permission
-    if (! member.permissions.has("MODERATE_MEMBERS")) throw "You do not have the `moderate_members` permission";
+    if (! member.permissions.has("MODERATE_MEMBERS")) throw "You do not have the Moderate members permission";
     // Check if the user is below on the role list
     if (! (memberPos > applyPos)) throw "You do not have a role higher than that member"
     // Allow unmute
diff --git a/src/commands/mod/viewas.ts b/src/commands/mod/viewas.ts
index 705c04a..b3875a7 100644
--- a/src/commands/mod/viewas.ts
+++ b/src/commands/mod/viewas.ts
@@ -1,8 +1,9 @@
-import Discord, { CategoryChannel, CommandInteraction } from "discord.js";
+import Discord, { CategoryChannel, CommandInteraction, GuildMember, MessageActionRow, MessageButton, MessageSelectMenu } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import { WrappedCheck } from "jshaiku";
 import getEmojiByName from "../../utils/getEmojiByName.js";
+import pageIndicator from "../../utils/createPageIndicator.js";
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
     builder
@@ -10,8 +11,9 @@
     .setDescription("View the server as a specific member")
     .addUserOption(option => option.setName("member").setDescription("The member to view as").setRequired(true))
 
-const callback = async (interaction: CommandInteraction) => {
-    let channels = []
+const callback = async (interaction: CommandInteraction): Promise<any> => {
+    let channels = [];
+    let m;
     interaction.guild.channels.cache.forEach(channel => {
         if (!channel.parent && channel.type !== "GUILD_CATEGORY") channels.push(channel)
     })
@@ -22,39 +24,83 @@
     )
     let autoSortBelow = ["GUILD_VOICE", "GUILD_STAGE_VOICE"]
     channels = channels.map(c => c.sort((a, b) => {
-        if (autoSortBelow.includes(a.type) && autoSortBelow.includes(b.type)) return a.name.localeCompare(b.name)
-        if (autoSortBelow.includes(a.type)) return -1
-        if (autoSortBelow.includes(b.type)) return 1
+        if (autoSortBelow.includes(a.type) && autoSortBelow.includes(b.type)) return a.position - b.position
+        if (autoSortBelow.includes(a.type)) return 1
+        if (autoSortBelow.includes(b.type)) return -1
         return a.position - b.position
     }))
+    // Sort all arrays by the position of the first channels parent position
+    channels = channels.sort((a, b) => {
+        if (!a[0].parent) return -1
+        if (!b[0].parent) return 1
+        return a[0].parent.position - b[0].parent.position
+    })
     let member = interaction.options.getMember("member") as Discord.GuildMember
-    await interaction.reply({embeds: [new generateEmojiEmbed()
+    m = await interaction.reply({embeds: [new EmojiEmbed()
         .setEmoji("MEMBER.JOIN")
         .setTitle("Viewing as " + member.displayName)
         .setStatus("Success")
-    ], ephemeral: true})
+    ], ephemeral: true, fetchReply: true})
     let page = 0;
     while (true) {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        m = await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji("MEMBER.JOIN")
             .setTitle("Viewing as " + member.displayName)
             .setStatus("Success")
             .setDescription(
-                `${channels[page][0].parent ? channels[page][0].parent.name  : "Uncategorised"}` +
-                "Visible:\n" +
+                `**${channels[page][0].parent ? channels[page][0].parent.name  : "Uncategorised"}**` + "\n" +
                 channels[page].map(c => {
-                    console.log(c)
-                    return (channels[page] as Discord.GuildChannel).permissionsFor(member).has("VIEW_CHANNEL") ?
-                        `${getEmojiByName("ICONS.CHANNEL." + c.type)} ${c.name}\n` : ""
-                }).join("")
+                    let channelType = c.type
+                    if (interaction.guild.rulesChannelId == c.id) channelType = "RULES"
+                    else if ("nsfw" in c && c.nsfw) channelType += "_NSFW"
+                    return c.permissionsFor(member).has("VIEW_CHANNEL") ? (
+                        `${getEmojiByName("ICONS.CHANNEL." + channelType)} ${c.name}\n` + (() => {
+                            if ("threads" in c && c.threads.cache.size > 0) {
+                                return c.threads.cache.map(t => ` ${
+                                    getEmojiByName("ICONS.CHANNEL.THREAD_PIPE") + " " +
+                                    getEmojiByName("ICONS.CHANNEL.THREAD_CHANNEL")} ${t.name}`).join("\n") + "\n"
+                            }return ""
+                        })()) : ""
+                }).join("") + "\n" + pageIndicator(channels.length, page)
             )
+        ], components: [
+            new MessageActionRow().addComponents([new MessageSelectMenu().setOptions(channels.map((c, index) => ({
+                label: c[0].parent ? c[0].parent.name : "Uncategorised",
+                value: index.toString(),
+                default: page === index
+            }))).setCustomId("select").setMaxValues(1).setMinValues(1).setPlaceholder("Select a category")]),
+            new MessageActionRow().addComponents([
+                new MessageButton()
+                    .setLabel(page === 0 ? "" : (channels[page - 1][0].parent ? channels[page - 1][0].parent.name : "Uncategorised"))
+                    .setDisabled(page === 0)
+                    .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
+                    .setStyle("PRIMARY")
+                    .setCustomId("previous"),
+                new MessageButton()
+                    .setLabel(page === channels.length - 1 ? "" : (channels[page + 1][0].parent ? channels[page + 1][0].parent.name : "Uncategorised"))
+                    .setDisabled(page === channels.length - 1)
+                    .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
+                    .setStyle("PRIMARY")
+                    .setCustomId("next")
+            ])
         ]})
-        break
+        let i;
+        try {
+            i = await m.awaitMessageComponent({ time: 300000 });
+        } catch (e) { return }
+        i.deferUpdate()
+        if (i.customId === "next") { page++; }
+        else if (i.customId === "previous") { page--; }
+        else if (i.customId === "select") { page = parseInt(i.values[0]); }
     }
 }
 
+
 const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
-    return true;
+    return true // FIXME FOR RELEASE
+    let member = (interaction.member as GuildMember)
+    if (! member.permissions.has("MANAGE_ROLES")) throw "You do not have the Manage roles permission";
+    return true
 }
 
 export { command, callback, check };
\ No newline at end of file
diff --git a/src/commands/mod/warn.ts b/src/commands/mod/warn.ts
index b8fb98f..370f347 100644
--- a/src/commands/mod/warn.ts
+++ b/src/commands/mod/warn.ts
@@ -2,9 +2,10 @@
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
 import confirmationMessage from "../../utils/confirmationMessage.js";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
 import { create, areTicketsEnabled } from "../../automations/createModActionTicket.js";
+import client from "../../utils/client.js"
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
     builder
@@ -23,7 +24,7 @@
         .setEmoji("PUNISH.WARN.RED")
         .setTitle("Warn")
         .setDescription(keyValueList({
-            "user": `<@!${(interaction.options.getMember("user") as GuildMember).id}> (${(interaction.options.getMember("user") as GuildMember).user.username})`,
+            "user": renderUser(interaction.options.getUser("user")),
             "reason": `\n> ${interaction.options.getString("reason") ? interaction.options.getString("reason") : "*No reason provided*"}`
         })
         + `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n\n`
@@ -39,7 +40,7 @@
         try {
             if (interaction.options.getString("notify") != "no") {
                 await (interaction.options.getMember("user") as GuildMember).send({
-                    embeds: [new generateEmojiEmbed()
+                    embeds: [new EmojiEmbed()
                         .setEmoji("PUNISH.WARN.RED")
                         .setTitle("Warned")
                         .setDescription(`You have been warned in ${interaction.guild.name}` +
@@ -51,7 +52,7 @@
                 dmd = true
             }
         } catch {
-            await interaction.editReply({embeds: [new generateEmojiEmbed()
+            await interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji("PUNISH.WARN.RED")
                 .setTitle(`Warn`)
                 .setDescription("Something went wrong and the user was not warned")
@@ -76,10 +77,15 @@
                 guild: interaction.guild.id
             }
         }
-        log(data, client);
+        try { await client.database.history.create(
+            "warn", interaction.guild.id,
+            (interaction.options.getMember("user") as GuildMember).user,
+            interaction.user, interaction.options.getString("reason")
+        )} catch {}
+        log(data);
         let failed = (dmd == false && interaction.options.getString("notify") != "no")
         if (!failed) {
-            await interaction.editReply({embeds: [new generateEmojiEmbed()
+            await interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji(`PUNISH.WARN.GREEN`)
                 .setTitle(`Warn`)
                 .setDescription("The user was warned" + (confirmation.response ? ` and an appeal ticket was opened in <#${confirmation.response}>` : ``))
@@ -87,7 +93,7 @@
             ], components: []})
         } else {
             let m = await interaction.editReply({
-                embeds: [new generateEmojiEmbed()
+                embeds: [new EmojiEmbed()
                     .setEmoji(`PUNISH.WARN.RED`)
                     .setTitle(`Warn`)
                     .setDescription("The user's DMs are not open\n\nWhat would you like to do?")
@@ -110,7 +116,7 @@
             try {
                 component = await (m as Discord.Message).awaitMessageComponent({filter: (m) => m.user.id === interaction.user.id, time: 300000});
             } catch (e) {
-                return await interaction.editReply({embeds: [new generateEmojiEmbed()
+                return await interaction.editReply({embeds: [new EmojiEmbed()
                     .setEmoji(`PUNISH.WARN.GREEN`)
                     .setTitle(`Warn`)
                     .setDescription("No changes were made")
@@ -119,7 +125,7 @@
             }
             if ( component.customId == "here" ) {
                 await interaction.channel.send({
-                    embeds: [new generateEmojiEmbed()
+                    embeds: [new EmojiEmbed()
                         .setEmoji(`PUNISH.WARN.RED`)
                         .setTitle(`Warn`)
                         .setDescription(`You have been warned` +
@@ -129,14 +135,14 @@
                     content: `<@!${(interaction.options.getMember("user") as GuildMember).id}>`,
                     allowedMentions: {users: [(interaction.options.getMember("user") as GuildMember).id]}
                 })
-                return await interaction.editReply({embeds: [new generateEmojiEmbed()
+                return await interaction.editReply({embeds: [new EmojiEmbed()
                     .setEmoji(`PUNISH.WARN.GREEN`)
                     .setTitle(`Warn`)
                     .setDescription("The user was warned" + (confirmation.response ? ` and an appeal ticket was opened in <#${confirmation.response}>` : ``))
                     .setStatus("Success")
                 ], components: []})
             } else {
-                await interaction.editReply({embeds: [new generateEmojiEmbed()
+                await interaction.editReply({embeds: [new EmojiEmbed()
                     .setEmoji(`PUNISH.WARN.GREEN`)
                     .setTitle(`Warn`)
                     .setDescription("The warn was logged")
@@ -145,7 +151,7 @@
             }
         }
     } else {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji("PUNISH.WARN.GREEN")
             .setTitle(`Warn`)
             .setDescription("No changes were made")
@@ -167,7 +173,7 @@
     // Allow the owner to warn anyone
     if (member.id == interaction.guild.ownerId) return true
     // Check if the user has moderate_members permission
-    if (! member.permissions.has("MODERATE_MEMBERS")) throw "You do not have the `moderate_members` permission";
+    if (! member.permissions.has("MODERATE_MEMBERS")) throw "You do not have the Moderate members permission";
     // Check if the user is below on the role list
     if (! (memberPos > applyPos)) throw "You do not have a role higher than that member"
     // Allow warn
diff --git a/src/commands/nucleus/guide.ts b/src/commands/nucleus/guide.ts
index 814d2f5..eb94de4 100644
--- a/src/commands/nucleus/guide.ts
+++ b/src/commands/nucleus/guide.ts
@@ -2,7 +2,7 @@
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
 import getEmojiByName from "../../utils/getEmojiByName.js";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import guide from "../../automations/guide.js";
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
diff --git a/src/commands/nucleus/invite.ts b/src/commands/nucleus/invite.ts
index 8b25820..7f7d4b8 100644
--- a/src/commands/nucleus/invite.ts
+++ b/src/commands/nucleus/invite.ts
@@ -1,7 +1,7 @@
 import { CommandInteraction, MessageActionRow, MessageButton } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import client from "../../utils/client.js"
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
@@ -10,7 +10,7 @@
     .setDescription("Invites Nucleus to your server")
 
 const callback = (interaction: CommandInteraction) => {
-    interaction.reply({embeds: [new generateEmojiEmbed()
+    interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Invite")
         .setDescription("You can invite Nucleus to your server by clicking the button below")
         .setEmoji("NUCLEUS.LOGO")
diff --git a/src/commands/nucleus/ping.ts b/src/commands/nucleus/ping.ts
index 58413c6..f10dcae 100644
--- a/src/commands/nucleus/ping.ts
+++ b/src/commands/nucleus/ping.ts
@@ -1,6 +1,6 @@
 import { CommandInteraction } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import { WrappedCheck } from "jshaiku";
 import client from "../../utils/client.js"
 
@@ -9,18 +9,18 @@
     .setName("ping")
     .setDescription("Gets the bot's ping time")
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
     // WEBSOCKET | Nucleus -> Discord
     // EDITING   | Nucleus -> discord -> nucleus | edit time / 2
     let initial = new Date().getTime();
-    await interaction.reply({embeds: [new generateEmojiEmbed()
+    await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Ping")
         .setDescription(`Checking ping times...`)
         .setEmoji("NUCLEUS.LOADING")
         .setStatus("Danger")
     ], ephemeral: true});
     let ping = new Date().getTime() - initial;
-    interaction.editReply({embeds: [new generateEmojiEmbed()
+    interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Ping")
         .setDescription(
             `**Ping:** \`${ping}ms\`\n` +
diff --git a/src/commands/nucleus/stats.ts b/src/commands/nucleus/stats.ts
index 1a0602e..cb10e7a 100644
--- a/src/commands/nucleus/stats.ts
+++ b/src/commands/nucleus/stats.ts
@@ -1,7 +1,7 @@
 import { CommandInteraction } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import client from "../../utils/client.js"
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
@@ -11,7 +11,7 @@
 
 const callback = (interaction: CommandInteraction) => {
     interaction.reply({
-        embeds: [new generateEmojiEmbed()
+        embeds: [new EmojiEmbed()
             .setTitle("Stats")
             .setDescription(
                 `**Servers:** ${client.guilds.cache.size}\n` +
diff --git a/src/commands/nucleus/suggest.ts b/src/commands/nucleus/suggest.ts
index c07d9b8..4e3a1c8 100644
--- a/src/commands/nucleus/suggest.ts
+++ b/src/commands/nucleus/suggest.ts
@@ -2,7 +2,7 @@
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
 import confirmationMessage from "../../utils/confirmationMessage.js";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import client from "../../utils/client.js"
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
@@ -11,7 +11,7 @@
     .setDescription("Sends a suggestion to the developers")
     .addStringOption(option => option.setName("suggestion").setDescription("The suggestion to send").setRequired(true))
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
     // @ts-ignore
     const { renderUser } = client.logger
     let suggestion = interaction.options.getString("suggestion");
@@ -26,21 +26,21 @@
     if (confirmation.success) {
         await (client.channels.cache.get('955161206459600976') as Discord.TextChannel).send({
             embeds: [
-                new generateEmojiEmbed()
+                new EmojiEmbed()
                     .setTitle(`Suggestion`)
                     .setDescription(`**From:** ${renderUser(interaction.member.user)}\n**Suggestion:**\n> ${suggestion}`)
                     .setStatus("Danger")
                     .setEmoji("NUCLEUS.LOGO")
             ]
         })
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji("ICONS.ADD")
             .setTitle(`Suggest`)
             .setDescription("Your suggestion was sent successfully")
             .setStatus("Success")
         ], components: []})
     } else {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji("ICONS.OPP.ADD")
             .setTitle(`Suggest`)
             .setDescription("No changes were made")
diff --git a/src/commands/privacy.ts b/src/commands/privacy.ts
index 3174421..cc6c554 100644
--- a/src/commands/privacy.ts
+++ b/src/commands/privacy.ts
@@ -8,7 +8,7 @@
     .setDescription("we changed the fucking charger again!")
     .addStringOption(option => option.setName("link").setDescription("fuck you").setRequired(false))
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
     console.log(await testLink(interaction.options.getString("link")))
 }
 
diff --git a/src/commands/role/all.ts b/src/commands/role/all.ts
index 44e77fd..d24110b 100644
--- a/src/commands/role/all.ts
+++ b/src/commands/role/all.ts
@@ -1,17 +1,161 @@
-import { CommandInteraction } from "discord.js";
+import Discord, { CommandInteraction, GuildMember, MessageActionRow, MessageButton, MessageSelectMenu } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import getEmojiByName from "../../utils/getEmojiByName.js";
+import addPlural from "../../utils/plurals.js";
+import client from "../../utils/client.js";
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
     builder
     .setName("all")
     .setDescription("Gives or removes a role from everyone")
 
-const callback = (interaction: CommandInteraction) => {
-    interaction.reply("This command is not yet finished [role/all]");
+class Filter {
+    name: string;
+    data: object;
+    checkFunction: (member) => boolean;
+    inverted: boolean = false;
+    constructor(name: (data) => string | string, data: object, check: (member) => boolean) {
+        if (typeof name === "function") { this.name = name(data);
+        } else { this.name = name; }
+        this.data = data;
+        this.checkFunction = check;
+    }
+    flip() { this.inverted = true; return this; }
+    check(member) {
+        if (this.inverted) return !this.checkFunction(member)
+        else return this.checkFunction(member)
+    }
 }
 
-const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
+const filterList = {
+    member: {
+        render: "Member",
+        has: {
+            render: "has",
+            role: (role) => ( new Filter((data) => `Member has role <@&${data.role}>`, {role: role, type: Discord.Role, render: "role"}, (member) => { return member.roles.cache.has(role)}))
+        },
+        joined: {
+            render: "joined",
+            before: (date) => ( new Filter((data) => `Joined server before <t:${Math.round(date.getTime() / 1000)}:F>`, {date: date, type: Date, render: "before"}, (member) => {
+                return member.joinedTimestamp < date.getTime()
+            })),
+            after: (date) => ( new Filter((data) => `Joined server after <t:${Math.round(date.getTime() / 1000)}:F>`, {date: date, type: Date, render: "after"}, (member) => {
+                return member.joinedTimestamp > date.getTime()
+            }).flip())
+        },
+        nickname: {
+            render: "Nickname",
+            set: () => ( new Filter((data) => `Member has a nickname set"`, {render: "set"}, (member) => { return member.nickname !== null})),
+            include: (name) => ( new Filter((data) => `Nickname includes "${name}"`, {nickname: name, type: String, render: "includes"}, (member) => {
+                return member.displayName.includes(name)})),
+            startsWith: (name) => ( new Filter((data) => `Nickname starts with "${name}"`, {nickname: name, type: String, render: "starts with"}, (member) => {
+                return member.displayName.startsWith(name)})),
+            endsWith: (name) => ( new Filter((data) => `Nickname ends with "${name}"`, {nickname: name, type: String, render: "ends with"}, (member) => {
+                return member.displayName.endsWith(name)}))
+        }
+    },
+    account: {
+        render: "Account",
+        created: {
+            render: "created",
+            before: (date) => ( new Filter((data) => `Account created before <t:${Math.round(date.getTime() / 1000)}:D>`, {date: date, type: Date, render: "before"}, (member) => {
+                return member.user.createdTimestamp < date.getTime()
+            })),
+            after: (date) => ( new Filter((data) => `Account created after <t:${Math.round(date.getTime() / 1000)}:D>`, {date: date, type: Date, render: "after"}, (member) => {
+                return member.user.createdTimestamp < date.getTime()
+            }).flip())
+        },
+        is: {
+            render: "is",
+            human: () => ( new Filter((data) => `Member is a human`, {human: true, render: "human"}, (member) => { return !member.bot })),
+        },
+        username: {
+            render: "Username",
+            include: (name) => ( new Filter((data) => `Nickname includes "${name}"`, {nickname: name, type: String, render: "includes"}, (member) => {
+                return member.user.name.includes(name)})),
+            startsWith: (name) => ( new Filter((data) => `Nickname starts with "${name}"`, {nickname: name, type: String, render: "starts with"}, (member) => {
+                return member.user.name.startsWith(name)})),
+            endsWith: (name) => ( new Filter((data) => `Nickname ends with "${name}"`, {nickname: name, type: String, render: "ends with"}, (member) => {
+                return member.user.name.endsWith(name)}))
+        }
+    }
+}
+
+const callback = async (interaction: CommandInteraction) => {
+    await interaction.reply({embeds: [new EmojiEmbed()
+        .setTitle("Role all")
+        .setDescription("Loading...")
+        .setStatus("Danger")
+        .setEmoji("NUCLEUS.LOADING")
+    ], ephemeral: true, fetchReply: true})
+    let filters: Filter[] = [
+        filterList.member.has.role("959901346000154674"),
+        filterList.member.nickname.startsWith("Pinea"),
+        filterList.member.joined.before(new Date(2022, 1)).flip()
+    ]
+    let all = true;
+    while (true) {
+        let count = 0;
+        let affected = []
+        let members = interaction.guild.members.cache
+        if (all) {
+            members.forEach(member => {
+                let applies = true;
+                filters.forEach(filter => { if (!filter.check(member)) { applies = false } })
+                if (applies) { affected.push(member) }
+            })
+        } else {
+            members.forEach(member => {
+                let applies = false;
+                filters.forEach(filter => { if (filter.check(member)) { applies = true } })
+                if (applies) { affected.push(member) }
+            })
+        }
+        await interaction.editReply({embeds: [new EmojiEmbed()
+            .setTitle("Role all")
+            .setDescription((all ? "All of the following must be true:" : "Any of the following must be true") + "\n" +
+                filters.map((f) => {
+                    count ++;
+                    return (count == 1 ? getEmojiByName("ICONS.FILTER") : (all ? "**and** " : "**or** ")) +
+                        (f.inverted ? "**not** " : "") + `${f.name}`
+                }).join("\n") + "\n\n" + `This will affect ${addPlural(affected.length.toString(), "member")}`)
+            .setEmoji("GUILD.ROLES.CREATE")
+            .setStatus("Success")
+        ], components: [
+            new MessageActionRow().addComponents([new MessageSelectMenu().setOptions(filters.map((f, index) => ({
+                label: (f.inverted ? "(Not) " : "") + f.name,
+                value: index.toString()
+            }))).setMinValues(1).setMaxValues(filters.length).setCustomId("select").setPlaceholder("Remove a filter")]),
+            new MessageActionRow().addComponents([
+                new MessageButton()
+                    .setLabel("Apply")
+                    .setStyle("PRIMARY")
+                    .setCustomId("apply")
+                    .setEmoji(client.emojis.cache.get(getEmojiByName("CONTROL.TICK", "id")))
+                    .setDisabled(affected.length === 0),
+                new MessageButton()
+                    .setLabel("Add filter")
+                    .setStyle("PRIMARY")
+                    .setCustomId("add")
+                    .setEmoji(client.emojis.cache.get(getEmojiByName("ICONS.FILTER", "id")))
+                    .setDisabled(filters.length >= 25)
+            ])
+        ]})
+        break
+    }
+}
+
+const check = async (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
+    let member = (interaction.member as GuildMember)
+    let me = (interaction.guild.me as GuildMember)
+    if (!me.permissions.has("MANAGE_ROLES")) throw "I do not have the Manage roles permission";
+    // Allow the owner to role anyone
+    if (member.id == interaction.guild.ownerId) return true
+    // Check if the user has manage_roles permission
+    if (! member.permissions.has("MANAGE_ROLES")) throw "You do not have the Manage roles permission";
+    // Allow role
     return true;
 }
 
diff --git a/src/commands/role/user.ts b/src/commands/role/user.ts
index b45e1d1..bb79098 100644
--- a/src/commands/role/user.ts
+++ b/src/commands/role/user.ts
@@ -1,17 +1,84 @@
-import { CommandInteraction } from "discord.js";
+import { CommandInteraction, GuildMember, Role } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
+import client from "../../utils/client.js";
+import confirmationMessage from "../../utils/confirmationMessage.js";
+import keyValueList from "../../utils/generateKeyValueList.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
     builder
     .setName("user")
     .setDescription("Gives or removes a role from someone")
+    .addUserOption(option => option.setName("user").setDescription("The member to give or remove the role from").setRequired(true))
+    .addRoleOption(option => option.setName("role").setDescription("The role to give or remove").setRequired(true))
+    .addStringOption(option => option.setName("action").setDescription("The action to perform").setRequired(true).addChoices([
+        ["Add", "give"],
+        ["Remove", "remove"]
+    ]))
 
-const callback = (interaction: CommandInteraction) => {
-    interaction.reply("This command is not yet finished [role/user]");
+
+const callback = async (interaction: CommandInteraction): Promise<any>  => {
+    const { renderUser, renderRole } = client.logger
+    let action = interaction.options.getString("action");
+    // TODO:[Modals] Replace this with a modal
+    let confirmation = await new confirmationMessage(interaction)
+        .setEmoji("GUILD.ROLES.DELETE")
+        .setTitle("Role")
+        .setDescription(keyValueList({
+            "user": renderUser(interaction.options.getUser("user")),
+            "role": renderRole(interaction.options.getRole("role"))
+        })
+        + `\nAre you sure you want to ${action == "give" ? "give the role to" : "remove the role from"} ${interaction.options.getUser("user")}?`)
+        .setColor("Danger")
+    .send()
+    if (confirmation.success) {
+        try {
+            let member = interaction.options.getMember("user") as GuildMember
+            let role = interaction.options.getRole("role") as Role
+            if (interaction.options.getString("action") == "give") {
+                member.roles.add(role)
+            } else {
+                member.roles.remove(role)
+            }
+        } catch (e) {
+            return await interaction.editReply({embeds: [new EmojiEmbed()
+                .setTitle("Role")
+                .setDescription("Something went wrong and the role could not be added")
+                .setStatus("Danger")
+                .setEmoji("CONTROL.BLOCKCROSS")
+            ], components: []})
+        }
+        return await interaction.editReply({embeds: [new EmojiEmbed()
+            .setTitle("Role")
+            .setDescription(`The role has been ${action == "give" ? "given" : "removed"} successfully`)
+            .setStatus("Success")
+            .setEmoji("GUILD.ROLES.CREATE")
+        ], components: []})
+    } else {
+        await interaction.editReply({embeds: [new EmojiEmbed()
+            .setEmoji("GUILD.ROLES.CREATE")
+            .setTitle("Role")
+            .setDescription(`You have cancelled the role change.`)
+            .setStatus("Danger")
+        ], components: []})
+    }
 }
 
 const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
+    let member = (interaction.member as GuildMember)
+    let me = (interaction.guild.me as GuildMember)
+    let apply = (interaction.options.getMember("user") as GuildMember)
+    if (member == null || me == null || apply == null) throw "That member is not in the server"
+    // Check if Nucleus has permission to role
+    if (!me.permissions.has("MANAGE_ROLES")) throw "I do not have the Manage roles permission";
+    // Allow the owner to role anyone
+    if (member.id == interaction.guild.ownerId) return true
+    // Check if the user has manage_roles permission
+    if (! member.permissions.has("MANAGE_ROLES")) throw "You do not have the Manage roles permission";
+    // Check if the role is above or equal to the user's highest role
+    if (apply.roles.highest.comparePositionTo(member.roles.highest) >= 0) throw "You cannot give a role higher than your highest role";
+    // Allow role
     return true;
 }
 
diff --git a/src/commands/server/about.ts b/src/commands/server/about.ts
index 895d2cc..28e09aa 100644
--- a/src/commands/server/about.ts
+++ b/src/commands/server/about.ts
@@ -1,7 +1,7 @@
 import Discord, { CommandInteraction, Guild, MessageActionRow, MessageButton } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../../utils/getEmojiByName.js";
 import generateKeyValueList, { toCapitals } from "../../utils/generateKeyValueList.js";
 import client from "../../utils/client.js"
@@ -10,10 +10,10 @@
     .setName("about")
     .setDescription("Shows info about the server")
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
     let guild = interaction.guild as Guild;
     const { renderUser, renderDelta } = client.logger
-    interaction.reply({embeds: [new generateEmojiEmbed()
+    interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Server Info")
         .setStatus("Success")
         .setEmoji("GUILD.GREEN")
diff --git a/src/commands/settings/logs/channel.ts b/src/commands/settings/logs/channel.ts
index 448f26a..19a389b 100644
--- a/src/commands/settings/logs/channel.ts
+++ b/src/commands/settings/logs/channel.ts
@@ -1,6 +1,6 @@
 import { ChannelType } from 'discord-api-types';
 import Discord, { CommandInteraction, MessageActionRow, MessageButton } from "discord.js";
-import generateEmojiEmbed from "../../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
 import confirmationMessage from "../../../utils/confirmationMessage.js";
 import getEmojiByName from "../../../utils/getEmojiByName.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
@@ -17,7 +17,7 @@
 
 const callback = async (interaction: CommandInteraction): Promise<any> => {
     let m;
-    m = await interaction.reply({embeds: [new generateEmojiEmbed()
+    m = await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Loading")
         .setStatus("Danger")
         .setEmoji("NUCLEUS.LOADING")
@@ -27,7 +27,7 @@
         try {
             channel = interaction.options.getChannel("channel")
         } catch {
-            return await interaction.editReply({embeds: [new generateEmojiEmbed()
+            return await interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji("CHANNEL.TEXT.DELETE")
                 .setTitle("Log Channel")
                 .setDescription("The channel you provided is not a valid channel")
@@ -36,7 +36,7 @@
         }
         channel = channel as Discord.TextChannel
         if (channel.guild.id != interaction.guild.id) {
-            return interaction.editReply({embeds: [new generateEmojiEmbed()
+            return interaction.editReply({embeds: [new EmojiEmbed()
                 .setTitle("Log Channel")
                 .setDescription(`You must choose a channel in this server`)
                 .setStatus("Danger")
@@ -52,10 +52,10 @@
         .send(true)
         if (confirmation.success) {
             try {
-                await client.database.write(interaction.guild.id, {"logging.logs.channel": channel.id})
+                await client.database.guilds.write(interaction.guild.id, {"logging.logs.channel": channel.id})
             } catch (e) {
                 console.log(e)
-                return interaction.editReply({embeds: [new generateEmojiEmbed()
+                return interaction.editReply({embeds: [new EmojiEmbed()
                     .setTitle("Log Channel")
                     .setDescription(`Something went wrong and the log channel could not be set`)
                     .setStatus("Danger")
@@ -63,7 +63,7 @@
                 ], components: []});
             }
         } else {
-            return interaction.editReply({embeds: [new generateEmojiEmbed()
+            return interaction.editReply({embeds: [new EmojiEmbed()
                 .setTitle("Log Channel")
                 .setDescription(`No changes were made`)
                 .setStatus("Success")
@@ -72,10 +72,10 @@
         }
     }
     let clicks = 0;
-    let data = await client.database.read(interaction.guild.id);
+    let data = await client.database.guilds.read(interaction.guild.id);
     let channel = data.logging.logs.channel;
     while (true) {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setTitle("Log channel")
             .setDescription(channel ? `Your log channel is currently set to <#${channel}>` : "This server does not have a log channel")
             .setStatus("Success")
@@ -96,14 +96,14 @@
             clicks += 1;
             if (clicks == 2) {
                 clicks = 0;
-                await client.database.write(interaction.guild.id, {}, ["logging.logs.channel"])
+                await client.database.guilds.write(interaction.guild.id, {}, ["logging.logs.channel"])
                 channel = undefined;
             }
         } else {
             break
         }
     }
-    await interaction.editReply({embeds: [new generateEmojiEmbed()
+    await interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Log channel")
         .setDescription(channel ? `Your log channel is currently set to <#${channel}>` : "This server does not have a log channel")
         .setStatus("Success")
diff --git a/src/commands/settings/logs/ignore.ts b/src/commands/settings/logs/ignore.ts
index 4b66307..12af085 100644
--- a/src/commands/settings/logs/ignore.ts
+++ b/src/commands/settings/logs/ignore.ts
@@ -1,7 +1,7 @@
 import { ChannelType } from 'discord-api-types';
 import Discord, { CommandInteraction } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
-import generateEmojiEmbed from "../../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
 import { WrappedCheck } from "jshaiku";
 import confirmationMessage from '../../../utils/confirmationMessage.js';
 import keyValueList from '../../../utils/generateKeyValueList.js';
@@ -24,7 +24,7 @@
     let channel = interaction.options.getChannel("addchannel")
     let user = interaction.options.getUser("adduser")
     let role = interaction.options.getRole("addrole")
-    await interaction.reply({embeds: [new generateEmojiEmbed()
+    await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Loading")
         .setStatus("Danger")
         .setEmoji("NUCLEUS.LOADING")
@@ -34,7 +34,7 @@
             try {
                 channel = interaction.guild.channels.cache.get(channel.id)
             } catch {
-                return await interaction.editReply({embeds: [new generateEmojiEmbed()
+                return await interaction.editReply({embeds: [new EmojiEmbed()
                     .setEmoji("CHANNEL.TEXT.DELETE")
                     .setTitle("Logs > Ignore")
                     .setDescription("The channel you provided is not a valid channel")
@@ -43,7 +43,7 @@
             }
             channel = channel as Discord.TextChannel
             if (channel.guild.id != interaction.guild.id) {
-                return interaction.editReply({embeds: [new generateEmojiEmbed()
+                return interaction.editReply({embeds: [new EmojiEmbed()
                     .setTitle("Logs > Ignore")
                     .setDescription(`You must choose a channel in this server`)
                     .setStatus("Danger")
@@ -55,7 +55,7 @@
             try {
                 user = interaction.guild.members.cache.get(user.id).user
             } catch {
-                return await interaction.editReply({embeds: [new generateEmojiEmbed()
+                return await interaction.editReply({embeds: [new EmojiEmbed()
                     .setEmoji("USER.DELETE")
                     .setTitle("Logs > Ignore")
                     .setDescription("The user you provided is not a valid user")
@@ -68,7 +68,7 @@
             try {
                 role = interaction.guild.roles.cache.get(role.id)
             } catch {
-                return await interaction.editReply({embeds: [new generateEmojiEmbed()
+                return await interaction.editReply({embeds: [new EmojiEmbed()
                     .setEmoji("ROLE.DELETE")
                     .setTitle("Logs > Ignore")
                     .setDescription("The role you provided is not a valid role")
@@ -77,7 +77,7 @@
             }
             role = role as Discord.Role
             if (role.guild.id != interaction.guild.id) {
-                return interaction.editReply({embeds: [new generateEmojiEmbed()
+                return interaction.editReply({embeds: [new EmojiEmbed()
                     .setTitle("Logs > Ignore")
                     .setDescription(`You must choose a role in this server`)
                     .setStatus("Danger")
@@ -97,12 +97,12 @@
             .setColor("Warning")
         .send(true)
         if (confirmation.success) {
-            let data = client.database.read(interaction.guild.id)
+            let data = client.database.guilds.read(interaction.guild.id)
             if (channel) data.logging.logs.ignore.channels.concat([channel.id])
             if (user) data.logging.logs.ignore.users.concat([user.id])
             if (role) data.logging.logs.ignore.roles.concat([role.id])
             if (interaction.options.getString("action") == "add") {
-                await client.database.append(interaction.guild.id, data)
+                await client.database.guilds.append(interaction.guild.id, data)
             }
         }
     }
diff --git a/src/commands/settings/staff/channel.ts b/src/commands/settings/staff/channel.ts
index 354d7f1..74605cf 100644
--- a/src/commands/settings/staff/channel.ts
+++ b/src/commands/settings/staff/channel.ts
@@ -1,6 +1,6 @@
 import { ChannelType } from 'discord-api-types';
 import Discord, { CommandInteraction, MessageActionRow, MessageButton } from "discord.js";
-import generateEmojiEmbed from "../../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
 import confirmationMessage from "../../../utils/confirmationMessage.js";
 import getEmojiByName from "../../../utils/getEmojiByName.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
@@ -17,7 +17,7 @@
 
 const callback = async (interaction: CommandInteraction): Promise<any> => {
     let m;
-    m = await interaction.reply({embeds: [new generateEmojiEmbed()
+    m = await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Loading")
         .setStatus("Danger")
         .setEmoji("NUCLEUS.LOADING")
@@ -27,7 +27,7 @@
         try {
             channel = interaction.options.getChannel("channel")
         } catch {
-            return await interaction.editReply({embeds: [new generateEmojiEmbed()
+            return await interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji("CHANNEL.TEXT.DELETE")
                 .setTitle("Staff Notifications Channel")
                 .setDescription("The channel you provided is not a valid channel")
@@ -36,7 +36,7 @@
         }
         channel = channel as Discord.TextChannel
         if (channel.guild.id != interaction.guild.id) {
-            return interaction.editReply({embeds: [new generateEmojiEmbed()
+            return interaction.editReply({embeds: [new EmojiEmbed()
                 .setTitle("Staff Notifications Channel")
                 .setDescription(`You must choose a channel in this server`)
                 .setStatus("Danger")
@@ -55,9 +55,9 @@
         .send(true)
         if (confirmation.success) {
             try {
-                await client.database.write(interaction.guild.id, {"logging.staff.channel": channel.id})
+                await client.database.guilds.write(interaction.guild.id, {"logging.staff.channel": channel.id})
             } catch (e) {
-                return interaction.editReply({embeds: [new generateEmojiEmbed()
+                return interaction.editReply({embeds: [new EmojiEmbed()
                     .setTitle("Staff Notifications Channel")
                     .setDescription(`Something went wrong and the staff notifications channel could not be set`)
                     .setStatus("Danger")
@@ -65,7 +65,7 @@
                 ], components: []});
             }
         } else {
-            return interaction.editReply({embeds: [new generateEmojiEmbed()
+            return interaction.editReply({embeds: [new EmojiEmbed()
                 .setTitle("Staff Notifications Channel")
                 .setDescription(`No changes were made`)
                 .setStatus("Success")
@@ -74,10 +74,10 @@
         }
     }
     let clicks = 0;
-    let data = await client.database.read(interaction.guild.id);
+    let data = await client.database.guilds.read(interaction.guild.id);
     let channel = data.logging.staff.channel;
     while (true) {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setTitle("Staff Notifications channel")
             .setDescription(channel ? `Your staff notifications channel is currently set to <#${channel}>` : "This server does not have a staff notifications channel")
             .setStatus("Success")
@@ -98,14 +98,14 @@
             clicks += 1;
             if (clicks == 2) {
                 clicks = 0;
-                await client.database.write(interaction.guild.id, {}, ["logging.staff.channel"])
+                await client.database.guilds.write(interaction.guild.id, {}, ["logging.staff.channel"])
                 channel = undefined;
             }
         } else {
             break
         }
     }
-    await interaction.editReply({embeds: [new generateEmojiEmbed()
+    await interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Staff Notifications channel")
         .setDescription(channel ? `Your staff notifications channel is currently set to <#${channel}>` : "This server does not have a staff notifications channel")
         .setStatus("Success")
diff --git a/src/commands/settings/tickets.ts b/src/commands/settings/tickets.ts
index 670a2f2..b505c5c 100644
--- a/src/commands/settings/tickets.ts
+++ b/src/commands/settings/tickets.ts
@@ -1,5 +1,5 @@
 import getEmojiByName from "../../utils/getEmojiByName.js";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import confirmationMessage from "../../utils/confirmationMessage.js";
 import Discord, { CommandInteraction, MessageActionRow, MessageButton, MessageSelectMenu, TextInputComponent } from "discord.js";
 import { SelectMenuOption, SlashCommandSubcommandBuilder } from "@discordjs/builders";
@@ -22,7 +22,7 @@
 const callback = async (interaction: CommandInteraction): Promise<any> => {
     let m;
     m = await interaction.reply({
-        embeds: [new generateEmojiEmbed()
+        embeds: [new EmojiEmbed()
             .setTitle("Loading")
             .setStatus("Danger")
             .setEmoji("NUCLEUS.LOADING")
@@ -42,7 +42,7 @@
                 channel = interaction.guild.channels.cache.get(options.category.id)
             } catch {
                 return await interaction.editReply({
-                    embeds: [new generateEmojiEmbed()
+                    embeds: [new EmojiEmbed()
                         .setEmoji("CHANNEL.TEXT.DELETE")
                         .setTitle("Tickets > Category")
                         .setDescription("The channel you provided is not a valid category")
@@ -52,7 +52,7 @@
             }
             channel = channel as Discord.CategoryChannel
             if (channel.guild.id != interaction.guild.id) return interaction.editReply({
-                embeds: [new generateEmojiEmbed()
+                embeds: [new EmojiEmbed()
                     .setTitle("Tickets > Category")
                     .setDescription(`You must choose a category in this server`)
                     .setStatus("Danger")
@@ -62,7 +62,7 @@
         }
         if (options.maxtickets) {
             if (options.maxtickets < 1) return interaction.editReply({
-                embeds: [new generateEmojiEmbed()
+                embeds: [new EmojiEmbed()
                     .setTitle("Tickets > Max Tickets")
                     .setDescription(`You must choose a number greater than 0`)
                     .setStatus("Danger")
@@ -76,7 +76,7 @@
                 role = interaction.guild.roles.cache.get(options.supportping.id)
             } catch {
                 return await interaction.editReply({
-                    embeds: [new generateEmojiEmbed()
+                    embeds: [new EmojiEmbed()
                         .setEmoji("GUILD.ROLE.DELETE")
                         .setTitle("Tickets > Support Ping")
                         .setDescription("The role you provided is not a valid role")
@@ -86,7 +86,7 @@
             }
             role = role as Discord.Role
             if (role.guild.id != interaction.guild.id) return interaction.editReply({
-                embeds: [new generateEmojiEmbed()
+                embeds: [new EmojiEmbed()
                     .setTitle("Tickets > Support Ping")
                     .setDescription(`You must choose a role in this server`)
                     .setStatus("Danger")
@@ -116,10 +116,10 @@
             if (options.maxtickets) toUpdate["tickets.maxTickets"] = options.maxtickets
             if (options.supportping) toUpdate["tickets.supportRole"] = options.supportping.id
             try {
-                await client.database.write(interaction.guild.id, toUpdate)
+                await client.database.guilds.write(interaction.guild.id, toUpdate)
             } catch (e) {
                 return interaction.editReply({
-                    embeds: [new generateEmojiEmbed()
+                    embeds: [new EmojiEmbed()
                         .setTitle("Tickets")
                         .setDescription(`Something went wrong and the staff notifications channel could not be set`)
                         .setStatus("Danger")
@@ -129,7 +129,7 @@
             }
         } else {
             return interaction.editReply({
-                embeds: [new generateEmojiEmbed()
+                embeds: [new EmojiEmbed()
                     .setTitle("Tickets")
                     .setDescription(`No changes were made`)
                     .setStatus("Success")
@@ -138,7 +138,7 @@
             });
         }
     }
-    let data = await client.database.read(interaction.guild.id);
+    let data = await client.database.guilds.read(interaction.guild.id);
     data.tickets.customTypes = data.tickets.customTypes.filter((v, i, a) => a.indexOf(v) === i)
     let lastClicked = "";
     let embed;
@@ -152,7 +152,7 @@
         customTypes: data.tickets.customTypes
     }
     while (true) {
-        embed = new generateEmojiEmbed()
+        embed = new EmojiEmbed()
             .setTitle("Tickets")
             .setDescription(
                 `${data.enabled ? "" : getEmojiByName("TICKETS.REPORT")} **Enabled:** ${data.enabled ? `${getEmojiByName("CONTROL.TICK")} Yes` : `${getEmojiByName("CONTROL.CROSS")} No`}\n` +
@@ -206,23 +206,23 @@
         if (i.component.customId == "clearCategory") {
             if (lastClicked == "cat") {
                 lastClicked = "";
-                await client.database.write(interaction.guild.id, {}, ["tickets.category"])
+                await client.database.guilds.write(interaction.guild.id, {}, ["tickets.category"])
                 data.category = undefined;
             } else lastClicked = "cat";
         } else if (i.component.customId == "clearMaxTickets") {
             if (lastClicked == "max") {
                 lastClicked = "";
-                await client.database.write(interaction.guild.id, {}, ["tickets.maxTickets"])
+                await client.database.guilds.write(interaction.guild.id, {}, ["tickets.maxTickets"])
                 data.maxTickets = 5;
             } else lastClicked = "max";
         } else if (i.component.customId == "clearSupportPing") {
             if (lastClicked == "sup") {
                 lastClicked = "";
-                await client.database.write(interaction.guild.id, {}, ["tickets.supportRole"])
+                await client.database.guilds.write(interaction.guild.id, {}, ["tickets.supportRole"])
                 data.supportRole = undefined;
             } else lastClicked = "sup";
         } else if (i.component.customId == "enabled") {
-            await client.database.write(interaction.guild.id, { "tickets.enabled": !data.enabled })
+            await client.database.guilds.write(interaction.guild.id, { "tickets.enabled": !data.enabled })
             data.enabled = !data.enabled;
         } else if (i.component.customId == "manageTypes") {
             data = await manageTypes(interaction, data, m);
@@ -238,7 +238,7 @@
         if (data.useCustom) {
             let customTypes = data.customTypes;
             await interaction.editReply({
-                embeds: [new generateEmojiEmbed()
+                embeds: [new EmojiEmbed()
                     .setTitle("Tickets > Types")
                     .setDescription(
                         "**Custom types enabled**\n\n" +
@@ -299,7 +299,7 @@
                     .setPlaceholder("Select types to use")
             ])
             await interaction.editReply({
-                embeds: [new generateEmojiEmbed()
+                embeds: [new EmojiEmbed()
                     .setTitle("Tickets > Types")
                     .setDescription(
                         "**Default types enabled**\n\n" +
@@ -331,7 +331,7 @@
         if (i.component.customId == "types") {
             i.deferUpdate()
             let types = toHexInteger(i.values, ticketTypes);
-            await client.database.write(interaction.guild.id, { "tickets.types": types })
+            await client.database.guilds.write(interaction.guild.id, { "tickets.types": types })
             data.types = types;
         } else if (i.component.customId == "removeTypes") {
             i.deferUpdate()
@@ -340,7 +340,7 @@
             if (customTypes) {
                 customTypes = customTypes.filter((t) => !types.includes(t));
                 customTypes = customTypes.length > 0 ? customTypes : null;
-                await client.database.write(interaction.guild.id, { "tickets.customTypes": customTypes })
+                await client.database.guilds.write(interaction.guild.id, { "tickets.customTypes": customTypes })
                 data.customTypes = customTypes;
             }
         } else if (i.component.customId == "addType") {
@@ -357,7 +357,7 @@
                 )
             ))
             await interaction.editReply({
-                embeds: [new generateEmojiEmbed()
+                embeds: [new EmojiEmbed()
                     .setTitle("Tickets > Types")
                     .setDescription("Modal opened. If you can't see it, click back and try again.")
                     .setStatus("Success")
@@ -369,15 +369,16 @@
                     .setCustomId("back")
                 ])]
             });
-            let out
+            let out;
             try {
                 out = await modalInteractionCollector(m, (m) => m.channel.id == interaction.channel.id, (m) => m.customId == "addType")
             } catch (e) { continue }
             if (out.fields) {
                 let toAdd = out.fields.getTextInputValue("type");
                 if (!toAdd) { continue }
+                toAdd = toAdd.substring(0, 80)
                 try {
-                    await client.database.append(interaction.guild.id, "tickets.customTypes", toAdd)
+                    await client.database.guilds.append(interaction.guild.id, "tickets.customTypes", toAdd)
                 } catch { continue }
                 data.customTypes = data.customTypes || [];
                 if (!data.customTypes.includes(toAdd)) {
@@ -386,11 +387,11 @@
             } else { continue }
         } else if (i.component.customId == "switchToDefault") {
             i.deferUpdate()
-            await client.database.write(interaction.guild.id, { "tickets.useCustom": false }, [])
+            await client.database.guilds.write(interaction.guild.id, { "tickets.useCustom": false }, [])
             data.useCustom = false;
         } else if (i.component.customId == "switchToCustom") {
             i.deferUpdate()
-            await client.database.write(interaction.guild.id, { "tickets.useCustom": true }, [])
+            await client.database.guilds.write(interaction.guild.id, { "tickets.useCustom": true }, [])
             data.useCustom = true;
         } else {
             i.deferUpdate()
diff --git a/src/commands/settings/verify/role.ts b/src/commands/settings/verify/role.ts
index 68b4bf9..44406e9 100644
--- a/src/commands/settings/verify/role.ts
+++ b/src/commands/settings/verify/role.ts
@@ -1,5 +1,5 @@
 import Discord, { CommandInteraction, MessageActionRow, MessageButton } from "discord.js";
-import generateEmojiEmbed from "../../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
 import confirmationMessage from "../../../utils/confirmationMessage.js";
 import getEmojiByName from "../../../utils/getEmojiByName.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
@@ -14,7 +14,7 @@
 
 const callback = async (interaction: CommandInteraction): Promise<any> => {
     let m;
-    m = await interaction.reply({embeds: [new generateEmojiEmbed()
+    m = await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Loading")
         .setStatus("Danger")
         .setEmoji("NUCLEUS.LOADING")
@@ -24,7 +24,7 @@
         try {
             role = interaction.options.getRole("role")
         } catch {
-            return await interaction.editReply({embeds: [new generateEmojiEmbed()
+            return await interaction.editReply({embeds: [new EmojiEmbed()
                 .setEmoji("GUILD.ROLES.DELETE")
                 .setTitle("Verify Role")
                 .setDescription("The role you provided is not a valid role")
@@ -33,7 +33,7 @@
         }
         role = role as Discord.Role
         if (role.guild.id != interaction.guild.id) {
-            return interaction.editReply({embeds: [new generateEmojiEmbed()
+            return interaction.editReply({embeds: [new EmojiEmbed()
                 .setTitle("Verify Role")
                 .setDescription(`You must choose a role in this server`)
                 .setStatus("Danger")
@@ -49,10 +49,10 @@
         .send(true)
         if (confirmation.success) {
             try {
-                await client.database.write(interaction.guild.id, {"verify.role": role.id, "verify.enabled": true});
+                await client.database.guilds.write(interaction.guild.id, {"verify.role": role.id, "verify.enabled": true});
             } catch (e) {
                 console.log(e)
-                return interaction.editReply({embeds: [new generateEmojiEmbed()
+                return interaction.editReply({embeds: [new EmojiEmbed()
                     .setTitle("Verify Role")
                     .setDescription(`Something went wrong while setting the verify role`)
                     .setStatus("Danger")
@@ -60,7 +60,7 @@
                 ], components: []});
             }
         } else {
-            return interaction.editReply({embeds: [new generateEmojiEmbed()
+            return interaction.editReply({embeds: [new EmojiEmbed()
                 .setTitle("Verify Role")
                 .setDescription(`No changes were made`)
                 .setStatus("Success")
@@ -69,10 +69,10 @@
         }
     }
     let clicks = 0;
-    let data = await client.database.read(interaction.guild.id);
+    let data = await client.database.guilds.read(interaction.guild.id);
     let role = data.verify.role;
     while (true) {
-        await interaction.editReply({embeds: [new generateEmojiEmbed()
+        await interaction.editReply({embeds: [new EmojiEmbed()
             .setTitle("Verify Role")
             .setDescription(role ? `Your verify role is currently set to <@&${role}>` : `You have not set a verify role`)
             .setStatus("Success")
@@ -93,14 +93,14 @@
             clicks += 1;
             if (clicks == 2) {
                 clicks = 0;
-                await client.database.write(interaction.guild.id, {}, ["verify.role", "verify.enabled"])
+                await client.database.guilds.write(interaction.guild.id, {}, ["verify.role", "verify.enabled"])
                 role = undefined;
             }
         } else {
             break
         }
     }
-    await interaction.editReply({embeds: [new generateEmojiEmbed()
+    await interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Verify Role")
         .setDescription(role ? `Your verify role is currently set to <@&${role}}>` : `You have not set a verify role`)
         .setStatus("Success")
diff --git a/src/commands/tag.ts b/src/commands/tag.ts
index 80bcbad..a9f0075 100644
--- a/src/commands/tag.ts
+++ b/src/commands/tag.ts
@@ -9,7 +9,6 @@
     .setDescription("Get and manage the servers tags")
 
 const callback = (interaction: CommandInteraction) => {
-    // try { statsChannelAdd(interaction.client, interaction.member); } catch {} // TODO: REMOVE THIS FOR PRODUCTION
     interaction.reply("This command is not yet finished [tag]");
 }
 
diff --git a/src/commands/tags/create.ts b/src/commands/tags/create.ts
index e53f94f..c1ed839 100644
--- a/src/commands/tags/create.ts
+++ b/src/commands/tags/create.ts
@@ -1,7 +1,7 @@
 import Discord, { CommandInteraction } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import confirmationMessage from "../../utils/confirmationMessage.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
 import client from "../../utils/client.js";
@@ -16,26 +16,26 @@
 const callback = async (interaction: CommandInteraction): Promise<any> => {
     let name = interaction.options.getString("name");
     let value = interaction.options.getString("value");
-    if (name.length > 100) return await interaction.reply({embeds: [new generateEmojiEmbed()
+    if (name.length > 100) return await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Tag Create")
         .setDescription("Tag names cannot be longer than 100 characters")
         .setStatus("Danger")
         .setEmoji("PUNISH.NICKNAME.RED")
     ], ephemeral: true});
-    if (value.length > 1000) return await interaction.reply({embeds: [new generateEmojiEmbed()
+    if (value.length > 1000) return await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Tag Create")
         .setDescription("Tag values cannot be longer than 1000 characters")
         .setStatus("Danger")
         .setEmoji("PUNISH.NICKNAME.RED")
     ], ephemeral: true});
-    let data = await client.database.read(interaction.guild.id);
-    if (data.tags.length >= 100) return await interaction.reply({embeds: [new generateEmojiEmbed()
+    let data = await client.database.guilds.read(interaction.guild.id);
+    if (data.tags.length >= 100) return await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Tag Create")
         .setDescription("You cannot have more than 100 tags")
         .setStatus("Danger")
         .setEmoji("PUNISH.NICKNAME.RED")
     ], ephemeral: true});
-    if (data.tags[name]) return await interaction.reply({embeds: [new generateEmojiEmbed()
+    if (data.tags[name]) return await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Tag Create")
         .setDescription("That tag already exists")
         .setStatus("Danger")
@@ -52,23 +52,23 @@
         .setColor("Warning")
         .setInverted(true)
     .send()
-    if (!confirmation) return await interaction.editReply({embeds: [new generateEmojiEmbed()
+    if (!confirmation) return await interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Tag Create")
         .setDescription("No changes were made")
         .setStatus("Success")
         .setEmoji("PUNISH.NICKNAME.GREEN")
     ]});
     try {
-        await client.database.write(interaction.guild.id, {[`tags.${name}`]: value});
+        await client.database.guilds.write(interaction.guild.id, {[`tags.${name}`]: value});
     } catch (e) {
-        return await interaction.editReply({embeds: [new generateEmojiEmbed()
+        return await interaction.editReply({embeds: [new EmojiEmbed()
             .setTitle("Tag Create")
             .setDescription("Something went wrong and the tag was not created")
             .setStatus("Danger")
             .setEmoji("PUNISH.NICKNAME.RED")
         ], components: []});
     }
-    return await interaction.editReply({embeds: [new generateEmojiEmbed()
+    return await interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Tag Create")
         .setDescription("Tag created")
         .setStatus("Success")
diff --git a/src/commands/tags/delete.ts b/src/commands/tags/delete.ts
index ff54ee5..f24a5fc 100644
--- a/src/commands/tags/delete.ts
+++ b/src/commands/tags/delete.ts
@@ -1,7 +1,7 @@
 import Discord, { CommandInteraction } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import confirmationMessage from "../../utils/confirmationMessage.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
 import client from "../../utils/client.js";
@@ -14,8 +14,8 @@
 
 const callback = async (interaction: CommandInteraction): Promise<any> => {
     let name = interaction.options.getString("name");
-    let data = await client.database.read(interaction.guild.id);
-    if (!data.tags[name]) return await interaction.reply({embeds: [new generateEmojiEmbed()
+    let data = await client.database.guilds.read(interaction.guild.id);
+    if (!data.tags[name]) return await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Tags")
         .setDescription("That tag does not exist")
         .setStatus("Danger")
@@ -32,25 +32,25 @@
         .setColor("Warning")
         .setInverted(true)
     .send()
-    if (!confirmation) return await interaction.editReply({embeds: [new generateEmojiEmbed()
+    if (!confirmation) return await interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Tag Delete")
         .setDescription("No changes were made")
         .setStatus("Success")
         .setEmoji("PUNISH.NICKNAME.GREEN")
     ]});
     try {
-        data = await client.database.read(interaction.guild.id);
+        data = await client.database.guilds.read(interaction.guild.id);
         delete data.tags[name];
-        await client.database.write(interaction.guild.id, {tags: data});
+        await client.database.guilds.write(interaction.guild.id, {tags: data});
     } catch (e) {
-        return await interaction.editReply({embeds: [new generateEmojiEmbed()
+        return await interaction.editReply({embeds: [new EmojiEmbed()
             .setTitle("Tag Delete")
             .setDescription("Something went wrong and the tag was not deleted")
             .setStatus("Danger")
             .setEmoji("PUNISH.NICKNAME.RED")
         ], components: []});
     }
-    return await interaction.editReply({embeds: [new generateEmojiEmbed()
+    return await interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Tag Delete")
         .setDescription("Tag deleted")
         .setStatus("Success")
diff --git a/src/commands/tags/edit.ts b/src/commands/tags/edit.ts
index 3cf73e5..b0a4835 100644
--- a/src/commands/tags/edit.ts
+++ b/src/commands/tags/edit.ts
@@ -1,7 +1,7 @@
 import Discord, { CommandInteraction } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import confirmationMessage from "../../utils/confirmationMessage.js";
 import keyValueList from "../../utils/generateKeyValueList.js";
 import client from "../../utils/client.js";
@@ -18,32 +18,32 @@
     let name = interaction.options.getString("name");
     let value = interaction.options.getString("value") || "";
     let newname = interaction.options.getString("newname") || "";
-    if (!newname && !value) return await interaction.reply({embeds: [new generateEmojiEmbed()
+    if (!newname && !value) return await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Tag Edit")
         .setDescription("You must specify a value or a new name")
         .setStatus("Danger")
         .setEmoji("PUNISH.NICKNAME.RED")
     ], ephemeral: true});
-    if (newname.length > 100) return await interaction.reply({embeds: [new generateEmojiEmbed()
+    if (newname.length > 100) return await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Tag Edit")
         .setDescription("Tag names cannot be longer than 100 characters")
         .setStatus("Danger")
         .setEmoji("PUNISH.NICKNAME.RED")
     ], ephemeral: true});
-    if (value.length > 2000) return await interaction.reply({embeds: [new generateEmojiEmbed()
+    if (value.length > 2000) return await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Tag Edit")
         .setDescription("Tag values cannot be longer than 2000 characters")
         .setStatus("Danger")
         .setEmoji("PUNISH.NICKNAME.RED")
     ], ephemeral: true});
-    let data = await client.database.read(interaction.guild.id);
-    if (!data.tags[name]) return await interaction.reply({embeds: [new generateEmojiEmbed()
+    let data = await client.database.guilds.read(interaction.guild.id);
+    if (!data.tags[name]) return await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Tag Edit")
         .setDescription("That tag does not exist")
         .setStatus("Danger")
         .setEmoji("PUNISH.NICKNAME.RED")
     ], ephemeral: true});
-    if (newname && newname !== name && data.tags[newname]) return await interaction.reply({embeds: [new generateEmojiEmbed()
+    if (newname && newname !== name && data.tags[newname]) return await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("Tag Edit")
         .setDescription("A tag with that name already exists")
         .setStatus("Danger")
@@ -60,7 +60,7 @@
         .setColor("Warning")
         .setInverted(true)
     .send()
-    if (!confirmation) return await interaction.editReply({embeds: [new generateEmojiEmbed()
+    if (!confirmation) return await interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Tag Edit")
         .setDescription("No changes were made")
         .setStatus("Success")
@@ -74,16 +74,16 @@
             toUnset.push(`tags.${name}`);
             toSet[`tags.${newname}`] = data.tags[name];
         }
-        await client.database.write(interaction.guild.id, toSet, toUnset);
+        await client.database.guilds.write(interaction.guild.id, toSet, toUnset);
     } catch (e) {
-        return await interaction.editReply({embeds: [new generateEmojiEmbed()
+        return await interaction.editReply({embeds: [new EmojiEmbed()
             .setTitle("Tag Edit")
             .setDescription("Something went wrong and the tag was not edited")
             .setStatus("Danger")
             .setEmoji("PUNISH.NICKNAME.RED")
         ], components: []});
     }
-    return await interaction.editReply({embeds: [new generateEmojiEmbed()
+    return await interaction.editReply({embeds: [new EmojiEmbed()
         .setTitle("Tags")
         .setDescription("Tag edited successfully")
         .setStatus("Success")
diff --git a/src/commands/tags/list.ts b/src/commands/tags/list.ts
index 5052a6b..a534791 100644
--- a/src/commands/tags/list.ts
+++ b/src/commands/tags/list.ts
@@ -1,8 +1,7 @@
 import Discord, { CommandInteraction, MessageActionRow, MessageButton } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
-import keyValueList from "../../utils/generateKeyValueList.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import client from "../../utils/client.js";
 import { SelectMenuOption } from '@discordjs/builders';
 import getEmojiByName from "../../utils/getEmojiByName.js";
@@ -25,10 +24,9 @@
         .setName("list")
         .setDescription("Lists all tags in the server")
 
-const callback = async (interaction: CommandInteraction) => {
-    let data = await client.database.read(interaction.guild.id);
+const callback = async (interaction: CommandInteraction): Promise<any> => {
+    let data = await client.database.guilds.read(interaction.guild.id);
     let tags = data.getKey("tags");
-    console.log(tags)
     let strings = []
     if (data === {}) strings = ["*No tags exist*"]
     else {
@@ -39,7 +37,6 @@
                 strings.push(string.slice(0, -1))
                 string = ""
             }
-            console.log(string)
             string += proposed
         }
         strings.push(string.slice(0, -1))
@@ -48,7 +45,7 @@
     let pages = []
     for (let string of strings) {
         pages.push(new Embed()
-            .setEmbed(new generateEmojiEmbed()
+            .setEmbed(new EmojiEmbed()
                 .setTitle("Tags")
                 .setDescription(string)
                 .setEmoji("PUNISH.NICKNAME.GREEN")
@@ -58,7 +55,7 @@
     let m;
     m = await interaction.reply({
         embeds: [
-            new generateEmojiEmbed()
+            new EmojiEmbed()
                 .setTitle("Welcome")
                 .setDescription(`One moment...`)
                 .setStatus("Danger")
@@ -128,7 +125,7 @@
             return;
         }
     }
-    let em = new Discord.MessageEmbed(pages[page])
+    let em = new Discord.MessageEmbed(pages[page].embed)
     em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page) + " | Message timed out");
     await interaction.editReply({
         embeds: [em],
diff --git a/src/commands/ticket/close.ts b/src/commands/ticket/close.ts
index 237623d..15abb0a 100644
--- a/src/commands/ticket/close.ts
+++ b/src/commands/ticket/close.ts
@@ -8,7 +8,7 @@
     .setName("close")
     .setDescription("Closes a ticket")
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
     await close(interaction);
 }
 
diff --git a/src/commands/ticket/create.ts b/src/commands/ticket/create.ts
index 6567c49..c44e576 100644
--- a/src/commands/ticket/create.ts
+++ b/src/commands/ticket/create.ts
@@ -9,7 +9,7 @@
     .setDescription("Creates a new modmail ticket")
     .addStringOption(option => option.setName("message").setDescription("The content of the ticket").setRequired(false))
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
     await create(interaction)
 }
 
diff --git a/src/commands/user/about.ts b/src/commands/user/about.ts
index 0c7a3eb..8557d15 100644
--- a/src/commands/user/about.ts
+++ b/src/commands/user/about.ts
@@ -1,7 +1,7 @@
 import Discord, { CommandInteraction, MessageActionRow, MessageButton } from "discord.js";
 import { SelectMenuOption, SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../../utils/getEmojiByName.js";
 import generateKeyValueList from "../../utils/generateKeyValueList.js";
 import createPageIndicator from "../../utils/createPageIndicator.js";
@@ -26,7 +26,7 @@
 }
 
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
     const { renderUser, renderDelta } = client.logger
     let member = (interaction.options.getMember("user") || interaction.member) as Discord.GuildMember;
     let flags: string[] = [];
@@ -105,7 +105,7 @@
 
     let embeds = [
         new Embed()
-            .setEmbed(new generateEmojiEmbed()
+            .setEmbed(new EmojiEmbed()
                 .setTitle("User Info: General")
                 .setStatus("Success")
                 .setEmoji("MEMBER.JOIN")
@@ -129,7 +129,7 @@
                 .setImage((await member.user.fetch()).bannerURL({format: "gif"}))
             ).setTitle("General").setDescription("General information about the user").setPageId(0),
         new Embed()
-            .setEmbed(new generateEmojiEmbed()
+            .setEmbed(new EmojiEmbed()
                 .setTitle("User Info: Roles")
                 .setStatus("Success")
                 .setEmoji("GUILD.ROLES.CREATE")
@@ -144,7 +144,7 @@
                 .setThumbnail(await member.user.displayAvatarURL({dynamic: true}))
             ).setTitle("Roles").setDescription("Roles the user has").setPageId(1),
         new Embed()
-            .setEmbed(new generateEmojiEmbed()
+            .setEmbed(new EmojiEmbed()
                 .setTitle("User Info: Key Permissions")
                 .setStatus("Success")
                 .setEmoji("GUILD.ROLES.CREATE")
@@ -158,7 +158,7 @@
             ).setTitle("Key Permissions").setDescription("Key permissions the user has").setPageId(2),
     ]
     let m
-    m = await interaction.reply({embeds: [new generateEmojiEmbed().setTitle("Loading").setEmoji("NUCLEUS.LOADING").setStatus("Danger")], fetchReply: true, ephemeral: true});
+    m = await interaction.reply({embeds: [new EmojiEmbed().setTitle("Loading").setEmoji("NUCLEUS.LOADING").setStatus("Danger")], fetchReply: true, ephemeral: true});
     let page = 0
     let breakReason = ""
     while (true) {
diff --git a/src/commands/user/avatar.ts b/src/commands/user/avatar.ts
index 9a84118..e72506f 100644
--- a/src/commands/user/avatar.ts
+++ b/src/commands/user/avatar.ts
@@ -1,10 +1,10 @@
 import Discord, { CommandInteraction } from "discord.js";
 import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../../utils/getEmojiByName.js";
 import generateKeyValueList from "../../utils/generateKeyValueList.js";
-import client from "../../client.js"
+import client from "../../utils/client.js"
 
 const command = (builder: SlashCommandSubcommandBuilder) =>
     builder
@@ -12,10 +12,10 @@
     .setDescription("Shows the avatar of a user")
     .addUserOption(option => option.setName("user").setDescription("The user to get the avatar of | Default: Yourself"))
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
     const { renderUser } = client.logger
     let member = (interaction.options.getMember("user") || interaction.member) as Discord.GuildMember;
-    await interaction.reply({embeds: [new generateEmojiEmbed()
+    await interaction.reply({embeds: [new EmojiEmbed()
         .setTitle("User Info")
         .setStatus("Success")
         .setEmoji("MEMBER.JOIN")
diff --git a/src/commands/user/track.ts b/src/commands/user/track.ts
index 0e6fafd..da332da 100644
--- a/src/commands/user/track.ts
+++ b/src/commands/user/track.ts
@@ -1,7 +1,7 @@
 import Discord, { CommandInteraction, GuildMember, Message, MessageActionRow, MessageButton } from "discord.js";
 import { SelectMenuOption, SlashCommandSubcommandBuilder } from "@discordjs/builders";
 import { WrappedCheck } from "jshaiku";
-import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../../utils/getEmojiByName.js";
 import addPlural from "../../utils/plurals.js";
 import client from "../../utils/client.js";
@@ -21,12 +21,12 @@
     return "TRACKS.VERTICAL.MIDDLE." + disabled + active
 }
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
     const { renderUser } = client.logger;
     const member = interaction.options.getMember("user") as GuildMember;
     const guild = interaction.guild;
-    let config = await client.database.read(guild.id);
-    await interaction.reply({embeds: [new generateEmojiEmbed()
+    let config = await client.database.guilds.read(guild.id);
+    await interaction.reply({embeds: [new EmojiEmbed()
         .setEmoji("NUCLEUS.LOADING")
         .setTitle("Loading")
         .setStatus("Danger")
@@ -35,9 +35,11 @@
     let generated;
     const roles = await guild.roles.fetch()
     let memberRoles = await member.roles
+    let managed
     while (true) {
         let data = config.tracks[track]
-        let managed = data.manageableBy.some(element => {return memberRoles.cache.has(element)})
+        if (data.manageableBy !== undefined) managed = data.manageableBy.some(element => {return memberRoles.cache.has(element)})
+        else managed = false
         let dropdown = new Discord.MessageSelectMenu().addOptions(config.tracks.map((option, index) => {
             let hasRoleInTrack = option.track.some(element => {return memberRoles.cache.has(element)})
             return new SelectMenuOption({
@@ -94,7 +96,7 @@
         } else {
             currentRoleIndex = selected.length == 0 ? -1 : data.track.indexOf(selected[0].toString())
         }
-        let m = await interaction.editReply({embeds: [new generateEmojiEmbed()
+        let m = await interaction.editReply({embeds: [new EmojiEmbed()
             .setEmoji("TRACKS.ICON")
             .setTitle("Tracks")
             .setDescription(`${generated}`)
@@ -160,16 +162,19 @@
 }
 
 const check = async (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
+    let tracks = (await client.database.guilds.read(interaction.guild.id)).tracks
+    if (!tracks) throw "This server does not have any tracks"
     let member = (interaction.member as GuildMember)
     // Allow the owner to promote anyone
     if (member.id == interaction.guild.ownerId) return true
     // Check if the user can manage any of the tracks
-    // @ts-ignore
-    let tracks = (await client.database.get(interaction.guild.id)).tracks
     let managed = false
-    tracks.forEach(element => { if (element.track.manageableBy.some(role => member.roles.cache.has(role))) managed = true });
+    tracks.forEach(element => {
+        if (!element.track.manageableBy) return
+        if (element.track.manageableBy.some(role => member.roles.cache.has(role))) managed = true
+    });
     // Check if the user has manage_roles permission
-    if (!managed && ! member.permissions.has("MANAGE_ROLES")) throw "You do not have the `manage_roles` permission";
+    if (!managed && ! member.permissions.has("MANAGE_ROLES")) throw "You do not have the Manage roles permission";
     // Allow track
     return true;
 }
diff --git a/src/commands/verify.ts b/src/commands/verify.ts
index c9abb77..4ccc807 100644
--- a/src/commands/verify.ts
+++ b/src/commands/verify.ts
@@ -7,7 +7,7 @@
     .setName("verify")
     .setDescription("Get verified in the server")
 
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
     verify(interaction);
 }
 
diff --git a/src/config/emojis.json b/src/config/emojis.json
index 7fba0e5..b91cdbf 100644
--- a/src/config/emojis.json
+++ b/src/config/emojis.json
@@ -17,16 +17,25 @@
     "ICONS": {
         "ADD": "826823514904330251",
         "REMOVE": "826823515268186152",
+        "EDIT": "989911820267577366",
+        "HISTORY": "989911933069168690",
+        "FILTER": "990242059451514902",
         "OPP": {
             "ADD": "837355918831124500",
             "REMOVE": "837355918420869162"
         },
         "CHANNEL": {
-            "GUILD_TEXT": "752971441351426089",
-            "GUILD_VOICE": "752971441586307091",
+            "GUILD_TEXT": "990209996182679632",
+            "GUILD_TEXT_NSFW": "990216363526221824",
+            "GUILD_VOICE": "990213162697637969",
+            "GUILD_VOICE_NSFW": "990216017244463124",
             "GUILD_STORE": "853668786925469706",
             "GUILD_NEWS": "853668786493063169",
-            "GUILD_STAGE": "853668786842763294"
+            "GUILD_NEWS_NSFW": "990216028300673094",
+            "GUILD_STAGE_VOICE": "853668786842763294",
+            "THREAD_CHANNEL": "990210005108158514",
+            "THREAD_PIPE": "990213168183779348",
+            "RULES": "990213153080115250"
         }
     },
     "CONTROL": {
@@ -81,7 +90,7 @@
         "SLOWMODE": {
             "ON": "777138171301068831",
             "OFF": "777138171447869480",
-            "//TODO": "// TODO"
+            "// TODO": "Make these green and red respectively"
         },
         "NSFW": {
             "ON": "729064531208175736",
diff --git a/src/events/channelCreate.ts b/src/events/channelCreate.ts
index ec788f7..3bde0f2 100644
--- a/src/events/channelCreate.ts
+++ b/src/events/channelCreate.ts
@@ -66,6 +66,6 @@
                 guild: channel.guild.id
             }
         }
-        log(data, channel.client);
+        log(data);
     } catch {}
 }
diff --git a/src/events/channelDelete.ts b/src/events/channelDelete.ts
index e8c888a..2188141 100644
--- a/src/events/channelDelete.ts
+++ b/src/events/channelDelete.ts
@@ -68,6 +68,6 @@
                 guild: channel.guild.id
             }
         }
-        log(data, channel.client);
+        log(data);
     } catch {}
 }
diff --git a/src/events/channelUpdate.ts b/src/events/channelUpdate.ts
index 25b7375..560ca11 100644
--- a/src/events/channelUpdate.ts
+++ b/src/events/channelUpdate.ts
@@ -130,6 +130,6 @@
                 guild: nc.guild.id
             }
         }
-        log(data, client);
+        log(data);
     } catch {}
 }
\ No newline at end of file
diff --git a/src/events/commandError.ts b/src/events/commandError.ts
index ba47426..8edb480 100644
--- a/src/events/commandError.ts
+++ b/src/events/commandError.ts
@@ -1,17 +1,17 @@
-import generateEmojiEmbed from "../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../utils/generateEmojiEmbed.js";
 
 export const event = 'commandError'
 
 export async function callback(client, interaction, error) {
     if (interaction.replied || interaction.deferred) {
-        await interaction.followUp({embeds: [new generateEmojiEmbed()
+        await interaction.followUp({embeds: [new EmojiEmbed()
             .setTitle("Something went wrong")
             .setDescription(error.message ?? error.toString())
             .setStatus("Danger")
             .setEmoji("CONTROL.BLOCKCROSS")
         ], ephemeral: true})
     } else {
-        await interaction.reply({embeds: [new generateEmojiEmbed()
+        await interaction.reply({embeds: [new EmojiEmbed()
             .setTitle("Something went wrong")
             .setDescription(error.message ?? error.toString())
             .setStatus("Danger")
diff --git a/src/events/emojiCreate.ts b/src/events/emojiCreate.ts
index c1ed3c5..1048869 100644
--- a/src/events/emojiCreate.ts
+++ b/src/events/emojiCreate.ts
@@ -25,6 +25,6 @@
                 guild: emoji.guild.id
             }
         }
-        log(data, client);
+        log(data);
     } catch {}
 }
diff --git a/src/events/emojiDelete.ts b/src/events/emojiDelete.ts
index 59bed1e..02bec0d 100644
--- a/src/events/emojiDelete.ts
+++ b/src/events/emojiDelete.ts
@@ -26,6 +26,6 @@
                 guild: emoji.guild.id
             }
         }
-        log(data, client);
+        log(data);
     } catch {}
 }
diff --git a/src/events/emojiUpdate.ts b/src/events/emojiUpdate.ts
index 2171b18..eb39cb9 100644
--- a/src/events/emojiUpdate.ts
+++ b/src/events/emojiUpdate.ts
@@ -32,6 +32,6 @@
                 guild: ne.guild.id
             }
         }
-        log(data, client);
+        log(data);
     } catch {}
 }
\ No newline at end of file
diff --git a/src/events/guildBanAdd.ts b/src/events/guildBanAdd.ts
index 4209788..a1848fd 100644
--- a/src/events/guildBanAdd.ts
+++ b/src/events/guildBanAdd.ts
@@ -11,7 +11,7 @@
         let auditLog = await getAuditLog(ban.guild, 'MEMBER_BAN_ADD')
         let audit = auditLog.entries.filter(entry => entry.target.id == ban.user.id).first();
         if (audit.executor.id == client.user.id) return
-        console.log(ban.reason)
+        try { await client.database.history.create("ban", ban.guild.id, ban.user, audit.executor, audit.reason) } catch {}
         let data = {
             meta: {
                 type: 'memberBan',
@@ -34,6 +34,6 @@
                 guild: ban.guild.id
             }
         }
-        log(data, ban.user.client);
+        log(data);
     } catch {}
 }
diff --git a/src/events/guildBanRemove.ts b/src/events/guildBanRemove.ts
index 11661f7..59fbf7a 100644
--- a/src/events/guildBanRemove.ts
+++ b/src/events/guildBanRemove.ts
@@ -12,6 +12,7 @@
         let auditLog = await getAuditLog(ban.guild, 'MEMBER_BAN_REMOVE')
         let audit = auditLog.entries.filter(entry => entry.target.id == ban.user.id).first();
         if (audit.executor.id == client.user.id) return
+        try { await client.database.history.create("unban", ban.guild.id, ban.user, audit.executor, audit.reason) } catch {}
         let data = {
             meta: {
                 type: 'memberUnban',
@@ -32,6 +33,6 @@
                 guild: ban.guild.id
             }
         }
-        log(data, ban.user.client);
+        log(data);
     } catch (e) {console.log(e)}
 }
diff --git a/src/events/guildCreate.ts b/src/events/guildCreate.ts
index 0222c7c..10986a5 100644
--- a/src/events/guildCreate.ts
+++ b/src/events/guildCreate.ts
@@ -1,5 +1,5 @@
 import { MessageActionRow, MessageButton } from "discord.js";
-import generateEmojiEmbed from "../utils/generateEmojiEmbed.js";
+import EmojiEmbed from "../utils/generateEmojiEmbed.js";
 import getEmojiByName from "../utils/getEmojiByName.js";
 import guide from "../automations/guide.js";
 
diff --git a/src/events/guildMemberUpdate.ts b/src/events/guildMemberUpdate.ts
index a1601bb..2175aaf 100644
--- a/src/events/guildMemberUpdate.ts
+++ b/src/events/guildMemberUpdate.ts
@@ -10,6 +10,9 @@
             let auditLog = await getAuditLog(after.guild, 'MEMBER_UPDATE');
             let audit = auditLog.entries.filter(entry => entry.target.id == after.id).first();
             if (audit.executor.id == client.user.id) return;
+            try { await client.database.history.create(
+                "nickname", after.guild.id, after.user, audit.executor,
+                null, before.nickname || before.user.username, after.nickname || after.user.username) } catch {}
             let data = {
                 meta: {
                     type: 'memberUpdate',
@@ -30,7 +33,7 @@
                     guild: after.guild.id
                 }
             }
-            log(data, after.client);
+            log(data);
         }
     } catch (e) { console.log(e) }
 }
diff --git a/src/events/guildUpdate.ts b/src/events/guildUpdate.ts
index 400cfe4..ee02b66 100644
--- a/src/events/guildUpdate.ts
+++ b/src/events/guildUpdate.ts
@@ -53,6 +53,6 @@
                 guild: after.id
             }
         }
-        log(data, after.client);
+        log(data);
     } catch (e) {}
 }
diff --git a/src/events/inviteCreate.ts b/src/events/inviteCreate.ts
index bdfeede..5081dd1 100644
--- a/src/events/inviteCreate.ts
+++ b/src/events/inviteCreate.ts
@@ -27,6 +27,6 @@
                 guild: invite.guild.id
             }
         }
-        log(data, invite.client);
+        log(data);
     } catch {}
 }
diff --git a/src/events/inviteDelete.ts b/src/events/inviteDelete.ts
index dec234f..b6ddd22 100644
--- a/src/events/inviteDelete.ts
+++ b/src/events/inviteDelete.ts
@@ -27,6 +27,6 @@
                 guild: invite.guild.id
             }
         }
-        log(data, invite.client);
+        log(data);
     } catch {}
 }
diff --git a/src/events/memberJoin.ts b/src/events/memberJoin.ts
index 317cc3a..f3c4d18 100644
--- a/src/events/memberJoin.ts
+++ b/src/events/memberJoin.ts
@@ -1,6 +1,8 @@
 import { callback as statsChannelAdd } from '../automations/statsChannelAdd.js';
 import { callback as welcome } from '../automations/welcome.js';
 import log from '../utils/log.js';
+import client from '../utils/client.js';
+
 export const event = 'guildMemberAdd'
 
 export async function callback(_, member) {
@@ -8,6 +10,7 @@
     try { statsChannelAdd(_, member); } catch {}
     try {
         const { log, NucleusColors, entry, renderUser, renderDelta } = member.client.logger
+        try { await client.database.history.create("join", member.guild.id, member.user, null, null) } catch {}
         let data = {
             meta: {
                 type: 'memberJoin',
@@ -28,6 +31,6 @@
                 guild: member.guild.id
             }
         }
-        log(data, member.client);
+        log(data);
     } catch {}
 }
diff --git a/src/events/memberLeave.ts b/src/events/memberLeave.ts
index 22b7cd3..50901dc 100644
--- a/src/events/memberLeave.ts
+++ b/src/events/memberLeave.ts
@@ -19,6 +19,7 @@
         }
         let data
         if (type == "kick") {
+            try { await client.database.history.create("kick", member.guild.id, member.user, audit.executor, audit.reason) } catch {}
             data = {
                 meta: {
                     type: 'memberKick',
@@ -44,6 +45,7 @@
                 }
             }
         } else {
+            try { await client.database.history.create("leave", member.guild.id, member.user, null, null) } catch {}
             data = {
                 meta: {
                     type: 'memberLeave',
@@ -67,6 +69,6 @@
                 }
             }
         }
-        log(data, member.client);
+        log(data);
     } catch {}
 }
diff --git a/src/events/messageDelete.ts b/src/events/messageDelete.ts
index f0f5e00..229b126 100644
--- a/src/events/messageDelete.ts
+++ b/src/events/messageDelete.ts
@@ -40,6 +40,6 @@
                 guild: message.channel.guild.id
             }
         }
-        log(data, client);
+        log(data);
     } catch {}
 }
diff --git a/src/events/messageEdit.ts b/src/events/messageEdit.ts
index ec713a2..0d42fb9 100644
--- a/src/events/messageEdit.ts
+++ b/src/events/messageEdit.ts
@@ -41,6 +41,6 @@
                 guild: newMessage.channel.guild.id
             }
         }
-        log(data, client);
+        log(data);
     } catch {}
 }
diff --git a/src/events/roleCreate.ts b/src/events/roleCreate.ts
index 2664790..61d0a87 100644
--- a/src/events/roleCreate.ts
+++ b/src/events/roleCreate.ts
@@ -26,6 +26,6 @@
                 guild: role.guild.id
             }
         }
-        log(data, client);
+        log(data);
     } catch {}
 }
diff --git a/src/events/roleDelete.ts b/src/events/roleDelete.ts
index 6edfeed..b0cb0f7 100644
--- a/src/events/roleDelete.ts
+++ b/src/events/roleDelete.ts
@@ -33,6 +33,6 @@
                 guild: role.guild.id
             }
         }
-        log(data, client);
+        log(data);
     } catch {}
 }
diff --git a/src/events/roleUpdate.ts b/src/events/roleUpdate.ts
index faf3237..982d915 100644
--- a/src/events/roleUpdate.ts
+++ b/src/events/roleUpdate.ts
@@ -41,7 +41,7 @@
             hidden: {
                 guild: nr.guild.id
             }
-        }
-        log(data, client);
+        } // TODO: show perms changed
+        log(data);
     } catch {}
 }
\ No newline at end of file
diff --git a/src/events/threadCreate.ts b/src/events/threadCreate.ts
index 77e9dea..5c65d78 100644
--- a/src/events/threadCreate.ts
+++ b/src/events/threadCreate.ts
@@ -29,6 +29,6 @@
                 guild: thread.guild.id
             }
         }
-        log(data, thread.client);
+        log(data);
     } catch {}
 }
diff --git a/src/events/threadDelete.ts b/src/events/threadDelete.ts
index 7bf8537..9507469 100644
--- a/src/events/threadDelete.ts
+++ b/src/events/threadDelete.ts
@@ -31,6 +31,6 @@
             guild: thread.guild.id
         }
     }
-    log(data, thread.client);
+    log(data);
     } catch {}
 }
diff --git a/src/events/threadUpdate.ts b/src/events/threadUpdate.ts
index 4067eba..f554a6c 100644
--- a/src/events/threadUpdate.ts
+++ b/src/events/threadUpdate.ts
@@ -38,6 +38,6 @@
                 guild: after.guild.id
             }
         }
-        log(data, after.client);
+        log(data);
     } catch {}
 }
diff --git a/src/index.ts b/src/index.ts
index ca14cdb..35afc14 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,10 +1,10 @@
 
-import config from './config/main.json' assert {type: 'json'};
 import { Logger } from './utils/log.js';
 import runServer from './api/index.js';
 import Memory from './utils/memory.js';
-import Database from './utils/database.js';
+import { Guilds, History, ModNotes, EventSchedulerDatabase } from './utils/database.js';
 import client from './utils/client.js';
+import EventScheduler from './utils/eventScheduler.js';
 
 await client.registerCommandsIn("./commands");
 await client.registerEventsIn("./events");
@@ -16,6 +16,11 @@
 client.verify = {}
 client.roleMenu = {}
 client.memory = new Memory()
-client.database = await new Database(config.mongoUrl).connect()
+client.database = {
+    guilds: await new Guilds().setup(),
+    history: await new History().setup(),
+    notes: await new ModNotes().setup(),
+    eventScheduler: new EventSchedulerDatabase()
+}
 
 await client.login();
\ No newline at end of file
diff --git a/src/utils/confirmationMessage.ts b/src/utils/confirmationMessage.ts
index dbcd52f..7eaa369 100644
--- a/src/utils/confirmationMessage.ts
+++ b/src/utils/confirmationMessage.ts
@@ -1,5 +1,5 @@
 import Discord, { CommandInteraction, MessageActionRow, Message } from "discord.js";
-import generateEmojiEmbed from "./generateEmojiEmbed.js"
+import EmojiEmbed from "./generateEmojiEmbed.js"
 import getEmojiByName from "./getEmojiByName.js";
 
 class confirmationMessage {
@@ -58,7 +58,7 @@
         while (true) {
             let object = {
                 embeds: [
-                    new generateEmojiEmbed()
+                    new EmojiEmbed()
                         .setEmoji(this.emoji)
                         .setTitle(this.title)
                         .setDescription(this.description)
diff --git a/src/utils/database.ts b/src/utils/database.ts
index 4e37652..66d7e67 100644
--- a/src/utils/database.ts
+++ b/src/utils/database.ts
@@ -1,5 +1,12 @@
-import { Collection, Db, MongoClient } from 'mongodb';
+import Discord from 'discord.js';
+import { Collection, MongoClient } from 'mongodb';
 import structuredClone from '@ungap/structured-clone';
+import config from '../config/main.json' assert {type: 'json'};
+
+
+const mongoClient = new MongoClient(config.mongoUrl);
+await mongoClient.connect()
+const database = mongoClient.db("Nucleus");
 
 
 export const Entry = data => {
@@ -19,21 +26,11 @@
 }
 
 
-export default class Database {
-    mongoClient: MongoClient;
-    database: Db;
+export class Guilds {
     guilds: Collection<GuildConfig>;
     defaultData: GuildConfig;
-
-    constructor(url) {
-        this.mongoClient = new MongoClient(url);
-    }
-
-    async connect() {
-        await this.mongoClient.connect()
-        this.database = this.mongoClient.db("Nucleus");
-        this.guilds = this.database.collection<GuildConfig>("guilds");
-        await this.guilds.createIndex({ id: "text" }, { unique: true });
+    async setup() {
+        this.guilds = database.collection<GuildConfig>("guilds");
         this.defaultData = (await import("../config/default.json", { assert: { type: "json" }})).default as unknown as GuildConfig;
         return this;
     }
@@ -79,6 +76,85 @@
     }
 }
 
+
+export class History {
+    histories: Collection<HistorySchema>;
+    defaultData: GuildConfig;
+
+    async setup() {
+        this.histories = database.collection<HistorySchema>("history");
+        return this;
+    }
+
+    async create(type: string, guild: string, user: Discord.User, moderator: Discord.User | null, reason: string | null, before?: null, after?: null, amount?: null) {
+        await this.histories.insertOne({
+            type: type,
+            guild: guild,
+            user: user.id,
+            moderator: moderator.id,
+            reason: reason,
+            occurredAt: new Date(),
+            before: before,
+            after: after,
+            amount: amount
+        });
+    }
+
+    async read(guild: string, user: string, year: number) {
+        let entry = (await this.histories.find({
+            guild: guild,
+            user: user,
+            occurredAt: {
+                $gte: new Date(year - 1, 11, 31, 23, 59, 59),
+                $lt: new Date(year + 1, 0, 1, 0, 0, 0)
+            }
+        }).toArray()) as HistorySchema[];
+        return entry;
+    }
+}
+
+export class ModNotes {
+    modNotes: Collection<ModNoteSchema>;
+    defaultData: GuildConfig;
+
+    async setup() {
+        this.modNotes = database.collection<ModNoteSchema>("modNotes");
+        return this;
+    }
+
+    async create(guild: string, user: string, note: string | null) {
+        await this.modNotes.updateOne({ guild: guild, user: user }, { $set: { note: note }}, { upsert: true });
+    }
+
+    async read(guild: string, user: string) {
+        let entry = await this.modNotes.findOne({ guild: guild, user: user });
+        return entry?.note ?? null;
+    }
+}
+
+export class EventSchedulerDatabase {
+    events: Collection<EventSchedulerSchema>;
+    defaultData: GuildConfig;
+
+    async setup() {
+        this.events = database.collection<EventSchedulerSchema>("eventScheduler");
+        return this;
+    }
+
+    async create(timestamp: Date, data: object) {
+        await this.events.insertOne({ timestamp: timestamp, data: data});
+    }
+
+    async getNext() {
+        let entry = await this.events.findOne({ timestamp: { $lte: new Date() }});
+        return entry;
+    }
+
+    async remove(timestamp: Date, data: object) {
+        await this.events.deleteOne({ timestamp: timestamp, data: data});
+    }
+}
+
 export interface GuildConfig {
     id: string,
     version: number,
@@ -205,10 +281,33 @@
             max: number,
             options: {
                 name: string,
-                description: string,
+                description: string | null,
                 role: string
             }[]
         }[]
     }
     tags: {}
-};
\ No newline at end of file
+};
+
+export interface HistorySchema {
+    type: string,
+    guild: string,
+    user: string,
+    moderator: string | null,
+    reason: string,
+    occurredAt: Date,
+    before: string | null,
+    after: string | null,
+    amount: string | null
+}
+
+export interface ModNoteSchema {
+    guild: string,
+    user: string,
+    note: string
+}
+
+export interface EventSchedulerSchema {
+    timestamp: Date,
+    data: object
+}
\ No newline at end of file
diff --git a/src/utils/dualCollector.ts b/src/utils/dualCollector.ts
index 902822a..67cef5c 100644
--- a/src/utils/dualCollector.ts
+++ b/src/utils/dualCollector.ts
@@ -1,6 +1,6 @@
 import Discord from 'discord.js';
 import client from './client.js';
-import generateEmojiEmbed from "./generateEmojiEmbed.js";
+import EmojiEmbed from "./generateEmojiEmbed.js";
 
 export default async function (m, interactionFilter, messageFilter) {
     let out;
diff --git a/src/utils/eventScheduler.ts b/src/utils/eventScheduler.ts
new file mode 100644
index 0000000..9210883
--- /dev/null
+++ b/src/utils/eventScheduler.ts
@@ -0,0 +1,37 @@
+import { EventSchedulerDatabase } from './database';
+import client from './client.js';
+
+class EventScheduler {
+    database: any;
+    next: {timestamp: Date, data: object, responded: boolean} | {};
+
+    constructor() {
+        this.database = EventSchedulerDatabase;
+        this.next = {};
+    }
+
+    async create(timestamp: Date, data: object) {
+        await this.database.create(timestamp, data);
+        if (this.next === {}) {
+            this.next = this.next = await this.getNext();
+            return
+        }
+        if (timestamp.getTime() < (this.next as {timestamp: Date}).timestamp.getTime()) {
+            this.next = {timestamp: timestamp, data: data, responded: false};
+        }
+    }
+
+    async getNext() {
+        let entry = await this.database.getNext();
+        if (entry) {
+            this.next = entry;
+        }
+        return this.next;
+    }
+
+    async delete(timestamp: Date, data: object) {
+        await this.database.delete(timestamp, data);
+    } // TODO: add a loop
+}
+
+export default EventScheduler;
\ No newline at end of file
diff --git a/src/utils/log.ts b/src/utils/log.ts
index 19eb2b6..55f8f4c 100644
--- a/src/utils/log.ts
+++ b/src/utils/log.ts
@@ -53,7 +53,7 @@
     }
 
     async log(log: any): Promise<void> {
-        let config = await client.database.read(log.hidden.guild);
+        let config = await client.database.guilds.read(log.hidden.guild);
         if (!config.logging.logs.enabled) return;
         if (!(log.meta.calculateType == true)) {
             if(!toHexArray(config.logging.logs.toLog).includes(log.meta.calculateType)) return console.log('Not logging this type of event');
diff --git a/src/utils/memory.ts b/src/utils/memory.ts
index 7e21fa9..a06705b 100644
--- a/src/utils/memory.ts
+++ b/src/utils/memory.ts
@@ -16,7 +16,7 @@
 
     async readGuildInfo(guild: string): Promise<object> {
         if (!this.memory[guild]) {
-            let guildData = await client.database.read(guild);
+            let guildData = await client.database.guilds.read(guild);
             this.memory[guild] = {
                 lastUpdated: Date.now(),
                 filters: guildData.filters,
diff --git a/src/utils/singleNotify.ts b/src/utils/singleNotify.ts
index a983478..051ec4d 100644
--- a/src/utils/singleNotify.ts
+++ b/src/utils/singleNotify.ts
@@ -1,5 +1,5 @@
 import client from './client.js';
-import generateEmojiEmbed from "./generateEmojiEmbed.js";
+import EmojiEmbed from "./generateEmojiEmbed.js";
 
 let severities = {
     "Critical": "Danger",
@@ -8,14 +8,14 @@
 }
 
 export default async function(type: string, guild: string, message: string, severity: string) {
-    let data = await client.database.read(guild);
+    let data = await client.database.guilds.read(guild);
     if (data.singleEventNotifications[type]) return;
     data.singleEventNotifications[type] = true;
-    client.database.write(guild, data);
+    client.database.guilds.write(guild, data);
     try {
         let channel = await client.channels.fetch(data.logging.staff.channel);
         if (!channel) return;
-        await channel.send({embeds: [new generateEmojiEmbed()
+        await channel.send({embeds: [new EmojiEmbed()
             .setTitle(`${severity} notification`)
             .setDescription(message)
             .setStatus(severities[severity])