summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlam3rboy <34555296+Flam3rboy@users.noreply.github.com>2021-08-13 12:59:59 +0200
committerFlam3rboy <34555296+Flam3rboy@users.noreply.github.com>2021-08-13 12:59:59 +0200
commit90d5307a5668030b414d35deeb2bb9b6845b76e0 (patch)
tree6dcb69012336c1222ac75ad539e0a576ada05a7c
parent:sparkles: server bundle (diff)
downloadserver-90d5307a5668030b414d35deeb2bb9b6845b76e0.tar.xz
rename @fosscord/server-util to -> @fosscord/util
-rw-r--r--api/package-lock.json50
-rw-r--r--api/package.json3
-rw-r--r--api/src/Server.ts8
-rw-r--r--api/src/index.ts2
-rw-r--r--api/src/middlewares/Authentication.ts21
-rw-r--r--api/src/middlewares/ErrorHandler.ts2
-rw-r--r--api/src/middlewares/RateLimit.ts21
-rw-r--r--api/src/routes/auth/login.ts2
-rw-r--r--api/src/routes/auth/register.ts2
-rw-r--r--api/src/routes/channels/#channel_id/index.ts3
-rw-r--r--api/src/routes/channels/#channel_id/invites.ts3
-rw-r--r--api/src/routes/channels/#channel_id/messages/#message_id/ack.ts4
-rw-r--r--api/src/routes/channels/#channel_id/messages/#message_id/index.ts4
-rw-r--r--api/src/routes/channels/#channel_id/messages/#message_id/reactions.ts4
-rw-r--r--api/src/routes/channels/#channel_id/messages/bulk-delete.ts4
-rw-r--r--api/src/routes/channels/#channel_id/messages/index.ts2
-rw-r--r--api/src/routes/channels/#channel_id/permissions.ts12
-rw-r--r--api/src/routes/channels/#channel_id/pins.ts4
-rw-r--r--api/src/routes/channels/#channel_id/typing.ts3
-rw-r--r--api/src/routes/channels/#channel_id/webhooks.ts2
-rw-r--r--api/src/routes/gateway.ts2
-rw-r--r--api/src/routes/guilds/#guild_id/bans.ts4
-rw-r--r--api/src/routes/guilds/#guild_id/channels.ts9
-rw-r--r--api/src/routes/guilds/#guild_id/delete.ts4
-rw-r--r--api/src/routes/guilds/#guild_id/index.ts5
-rw-r--r--api/src/routes/guilds/#guild_id/invites.ts2
-rw-r--r--api/src/routes/guilds/#guild_id/members/#member_id/index.ts6
-rw-r--r--api/src/routes/guilds/#guild_id/members/#member_id/nick.ts2
-rw-r--r--api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts2
-rw-r--r--api/src/routes/guilds/#guild_id/members/index.ts2
-rw-r--r--api/src/routes/guilds/#guild_id/regions.ts4
-rw-r--r--api/src/routes/guilds/#guild_id/roles.ts7
-rw-r--r--api/src/routes/guilds/#guild_id/templates.ts2
-rw-r--r--api/src/routes/guilds/#guild_id/vanity-url.ts2
-rw-r--r--api/src/routes/guilds/#guild_id/welcome_screen.ts4
-rw-r--r--api/src/routes/guilds/#guild_id/widget.json.ts2
-rw-r--r--api/src/routes/guilds/#guild_id/widget.png.ts2
-rw-r--r--api/src/routes/guilds/#guild_id/widget.ts2
-rw-r--r--api/src/routes/guilds/index.ts2
-rw-r--r--api/src/routes/guilds/templates/index.ts2
-rw-r--r--api/src/routes/invites/index.ts2
-rw-r--r--api/src/routes/users/@me/channels.ts7
-rw-r--r--api/src/routes/users/@me/delete.ts2
-rw-r--r--api/src/routes/users/@me/disable.ts2
-rw-r--r--api/src/routes/users/@me/guilds.ts14
-rw-r--r--api/src/routes/users/@me/index.ts2
-rw-r--r--api/src/routes/users/@me/relationships.ts7
-rw-r--r--api/src/schema/Channel.ts2
-rw-r--r--api/src/schema/Guild.ts2
-rw-r--r--api/src/schema/Message.ts2
-rw-r--r--api/src/test/test.ts2
-rw-r--r--api/src/util/Channel.ts8
-rw-r--r--api/src/util/Config.ts4
-rw-r--r--api/src/util/Event.ts26
-rw-r--r--api/src/util/Member.ts7
-rw-r--r--api/src/util/Message.ts16
-rw-r--r--api/src/util/User.ts2
-rw-r--r--api/src/util/cdn.ts2
-rw-r--r--api/src/util/ipAddress.ts2
-rw-r--r--api/src/util/passwordStrength.ts2
-rw-r--r--cdn/package-lock.json50
-rw-r--r--cdn/package.json3
-rw-r--r--cdn/src/Server.ts24
-rw-r--r--cdn/src/routes/attachments.ts2
-rw-r--r--cdn/src/routes/avatars.ts2
-rw-r--r--cdn/src/routes/external.ts2
66 files changed, 254 insertions, 165 deletions
diff --git a/api/package-lock.json b/api/package-lock.json
index 8e9a42cd..0a9af8e0 100644
--- a/api/package-lock.json
+++ b/api/package-lock.json
@@ -7,9 +7,11 @@
 		"": {
 			"name": "@fosscord/api",
 			"version": "1.0.0",
+			"hasInstallScript": true,
 			"license": "ISC",
 			"dependencies": {
 				"@fosscord/server-util": "^1.3.52",
+				"@fosscord/util": "file:../util",
 				"@types/jest": "^26.0.22",
 				"@types/json-schema": "^7.0.7",
 				"ajv": "^8.4.0",
@@ -60,6 +62,30 @@
 				"typescript": "^4.1.2"
 			}
 		},
+		"../util": {
+			"name": "@fosscord/util",
+			"version": "1.3.52",
+			"license": "GPLV3",
+			"dependencies": {
+				"@types/jsonwebtoken": "^8.5.0",
+				"@types/mongoose-autopopulate": "^0.10.1",
+				"@types/mongoose-lean-virtuals": "^0.5.1",
+				"@types/node": "^14.14.25",
+				"ajv": "^8.5.0",
+				"amqplib": "^0.8.0",
+				"dot-prop": "^6.0.1",
+				"env-paths": "^2.2.1",
+				"jsonwebtoken": "^8.5.1",
+				"missing-native-js-functions": "^1.2.2",
+				"mongodb": "^3.6.9",
+				"mongoose": "^5.13.7",
+				"mongoose-autopopulate": "^0.12.3",
+				"typescript": "^4.1.3"
+			},
+			"devDependencies": {
+				"@types/amqplib": "^0.8.1"
+			}
+		},
 		"node_modules/@babel/code-frame": {
 			"version": "7.14.5",
 			"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz",
@@ -700,6 +726,10 @@
 				"typescript": "^4.1.3"
 			}
 		},
+		"node_modules/@fosscord/util": {
+			"resolved": "../util",
+			"link": true
+		},
 		"node_modules/@istanbuljs/load-nyc-config": {
 			"version": "1.1.0",
 			"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
@@ -11593,6 +11623,26 @@
 				"typescript": "^4.1.3"
 			}
 		},
+		"@fosscord/util": {
+			"version": "file:../util",
+			"requires": {
+				"@types/amqplib": "^0.8.1",
+				"@types/jsonwebtoken": "^8.5.0",
+				"@types/mongoose-autopopulate": "^0.10.1",
+				"@types/mongoose-lean-virtuals": "^0.5.1",
+				"@types/node": "^14.14.25",
+				"ajv": "^8.5.0",
+				"amqplib": "^0.8.0",
+				"dot-prop": "^6.0.1",
+				"env-paths": "^2.2.1",
+				"jsonwebtoken": "^8.5.1",
+				"missing-native-js-functions": "^1.2.2",
+				"mongodb": "^3.6.9",
+				"mongoose": "^5.13.7",
+				"mongoose-autopopulate": "^0.12.3",
+				"typescript": "^4.1.3"
+			}
+		},
 		"@istanbuljs/load-nyc-config": {
 			"version": "1.1.0",
 			"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
diff --git a/api/package.json b/api/package.json
index bb22f94c..96afa82e 100644
--- a/api/package.json
+++ b/api/package.json
@@ -5,6 +5,8 @@
 	"main": "dist/Server.js",
 	"types": "dist/Server.d.ts",
 	"scripts": {
+		"link": "npm run build && npm link",
+		"postinstall": "npm run --prefix ../util/ link && npm link @fosscord/util && npm run link",
 		"test": "jest",
 		"test:watch": "jest --watch",
 		"start": "npm run build && node dist/start",
@@ -34,6 +36,7 @@
 	"homepage": "https://github.com/fosscord/fosscord-api#readme",
 	"dependencies": {
 		"@fosscord/server-util": "^1.3.52",
+		"@fosscord/util": "file:../util",
 		"@types/jest": "^26.0.22",
 		"@types/json-schema": "^7.0.7",
 		"ajv": "^8.4.0",
diff --git a/api/src/Server.ts b/api/src/Server.ts
index 7299425a..a60c5e4d 100644
--- a/api/src/Server.ts
+++ b/api/src/Server.ts
@@ -3,7 +3,7 @@ import fs from "fs";
 import { Connection } from "mongoose";
 import { Server, ServerOptions } from "lambert-server";
 import { Authentication, CORS } from "./middlewares/";
-import { Config, db, RabbitMQ } from "@fosscord/server-util";
+import { Config, db, initEvent, RabbitMQ } from "@fosscord/util";
 import i18next from "i18next";
 import i18nextMiddleware, { I18next } from "i18next-http-middleware";
 import i18nextBackend from "i18next-node-fs-backend";
@@ -56,9 +56,8 @@ export class FosscordServer extends Server {
 		// @ts-ignore
 		await (db as Promise<Connection>);
 		await this.setupSchema();
-		console.log("[Database] connected");
 		await Config.init();
-		await RabbitMQ.init();
+		await initEvent();
 
 		this.app.use(CORS);
 		this.app.use(Authentication);
@@ -93,11 +92,12 @@ export class FosscordServer extends Server {
 		app.use("/api/v9", api);
 		app.use("/api", api); // allow unversioned requests
 
-		api.get("*", (req: Request, res: Response) => {
+		api.get("*", (req: Request, res: Response, next) => {
 			res.status(404).json({
 				message: "404: Not Found",
 				code: 0
 			});
+			next();
 		});
 
 		this.app = app;
diff --git a/api/src/index.ts b/api/src/index.ts
index 554c296f..6037e31f 100644
--- a/api/src/index.ts
+++ b/api/src/index.ts
@@ -7,9 +7,7 @@ export * from "./schema/Invite";
 export * from "./schema/Message";
 export * from "./util/Config";
 export * from "./util/Constants";
-export * from "./util/Event";
 export * from "./util/instanceOf";
-export * from "./util/Event";
 export * from "./util/instanceOf";
 export * from "./util/Member";
 export * from "./util/RandomInviteID";
diff --git a/api/src/middlewares/Authentication.ts b/api/src/middlewares/Authentication.ts
index 01b7ef57..00cd9ea7 100644
--- a/api/src/middlewares/Authentication.ts
+++ b/api/src/middlewares/Authentication.ts
@@ -1,15 +1,15 @@
 import { NextFunction, Request, Response } from "express";
 import { HTTPError } from "lambert-server";
-import { checkToken, Config } from "@fosscord/server-util";
+import { checkToken, Config } from "@fosscord/util";
 
 export const NO_AUTHORIZATION_ROUTES = [
-	/^\/api(\/v\d+)?\/auth\/login/,
-	/^\/api(\/v\d+)?\/auth\/register/,
-	/^\/api(\/v\d+)?\/webhooks\//,
-	/^\/api(\/v\d+)?\/ping/,
-	/^\/api(\/v\d+)?\/gateway/,
-	/^\/api(\/v\d+)?\/experiments/,
-	/^\/api(\/v\d+)?\/guilds\/\d+\/widget\.(json|png)/
+	"/auth/login",
+	"/auth/register",
+	"/webhooks/",
+	"/ping",
+	"/gateway",
+	"/experiments"
+	// /^\/api(\/v\d+)?\/guilds\/\d+\/widget\.(json|png)/
 ];
 
 export const API_PREFIX = /^\/api(\/v\d+)?/;
@@ -24,13 +24,14 @@ declare global {
 		}
 	}
 }
+// TODO wenn client offen ist, wird http://localhost:8080/api/v9/users/@me/guild-events blockiert?
 
 export async function Authentication(req: Request, res: Response, next: NextFunction) {
 	if (req.method === "OPTIONS") return res.sendStatus(204);
 	if (!req.url.startsWith("/api")) return next();
 	const apiPath = req.url.replace(API_PREFIX, "");
-	if (apiPath.startsWith("/invites") && req.method === "GET") return next();
-	if (NO_AUTHORIZATION_ROUTES.some((x) => x.test(req.url))) return next();
+	if (apiPath.startsWith("/invites") && req.method === "GET") return next(); // @ts-ignore
+	if (NO_AUTHORIZATION_ROUTES.some((x) => apiPath.startsWith(x) || x.test?.(req.url))) return next();
 	if (!req.headers.authorization) return next(new HTTPError("Missing Authorization Header", 401));
 
 	try {
diff --git a/api/src/middlewares/ErrorHandler.ts b/api/src/middlewares/ErrorHandler.ts
index 2e6b1d8b..04d56026 100644
--- a/api/src/middlewares/ErrorHandler.ts
+++ b/api/src/middlewares/ErrorHandler.ts
@@ -25,8 +25,6 @@ export function ErrorHandler(error: Error, req: Request, res: Response, next: Ne
 		if (httpcode > 511) httpcode = 400;
 
 		res.status(httpcode).json({ code: code, message, errors });
-
-		return;
 	} catch (error) {
 		console.error(error);
 		return res.status(500).json({ code: 500, message: "Internal Server Error" });
diff --git a/api/src/middlewares/RateLimit.ts b/api/src/middlewares/RateLimit.ts
index c8fdeba2..a1bb0c44 100644
--- a/api/src/middlewares/RateLimit.ts
+++ b/api/src/middlewares/RateLimit.ts
@@ -1,16 +1,17 @@
-import { db, MongooseCache, Bucket, Config } from "@fosscord/server-util";
+// @ts-nocheck
+import { db, Bucket, Config } from "@fosscord/util";
 import { NextFunction, Request, Response, Router } from "express";
 import { getIpAdress } from "../util/ipAddress";
 import { API_PREFIX_TRAILING_SLASH } from "./Authentication";
 
-const Cache = new MongooseCache(
-	db.collection("ratelimits"),
-	[
-		// TODO: uncomment $match and fix error: not receiving change events
-		// { $match: { blocked: true } }
-	],
-	{ onlyEvents: false, array: true }
-);
+// const Cache = new MongooseCache(
+// 	db.collection("ratelimits"),
+// 	[
+// 		// TODO: uncomment $match and fix error: not receiving change events
+// 		// { $match: { blocked: true } }
+// 	],
+// 	{ onlyEvents: false, array: true }
+// );
 
 // Docs: https://discord.com/developers/docs/topics/rate-limits
 
@@ -31,6 +32,7 @@ TODO: use config values
 
 */
 
+// TODO: FIX with new event handling
 export default function RateLimit(opts: {
 	bucket?: string;
 	window: number;
@@ -44,6 +46,7 @@ export default function RateLimit(opts: {
 	success?: boolean;
 	onlyIp?: boolean;
 }): any {
+	return (req, res, next) => next();
 	Cache.init(); // will only initalize it once
 
 	return async (req: Request, res: Response, next: NextFunction): Promise<any> => {
diff --git a/api/src/routes/auth/login.ts b/api/src/routes/auth/login.ts
index c3661608..f55d5351 100644
--- a/api/src/routes/auth/login.ts
+++ b/api/src/routes/auth/login.ts
@@ -2,7 +2,7 @@ import { Request, Response, Router } from "express";
 import { check, FieldErrors, Length } from "../../util/instanceOf";
 import bcrypt from "bcrypt";
 import jwt from "jsonwebtoken";
-import { Config, UserModel } from "@fosscord/server-util";
+import { Config, UserModel } from "@fosscord/util";
 import { adjustEmail } from "./register";
 import RateLimit from "../../middlewares/RateLimit";
 
diff --git a/api/src/routes/auth/register.ts b/api/src/routes/auth/register.ts
index 66a1fc8d..fecde874 100644
--- a/api/src/routes/auth/register.ts
+++ b/api/src/routes/auth/register.ts
@@ -1,5 +1,5 @@
 import { Request, Response, Router } from "express";
-import { trimSpecial, User, Snowflake, UserModel, Config } from "@fosscord/server-util";
+import { trimSpecial, User, Snowflake, UserModel, Config } from "@fosscord/util";
 import bcrypt from "bcrypt";
 import { check, Email, EMAIL_REGEX, FieldErrors, Length } from "../../util/instanceOf";
 import "missing-native-js-functions";
diff --git a/api/src/routes/channels/#channel_id/index.ts b/api/src/routes/channels/#channel_id/index.ts
index 81e5054e..3bfa80be 100644
--- a/api/src/routes/channels/#channel_id/index.ts
+++ b/api/src/routes/channels/#channel_id/index.ts
@@ -1,8 +1,7 @@
-import { ChannelDeleteEvent, ChannelModel, ChannelUpdateEvent, getPermission, GuildUpdateEvent, toObject } from "@fosscord/server-util";
+import { ChannelDeleteEvent, ChannelModel, ChannelUpdateEvent, emitEvent, getPermission, GuildUpdateEvent, toObject } from "@fosscord/util";
 import { Router, Response, Request } from "express";
 import { HTTPError } from "lambert-server";
 import { ChannelModifySchema } from "../../../schema/Channel";
-import { emitEvent } from "../../../util/Event";
 import { check } from "../../../util/instanceOf";
 const router: Router = Router();
 // TODO: delete channel
diff --git a/api/src/routes/channels/#channel_id/invites.ts b/api/src/routes/channels/#channel_id/invites.ts
index c9db4dd2..438f8c51 100644
--- a/api/src/routes/channels/#channel_id/invites.ts
+++ b/api/src/routes/channels/#channel_id/invites.ts
@@ -3,11 +3,10 @@ import { HTTPError } from "lambert-server";
 
 import { check } from "../../../util/instanceOf";
 import { random } from "../../../util/RandomInviteID";
-import { emitEvent } from "../../../util/Event";
 
 import { InviteCreateSchema } from "../../../schema/Invite";
 
-import { getPermission, ChannelModel, InviteModel, InviteCreateEvent, toObject } from "@fosscord/server-util";
+import { getPermission, ChannelModel, InviteModel, InviteCreateEvent, toObject, emitEvent } from "@fosscord/util";
 
 const router: Router = Router();
 
diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts b/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts
index f4d9e696..bbc779dd 100644
--- a/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts
+++ b/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts
@@ -1,6 +1,6 @@
-import { getPermission, MessageAckEvent, ReadStateModel } from "@fosscord/server-util";
+import { emitEvent, getPermission, MessageAckEvent, ReadStateModel } from "@fosscord/util";
 import { Request, Response, Router } from "express";
-import { emitEvent } from "../../../../../util/Event";
+
 import { check } from "../../../../../util/instanceOf";
 
 const router = Router();
diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts
index a7c23d2f..3c58d034 100644
--- a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts
+++ b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts
@@ -1,8 +1,8 @@
-import { ChannelModel, getPermission, MessageDeleteEvent, MessageModel, MessageUpdateEvent, toObject } from "@fosscord/server-util";
+import { ChannelModel, emitEvent, getPermission, MessageDeleteEvent, MessageModel, MessageUpdateEvent, toObject } from "@fosscord/util";
 import { Router, Response, Request } from "express";
 import { HTTPError } from "lambert-server";
 import { MessageCreateSchema } from "../../../../../schema/Message";
-import { emitEvent } from "../../../../../util/Event";
+
 import { check } from "../../../../../util/instanceOf";
 import { handleMessage, postHandleMessage } from "../../../../../util/Message";
 
diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/reactions.ts b/api/src/routes/channels/#channel_id/messages/#message_id/reactions.ts
index 168a870f..34d2ce3a 100644
--- a/api/src/routes/channels/#channel_id/messages/#message_id/reactions.ts
+++ b/api/src/routes/channels/#channel_id/messages/#message_id/reactions.ts
@@ -1,5 +1,6 @@
 import {
 	ChannelModel,
+	emitEvent,
 	EmojiModel,
 	getPermission,
 	MemberModel,
@@ -12,10 +13,9 @@ import {
 	PublicUserProjection,
 	toObject,
 	UserModel
-} from "@fosscord/server-util";
+} from "@fosscord/util";
 import { Router, Response, Request } from "express";
 import { HTTPError } from "lambert-server";
-import { emitEvent } from "../../../../../util/Event";
 
 const router = Router();
 // TODO: check if emoji is really an unicode emoji or a prperly encoded external emoji
diff --git a/api/src/routes/channels/#channel_id/messages/bulk-delete.ts b/api/src/routes/channels/#channel_id/messages/bulk-delete.ts
index e53cd597..8132462f 100644
--- a/api/src/routes/channels/#channel_id/messages/bulk-delete.ts
+++ b/api/src/routes/channels/#channel_id/messages/bulk-delete.ts
@@ -1,7 +1,7 @@
 import { Router, Response, Request } from "express";
-import { ChannelModel, Config, getPermission, MessageDeleteBulkEvent, MessageModel } from "@fosscord/server-util";
+import { ChannelModel, Config, emitEvent, getPermission, MessageDeleteBulkEvent, MessageModel } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
-import { emitEvent } from "../../../../util/Event";
+
 import { check } from "../../../../util/instanceOf";
 
 const router: Router = Router();
diff --git a/api/src/routes/channels/#channel_id/messages/index.ts b/api/src/routes/channels/#channel_id/messages/index.ts
index fea4d6a4..6ae6491f 100644
--- a/api/src/routes/channels/#channel_id/messages/index.ts
+++ b/api/src/routes/channels/#channel_id/messages/index.ts
@@ -1,5 +1,5 @@
 import { Router, Response, Request } from "express";
-import { Attachment, ChannelModel, ChannelType, getPermission, MessageDocument, MessageModel, toObject } from "@fosscord/server-util";
+import { Attachment, ChannelModel, ChannelType, getPermission, MessageDocument, MessageModel, toObject } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { MessageCreateSchema } from "../../../../schema/Message";
 import { check, instanceOf, Length } from "../../../../util/instanceOf";
diff --git a/api/src/routes/channels/#channel_id/permissions.ts b/api/src/routes/channels/#channel_id/permissions.ts
index 12364293..4cbc7522 100644
--- a/api/src/routes/channels/#channel_id/permissions.ts
+++ b/api/src/routes/channels/#channel_id/permissions.ts
@@ -1,7 +1,15 @@
-import { ChannelModel, ChannelPermissionOverwrite, ChannelUpdateEvent, getPermission, MemberModel, RoleModel } from "@fosscord/server-util";
+import {
+	ChannelModel,
+	ChannelPermissionOverwrite,
+	ChannelUpdateEvent,
+	emitEvent,
+	getPermission,
+	MemberModel,
+	RoleModel
+} from "@fosscord/util";
 import { Router, Response, Request } from "express";
 import { HTTPError } from "lambert-server";
-import { emitEvent } from "../../../util/Event";
+
 import { check } from "../../../util/instanceOf";
 const router: Router = Router();
 
diff --git a/api/src/routes/channels/#channel_id/pins.ts b/api/src/routes/channels/#channel_id/pins.ts
index 65d6b975..18a5861b 100644
--- a/api/src/routes/channels/#channel_id/pins.ts
+++ b/api/src/routes/channels/#channel_id/pins.ts
@@ -2,14 +2,14 @@ import {
 	ChannelModel,
 	ChannelPinsUpdateEvent,
 	Config,
+	emitEvent,
 	getPermission,
 	MessageModel,
 	MessageUpdateEvent,
 	toObject
-} from "@fosscord/server-util";
+} from "@fosscord/util";
 import { Router, Request, Response } from "express";
 import { HTTPError } from "lambert-server";
-import { emitEvent } from "../../../util/Event";
 
 const router: Router = Router();
 
diff --git a/api/src/routes/channels/#channel_id/typing.ts b/api/src/routes/channels/#channel_id/typing.ts
index de549883..21d453d8 100644
--- a/api/src/routes/channels/#channel_id/typing.ts
+++ b/api/src/routes/channels/#channel_id/typing.ts
@@ -1,8 +1,7 @@
-import { ChannelModel, MemberModel, toObject, TypingStartEvent } from "@fosscord/server-util";
+import { ChannelModel, emitEvent, MemberModel, toObject, TypingStartEvent } from "@fosscord/util";
 import { Router, Request, Response } from "express";
 
 import { HTTPError } from "lambert-server";
-import { emitEvent } from "../../../util/Event";
 
 const router: Router = Router();
 
diff --git a/api/src/routes/channels/#channel_id/webhooks.ts b/api/src/routes/channels/#channel_id/webhooks.ts
index 6c1aea2a..7852f8f3 100644
--- a/api/src/routes/channels/#channel_id/webhooks.ts
+++ b/api/src/routes/channels/#channel_id/webhooks.ts
@@ -1,6 +1,6 @@
 import { Router, Response, Request } from "express";
 import { check, Length } from "../../../util/instanceOf";
-import { ChannelModel, getPermission, trimSpecial } from "@fosscord/server-util";
+import { ChannelModel, getPermission, trimSpecial } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { isTextChannel } from "./messages/index";
 
diff --git a/api/src/routes/gateway.ts b/api/src/routes/gateway.ts
index f2bc5b34..3120718e 100644
--- a/api/src/routes/gateway.ts
+++ b/api/src/routes/gateway.ts
@@ -1,4 +1,4 @@
-import { Config } from "@fosscord/server-util";
+import { Config } from "@fosscord/util";
 import { Router, Response, Request } from "express";
 
 const router = Router();
diff --git a/api/src/routes/guilds/#guild_id/bans.ts b/api/src/routes/guilds/#guild_id/bans.ts
index d9752f61..bb3eac03 100644
--- a/api/src/routes/guilds/#guild_id/bans.ts
+++ b/api/src/routes/guilds/#guild_id/bans.ts
@@ -1,9 +1,9 @@
 import { Request, Response, Router } from "express";
-import { BanModel, getPermission, GuildBanAddEvent, GuildBanRemoveEvent, GuildModel, toObject } from "@fosscord/server-util";
+import { BanModel, emitEvent, getPermission, GuildBanAddEvent, GuildBanRemoveEvent, GuildModel, toObject } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { getIpAdress } from "../../../util/ipAddress";
 import { BanCreateSchema } from "../../../schema/Ban";
-import { emitEvent } from "../../../util/Event";
+
 import { check } from "../../../util/instanceOf";
 import { removeMember } from "../../../util/Member";
 import { getPublicUser } from "../../../util/User";
diff --git a/api/src/routes/guilds/#guild_id/channels.ts b/api/src/routes/guilds/#guild_id/channels.ts
index 52361f5e..8d97cf96 100644
--- a/api/src/routes/guilds/#guild_id/channels.ts
+++ b/api/src/routes/guilds/#guild_id/channels.ts
@@ -8,11 +8,12 @@ import {
 	toObject,
 	ChannelUpdateEvent,
 	AnyChannel,
-	getPermission
-} from "@fosscord/server-util";
+	getPermission,
+	emitEvent
+} from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { ChannelModifySchema } from "../../../schema/Channel";
-import { emitEvent } from "../../../util/Event";
+
 import { check } from "../../../util/instanceOf";
 import { createChannel } from "../../../util/Channel";
 const router = Router();
@@ -64,7 +65,7 @@ router.patch(
 
 		const channel = await ChannelModel.findOneAndUpdate({ id: req.body, guild_id }, opts).exec();
 
-		await emitEvent({ event: "CHANNEL_UPDATE", data: channel, channel_id: body.id, guild_id } as ChannelUpdateEvent);
+		await emitEvent({ event: "CHANNEL_UPDATE", data: toObject(channel), channel_id: body.id, guild_id } as ChannelUpdateEvent);
 
 		res.json(toObject(channel));
 	}
diff --git a/api/src/routes/guilds/#guild_id/delete.ts b/api/src/routes/guilds/#guild_id/delete.ts
index 6cca289e..ba1c2fde 100644
--- a/api/src/routes/guilds/#guild_id/delete.ts
+++ b/api/src/routes/guilds/#guild_id/delete.ts
@@ -1,5 +1,6 @@
 import {
 	ChannelModel,
+	emitEvent,
 	EmojiModel,
 	GuildDeleteEvent,
 	GuildModel,
@@ -8,10 +9,9 @@ import {
 	MessageModel,
 	RoleModel,
 	UserModel
-} from "@fosscord/server-util";
+} from "@fosscord/util";
 import { Router, Request, Response } from "express";
 import { HTTPError } from "lambert-server";
-import { emitEvent } from "../../../util/Event";
 
 const router = Router();
 
diff --git a/api/src/routes/guilds/#guild_id/index.ts b/api/src/routes/guilds/#guild_id/index.ts
index dc4ddb39..1afa603f 100644
--- a/api/src/routes/guilds/#guild_id/index.ts
+++ b/api/src/routes/guilds/#guild_id/index.ts
@@ -1,6 +1,7 @@
 import { Request, Response, Router } from "express";
 import {
 	ChannelModel,
+	emitEvent,
 	EmojiModel,
 	getPermission,
 	GuildDeleteEvent,
@@ -12,10 +13,10 @@ import {
 	RoleModel,
 	toObject,
 	UserModel
-} from "@fosscord/server-util";
+} from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { GuildUpdateSchema } from "../../../schema/Guild";
-import { emitEvent } from "../../../util/Event";
+
 import { check } from "../../../util/instanceOf";
 import { handleFile } from "../../../util/cdn";
 import "missing-native-js-functions";
diff --git a/api/src/routes/guilds/#guild_id/invites.ts b/api/src/routes/guilds/#guild_id/invites.ts
index 1894ec96..08048d61 100644
--- a/api/src/routes/guilds/#guild_id/invites.ts
+++ b/api/src/routes/guilds/#guild_id/invites.ts
@@ -1,4 +1,4 @@
-import { getPermission, InviteModel, toObject } from "@fosscord/server-util";
+import { getPermission, InviteModel, toObject } from "@fosscord/util";
 import { Request, Response, Router } from "express";
 
 const router = Router();
diff --git a/api/src/routes/guilds/#guild_id/members/#member_id/index.ts b/api/src/routes/guilds/#guild_id/members/#member_id/index.ts
index 9a1676e6..eac6684a 100644
--- a/api/src/routes/guilds/#guild_id/members/#member_id/index.ts
+++ b/api/src/routes/guilds/#guild_id/members/#member_id/index.ts
@@ -8,13 +8,13 @@ import {
 	getPermission,
 	PermissionResolvable,
 	RoleModel,
-	GuildMemberUpdateEvent
-} from "@fosscord/server-util";
+	GuildMemberUpdateEvent,
+	emitEvent
+} from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { addMember, isMember, removeMember } from "../../../../../util/Member";
 import { check } from "../../../../../util/instanceOf";
 import { MemberChangeSchema } from "../../../../../schema/Member";
-import { emitEvent } from "../../../../../util/Event";
 
 const router = Router();
 
diff --git a/api/src/routes/guilds/#guild_id/members/#member_id/nick.ts b/api/src/routes/guilds/#guild_id/members/#member_id/nick.ts
index 9078409d..5784b5d5 100644
--- a/api/src/routes/guilds/#guild_id/members/#member_id/nick.ts
+++ b/api/src/routes/guilds/#guild_id/members/#member_id/nick.ts
@@ -1,4 +1,4 @@
-import { getPermission, PermissionResolvable } from "@fosscord/server-util";
+import { getPermission, PermissionResolvable } from "@fosscord/util";
 import { Request, Response, Router } from "express";
 import { check } from "lambert-server";
 import { MemberNickChangeSchema } from "../../../../../schema/Member";
diff --git a/api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts b/api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts
index b7a43c74..fad0695e 100644
--- a/api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts
+++ b/api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts
@@ -1,4 +1,4 @@
-import { getPermission } from "@fosscord/server-util";
+import { getPermission } from "@fosscord/util";
 import { Request, Response, Router } from "express";
 import { addRole, removeRole } from "../../../../../../../util/Member";
 
diff --git a/api/src/routes/guilds/#guild_id/members/index.ts b/api/src/routes/guilds/#guild_id/members/index.ts
index a157d8f5..70303436 100644
--- a/api/src/routes/guilds/#guild_id/members/index.ts
+++ b/api/src/routes/guilds/#guild_id/members/index.ts
@@ -1,5 +1,5 @@
 import { Request, Response, Router } from "express";
-import { GuildModel, MemberModel, toObject } from "@fosscord/server-util";
+import { GuildModel, MemberModel, toObject } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { instanceOf, Length } from "../../../../util/instanceOf";
 import { PublicMemberProjection, isMember } from "../../../../util/Member";
diff --git a/api/src/routes/guilds/#guild_id/regions.ts b/api/src/routes/guilds/#guild_id/regions.ts
index 3a46d766..5ec649ee 100644
--- a/api/src/routes/guilds/#guild_id/regions.ts
+++ b/api/src/routes/guilds/#guild_id/regions.ts
@@ -1,4 +1,4 @@
-import { Config } from "@fosscord/server-util";
+import { Config } from "@fosscord/util";
 import { Request, Response, Router } from "express";
 
 const router = Router();
@@ -7,4 +7,4 @@ router.get("/", async (req: Request, res: Response) => {
 	return res.json(Config.get().regions.available);
 });
 
-export default router;
\ No newline at end of file
+export default router;
diff --git a/api/src/routes/guilds/#guild_id/roles.ts b/api/src/routes/guilds/#guild_id/roles.ts
index 77206a0f..a4bc44e0 100644
--- a/api/src/routes/guilds/#guild_id/roles.ts
+++ b/api/src/routes/guilds/#guild_id/roles.ts
@@ -9,10 +9,11 @@ import {
 	MemberModel,
 	GuildRoleCreateEvent,
 	GuildRoleUpdateEvent,
-	GuildRoleDeleteEvent
-} from "@fosscord/server-util";
+	GuildRoleDeleteEvent,
+	emitEvent
+} from "@fosscord/util";
 import { HTTPError } from "lambert-server";
-import { emitEvent } from "../../../util/Event";
+
 import { check } from "../../../util/instanceOf";
 import { RoleModifySchema } from "../../../schema/Roles";
 import { getPublicUser } from "../../../util/User";
diff --git a/api/src/routes/guilds/#guild_id/templates.ts b/api/src/routes/guilds/#guild_id/templates.ts
index 8306ac37..fdca1c40 100644
--- a/api/src/routes/guilds/#guild_id/templates.ts
+++ b/api/src/routes/guilds/#guild_id/templates.ts
@@ -1,5 +1,5 @@
 import { Request, Response, Router } from "express";
-import { TemplateModel, GuildModel, getPermission, toObject, UserModel, Snowflake } from "@fosscord/server-util";
+import { TemplateModel, GuildModel, getPermission, toObject, UserModel, Snowflake } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { TemplateCreateSchema, TemplateModifySchema } from "../../../schema/Template";
 import { check } from "../../../util/instanceOf";
diff --git a/api/src/routes/guilds/#guild_id/vanity-url.ts b/api/src/routes/guilds/#guild_id/vanity-url.ts
index 323b2647..86adfeb0 100644
--- a/api/src/routes/guilds/#guild_id/vanity-url.ts
+++ b/api/src/routes/guilds/#guild_id/vanity-url.ts
@@ -1,4 +1,4 @@
-import { getPermission, GuildModel, InviteModel, trimSpecial } from "@fosscord/server-util";
+import { getPermission, GuildModel, InviteModel, trimSpecial } from "@fosscord/util";
 import { Router, Request, Response } from "express";
 import { HTTPError } from "lambert-server";
 import { check, Length } from "../../../util/instanceOf";
diff --git a/api/src/routes/guilds/#guild_id/welcome_screen.ts b/api/src/routes/guilds/#guild_id/welcome_screen.ts
index 656a0ee0..c717042e 100644
--- a/api/src/routes/guilds/#guild_id/welcome_screen.ts
+++ b/api/src/routes/guilds/#guild_id/welcome_screen.ts
@@ -1,7 +1,7 @@
 import { Request, Response, Router } from "express";
-import { GuildModel, getPermission, toObject, Snowflake } from "@fosscord/server-util";
+import { GuildModel, getPermission, toObject, Snowflake } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
-import { emitEvent } from "../../../util/Event";
+
 import { check } from "../../../util/instanceOf";
 import { isMember } from "../../../util/Member";
 import { GuildAddChannelToWelcomeScreenSchema } from "../../../schema/Guild";
diff --git a/api/src/routes/guilds/#guild_id/widget.json.ts b/api/src/routes/guilds/#guild_id/widget.json.ts
index 6f777ab4..8719bd85 100644
--- a/api/src/routes/guilds/#guild_id/widget.json.ts
+++ b/api/src/routes/guilds/#guild_id/widget.json.ts
@@ -1,5 +1,5 @@
 import { Request, Response, Router } from "express";
-import { Config, Permissions, GuildModel, InviteModel, ChannelModel, MemberModel } from "@fosscord/server-util";
+import { Config, Permissions, GuildModel, InviteModel, ChannelModel, MemberModel } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { random } from "../../../util/RandomInviteID";
 
diff --git a/api/src/routes/guilds/#guild_id/widget.png.ts b/api/src/routes/guilds/#guild_id/widget.png.ts
index a0a8c938..80dc9f2b 100644
--- a/api/src/routes/guilds/#guild_id/widget.png.ts
+++ b/api/src/routes/guilds/#guild_id/widget.png.ts
@@ -1,5 +1,5 @@
 import { Request, Response, Router } from "express";
-import { GuildModel } from "@fosscord/server-util";
+import { GuildModel } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import fs from "fs";
 import path from "path";
diff --git a/api/src/routes/guilds/#guild_id/widget.ts b/api/src/routes/guilds/#guild_id/widget.ts
index 0e6df186..85eed5e9 100644
--- a/api/src/routes/guilds/#guild_id/widget.ts
+++ b/api/src/routes/guilds/#guild_id/widget.ts
@@ -1,5 +1,5 @@
 import { Request, Response, Router } from "express";
-import { getPermission, GuildModel } from "@fosscord/server-util";
+import { getPermission, GuildModel } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { check } from "../../../util/instanceOf";
 import { WidgetModifySchema } from "../../../schema/Widget";
diff --git a/api/src/routes/guilds/index.ts b/api/src/routes/guilds/index.ts
index 25b55896..c97a8205 100644
--- a/api/src/routes/guilds/index.ts
+++ b/api/src/routes/guilds/index.ts
@@ -1,5 +1,5 @@
 import { Router, Request, Response } from "express";
-import { RoleModel, GuildModel, Snowflake, Guild, RoleDocument, Config } from "@fosscord/server-util";
+import { RoleModel, GuildModel, Snowflake, Guild, RoleDocument, Config } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { check } from "./../../util/instanceOf";
 import { GuildCreateSchema } from "../../schema/Guild";
diff --git a/api/src/routes/guilds/templates/index.ts b/api/src/routes/guilds/templates/index.ts
index 0f332de0..7fed3c5d 100644
--- a/api/src/routes/guilds/templates/index.ts
+++ b/api/src/routes/guilds/templates/index.ts
@@ -1,6 +1,6 @@
 import { Request, Response, Router } from "express";
 const router: Router = Router();
-import { TemplateModel, GuildModel, toObject, UserModel, RoleModel, Snowflake, Guild, Config } from "@fosscord/server-util";
+import { TemplateModel, GuildModel, toObject, UserModel, RoleModel, Snowflake, Guild, Config } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { GuildTemplateCreateSchema } from "../../../schema/Guild";
 import { getPublicUser } from "../../../util/User";
diff --git a/api/src/routes/invites/index.ts b/api/src/routes/invites/index.ts
index 8c04713c..992694df 100644
--- a/api/src/routes/invites/index.ts
+++ b/api/src/routes/invites/index.ts
@@ -1,5 +1,5 @@
 import { Router, Request, Response } from "express";
-import { getPermission, InviteModel, toObject } from "@fosscord/server-util";
+import { getPermission, InviteModel, toObject } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { addMember } from "../../util/Member";
 const router: Router = Router();
diff --git a/api/src/routes/users/@me/channels.ts b/api/src/routes/users/@me/channels.ts
index a425a25f..db9f8832 100644
--- a/api/src/routes/users/@me/channels.ts
+++ b/api/src/routes/users/@me/channels.ts
@@ -8,10 +8,11 @@ import {
 	trimSpecial,
 	Channel,
 	DMChannel,
-	UserModel
-} from "@fosscord/server-util";
+	UserModel,
+	emitEvent
+} from "@fosscord/util";
 import { HTTPError } from "lambert-server";
-import { emitEvent } from "../../../util/Event";
+
 import { DmChannelCreateSchema } from "../../../schema/Channel";
 import { check } from "../../../util/instanceOf";
 
diff --git a/api/src/routes/users/@me/delete.ts b/api/src/routes/users/@me/delete.ts
index edda8e2d..f863237d 100644
--- a/api/src/routes/users/@me/delete.ts
+++ b/api/src/routes/users/@me/delete.ts
@@ -1,5 +1,5 @@
 import { Router, Request, Response } from "express";
-import { GuildModel, MemberModel, UserModel } from "@fosscord/server-util";
+import { GuildModel, MemberModel, UserModel } from "@fosscord/util";
 import bcrypt from "bcrypt";
 const router = Router();
 
diff --git a/api/src/routes/users/@me/disable.ts b/api/src/routes/users/@me/disable.ts
index 0e5b734e..2d3a9850 100644
--- a/api/src/routes/users/@me/disable.ts
+++ b/api/src/routes/users/@me/disable.ts
@@ -1,4 +1,4 @@
-import { UserModel } from "@fosscord/server-util";
+import { UserModel } from "@fosscord/util";
 import { Router, Response, Request } from "express";
 import bcrypt from "bcrypt";
 
diff --git a/api/src/routes/users/@me/guilds.ts b/api/src/routes/users/@me/guilds.ts
index 6528552b..a9b53b75 100644
--- a/api/src/routes/users/@me/guilds.ts
+++ b/api/src/routes/users/@me/guilds.ts
@@ -1,7 +1,7 @@
 import { Router, Request, Response } from "express";
-import { GuildModel, MemberModel, UserModel, GuildDeleteEvent, GuildMemberRemoveEvent, toObject } from "@fosscord/server-util";
+import { GuildModel, MemberModel, UserModel, GuildDeleteEvent, GuildMemberRemoveEvent, toObject, emitEvent } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
-import { emitEvent } from "../../../util/Event";
+
 import { getPublicUser } from "../../../util/User";
 
 const router: Router = Router();
@@ -32,10 +32,10 @@ router.delete("/:id", async (req: Request, res: Response) => {
 		emitEvent({
 			event: "GUILD_DELETE",
 			data: {
-				id: guild_id,
+				id: guild_id
 			},
-			user_id: req.user_id,
-		} as GuildDeleteEvent),
+			user_id: req.user_id
+		} as GuildDeleteEvent)
 	]);
 
 	const user = await getPublicUser(req.user_id);
@@ -44,9 +44,9 @@ router.delete("/:id", async (req: Request, res: Response) => {
 		event: "GUILD_MEMBER_REMOVE",
 		data: {
 			guild_id: guild_id,
-			user: user,
+			user: user
 		},
-		guild_id: guild_id,
+		guild_id: guild_id
 	} as GuildMemberRemoveEvent);
 
 	return res.sendStatus(204);
diff --git a/api/src/routes/users/@me/index.ts b/api/src/routes/users/@me/index.ts
index 7bd4a486..c073e78a 100644
--- a/api/src/routes/users/@me/index.ts
+++ b/api/src/routes/users/@me/index.ts
@@ -1,5 +1,5 @@
 import { Router, Request, Response } from "express";
-import { UserModel, toObject, PublicUserProjection } from "@fosscord/server-util";
+import { UserModel, toObject, PublicUserProjection } from "@fosscord/util";
 import { getPublicUser } from "../../../util/User";
 import { UserModifySchema } from "../../../schema/User";
 import { check } from "../../../util/instanceOf";
diff --git a/api/src/routes/users/@me/relationships.ts b/api/src/routes/users/@me/relationships.ts
index a8f03143..642ee5f9 100644
--- a/api/src/routes/users/@me/relationships.ts
+++ b/api/src/routes/users/@me/relationships.ts
@@ -5,11 +5,12 @@ import {
 	toObject,
 	RelationshipType,
 	RelationshipRemoveEvent,
-	UserDocument
-} from "@fosscord/server-util";
+	UserDocument,
+	emitEvent
+} from "@fosscord/util";
 import { Router, Response, Request } from "express";
 import { HTTPError } from "lambert-server";
-import { emitEvent } from "../../../util/Event";
+
 import { check, Length } from "../../../util/instanceOf";
 
 const router = Router();
diff --git a/api/src/schema/Channel.ts b/api/src/schema/Channel.ts
index 48c3a1d2..18a8f835 100644
--- a/api/src/schema/Channel.ts
+++ b/api/src/schema/Channel.ts
@@ -1,4 +1,4 @@
-import { ChannelType } from "@fosscord/server-util";
+import { ChannelType } from "@fosscord/util";
 import { Length } from "../util/instanceOf";
 
 export const ChannelModifySchema = {
diff --git a/api/src/schema/Guild.ts b/api/src/schema/Guild.ts
index 0443e64c..ce40b49f 100644
--- a/api/src/schema/Guild.ts
+++ b/api/src/schema/Guild.ts
@@ -1,4 +1,4 @@
-import { ChannelSchema, GuildChannel } from "@fosscord/server-util";
+import { ChannelSchema, GuildChannel } from "@fosscord/util";
 import { Length } from "../util/instanceOf";
 
 export const GuildCreateSchema = {
diff --git a/api/src/schema/Message.ts b/api/src/schema/Message.ts
index 8423d706..2dd54f0c 100644
--- a/api/src/schema/Message.ts
+++ b/api/src/schema/Message.ts
@@ -1,4 +1,4 @@
-import { Embed, EmbedImage } from "@fosscord/server-util";
+import { Embed, EmbedImage } from "@fosscord/util";
 import { Length } from "../util/instanceOf";
 
 export const MessageCreateSchema = {
diff --git a/api/src/test/test.ts b/api/src/test/test.ts
index 478edcc4..c37c762b 100644
--- a/api/src/test/test.ts
+++ b/api/src/test/test.ts
@@ -1,3 +1,3 @@
-import { Snowflake } from "@fosscord/server-util";
+import { Snowflake } from "@fosscord/util";
 
 console.log(Snowflake.deconstruct("0"));
diff --git a/api/src/util/Channel.ts b/api/src/util/Channel.ts
index 4d322812..ef04d521 100644
--- a/api/src/util/Channel.ts
+++ b/api/src/util/Channel.ts
@@ -2,18 +2,18 @@ import {
 	ChannelCreateEvent,
 	ChannelModel,
 	ChannelType,
+	emitEvent,
 	getPermission,
 	GuildModel,
 	Snowflake,
 	TextChannel,
+	toObject,
 	VoiceChannel
-} from "@fosscord/server-util";
+} from "@fosscord/util";
 import { HTTPError } from "lambert-server";
-import { emitEvent } from "./Event";
 
 // TODO: DM channel
 export async function createChannel(channel: Partial<TextChannel | VoiceChannel>, user_id: string = "0") {
-
 	// Always check if user has permission first
 	const permissions = await getPermission(user_id, channel.guild_id);
 	permissions.hasThrow("MANAGE_CHANNELS");
@@ -50,7 +50,7 @@ export async function createChannel(channel: Partial<TextChannel | VoiceChannel>
 		recipient_ids: null
 	}).save();
 
-	await emitEvent({ event: "CHANNEL_CREATE", data: channel, guild_id: channel.guild_id } as ChannelCreateEvent);
+	await emitEvent({ event: "CHANNEL_CREATE", data: toObject(channel), guild_id: channel.guild_id } as ChannelCreateEvent);
 
 	return channel;
 }
diff --git a/api/src/util/Config.ts b/api/src/util/Config.ts
index e2e0d312..c86afbe7 100644
--- a/api/src/util/Config.ts
+++ b/api/src/util/Config.ts
@@ -1,7 +1,7 @@
 // @ts-nocheck
 import Ajv, { JSONSchemaType } from "ajv";
-import { getConfigPathForFile } from "@fosscord/server-util/dist/util/Config";
-import { Config } from "@fosscord/server-util";
+import { getConfigPathForFile } from "@fosscord/util/dist/util/Config";
+import { Config } from "@fosscord/util";
 
 export interface RateLimitOptions {
 	count: number;
diff --git a/api/src/util/Event.ts b/api/src/util/Event.ts
deleted file mode 100644
index 4dd56417..00000000
--- a/api/src/util/Event.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { Config, Event, EventModel, RabbitMQ } from "@fosscord/server-util";
-
-export async function emitEvent(payload: Omit<Event, "created_at">) {
-	if (RabbitMQ.connection) {
-		const id = (payload.channel_id || payload.user_id || payload.guild_id) as string;
-		if (!id) console.error("event doesn't contain any id", payload);
-		const data = typeof payload.data === "object" ? JSON.stringify(payload.data) : payload.data; // use rabbitmq for event transmission
-		await RabbitMQ.channel?.assertExchange(id, "fanout", { durable: false });
-
-		// assertQueue isn't needed, because a queue will automatically created if it doesn't exist
-		const successful = RabbitMQ.channel?.publish(id, "", Buffer.from(`${data}`), { type: payload.event });
-		if (!successful) throw new Error("failed to send event");
-	} else {
-		// use mongodb for event transmission
-		// TODO: use event emitter for local server bundle
-		const obj = {
-			created_at: new Date(), // in seconds
-			...payload
-		};
-		// TODO: bigint isn't working
-
-		return await new EventModel(obj).save();
-	}
-}
-
-export async function emitAuditLog(payload: any) {}
diff --git a/api/src/util/Member.ts b/api/src/util/Member.ts
index 7b06720b..ee3f64ad 100644
--- a/api/src/util/Member.ts
+++ b/api/src/util/Member.ts
@@ -11,11 +11,12 @@ import {
 	toObject,
 	UserModel,
 	GuildDocument,
-	Config
-} from "@fosscord/server-util";
+	Config,
+	emitEvent
+} from "@fosscord/util";
 
 import { HTTPError } from "lambert-server";
-import { emitEvent } from "./Event";
+
 import { getPublicUser } from "./User";
 
 export const PublicMemberProjection = {
diff --git a/api/src/util/Message.ts b/api/src/util/Message.ts
index e811f522..a55c3365 100644
--- a/api/src/util/Message.ts
+++ b/api/src/util/Message.ts
@@ -1,14 +1,14 @@
-import { ChannelModel, Embed, Message, MessageCreateEvent, MessageUpdateEvent } from "@fosscord/server-util";
-import { Snowflake } from "@fosscord/server-util";
-import { MessageModel } from "@fosscord/server-util";
-import { PublicMemberProjection } from "@fosscord/server-util";
-import { toObject } from "@fosscord/server-util";
-import { getPermission } from "@fosscord/server-util";
+import { ChannelModel, Embed, emitEvent, Message, MessageCreateEvent, MessageUpdateEvent } from "@fosscord/util";
+import { Snowflake } from "@fosscord/util";
+import { MessageModel } from "@fosscord/util";
+import { PublicMemberProjection } from "@fosscord/util";
+import { toObject } from "@fosscord/util";
+import { getPermission } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import fetch from "node-fetch";
 import cheerio from "cheerio";
-import { emitEvent } from "./Event";
-import { MessageType } from "@fosscord/server-util/dist/util/Constants";
+
+import { MessageType } from "@fosscord/util/dist/util/Constants";
 // TODO: check webhook, application, system author
 
 const LINK_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g;
diff --git a/api/src/util/User.ts b/api/src/util/User.ts
index 107fc759..392c7101 100644
--- a/api/src/util/User.ts
+++ b/api/src/util/User.ts
@@ -1,4 +1,4 @@
-import { toObject, UserModel, PublicUserProjection } from "@fosscord/server-util";
+import { toObject, UserModel, PublicUserProjection } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 
 export { PublicUserProjection };
diff --git a/api/src/util/cdn.ts b/api/src/util/cdn.ts
index aed8ca0a..3c71d980 100644
--- a/api/src/util/cdn.ts
+++ b/api/src/util/cdn.ts
@@ -1,4 +1,4 @@
-import { Config } from "@fosscord/server-util";
+import { Config } from "@fosscord/util";
 import FormData from "form-data";
 import { HTTPError } from "lambert-server";
 import fetch from "node-fetch";
diff --git a/api/src/util/ipAddress.ts b/api/src/util/ipAddress.ts
index f2c8fd4d..0a724daa 100644
--- a/api/src/util/ipAddress.ts
+++ b/api/src/util/ipAddress.ts
@@ -1,4 +1,4 @@
-import { Config } from "@fosscord/server-util";
+import { Config } from "@fosscord/util";
 import { Request } from "express";
 // use ipdata package instead of simple fetch because of integrated caching
 import fetch from "node-fetch";
diff --git a/api/src/util/passwordStrength.ts b/api/src/util/passwordStrength.ts
index cc503843..dfffa2c0 100644
--- a/api/src/util/passwordStrength.ts
+++ b/api/src/util/passwordStrength.ts
@@ -1,4 +1,4 @@
-import { Config } from "@fosscord/server-util";
+import { Config } from "@fosscord/util";
 import "missing-native-js-functions";
 
 const reNUMBER = /[0-9]/g;
diff --git a/cdn/package-lock.json b/cdn/package-lock.json
index 6a51d710..0c87d5c3 100644
--- a/cdn/package-lock.json
+++ b/cdn/package-lock.json
@@ -7,9 +7,11 @@
 		"": {
 			"name": "@fosscord/cdn",
 			"version": "1.0.0",
+			"hasInstallScript": true,
 			"license": "ISC",
 			"dependencies": {
 				"@fosscord/server-util": "^1.3.42",
+				"@fosscord/util": "file:../util",
 				"body-parser": "^1.19.0",
 				"btoa": "^1.2.1",
 				"cheerio": "^1.0.0-rc.5",
@@ -39,6 +41,30 @@
 				"@types/uuid": "^8.3.0"
 			}
 		},
+		"../util": {
+			"name": "@fosscord/util",
+			"version": "1.3.52",
+			"license": "GPLV3",
+			"dependencies": {
+				"@types/jsonwebtoken": "^8.5.0",
+				"@types/mongoose-autopopulate": "^0.10.1",
+				"@types/mongoose-lean-virtuals": "^0.5.1",
+				"@types/node": "^14.14.25",
+				"ajv": "^8.5.0",
+				"amqplib": "^0.8.0",
+				"dot-prop": "^6.0.1",
+				"env-paths": "^2.2.1",
+				"jsonwebtoken": "^8.5.1",
+				"missing-native-js-functions": "^1.2.2",
+				"mongodb": "^3.6.9",
+				"mongoose": "^5.13.7",
+				"mongoose-autopopulate": "^0.12.3",
+				"typescript": "^4.1.3"
+			},
+			"devDependencies": {
+				"@types/amqplib": "^0.8.1"
+			}
+		},
 		"node_modules/@fosscord/server-util": {
 			"version": "1.3.42",
 			"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.42.tgz",
@@ -59,6 +85,10 @@
 				"typescript": "^4.1.3"
 			}
 		},
+		"node_modules/@fosscord/util": {
+			"resolved": "../util",
+			"link": true
+		},
 		"node_modules/@tokenizer/token": {
 			"version": "0.1.1",
 			"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz",
@@ -1963,6 +1993,26 @@
 				"typescript": "^4.1.3"
 			}
 		},
+		"@fosscord/util": {
+			"version": "file:../util",
+			"requires": {
+				"@types/amqplib": "^0.8.1",
+				"@types/jsonwebtoken": "^8.5.0",
+				"@types/mongoose-autopopulate": "^0.10.1",
+				"@types/mongoose-lean-virtuals": "^0.5.1",
+				"@types/node": "^14.14.25",
+				"ajv": "^8.5.0",
+				"amqplib": "^0.8.0",
+				"dot-prop": "^6.0.1",
+				"env-paths": "^2.2.1",
+				"jsonwebtoken": "^8.5.1",
+				"missing-native-js-functions": "^1.2.2",
+				"mongodb": "^3.6.9",
+				"mongoose": "^5.13.7",
+				"mongoose-autopopulate": "^0.12.3",
+				"typescript": "^4.1.3"
+			}
+		},
 		"@tokenizer/token": {
 			"version": "0.1.1",
 			"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz",
diff --git a/cdn/package.json b/cdn/package.json
index bb7e7488..26f62b2c 100644
--- a/cdn/package.json
+++ b/cdn/package.json
@@ -5,6 +5,8 @@
 	"main": "dist/index.js",
 	"types": "dist/index.d.ts",
 	"scripts": {
+		"link": "npm run build && npm link",
+		"postinstall": "npm run --prefix ../util/ link && npm link @fosscord/util && npm run link",
 		"test": "echo \"Error: no test specified\" && exit 1",
 		"build": "tsc -b .",
 		"start": "npm run build && node dist/start.js"
@@ -22,6 +24,7 @@
 	"homepage": "https://github.com/discord-open-source/discord-cdn#readme",
 	"dependencies": {
 		"@fosscord/server-util": "^1.3.42",
+		"@fosscord/util": "file:../util",
 		"body-parser": "^1.19.0",
 		"btoa": "^1.2.1",
 		"cheerio": "^1.0.0-rc.5",
diff --git a/cdn/src/Server.ts b/cdn/src/Server.ts
index 1b79b037..a73a948c 100644
--- a/cdn/src/Server.ts
+++ b/cdn/src/Server.ts
@@ -1,5 +1,5 @@
 import { Server, ServerOptions } from "lambert-server";
-import { Config, db } from "@fosscord/server-util";
+import { Config, db } from "@fosscord/util";
 import path from "path";
 import avatarsRoute from "./routes/avatars";
 
@@ -13,11 +13,9 @@ export class CDNServer extends Server {
 	}
 
 	async start() {
-		console.log("[Database] connecting ...");
 		// @ts-ignore
 		await (db as Promise<Connection>);
 		await Config.init();
-		console.log("[Database] connected");
 		this.app.use((req, res, next) => {
 			res.set("Access-Control-Allow-Origin", "*");
 			// TODO: use better CSP policy
@@ -33,31 +31,31 @@ export class CDNServer extends Server {
 		await this.registerRoutes(path.join(__dirname, "routes/"));
 
 		this.app.use("/icons/", avatarsRoute);
-		this.log("info", "[Server] Route /icons registered");
+		this.log("verbose", "[Server] Route /icons registered");
 
 		this.app.use("/emojis/", avatarsRoute);
-		this.log("info", "[Server] Route /emojis registered");
+		this.log("verbose", "[Server] Route /emojis registered");
 
 		this.app.use("/stickers/", avatarsRoute);
-		this.log("info", "[Server] Route /stickers registered");
+		this.log("verbose", "[Server] Route /stickers registered");
 
 		this.app.use("/banners/", avatarsRoute);
-		this.log("info", "[Server] Route /banners registered");
-		
+		this.log("verbose", "[Server] Route /banners registered");
+
 		this.app.use("/splashes/", avatarsRoute);
-		this.log("info", "[Server] Route /splashes registered");
+		this.log("verbose", "[Server] Route /splashes registered");
 
 		this.app.use("/app-icons/", avatarsRoute);
-		this.log("info", "[Server] Route /app-icons registered");
+		this.log("verbose", "[Server] Route /app-icons registered");
 
 		this.app.use("/app-assets/", avatarsRoute);
-		this.log("info", "[Server] Route /app-assets registered");
+		this.log("verbose", "[Server] Route /app-assets registered");
 
 		this.app.use("/discover-splashes/", avatarsRoute);
-		this.log("info", "[Server] Route /discover-splashes registered");
+		this.log("verbose", "[Server] Route /discover-splashes registered");
 
 		this.app.use("/team-icons/", avatarsRoute);
-		this.log("info", "[Server] Route /team-icons registered");
+		this.log("verbose", "[Server] Route /team-icons registered");
 
 		return super.start();
 	}
diff --git a/cdn/src/routes/attachments.ts b/cdn/src/routes/attachments.ts
index c387aa37..6ce64ed4 100644
--- a/cdn/src/routes/attachments.ts
+++ b/cdn/src/routes/attachments.ts
@@ -1,5 +1,5 @@
 import { Router, Response, Request } from "express";
-import { Config, Snowflake } from "@fosscord/server-util";
+import { Config, Snowflake } from "@fosscord/util";
 import { storage } from "../util/Storage";
 import FileType from "file-type";
 import { HTTPError } from "lambert-server";
diff --git a/cdn/src/routes/avatars.ts b/cdn/src/routes/avatars.ts
index 60befe2c..03388afc 100644
--- a/cdn/src/routes/avatars.ts
+++ b/cdn/src/routes/avatars.ts
@@ -1,5 +1,5 @@
 import { Router, Response, Request } from "express";
-import { Config, Snowflake } from "@fosscord/server-util";
+import { Config, Snowflake } from "@fosscord/util";
 import { storage } from "../util/Storage";
 import FileType from "file-type";
 import { HTTPError } from "lambert-server";
diff --git a/cdn/src/routes/external.ts b/cdn/src/routes/external.ts
index 3abe9c22..625b6bbd 100644
--- a/cdn/src/routes/external.ts
+++ b/cdn/src/routes/external.ts
@@ -4,7 +4,7 @@ import { Router, Response, Request } from "express";
 import fetch from "node-fetch";
 import crypto from "crypto";
 import { HTTPError } from "lambert-server";
-import { Snowflake } from "@fosscord/server-util";
+import { Snowflake } from "@fosscord/util";
 import { storage } from "../util/Storage";
 
 const router = Router();