summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorTheArcaneBrony <myrainbowdash949@gmail.com>2022-08-27 05:18:48 +0200
committerTheArcaneBrony <myrainbowdash949@gmail.com>2022-09-04 10:48:54 +0200
commit7d936efb2f37db42c3e57ee9a915ed4d5ab8e25f (patch)
tree69d68d640c4ac2946b118591f02de9d3c24fb29b /src
parentAdd sqlite migration for plugin settings (diff)
downloadserver-7d936efb2f37db42c3e57ee9a915ed4d5ab8e25f.tar.xz
Cleanup, reformat, fix some todos, git hook
fixup! Cleanup, reformat, fix some todos, git hook
Diffstat (limited to 'src')
-rw-r--r--src/Server.ts20
-rw-r--r--src/api/Server.ts3
-rw-r--r--src/api/middlewares/ErrorHandler.ts9
-rw-r--r--src/api/middlewares/RateLimit.ts2
-rw-r--r--src/api/middlewares/TestClient.ts9
-rw-r--r--src/api/routes/applications/#id/entitlements.ts2
-rw-r--r--src/api/routes/channels/#channel_id/followers.ts2
-rw-r--r--src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts2
-rw-r--r--src/api/routes/channels/#channel_id/messages/index.ts27
-rw-r--r--src/api/routes/channels/#channel_id/recipients.ts4
-rw-r--r--src/api/routes/discoverable-guilds.ts7
-rw-r--r--src/api/routes/discovery.ts3
-rw-r--r--src/api/routes/experiments.ts2
-rw-r--r--src/api/routes/guilds/#guild_id/discovery-requirements.ts5
-rw-r--r--src/api/routes/guilds/#guild_id/premium.ts2
-rw-r--r--src/api/routes/guilds/#guild_id/regions.ts2
-rw-r--r--src/api/routes/guilds/#guild_id/templates.ts4
-rw-r--r--src/api/routes/guilds/#guild_id/widget.json.ts4
-rw-r--r--src/api/routes/guilds/index.ts5
-rw-r--r--src/api/routes/guilds/templates/index.ts7
-rw-r--r--src/api/routes/outbound-promotions.ts2
-rw-r--r--src/api/routes/partners/#guild_id/requirements.ts5
-rw-r--r--src/api/routes/ping.ts2
-rw-r--r--src/api/routes/science.ts2
-rw-r--r--src/api/routes/track.ts2
-rw-r--r--src/api/routes/users/@me/activities/statistics/applications.ts2
-rw-r--r--src/api/routes/users/@me/affinities/guilds.ts2
-rw-r--r--src/api/routes/users/@me/affinities/users.ts2
-rw-r--r--src/api/routes/users/@me/billing/payment-sources.ts2
-rw-r--r--src/api/routes/users/@me/delete.ts7
-rw-r--r--src/api/routes/users/@me/devices.ts2
-rw-r--r--src/api/routes/users/@me/disable.ts1
-rw-r--r--src/api/routes/users/@me/email-settings.ts2
-rw-r--r--src/api/routes/users/@me/entitlements.ts2
-rw-r--r--src/api/routes/users/@me/guilds/premium/subscription-slots.ts4
-rw-r--r--src/api/routes/users/@me/index.ts1
-rw-r--r--src/api/routes/users/@me/library.ts2
-rw-r--r--src/api/routes/users/@me/mfa/codes.ts3
-rw-r--r--src/api/routes/users/@me/mfa/totp/disable.ts1
-rw-r--r--src/api/routes/users/@me/mfa/totp/enable.ts1
-rw-r--r--src/api/routes/users/@me/relationships.ts6
-rw-r--r--src/api/routes/voice/regions.ts2
-rw-r--r--src/api/util/handlers/Message.ts21
-rw-r--r--src/api/util/handlers/Voice.ts4
-rw-r--r--src/api/util/index.ts8
-rw-r--r--src/api/util/utility/String.ts18
-rw-r--r--src/cdn/Server.ts3
-rw-r--r--src/cdn/util/FileStorage.ts35
-rw-r--r--src/gateway/Server.ts3
-rw-r--r--src/gateway/opcodes/Identify.ts12
-rw-r--r--src/gateway/opcodes/PresenceUpdate.ts2
-rw-r--r--src/gateway/opcodes/VoiceStateUpdate.ts6
-rw-r--r--src/plugins/PluginIndex.ts5
-rw-r--r--src/plugins/example-plugin/TestPlugin.ts52
-rw-r--r--src/plugins/example-plugin/TestSettings.ts14
-rw-r--r--src/plugins/example-plugin/plugin.json14
-rw-r--r--src/start.ts16
-rw-r--r--src/util/config/Config.ts8
-rw-r--r--src/util/entities/Channel.ts4
-rw-r--r--src/util/entities/Guild.ts4
-rw-r--r--src/util/entities/Invite.ts2
-rw-r--r--src/util/entities/PluginConfig.ts2
-rw-r--r--src/util/entities/Session.ts6
-rw-r--r--src/util/entities/User.ts2
-rw-r--r--src/util/entities/VoiceState.ts2
-rw-r--r--src/util/entities/index.ts6
-rw-r--r--src/util/index.ts3
-rw-r--r--src/util/migrations/mariadb/1660404644371-PluginConfigs.ts27
-rw-r--r--src/util/migrations/mariadb/1660534571948-UpdateMigrations.ts135
-rw-r--r--src/util/migrations/postgres/1660404619978-PluginConfigs.ts15
-rw-r--r--src/util/migrations/sqlite/1660534525799-UpdateMigrations.ts91
-rw-r--r--src/util/migrations/sqlite/1660565540177-sync_rebase_15aug2022.ts15
-rw-r--r--src/util/plugin/Plugin.ts210
-rw-r--r--src/util/plugin/PluginConfig.ts35
-rw-r--r--src/util/plugin/PluginEventHandler.ts161
-rw-r--r--src/util/plugin/PluginLoader.ts30
-rw-r--r--src/util/plugin/PluginManifest.ts18
-rw-r--r--src/util/plugin/PluginStore.ts7
-rw-r--r--src/util/plugin/event_types/ChannelCreateEventArgs.ts14
-rw-r--r--src/util/plugin/event_types/GuildCreateEventArgs.ts10
-rw-r--r--src/util/plugin/event_types/LoginEventArgs.ts12
-rw-r--r--src/util/plugin/event_types/MessageEventArgs.ts10
-rw-r--r--src/util/plugin/event_types/PluginLoadedEventArgs.ts4
-rw-r--r--src/util/plugin/event_types/RegisterEventArgs.ts14
-rw-r--r--src/util/plugin/event_types/StatusChangeEventArgs.ts10
-rw-r--r--src/util/plugin/event_types/TypingEventArgs.ts16
-rwxr-xr-xsrc/util/plugin/event_types/_gen.sh4
-rw-r--r--src/util/plugin/event_types/base/EventResult.ts6
-rw-r--r--src/util/plugin/event_types/index.ts2
-rw-r--r--src/util/plugin/index.ts2
-rw-r--r--src/util/schemas/ActivitySchema.ts2
-rw-r--r--src/util/schemas/ChannelPermissionOverwriteSchema.ts2
-rw-r--r--src/util/schemas/MessageCreateSchema.ts2
-rw-r--r--src/util/schemas/RelationshipPutSchema.ts2
-rw-r--r--src/util/schemas/UserSettingsSchema.ts2
-rw-r--r--src/util/schemas/VoiceStateUpdateSchema.ts2
-rw-r--r--src/util/util/Base64.ts (renamed from src/api/util/utility/Base64.ts)0
-rw-r--r--src/util/util/Config.ts1
-rw-r--r--src/util/util/Environment.ts2
-rw-r--r--src/util/util/Logo.ts65
-rw-r--r--src/util/util/Permissions.ts7
-rw-r--r--src/util/util/RandomInviteID.ts (renamed from src/api/util/utility/RandomInviteID.ts)2
-rw-r--r--src/util/util/Rights.ts2
-rw-r--r--src/util/util/String.ts17
-rw-r--r--src/util/util/index.ts5
-rw-r--r--src/util/util/ipAddress.ts (renamed from src/api/util/utility/ipAddress.ts)4
-rw-r--r--src/util/util/passwordStrength.ts (renamed from src/api/util/utility/passwordStrength.ts)2
107 files changed, 717 insertions, 678 deletions
diff --git a/src/Server.ts b/src/Server.ts
index 85de728f..ce7886b9 100644
--- a/src/Server.ts
+++ b/src/Server.ts
@@ -8,7 +8,10 @@ import { Config, getOrInitialiseDatabase } from "@fosscord/util";
 import * as Sentry from "@sentry/node";
 import * as Tracing from "@sentry/tracing";
 import { PluginLoader } from "@fosscord/util";
-import { PluginConfig } from "util/plugin/PluginConfig";
+import express from "express";
+import http from "http";
+import { bold, green, yellow } from "picocolors";
+import { PluginConfig } from "./util/plugin/PluginConfig";
 
 const app = express();
 const server = http.createServer();
@@ -16,11 +19,8 @@ const port = Number(process.env.PORT) || 3001;
 const production = process.env.NODE_ENV == "development" ? false : true;
 server.on("request", app);
 
-// @ts-ignore
 const api = new Api.FosscordServer({ server, port, production, app });
-// @ts-ignore
 const cdn = new CDNServer({ server, port, production, app });
-// @ts-ignore
 const gateway = new Gateway.Server({ server, port, production });
 
 //this is what has been added for the /stop API route
@@ -38,13 +38,13 @@ async function main() {
 	await PluginConfig.init();
 
 	//Sentry
-	if (Config.get().sentry.enabled) {
+	if (cfg.sentry.enabled) {
 		console.log(`[Bundle] ${yellow("You are using Sentry! This may slightly impact performance on large loads!")}`);
 		Sentry.init({
-			dsn: Config.get().sentry.endpoint,
+			dsn: cfg.sentry.endpoint,
 			integrations: [new Sentry.Integrations.Http({ tracing: true }), new Tracing.Integrations.Express({ app })],
-			tracesSampleRate: Config.get().sentry.traceSampleRate,
-			environment: Config.get().sentry.environment
+			tracesSampleRate: cfg.sentry.traceSampleRate,
+			environment: cfg.sentry.environment
 		});
 
 		app.use(Sentry.Handlers.requestHandler());
@@ -54,7 +54,7 @@ async function main() {
 	server.listen(port);
 	await Promise.all([api.start(), cdn.start(), gateway.start()]);
 
-	if (Config.get().sentry.enabled) {
+	if (cfg.sentry.enabled) {
 		app.use(Sentry.Handlers.errorHandler());
 		app.use(function onError(err: any, req: any, res: any, next: any) {
 			res.statusCode = 500;
@@ -63,7 +63,7 @@ async function main() {
 	}
 
 	console.log(`[Server] ${green(`listening on port ${bold(port)}`)}`);
-	await PluginLoader.loadPlugins();
+	PluginLoader.loadPlugins();
 }
 
 main().catch(console.error);
diff --git a/src/api/Server.ts b/src/api/Server.ts
index a3e6f23b..03c68af1 100644
--- a/src/api/Server.ts
+++ b/src/api/Server.ts
@@ -4,6 +4,7 @@ import { Server, ServerOptions } from "lambert-server";
 import morgan from "morgan";
 import path from "path";
 import { red } from "picocolors";
+import { PluginConfig } from "../util";
 import { Authentication, CORS } from "./middlewares/";
 import { BodyParser } from "./middlewares/BodyParser";
 import { ErrorHandler } from "./middlewares/ErrorHandler";
@@ -40,7 +41,7 @@ export class FosscordServer extends Server {
 		await initEvent();
 		await initInstance();
 
-		let logRequests = process.env["LOG_REQUESTS"] != undefined;
+		let logRequests = "LOG_REQUESTS" in process.env;
 		if (logRequests) {
 			this.app.use(
 				morgan("combined", {
diff --git a/src/api/middlewares/ErrorHandler.ts b/src/api/middlewares/ErrorHandler.ts
index a3333be5..3ce1137e 100644
--- a/src/api/middlewares/ErrorHandler.ts
+++ b/src/api/middlewares/ErrorHandler.ts
@@ -9,14 +9,13 @@ export function ErrorHandler(error: Error, req: Request, res: Response, next: Ne
 		let code = 400;
 		let httpcode = code;
 		let message = error?.toString();
-		let errors = undefined;
-		let data = undefined;
+		let errors = null;
+		let data = null;
 
 		if (error instanceof HTTPError && error.code) {
 			code = httpcode = error.code;
-			if(error.data) data = error.data;
-		}
-		else if (error instanceof ApiError) {
+			if (error.data) data = error.data;
+		} else if (error instanceof ApiError) {
 			code = error.code;
 			message = error.message;
 			httpcode = error.httpStatus;
diff --git a/src/api/middlewares/RateLimit.ts b/src/api/middlewares/RateLimit.ts
index dc93dcef..6d4b08b0 100644
--- a/src/api/middlewares/RateLimit.ts
+++ b/src/api/middlewares/RateLimit.ts
@@ -1,6 +1,6 @@
-import { getIpAdress } from "@fosscord/api";
 import { Config, getRights, listenEvent } from "@fosscord/util";
 import { NextFunction, Request, Response, Router } from "express";
+import { getIpAdress } from "..";
 import { API_PREFIX_TRAILING_SLASH } from "./Authentication";
 
 // Docs: https://discord.com/developers/docs/topics/rate-limits
diff --git a/src/api/middlewares/TestClient.ts b/src/api/middlewares/TestClient.ts
index 9090840e..e4daaf25 100644
--- a/src/api/middlewares/TestClient.ts
+++ b/src/api/middlewares/TestClient.ts
@@ -10,6 +10,7 @@ import { patchFile } from "..";
 
 const prettier = require("prettier");
 const AssetsPath = path.join(__dirname, "..", "..", "..", "assets");
+const cfg = Config.get();
 
 export default function TestClient(app: Application) {
 	const agent = new ProxyAgent();
@@ -81,22 +82,22 @@ export default function TestClient(app: Application) {
 		return res.send(fs.readFileSync(assetCacheItem.FilePath));
 	});
 	app.get("/developers*", (_req: Request, res: Response) => {
-		const { useTestClient } = Config.get().client;
 		res.set("Cache-Control", "public, max-age=" + 60 * 60 * 24);
 		res.set("content-type", "text/html");
 
-		if (!useTestClient) return res.send("Test client is disabled on this instance. Use a stand-alone client to connect this instance.");
+		if (!cfg.client.useTestClient)
+			return res.send("Test client is disabled on this instance. Use a stand-alone client to connect this instance.");
 
 		res.send(fs.readFileSync(path.join(__dirname, "..", "..", "..", "assets", "developers.html"), { encoding: "utf8" }));
 	});
 	app.get("*", (req: Request, res: Response) => {
-		const { useTestClient } = Config.get().client;
 		res.set("Cache-Control", "public, max-age=" + 60 * 60 * 24);
 		res.set("content-type", "text/html");
 
 		if (req.url.startsWith("/api") || req.url.startsWith("/__development")) return;
 
-		if (!useTestClient) return res.send("Test client is disabled on this instance. Use a stand-alone client to connect this instance.");
+		if (!cfg.client.useTestClient)
+			return res.send("Test client is disabled on this instance. Use a stand-alone client to connect this instance.");
 		if (req.url.startsWith("/invite")) return res.send(html.replace("9b2b7f0632acd0c5e781", "9f24f709a3de09b67c49"));
 
 		res.send(html);
diff --git a/src/api/routes/applications/#id/entitlements.ts b/src/api/routes/applications/#id/entitlements.ts
index 26054eb0..07b9219d 100644
--- a/src/api/routes/applications/#id/entitlements.ts
+++ b/src/api/routes/applications/#id/entitlements.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express";
 const router = Router();
 
 router.get("/", route({}), (req: Request, res: Response) => {
-	// TODO:
+	// TODO: implement route
 	//const { exclude_consumed } = req.query;
 	res.status(200).send([]);
 });
diff --git a/src/api/routes/channels/#channel_id/followers.ts b/src/api/routes/channels/#channel_id/followers.ts
index c06db61b..d91f4b84 100644
--- a/src/api/routes/channels/#channel_id/followers.ts
+++ b/src/api/routes/channels/#channel_id/followers.ts
@@ -1,6 +1,6 @@
 import { Router } from "express";
 const router: Router = Router();
-// TODO:
+// TODO: implement route
 
 export default router;
 
diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts b/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts
index fbbc65f0..5cdb2ba1 100644
--- a/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts
+++ b/src/api/routes/channels/#channel_id/messages/#message_id/crosspost.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express";
 const router = Router();
 
 router.post("/", route({ permission: "MANAGE_MESSAGES" }), (req: Request, res: Response) => {
-	// TODO:
+	// TODO: implement route
 	res.json({
 		id: "",
 		type: 0,
diff --git a/src/api/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts
index d542ea0f..00008ed4 100644
--- a/src/api/routes/channels/#channel_id/messages/index.ts
+++ b/src/api/routes/channels/#channel_id/messages/index.ts
@@ -12,12 +12,10 @@ import {
 	Message,
 	MessageCreateEvent,
 	MessageCreateSchema,
-	Snowflake,
-	uploadFile,
-	Member,
-	MessageCreateSchema,
 	PluginEventHandler,
-	PreMessageEventArgs
+	PreMessageEventArgs,
+	Snowflake,
+	uploadFile
 } from "@fosscord/util";
 import { Request, Response, Router } from "express";
 import multer from "multer";
@@ -210,8 +208,8 @@ router.post(
 				})
 			);
 		}
-	
-	    //Defining member fields
+
+		//Defining member fields
 		var member = await Member.findOneOrFail({ where: { id: req.user_id }, relations: ["roles", "user"] });
 		// TODO: This doesn't work either
 		// member.roles = member.roles.filter((role) => {
@@ -224,10 +222,17 @@ router.post(
 		// delete message.member.last_message_id;
 		// delete message.member.index;
 
-		let blocks = (await PluginEventHandler.preMessageEvent({
-			message
-		} as PreMessageEventArgs)).filter(x=>x.cancel);
-		if(blocks.length > 0) throw new HTTPError("Message denied.", 400, blocks.filter(x=>x.blockReason).map(x=>x.blockReason));
+		let blocks = (
+			await PluginEventHandler.preMessageEvent({
+				message
+			} as PreMessageEventArgs)
+		).filter((x) => x.cancel);
+		if (blocks.length > 0)
+			throw new HTTPError(
+				"Message denied.",
+				400,
+				blocks.filter((x) => x.blockReason).map((x) => x.blockReason)
+			);
 
 		await Promise.all([
 			message.save(),
diff --git a/src/api/routes/channels/#channel_id/recipients.ts b/src/api/routes/channels/#channel_id/recipients.ts
index 276a0eda..fc6b6b4f 100644
--- a/src/api/routes/channels/#channel_id/recipients.ts
+++ b/src/api/routes/channels/#channel_id/recipients.ts
@@ -26,7 +26,7 @@ router.put("/:user_id", route({}), async (req: Request, res: Response) => {
 		return res.status(201).json(new_channel);
 	} else {
 		if (channel.recipients!.map((r) => r.user_id).includes(user_id)) {
-			throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error?
+			throw DiscordApiErrors.INVALID_RECIPIENT; //TODO: is this the right error?
 		}
 
 		channel.recipients!.push(OrmUtils.mergeDeep(new Recipient(), { channel_id, user_id: user_id }));
@@ -57,7 +57,7 @@ router.delete("/:user_id", route({}), async (req: Request, res: Response) => {
 		throw DiscordApiErrors.MISSING_PERMISSIONS;
 
 	if (!channel.recipients!.map((r) => r.user_id).includes(user_id)) {
-		throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error?
+		throw DiscordApiErrors.INVALID_RECIPIENT; //TODO: is this the right error?
 	}
 
 	await Channel.removeRecipientFromChannel(channel, user_id);
diff --git a/src/api/routes/discoverable-guilds.ts b/src/api/routes/discoverable-guilds.ts
index 2bf49287..3516efd1 100644
--- a/src/api/routes/discoverable-guilds.ts
+++ b/src/api/routes/discoverable-guilds.ts
@@ -7,9 +7,10 @@ import { route } from "..";
 const router = Router();
 
 router.get("/", route({}), async (req: Request, res: Response) => {
+	let cfg = Config.get();
 	const { offset, limit, categories } = req.query;
-	let showAllGuilds = Config.get().guild.discovery.showAllGuilds;
-	let configLimit = Config.get().guild.discovery.limit;
+	let showAllGuilds = cfg.guild.discovery.showAllGuilds;
+	let configLimit = cfg.guild.discovery.limit;
 	// ! this only works using SQL querys
 	// const guilds = await Guild.find({ where: { features: "DISCOVERABLE" } }); //, take: Math.abs(Number(limit)) });
 	let guilds;
@@ -31,7 +32,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
 	res.send({
 		total: total,
 		guilds: guilds,
-		offset: Number(offset || Config.get().guild.discovery.offset),
+		offset: Number(offset || cfg.guild.discovery.offset),
 		limit: Number(limit || configLimit)
 	});
 });
diff --git a/src/api/routes/discovery.ts b/src/api/routes/discovery.ts
index 7b9edd48..dce29ef6 100644
--- a/src/api/routes/discovery.ts
+++ b/src/api/routes/discovery.ts
@@ -5,8 +5,7 @@ import { route } from "..";
 const router = Router();
 
 router.get("/categories", route({}), async (req: Request, res: Response) => {
-	// TODO:
-	// Get locale instead
+	// TODO: Get locale instead
 
 	const { locale, primary_only } = req.query;
 
diff --git a/src/api/routes/experiments.ts b/src/api/routes/experiments.ts
index 0355c631..356d674f 100644
--- a/src/api/routes/experiments.ts
+++ b/src/api/routes/experiments.ts
@@ -4,7 +4,7 @@ import { route } from "..";
 const router = Router();
 
 router.get("/", route({}), (req: Request, res: Response) => {
-	// TODO:
+	// TODO: implement route
 	res.send({ fingerprint: "", assignments: [], guild_experiments: [] });
 });
 
diff --git a/src/api/routes/guilds/#guild_id/discovery-requirements.ts b/src/api/routes/guilds/#guild_id/discovery-requirements.ts
index c0260fe7..b8fdd060 100644
--- a/src/api/routes/guilds/#guild_id/discovery-requirements.ts
+++ b/src/api/routes/guilds/#guild_id/discovery-requirements.ts
@@ -5,9 +5,8 @@ const router = Router();
 
 router.get("/", route({}), async (req: Request, res: Response) => {
 	const { guild_id } = req.params;
-	// TODO:
-	// Load from database
-	// Admin control, but for now it allows anyone to be discoverable
+	// TODO: Load from database
+	// TODO: Admin control, but for now it allows anyone to be discoverable
 
 	res.send({
 		guild_id: guild_id,
diff --git a/src/api/routes/guilds/#guild_id/premium.ts b/src/api/routes/guilds/#guild_id/premium.ts
index b7716378..920811b0 100644
--- a/src/api/routes/guilds/#guild_id/premium.ts
+++ b/src/api/routes/guilds/#guild_id/premium.ts
@@ -3,7 +3,7 @@ import { Request, Response, Router } from "express";
 const router = Router();
 
 router.get("/subscriptions", route({}), async (req: Request, res: Response) => {
-	// TODO:
+	// TODO: implement route
 	res.json([]);
 });
 
diff --git a/src/api/routes/guilds/#guild_id/regions.ts b/src/api/routes/guilds/#guild_id/regions.ts
index aa57ec65..5064ace5 100644
--- a/src/api/routes/guilds/#guild_id/regions.ts
+++ b/src/api/routes/guilds/#guild_id/regions.ts
@@ -7,7 +7,7 @@ const router = Router();
 router.get("/", route({}), async (req: Request, res: Response) => {
 	const { guild_id } = req.params;
 	const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
-	//TODO we should use an enum for guild's features and not hardcoded strings
+	//TODO: we should use an enum for guild's features and not hardcoded strings
 	return res.json(await getVoiceRegions(getIpAdress(req), guild.features.includes("VIP_REGIONS")));
 });
 
diff --git a/src/api/routes/guilds/#guild_id/templates.ts b/src/api/routes/guilds/#guild_id/templates.ts
index 448ee033..af116760 100644
--- a/src/api/routes/guilds/#guild_id/templates.ts
+++ b/src/api/routes/guilds/#guild_id/templates.ts
@@ -1,5 +1,5 @@
-import { generateCode, route } from "@fosscord/api";
-import { Guild, HTTPError, OrmUtils, Template } from "@fosscord/util";
+import { route } from "@fosscord/api";
+import { generateCode, Guild, HTTPError, OrmUtils, Template } from "@fosscord/util";
 import { Request, Response, Router } from "express";
 
 const router: Router = Router();
diff --git a/src/api/routes/guilds/#guild_id/widget.json.ts b/src/api/routes/guilds/#guild_id/widget.json.ts
index 368fe46e..66cc456f 100644
--- a/src/api/routes/guilds/#guild_id/widget.json.ts
+++ b/src/api/routes/guilds/#guild_id/widget.json.ts
@@ -1,5 +1,5 @@
-import { random, route } from "@fosscord/api";
-import { Channel, Guild, HTTPError, Invite, Member, OrmUtils, Permissions } from "@fosscord/util";
+import { route } from "@fosscord/api";
+import { Channel, Guild, HTTPError, Invite, Member, OrmUtils, Permissions, random } from "@fosscord/util";
 import { Request, Response, Router } from "express";
 
 const router: Router = Router();
diff --git a/src/api/routes/guilds/index.ts b/src/api/routes/guilds/index.ts
index 6946e2f7..3d433232 100644
--- a/src/api/routes/guilds/index.ts
+++ b/src/api/routes/guilds/index.ts
@@ -7,9 +7,10 @@ const router: Router = Router();
 //TODO: create default channel
 
 router.post("/", route({ body: "GuildCreateSchema", right: "CREATE_GUILDS" }), async (req: Request, res: Response) => {
+	let cfg = Config.get();
 	const body = req.body as GuildCreateSchema;
 
-	const { maxGuilds } = Config.get().limits.user;
+	const { maxGuilds } = cfg.limits.user;
 	const guild_count = await Member.count({ where: { id: req.user_id } });
 	const rights = await getRights(req.user_id);
 	if (guild_count >= maxGuilds && !rights.has("MANAGE_GUILDS")) {
@@ -18,7 +19,7 @@ router.post("/", route({ body: "GuildCreateSchema", right: "CREATE_GUILDS" }), a
 
 	const guild = await Guild.createGuild({ ...body, owner_id: req.user_id });
 
-	const { autoJoin } = Config.get().guild;
+	const { autoJoin } = cfg.guild;
 	if (autoJoin.enabled && !autoJoin.guilds?.length) {
 		// @ts-ignore
 		await Config.set({ guild: { autoJoin: { guilds: [guild.id] } } });
diff --git a/src/api/routes/guilds/templates/index.ts b/src/api/routes/guilds/templates/index.ts
index 467186a3..bef10d6c 100644
--- a/src/api/routes/guilds/templates/index.ts
+++ b/src/api/routes/guilds/templates/index.ts
@@ -4,8 +4,9 @@ import { Request, Response, Router } from "express";
 import fetch from "node-fetch";
 const router: Router = Router();
 
+let cfg = Config.get();
 router.get("/:code", route({}), async (req: Request, res: Response) => {
-	const { allowDiscordTemplates, allowRaws, enabled } = Config.get().templates;
+	const { allowDiscordTemplates, allowRaws, enabled } = cfg.templates;
 	if (!enabled) res.json({ code: 403, message: "Template creation & usage is disabled on this instance." }).sendStatus(403);
 
 	const { code } = req.params;
@@ -33,14 +34,14 @@ router.get("/:code", route({}), async (req: Request, res: Response) => {
 });
 
 router.post("/:code", route({ body: "GuildTemplateCreateSchema" }), async (req: Request, res: Response) => {
-	const { enabled, allowTemplateCreation, allowDiscordTemplates, allowRaws } = Config.get().templates;
+	const { enabled, allowTemplateCreation, allowDiscordTemplates, allowRaws } = cfg.templates;
 	if (!enabled) return res.json({ code: 403, message: "Template creation & usage is disabled on this instance." }).sendStatus(403);
 	if (!allowTemplateCreation) return res.json({ code: 403, message: "Template creation is disabled on this instance." }).sendStatus(403);
 
 	const { code } = req.params;
 	const body = req.body as GuildTemplateCreateSchema;
 
-	const { maxGuilds } = Config.get().limits.user;
+	const { maxGuilds } = cfg.limits.user;
 
 	const guild_count = await Member.count({ where: { id: req.user_id } });
 	if (guild_count >= maxGuilds) {
diff --git a/src/api/routes/outbound-promotions.ts b/src/api/routes/outbound-promotions.ts
index 8e407184..42378bb2 100644
--- a/src/api/routes/outbound-promotions.ts
+++ b/src/api/routes/outbound-promotions.ts
@@ -1,5 +1,5 @@
-import { route } from "@fosscord/api";
 import { Request, Response, Router } from "express";
+import { route } from "..";
 
 const router: Router = Router();
 
diff --git a/src/api/routes/partners/#guild_id/requirements.ts b/src/api/routes/partners/#guild_id/requirements.ts
index c0260fe7..b8fdd060 100644
--- a/src/api/routes/partners/#guild_id/requirements.ts
+++ b/src/api/routes/partners/#guild_id/requirements.ts
@@ -5,9 +5,8 @@ const router = Router();
 
 router.get("/", route({}), async (req: Request, res: Response) => {
 	const { guild_id } = req.params;
-	// TODO:
-	// Load from database
-	// Admin control, but for now it allows anyone to be discoverable
+	// TODO: Load from database
+	// TODO: Admin control, but for now it allows anyone to be discoverable
 
 	res.send({
 		guild_id: guild_id,
diff --git a/src/api/routes/ping.ts b/src/api/routes/ping.ts
index 5f1b0174..e8b25442 100644
--- a/src/api/routes/ping.ts
+++ b/src/api/routes/ping.ts
@@ -1,6 +1,6 @@
-import { route } from "@fosscord/api";
 import { Config } from "@fosscord/util";
 import { Request, Response, Router } from "express";
+import { route } from "..";
 
 const router = Router();
 
diff --git a/src/api/routes/science.ts b/src/api/routes/science.ts
index cb01e576..a25fc958 100644
--- a/src/api/routes/science.ts
+++ b/src/api/routes/science.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express";
 const router = Router();
 
 router.post("/", route({}), (req: Request, res: Response) => {
-	// TODO:
+	// TODO: implement route?
 	res.sendStatus(204);
 });
 
diff --git a/src/api/routes/track.ts b/src/api/routes/track.ts
index cb01e576..a25fc958 100644
--- a/src/api/routes/track.ts
+++ b/src/api/routes/track.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express";
 const router = Router();
 
 router.post("/", route({}), (req: Request, res: Response) => {
-	// TODO:
+	// TODO: implement route?
 	res.sendStatus(204);
 });
 
diff --git a/src/api/routes/users/@me/activities/statistics/applications.ts b/src/api/routes/users/@me/activities/statistics/applications.ts
index ba359b47..1a3b9906 100644
--- a/src/api/routes/users/@me/activities/statistics/applications.ts
+++ b/src/api/routes/users/@me/activities/statistics/applications.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express";
 const router = Router();
 
 router.get("/", route({}), (req: Request, res: Response) => {
-	// TODO:
+	// TODO: implement route
 	res.json([]).status(200);
 });
 
diff --git a/src/api/routes/users/@me/affinities/guilds.ts b/src/api/routes/users/@me/affinities/guilds.ts
index e733910f..7e1a76c2 100644
--- a/src/api/routes/users/@me/affinities/guilds.ts
+++ b/src/api/routes/users/@me/affinities/guilds.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express";
 const router = Router();
 
 router.get("/", route({}), (req: Request, res: Response) => {
-	// TODO:
+	// TODO: implement route
 	res.status(200).send({ guild_affinities: [] });
 });
 
diff --git a/src/api/routes/users/@me/affinities/users.ts b/src/api/routes/users/@me/affinities/users.ts
index 758bedc3..ead5c564 100644
--- a/src/api/routes/users/@me/affinities/users.ts
+++ b/src/api/routes/users/@me/affinities/users.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express";
 const router = Router();
 
 router.get("/", route({}), (req: Request, res: Response) => {
-	// TODO:
+	// TODO: implement route
 	res.status(200).send({ user_affinities: [], inverse_user_affinities: [] });
 });
 
diff --git a/src/api/routes/users/@me/billing/payment-sources.ts b/src/api/routes/users/@me/billing/payment-sources.ts
index ba359b47..1a3b9906 100644
--- a/src/api/routes/users/@me/billing/payment-sources.ts
+++ b/src/api/routes/users/@me/billing/payment-sources.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express";
 const router = Router();
 
 router.get("/", route({}), (req: Request, res: Response) => {
-	// TODO:
+	// TODO: implement route
 	res.json([]).status(200);
 });
 
diff --git a/src/api/routes/users/@me/delete.ts b/src/api/routes/users/@me/delete.ts
index dfc6131b..c3caf327 100644
--- a/src/api/routes/users/@me/delete.ts
+++ b/src/api/routes/users/@me/delete.ts
@@ -1,5 +1,6 @@
 import { route } from "@fosscord/api";
 import { HTTPError, Member, User } from "@fosscord/util";
+import bcrypt from "bcrypt";
 import { Request, Response, Router } from "express";
 
 let bcrypt: any;
@@ -24,7 +25,11 @@ router.post("/", route({}), async (req: Request, res: Response) => {
 		}
 	}
 
-	// TODO: decrement guild member count
+	(await Member.find({ where: { id: req.user_id }, relations: ["guild"] })).forEach((x) => {
+		let g = x.guild;
+		if (g.member_count) g.member_count--;
+		g.save();
+	});
 
 	if (correctpass) {
 		await Promise.all([User.delete({ id: req.user_id }), Member.delete({ id: req.user_id })]);
diff --git a/src/api/routes/users/@me/devices.ts b/src/api/routes/users/@me/devices.ts
index cb01e576..7c0fd034 100644
--- a/src/api/routes/users/@me/devices.ts
+++ b/src/api/routes/users/@me/devices.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express";
 const router = Router();
 
 router.post("/", route({}), (req: Request, res: Response) => {
-	// TODO:
+	// TODO: implement route
 	res.sendStatus(204);
 });
 
diff --git a/src/api/routes/users/@me/disable.ts b/src/api/routes/users/@me/disable.ts
index 05976908..e47ace91 100644
--- a/src/api/routes/users/@me/disable.ts
+++ b/src/api/routes/users/@me/disable.ts
@@ -1,5 +1,6 @@
 import { route } from "@fosscord/api";
 import { User } from "@fosscord/util";
+import bcrypt from "bcrypt";
 import { Request, Response, Router } from "express";
 
 let bcrypt: any;
diff --git a/src/api/routes/users/@me/email-settings.ts b/src/api/routes/users/@me/email-settings.ts
index 28d0864a..fc248283 100644
--- a/src/api/routes/users/@me/email-settings.ts
+++ b/src/api/routes/users/@me/email-settings.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express";
 const router = Router();
 
 router.get("/", route({}), (req: Request, res: Response) => {
-	// TODO:
+	// TODO: implement route
 	res.json({
 		categories: {
 			social: true,
diff --git a/src/api/routes/users/@me/entitlements.ts b/src/api/routes/users/@me/entitlements.ts
index 7aaa5d7c..2848755a 100644
--- a/src/api/routes/users/@me/entitlements.ts
+++ b/src/api/routes/users/@me/entitlements.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express";
 const router = Router();
 
 router.get("/gifts", route({}), (req: Request, res: Response) => {
-	// TODO:
+	// TODO: implement route
 	res.json([]).status(200);
 });
 
diff --git a/src/api/routes/users/@me/guilds/premium/subscription-slots.ts b/src/api/routes/users/@me/guilds/premium/subscription-slots.ts
index ba359b47..3ce7ac1a 100644
--- a/src/api/routes/users/@me/guilds/premium/subscription-slots.ts
+++ b/src/api/routes/users/@me/guilds/premium/subscription-slots.ts
@@ -1,10 +1,10 @@
-import { route } from "@fosscord/api";
 import { Request, Response, Router } from "express";
+import { route } from "../../../../..";
 
 const router = Router();
 
 router.get("/", route({}), (req: Request, res: Response) => {
-	// TODO:
+	// TODO: implement route
 	res.json([]).status(200);
 });
 
diff --git a/src/api/routes/users/@me/index.ts b/src/api/routes/users/@me/index.ts
index 563300dc..7ee0a178 100644
--- a/src/api/routes/users/@me/index.ts
+++ b/src/api/routes/users/@me/index.ts
@@ -12,6 +12,7 @@ import {
 	UserModifySchema,
 	UserUpdateEvent
 } from "@fosscord/util";
+import bcrypt from "bcrypt";
 import { Request, Response, Router } from "express";
 
 let bcrypt: any;
diff --git a/src/api/routes/users/@me/library.ts b/src/api/routes/users/@me/library.ts
index 0aea02a0..b1a5a53e 100644
--- a/src/api/routes/users/@me/library.ts
+++ b/src/api/routes/users/@me/library.ts
@@ -4,7 +4,7 @@ import { Request, Response, Router } from "express";
 const router = Router();
 
 router.get("/", route({}), (req: Request, res: Response) => {
-	// TODO:
+	// TODO: Add library route
 	res.status(200).send([]);
 });
 
diff --git a/src/api/routes/users/@me/mfa/codes.ts b/src/api/routes/users/@me/mfa/codes.ts
index c62581cc..956ac2ae 100644
--- a/src/api/routes/users/@me/mfa/codes.ts
+++ b/src/api/routes/users/@me/mfa/codes.ts
@@ -1,6 +1,7 @@
-import { route } from "@fosscord/api";
 import { BackupCode, Config, FieldErrors, generateMfaBackupCodes, MfaCodesSchema, User } from "@fosscord/util";
+import bcrypt from "bcrypt";
 import { Request, Response, Router } from "express";
+import { route } from "../../../..";
 
 let bcrypt: any;
 try {
diff --git a/src/api/routes/users/@me/mfa/totp/disable.ts b/src/api/routes/users/@me/mfa/totp/disable.ts
index a53fa816..22f34e06 100644
--- a/src/api/routes/users/@me/mfa/totp/disable.ts
+++ b/src/api/routes/users/@me/mfa/totp/disable.ts
@@ -2,6 +2,7 @@ import { route } from "@fosscord/api";
 import { BackupCode, generateToken, HTTPError, TotpDisableSchema, User } from "@fosscord/util";
 import { Request, Response, Router } from "express";
 import { verifyToken } from "node-2fa";
+import { route } from "../../../../..";
 
 const router = Router();
 
diff --git a/src/api/routes/users/@me/mfa/totp/enable.ts b/src/api/routes/users/@me/mfa/totp/enable.ts
index 0bf1a188..15b2764b 100644
--- a/src/api/routes/users/@me/mfa/totp/enable.ts
+++ b/src/api/routes/users/@me/mfa/totp/enable.ts
@@ -2,6 +2,7 @@ import { route } from "@fosscord/api";
 import { BackupCode, Config, generateMfaBackupCodes, generateToken, HTTPError, TotpEnableSchema, User } from "@fosscord/util";
 import { Request, Response, Router } from "express";
 import { verifyToken } from "node-2fa";
+import { route } from "../../../../..";
 
 let bcrypt: any;
 try {
diff --git a/src/api/routes/users/@me/relationships.ts b/src/api/routes/users/@me/relationships.ts
index 8267c142..1ff6c452 100644
--- a/src/api/routes/users/@me/relationships.ts
+++ b/src/api/routes/users/@me/relationships.ts
@@ -25,7 +25,7 @@ router.get("/", route({}), async (req: Request, res: Response) => {
 		select: ["relationships"]
 	});
 
-	//TODO DTO
+	//TODO: DTO
 	const related_users = user.relationships.map((r) => {
 		return {
 			id: r.to.id,
@@ -181,7 +181,7 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ
 		if (friendRequest.type === RelationshipType.blocked) throw new HTTPError("The user blocked you");
 		if (friendRequest.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user");
 		// accept friend request
-		incoming_relationship = friendRequest as any; //TODO: checkme, any cast
+		incoming_relationship = friendRequest;
 		incoming_relationship.type = RelationshipType.friends;
 	}
 
@@ -189,7 +189,7 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ
 		if (relationship.type === RelationshipType.outgoing) throw new HTTPError("You already sent a friend request");
 		if (relationship.type === RelationshipType.blocked) throw new HTTPError("Unblock the user before sending a friend request");
 		if (relationship.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user");
-		outgoing_relationship = relationship as any; //TODO: checkme, any cast
+		outgoing_relationship = relationship;
 		outgoing_relationship.type = RelationshipType.friends;
 	}
 
diff --git a/src/api/routes/voice/regions.ts b/src/api/routes/voice/regions.ts
index eacdcf11..9745bbe4 100644
--- a/src/api/routes/voice/regions.ts
+++ b/src/api/routes/voice/regions.ts
@@ -1,5 +1,5 @@
-import { getIpAdress, getVoiceRegions, route } from "@fosscord/api";
 import { Request, Response, Router } from "express";
+import { getIpAdress, getVoiceRegions, route } from "../..";
 
 const router: Router = Router();
 
diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts
index 07ed11ad..5237b26a 100644
--- a/src/api/util/handlers/Message.ts
+++ b/src/api/util/handlers/Message.ts
@@ -18,16 +18,11 @@ import {
 	MessageType,
 	MessageUpdateEvent,
 	OrmUtils,
+	PluginEventHandler,
+	PreMessageEventArgs,
 	Role,
 	ROLE_MENTION,
 	User,
-	Application,
-	Webhook,
-	Attachment,
-	Config,
-	MessageCreateSchema,
-	PluginEventHandler,
-	PreMessageEventArgs,
 	USER_MENTION,
 	Webhook
 } from "@fosscord/util";
@@ -212,11 +207,15 @@ export async function postHandleMessage(message: Message) {
 export async function sendMessage(opts: MessageOptions) {
 	const message = await handleMessage({ ...opts, timestamp: new Date() });
 
-	if((await PluginEventHandler.preMessageEvent({
-		message
-	} as PreMessageEventArgs)).filter(x=>x.cancel).length > 0) return;
+	if (
+		(
+			await PluginEventHandler.preMessageEvent({
+				message
+			} as PreMessageEventArgs)
+		).filter((x) => x.cancel).length > 0
+	)
+		return;
 
-	//TODO: check this, removed toJSON call
 	await Promise.all([
 		Message.insert(message),
 		emitEvent({ event: "MESSAGE_CREATE", channel_id: opts.channel_id, data: message } as MessageCreateEvent)
diff --git a/src/api/util/handlers/Voice.ts b/src/api/util/handlers/Voice.ts
index 4d60eb91..624c868a 100644
--- a/src/api/util/handlers/Voice.ts
+++ b/src/api/util/handlers/Voice.ts
@@ -1,5 +1,5 @@
 import { Config } from "@fosscord/util";
-import { distanceBetweenLocations, IPAnalysis } from "../utility/ipAddress";
+import { distanceBetweenLocations, IPAnalysis } from "../../../util/util/ipAddress";
 
 export async function getVoiceRegions(ipAddress: string, vip: boolean) {
 	const regions = Config.get().regions;
@@ -12,7 +12,7 @@ export async function getVoiceRegions(ipAddress: string, vip: boolean) {
 		let min = Number.POSITIVE_INFINITY;
 
 		for (let ar of availableRegions) {
-			//TODO the endpoint location should be saved in the database if not already present to prevent IPAnalysis call
+			//TODO: the endpoint location should be saved in the database if not already present to prevent IPAnalysis call
 			const dist = distanceBetweenLocations(clientIpAnalysis, ar.location || (await IPAnalysis(ar.endpoint)));
 
 			if (dist < min) {
diff --git a/src/api/util/index.ts b/src/api/util/index.ts
index f01c2f43..5180e17c 100644
--- a/src/api/util/index.ts
+++ b/src/api/util/index.ts
@@ -1,12 +1,8 @@
+export * from "../../util/util/Base64";
+export * from "../../util/util/ipAddress";
 export * from "./entities/AssetCacheItem";
 export * from "./handlers/Message";
 export * from "./handlers/route";
 export * from "./handlers/Voice";
-export * from "./utility/Base64";
-export * from "./utility/captcha";
-export * from "./utility/ipAddress";
-export * from "./utility/passwordStrength";
-export * from "./utility/RandomInviteID";
-export * from "./utility/String";
 export * from "./utility/captcha";
 export * from "./TestClientPatcher";
\ No newline at end of file
diff --git a/src/api/util/utility/String.ts b/src/api/util/utility/String.ts
deleted file mode 100644
index a2e491e4..00000000
--- a/src/api/util/utility/String.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { FieldErrors } from "@fosscord/util";
-import { Request } from "express";
-import { ntob } from "./Base64";
-
-export function checkLength(str: string, min: number, max: number, key: string, req: Request) {
-	if (str.length < min || str.length > max) {
-		throw FieldErrors({
-			[key]: {
-				code: "BASE_TYPE_BAD_LENGTH",
-				message: req.t("common:field.BASE_TYPE_BAD_LENGTH", { length: `${min} - ${max}` })
-			}
-		});
-	}
-}
-
-export function generateCode() {
-	return ntob(Date.now() + Math.randomIntBetween(0, 10000));
-}
diff --git a/src/cdn/Server.ts b/src/cdn/Server.ts
index 8b684b53..3729daf9 100644
--- a/src/cdn/Server.ts
+++ b/src/cdn/Server.ts
@@ -2,11 +2,10 @@ import { Config, getOrInitialiseDatabase, registerRoutes } from "@fosscord/util"
 import bodyParser from "body-parser";
 import { Server, ServerOptions } from "lambert-server";
 import path from "path";
+import { PluginConfig } from "../util/plugin/PluginConfig";
 import avatarsRoute from "./routes/avatars";
 import guildProfilesRoute from "./routes/guild-profiles";
 import iconsRoute from "./routes/role-icons";
-import bodyParser from "body-parser";
-import { PluginConfig } from "util/plugin/PluginConfig";
 
 export interface CDNServerOptions extends ServerOptions {}
 
diff --git a/src/cdn/util/FileStorage.ts b/src/cdn/util/FileStorage.ts
index fea013a6..375d23e7 100644
--- a/src/cdn/util/FileStorage.ts
+++ b/src/cdn/util/FileStorage.ts
@@ -1,5 +1,5 @@
 import fs from "fs";
-import { dirname, join } from "path";
+import path, { dirname, join } from "path";
 import { Readable } from "stream";
 import { Storage } from "./Storage";
 //import ExifTransformer = require("exif-be-gone");
@@ -7,44 +7,47 @@ import ExifTransformer from "exif-be-gone";
 
 // TODO: split stored files into separate folders named after cloned route
 
-function getPath(path: string) {
+function getPath(filePath: string) {
 	// STORAGE_LOCATION has a default value in start.ts
 	const root = process.env.STORAGE_LOCATION || "../";
-	let filename = join(root, path);
+	let filename = join(root, filePath);
 
-	if (path.indexOf("\0") !== -1 || !filename.startsWith(root)) throw new Error("invalid path");
+	if (filePath.indexOf("\0") !== -1 || !filename.startsWith(root)) throw new Error("invalid path");
 	return filename;
 }
 
 export class FileStorage implements Storage {
-	async get(path: string): Promise<Buffer | null> {
-		path = getPath(path);
+	async get(filePath: string): Promise<Buffer | null> {
+		filePath = getPath(filePath);
 		try {
-			return fs.readFileSync(path);
+			return fs.readFileSync(filePath);
 		} catch (error) {
 			try {
-				const files = fs.readdirSync(path);
+				const files = fs.readdirSync(filePath);
 				if (!files.length) return null;
-				return fs.readFileSync(join(path, files[0]));
+				return fs.readFileSync(join(filePath, files[0]));
 			} catch (error) {
 				return null;
 			}
 		}
 	}
 
-	async set(path: string, value: any) {
-		path = getPath(path);
+	async set(filePath: string, value: any) {
+		filePath = getPath(filePath);
 		//fse.ensureDirSync(dirname(path));
-		fs.mkdirSync(dirname(path), { recursive: true });
+		fs.mkdirSync(dirname(filePath), { recursive: true });
 
 		value = Readable.from(value);
-		const cleaned_file = fs.createWriteStream(path);
+		const cleaned_file = fs.createWriteStream(filePath);
 
 		return value.pipe(new ExifTransformer()).pipe(cleaned_file);
 	}
 
-	async delete(path: string) {
-		//TODO we should delete the parent directory if empty
-		fs.unlinkSync(getPath(path));
+	async delete(filePath: string) {
+		//TODO: (done?) we should delete the parent directory if empty
+		fs.unlinkSync(getPath(filePath));
+		if (fs.readdirSync(path.dirname(filePath)).length == 0) {
+			fs.rmSync(path.dirname(filePath));
+		}
 	}
 }
diff --git a/src/gateway/Server.ts b/src/gateway/Server.ts
index 60a82d8f..15021118 100644
--- a/src/gateway/Server.ts
+++ b/src/gateway/Server.ts
@@ -2,9 +2,8 @@ import { closeDatabase, Config, getOrInitialiseDatabase, initEvent } from "@foss
 import dotenv from "dotenv";
 import http from "http";
 import ws from "ws";
+import { PluginConfig } from "../util/plugin/PluginConfig";
 import { Connection } from "./events/Connection";
-import http from "http";
-import { PluginConfig } from "util/plugin/PluginConfig";
 dotenv.config();
 
 export class Server {
diff --git a/src/gateway/opcodes/Identify.ts b/src/gateway/opcodes/Identify.ts
index ac6955fd..a2ce9ff5 100644
--- a/src/gateway/opcodes/Identify.ts
+++ b/src/gateway/opcodes/Identify.ts
@@ -77,7 +77,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
 			// TODO: check if status is only one of: online, dnd, offline, idle
 			status: identify.presence?.status || "offline", //does the session always start as online?
 			client_info: {
-				//TODO read from identity
+				//TODO: read from identity
 				client: "desktop",
 				os: identify.properties?.os,
 				version: 0
@@ -147,7 +147,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
 	const channels = recipients.map((x) => {
 		// @ts-ignore
 		x.channel.recipients = x.channel.recipients?.map((x) => x.user);
-		//TODO is this needed? check if users in group dm that are not friends are sent in the READY event
+		//TODO: is this needed? check if users in group dm that are not friends are sent in the READY event
 		users = users.concat(x.channel.recipients as unknown as User[]);
 		if (x.channel.isDm()) {
 			x.channel.recipients = x.channel.recipients!.filter((x) => x.id !== this.user_id);
@@ -274,10 +274,10 @@ export async function onIdentify(this: WebSocket, data: Payload) {
 		d
 	});
 
-	//TODO send READY_SUPPLEMENTAL
-	//TODO send GUILD_MEMBER_LIST_UPDATE
-	//TODO send SESSIONS_REPLACE
-	//TODO send VOICE_STATE_UPDATE to let the client know if another device is already connected to a voice channel
+	//TODO: send READY_SUPPLEMENTAL
+	//TODO: send GUILD_MEMBER_LIST_UPDATE
+	//TODO: send SESSIONS_REPLACE
+	//TODO: send VOICE_STATE_UPDATE to let the client know if another device is already connected to a voice channel
 
 	await setupListener.call(this);
 }
diff --git a/src/gateway/opcodes/PresenceUpdate.ts b/src/gateway/opcodes/PresenceUpdate.ts
index ad712234..5e17bfbc 100644
--- a/src/gateway/opcodes/PresenceUpdate.ts
+++ b/src/gateway/opcodes/PresenceUpdate.ts
@@ -14,7 +14,7 @@ export async function onPresenceUpdate(this: WebSocket, { d }: Payload) {
 		data: {
 			user: await User.getPublicUser(this.user_id),
 			activities: presence.activities,
-			client_status: {}, // TODO:
+			client_status: {}, // TODO: add client status
 			status: presence.status
 		}
 	} as PresenceUpdateEvent);
diff --git a/src/gateway/opcodes/VoiceStateUpdate.ts b/src/gateway/opcodes/VoiceStateUpdate.ts
index 20502584..5fd7cf97 100644
--- a/src/gateway/opcodes/VoiceStateUpdate.ts
+++ b/src/gateway/opcodes/VoiceStateUpdate.ts
@@ -58,9 +58,9 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) {
 		});
 	}
 
-	//TODO the member should only have these properties: hoisted_role, deaf, joined_at, mute, roles, user
-	//TODO the member.user should only have these properties: avatar, discriminator, id, username
-	//TODO this may fail
+	//TODO: the member should only have these properties: hoisted_role, deaf, joined_at, mute, roles, user
+	//TODO: the member.user should only have these properties: avatar, discriminator, id, username
+	//TODO: this may fail
 	voiceState.member = await Member.findOneOrFail({
 		where: { id: voiceState.user_id, guild_id: voiceState.guild_id },
 		relations: ["user", "roles"]
diff --git a/src/plugins/PluginIndex.ts b/src/plugins/PluginIndex.ts
index 502161a1..2688d0bf 100644
--- a/src/plugins/PluginIndex.ts
+++ b/src/plugins/PluginIndex.ts
@@ -1,6 +1,5 @@
-import { Plugin } from "util/plugin";
 import * as example_plugin from "./example-plugin/TestPlugin";
 
 export const PluginIndex: any = {
-    "example-plugin": new example_plugin.default(),
-};
\ No newline at end of file
+	"example-plugin": new example_plugin.default()
+};
diff --git a/src/plugins/example-plugin/TestPlugin.ts b/src/plugins/example-plugin/TestPlugin.ts
index 18e634f7..da25c474 100644
--- a/src/plugins/example-plugin/TestPlugin.ts
+++ b/src/plugins/example-plugin/TestPlugin.ts
@@ -1,26 +1,36 @@
-import { setupListener } from "@fosscord/gateway";
-import { Channel, Guild, Plugin, PluginLoadedEventArgs, PluginLoader, PluginManifest, PreMessageEventArgs, PreMessageEventResult } from "@fosscord/util";
+import {
+	Channel,
+	Guild,
+	Plugin,
+	PluginLoadedEventArgs,
+	PluginLoader,
+	PluginManifest,
+	PreMessageEventArgs,
+	PreMessageEventResult
+} from "@fosscord/util";
 import { TestSettings } from "./TestSettings";
 
 export default class TestPlugin implements Plugin {
-    pluginManifest?: PluginManifest | undefined;
-    settings: TestSettings = new TestSettings();
-    async onPluginLoaded(env: PluginLoadedEventArgs) {
-        console.log("Test plugin active!");
-        if(this.pluginManifest) this.settings = PluginLoader.getPluginConfig(this.pluginManifest.id, this.settings) as TestSettings;
-    }
-    async onPreMessage(data: PreMessageEventArgs): Promise<PreMessageEventResult> {
-        let channel = await Channel.findOne({ where: { id: data.message.channel_id } });
-        let guild = await Guild.findOne({ where: { id: data.message.guild_id } });
-        let block = data.message.content?.includes('UwU');
-        
-        let result = {cancel: block} as PreMessageEventResult;
+	pluginManifest?: PluginManifest | undefined;
+	settings: TestSettings = new TestSettings();
+	async onPluginLoaded(env: PluginLoadedEventArgs) {
+		console.log("Test plugin active!");
+		if (this.pluginManifest) this.settings = PluginLoader.getPluginConfig(this.pluginManifest.id, this.settings) as TestSettings;
+	}
+	async onPreMessage(data: PreMessageEventArgs): Promise<PreMessageEventResult> {
+		let channel = await Channel.findOne({ where: { id: data.message.channel_id } });
+		let guild = await Guild.findOne({ where: { id: data.message.guild_id } });
+		let block = data.message.content?.includes("UwU");
 
-        if(block) {
-            console.log(`[TestPlugin] Blocked message in ${guild?.name}/#${channel?.name} by ${data.message.author?.username}: ${data.message.content}`);
-            result.blockReason = "[TestPlugin] Your message contains UwU! Get bamboozled!";
-        }
+		let result = { cancel: block } as PreMessageEventResult;
 
-        return result;
-    }
-}
\ No newline at end of file
+		if (block) {
+			console.log(
+				`[TestPlugin] Blocked message in ${guild?.name}/#${channel?.name} by ${data.message.author?.username}: ${data.message.content}`
+			);
+			result.blockReason = "[TestPlugin] Your message contains UwU! Get bamboozled!";
+		}
+
+		return result;
+	}
+}
diff --git a/src/plugins/example-plugin/TestSettings.ts b/src/plugins/example-plugin/TestSettings.ts
index d8c52187..f7ec79ff 100644
--- a/src/plugins/example-plugin/TestSettings.ts
+++ b/src/plugins/example-plugin/TestSettings.ts
@@ -1,11 +1,11 @@
 export class TestSettings {
-    someInt: number = 10;
-    someStr: string = "asdf";
-    someBool: boolean = true;
-    someDate: Date = new Date();
-    subSettings: SubSettings = new SubSettings();
+	someInt: number = 10;
+	someStr: string = "asdf";
+	someBool: boolean = true;
+	someDate: Date = new Date();
+	subSettings: SubSettings = new SubSettings();
 }
 
 export class SubSettings {
-    someStr: string = "jklm";
-}
\ No newline at end of file
+	someStr: string = "jklm";
+}
diff --git a/src/plugins/example-plugin/plugin.json b/src/plugins/example-plugin/plugin.json
index f6c1b7ff..4db01152 100644
--- a/src/plugins/example-plugin/plugin.json
+++ b/src/plugins/example-plugin/plugin.json
@@ -1,10 +1,8 @@
 {
-    "id": "example-plugin",
-    "name": "Fosscord example plugin",
-    "authors": [
-        "The Arcane Brony"
-    ],
-    "repository": "https://github.com/fosscord/fosscord-server",
-    "license": "",
-    "mainClass": "TestPlugin"
+	"id": "example-plugin",
+	"name": "Fosscord example plugin",
+	"authors": ["The Arcane Brony"],
+	"repository": "https://github.com/fosscord/fosscord-server",
+	"license": "",
+	"mainClass": "TestPlugin"
 }
diff --git a/src/start.ts b/src/start.ts
index 94cf864e..047b3cf6 100644
--- a/src/start.ts
+++ b/src/start.ts
@@ -6,9 +6,8 @@ import os from "os";
 import { bold, cyan, red, yellow } from "picocolors";
 import "reflect-metadata";
 import { initStats } from "./stats";
-config();
-import { execSync } from "child_process";
 import { Logo } from "./util";
+config();
 
 // TODO: add socket event transmission
 let cores = 1;
@@ -27,15 +26,10 @@ if (cluster.isMaster) {
 		}
 	}
 	const commit = getCommitOrFail();
-Logo.printLogo();
-console.log(bold(`
-		fosscord-server | ${yellow(
-			`Pre-release (${
-				commit !== null
-					? commit.slice(0, 7)
-					: "Unknown (Git cannot be found)"
-			})`
-		)}
+	Logo.printLogo();
+	console.log(
+		bold(`
+		fosscord-server | ${yellow(`Pre-release (${commit !== null ? commit.slice(0, 7) : "Unknown (Git cannot be found)"})`)}
 
 Commit Hash: ${commit !== null ? `${cyan(commit)} (${yellow(commit.slice(0, 7))})` : "Unknown (Git cannot be found)"}
 Cores: ${cyan(os.cpus().length)} (Using ${cores} thread(s).)
diff --git a/src/util/config/Config.ts b/src/util/config/Config.ts
index 36c4509d..562d589a 100644
--- a/src/util/config/Config.ts
+++ b/src/util/config/Config.ts
@@ -20,12 +20,12 @@ import {
 
 export class ConfigValue {
 	gateway: EndpointConfiguration = {
-		endpointPublic: '${location.protocol === "https:" ? "wss://" : "ws://"}${location.host}',
-		endpointPrivate: `ws://localhost:3001`
+		endpointPrivate: `ws://localhost:3001`,
+		endpointPublic: '${location.protocol === "https:" ? "wss://" : "ws://"}${location.host}'
 	};
 	cdn: EndpointConfiguration = {
-		endpointPublic: "${location.host}",
-		endpointPrivate: `http://localhost:3001`
+		endpointPrivate: `http://localhost:3001`,
+		endpointPublic: "${location.host}"
 	};
 	api: ApiConfiguration = new ApiConfiguration();
 	general: GeneralConfiguration = new GeneralConfiguration();
diff --git a/src/util/entities/Channel.ts b/src/util/entities/Channel.ts
index b17fdba0..c803b1b2 100644
--- a/src/util/entities/Channel.ts
+++ b/src/util/entities/Channel.ts
@@ -359,8 +359,8 @@ export class Channel extends BaseClass {
 	}
 
 	static async deleteChannel(channel: Channel) {
-		await Message.delete({ channel_id: channel.id }); //TODO we should also delete the attachments from the cdn but to do that we need to move cdn.ts in util
-		//TODO before deleting the channel we should check and delete other relations
+		await Message.delete({ channel_id: channel.id }); //TODO: we should also delete the attachments from the cdn but to do that we need to move cdn.ts in util
+		//TODO: before deleting the channel we should check and delete other relations
 		await Channel.delete({ id: channel.id });
 	}
 
diff --git a/src/util/entities/Guild.ts b/src/util/entities/Guild.ts
index cd7fa561..9edd3753 100644
--- a/src/util/entities/Guild.ts
+++ b/src/util/entities/Guild.ts
@@ -18,7 +18,7 @@ import { Webhook } from "./Webhook";
 // TODO: guild_scheduled_events
 // TODO: stage_instances
 // TODO: threads
-// TODO:
+// TODO: implement keywords
 // "keywords": [
 // 		"Genshin Impact",
 // 		"Paimon",
@@ -75,7 +75,7 @@ export class Guild extends BaseClass {
 	explicit_content_filter?: number = Config.get().defaults.guild.explicitContentFilter;
 
 	@Column({ type: "simple-array" })
-	features: string[]; //TODO use enum
+	features: string[]; //TODO: use enum
 	//TODO: https://discord.com/developers/docs/resources/guild#guild-object-guild-features
 
 	@Column({ nullable: true })
diff --git a/src/util/entities/Invite.ts b/src/util/entities/Invite.ts
index f6ba85d7..ccb0099a 100644
--- a/src/util/entities/Invite.ts
+++ b/src/util/entities/Invite.ts
@@ -1,5 +1,5 @@
-import { random } from "@fosscord/api";
 import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn, RelationId } from "typeorm";
+import { random } from "..";
 import { BaseClassWithoutId } from "./BaseClass";
 import { Channel } from "./Channel";
 import { Guild } from "./Guild";
diff --git a/src/util/entities/PluginConfig.ts b/src/util/entities/PluginConfig.ts
index 87de5167..2fb0c0c2 100644
--- a/src/util/entities/PluginConfig.ts
+++ b/src/util/entities/PluginConfig.ts
@@ -8,4 +8,4 @@ export class PluginConfigEntity extends BaseClassWithoutId {
 
 	@Column({ type: "simple-json", nullable: true })
 	value: number | boolean | null | string | Date | undefined;
-}
\ No newline at end of file
+}
diff --git a/src/util/entities/Session.ts b/src/util/entities/Session.ts
index 0cb4c309..43945466 100644
--- a/src/util/entities/Session.ts
+++ b/src/util/entities/Session.ts
@@ -4,7 +4,7 @@ import { Status } from "../interfaces/Status";
 import { BaseClass } from "./BaseClass";
 import { User } from "./User";
 
-//TODO we need to remove all sessions on server start because if the server crashes without closing websockets it won't delete them
+//TODO: we need to remove all sessions on server start because if the server crashes without closing websockets it won't delete them
 
 @Entity("sessions")
 export class Session extends BaseClass {
@@ -18,7 +18,7 @@ export class Session extends BaseClass {
 	})
 	user: User;
 
-	//TODO check, should be 32 char long hex string
+	//TODO: check, should be 32 char long hex string
 	@Column({ nullable: false, select: false })
 	session_id: string;
 
@@ -34,7 +34,7 @@ export class Session extends BaseClass {
 	};
 
 	@Column({ nullable: false, type: "varchar" })
-	status: Status; //TODO enum
+	status: Status; //TODO: enum
 }
 
 export const PrivateSessionProjection: (keyof Session)[] = ["user_id", "session_id", "activities", "client_info", "status"];
diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts
index 57afb132..21ed14f4 100644
--- a/src/util/entities/User.ts
+++ b/src/util/entities/User.ts
@@ -250,7 +250,7 @@ export class User extends BaseClass {
 	 * 		date_of_birth,
 	 * 		req,
 	 * 	}
-	 * @return {*} 
+	 * @return {*}
 	 * @memberof User
 	 */
 	static async register({
diff --git a/src/util/entities/VoiceState.ts b/src/util/entities/VoiceState.ts
index baf2c687..23cab248 100644
--- a/src/util/entities/VoiceState.ts
+++ b/src/util/entities/VoiceState.ts
@@ -42,7 +42,7 @@ export class VoiceState extends BaseClass {
 	// @ManyToOne(() => Member, {
 	// 	onDelete: "CASCADE",
 	// })
-	//TODO find a way to make it work without breaking Guild.voice_states
+	//TODO: find a way to make it work without breaking Guild.voice_states
 	member: Member;
 
 	@Column()
diff --git a/src/util/entities/index.ts b/src/util/entities/index.ts
index 444a7e49..d2820c58 100644
--- a/src/util/entities/index.ts
+++ b/src/util/entities/index.ts
@@ -16,6 +16,7 @@ export * from "./Member";
 export * from "./Message";
 export * from "./Migration";
 export * from "./Note";
+export * from "./PluginConfig";
 export * from "./RateLimit";
 export * from "./ReadState";
 export * from "./Recipient";
@@ -31,8 +32,3 @@ export * from "./User";
 export * from "./UserSettings";
 export * from "./VoiceState";
 export * from "./Webhook";
-export * from "./ClientRelease";
-export * from "./BackupCodes";
-export * from "./Note";
-export * from "./UserSettings";
-export * from "./PluginConfig";
diff --git a/src/util/index.ts b/src/util/index.ts
index 0cf30a71..b8707c3e 100644
--- a/src/util/index.ts
+++ b/src/util/index.ts
@@ -4,8 +4,7 @@ export * from "./config/index";
 export * from "./dtos/index";
 export * from "./entities/index";
 export * from "./interfaces/index";
+export * from "./plugin";
 export * from "./schemas";
 export * from "./util/index";
 export * from "./util/MFA";
-export * from "./schemas";
-export * from "./plugin";
\ No newline at end of file
diff --git a/src/util/migrations/mariadb/1660404644371-PluginConfigs.ts b/src/util/migrations/mariadb/1660404644371-PluginConfigs.ts
index 73953ca8..6cbc594c 100644
--- a/src/util/migrations/mariadb/1660404644371-PluginConfigs.ts
+++ b/src/util/migrations/mariadb/1660404644371-PluginConfigs.ts
@@ -1,42 +1,41 @@
 import { MigrationInterface, QueryRunner } from "typeorm";
 
 export class PluginConfigs1660404644371 implements MigrationInterface {
-    name = 'PluginConfigs1660404644371'
+	name = "PluginConfigs1660404644371";
 
-    public async up(queryRunner: QueryRunner): Promise<void> {
-        await queryRunner.query(`
+	public async up(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(`
             DROP INDEX \`IDX_76ba283779c8441fd5ff819c8c\` ON \`users\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             CREATE TABLE \`plugin_config\` (
                 \`key\` varchar(255) NOT NULL,
                 \`value\` text NULL,
                 PRIMARY KEY (\`key\`)
             ) ENGINE = InnoDB
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`channels\`
             ADD \`flags\` int NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`channels\`
             ADD \`default_thread_rate_limit_per_user\` int NULL
         `);
-    }
+	}
 
-    public async down(queryRunner: QueryRunner): Promise<void> {
-        await queryRunner.query(`
+	public async down(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(`
             ALTER TABLE \`channels\` DROP COLUMN \`default_thread_rate_limit_per_user\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`channels\` DROP COLUMN \`flags\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             DROP TABLE \`plugin_config\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             CREATE UNIQUE INDEX \`IDX_76ba283779c8441fd5ff819c8c\` ON \`users\` (\`settingsId\`)
         `);
-    }
-
+	}
 }
diff --git a/src/util/migrations/mariadb/1660534571948-UpdateMigrations.ts b/src/util/migrations/mariadb/1660534571948-UpdateMigrations.ts
index d799fe80..eee8c39c 100644
--- a/src/util/migrations/mariadb/1660534571948-UpdateMigrations.ts
+++ b/src/util/migrations/mariadb/1660534571948-UpdateMigrations.ts
@@ -1,229 +1,228 @@
 import { MigrationInterface, QueryRunner } from "typeorm";
 
 export class UpdateMigrations1660534571948 implements MigrationInterface {
-    name = 'UpdateMigrations1660534571948'
+	name = "UpdateMigrations1660534571948";
 
-    public async up(queryRunner: QueryRunner): Promise<void> {
-        await queryRunner.query(`
+	public async up(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP FOREIGN KEY \`FK_e5bf78cdbbe9ba91062d74c5aba\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`invites\` DROP FOREIGN KEY \`FK_15c35422032e0b22b4ada95f48f\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             DROP INDEX \`IDX_76ba283779c8441fd5ff819c8c\` ON \`users\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             CREATE TABLE \`plugin_config\` (
                 \`key\` varchar(255) NOT NULL,
                 \`value\` text NULL,
                 PRIMARY KEY (\`key\`)
             ) ENGINE = InnoDB
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`rpc_origins\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`primary_sku_id\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`slug\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`guild_id\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`type\` text NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`hook\` tinyint NOT NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`redirect_uris\` text NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`rpc_application_state\` int NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`store_application_state\` int NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`verification_state\` int NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`interactions_endpoint_url\` varchar(255) NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`integration_public\` tinyint NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`integration_require_code_grant\` tinyint NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`discoverability_state\` int NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`discovery_eligibility_flags\` int NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`tags\` text NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`install_params\` text NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`bot_user_id\` varchar(255) NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD UNIQUE INDEX \`IDX_2ce5a55796fe4c2f77ece57a64\` (\`bot_user_id\`)
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`channels\`
             ADD \`flags\` int NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`channels\`
             ADD \`default_thread_rate_limit_per_user\` int NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` CHANGE \`description\` \`description\` varchar(255) NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`flags\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`flags\` int NOT NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             CREATE UNIQUE INDEX \`REL_2ce5a55796fe4c2f77ece57a64\` ON \`applications\` (\`bot_user_id\`)
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD CONSTRAINT \`FK_2ce5a55796fe4c2f77ece57a647\` FOREIGN KEY (\`bot_user_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`invites\`
             ADD CONSTRAINT \`FK_15c35422032e0b22b4ada95f48f\` FOREIGN KEY (\`inviter_id\`) REFERENCES \`users\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
         `);
-    }
+	}
 
-    public async down(queryRunner: QueryRunner): Promise<void> {
-        await queryRunner.query(`
+	public async down(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(`
             ALTER TABLE \`invites\` DROP FOREIGN KEY \`FK_15c35422032e0b22b4ada95f48f\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP FOREIGN KEY \`FK_2ce5a55796fe4c2f77ece57a647\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             DROP INDEX \`REL_2ce5a55796fe4c2f77ece57a64\` ON \`applications\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`flags\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`flags\` varchar(255) NOT NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` CHANGE \`description\` \`description\` varchar(255) NOT NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`channels\` DROP COLUMN \`default_thread_rate_limit_per_user\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`channels\` DROP COLUMN \`flags\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP INDEX \`IDX_2ce5a55796fe4c2f77ece57a64\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`bot_user_id\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`install_params\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`tags\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`discovery_eligibility_flags\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`discoverability_state\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`integration_require_code_grant\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`integration_public\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`interactions_endpoint_url\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`verification_state\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`store_application_state\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`rpc_application_state\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`redirect_uris\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`hook\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\` DROP COLUMN \`type\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`guild_id\` varchar(255) NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`slug\` varchar(255) NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`primary_sku_id\` varchar(255) NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD \`rpc_origins\` text NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             DROP TABLE \`plugin_config\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             CREATE UNIQUE INDEX \`IDX_76ba283779c8441fd5ff819c8c\` ON \`users\` (\`settingsId\`)
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`invites\`
             ADD CONSTRAINT \`FK_15c35422032e0b22b4ada95f48f\` FOREIGN KEY (\`inviter_id\`) REFERENCES \`users\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`applications\`
             ADD CONSTRAINT \`FK_e5bf78cdbbe9ba91062d74c5aba\` FOREIGN KEY (\`guild_id\`) REFERENCES \`guilds\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION
         `);
-    }
-
+	}
 }
diff --git a/src/util/migrations/postgres/1660404619978-PluginConfigs.ts b/src/util/migrations/postgres/1660404619978-PluginConfigs.ts
index d8a5ab4d..21d4757c 100644
--- a/src/util/migrations/postgres/1660404619978-PluginConfigs.ts
+++ b/src/util/migrations/postgres/1660404619978-PluginConfigs.ts
@@ -1,22 +1,21 @@
 import { MigrationInterface, QueryRunner } from "typeorm";
 
 export class PluginConfigs1660404619978 implements MigrationInterface {
-    name = 'PluginConfigs1660404619978'
+	name = "PluginConfigs1660404619978";
 
-    public async up(queryRunner: QueryRunner): Promise<void> {
-        await queryRunner.query(`
+	public async up(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(`
             CREATE TABLE "plugin_config" (
                 "key" character varying NOT NULL,
                 "value" text,
                 CONSTRAINT "PK_aa929ece56c59233b85a16f62ef" PRIMARY KEY ("key")
             )
         `);
-    }
+	}
 
-    public async down(queryRunner: QueryRunner): Promise<void> {
-        await queryRunner.query(`
+	public async down(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(`
             DROP TABLE "plugin_config"
         `);
-    }
-
+	}
 }
diff --git a/src/util/migrations/sqlite/1660534525799-UpdateMigrations.ts b/src/util/migrations/sqlite/1660534525799-UpdateMigrations.ts
index 54a59fab..8f5e364b 100644
--- a/src/util/migrations/sqlite/1660534525799-UpdateMigrations.ts
+++ b/src/util/migrations/sqlite/1660534525799-UpdateMigrations.ts
@@ -1,10 +1,10 @@
 import { MigrationInterface, QueryRunner } from "typeorm";
 
 export class UpdateMigrations1660534525799 implements MigrationInterface {
-    name = 'UpdateMigrations1660534525799'
+	name = "UpdateMigrations1660534525799";
 
-    public async up(queryRunner: QueryRunner): Promise<void> {
-        await queryRunner.query(`
+	public async up(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(`
             CREATE TABLE "temporary_applications" (
                 "id" varchar PRIMARY KEY NOT NULL,
                 "name" varchar NOT NULL,
@@ -28,7 +28,7 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
             )
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             INSERT INTO "temporary_applications"(
                     "id",
                     "name",
@@ -69,14 +69,14 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 "guild_id"
             FROM "applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             DROP TABLE "applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE "temporary_applications"
                 RENAME TO "applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             CREATE TABLE "temporary_applications" (
                 "id" varchar PRIMARY KEY NOT NULL,
                 "name" varchar NOT NULL,
@@ -96,7 +96,7 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
             )
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             INSERT INTO "temporary_applications"(
                     "id",
                     "name",
@@ -129,14 +129,14 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 "team_id"
             FROM "applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             DROP TABLE "applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE "temporary_applications"
                 RENAME TO "applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             CREATE TABLE "temporary_applications" (
                 "id" varchar PRIMARY KEY NOT NULL,
                 "name" varchar NOT NULL,
@@ -171,7 +171,7 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
             )
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             INSERT INTO "temporary_applications"(
                     "id",
                     "name",
@@ -204,14 +204,14 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 "team_id"
             FROM "applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             DROP TABLE "applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE "temporary_applications"
                 RENAME TO "applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             CREATE TABLE "temporary_applications" (
                 "id" varchar PRIMARY KEY NOT NULL,
                 "name" varchar NOT NULL,
@@ -246,7 +246,7 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
             )
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             INSERT INTO "temporary_applications"(
                     "id",
                     "name",
@@ -307,14 +307,14 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 "bot_user_id"
             FROM "applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             DROP TABLE "applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE "temporary_applications"
                 RENAME TO "applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             CREATE TABLE "temporary_applications" (
                 "id" varchar PRIMARY KEY NOT NULL,
                 "name" varchar NOT NULL,
@@ -350,7 +350,7 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 CONSTRAINT "FK_2ce5a55796fe4c2f77ece57a647" FOREIGN KEY ("bot_user_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
             )
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             INSERT INTO "temporary_applications"(
                     "id",
                     "name",
@@ -411,21 +411,21 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 "bot_user_id"
             FROM "applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             DROP TABLE "applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE "temporary_applications"
                 RENAME TO "applications"
         `);
-    }
+	}
 
-    public async down(queryRunner: QueryRunner): Promise<void> {
-        await queryRunner.query(`
+	public async down(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(`
             ALTER TABLE "applications"
                 RENAME TO "temporary_applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             CREATE TABLE "applications" (
                 "id" varchar PRIMARY KEY NOT NULL,
                 "name" varchar NOT NULL,
@@ -460,7 +460,7 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
             )
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             INSERT INTO "applications"(
                     "id",
                     "name",
@@ -521,14 +521,14 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 "bot_user_id"
             FROM "temporary_applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             DROP TABLE "temporary_applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE "applications"
                 RENAME TO "temporary_applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             CREATE TABLE "applications" (
                 "id" varchar PRIMARY KEY NOT NULL,
                 "name" varchar NOT NULL,
@@ -563,7 +563,7 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
             )
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             INSERT INTO "applications"(
                     "id",
                     "name",
@@ -624,14 +624,14 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 "bot_user_id"
             FROM "temporary_applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             DROP TABLE "temporary_applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE "applications"
                 RENAME TO "temporary_applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             CREATE TABLE "applications" (
                 "id" varchar PRIMARY KEY NOT NULL,
                 "name" varchar NOT NULL,
@@ -651,7 +651,7 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
             )
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             INSERT INTO "applications"(
                     "id",
                     "name",
@@ -684,14 +684,14 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 "team_id"
             FROM "temporary_applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             DROP TABLE "temporary_applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE "applications"
                 RENAME TO "temporary_applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             CREATE TABLE "applications" (
                 "id" varchar PRIMARY KEY NOT NULL,
                 "name" varchar NOT NULL,
@@ -715,7 +715,7 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
             )
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             INSERT INTO "applications"(
                     "id",
                     "name",
@@ -748,14 +748,14 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 "team_id"
             FROM "temporary_applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             DROP TABLE "temporary_applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE "applications"
                 RENAME TO "temporary_applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             CREATE TABLE "applications" (
                 "id" varchar PRIMARY KEY NOT NULL,
                 "name" varchar NOT NULL,
@@ -780,7 +780,7 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 CONSTRAINT "FK_e57508958bf92b9d9d25231b5e8" FOREIGN KEY ("owner_id") REFERENCES "users" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION
             )
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             INSERT INTO "applications"(
                     "id",
                     "name",
@@ -821,9 +821,8 @@ export class UpdateMigrations1660534525799 implements MigrationInterface {
                 "guild_id"
             FROM "temporary_applications"
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             DROP TABLE "temporary_applications"
         `);
-    }
-
+	}
 }
diff --git a/src/util/migrations/sqlite/1660565540177-sync_rebase_15aug2022.ts b/src/util/migrations/sqlite/1660565540177-sync_rebase_15aug2022.ts
index 665df6c5..17f1fb16 100644
--- a/src/util/migrations/sqlite/1660565540177-sync_rebase_15aug2022.ts
+++ b/src/util/migrations/sqlite/1660565540177-sync_rebase_15aug2022.ts
@@ -1,18 +1,17 @@
 import { MigrationInterface, QueryRunner } from "typeorm";
 
 export class syncRebase15aug20221660565540177 implements MigrationInterface {
-    name = 'syncRebase15aug20221660565540177'
+	name = "syncRebase15aug20221660565540177";
 
-    public async up(queryRunner: QueryRunner): Promise<void> {
-        await queryRunner.query(`
+	public async up(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(`
             CREATE TABLE "plugin_config" ("key" varchar PRIMARY KEY NOT NULL, "value" text)
         `);
-    }
+	}
 
-    public async down(queryRunner: QueryRunner): Promise<void> {
-        await queryRunner.query(`
+	public async down(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(`
             DROP TABLE "plugin_config"
         `);
-    }
-
+	}
 }
diff --git a/src/util/plugin/Plugin.ts b/src/util/plugin/Plugin.ts
index 6a6f03f4..9bccba9d 100644
--- a/src/util/plugin/Plugin.ts
+++ b/src/util/plugin/Plugin.ts
@@ -1,14 +1,27 @@
-import EventEmitter from "events";
-import { PluginLoadedEventArgs, PluginManifest, TypedEventEmitter } from "@fosscord/util";
-import { PluginConfig } from "./PluginConfig";
-import { PreRegisterEventArgs, PreRegisterEventResult, OnRegisterEventArgs } from '.';
-import { PreMessageEventArgs, PreMessageEventResult, OnMessageEventArgs } from '.';
-import { PreLoginEventArgs, PreLoginEventResult, OnLoginEventArgs } from '.';
-import { PreGuildCreateEventArgs, PreGuildCreateEventResult, OnGuildCreateEventArgs } from '.';
-import { PreChannelCreateEventArgs, PreChannelCreateEventResult, OnChannelCreateEventArgs } from '.';
-import { PreTypingEventArgs, PreTypingEventResult, OnTypingEventArgs } from '.';
-import { PreStatusChangeEventArgs, PreStatusChangeEventResult, OnStatusChangeEventArgs } from '.';
-
+import {
+	OnChannelCreateEventArgs,
+	OnGuildCreateEventArgs,
+	OnLoginEventArgs,
+	OnMessageEventArgs,
+	OnRegisterEventArgs,
+	OnStatusChangeEventArgs,
+	OnTypingEventArgs,
+	PreChannelCreateEventArgs,
+	PreChannelCreateEventResult,
+	PreGuildCreateEventArgs,
+	PreGuildCreateEventResult,
+	PreLoginEventArgs,
+	PreLoginEventResult,
+	PreMessageEventArgs,
+	PreMessageEventResult,
+	PreRegisterEventArgs,
+	PreRegisterEventResult,
+	PreStatusChangeEventArgs,
+	PreStatusChangeEventResult,
+	PreTypingEventArgs,
+	PreTypingEventResult
+} from ".";
+import { PluginLoadedEventArgs, PluginManifest } from "..";
 
 /*type PluginEvents = {
 	error: (error: Error | unknown) => void;
@@ -27,134 +40,131 @@ export class Plugin {
 	pluginPath?: string;
 	pluginManifest?: PluginManifest;
 	/**
-	 *	
+	 *
 	 *
 	 * @param {PluginLoadedEventArgs} args Info about plugin environment
 	 * @memberof Plugin
 	 */
-	async onPluginLoaded?(args?: PluginLoadedEventArgs) {
-
-	}
+	async onPluginLoaded?(args?: PluginLoadedEventArgs) {}
 
 	//generated
 	/**
-	* RegisterEvent: document me
-	*
-	* @param {OnRegisterEventArgs} args Info about what's going on
-	* @memberof Plugin
-	*/
+	 * RegisterEvent: document me
+	 *
+	 * @param {OnRegisterEventArgs} args Info about what's going on
+	 * @memberof Plugin
+	 */
 	async onRegister?(args: OnRegisterEventArgs): Promise<void>;
 
 	/**
-	* RegisterEvent: Executed before changes are announced
-	* document me.
-	*
-	* @param {PreRegisterEventArgs} args Info about what's going on
-	* @return {PreRegisterEventResult} How event should be handled
-	* @memberof Plugin
-	*/
+	 * RegisterEvent: Executed before changes are announced
+	 * document me.
+	 *
+	 * @param {PreRegisterEventArgs} args Info about what's going on
+	 * @return {PreRegisterEventResult} How event should be handled
+	 * @memberof Plugin
+	 */
 	async onPreRegister?(args: PreRegisterEventArgs): Promise<PreRegisterEventResult>;
 	/**
-	* MessageEvent: document me
-	*
-	* @param {OnMessageEventArgs} args Info about what's going on
-	* @memberof Plugin
-	*/
+	 * MessageEvent: document me
+	 *
+	 * @param {OnMessageEventArgs} args Info about what's going on
+	 * @memberof Plugin
+	 */
 	async onMessage?(args: OnMessageEventArgs): Promise<void>;
 
 	/**
-	* MessageEvent: Executed before changes are announced
-	* document me.
-	*
-	* @param {PreMessageEventArgs} args Info about what's going on
-	* @return {PreMessageEventResult} How event should be handled
-	* @memberof Plugin
-	*/
+	 * MessageEvent: Executed before changes are announced
+	 * document me.
+	 *
+	 * @param {PreMessageEventArgs} args Info about what's going on
+	 * @return {PreMessageEventResult} How event should be handled
+	 * @memberof Plugin
+	 */
 	async onPreMessage?(args: PreMessageEventArgs): Promise<PreMessageEventResult>;
 	/**
-	* LoginEvent: document me
-	*
-	* @param {OnLoginEventArgs} args Info about what's going on
-	* @memberof Plugin
-	*/
+	 * LoginEvent: document me
+	 *
+	 * @param {OnLoginEventArgs} args Info about what's going on
+	 * @memberof Plugin
+	 */
 	async onLogin?(args: OnLoginEventArgs): Promise<void>;
 
 	/**
-	* LoginEvent: Executed before changes are announced
-	* document me.
-	*
-	* @param {PreLoginEventArgs} args Info about what's going on
-	* @return {PreLoginEventResult} How event should be handled
-	* @memberof Plugin
-	*/
+	 * LoginEvent: Executed before changes are announced
+	 * document me.
+	 *
+	 * @param {PreLoginEventArgs} args Info about what's going on
+	 * @return {PreLoginEventResult} How event should be handled
+	 * @memberof Plugin
+	 */
 	async onPreLogin?(args: PreLoginEventArgs): Promise<PreLoginEventResult>;
 	/**
-	* GuildCreateEvent: document me
-	*
-	* @param {OnGuildCreateEventArgs} args Info about what's going on
-	* @memberof Plugin
-	*/
+	 * GuildCreateEvent: document me
+	 *
+	 * @param {OnGuildCreateEventArgs} args Info about what's going on
+	 * @memberof Plugin
+	 */
 	async onGuildCreate?(args: OnGuildCreateEventArgs): Promise<void>;
 
 	/**
-	* GuildCreateEvent: Executed before changes are announced
-	* document me.
-	*
-	* @param {PreGuildCreateEventArgs} args Info about what's going on
-	* @return {PreGuildCreateEventResult} How event should be handled
-	* @memberof Plugin
-	*/
+	 * GuildCreateEvent: Executed before changes are announced
+	 * document me.
+	 *
+	 * @param {PreGuildCreateEventArgs} args Info about what's going on
+	 * @return {PreGuildCreateEventResult} How event should be handled
+	 * @memberof Plugin
+	 */
 	async onPreGuildCreate?(args: PreGuildCreateEventArgs): Promise<PreGuildCreateEventResult>;
 	/**
-	* ChannelCreateEvent: document me
-	*
-	* @param {OnChannelCreateEventArgs} args Info about what's going on
-	* @memberof Plugin
-	*/
+	 * ChannelCreateEvent: document me
+	 *
+	 * @param {OnChannelCreateEventArgs} args Info about what's going on
+	 * @memberof Plugin
+	 */
 	async onChannelCreate?(args: OnChannelCreateEventArgs): Promise<void>;
 
 	/**
-	* ChannelCreateEvent: Executed before changes are announced
-	* document me.
-	*
-	* @param {PreChannelCreateEventArgs} args Info about what's going on
-	* @return {PreChannelCreateEventResult} How event should be handled
-	* @memberof Plugin
-	*/
+	 * ChannelCreateEvent: Executed before changes are announced
+	 * document me.
+	 *
+	 * @param {PreChannelCreateEventArgs} args Info about what's going on
+	 * @return {PreChannelCreateEventResult} How event should be handled
+	 * @memberof Plugin
+	 */
 	async onPreChannelCreate?(args: PreChannelCreateEventArgs): Promise<PreChannelCreateEventResult>;
 	/**
-	* TypingEvent: document me
-	*
-	* @param {OnTypingEventArgs} args Info about what's going on
-	* @memberof Plugin
-	*/
+	 * TypingEvent: document me
+	 *
+	 * @param {OnTypingEventArgs} args Info about what's going on
+	 * @memberof Plugin
+	 */
 	async onTyping?(args: OnTypingEventArgs): Promise<void>;
 
 	/**
-	* TypingEvent: Executed before changes are announced
-	* document me.
-	*
-	* @param {PreTypingEventArgs} args Info about what's going on
-	* @return {PreTypingEventResult} How event should be handled
-	* @memberof Plugin
-	*/
+	 * TypingEvent: Executed before changes are announced
+	 * document me.
+	 *
+	 * @param {PreTypingEventArgs} args Info about what's going on
+	 * @return {PreTypingEventResult} How event should be handled
+	 * @memberof Plugin
+	 */
 	async onPreTyping?(args: PreTypingEventArgs): Promise<PreTypingEventResult>;
 	/**
-	* StatusChangeEvent: document me
-	*
-	* @param {OnStatusChangeEventArgs} args Info about what's going on
-	* @memberof Plugin
-	*/
+	 * StatusChangeEvent: document me
+	 *
+	 * @param {OnStatusChangeEventArgs} args Info about what's going on
+	 * @memberof Plugin
+	 */
 	async onStatusChange?(args: OnStatusChangeEventArgs): Promise<void>;
 
 	/**
-	* StatusChangeEvent: Executed before changes are announced
-	* document me.
-	*
-	* @param {PreStatusChangeEventArgs} args Info about what's going on
-	* @return {PreStatusChangeEventResult} How event should be handled
-	* @memberof Plugin
-	*/
+	 * StatusChangeEvent: Executed before changes are announced
+	 * document me.
+	 *
+	 * @param {PreStatusChangeEventArgs} args Info about what's going on
+	 * @return {PreStatusChangeEventResult} How event should be handled
+	 * @memberof Plugin
+	 */
 	async onPreStatusChange?(args: PreStatusChangeEventArgs): Promise<PreStatusChangeEventResult>;
-
 }
diff --git a/src/util/plugin/PluginConfig.ts b/src/util/plugin/PluginConfig.ts
index 883bca7c..b9c8aef0 100644
--- a/src/util/plugin/PluginConfig.ts
+++ b/src/util/plugin/PluginConfig.ts
@@ -1,6 +1,6 @@
 import fs from "fs";
-import { OrmUtils, Environment } from "..";
-import { PluginConfigEntity } from "util/entities/PluginConfig";
+import { Environment } from "..";
+import { PluginConfigEntity } from "../entities/PluginConfig";
 
 // TODO: yaml instead of json
 const overridePath = process.env.PLUGIN_CONFIG_PATH ?? "";
@@ -14,26 +14,28 @@ let pairs: PluginConfigEntity[];
 export const PluginConfig = {
 	init: async function init() {
 		if (config) return config;
-		console.log('[PluginConfig] Loading configuration...')
+		console.log("[PluginConfig] Loading configuration...");
 		pairs = await PluginConfigEntity.find();
 		config = pairsToConfig(pairs);
 		//config = (config || {}).merge(new ConfigValue());
 		//config = OrmUtils.mergeDeep(new ConfigValue(), config)
 
-		if(process.env.PLUGIN_CONFIG_PATH)
+		if (process.env.PLUGIN_CONFIG_PATH)
 			try {
 				const overrideConfig = JSON.parse(fs.readFileSync(overridePath, { encoding: "utf8" }));
 				config = overrideConfig.merge(config);
 			} catch (error) {
 				fs.writeFileSync(overridePath, JSON.stringify(config, null, 4));
 			}
-		
+
 		return this.set(config);
 	},
 	get: function get() {
-		if(!config) {
-			if(Environment.isDebug)
-				console.log("Oops.. trying to get config without config existing... Returning defaults... (Is the database still initialising?)");
+		if (!config) {
+			if (Environment.isDebug)
+				console.log(
+					"Oops.. trying to get config without config existing... Returning defaults... (Is the database still initialising?)"
+				);
 			return {};
 		}
 		return config;
@@ -43,7 +45,7 @@ export const PluginConfig = {
 		config = val.merge(config);
 
 		return applyConfig(config);
-	},
+	}
 };
 
 function applyConfig(val: any) {
@@ -56,17 +58,14 @@ function applyConfig(val: any) {
 
 		pair.key = key;
 		pair.value = obj;
-		if(!pair.key || pair.key == null) {
-			console.log(`[PluginConfig] WARN: Empty key`)
+		if (!pair.key || pair.key == null) {
+			console.log(`[PluginConfig] WARN: Empty key`);
 			console.log(pair);
-			if(Environment.isDebug) debugger;
-		}
-		else
-			return pair.save();
+			if (Environment.isDebug) debugger;
+		} else return pair.save();
 	}
-	if(process.env.PLUGIN_CONFIG_PATH) {
-		if(Environment.isDebug)
-			console.log(`Writing config: ${process.env.PLUGIN_CONFIG_PATH}`)
+	if (process.env.PLUGIN_CONFIG_PATH) {
+		if (Environment.isDebug) console.log(`Writing config: ${process.env.PLUGIN_CONFIG_PATH}`);
 		fs.writeFileSync(overridePath, JSON.stringify(val, null, 4));
 	}
 
diff --git a/src/util/plugin/PluginEventHandler.ts b/src/util/plugin/PluginEventHandler.ts
index d5fc67f4..3ed1efa6 100644
--- a/src/util/plugin/PluginEventHandler.ts
+++ b/src/util/plugin/PluginEventHandler.ts
@@ -1,67 +1,102 @@
-import { PreRegisterEventArgs, OnRegisterEventArgs, PreRegisterEventResult } from './event_types';
-import { PreMessageEventArgs, OnMessageEventArgs, PreMessageEventResult } from './event_types';
-import { PreLoginEventArgs, OnLoginEventArgs, PreLoginEventResult } from './event_types';
-import { PreGuildCreateEventArgs, OnGuildCreateEventArgs, PreGuildCreateEventResult } from './event_types';
-import { PreChannelCreateEventArgs, OnChannelCreateEventArgs, PreChannelCreateEventResult } from './event_types';
-import { PreTypingEventArgs, OnTypingEventArgs, PreTypingEventResult } from './event_types';
-import { PreStatusChangeEventArgs, OnStatusChangeEventArgs, PreStatusChangeEventResult } from './event_types';
 import { PluginStore } from ".";
+import {
+	OnChannelCreateEventArgs,
+	OnGuildCreateEventArgs,
+	OnLoginEventArgs,
+	OnMessageEventArgs,
+	OnRegisterEventArgs,
+	OnStatusChangeEventArgs,
+	OnTypingEventArgs,
+	PreChannelCreateEventArgs,
+	PreChannelCreateEventResult,
+	PreGuildCreateEventArgs,
+	PreGuildCreateEventResult,
+	PreLoginEventArgs,
+	PreLoginEventResult,
+	PreMessageEventArgs,
+	PreMessageEventResult,
+	PreRegisterEventArgs,
+	PreRegisterEventResult,
+	PreStatusChangeEventArgs,
+	PreStatusChangeEventResult,
+	PreTypingEventArgs,
+	PreTypingEventResult
+} from "./event_types";
 
 export class PluginEventHandler {
-    public static async preRegisterEvent(args: PreRegisterEventArgs): Promise<PreRegisterEventResult[]> {
-        return (await Promise.all(PluginStore.plugins.filter(x=>x.onPreRegister).map(x=>x.onPreRegister && x.onPreRegister(args)))).filter(x=>x) as PreRegisterEventResult[];
-    }
-    
-    public static async onRegisterEvent(args: OnRegisterEventArgs): Promise<void> {
-        await Promise.all(PluginStore.plugins.filter(x=>x.onRegister).map(x=>x.onRegister && x.onRegister(args)));
-    }
-    
-    public static async preMessageEvent(args: PreMessageEventArgs): Promise<PreMessageEventResult[]> {
-        return (await Promise.all(PluginStore.plugins.filter(x=>x.onPreMessage).map(x=>x.onPreMessage && x.onPreMessage(args)))).filter(x=>x) as PreMessageEventResult[];
-    }
-    
-    public static async onMessageEvent(args: OnMessageEventArgs): Promise<void> {
-        await Promise.all(PluginStore.plugins.filter(x=>x.onMessage).map(x=>x.onMessage && x.onMessage(args)));
-    }
-    
-    public static async preLoginEvent(args: PreLoginEventArgs): Promise<PreLoginEventResult[]> {
-        return (await Promise.all(PluginStore.plugins.filter(x=>x.onPreLogin).map(x=>x.onPreLogin && x.onPreLogin(args)))).filter(x=>x) as PreLoginEventResult[];
-    }
-    
-    public static async onLoginEvent(args: OnLoginEventArgs): Promise<void> {
-        await Promise.all(PluginStore.plugins.filter(x=>x.onLogin).map(x=>x.onLogin && x.onLogin(args)));
-    }
-    
-    public static async preGuildCreateEvent(args: PreGuildCreateEventArgs): Promise<PreGuildCreateEventResult[]> {
-        return (await Promise.all(PluginStore.plugins.filter(x=>x.onPreGuildCreate).map(x=>x.onPreGuildCreate && x.onPreGuildCreate(args)))).filter(x=>x) as PreGuildCreateEventResult[];
-    }
-    
-    public static async onGuildCreateEvent(args: OnGuildCreateEventArgs): Promise<void> {
-        await Promise.all(PluginStore.plugins.filter(x=>x.onGuildCreate).map(x=>x.onGuildCreate && x.onGuildCreate(args)));
-    }
-    
-    public static async preChannelCreateEvent(args: PreChannelCreateEventArgs): Promise<PreChannelCreateEventResult[]> {
-        return (await Promise.all(PluginStore.plugins.filter(x=>x.onPreChannelCreate).map(x=>x.onPreChannelCreate && x.onPreChannelCreate(args)))).filter(x=>x) as PreChannelCreateEventResult[];
-    }
-    
-    public static async onChannelCreateEvent(args: OnChannelCreateEventArgs): Promise<void> {
-        await Promise.all(PluginStore.plugins.filter(x=>x.onChannelCreate).map(x=>x.onChannelCreate && x.onChannelCreate(args)));
-    }
-    
-    public static async preTypingEvent(args: PreTypingEventArgs): Promise<PreTypingEventResult[]> {
-        return (await Promise.all(PluginStore.plugins.filter(x=>x.onPreTyping).map(x=>x.onPreTyping && x.onPreTyping(args)))).filter(x=>x) as PreTypingEventResult[];
-    }
-    
-    public static async onTypingEvent(args: OnTypingEventArgs): Promise<void> {
-        await Promise.all(PluginStore.plugins.filter(x=>x.onTyping).map(x=>x.onTyping && x.onTyping(args)));
-    }
-    
-    public static async preStatusChangeEvent(args: PreStatusChangeEventArgs): Promise<PreStatusChangeEventResult[]> {
-        return (await Promise.all(PluginStore.plugins.filter(x=>x.onPreStatusChange).map(x=>x.onPreStatusChange && x.onPreStatusChange(args)))).filter(x=>x) as PreStatusChangeEventResult[];
-    }
-    
-    public static async onStatusChangeEvent(args: OnStatusChangeEventArgs): Promise<void> {
-        await Promise.all(PluginStore.plugins.filter(x=>x.onStatusChange).map(x=>x.onStatusChange && x.onStatusChange(args)));
-    }
-    
+	public static async preRegisterEvent(args: PreRegisterEventArgs): Promise<PreRegisterEventResult[]> {
+		return (
+			await Promise.all(PluginStore.plugins.filter((x) => x.onPreRegister).map((x) => x.onPreRegister && x.onPreRegister(args)))
+		).filter((x) => x) as PreRegisterEventResult[];
+	}
+
+	public static async onRegisterEvent(args: OnRegisterEventArgs): Promise<void> {
+		await Promise.all(PluginStore.plugins.filter((x) => x.onRegister).map((x) => x.onRegister && x.onRegister(args)));
+	}
+
+	public static async preMessageEvent(args: PreMessageEventArgs): Promise<PreMessageEventResult[]> {
+		return (
+			await Promise.all(PluginStore.plugins.filter((x) => x.onPreMessage).map((x) => x.onPreMessage && x.onPreMessage(args)))
+		).filter((x) => x) as PreMessageEventResult[];
+	}
+
+	public static async onMessageEvent(args: OnMessageEventArgs): Promise<void> {
+		await Promise.all(PluginStore.plugins.filter((x) => x.onMessage).map((x) => x.onMessage && x.onMessage(args)));
+	}
+
+	public static async preLoginEvent(args: PreLoginEventArgs): Promise<PreLoginEventResult[]> {
+		return (await Promise.all(PluginStore.plugins.filter((x) => x.onPreLogin).map((x) => x.onPreLogin && x.onPreLogin(args)))).filter(
+			(x) => x
+		) as PreLoginEventResult[];
+	}
+
+	public static async onLoginEvent(args: OnLoginEventArgs): Promise<void> {
+		await Promise.all(PluginStore.plugins.filter((x) => x.onLogin).map((x) => x.onLogin && x.onLogin(args)));
+	}
+
+	public static async preGuildCreateEvent(args: PreGuildCreateEventArgs): Promise<PreGuildCreateEventResult[]> {
+		return (
+			await Promise.all(
+				PluginStore.plugins.filter((x) => x.onPreGuildCreate).map((x) => x.onPreGuildCreate && x.onPreGuildCreate(args))
+			)
+		).filter((x) => x) as PreGuildCreateEventResult[];
+	}
+
+	public static async onGuildCreateEvent(args: OnGuildCreateEventArgs): Promise<void> {
+		await Promise.all(PluginStore.plugins.filter((x) => x.onGuildCreate).map((x) => x.onGuildCreate && x.onGuildCreate(args)));
+	}
+
+	public static async preChannelCreateEvent(args: PreChannelCreateEventArgs): Promise<PreChannelCreateEventResult[]> {
+		return (
+			await Promise.all(
+				PluginStore.plugins.filter((x) => x.onPreChannelCreate).map((x) => x.onPreChannelCreate && x.onPreChannelCreate(args))
+			)
+		).filter((x) => x) as PreChannelCreateEventResult[];
+	}
+
+	public static async onChannelCreateEvent(args: OnChannelCreateEventArgs): Promise<void> {
+		await Promise.all(PluginStore.plugins.filter((x) => x.onChannelCreate).map((x) => x.onChannelCreate && x.onChannelCreate(args)));
+	}
+
+	public static async preTypingEvent(args: PreTypingEventArgs): Promise<PreTypingEventResult[]> {
+		return (
+			await Promise.all(PluginStore.plugins.filter((x) => x.onPreTyping).map((x) => x.onPreTyping && x.onPreTyping(args)))
+		).filter((x) => x) as PreTypingEventResult[];
+	}
+
+	public static async onTypingEvent(args: OnTypingEventArgs): Promise<void> {
+		await Promise.all(PluginStore.plugins.filter((x) => x.onTyping).map((x) => x.onTyping && x.onTyping(args)));
+	}
+
+	public static async preStatusChangeEvent(args: PreStatusChangeEventArgs): Promise<PreStatusChangeEventResult[]> {
+		return (
+			await Promise.all(
+				PluginStore.plugins.filter((x) => x.onPreStatusChange).map((x) => x.onPreStatusChange && x.onPreStatusChange(args))
+			)
+		).filter((x) => x) as PreStatusChangeEventResult[];
+	}
+
+	public static async onStatusChangeEvent(args: OnStatusChangeEventArgs): Promise<void> {
+		await Promise.all(PluginStore.plugins.filter((x) => x.onStatusChange).map((x) => x.onStatusChange && x.onStatusChange(args)));
+	}
 }
diff --git a/src/util/plugin/PluginLoader.ts b/src/util/plugin/PluginLoader.ts
index 4dc0129a..9f37ed87 100644
--- a/src/util/plugin/PluginLoader.ts
+++ b/src/util/plugin/PluginLoader.ts
@@ -1,16 +1,16 @@
-import path from "path";
 import fs from "fs";
-import { Plugin, PluginLoadedEventArgs, PluginManifest, PluginStore } from "./";
-import { PluginIndex } from "plugins/PluginIndex";
+import path from "path";
+import { OrmUtils } from "..";
+import { PluginIndex } from "../../plugins/PluginIndex";
+import { PluginLoadedEventArgs, PluginManifest, PluginStore } from "./";
 import { PluginConfig } from "./PluginConfig";
-import { OrmUtils, PluginConfigEntity } from "..";
 
 const root = process.env.PLUGIN_LOCATION || "dist/plugins";
 
 let pluginsLoaded = false;
 export class PluginLoader {
 	public static async loadPlugins() {
-		if(pluginsLoaded) return;
+		if (pluginsLoaded) return;
 		PluginConfig.init();
 		console.log(`Plugin root directory: ${path.resolve(root)}`);
 		const dirs = fs.readdirSync(root).filter((x) => {
@@ -33,33 +33,31 @@ export class PluginLoader {
 				`Plugin info: ${manifest.name} (${manifest.id}), written by ${manifest.authors}, available at ${manifest.repository}`
 			);
 			const module_ = PluginIndex[manifest.id];
-			
+
 			module_.pluginPath = modPath;
 			module_.pluginManifest = manifest;
 			Object.freeze(module_.pluginPath);
 			Object.freeze(module_.pluginManifest);
-			
-			if(module_.onPluginLoaded) await module_.onPluginLoaded({} as PluginLoadedEventArgs);
+
+			if (module_.onPluginLoaded) await module_.onPluginLoaded({} as PluginLoadedEventArgs);
 			PluginStore.plugins.push(module_);
 		});
 
 		console.log(`Done loading ${PluginStore.plugins.length} plugins!`);
 	}
-	
+
 	public static getPluginConfig(id: string, defaults?: any): any {
 		let cfg = PluginConfig.get()[id];
-		if(defaults) {
-			if(cfg)
-				cfg = OrmUtils.mergeDeep(defaults, cfg);
-			else
-				cfg = defaults;
+		if (defaults) {
+			if (cfg) cfg = OrmUtils.mergeDeep(defaults, cfg);
+			else cfg = defaults;
 			this.setPluginConfig(id, cfg);
 		}
-		if(!cfg) console.log(`[PluginConfig/WARN] Getting plugin settings for '${id}' returned null! (Did you forget to add settings?)`);
+		if (!cfg) console.log(`[PluginConfig/WARN] Getting plugin settings for '${id}' returned null! (Did you forget to add settings?)`);
 		return cfg;
 	}
 	public static async setPluginConfig(id: string, config: Partial<any>): Promise<void> {
-		if(!config) console.log(`[PluginConfig/WARN] ${id} tried to set config=null!`);
+		if (!config) console.log(`[PluginConfig/WARN] ${id} tried to set config=null!`);
 		await PluginConfig.set({ [id]: OrmUtils.mergeDeep(PluginLoader.getPluginConfig(id) || {}, config) });
 	}
 }
diff --git a/src/util/plugin/PluginManifest.ts b/src/util/plugin/PluginManifest.ts
index 79ecc465..518202ec 100644
--- a/src/util/plugin/PluginManifest.ts
+++ b/src/util/plugin/PluginManifest.ts
@@ -1,10 +1,10 @@
 export class PluginManifest {
-    id: string;
-    name: string;
-    authors: string[];
-    repository: string;
-    license: string;
-	version: string // semver
-	versionCode: number // integer
-    mainClass: string;
-}
\ No newline at end of file
+	id: string;
+	name: string;
+	authors: string[];
+	repository: string;
+	license: string;
+	version: string; // semver
+	versionCode: number; // integer
+	mainClass: string;
+}
diff --git a/src/util/plugin/PluginStore.ts b/src/util/plugin/PluginStore.ts
index 60d7f7b7..8b02f157 100644
--- a/src/util/plugin/PluginStore.ts
+++ b/src/util/plugin/PluginStore.ts
@@ -1,9 +1,4 @@
-import path from "path";
-import fs from "fs";
-import { Plugin, PluginLoadedEventArgs, PluginManifest } from "./";
-import { PluginIndex } from "plugins/PluginIndex";
-import { PluginConfig } from "./PluginConfig";
-import { OrmUtils, PluginConfigEntity } from "..";
+import { Plugin } from "./";
 
 const root = process.env.PLUGIN_LOCATION || "dist/plugins";
 
diff --git a/src/util/plugin/event_types/ChannelCreateEventArgs.ts b/src/util/plugin/event_types/ChannelCreateEventArgs.ts
index 87fa3691..eb103346 100644
--- a/src/util/plugin/event_types/ChannelCreateEventArgs.ts
+++ b/src/util/plugin/event_types/ChannelCreateEventArgs.ts
@@ -2,16 +2,16 @@ import { Channel, Guild, User } from "util/entities";
 import { EventResult } from ".";
 
 export interface PreChannelCreateEventArgs {
-    channel: Channel,
-	guild: Guild,
-	user: User
+	channel: Channel;
+	guild: Guild;
+	user: User;
 }
 export interface PreChannelCreateEventResult extends EventResult {
-    channel: Partial<Channel>
+	channel: Partial<Channel>;
 }
 
 export interface OnChannelCreateEventArgs {
-    channel: Channel,
-	guild: Guild,
-	user: User
+	channel: Channel;
+	guild: Guild;
+	user: User;
 }
diff --git a/src/util/plugin/event_types/GuildCreateEventArgs.ts b/src/util/plugin/event_types/GuildCreateEventArgs.ts
index 7724b4f3..0df9beb1 100644
--- a/src/util/plugin/event_types/GuildCreateEventArgs.ts
+++ b/src/util/plugin/event_types/GuildCreateEventArgs.ts
@@ -2,14 +2,14 @@ import { Guild, User } from "util/entities";
 import { EventResult } from ".";
 
 export interface PreGuildCreateEventArgs {
-    user: User,
-	guild: Guild
+	user: User;
+	guild: Guild;
 }
 export interface PreGuildCreateEventResult extends EventResult {
-    guild: Partial<Guild>
+	guild: Partial<Guild>;
 }
 
 export interface OnGuildCreateEventArgs {
-    user: User,
-	guild: Guild
+	user: User;
+	guild: Guild;
 }
diff --git a/src/util/plugin/event_types/LoginEventArgs.ts b/src/util/plugin/event_types/LoginEventArgs.ts
index 8f80b69f..4f10e451 100644
--- a/src/util/plugin/event_types/LoginEventArgs.ts
+++ b/src/util/plugin/event_types/LoginEventArgs.ts
@@ -2,14 +2,12 @@ import { User } from "util/entities";
 import { EventResult } from ".";
 
 export interface PreLoginEventArgs {
-	ip: String,
-	user: User
-}
-export interface PreLoginEventResult extends EventResult {
-    
+	ip: String;
+	user: User;
 }
+export interface PreLoginEventResult extends EventResult {}
 
 export interface OnLoginEventArgs {
-	ip: String,
-	user: User
+	ip: String;
+	user: User;
 }
diff --git a/src/util/plugin/event_types/MessageEventArgs.ts b/src/util/plugin/event_types/MessageEventArgs.ts
index ab276429..01df9b75 100644
--- a/src/util/plugin/event_types/MessageEventArgs.ts
+++ b/src/util/plugin/event_types/MessageEventArgs.ts
@@ -2,14 +2,14 @@ import { Message, User } from "util/entities";
 import { EventResult } from ".";
 
 export interface PreMessageEventArgs {
-	user: User,
-    message: Message;
+	user: User;
+	message: Message;
 }
 export interface PreMessageEventResult extends EventResult {
-    message: Partial<Message>
+	message: Partial<Message>;
 }
 
 export interface OnMessageEventArgs {
-	user: User,
-    message: Message
+	user: User;
+	message: Message;
 }
diff --git a/src/util/plugin/event_types/PluginLoadedEventArgs.ts b/src/util/plugin/event_types/PluginLoadedEventArgs.ts
index 58829f15..a585675b 100644
--- a/src/util/plugin/event_types/PluginLoadedEventArgs.ts
+++ b/src/util/plugin/event_types/PluginLoadedEventArgs.ts
@@ -1,3 +1 @@
-export interface PluginLoadedEventArgs {
-    
-}
\ No newline at end of file
+export interface PluginLoadedEventArgs {}
diff --git a/src/util/plugin/event_types/RegisterEventArgs.ts b/src/util/plugin/event_types/RegisterEventArgs.ts
index d36d7e64..f3e0fdd4 100644
--- a/src/util/plugin/event_types/RegisterEventArgs.ts
+++ b/src/util/plugin/event_types/RegisterEventArgs.ts
@@ -2,16 +2,16 @@ import { User } from "util/entities";
 import { EventResult } from ".";
 
 export interface PreRegisterEventArgs {
-	age: any,
-	user: User,
-	ip: String
+	age: any;
+	user: User;
+	ip: String;
 }
 export interface PreRegisterEventResult extends EventResult {
-    user: Partial<User>
+	user: Partial<User>;
 }
 
 export interface OnRegisterEventArgs {
-    age: any,
-	user: User,
-	ip: String
+	age: any;
+	user: User;
+	ip: String;
 }
diff --git a/src/util/plugin/event_types/StatusChangeEventArgs.ts b/src/util/plugin/event_types/StatusChangeEventArgs.ts
index c1a67112..b412cffa 100644
--- a/src/util/plugin/event_types/StatusChangeEventArgs.ts
+++ b/src/util/plugin/event_types/StatusChangeEventArgs.ts
@@ -3,14 +3,14 @@ import { Presence } from "util/interfaces";
 import { EventResult } from ".";
 
 export interface PreStatusChangeEventArgs {
-    user: User,
-	presence: Presence
+	user: User;
+	presence: Presence;
 }
 export interface PreStatusChangeEventResult extends EventResult {
-    presence: Partial<Presence>
+	presence: Partial<Presence>;
 }
 
 export interface OnStatusChangeEventArgs {
-    user: User,
-	presence: Presence
+	user: User;
+	presence: Presence;
 }
diff --git a/src/util/plugin/event_types/TypingEventArgs.ts b/src/util/plugin/event_types/TypingEventArgs.ts
index 3ac59b41..694ef83b 100644
--- a/src/util/plugin/event_types/TypingEventArgs.ts
+++ b/src/util/plugin/event_types/TypingEventArgs.ts
@@ -2,16 +2,14 @@ import { Channel, Guild, User } from "util/entities";
 import { EventResult } from ".";
 
 export interface PreTypingEventArgs {
-    channel: Channel,
-	guild: Guild,
-	user: User
-}
-export interface PreTypingEventResult extends EventResult {
-    
+	channel: Channel;
+	guild: Guild;
+	user: User;
 }
+export interface PreTypingEventResult extends EventResult {}
 
 export interface OnTypingEventArgs {
-    channel: Channel,
-	guild: Guild,
-	user: User
+	channel: Channel;
+	guild: Guild;
+	user: User;
 }
diff --git a/src/util/plugin/event_types/_gen.sh b/src/util/plugin/event_types/_gen.sh
index 9f761d1e..f8769301 100755
--- a/src/util/plugin/event_types/_gen.sh
+++ b/src/util/plugin/event_types/_gen.sh
@@ -48,8 +48,8 @@ do
         echo "    async onPre${event}?(args: Pre${event}EventArgs): Promise<Pre${event}EventResult>;"
     ) >> ../plugin.eventfuncs.generated
 
-    echo "import { Pre${event}EventArgs, On${event}EventArgs, Pre${event}EventResult } from './event_types';" >> ../PluginEventHandler.ts.1
-    echo "import { Pre${event}EventArgs, Pre${event}EventResult, On${event}EventArgs } from '.';" >> ../plugin.imports.generated
+    echo "import { Pre${event}EventArgs, On${event}EventArgs, Pre${event}EventResult } from \"./event_types\";" >> ../PluginEventHandler.ts.1
+    echo "import { Pre${event}EventArgs, Pre${event}EventResult, On${event}EventArgs } from \".\";" >> ../plugin.imports.generated
     cmp --silent "${event}EventArgs.ts" "${event}EventArgs.ts.generated" && rm -f "${event}EventArgs.ts.generated"
 done < _pdo
 
diff --git a/src/util/plugin/event_types/base/EventResult.ts b/src/util/plugin/event_types/base/EventResult.ts
index f18837cd..7acaa775 100644
--- a/src/util/plugin/event_types/base/EventResult.ts
+++ b/src/util/plugin/event_types/base/EventResult.ts
@@ -1,4 +1,4 @@
 export interface EventResult {
-    cancel?: boolean;
-    blockReason?: string;
-}
\ No newline at end of file
+	cancel?: boolean;
+	blockReason?: string;
+}
diff --git a/src/util/plugin/event_types/index.ts b/src/util/plugin/event_types/index.ts
index 4a585dc0..773e8dc9 100644
--- a/src/util/plugin/event_types/index.ts
+++ b/src/util/plugin/event_types/index.ts
@@ -1,3 +1,4 @@
+export * from "./base/index";
 export * from "./ChannelCreateEventArgs";
 export * from "./GuildCreateEventArgs";
 export * from "./LoginEventArgs";
@@ -6,4 +7,3 @@ export * from "./PluginLoadedEventArgs";
 export * from "./RegisterEventArgs";
 export * from "./StatusChangeEventArgs";
 export * from "./TypingEventArgs";
-export * from "./base/index";
diff --git a/src/util/plugin/index.ts b/src/util/plugin/index.ts
index 7a297981..ffc7803e 100644
--- a/src/util/plugin/index.ts
+++ b/src/util/plugin/index.ts
@@ -1,7 +1,7 @@
+export * from "./event_types/index";
 export * from "./Plugin";
 export * from "./PluginConfig";
 export * from "./PluginEventHandler";
 export * from "./PluginLoader";
 export * from "./PluginManifest";
 export * from "./PluginStore";
-export * from "./event_types/index";
diff --git a/src/util/schemas/ActivitySchema.ts b/src/util/schemas/ActivitySchema.ts
index d94557ea..a572b01a 100644
--- a/src/util/schemas/ActivitySchema.ts
+++ b/src/util/schemas/ActivitySchema.ts
@@ -1,4 +1,4 @@
-import { Activity, Status } from "@fosscord/util";
+import { Activity, Status } from "..";
 
 export const ActivitySchema = {
 	afk: Boolean,
diff --git a/src/util/schemas/ChannelPermissionOverwriteSchema.ts b/src/util/schemas/ChannelPermissionOverwriteSchema.ts
index e8bc13bb..faa957dd 100644
--- a/src/util/schemas/ChannelPermissionOverwriteSchema.ts
+++ b/src/util/schemas/ChannelPermissionOverwriteSchema.ts
@@ -1,4 +1,4 @@
-import { ChannelPermissionOverwrite } from "@fosscord/util";
+import { ChannelPermissionOverwrite } from "..";
 
 // TODO: Only permissions your bot has in the guild or channel can be allowed/denied (unless your bot has a MANAGE_ROLES overwrite in the channel)
 
diff --git a/src/util/schemas/MessageCreateSchema.ts b/src/util/schemas/MessageCreateSchema.ts
index bf3470bb..62c93754 100644
--- a/src/util/schemas/MessageCreateSchema.ts
+++ b/src/util/schemas/MessageCreateSchema.ts
@@ -1,4 +1,4 @@
-import { Embed } from "@fosscord/util";
+import { Embed } from "..";
 
 export interface MessageCreateSchema {
 	type?: number;
diff --git a/src/util/schemas/RelationshipPutSchema.ts b/src/util/schemas/RelationshipPutSchema.ts
index 0a7f9720..f90c0d56 100644
--- a/src/util/schemas/RelationshipPutSchema.ts
+++ b/src/util/schemas/RelationshipPutSchema.ts
@@ -1,4 +1,4 @@
-import { RelationshipType } from "@fosscord/util";
+import { RelationshipType } from "..";
 
 export interface RelationshipPutSchema {
 	type?: RelationshipType;
diff --git a/src/util/schemas/UserSettingsSchema.ts b/src/util/schemas/UserSettingsSchema.ts
index eb9b316d..657f483e 100644
--- a/src/util/schemas/UserSettingsSchema.ts
+++ b/src/util/schemas/UserSettingsSchema.ts
@@ -1,3 +1,3 @@
-import { UserSettings } from "@fosscord/util";
+import { UserSettings } from "..";
 
 export interface UserSettingsSchema extends Partial<UserSettings> {}
diff --git a/src/util/schemas/VoiceStateUpdateSchema.ts b/src/util/schemas/VoiceStateUpdateSchema.ts
index ea286b1a..0dec6383 100644
--- a/src/util/schemas/VoiceStateUpdateSchema.ts
+++ b/src/util/schemas/VoiceStateUpdateSchema.ts
@@ -6,7 +6,7 @@ export const VoiceStateUpdateSchema = {
 	self_video: Boolean
 };
 
-//TODO need more testing when community guild and voice stage channel are working
+//TODO: need more testing when community guild and voice stage channel are working
 export interface VoiceStateUpdateSchema {
 	channel_id: string;
 	guild_id?: string;
diff --git a/src/api/util/utility/Base64.ts b/src/util/util/Base64.ts
index 46cff77a..46cff77a 100644
--- a/src/api/util/utility/Base64.ts
+++ b/src/util/util/Base64.ts
diff --git a/src/util/util/Config.ts b/src/util/util/Config.ts
index cc7090a6..49a1f3f8 100644
--- a/src/util/util/Config.ts
+++ b/src/util/util/Config.ts
@@ -4,7 +4,6 @@ import { OrmUtils } from ".";
 import { ConfigValue } from "../config";
 import { ConfigEntity } from "../entities/Config";
 
-// TODO: yaml instead of json
 const overridePath = process.env.CONFIG_PATH ?? "";
 
 let config: ConfigValue;
diff --git a/src/util/util/Environment.ts b/src/util/util/Environment.ts
index a6d68785..3ebeb56c 100644
--- a/src/util/util/Environment.ts
+++ b/src/util/util/Environment.ts
@@ -1,3 +1,3 @@
 export class Environment {
-    static isDebug: boolean = /--debug|--inspect/.test(process.execArgv.join(' '));
+	static isDebug: boolean = /--debug|--inspect/.test(process.execArgv.join(" "));
 }
diff --git a/src/util/util/Logo.ts b/src/util/util/Logo.ts
index b1627198..3e108af2 100644
--- a/src/util/util/Logo.ts
+++ b/src/util/util/Logo.ts
@@ -1,41 +1,40 @@
-import { existsSync } from "fs";
 import { execSync } from "child_process";
+import { existsSync } from "fs";
 
 export class Logo {
-    public static printLogo(){
-        if(existsSync("/usr/bin/chafa"))
-        return execSync("chafa https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Wordmark-Orange.svg", {
-			env: process.env,
-			encoding: "utf-8",
-            stdio: "inherit",
-            
-		});
-        else console.log(Logo.logoVersions['1'] as string)
-    }
-    private static getConsoleColors(): number {
-        return 1;
-        if(!process.env.TERM) return 1;
-        else {
-            switch (process.env.TERM) {
-                case "":
-                    
-                    break;
-            
-                default:
-                    break;
-            }
-        }
-        return 1;
-    }
-    private static logoVersions: any = {
-        '1':
-           `███████╗ ██████╗ ███████╗███████╗ ██████╗ ██████╗ ██████╗ ██████╗
+	public static printLogo() {
+		if (existsSync("/usr/bin/chafa"))
+			return execSync(
+				"chafa https://raw.githubusercontent.com/fosscord/fosscord/master/assets-rebrand/svg/Fosscord-Wordmark-Orange.svg",
+				{
+					env: process.env,
+					encoding: "utf-8",
+					stdio: "inherit"
+				}
+			);
+		else console.log(Logo.logoVersions["1"] as string);
+	}
+	private static getConsoleColors(): number {
+		return 1;
+		if (!process.env.TERM) return 1;
+		else {
+			switch (process.env.TERM) {
+				case "":
+					break;
+
+				default:
+					break;
+			}
+		}
+		return 1;
+	}
+	private static logoVersions: any = {
+		"1": `███████╗ ██████╗ ███████╗███████╗ ██████╗ ██████╗ ██████╗ ██████╗
             ██╔════╝██╔═══██╗██╔════╝██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔══██╗
             █████╗  ██║   ██║███████╗███████╗██║     ██║   ██║██████╔╝██║  ██║
             ██╔══╝  ██║   ██║╚════██║╚════██║██║     ██║   ██║██╔══██╗██║  ██║
             ██║     ╚██████╔╝███████║███████║╚██████╗╚██████╔╝██║  ██║██████╔╝
             ╚═╝      ╚═════╝ ╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝  ╚═╝╚═════╝`,
-        '2':``
-            
-    }
-}
\ No newline at end of file
+		"2": ``
+	};
+}
diff --git a/src/util/util/Permissions.ts b/src/util/util/Permissions.ts
index b8d0d8ae..bc98edb3 100644
--- a/src/util/util/Permissions.ts
+++ b/src/util/util/Permissions.ts
@@ -55,11 +55,14 @@ export class Permissions extends BitField {
 		MANAGE_EMOJIS_AND_STICKERS: BitFlag(30),
 		USE_APPLICATION_COMMANDS: BitFlag(31),
 		REQUEST_TO_SPEAK: BitFlag(32),
-		// TODO: what is permission 33?
+		MANAGE_EVENTS: BitFlag(33),
 		MANAGE_THREADS: BitFlag(34),
 		USE_PUBLIC_THREADS: BitFlag(35),
 		USE_PRIVATE_THREADS: BitFlag(36),
-		USE_EXTERNAL_STICKERS: BitFlag(37)
+		USE_EXTERNAL_STICKERS: BitFlag(37),
+		SEND_MESSAGES_IN_THREADS: BitFlag(38),
+		START_VOICE_ACTIVITIES: BitFlag(39),
+		MODERATE_MEMBERS: BitFlag(40)
 
 		/**
 		 * CUSTOM PERMISSIONS ideas:
diff --git a/src/api/util/utility/RandomInviteID.ts b/src/util/util/RandomInviteID.ts
index feebfd3d..8ffca06b 100644
--- a/src/api/util/utility/RandomInviteID.ts
+++ b/src/util/util/RandomInviteID.ts
@@ -1,4 +1,4 @@
-import { Snowflake } from "@fosscord/util";
+import { Snowflake } from ".";
 
 export function random(length = 6) {
 	// Declare all characters
diff --git a/src/util/util/Rights.ts b/src/util/util/Rights.ts
index 236bfea7..d2a7f1f7 100644
--- a/src/util/util/Rights.ts
+++ b/src/util/util/Rights.ts
@@ -5,7 +5,7 @@ import { BitField, BitFieldResolvable, BitFlag } from "./BitField";
 export type RightResolvable = bigint | number | Rights | RightResolvable[] | RightString;
 
 type RightString = keyof typeof Rights.FLAGS;
-// TODO: just like roles for members, users should have privilidges which combine multiple rights into one and make it easy to assign
+// TODO: just like roles for members, users should have privilides which combine multiple rights into one and make it easy to assign
 
 export class Rights extends BitField {
 	constructor(bits: BitFieldResolvable = 0) {
diff --git a/src/util/util/String.ts b/src/util/util/String.ts
index 55f11e8d..5e6bfb6f 100644
--- a/src/util/util/String.ts
+++ b/src/util/util/String.ts
@@ -1,3 +1,5 @@
+import { Request } from "express";
+import { FieldErrors, ntob } from ".";
 import { SPECIAL_CHAR } from "./Regex";
 
 export function trimSpecial(str?: string): string {
@@ -5,3 +7,18 @@ export function trimSpecial(str?: string): string {
 	if (!str) return;
 	return str.replace(SPECIAL_CHAR, "").trim();
 }
+
+export function checkLength(str: string, min: number, max: number, key: string, req: Request) {
+	if (str.length < min || str.length > max) {
+		throw FieldErrors({
+			[key]: {
+				code: "BASE_TYPE_BAD_LENGTH",
+				message: req.t("common:field.BASE_TYPE_BAD_LENGTH", { length: `${min} - ${max}` })
+			}
+		});
+	}
+}
+
+export function generateCode() {
+	return ntob(Date.now() + Math.randomIntBetween(0, 10000));
+}
diff --git a/src/util/util/index.ts b/src/util/util/index.ts
index 4135f44e..b13fe9ad 100644
--- a/src/util/util/index.ts
+++ b/src/util/util/index.ts
@@ -1,5 +1,6 @@
 export * from "./ApiError";
 export * from "./Array";
+export * from "./Base64";
 export * from "./BitField";
 //export * from "./Categories";
 export * from "./cdn";
@@ -7,6 +8,7 @@ export * from "./Config";
 export * from "./Constants";
 export * from "./Database";
 export * from "./Email";
+export * from "./Environment";
 export * from "./Event";
 export * from "./FieldError";
 export * from "./imports/HTTPError";
@@ -14,9 +16,12 @@ export * from "./imports/index";
 export * from "./imports/OrmUtils";
 export * from "./Intents";
 export * from "./InvisibleCharacters";
+export * from "./ipAddress";
+export * from "./Logo";
 export * from "./MessageFlags";
 export * from "./Permissions";
 export * from "./RabbitMQ";
+export * from "./RandomInviteID";
 export * from "./Regex";
 export * from "./Rights";
 export * from "./Snowflake";
diff --git a/src/api/util/utility/ipAddress.ts b/src/util/util/ipAddress.ts
index c96feb9e..925c62e5 100644
--- a/src/api/util/utility/ipAddress.ts
+++ b/src/util/util/ipAddress.ts
@@ -1,5 +1,5 @@
-import { Config } from "@fosscord/util";
 import { Request } from "express";
+import { Config } from ".";
 // use ipdata package instead of simple fetch because of integrated caching
 import fetch from "node-fetch";
 
@@ -60,7 +60,7 @@ const exampleData = {
 	status: 200
 };
 
-//TODO add function that support both ip and domain names
+//TODO: add function that support both ip and domain names
 export async function IPAnalysis(ip: string): Promise<typeof exampleData> {
 	const { ipdataApiKey } = Config.get().security;
 	if (!ipdataApiKey) return { ...exampleData, ip };
diff --git a/src/api/util/utility/passwordStrength.ts b/src/util/util/passwordStrength.ts
index ff83d3df..1026a07e 100644
--- a/src/api/util/utility/passwordStrength.ts
+++ b/src/util/util/passwordStrength.ts
@@ -1,4 +1,4 @@
-import { Config } from "@fosscord/util";
+import { Config } from ".";
 
 const reNUMBER = /[0-9]/g;
 const reUPPERCASELETTER = /[A-Z]/g;