summary refs log tree commit diff
path: root/src/util
diff options
context:
space:
mode:
authorMadeline <46743919+MaddyUnderStars@users.noreply.github.com>2022-09-26 22:29:30 +1000
committerMadeline <46743919+MaddyUnderStars@users.noreply.github.com>2022-09-26 22:41:21 +1000
commit99ee7e9400f06e8718612d8b52d15215dc620774 (patch)
tree08de8c5d3985b9c2eaa419f5198f891ecd82d012 /src/util
parentRemove the cdn storage location log (diff)
downloadserver-99ee7e9400f06e8718612d8b52d15215dc620774.tar.xz
Prettier
Diffstat (limited to 'src/util')
-rw-r--r--src/util/dtos/DmChannelDTO.ts21
-rw-r--r--src/util/entities/Attachment.ts19
-rw-r--r--src/util/entities/AuditLog.ts16
-rw-r--r--src/util/entities/BackupCodes.ts4
-rw-r--r--src/util/entities/BaseClass.ts36
-rw-r--r--src/util/entities/Categories.ts24
-rw-r--r--src/util/entities/Channel.ts846
-rw-r--r--src/util/entities/ClientRelease.ts2
-rw-r--r--src/util/entities/Config.ts31
-rw-r--r--src/util/entities/ConnectedAccount.ts3
-rw-r--r--src/util/entities/Emoji.ts2
-rw-r--r--src/util/entities/Encryption.ts20
-rw-r--r--src/util/entities/Guild.ts42
-rw-r--r--src/util/entities/Invite.ts12
-rw-r--r--src/util/entities/Member.ts68
-rw-r--r--src/util/entities/Message.ts27
-rw-r--r--src/util/entities/Migration.ts11
-rw-r--r--src/util/entities/Note.ts2
-rw-r--r--src/util/entities/ReadState.ts13
-rw-r--r--src/util/entities/Relationship.ts9
-rw-r--r--src/util/entities/StickerPack.ts10
-rw-r--r--src/util/entities/Team.ts10
-rw-r--r--src/util/entities/TeamMember.ts10
-rw-r--r--src/util/entities/User.ts122
-rw-r--r--src/util/entities/index.ts2
-rw-r--r--src/util/imports/OrmUtils.ts22
-rw-r--r--src/util/imports/index.ts2
-rw-r--r--src/util/index.ts2
-rw-r--r--src/util/interfaces/Activity.ts3
-rw-r--r--src/util/interfaces/Event.ts2
-rw-r--r--src/util/migrations/1633864260873-EmojiRoles.ts8
-rw-r--r--src/util/migrations/1633864669243-EmojiUser.ts12
-rw-r--r--src/util/migrations/1633881705509-VanityInvite.ts14
-rw-r--r--src/util/migrations/1634308884591-Stickers.ts73
-rw-r--r--src/util/migrations/1634424361103-Presence.ts5
-rw-r--r--src/util/migrations/1634426540271-MigrationTimestamp.ts6
-rw-r--r--src/util/migrations/1660678870706-opencordFixes.ts37
-rw-r--r--src/util/migrations/1660689892073-mobileFixes2.ts25
-rw-r--r--src/util/schemas/ActivitySchema.ts5
-rw-r--r--src/util/schemas/BackupCodesChallengeSchema.ts2
-rw-r--r--src/util/schemas/BanCreateSchema.ts2
-rw-r--r--src/util/schemas/BanModeratorSchema.ts2
-rw-r--r--src/util/schemas/BanRegistrySchema.ts2
-rw-r--r--src/util/schemas/BulkDeleteSchema.ts2
-rw-r--r--src/util/schemas/ChannelModifySchema.ts2
-rw-r--r--src/util/schemas/CodesVerificationSchema.ts2
-rw-r--r--src/util/schemas/DmChannelCreateSchema.ts2
-rw-r--r--src/util/schemas/EmojiCreateSchema.ts2
-rw-r--r--src/util/schemas/EmojiModifySchema.ts2
-rw-r--r--src/util/schemas/GuildCreateSchema.ts2
-rw-r--r--src/util/schemas/GuildTemplateCreateSchema.ts2
-rw-r--r--src/util/schemas/GuildUpdateWelcomeScreenSchema.ts2
-rw-r--r--src/util/schemas/InviteCreateSchema.ts2
-rw-r--r--src/util/schemas/LoginSchema.ts2
-rw-r--r--src/util/schemas/MemberChangeSchema.ts2
-rw-r--r--src/util/schemas/MemberNickChangeSchema.ts2
-rw-r--r--src/util/schemas/MessageAcknowledgeSchema.ts2
-rw-r--r--src/util/schemas/MessageCreateSchema.ts2
-rw-r--r--src/util/schemas/MfaCodesSchema.ts2
-rw-r--r--src/util/schemas/ModifyGuildStickerSchema.ts2
-rw-r--r--src/util/schemas/PruneSchema.ts2
-rw-r--r--src/util/schemas/PurgeSchema.ts2
-rw-r--r--src/util/schemas/RegisterSchema.ts2
-rw-r--r--src/util/schemas/RelationshipPostSchema.ts2
-rw-r--r--src/util/schemas/RelationshipPutSchema.ts2
-rw-r--r--src/util/schemas/RoleModifySchema.ts2
-rw-r--r--src/util/schemas/SelectProtocolSchema.ts14
-rw-r--r--src/util/schemas/TemplateCreateSchema.ts2
-rw-r--r--src/util/schemas/TemplateModifySchema.ts2
-rw-r--r--src/util/schemas/TotpDisableSchema.ts2
-rw-r--r--src/util/schemas/TotpEnableSchema.ts2
-rw-r--r--src/util/schemas/TotpSchema.ts10
-rw-r--r--src/util/schemas/UserModifySchema.ts2
-rw-r--r--src/util/schemas/Validator.ts22
-rw-r--r--src/util/schemas/VanityUrlSchema.ts2
-rw-r--r--src/util/schemas/VoiceIdentifySchema.ts2
-rw-r--r--src/util/schemas/VoiceStateUpdateSchema.ts4
-rw-r--r--src/util/schemas/VoiceVideoSchema.ts4
-rw-r--r--src/util/schemas/WebhookCreateSchema.ts2
-rw-r--r--src/util/schemas/WidgetModifySchema.ts2
-rw-r--r--src/util/schemas/index.ts2
-rw-r--r--src/util/util/ApiError.ts19
-rw-r--r--src/util/util/AutoUpdate.ts17
-rw-r--r--src/util/util/BannedWords.ts10
-rw-r--r--src/util/util/BitField.ts23
-rw-r--r--src/util/util/Categories.ts2
-rw-r--r--src/util/util/Config.ts15
-rw-r--r--src/util/util/Constants.ts576
-rw-r--r--src/util/util/Database.ts15
-rw-r--r--src/util/util/Email.ts2
-rw-r--r--src/util/util/Event.ts48
-rw-r--r--src/util/util/FieldError.ts12
-rw-r--r--src/util/util/Intents.ts7
-rw-r--r--src/util/util/InvisibleCharacters.ts112
-rw-r--r--src/util/util/Permissions.ts72
-rw-r--r--src/util/util/RabbitMQ.ts6
-rw-r--r--src/util/util/Rights.ts40
-rw-r--r--src/util/util/Snowflake.ts13
-rw-r--r--src/util/util/Token.ts9
-rw-r--r--src/util/util/TraverseDirectory.ts7
-rw-r--r--src/util/util/cdn.ts48
-rw-r--r--src/util/util/index.ts2
102 files changed, 1816 insertions, 945 deletions
diff --git a/src/util/dtos/DmChannelDTO.ts b/src/util/dtos/DmChannelDTO.ts
index 226b2f9d..fcc91204 100644
--- a/src/util/dtos/DmChannelDTO.ts
+++ b/src/util/dtos/DmChannelDTO.ts
@@ -11,7 +11,11 @@ export class DmChannelDTO {
 	recipients: MinimalPublicUserDTO[];
 	type: number;
 
-	static async from(channel: Channel, excluded_recipients: string[] = [], origin_channel_id?: string) {
+	static async from(
+		channel: Channel,
+		excluded_recipients: string[] = [],
+		origin_channel_id?: string,
+	) {
 		const obj = new DmChannelDTO();
 		obj.icon = channel.icon || null;
 		obj.id = channel.id;
@@ -23,10 +27,15 @@ export class DmChannelDTO {
 		obj.recipients = (
 			await Promise.all(
 				channel
-					.recipients!.filter((r) => !excluded_recipients.includes(r.user_id))
+					.recipients!.filter(
+						(r) => !excluded_recipients.includes(r.user_id),
+					)
 					.map(async (r) => {
-						return await User.findOneOrFail({ where: { id: r.user_id }, select: PublicUserProjection });
-					})
+						return await User.findOneOrFail({
+							where: { id: r.user_id },
+							select: PublicUserProjection,
+						});
+					}),
 			)
 		).map((u) => new MinimalPublicUserDTO(u));
 		return obj;
@@ -35,7 +44,9 @@ export class DmChannelDTO {
 	excludedRecipients(excluded_recipients: string[]): DmChannelDTO {
 		return {
 			...this,
-			recipients: this.recipients.filter((r) => !excluded_recipients.includes(r.id)),
+			recipients: this.recipients.filter(
+				(r) => !excluded_recipients.includes(r.id),
+			),
 		};
 	}
 }
diff --git a/src/util/entities/Attachment.ts b/src/util/entities/Attachment.ts
index 7b4b17eb..055b6f4b 100644
--- a/src/util/entities/Attachment.ts
+++ b/src/util/entities/Attachment.ts
@@ -1,4 +1,11 @@
-import { BeforeRemove, Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
+import {
+	BeforeRemove,
+	Column,
+	Entity,
+	JoinColumn,
+	ManyToOne,
+	RelationId,
+} from "typeorm";
 import { URL } from "url";
 import { deleteFile } from "../util/cdn";
 import { BaseClass } from "./BaseClass";
@@ -31,9 +38,13 @@ export class Attachment extends BaseClass {
 	message_id: string;
 
 	@JoinColumn({ name: "message_id" })
-	@ManyToOne(() => require("./Message").Message, (message: import("./Message").Message) => message.attachments, {
-		onDelete: "CASCADE",
-	})
+	@ManyToOne(
+		() => require("./Message").Message,
+		(message: import("./Message").Message) => message.attachments,
+		{
+			onDelete: "CASCADE",
+		},
+	)
 	message: import("./Message").Message;
 
 	@BeforeRemove()
diff --git a/src/util/entities/AuditLog.ts b/src/util/entities/AuditLog.ts
index b003e7ba..9cc97742 100644
--- a/src/util/entities/AuditLog.ts
+++ b/src/util/entities/AuditLog.ts
@@ -5,24 +5,24 @@ import { User } from "./User";
 
 export enum AuditLogEvents {
 	// guild level
-	GUILD_UPDATE = 1, 
+	GUILD_UPDATE = 1,
 	GUILD_IMPORT = 2,
 	GUILD_EXPORTED = 3,
 	GUILD_ARCHIVE = 4,
 	GUILD_UNARCHIVE = 5,
 	// join-leave
-	USER_JOIN = 6, 
+	USER_JOIN = 6,
 	USER_LEAVE = 7,
 	// channels
-	CHANNEL_CREATE = 10, 
+	CHANNEL_CREATE = 10,
 	CHANNEL_UPDATE = 11,
 	CHANNEL_DELETE = 12,
 	// permission overrides
-	CHANNEL_OVERWRITE_CREATE = 13, 
+	CHANNEL_OVERWRITE_CREATE = 13,
 	CHANNEL_OVERWRITE_UPDATE = 14,
 	CHANNEL_OVERWRITE_DELETE = 15,
 	// kick and ban
-	MEMBER_KICK = 20, 
+	MEMBER_KICK = 20,
 	MEMBER_PRUNE = 21,
 	MEMBER_BAN_ADD = 22,
 	MEMBER_BAN_REMOVE = 23,
@@ -79,17 +79,17 @@ export enum AuditLogEvents {
 	// application commands
 	APPLICATION_COMMAND_PERMISSION_UPDATE = 121,
 	// automod
-	POLICY_CREATE = 140, 
+	POLICY_CREATE = 140,
 	POLICY_UPDATE = 141,
 	POLICY_DELETE = 142,
-	MESSAGE_BLOCKED_BY_POLICIES = 143,  // in fosscord, blocked messages are stealth-dropped
+	MESSAGE_BLOCKED_BY_POLICIES = 143, // in fosscord, blocked messages are stealth-dropped
 	// instance policies affecting the guild
 	GUILD_AFFECTED_BY_POLICIES = 216,
 	// message moves
 	IN_GUILD_MESSAGE_MOVE = 223,
 	CROSS_GUILD_MESSAGE_MOVE = 224,
 	// message routing
-	ROUTE_CREATE = 225, 
+	ROUTE_CREATE = 225,
 	ROUTE_UPDATE = 226,
 }
 
diff --git a/src/util/entities/BackupCodes.ts b/src/util/entities/BackupCodes.ts
index d532a39a..81cdbb6d 100644
--- a/src/util/entities/BackupCodes.ts
+++ b/src/util/entities/BackupCodes.ts
@@ -24,7 +24,7 @@ export function generateMfaBackupCodes(user_id: string) {
 	for (let i = 0; i < 10; i++) {
 		const code = BackupCode.create({
 			user: { id: user_id },
-			code: crypto.randomBytes(4).toString("hex"),	// 8 characters
+			code: crypto.randomBytes(4).toString("hex"), // 8 characters
 			consumed: false,
 			expired: false,
 		});
@@ -32,4 +32,4 @@ export function generateMfaBackupCodes(user_id: string) {
 	}
 
 	return backup_codes;
-}
\ No newline at end of file
+}
diff --git a/src/util/entities/BaseClass.ts b/src/util/entities/BaseClass.ts
index d5a7c2bf..9942b60e 100644
--- a/src/util/entities/BaseClass.ts
+++ b/src/util/entities/BaseClass.ts
@@ -1,5 +1,12 @@
 import "reflect-metadata";
-import { BaseEntity, BeforeInsert, BeforeUpdate, FindOptionsWhere, ObjectIdColumn, PrimaryColumn } from "typeorm";
+import {
+	BaseEntity,
+	BeforeInsert,
+	BeforeUpdate,
+	FindOptionsWhere,
+	ObjectIdColumn,
+	PrimaryColumn,
+} from "typeorm";
 import { Snowflake } from "../util/Snowflake";
 import "missing-native-js-functions";
 import { getDatabase } from "..";
@@ -22,23 +29,40 @@ export class BaseClassWithoutId extends BaseEntity {
 	toJSON(): any {
 		return Object.fromEntries(
 			this.metadata!.columns // @ts-ignore
-				.map((x) => [x.propertyName, this[x.propertyName]]) // @ts-ignore
-				.concat(this.metadata.relations.map((x) => [x.propertyName, this[x.propertyName]]))
+				.map((x) => [x.propertyName, this[x.propertyName]])
+				.concat(
+					// @ts-ignore
+					this.metadata.relations.map((x) => [
+						x.propertyName,
+						// @ts-ignore
+						this[x.propertyName],
+					]),
+				),
 		);
 	}
 
-	static increment<T extends BaseClass>(conditions: FindOptionsWhere<T>, propertyPath: string, value: number | string) {
+	static increment<T extends BaseClass>(
+		conditions: FindOptionsWhere<T>,
+		propertyPath: string,
+		value: number | string,
+	) {
 		const repository = this.getRepository();
 		return repository.increment(conditions, propertyPath, value);
 	}
 
-	static decrement<T extends BaseClass>(conditions: FindOptionsWhere<T>, propertyPath: string, value: number | string) {
+	static decrement<T extends BaseClass>(
+		conditions: FindOptionsWhere<T>,
+		propertyPath: string,
+		value: number | string,
+	) {
 		const repository = this.getRepository();
 		return repository.decrement(conditions, propertyPath, value);
 	}
 }
 
-export const PrimaryIdColumn = process.env.DATABASE?.startsWith("mongodb") ? ObjectIdColumn : PrimaryColumn;
+export const PrimaryIdColumn = process.env.DATABASE?.startsWith("mongodb")
+	? ObjectIdColumn
+	: PrimaryColumn;
 
 export class BaseClass extends BaseClassWithoutId {
 	@PrimaryIdColumn()
diff --git a/src/util/entities/Categories.ts b/src/util/entities/Categories.ts
index 81fbc303..f12b237d 100644
--- a/src/util/entities/Categories.ts
+++ b/src/util/entities/Categories.ts
@@ -1,4 +1,4 @@
-import { PrimaryColumn, Column, Entity} from "typeorm";
+import { PrimaryColumn, Column, Entity } from "typeorm";
 import { BaseClassWithoutId } from "./BaseClass";
 
 // TODO: categories:
@@ -16,18 +16,18 @@ import { BaseClassWithoutId } from "./BaseClass";
 // Also populate discord default categories
 
 @Entity("categories")
-export class Categories extends BaseClassWithoutId { // Not using snowflake
-    
-    @PrimaryColumn()
-	id: number;
+export class Categories extends BaseClassWithoutId {
+	// Not using snowflake
 
-    @Column({ nullable: true })
-    name: string;
+	@PrimaryColumn()
+	id: number;
 
-    @Column({ type: "simple-json" })
-    localizations: string;
+	@Column({ nullable: true })
+	name: string;
 
-    @Column({ nullable: true })
-    is_primary: boolean;
+	@Column({ type: "simple-json" })
+	localizations: string;
 
-}
\ No newline at end of file
+	@Column({ nullable: true })
+	is_primary: boolean;
+}
diff --git a/src/util/entities/Channel.ts b/src/util/entities/Channel.ts
index 2200bfa3..14f36857 100644
--- a/src/util/entities/Channel.ts
+++ b/src/util/entities/Channel.ts
@@ -1,389 +1,457 @@
-import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";

-import { BaseClass } from "./BaseClass";

-import { Guild } from "./Guild";

-import { PublicUserProjection, User } from "./User";

-import { HTTPError } from "lambert-server";

-import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial, InvisibleCharacters, ChannelTypes } from "../util";

-import { ChannelCreateEvent, ChannelRecipientRemoveEvent } from "../interfaces";

-import { Recipient } from "./Recipient";

-import { Message } from "./Message";

-import { ReadState } from "./ReadState";

-import { Invite } from "./Invite";

-import { VoiceState } from "./VoiceState";

-import { Webhook } from "./Webhook";

-import { DmChannelDTO } from "../dtos";

-

-export enum ChannelType {

-	GUILD_TEXT = 0, // a text channel within a guild

-	DM = 1, // a direct message between users

-	GUILD_VOICE = 2, // a voice channel within a guild

-	GROUP_DM = 3, // a direct message between multiple users

-	GUILD_CATEGORY = 4, // an organizational category that contains zero or more channels

-	GUILD_NEWS = 5, // a channel that users can follow and crosspost into a guild or route

-	GUILD_STORE = 6, // a channel in which game developers can sell their things

-	ENCRYPTED = 7, // end-to-end encrypted channel

-	ENCRYPTED_THREAD = 8, // end-to-end encrypted thread channel

-	TRANSACTIONAL = 9, // event chain style transactional channel

-	GUILD_NEWS_THREAD = 10, // a temporary sub-channel within a GUILD_NEWS channel

-	GUILD_PUBLIC_THREAD = 11, // a temporary sub-channel within a GUILD_TEXT channel

-	GUILD_PRIVATE_THREAD = 12, // a temporary sub-channel within a GUILD_TEXT channel that is only viewable by those invited and those with the MANAGE_THREADS permission

-	GUILD_STAGE_VOICE = 13, // a voice channel for hosting events with an audience

-	DIRECTORY = 14, // guild directory listing channel

-	GUILD_FORUM = 15, // forum composed of IM threads

-	TICKET_TRACKER = 33, // ticket tracker, individual ticket items shall have type 12

-	KANBAN = 34, // confluence like kanban board

-	VOICELESS_WHITEBOARD = 35, // whiteboard but without voice (whiteboard + voice is the same as stage)

-	CUSTOM_START = 64, // start custom channel types from here

-	UNHANDLED = 255 // unhandled unowned pass-through channel type

-}

-

-@Entity("channels")

-export class Channel extends BaseClass {

-	@Column()

-	created_at: Date;

-

-	@Column({ nullable: true })

-	name?: string;

-

-	@Column({ type: "text", nullable: true })

-	icon?: string | null;

-

-	@Column({ type: "int" })

-	type: ChannelType;

-

-	@OneToMany(() => Recipient, (recipient: Recipient) => recipient.channel, {

-		cascade: true,

-		orphanedRowAction: "delete",

-	})

-	recipients?: Recipient[];

-

-	@Column({ nullable: true })

-	last_message_id?: string;

-

-	@Column({ nullable: true })

-	@RelationId((channel: Channel) => channel.guild)

-	guild_id?: string;

-

-	@JoinColumn({ name: "guild_id" })

-	@ManyToOne(() => Guild, {

-		onDelete: "CASCADE",

-	})

-	guild: Guild;

-

-	@Column({ nullable: true })

-	@RelationId((channel: Channel) => channel.parent)

-	parent_id: string;

-

-	@JoinColumn({ name: "parent_id" })

-	@ManyToOne(() => Channel)

-	parent?: Channel;

-

-	// for group DMs and owned custom channel types

-	@Column({ nullable: true })

-	@RelationId((channel: Channel) => channel.owner)

-	owner_id?: string;

-

-	@JoinColumn({ name: "owner_id" })

-	@ManyToOne(() => User)

-	owner: User;

-

-	@Column({ nullable: true })

-	last_pin_timestamp?: number;

-

-	@Column({ nullable: true })

-	default_auto_archive_duration?: number;

-

-	@Column({ nullable: true })

-	position?: number;

-

-	@Column({ type: "simple-json", nullable: true })

-	permission_overwrites?: ChannelPermissionOverwrite[];

-

-	@Column({ nullable: true })

-	video_quality_mode?: number;

-

-	@Column({ nullable: true })

-	bitrate?: number;

-

-	@Column({ nullable: true })

-	user_limit?: number;

-

-	@Column()

-	nsfw: boolean = false;

-

-	@Column({ nullable: true })

-	rate_limit_per_user?: number;

-

-	@Column({ nullable: true })

-	topic?: string;

-

-	@OneToMany(() => Invite, (invite: Invite) => invite.channel, {

-		cascade: true,

-		orphanedRowAction: "delete",

-	})

-	invites?: Invite[];

-

-	@Column({ nullable: true })

-	retention_policy_id?: string;

-

-	@OneToMany(() => Message, (message: Message) => message.channel, {

-		cascade: true,

-		orphanedRowAction: "delete",

-	})

-	messages?: Message[];

-

-	@OneToMany(() => VoiceState, (voice_state: VoiceState) => voice_state.channel, {

-		cascade: true,

-		orphanedRowAction: "delete",

-	})

-	voice_states?: VoiceState[];

-

-	@OneToMany(() => ReadState, (read_state: ReadState) => read_state.channel, {

-		cascade: true,

-		orphanedRowAction: "delete",

-	})

-	read_states?: ReadState[];

-

-	@OneToMany(() => Webhook, (webhook: Webhook) => webhook.channel, {

-		cascade: true,

-		orphanedRowAction: "delete",

-	})

-	webhooks?: Webhook[];

-

-	// TODO: DM channel

-	static async createChannel(

-		channel: Partial<Channel>,

-		user_id: string = "0",

-		opts?: {

-			keepId?: boolean;

-			skipExistsCheck?: boolean;

-			skipPermissionCheck?: boolean;

-			skipEventEmit?: boolean;

-			skipNameChecks?: boolean;

-		}

-	) {

-		if (!opts?.skipPermissionCheck) {

-			// Always check if user has permission first

-			const permissions = await getPermission(user_id, channel.guild_id);

-			permissions.hasThrow("MANAGE_CHANNELS");

-		}

-

-		if (!opts?.skipNameChecks) {

-			const guild = await Guild.findOneOrFail({ where: { id: channel.guild_id } });

-			if (!guild.features.includes("ALLOW_INVALID_CHANNEL_NAMES") && channel.name) {

-				for (var character of InvisibleCharacters)

-					if (channel.name.includes(character))

-						throw new HTTPError("Channel name cannot include invalid characters", 403);

-

-				// Categories skip these checks on discord.com

-				if (channel.type !== ChannelType.GUILD_CATEGORY) {

-					if (channel.name.includes(" "))

-						throw new HTTPError("Channel name cannot include invalid characters", 403);

-

-					if (channel.name.match(/\-\-+/g))

-						throw new HTTPError("Channel name cannot include multiple adjacent dashes.", 403);

-

-					if (channel.name.charAt(0) === "-" ||

-						channel.name.charAt(channel.name.length - 1) === "-")

-						throw new HTTPError("Channel name cannot start/end with dash.", 403);

-				}

-				else

-					channel.name = channel.name.trim();	//category names are trimmed client side on discord.com

-			}

-

-			if (!guild.features.includes("ALLOW_UNNAMED_CHANNELS")) {

-				if (!channel.name)

-					throw new HTTPError("Channel name cannot be empty.", 403);

-			}

-		}

-

-		switch (channel.type) {

-			case ChannelType.GUILD_TEXT:

-			case ChannelType.GUILD_NEWS:

-			case ChannelType.GUILD_VOICE:

-				if (channel.parent_id && !opts?.skipExistsCheck) {

-					const exists = await Channel.findOneOrFail({ where: { id: channel.parent_id } });

-					if (!exists) throw new HTTPError("Parent id channel doesn't exist", 400);

-					if (exists.guild_id !== channel.guild_id)

-						throw new HTTPError("The category channel needs to be in the guild");

-				}

-				break;

-			case ChannelType.GUILD_CATEGORY:

-			case ChannelType.UNHANDLED:

-				break;

-			case ChannelType.DM:

-			case ChannelType.GROUP_DM:

-				throw new HTTPError("You can't create a dm channel in a guild");

-			case ChannelType.GUILD_STORE:

-			default:

-				throw new HTTPError("Not yet supported");

-		}

-

-		if (!channel.permission_overwrites) channel.permission_overwrites = [];

-		// TODO: eagerly auto generate position of all guild channels

-

-		channel = {

-			...channel,

-			...(!opts?.keepId && { id: Snowflake.generate() }),

-			created_at: new Date(),

-			position: (channel.type === ChannelType.UNHANDLED ? 0 : channel.position) || 0,

-		};

-

-		await Promise.all([

-			Channel.create(channel).save(),

-			!opts?.skipEventEmit

-				? emitEvent({

-					event: "CHANNEL_CREATE",

-					data: channel,

-					guild_id: channel.guild_id,

-				} as ChannelCreateEvent)

-				: Promise.resolve(),

-		]);

-

-		return channel;

-	}

-

-	static async createDMChannel(recipients: string[], creator_user_id: string, name?: string) {

-		recipients = recipients.unique().filter((x) => x !== creator_user_id);

-		// TODO: check config for max number of recipients

-		/** if you want to disallow note to self channels, uncomment the conditional below

-

-		const otherRecipientsUsers = await User.find({ where: recipients.map((x) => ({ id: x })) });

-		if (otherRecipientsUsers.length !== recipients.length) {

-			throw new HTTPError("Recipient/s not found");

-		}

-		**/

-

-		const type = recipients.length > 1 ? ChannelType.GROUP_DM : ChannelType.DM;

-

-		let channel = null;

-

-		const channelRecipients = [...recipients, creator_user_id];

-

-		const userRecipients = await Recipient.find({

-			where: { user_id: creator_user_id },

-			relations: ["channel", "channel.recipients"],

-		});

-

-		for (let ur of userRecipients) {

-			let re = ur.channel.recipients!.map((r) => r.user_id);

-			if (re.length === channelRecipients.length) {

-				if (containsAll(re, channelRecipients)) {

-					if (channel == null) {

-						channel = ur.channel;

-						await ur.assign({ closed: false }).save();

-					}

-				}

-			}

-		}

-

-		if (channel == null) {

-			name = trimSpecial(name);

-

-			channel = await Channel.create({

-				name,

-				type,

-				owner_id: undefined,

-				created_at: new Date(),

-				last_message_id: undefined,

-				recipients: channelRecipients.map(

-					(x) =>

-						Recipient.create({ user_id: x, closed: !(type === ChannelType.GROUP_DM || x === creator_user_id) })

-				),

-				nsfw: false,

-			}).save();

-		}

-

-		const channel_dto = await DmChannelDTO.from(channel);

-

-		if (type === ChannelType.GROUP_DM) {

-			for (let recipient of channel.recipients!) {

-				await emitEvent({

-					event: "CHANNEL_CREATE",

-					data: channel_dto.excludedRecipients([recipient.user_id]),

-					user_id: recipient.user_id,

-				});

-			}

-		} else {

-			await emitEvent({ event: "CHANNEL_CREATE", data: channel_dto, user_id: creator_user_id });

-		}

-

-		if (recipients.length === 1) return channel_dto;

-		else return channel_dto.excludedRecipients([creator_user_id]);

-	}

-

-	static async removeRecipientFromChannel(channel: Channel, user_id: string) {

-		await Recipient.delete({ channel_id: channel.id, user_id: user_id });

-		channel.recipients = channel.recipients?.filter((r) => r.user_id !== user_id);

-

-		if (channel.recipients?.length === 0) {

-			await Channel.deleteChannel(channel);

-			await emitEvent({

-				event: "CHANNEL_DELETE",

-				data: await DmChannelDTO.from(channel, [user_id]),

-				user_id: user_id,

-			});

-			return;

-		}

-

-		await emitEvent({

-			event: "CHANNEL_DELETE",

-			data: await DmChannelDTO.from(channel, [user_id]),

-			user_id: user_id,

-		});

-

-		//If the owner leave the server user is the new owner

-		if (channel.owner_id === user_id) {

-			channel.owner_id = "1"; // The channel is now owned by the server user

-			await emitEvent({

-				event: "CHANNEL_UPDATE",

-				data: await DmChannelDTO.from(channel, [user_id]),

-				channel_id: channel.id,

-			});

-		}

-

-		await channel.save();

-

-		await emitEvent({

-			event: "CHANNEL_RECIPIENT_REMOVE",

-			data: {

-				channel_id: channel.id,

-				user: await User.findOneOrFail({ where: { id: user_id }, select: PublicUserProjection }),

-			},

-			channel_id: channel.id,

-		} as ChannelRecipientRemoveEvent);

-	}

-

-	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 Channel.delete({ id: channel.id });

-	}

-

-	isDm() {

-		return this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM;

-	}

-

-	// Does the channel support sending messages ( eg categories do not )

-	isWritable() {

-		const disallowedChannelTypes = [

-			ChannelType.GUILD_CATEGORY,

-			ChannelType.GUILD_STAGE_VOICE,

-			ChannelType.VOICELESS_WHITEBOARD,

-		];

-		return disallowedChannelTypes.indexOf(this.type) == -1;

-	}

-}

-

-export interface ChannelPermissionOverwrite {

-	allow: string;

-	deny: string;

-	id: string;

-	type: ChannelPermissionOverwriteType;

-}

-

-export enum ChannelPermissionOverwriteType {

-	role = 0,

-	member = 1,

-	group = 2,

-}

+import {
+	Column,
+	Entity,
+	JoinColumn,
+	ManyToOne,
+	OneToMany,
+	RelationId,
+} from "typeorm";
+import { BaseClass } from "./BaseClass";
+import { Guild } from "./Guild";
+import { PublicUserProjection, User } from "./User";
+import { HTTPError } from "lambert-server";
+import {
+	containsAll,
+	emitEvent,
+	getPermission,
+	Snowflake,
+	trimSpecial,
+	InvisibleCharacters,
+	ChannelTypes,
+} from "../util";
+import { ChannelCreateEvent, ChannelRecipientRemoveEvent } from "../interfaces";
+import { Recipient } from "./Recipient";
+import { Message } from "./Message";
+import { ReadState } from "./ReadState";
+import { Invite } from "./Invite";
+import { VoiceState } from "./VoiceState";
+import { Webhook } from "./Webhook";
+import { DmChannelDTO } from "../dtos";
+
+export enum ChannelType {
+	GUILD_TEXT = 0, // a text channel within a guild
+	DM = 1, // a direct message between users
+	GUILD_VOICE = 2, // a voice channel within a guild
+	GROUP_DM = 3, // a direct message between multiple users
+	GUILD_CATEGORY = 4, // an organizational category that contains zero or more channels
+	GUILD_NEWS = 5, // a channel that users can follow and crosspost into a guild or route
+	GUILD_STORE = 6, // a channel in which game developers can sell their things
+	ENCRYPTED = 7, // end-to-end encrypted channel
+	ENCRYPTED_THREAD = 8, // end-to-end encrypted thread channel
+	TRANSACTIONAL = 9, // event chain style transactional channel
+	GUILD_NEWS_THREAD = 10, // a temporary sub-channel within a GUILD_NEWS channel
+	GUILD_PUBLIC_THREAD = 11, // a temporary sub-channel within a GUILD_TEXT channel
+	GUILD_PRIVATE_THREAD = 12, // a temporary sub-channel within a GUILD_TEXT channel that is only viewable by those invited and those with the MANAGE_THREADS permission
+	GUILD_STAGE_VOICE = 13, // a voice channel for hosting events with an audience
+	DIRECTORY = 14, // guild directory listing channel
+	GUILD_FORUM = 15, // forum composed of IM threads
+	TICKET_TRACKER = 33, // ticket tracker, individual ticket items shall have type 12
+	KANBAN = 34, // confluence like kanban board
+	VOICELESS_WHITEBOARD = 35, // whiteboard but without voice (whiteboard + voice is the same as stage)
+	CUSTOM_START = 64, // start custom channel types from here
+	UNHANDLED = 255, // unhandled unowned pass-through channel type
+}
+
+@Entity("channels")
+export class Channel extends BaseClass {
+	@Column()
+	created_at: Date;
+
+	@Column({ nullable: true })
+	name?: string;
+
+	@Column({ type: "text", nullable: true })
+	icon?: string | null;
+
+	@Column({ type: "int" })
+	type: ChannelType;
+
+	@OneToMany(() => Recipient, (recipient: Recipient) => recipient.channel, {
+		cascade: true,
+		orphanedRowAction: "delete",
+	})
+	recipients?: Recipient[];
+
+	@Column({ nullable: true })
+	last_message_id?: string;
+
+	@Column({ nullable: true })
+	@RelationId((channel: Channel) => channel.guild)
+	guild_id?: string;
+
+	@JoinColumn({ name: "guild_id" })
+	@ManyToOne(() => Guild, {
+		onDelete: "CASCADE",
+	})
+	guild: Guild;
+
+	@Column({ nullable: true })
+	@RelationId((channel: Channel) => channel.parent)
+	parent_id: string;
+
+	@JoinColumn({ name: "parent_id" })
+	@ManyToOne(() => Channel)
+	parent?: Channel;
+
+	// for group DMs and owned custom channel types
+	@Column({ nullable: true })
+	@RelationId((channel: Channel) => channel.owner)
+	owner_id?: string;
+
+	@JoinColumn({ name: "owner_id" })
+	@ManyToOne(() => User)
+	owner: User;
+
+	@Column({ nullable: true })
+	last_pin_timestamp?: number;
+
+	@Column({ nullable: true })
+	default_auto_archive_duration?: number;
+
+	@Column({ nullable: true })
+	position?: number;
+
+	@Column({ type: "simple-json", nullable: true })
+	permission_overwrites?: ChannelPermissionOverwrite[];
+
+	@Column({ nullable: true })
+	video_quality_mode?: number;
+
+	@Column({ nullable: true })
+	bitrate?: number;
+
+	@Column({ nullable: true })
+	user_limit?: number;
+
+	@Column()
+	nsfw: boolean = false;
+
+	@Column({ nullable: true })
+	rate_limit_per_user?: number;
+
+	@Column({ nullable: true })
+	topic?: string;
+
+	@OneToMany(() => Invite, (invite: Invite) => invite.channel, {
+		cascade: true,
+		orphanedRowAction: "delete",
+	})
+	invites?: Invite[];
+
+	@Column({ nullable: true })
+	retention_policy_id?: string;
+
+	@OneToMany(() => Message, (message: Message) => message.channel, {
+		cascade: true,
+		orphanedRowAction: "delete",
+	})
+	messages?: Message[];
+
+	@OneToMany(
+		() => VoiceState,
+		(voice_state: VoiceState) => voice_state.channel,
+		{
+			cascade: true,
+			orphanedRowAction: "delete",
+		},
+	)
+	voice_states?: VoiceState[];
+
+	@OneToMany(() => ReadState, (read_state: ReadState) => read_state.channel, {
+		cascade: true,
+		orphanedRowAction: "delete",
+	})
+	read_states?: ReadState[];
+
+	@OneToMany(() => Webhook, (webhook: Webhook) => webhook.channel, {
+		cascade: true,
+		orphanedRowAction: "delete",
+	})
+	webhooks?: Webhook[];
+
+	// TODO: DM channel
+	static async createChannel(
+		channel: Partial<Channel>,
+		user_id: string = "0",
+		opts?: {
+			keepId?: boolean;
+			skipExistsCheck?: boolean;
+			skipPermissionCheck?: boolean;
+			skipEventEmit?: boolean;
+			skipNameChecks?: boolean;
+		},
+	) {
+		if (!opts?.skipPermissionCheck) {
+			// Always check if user has permission first
+			const permissions = await getPermission(user_id, channel.guild_id);
+			permissions.hasThrow("MANAGE_CHANNELS");
+		}
+
+		if (!opts?.skipNameChecks) {
+			const guild = await Guild.findOneOrFail({
+				where: { id: channel.guild_id },
+			});
+			if (
+				!guild.features.includes("ALLOW_INVALID_CHANNEL_NAMES") &&
+				channel.name
+			) {
+				for (var character of InvisibleCharacters)
+					if (channel.name.includes(character))
+						throw new HTTPError(
+							"Channel name cannot include invalid characters",
+							403,
+						);
+
+				// Categories skip these checks on discord.com
+				if (channel.type !== ChannelType.GUILD_CATEGORY) {
+					if (channel.name.includes(" "))
+						throw new HTTPError(
+							"Channel name cannot include invalid characters",
+							403,
+						);
+
+					if (channel.name.match(/\-\-+/g))
+						throw new HTTPError(
+							"Channel name cannot include multiple adjacent dashes.",
+							403,
+						);
+
+					if (
+						channel.name.charAt(0) === "-" ||
+						channel.name.charAt(channel.name.length - 1) === "-"
+					)
+						throw new HTTPError(
+							"Channel name cannot start/end with dash.",
+							403,
+						);
+				} else channel.name = channel.name.trim(); //category names are trimmed client side on discord.com
+			}
+
+			if (!guild.features.includes("ALLOW_UNNAMED_CHANNELS")) {
+				if (!channel.name)
+					throw new HTTPError("Channel name cannot be empty.", 403);
+			}
+		}
+
+		switch (channel.type) {
+			case ChannelType.GUILD_TEXT:
+			case ChannelType.GUILD_NEWS:
+			case ChannelType.GUILD_VOICE:
+				if (channel.parent_id && !opts?.skipExistsCheck) {
+					const exists = await Channel.findOneOrFail({
+						where: { id: channel.parent_id },
+					});
+					if (!exists)
+						throw new HTTPError(
+							"Parent id channel doesn't exist",
+							400,
+						);
+					if (exists.guild_id !== channel.guild_id)
+						throw new HTTPError(
+							"The category channel needs to be in the guild",
+						);
+				}
+				break;
+			case ChannelType.GUILD_CATEGORY:
+			case ChannelType.UNHANDLED:
+				break;
+			case ChannelType.DM:
+			case ChannelType.GROUP_DM:
+				throw new HTTPError("You can't create a dm channel in a guild");
+			case ChannelType.GUILD_STORE:
+			default:
+				throw new HTTPError("Not yet supported");
+		}
+
+		if (!channel.permission_overwrites) channel.permission_overwrites = [];
+		// TODO: eagerly auto generate position of all guild channels
+
+		channel = {
+			...channel,
+			...(!opts?.keepId && { id: Snowflake.generate() }),
+			created_at: new Date(),
+			position:
+				(channel.type === ChannelType.UNHANDLED
+					? 0
+					: channel.position) || 0,
+		};
+
+		await Promise.all([
+			Channel.create(channel).save(),
+			!opts?.skipEventEmit
+				? emitEvent({
+						event: "CHANNEL_CREATE",
+						data: channel,
+						guild_id: channel.guild_id,
+				  } as ChannelCreateEvent)
+				: Promise.resolve(),
+		]);
+
+		return channel;
+	}
+
+	static async createDMChannel(
+		recipients: string[],
+		creator_user_id: string,
+		name?: string,
+	) {
+		recipients = recipients.unique().filter((x) => x !== creator_user_id);
+		// TODO: check config for max number of recipients
+		/** if you want to disallow note to self channels, uncomment the conditional below
+
+		const otherRecipientsUsers = await User.find({ where: recipients.map((x) => ({ id: x })) });
+		if (otherRecipientsUsers.length !== recipients.length) {
+			throw new HTTPError("Recipient/s not found");
+		}
+		**/
+
+		const type =
+			recipients.length > 1 ? ChannelType.GROUP_DM : ChannelType.DM;
+
+		let channel = null;
+
+		const channelRecipients = [...recipients, creator_user_id];
+
+		const userRecipients = await Recipient.find({
+			where: { user_id: creator_user_id },
+			relations: ["channel", "channel.recipients"],
+		});
+
+		for (let ur of userRecipients) {
+			let re = ur.channel.recipients!.map((r) => r.user_id);
+			if (re.length === channelRecipients.length) {
+				if (containsAll(re, channelRecipients)) {
+					if (channel == null) {
+						channel = ur.channel;
+						await ur.assign({ closed: false }).save();
+					}
+				}
+			}
+		}
+
+		if (channel == null) {
+			name = trimSpecial(name);
+
+			channel = await Channel.create({
+				name,
+				type,
+				owner_id: undefined,
+				created_at: new Date(),
+				last_message_id: undefined,
+				recipients: channelRecipients.map((x) =>
+					Recipient.create({
+						user_id: x,
+						closed: !(
+							type === ChannelType.GROUP_DM ||
+							x === creator_user_id
+						),
+					}),
+				),
+				nsfw: false,
+			}).save();
+		}
+
+		const channel_dto = await DmChannelDTO.from(channel);
+
+		if (type === ChannelType.GROUP_DM) {
+			for (let recipient of channel.recipients!) {
+				await emitEvent({
+					event: "CHANNEL_CREATE",
+					data: channel_dto.excludedRecipients([recipient.user_id]),
+					user_id: recipient.user_id,
+				});
+			}
+		} else {
+			await emitEvent({
+				event: "CHANNEL_CREATE",
+				data: channel_dto,
+				user_id: creator_user_id,
+			});
+		}
+
+		if (recipients.length === 1) return channel_dto;
+		else return channel_dto.excludedRecipients([creator_user_id]);
+	}
+
+	static async removeRecipientFromChannel(channel: Channel, user_id: string) {
+		await Recipient.delete({ channel_id: channel.id, user_id: user_id });
+		channel.recipients = channel.recipients?.filter(
+			(r) => r.user_id !== user_id,
+		);
+
+		if (channel.recipients?.length === 0) {
+			await Channel.deleteChannel(channel);
+			await emitEvent({
+				event: "CHANNEL_DELETE",
+				data: await DmChannelDTO.from(channel, [user_id]),
+				user_id: user_id,
+			});
+			return;
+		}
+
+		await emitEvent({
+			event: "CHANNEL_DELETE",
+			data: await DmChannelDTO.from(channel, [user_id]),
+			user_id: user_id,
+		});
+
+		//If the owner leave the server user is the new owner
+		if (channel.owner_id === user_id) {
+			channel.owner_id = "1"; // The channel is now owned by the server user
+			await emitEvent({
+				event: "CHANNEL_UPDATE",
+				data: await DmChannelDTO.from(channel, [user_id]),
+				channel_id: channel.id,
+			});
+		}
+
+		await channel.save();
+
+		await emitEvent({
+			event: "CHANNEL_RECIPIENT_REMOVE",
+			data: {
+				channel_id: channel.id,
+				user: await User.findOneOrFail({
+					where: { id: user_id },
+					select: PublicUserProjection,
+				}),
+			},
+			channel_id: channel.id,
+		} as ChannelRecipientRemoveEvent);
+	}
+
+	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 Channel.delete({ id: channel.id });
+	}
+
+	isDm() {
+		return (
+			this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM
+		);
+	}
+
+	// Does the channel support sending messages ( eg categories do not )
+	isWritable() {
+		const disallowedChannelTypes = [
+			ChannelType.GUILD_CATEGORY,
+			ChannelType.GUILD_STAGE_VOICE,
+			ChannelType.VOICELESS_WHITEBOARD,
+		];
+		return disallowedChannelTypes.indexOf(this.type) == -1;
+	}
+}
+
+export interface ChannelPermissionOverwrite {
+	allow: string;
+	deny: string;
+	id: string;
+	type: ChannelPermissionOverwriteType;
+}
+
+export enum ChannelPermissionOverwriteType {
+	role = 0,
+	member = 1,
+	group = 2,
+}
diff --git a/src/util/entities/ClientRelease.ts b/src/util/entities/ClientRelease.ts
index c5afd307..2723ab67 100644
--- a/src/util/entities/ClientRelease.ts
+++ b/src/util/entities/ClientRelease.ts
@@ -1,4 +1,4 @@
-import { Column, Entity} from "typeorm";
+import { Column, Entity } from "typeorm";
 import { BaseClass } from "./BaseClass";
 
 @Entity("client_release")
diff --git a/src/util/entities/Config.ts b/src/util/entities/Config.ts
index 9aabc1a8..cd7a6923 100644
--- a/src/util/entities/Config.ts
+++ b/src/util/entities/Config.ts
@@ -191,17 +191,17 @@ export interface ConfigValue {
 		allowTemplateCreation: Boolean;
 		allowDiscordTemplates: Boolean;
 		allowRaws: Boolean;
-	},
+	};
 	client: {
 		useTestClient: Boolean;
 		releases: {
 			useLocalRelease: Boolean; //TODO
 			upstreamVersion: string;
 		};
-	},
+	};
 	metrics: {
 		timeout: number;
-	},
+	};
 	sentry: {
 		enabled: boolean;
 		endpoint: string;
@@ -230,7 +230,8 @@ export const DefaultConfigOptions: ConfigValue = {
 	},
 	general: {
 		instanceName: "Fosscord Instance",
-		instanceDescription: "This is a Fosscord instance made in pre-release days",
+		instanceDescription:
+			"This is a Fosscord instance made in pre-release days",
 		frontPage: null,
 		tosPage: null,
 		correspondenceEmail: "noreply@localhost.local",
@@ -318,8 +319,9 @@ export const DefaultConfigOptions: ConfigValue = {
 			sitekey: null,
 			secret: null,
 		},
-		ipdataApiKey: "eca677b284b3bac29eb72f5e496aa9047f26543605efe99ff2ce35c9",
-		defaultRights: "30644591655936",	// See util/scripts/rights.js
+		ipdataApiKey:
+			"eca677b284b3bac29eb72f5e496aa9047f26543605efe99ff2ce35c9",
+		defaultRights: "30644591655936", // See util/scripts/rights.js
 	},
 	login: {
 		requireCaptcha: false,
@@ -395,22 +397,23 @@ export const DefaultConfigOptions: ConfigValue = {
 		enabled: true,
 		allowTemplateCreation: true,
 		allowDiscordTemplates: true,
-		allowRaws: false
+		allowRaws: false,
 	},
 	client: {
 		useTestClient: true,
 		releases: {
 			useLocalRelease: true,
-			upstreamVersion: "0.0.264"
-		}
+			upstreamVersion: "0.0.264",
+		},
 	},
 	metrics: {
-		timeout: 30000
+		timeout: 30000,
 	},
 	sentry: {
 		enabled: false,
-		endpoint: "https://05e8e3d005f34b7d97e920ae5870a5e5@sentry.thearcanebrony.net/6",
+		endpoint:
+			"https://05e8e3d005f34b7d97e920ae5870a5e5@sentry.thearcanebrony.net/6",
 		traceSampleRate: 1.0,
-		environment: hostname()
-	}
-};
\ No newline at end of file
+		environment: hostname(),
+	},
+};
diff --git a/src/util/entities/ConnectedAccount.ts b/src/util/entities/ConnectedAccount.ts
index 09ae30ab..a893ff34 100644
--- a/src/util/entities/ConnectedAccount.ts
+++ b/src/util/entities/ConnectedAccount.ts
@@ -2,7 +2,8 @@ import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
 import { BaseClass } from "./BaseClass";
 import { User } from "./User";
 
-export interface PublicConnectedAccount extends Pick<ConnectedAccount, "name" | "type" | "verified"> {}
+export interface PublicConnectedAccount
+	extends Pick<ConnectedAccount, "name" | "type" | "verified"> {}
 
 @Entity("connected_accounts")
 export class ConnectedAccount extends BaseClass {
diff --git a/src/util/entities/Emoji.ts b/src/util/entities/Emoji.ts
index a3615b7d..0aa640b5 100644
--- a/src/util/entities/Emoji.ts
+++ b/src/util/entities/Emoji.ts
@@ -40,7 +40,7 @@ export class Emoji extends BaseClass {
 
 	@Column({ type: "simple-array" })
 	roles: string[]; // roles this emoji is whitelisted to (new discord feature?)
-	
+
 	@Column({ type: "simple-array", nullable: true })
 	groups: string[]; // user groups this emoji is whitelisted to (Fosscord extension)
 }
diff --git a/src/util/entities/Encryption.ts b/src/util/entities/Encryption.ts
index b597b90a..4c427b32 100644
--- a/src/util/entities/Encryption.ts
+++ b/src/util/entities/Encryption.ts
@@ -1,9 +1,23 @@
-import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";
+import {
+	Column,
+	Entity,
+	JoinColumn,
+	ManyToOne,
+	OneToMany,
+	RelationId,
+} from "typeorm";
 import { BaseClass } from "./BaseClass";
 import { Guild } from "./Guild";
 import { PublicUserProjection, User } from "./User";
 import { HTTPError } from "lambert-server";
-import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial, InvisibleCharacters } from "../util";
+import {
+	containsAll,
+	emitEvent,
+	getPermission,
+	Snowflake,
+	trimSpecial,
+	InvisibleCharacters,
+} from "../util";
 import { BitField, BitFieldResolvable, BitFlag } from "../util/BitField";
 import { Recipient } from "./Recipient";
 import { Message } from "./Message";
@@ -13,7 +27,6 @@ import { DmChannelDTO } from "../dtos";
 
 @Entity("security_settings")
 export class SecuritySettings extends BaseClass {
-
 	@Column({ nullable: true })
 	guild_id: string;
 
@@ -31,5 +44,4 @@ export class SecuritySettings extends BaseClass {
 
 	@Column({ nullable: true })
 	used_since_message: string;
-
 }
diff --git a/src/util/entities/Guild.ts b/src/util/entities/Guild.ts
index 2ce7c213..8854fec0 100644
--- a/src/util/entities/Guild.ts
+++ b/src/util/entities/Guild.ts
@@ -1,4 +1,13 @@
-import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, OneToMany, OneToOne, RelationId } from "typeorm";
+import {
+	Column,
+	Entity,
+	JoinColumn,
+	ManyToMany,
+	ManyToOne,
+	OneToMany,
+	OneToOne,
+	RelationId,
+} from "typeorm";
 import { Config, handleFile, Snowflake } from "..";
 import { Ban } from "./Ban";
 import { BaseClass } from "./BaseClass";
@@ -86,7 +95,7 @@ export class Guild extends BaseClass {
 	//TODO: https://discord.com/developers/docs/resources/guild#guild-object-guild-features
 
 	@Column({ nullable: true })
-	primary_category_id?: string;	// TODO: this was number?
+	primary_category_id?: string; // TODO: this was number?
 
 	@Column({ nullable: true })
 	icon?: string;
@@ -269,7 +278,7 @@ export class Guild extends BaseClass {
 
 	@Column()
 	nsfw: boolean;
-	
+
 	// TODO: nested guilds
 	@Column({ nullable: true })
 	parent?: string;
@@ -332,10 +341,13 @@ export class Guild extends BaseClass {
 			permissions: String("2251804225"),
 			position: 0,
 			icon: undefined,
-			unicode_emoji: undefined
+			unicode_emoji: undefined,
 		}).save();
 
-		if (!body.channels || !body.channels.length) body.channels = [{ id: "01", type: 0, name: "general", nsfw: false }];
+		if (!body.channels || !body.channels.length)
+			body.channels = [
+				{ id: "01", type: 0, name: "general", nsfw: false },
+			];
 
 		const ids = new Map();
 
@@ -345,17 +357,23 @@ export class Guild extends BaseClass {
 			}
 		});
 
-		for (const channel of body.channels?.sort((a, b) => (a.parent_id ? 1 : -1))) {
+		for (const channel of body.channels?.sort((a, b) =>
+			a.parent_id ? 1 : -1,
+		)) {
 			var id = ids.get(channel.id) || Snowflake.generate();
 
 			var parent_id = ids.get(channel.parent_id);
 
-			await Channel.createChannel({ ...channel, guild_id, id, parent_id }, body.owner_id, {
-				keepId: true,
-				skipExistsCheck: true,
-				skipPermissionCheck: true,
-				skipEventEmit: true,
-			});
+			await Channel.createChannel(
+				{ ...channel, guild_id, id, parent_id },
+				body.owner_id,
+				{
+					keepId: true,
+					skipExistsCheck: true,
+					skipPermissionCheck: true,
+					skipEventEmit: true,
+				},
+			);
 		}
 
 		return guild;
diff --git a/src/util/entities/Invite.ts b/src/util/entities/Invite.ts
index 4f36f247..90dec92a 100644
--- a/src/util/entities/Invite.ts
+++ b/src/util/entities/Invite.ts
@@ -1,4 +1,11 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId, PrimaryColumn } from "typeorm";
+import {
+	Column,
+	Entity,
+	JoinColumn,
+	ManyToOne,
+	RelationId,
+	PrimaryColumn,
+} from "typeorm";
 import { Member } from "./Member";
 import { BaseClassWithoutId } from "./BaseClass";
 import { Channel } from "./Channel";
@@ -76,7 +83,8 @@ export class Invite extends BaseClassWithoutId {
 
 	static async joinGuild(user_id: string, code: string) {
 		const invite = await Invite.findOneOrFail({ where: { code } });
-		if (invite.uses++ >= invite.max_uses && invite.max_uses !== 0) await Invite.delete({ code });
+		if (invite.uses++ >= invite.max_uses && invite.max_uses !== 0)
+			await Invite.delete({ code });
 		else await invite.save();
 
 		await Member.addToGuild(user_id, invite.guild_id);
diff --git a/src/util/entities/Member.ts b/src/util/entities/Member.ts
index 7d1346ba..f2762adc 100644
--- a/src/util/entities/Member.ts
+++ b/src/util/entities/Member.ts
@@ -22,7 +22,6 @@ import {
 	GuildMemberRemoveEvent,
 	GuildMemberUpdateEvent,
 	MessageCreateEvent,
-
 } from "../interfaces";
 import { HTTPError } from "lambert-server";
 import { Role } from "./Role";
@@ -126,19 +125,34 @@ export class Member extends BaseClassWithoutId {
 		if (this.nick) {
 			this.nick = this.nick.split("\n").join("");
 			this.nick = this.nick.split("\t").join("");
-			if (BannedWords.find(this.nick)) throw FieldErrors({ nick: { message: "Bad nickname", code: "INVALID_NICKNAME" } });
+			if (BannedWords.find(this.nick))
+				throw FieldErrors({
+					nick: { message: "Bad nickname", code: "INVALID_NICKNAME" },
+				});
 		}
 	}
 
 	static async IsInGuildOrFail(user_id: string, guild_id: string) {
-		if (await Member.count({ where: { id: user_id, guild: { id: guild_id } } })) return true;
+		if (
+			await Member.count({
+				where: { id: user_id, guild: { id: guild_id } },
+			})
+		)
+			return true;
 		throw new HTTPError("You are not member of this guild", 403);
 	}
 
 	static async removeFromGuild(user_id: string, guild_id: string) {
-		const guild = await Guild.findOneOrFail({ select: ["owner_id"], where: { id: guild_id } });
-		if (guild.owner_id === user_id) throw new Error("The owner cannot be removed of the guild");
-		const member = await Member.findOneOrFail({ where: { id: user_id, guild_id }, relations: ["user"] });
+		const guild = await Guild.findOneOrFail({
+			select: ["owner_id"],
+			where: { id: guild_id },
+		});
+		if (guild.owner_id === user_id)
+			throw new Error("The owner cannot be removed of the guild");
+		const member = await Member.findOneOrFail({
+			where: { id: user_id, guild_id },
+			relations: ["user"],
+		});
 
 		// use promise all to execute all promises at the same time -> save time
 		return Promise.all([
@@ -169,9 +183,12 @@ export class Member extends BaseClassWithoutId {
 				where: { id: user_id, guild_id },
 				relations: ["user", "roles"], // we don't want to load  the role objects just the ids
 				//@ts-ignore
-				select: ["index", "roles.id"],	// TODO fix type
+				select: ["index", "roles.id"], // TODO fix type
+			}),
+			Role.findOneOrFail({
+				where: { id: role_id, guild_id },
+				select: ["id"],
 			}),
-			Role.findOneOrFail({ where: { id: role_id, guild_id }, select: ["id"] }),
 		]);
 		member.roles.push(Role.create({ id: role_id }));
 
@@ -189,7 +206,11 @@ export class Member extends BaseClassWithoutId {
 		]);
 	}
 
-	static async removeRole(user_id: string, guild_id: string, role_id: string) {
+	static async removeRole(
+		user_id: string,
+		guild_id: string,
+		role_id: string,
+	) {
 		const [member] = await Promise.all([
 			Member.findOneOrFail({
 				where: { id: user_id, guild_id },
@@ -215,7 +236,11 @@ export class Member extends BaseClassWithoutId {
 		]);
 	}
 
-	static async changeNickname(user_id: string, guild_id: string, nickname: string) {
+	static async changeNickname(
+		user_id: string,
+		guild_id: string,
+		nickname: string,
+	) {
 		const member = await Member.findOneOrFail({
 			where: {
 				id: user_id,
@@ -249,7 +274,10 @@ export class Member extends BaseClassWithoutId {
 		const { maxGuilds } = Config.get().limits.user;
 		const guild_count = await Member.count({ where: { id: user_id } });
 		if (guild_count >= maxGuilds) {
-			throw new HTTPError(`You are at the ${maxGuilds} server limit.`, 403);
+			throw new HTTPError(
+				`You are at the ${maxGuilds} server limit.`,
+				403,
+			);
 		}
 
 		const guild = await Guild.findOneOrFail({
@@ -259,7 +287,11 @@ export class Member extends BaseClassWithoutId {
 			relations: [...PublicGuildRelations, "system_channel"],
 		});
 
-		if (await Member.count({ where: { id: user.id, guild: { id: guild_id } } }))
+		if (
+			await Member.count({
+				where: { id: user.id, guild: { id: guild_id } },
+			})
+		)
 			throw new HTTPError("You are already a member of this guild", 400);
 
 		const member = {
@@ -268,7 +300,7 @@ export class Member extends BaseClassWithoutId {
 			nick: undefined,
 			roles: [guild_id], // @everyone role
 			joined_at: new Date(),
-			premium_since: (new Date()).getTime(),
+			premium_since: new Date().getTime(),
 			deaf: false,
 			mute: false,
 			pending: false,
@@ -339,7 +371,11 @@ export class Member extends BaseClassWithoutId {
 			});
 			await Promise.all([
 				message.save(),
-				emitEvent({ event: "MESSAGE_CREATE", channel_id: message.channel_id, data: message } as MessageCreateEvent)
+				emitEvent({
+					event: "MESSAGE_CREATE",
+					channel_id: message.channel_id,
+					data: message,
+				} as MessageCreateEvent),
 			]);
 		}
 	}
@@ -362,7 +398,7 @@ export interface UserGuildSettings {
 
 	channel_overrides: {
 		[channel_id: string]: ChannelOverride;
-	} | null,
+	} | null;
 	message_notifications: number;
 	mobile_push: boolean;
 	mute_config: MuteConfig | null;
@@ -389,7 +425,7 @@ export const DefaultUserGuildSettings: UserGuildSettings = {
 	notify_highlights: 0,
 	suppress_everyone: false,
 	suppress_roles: false,
-	version: 453,	// ?
+	version: 453, // ?
 	guild_id: null,
 };
 
diff --git a/src/util/entities/Message.ts b/src/util/entities/Message.ts
index be790502..a52b4785 100644
--- a/src/util/entities/Message.ts
+++ b/src/util/entities/Message.ts
@@ -51,7 +51,7 @@ export enum MessageType {
 	SELF_COMMAND_SCRIPT = 43, // self command scripts
 	ENCRYPTION = 50,
 	CUSTOM_START = 63,
-	UNHANDLED = 255
+	UNHANDLED = 255,
 }
 
 @Entity("messages")
@@ -115,7 +115,10 @@ export class Message extends BaseClass {
 	@ManyToOne(() => Application)
 	application?: Application;
 
-	@Column({ nullable: true, type: process.env.PRODUCTION ? "longtext" : undefined })
+	@Column({
+		nullable: true,
+		type: process.env.PRODUCTION ? "longtext" : undefined,
+	})
 	content?: string;
 
 	@Column()
@@ -147,10 +150,14 @@ export class Message extends BaseClass {
 	@ManyToMany(() => Sticker, { cascade: true, onDelete: "CASCADE" })
 	sticker_items?: Sticker[];
 
-	@OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, {
-		cascade: true,
-		orphanedRowAction: "delete",
-	})
+	@OneToMany(
+		() => Attachment,
+		(attachment: Attachment) => attachment.message,
+		{
+			cascade: true,
+			orphanedRowAction: "delete",
+		},
+	)
 	attachments?: Attachment[];
 
 	@Column({ type: "simple-json" })
@@ -176,7 +183,7 @@ export class Message extends BaseClass {
 
 	@Column({ nullable: true })
 	flags?: string;
-	
+
 	@Column({ type: "simple-json", nullable: true })
 	message_reference?: {
 		message_id: string;
@@ -204,7 +211,11 @@ export class Message extends BaseClass {
 	@BeforeInsert()
 	validate() {
 		if (this.content) {
-			if (BannedWords.find(this.content)) throw new HTTPError("Message was blocked by automatic moderation", 200000);
+			if (BannedWords.find(this.content))
+				throw new HTTPError(
+					"Message was blocked by automatic moderation",
+					200000,
+				);
 		}
 	}
 }
diff --git a/src/util/entities/Migration.ts b/src/util/entities/Migration.ts
index 3f39ae72..f4e54eae 100644
--- a/src/util/entities/Migration.ts
+++ b/src/util/entities/Migration.ts
@@ -1,7 +1,14 @@
-import { Column, Entity, ObjectIdColumn, PrimaryGeneratedColumn } from "typeorm";
+import {
+	Column,
+	Entity,
+	ObjectIdColumn,
+	PrimaryGeneratedColumn,
+} from "typeorm";
 import { BaseClassWithoutId } from ".";
 
-export const PrimaryIdAutoGenerated = process.env.DATABASE?.startsWith("mongodb")
+export const PrimaryIdAutoGenerated = process.env.DATABASE?.startsWith(
+	"mongodb",
+)
 	? ObjectIdColumn
 	: PrimaryGeneratedColumn;
 
diff --git a/src/util/entities/Note.ts b/src/util/entities/Note.ts
index 36017c5e..b3ac45ee 100644
--- a/src/util/entities/Note.ts
+++ b/src/util/entities/Note.ts
@@ -15,4 +15,4 @@ export class Note extends BaseClass {
 
 	@Column()
 	content: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/entities/ReadState.ts b/src/util/entities/ReadState.ts
index b915573b..53ed5589 100644
--- a/src/util/entities/ReadState.ts
+++ b/src/util/entities/ReadState.ts
@@ -1,4 +1,11 @@
-import { Column, Entity, Index, JoinColumn, ManyToOne, RelationId } from "typeorm";
+import {
+	Column,
+	Entity,
+	Index,
+	JoinColumn,
+	ManyToOne,
+	RelationId,
+} from "typeorm";
 import { BaseClass } from "./BaseClass";
 import { Channel } from "./Channel";
 import { Message } from "./Message";
@@ -33,8 +40,8 @@ export class ReadState extends BaseClass {
 
 	// fully read marker
 	@Column({ nullable: true })
-	last_message_id: string; 
-	
+	last_message_id: string;
+
 	// public read receipt
 	@Column({ nullable: true })
 	public_ack: string;
diff --git a/src/util/entities/Relationship.ts b/src/util/entities/Relationship.ts
index c3592c76..25b52757 100644
--- a/src/util/entities/Relationship.ts
+++ b/src/util/entities/Relationship.ts
@@ -1,4 +1,11 @@
-import { Column, Entity, Index, JoinColumn, ManyToOne, RelationId } from "typeorm";
+import {
+	Column,
+	Entity,
+	Index,
+	JoinColumn,
+	ManyToOne,
+	RelationId,
+} from "typeorm";
 import { BaseClass } from "./BaseClass";
 import { User } from "./User";
 
diff --git a/src/util/entities/StickerPack.ts b/src/util/entities/StickerPack.ts
index ec8c69a2..04d74bac 100644
--- a/src/util/entities/StickerPack.ts
+++ b/src/util/entities/StickerPack.ts
@@ -1,4 +1,12 @@
-import { Column, Entity, JoinColumn, ManyToOne, OneToMany, OneToOne, RelationId } from "typeorm";
+import {
+	Column,
+	Entity,
+	JoinColumn,
+	ManyToOne,
+	OneToMany,
+	OneToOne,
+	RelationId,
+} from "typeorm";
 import { Sticker } from ".";
 import { BaseClass } from "./BaseClass";
 
diff --git a/src/util/entities/Team.ts b/src/util/entities/Team.ts
index 22140b7f..8f410bb4 100644
--- a/src/util/entities/Team.ts
+++ b/src/util/entities/Team.ts
@@ -1,4 +1,12 @@
-import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, OneToMany, RelationId } from "typeorm";
+import {
+	Column,
+	Entity,
+	JoinColumn,
+	ManyToMany,
+	ManyToOne,
+	OneToMany,
+	RelationId,
+} from "typeorm";
 import { BaseClass } from "./BaseClass";
 import { TeamMember } from "./TeamMember";
 import { User } from "./User";
diff --git a/src/util/entities/TeamMember.ts b/src/util/entities/TeamMember.ts
index b726e1e8..3f4a0422 100644
--- a/src/util/entities/TeamMember.ts
+++ b/src/util/entities/TeamMember.ts
@@ -20,9 +20,13 @@ export class TeamMember extends BaseClass {
 	team_id: string;
 
 	@JoinColumn({ name: "team_id" })
-	@ManyToOne(() => require("./Team").Team, (team: import("./Team").Team) => team.members, {
-		onDelete: "CASCADE",
-	})
+	@ManyToOne(
+		() => require("./Team").Team,
+		(team: import("./Team").Team) => team.members,
+		{
+			onDelete: "CASCADE",
+		},
+	)
 	team: import("./Team").Team;
 
 	@Column({ nullable: true })
diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts
index 84a8a674..1389a424 100644
--- a/src/util/entities/User.ts
+++ b/src/util/entities/User.ts
@@ -1,9 +1,24 @@
-import { BeforeInsert, BeforeUpdate, Column, Entity, FindOneOptions, JoinColumn, OneToMany } from "typeorm";
+import {
+	BeforeInsert,
+	BeforeUpdate,
+	Column,
+	Entity,
+	FindOneOptions,
+	JoinColumn,
+	OneToMany,
+} from "typeorm";
 import { BaseClass } from "./BaseClass";
 import { BitField } from "../util/BitField";
 import { Relationship } from "./Relationship";
 import { ConnectedAccount } from "./ConnectedAccount";
-import { Config, FieldErrors, Snowflake, trimSpecial, BannedWords, adjustEmail } from "..";
+import {
+	Config,
+	FieldErrors,
+	Snowflake,
+	trimSpecial,
+	BannedWords,
+	adjustEmail,
+} from "..";
 import { Member, Session } from ".";
 
 export enum PublicUserEnum {
@@ -38,7 +53,7 @@ export enum PrivateUserEnum {
 export type PrivateUserKeys = keyof typeof PrivateUserEnum | PublicUserKeys;
 
 export const PublicUserProjection = Object.values(PublicUserEnum).filter(
-	(x) => typeof x === "string"
+	(x) => typeof x === "string",
 ) as PublicUserKeys[];
 export const PrivateUserProjection = [
 	...PublicUserProjection,
@@ -48,7 +63,7 @@ export const PrivateUserProjection = [
 // Private user data that should never get sent to the client
 export type PublicUser = Pick<User, PublicUserKeys>;
 
-export interface UserPublic extends Pick<User, PublicUserKeys> { }
+export interface UserPublic extends Pick<User, PublicUserKeys> {}
 
 export interface UserPrivate extends Pick<User, PrivateUserKeys> {
 	locale: string;
@@ -144,17 +159,25 @@ export class User extends BaseClass {
 	sessions: Session[];
 
 	@JoinColumn({ name: "relationship_ids" })
-	@OneToMany(() => Relationship, (relationship: Relationship) => relationship.from, {
-		cascade: true,
-		orphanedRowAction: "delete",
-	})
+	@OneToMany(
+		() => Relationship,
+		(relationship: Relationship) => relationship.from,
+		{
+			cascade: true,
+			orphanedRowAction: "delete",
+		},
+	)
 	relationships: Relationship[];
 
 	@JoinColumn({ name: "connected_account_ids" })
-	@OneToMany(() => ConnectedAccount, (account: ConnectedAccount) => account.user, {
-		cascade: true,
-		orphanedRowAction: "delete",
-	})
+	@OneToMany(
+		() => ConnectedAccount,
+		(account: ConnectedAccount) => account.user,
+		{
+			cascade: true,
+			orphanedRowAction: "delete",
+		},
+	)
 	connected_accounts: ConnectedAccount[];
 
 	@Column({ type: "simple-json", select: false })
@@ -177,16 +200,43 @@ export class User extends BaseClass {
 	@BeforeInsert()
 	validate() {
 		this.email = adjustEmail(this.email);
-		if (!this.email) throw FieldErrors({ email: { message: "Invalid email", code: "EMAIL_INVALID" } });
-		if (!this.email.match(/([a-z\d.-]{3,})@([a-z\d.-]+).([a-z]{2,})/g)) throw FieldErrors({ email: { message: "Invalid email", code: "EMAIL_INVALID" } });
+		if (!this.email)
+			throw FieldErrors({
+				email: { message: "Invalid email", code: "EMAIL_INVALID" },
+			});
+		if (!this.email.match(/([a-z\d.-]{3,})@([a-z\d.-]+).([a-z]{2,})/g))
+			throw FieldErrors({
+				email: { message: "Invalid email", code: "EMAIL_INVALID" },
+			});
 
 		const discrim = Number(this.discriminator);
-		if (this.discriminator.length > 4) throw FieldErrors({ email: { message: "Discriminator cannot be more than 4 digits.", code: "DISCRIMINATOR_INVALID" } });
-		if (isNaN(discrim)) throw FieldErrors({ email: { message: "Discriminator must be a number.", code: "DISCRIMINATOR_INVALID" } });
-		if (discrim <= 0 || discrim >= 10000) throw FieldErrors({ email: { message: "Discriminator must be a number.", code: "DISCRIMINATOR_INVALID" } });
+		if (this.discriminator.length > 4)
+			throw FieldErrors({
+				email: {
+					message: "Discriminator cannot be more than 4 digits.",
+					code: "DISCRIMINATOR_INVALID",
+				},
+			});
+		if (isNaN(discrim))
+			throw FieldErrors({
+				email: {
+					message: "Discriminator must be a number.",
+					code: "DISCRIMINATOR_INVALID",
+				},
+			});
+		if (discrim <= 0 || discrim >= 10000)
+			throw FieldErrors({
+				email: {
+					message: "Discriminator must be a number.",
+					code: "DISCRIMINATOR_INVALID",
+				},
+			});
 		this.discriminator = discrim.toString().padStart(4, "0");
 
-		if (BannedWords.find(this.username)) throw FieldErrors({ username: { message: "Bad username", code: "INVALID_USERNAME" } });
+		if (BannedWords.find(this.username))
+			throw FieldErrors({
+				username: { message: "Bad username", code: "INVALID_USERNAME" },
+			});
 	}
 
 	toPublicUser() {
@@ -202,17 +252,25 @@ export class User extends BaseClass {
 			where: { id: user_id },
 			...opts,
 			//@ts-ignore
-			select: [...PublicUserProjection, ...(opts?.select || [])],	// TODO: fix
+			select: [...PublicUserProjection, ...(opts?.select || [])], // TODO: fix
 		});
 	}
 
-	private static async generateDiscriminator(username: string): Promise<string | undefined> {
+	private static async generateDiscriminator(
+		username: string,
+	): Promise<string | undefined> {
 		if (Config.get().register.incrementingDiscriminators) {
 			// discriminator will be incrementally generated
 
 			// First we need to figure out the currently highest discrimnator for the given username and then increment it
-			const users = await User.find({ where: { username }, select: ["discriminator"] });
-			const highestDiscriminator = Math.max(0, ...users.map((u) => Number(u.discriminator)));
+			const users = await User.find({
+				where: { username },
+				select: ["discriminator"],
+			});
+			const highestDiscriminator = Math.max(
+				0,
+				...users.map((u) => Number(u.discriminator)),
+			);
 
 			const discriminator = highestDiscriminator + 1;
 			if (discriminator >= 10000) {
@@ -226,8 +284,13 @@ export class User extends BaseClass {
 			// randomly generates a discriminator between 1 and 9999 and checks max five times if it already exists
 			// TODO: is there any better way to generate a random discriminator only once, without checking if it already exists in the database?
 			for (let tries = 0; tries < 5; tries++) {
-				const discriminator = Math.randomIntBetween(1, 9999).toString().padStart(4, "0");
-				const exists = await User.findOne({ where: { discriminator, username: username }, select: ["id"] });
+				const discriminator = Math.randomIntBetween(1, 9999)
+					.toString()
+					.padStart(4, "0");
+				const exists = await User.findOne({
+					where: { discriminator, username: username },
+					select: ["id"],
+				});
 				if (!exists) return discriminator;
 			}
 
@@ -265,7 +328,8 @@ export class User extends BaseClass {
 		// TODO: save date_of_birth
 		// appearently discord doesn't save the date of birth and just calculate if nsfw is allowed
 		// if nsfw_allowed is null/undefined it'll require date_of_birth to set it to true/false
-		const language = req.language === "en" ? "en-US" : req.language || "en-US";
+		const language =
+			req.language === "en" ? "en-US" : req.language || "en-US";
 
 		const user = User.create({
 			created_at: new Date(),
@@ -295,8 +359,8 @@ export class User extends BaseClass {
 			},
 			settings: { ...defaultSettings, locale: language },
 			purchased_flags: 5, // TODO: idk what the values for this are
-			premium_usage_flags: 2,  // TODO: idk what the values for this are
-			extended_settings: "",	// TODO: was {}
+			premium_usage_flags: 2, // TODO: idk what the values for this are
+			extended_settings: "", // TODO: was {}
 			fingerprints: [],
 		});
 
@@ -305,7 +369,7 @@ export class User extends BaseClass {
 		setImmediate(async () => {
 			if (Config.get().guild.autoJoin.enabled) {
 				for (const guild of Config.get().guild.autoJoin.guilds || []) {
-					await Member.addToGuild(user.id, guild).catch((e) => { });
+					await Member.addToGuild(user.id, guild).catch((e) => {});
 				}
 			}
 		});
@@ -372,7 +436,7 @@ export interface UserSettings {
 	disable_games_tab: boolean;
 	enable_tts_command: boolean;
 	explicit_content_filter: number;
-	friend_source_flags: { all: boolean; };
+	friend_source_flags: { all: boolean };
 	gateway_connected: boolean;
 	gif_auto_play: boolean;
 	// every top guild is displayed as a "folder"
diff --git a/src/util/entities/index.ts b/src/util/entities/index.ts
index 49793810..c439a4b7 100644
--- a/src/util/entities/index.ts
+++ b/src/util/entities/index.ts
@@ -29,4 +29,4 @@ export * from "./VoiceState";
 export * from "./Webhook";
 export * from "./ClientRelease";
 export * from "./BackupCodes";
-export * from "./Note";
\ No newline at end of file
+export * from "./Note";
diff --git a/src/util/imports/OrmUtils.ts b/src/util/imports/OrmUtils.ts
index 68a1932c..26652db0 100644
--- a/src/util/imports/OrmUtils.ts
+++ b/src/util/imports/OrmUtils.ts
@@ -9,7 +9,12 @@ export class OrmUtils {
 		return !item.constructor || item.constructor === Object;
 	}
 
-	private static mergeArrayKey(target: any, key: number, value: any, memo: Map<any, any>) {
+	private static mergeArrayKey(
+		target: any,
+		key: number,
+		value: any,
+		memo: Map<any, any>,
+	) {
 		// Have we seen this before?  Prevent infinite recursion.
 		if (memo.has(value)) {
 			target[key] = memo.get(value);
@@ -38,7 +43,12 @@ export class OrmUtils {
 		memo.delete(value);
 	}
 
-	private static mergeObjectKey(target: any, key: string, value: any, memo: Map<any, any>) {
+	private static mergeObjectKey(
+		target: any,
+		key: string,
+		value: any,
+		memo: Map<any, any>,
+	) {
 		// Have we seen this before?  Prevent infinite recursion.
 		if (memo.has(value)) {
 			Object.assign(target, { [key]: memo.get(value) });
@@ -67,7 +77,11 @@ export class OrmUtils {
 		memo.delete(value);
 	}
 
-	private static merge(target: any, source: any, memo: Map<any, any> = new Map()): any {
+	private static merge(
+		target: any,
+		source: any,
+		memo: Map<any, any> = new Map(),
+	): any {
 		if (Array.isArray(target) && Array.isArray(source)) {
 			for (let key = 0; key < source.length; key++) {
 				this.mergeArrayKey(target, key, source[key], memo);
@@ -93,4 +107,4 @@ export class OrmUtils {
 
 		return target;
 	}
-}
\ No newline at end of file
+}
diff --git a/src/util/imports/index.ts b/src/util/imports/index.ts
index 5d9bfb5f..823151d9 100644
--- a/src/util/imports/index.ts
+++ b/src/util/imports/index.ts
@@ -1 +1 @@
-export * from "./OrmUtils";
\ No newline at end of file
+export * from "./OrmUtils";
diff --git a/src/util/index.ts b/src/util/index.ts
index 385070a3..3773c275 100644
--- a/src/util/index.ts
+++ b/src/util/index.ts
@@ -5,4 +5,4 @@ export * from "./interfaces/index";
 export * from "./entities/index";
 export * from "./dtos/index";
 export * from "./schemas";
-export * from "./imports";
\ No newline at end of file
+export * from "./imports";
diff --git a/src/util/interfaces/Activity.ts b/src/util/interfaces/Activity.ts
index 9912e197..279ee40f 100644
--- a/src/util/interfaces/Activity.ts
+++ b/src/util/interfaces/Activity.ts
@@ -36,7 +36,8 @@ export interface Activity {
 
 	id?: string;
 	sync_id?: string;
-	metadata?: { // spotify
+	metadata?: {
+		// spotify
 		context_uri?: string;
 		album_id: string;
 		artist_ids: string[];
diff --git a/src/util/interfaces/Event.ts b/src/util/interfaces/Event.ts
index 59f995db..472fd572 100644
--- a/src/util/interfaces/Event.ts
+++ b/src/util/interfaces/Event.ts
@@ -75,7 +75,7 @@ export interface ReadyEventData {
 		number,
 		[[number, { e: number; s: number }[]]],
 		[number, [[number, [number, number]]]],
-		{ b: number; k: bigint[] }[]
+		{ b: number; k: bigint[] }[],
 	][];
 	guild_join_requests?: any[]; // ? what is this? this is new
 	shard?: [number, number];
diff --git a/src/util/migrations/1633864260873-EmojiRoles.ts b/src/util/migrations/1633864260873-EmojiRoles.ts
index f0d709f2..31ced96b 100644
--- a/src/util/migrations/1633864260873-EmojiRoles.ts
+++ b/src/util/migrations/1633864260873-EmojiRoles.ts
@@ -4,10 +4,14 @@ export class EmojiRoles1633864260873 implements MigrationInterface {
 	name = "EmojiRoles1633864260873";
 
 	public async up(queryRunner: QueryRunner): Promise<void> {
-		await queryRunner.query(`ALTER TABLE "emojis" ADD "roles" text NOT NULL DEFAULT ''`);
+		await queryRunner.query(
+			`ALTER TABLE "emojis" ADD "roles" text NOT NULL DEFAULT ''`,
+		);
 	}
 
 	public async down(queryRunner: QueryRunner): Promise<void> {
-		await queryRunner.query(`ALTER TABLE "emojis" DROP COLUMN column_name "roles"`);
+		await queryRunner.query(
+			`ALTER TABLE "emojis" DROP COLUMN column_name "roles"`,
+		);
 	}
 }
diff --git a/src/util/migrations/1633864669243-EmojiUser.ts b/src/util/migrations/1633864669243-EmojiUser.ts
index 982405d7..9610216b 100644
--- a/src/util/migrations/1633864669243-EmojiUser.ts
+++ b/src/util/migrations/1633864669243-EmojiUser.ts
@@ -7,17 +7,21 @@ export class EmojiUser1633864669243 implements MigrationInterface {
 		await queryRunner.query(`ALTER TABLE "emojis" ADD "user_id" varchar`);
 		try {
 			await queryRunner.query(
-				`ALTER TABLE "emojis" ADD CONSTRAINT FK_fa7ddd5f9a214e28ce596548421 FOREIGN KEY (user_id) REFERENCES users(id)`
+				`ALTER TABLE "emojis" ADD CONSTRAINT FK_fa7ddd5f9a214e28ce596548421 FOREIGN KEY (user_id) REFERENCES users(id)`,
 			);
 		} catch (error) {
 			console.error(
-				"sqlite doesn't support altering foreign keys: https://stackoverflow.com/questions/1884818/how-do-i-add-a-foreign-key-to-an-existing-sqlite-table"
+				"sqlite doesn't support altering foreign keys: https://stackoverflow.com/questions/1884818/how-do-i-add-a-foreign-key-to-an-existing-sqlite-table",
 			);
 		}
 	}
 
 	public async down(queryRunner: QueryRunner): Promise<void> {
-		await queryRunner.query(`ALTER TABLE "emojis" DROP COLUMN column_name "user_id"`);
-		await queryRunner.query(`ALTER TABLE "emojis" DROP CONSTRAINT FK_fa7ddd5f9a214e28ce596548421`);
+		await queryRunner.query(
+			`ALTER TABLE "emojis" DROP COLUMN column_name "user_id"`,
+		);
+		await queryRunner.query(
+			`ALTER TABLE "emojis" DROP CONSTRAINT FK_fa7ddd5f9a214e28ce596548421`,
+		);
 	}
 }
diff --git a/src/util/migrations/1633881705509-VanityInvite.ts b/src/util/migrations/1633881705509-VanityInvite.ts
index 45485310..16072473 100644
--- a/src/util/migrations/1633881705509-VanityInvite.ts
+++ b/src/util/migrations/1633881705509-VanityInvite.ts
@@ -5,15 +5,21 @@ export class VanityInvite1633881705509 implements MigrationInterface {
 
 	public async up(queryRunner: QueryRunner): Promise<void> {
 		try {
-			await queryRunner.query(`ALTER TABLE "emojis" DROP COLUMN vanity_url_code`);
-			await queryRunner.query(`ALTER TABLE "emojis" DROP CONSTRAINT FK_c2c1809d79eb120ea0cb8d342ad`);
+			await queryRunner.query(
+				`ALTER TABLE "emojis" DROP COLUMN vanity_url_code`,
+			);
+			await queryRunner.query(
+				`ALTER TABLE "emojis" DROP CONSTRAINT FK_c2c1809d79eb120ea0cb8d342ad`,
+			);
 		} catch (error) {}
 	}
 
 	public async down(queryRunner: QueryRunner): Promise<void> {
-		await queryRunner.query(`ALTER TABLE "emojis" ADD vanity_url_code varchar`);
 		await queryRunner.query(
-			`ALTER TABLE "emojis" ADD CONSTRAINT FK_c2c1809d79eb120ea0cb8d342ad FOREIGN KEY ("vanity_url_code") REFERENCES "invites"("code") ON DELETE NO ACTION ON UPDATE NO ACTION`
+			`ALTER TABLE "emojis" ADD vanity_url_code varchar`,
+		);
+		await queryRunner.query(
+			`ALTER TABLE "emojis" ADD CONSTRAINT FK_c2c1809d79eb120ea0cb8d342ad FOREIGN KEY ("vanity_url_code") REFERENCES "invites"("code") ON DELETE NO ACTION ON UPDATE NO ACTION`,
 		);
 	}
 }
diff --git a/src/util/migrations/1634308884591-Stickers.ts b/src/util/migrations/1634308884591-Stickers.ts
index fbc4649f..f7b83242 100644
--- a/src/util/migrations/1634308884591-Stickers.ts
+++ b/src/util/migrations/1634308884591-Stickers.ts
@@ -1,35 +1,64 @@
-import { MigrationInterface, QueryRunner, Table, TableColumn, TableForeignKey } from "typeorm";
+import {
+	MigrationInterface,
+	QueryRunner,
+	Table,
+	TableColumn,
+	TableForeignKey,
+} from "typeorm";
 
 export class Stickers1634308884591 implements MigrationInterface {
 	name = "Stickers1634308884591";
 
 	public async up(queryRunner: QueryRunner): Promise<void> {
-		await queryRunner.dropForeignKey("read_states", "FK_6f255d873cfbfd7a93849b7ff74");
+		await queryRunner.dropForeignKey(
+			"read_states",
+			"FK_6f255d873cfbfd7a93849b7ff74",
+		);
 		await queryRunner.changeColumn(
 			"stickers",
 			"tags",
-			new TableColumn({ name: "tags", type: "varchar", isNullable: true })
+			new TableColumn({
+				name: "tags",
+				type: "varchar",
+				isNullable: true,
+			}),
 		);
 		await queryRunner.changeColumn(
 			"stickers",
 			"pack_id",
-			new TableColumn({ name: "pack_id", type: "varchar", isNullable: true })
+			new TableColumn({
+				name: "pack_id",
+				type: "varchar",
+				isNullable: true,
+			}),
+		);
+		await queryRunner.changeColumn(
+			"stickers",
+			"type",
+			new TableColumn({ name: "type", type: "integer" }),
 		);
-		await queryRunner.changeColumn("stickers", "type", new TableColumn({ name: "type", type: "integer" }));
 		await queryRunner.changeColumn(
 			"stickers",
 			"format_type",
-			new TableColumn({ name: "format_type", type: "integer" })
+			new TableColumn({ name: "format_type", type: "integer" }),
 		);
 		await queryRunner.changeColumn(
 			"stickers",
 			"available",
-			new TableColumn({ name: "available", type: "boolean", isNullable: true })
+			new TableColumn({
+				name: "available",
+				type: "boolean",
+				isNullable: true,
+			}),
 		);
 		await queryRunner.changeColumn(
 			"stickers",
 			"user_id",
-			new TableColumn({ name: "user_id", type: "boolean", isNullable: true })
+			new TableColumn({
+				name: "user_id",
+				type: "boolean",
+				isNullable: true,
+			}),
 		);
 		await queryRunner.createForeignKey(
 			"stickers",
@@ -39,17 +68,33 @@ export class Stickers1634308884591 implements MigrationInterface {
 				referencedColumnNames: ["id"],
 				referencedTableName: "users",
 				onDelete: "CASCADE",
-			})
+			}),
 		);
 		await queryRunner.createTable(
 			new Table({
 				name: "sticker_packs",
 				columns: [
-					new TableColumn({ name: "id", type: "varchar", isPrimary: true }),
+					new TableColumn({
+						name: "id",
+						type: "varchar",
+						isPrimary: true,
+					}),
 					new TableColumn({ name: "name", type: "varchar" }),
-					new TableColumn({ name: "description", type: "varchar", isNullable: true }),
-					new TableColumn({ name: "banner_asset_id", type: "varchar", isNullable: true }),
-					new TableColumn({ name: "cover_sticker_id", type: "varchar", isNullable: true }),
+					new TableColumn({
+						name: "description",
+						type: "varchar",
+						isNullable: true,
+					}),
+					new TableColumn({
+						name: "banner_asset_id",
+						type: "varchar",
+						isNullable: true,
+					}),
+					new TableColumn({
+						name: "cover_sticker_id",
+						type: "varchar",
+						isNullable: true,
+					}),
 				],
 				foreignKeys: [
 					new TableForeignKey({
@@ -58,7 +103,7 @@ export class Stickers1634308884591 implements MigrationInterface {
 						referencedTableName: "stickers",
 					}),
 				],
-			})
+			}),
 		);
 	}
 
diff --git a/src/util/migrations/1634424361103-Presence.ts b/src/util/migrations/1634424361103-Presence.ts
index 729955b8..a71cb253 100644
--- a/src/util/migrations/1634424361103-Presence.ts
+++ b/src/util/migrations/1634424361103-Presence.ts
@@ -4,7 +4,10 @@ export class Presence1634424361103 implements MigrationInterface {
 	name = "Presence1634424361103";
 
 	public async up(queryRunner: QueryRunner): Promise<void> {
-		queryRunner.addColumn("sessions", new TableColumn({ name: "activites", type: "text" }));
+		queryRunner.addColumn(
+			"sessions",
+			new TableColumn({ name: "activites", type: "text" }),
+		);
 	}
 
 	public async down(queryRunner: QueryRunner): Promise<void> {}
diff --git a/src/util/migrations/1634426540271-MigrationTimestamp.ts b/src/util/migrations/1634426540271-MigrationTimestamp.ts
index 3208b25b..fb596906 100644
--- a/src/util/migrations/1634426540271-MigrationTimestamp.ts
+++ b/src/util/migrations/1634426540271-MigrationTimestamp.ts
@@ -7,7 +7,11 @@ export class MigrationTimestamp1634426540271 implements MigrationInterface {
 		await queryRunner.changeColumn(
 			"migrations",
 			"timestamp",
-			new TableColumn({ name: "timestampe", type: "bigint", isNullable: false })
+			new TableColumn({
+				name: "timestampe",
+				type: "bigint",
+				isNullable: false,
+			}),
 		);
 	}
 
diff --git a/src/util/migrations/1660678870706-opencordFixes.ts b/src/util/migrations/1660678870706-opencordFixes.ts
index 1f10c212..53c561ce 100644
--- a/src/util/migrations/1660678870706-opencordFixes.ts
+++ b/src/util/migrations/1660678870706-opencordFixes.ts
@@ -1,53 +1,52 @@
 import { MigrationInterface, QueryRunner } from "typeorm";
 
 export class opencordFixes1660678870706 implements MigrationInterface {
-    name = 'opencordFixes1660678870706'
+	name = "opencordFixes1660678870706";
 
-    public async up(queryRunner: QueryRunner): Promise<void> {
-        await queryRunner.query(`
+	public async up(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(`
             ALTER TABLE \`users\`
             ADD \`purchased_flags\` int NOT NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`users\`
             ADD \`premium_usage_flags\` int NOT NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`user_settings\`
             ADD \`friend_discovery_flags\` int NOT NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`user_settings\`
             ADD \`view_nsfw_guilds\` tinyint NOT NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`user_settings\`
             ADD \`passwordless\` tinyint NOT NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`users\` CHANGE \`mfa_enabled\` \`mfa_enabled\` tinyint NOT NULL
         `);
-    }
+	}
 
-    public async down(queryRunner: QueryRunner): Promise<void> {
-        await queryRunner.query(`
+	public async down(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(`
             ALTER TABLE \`users\` CHANGE \`mfa_enabled\` \`mfa_enabled\` tinyint NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`user_settings\` DROP COLUMN \`passwordless\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`user_settings\` DROP COLUMN \`view_nsfw_guilds\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`user_settings\` DROP COLUMN \`friend_discovery_flags\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`users\` DROP COLUMN \`premium_usage_flags\`
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`users\` DROP COLUMN \`purchased_flags\`
         `);
-    }
-
-}
\ No newline at end of file
+	}
+}
diff --git a/src/util/migrations/1660689892073-mobileFixes2.ts b/src/util/migrations/1660689892073-mobileFixes2.ts
index bd28694e..63e7e032 100644
--- a/src/util/migrations/1660689892073-mobileFixes2.ts
+++ b/src/util/migrations/1660689892073-mobileFixes2.ts
@@ -1,37 +1,36 @@
 import { MigrationInterface, QueryRunner } from "typeorm";
 
 export class mobileFixes21660689892073 implements MigrationInterface {
-    name = 'mobileFixes21660689892073'
+	name = "mobileFixes21660689892073";
 
-    public async up(queryRunner: QueryRunner): Promise<void> {
-        await queryRunner.query(`
+	public async up(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(`
             ALTER TABLE \`user_settings\`
             ADD \`banner_color\` varchar(255) NULL
         `);
 		await queryRunner.query(`
 			UPDATE \`channels\` SET \`nsfw\` = 0 WHERE \`nsfw\` = NULL
 		`);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`channels\` CHANGE \`nsfw\` \`nsfw\` tinyint NOT NULL
         `);
 		await queryRunner.query(`
 			UPDATE \`guilds\` SET \`nsfw\` = 0 WHERE \`nsfw\` = NULL
 		`);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`guilds\` CHANGE \`nsfw\` \`nsfw\` tinyint NOT NULL
         `);
-    }
+	}
 
-    public async down(queryRunner: QueryRunner): Promise<void> {
-        await queryRunner.query(`
+	public async down(queryRunner: QueryRunner): Promise<void> {
+		await queryRunner.query(`
             ALTER TABLE \`guilds\` CHANGE \`nsfw\` \`nsfw\` tinyint NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`channels\` CHANGE \`nsfw\` \`nsfw\` tinyint NULL
         `);
-        await queryRunner.query(`
+		await queryRunner.query(`
             ALTER TABLE \`user_settings\` DROP COLUMN \`banner_color\`
         `);
-    }
-
-}
\ No newline at end of file
+	}
+}
diff --git a/src/util/schemas/ActivitySchema.ts b/src/util/schemas/ActivitySchema.ts
index d316420e..5a3d205b 100644
--- a/src/util/schemas/ActivitySchema.ts
+++ b/src/util/schemas/ActivitySchema.ts
@@ -41,7 +41,8 @@ export const ActivitySchema = {
 
 			$id: String,
 			$sync_id: String,
-			$metadata: { // spotify
+			$metadata: {
+				// spotify
 				$context_uri: String,
 				album_id: String,
 				artist_ids: [String],
@@ -57,4 +58,4 @@ export interface ActivitySchema {
 	status: Status;
 	activities?: Activity[];
 	since?: number; // unix time (in milliseconds) of when the client went idle, or null if the client is not idle
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/BackupCodesChallengeSchema.ts b/src/util/schemas/BackupCodesChallengeSchema.ts
index d6b519b7..8e2f0649 100644
--- a/src/util/schemas/BackupCodesChallengeSchema.ts
+++ b/src/util/schemas/BackupCodesChallengeSchema.ts
@@ -1,3 +1,3 @@
 export interface BackupCodesChallengeSchema {
 	password: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/BanCreateSchema.ts b/src/util/schemas/BanCreateSchema.ts
index 876b2a89..834577dc 100644
--- a/src/util/schemas/BanCreateSchema.ts
+++ b/src/util/schemas/BanCreateSchema.ts
@@ -1,4 +1,4 @@
 export interface BanCreateSchema {
 	delete_message_days?: string;
 	reason?: string;
-};
\ No newline at end of file
+}
diff --git a/src/util/schemas/BanModeratorSchema.ts b/src/util/schemas/BanModeratorSchema.ts
index 8efa2402..afb76433 100644
--- a/src/util/schemas/BanModeratorSchema.ts
+++ b/src/util/schemas/BanModeratorSchema.ts
@@ -4,4 +4,4 @@ export interface BanModeratorSchema {
 	guild_id: string;
 	executor_id: string;
 	reason?: string | undefined;
-};
\ No newline at end of file
+}
diff --git a/src/util/schemas/BanRegistrySchema.ts b/src/util/schemas/BanRegistrySchema.ts
index 8680d3db..501f94dc 100644
--- a/src/util/schemas/BanRegistrySchema.ts
+++ b/src/util/schemas/BanRegistrySchema.ts
@@ -5,4 +5,4 @@ export interface BanRegistrySchema {
 	executor_id: string;
 	ip?: string;
 	reason?: string | undefined;
-};
\ No newline at end of file
+}
diff --git a/src/util/schemas/BulkDeleteSchema.ts b/src/util/schemas/BulkDeleteSchema.ts
index 6a71e052..bfc4df65 100644
--- a/src/util/schemas/BulkDeleteSchema.ts
+++ b/src/util/schemas/BulkDeleteSchema.ts
@@ -1,3 +1,3 @@
 export interface BulkDeleteSchema {
 	messages: string[];
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/ChannelModifySchema.ts b/src/util/schemas/ChannelModifySchema.ts
index 835ea2d7..9a07f983 100644
--- a/src/util/schemas/ChannelModifySchema.ts
+++ b/src/util/schemas/ChannelModifySchema.ts
@@ -27,4 +27,4 @@ export interface ChannelModifySchema {
 	flags?: number;
 	default_thread_rate_limit_per_user?: number;
 	video_quality_mode?: number;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/CodesVerificationSchema.ts b/src/util/schemas/CodesVerificationSchema.ts
index e8e2e7b4..73c371eb 100644
--- a/src/util/schemas/CodesVerificationSchema.ts
+++ b/src/util/schemas/CodesVerificationSchema.ts
@@ -2,4 +2,4 @@ export interface CodesVerificationSchema {
 	key: string;
 	nonce: string;
 	regenerate?: boolean;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/DmChannelCreateSchema.ts b/src/util/schemas/DmChannelCreateSchema.ts
index 04b8ff69..1b0fe86d 100644
--- a/src/util/schemas/DmChannelCreateSchema.ts
+++ b/src/util/schemas/DmChannelCreateSchema.ts
@@ -1,4 +1,4 @@
 export interface DmChannelCreateSchema {
 	name?: string;
 	recipients: string[];
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/EmojiCreateSchema.ts b/src/util/schemas/EmojiCreateSchema.ts
index 8e2a2307..34084713 100644
--- a/src/util/schemas/EmojiCreateSchema.ts
+++ b/src/util/schemas/EmojiCreateSchema.ts
@@ -3,4 +3,4 @@ export interface EmojiCreateSchema {
 	image: string;
 	require_colons?: boolean | null;
 	roles?: string[];
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/EmojiModifySchema.ts b/src/util/schemas/EmojiModifySchema.ts
index cd5b7e3e..05d2d395 100644
--- a/src/util/schemas/EmojiModifySchema.ts
+++ b/src/util/schemas/EmojiModifySchema.ts
@@ -1,4 +1,4 @@
 export interface EmojiModifySchema {
 	name?: string;
 	roles?: string[];
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/GuildCreateSchema.ts b/src/util/schemas/GuildCreateSchema.ts
index 9b5f7dc2..f3de7007 100644
--- a/src/util/schemas/GuildCreateSchema.ts
+++ b/src/util/schemas/GuildCreateSchema.ts
@@ -11,4 +11,4 @@ export interface GuildCreateSchema {
 	guild_template_code?: string;
 	system_channel_id?: string;
 	rules_channel_id?: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/GuildTemplateCreateSchema.ts b/src/util/schemas/GuildTemplateCreateSchema.ts
index 7caefcb8..59db8428 100644
--- a/src/util/schemas/GuildTemplateCreateSchema.ts
+++ b/src/util/schemas/GuildTemplateCreateSchema.ts
@@ -1,4 +1,4 @@
 export interface GuildTemplateCreateSchema {
 	name: string;
 	avatar?: string | null;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/GuildUpdateWelcomeScreenSchema.ts b/src/util/schemas/GuildUpdateWelcomeScreenSchema.ts
index 0022da6e..e271b83e 100644
--- a/src/util/schemas/GuildUpdateWelcomeScreenSchema.ts
+++ b/src/util/schemas/GuildUpdateWelcomeScreenSchema.ts
@@ -7,4 +7,4 @@ export interface GuildUpdateWelcomeScreenSchema {
 	}[];
 	enabled?: boolean;
 	description?: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/InviteCreateSchema.ts b/src/util/schemas/InviteCreateSchema.ts
index 83ae22dd..cac11147 100644
--- a/src/util/schemas/InviteCreateSchema.ts
+++ b/src/util/schemas/InviteCreateSchema.ts
@@ -8,4 +8,4 @@ export interface InviteCreateSchema {
 	unique?: boolean;
 	target_user?: string;
 	target_user_type?: number;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/LoginSchema.ts b/src/util/schemas/LoginSchema.ts
index 543d236c..dc889d94 100644
--- a/src/util/schemas/LoginSchema.ts
+++ b/src/util/schemas/LoginSchema.ts
@@ -5,4 +5,4 @@ export interface LoginSchema {
 	captcha_key?: string;
 	login_source?: string;
 	gift_code_sku_id?: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/MemberChangeSchema.ts b/src/util/schemas/MemberChangeSchema.ts
index 566d7e20..2367bef3 100644
--- a/src/util/schemas/MemberChangeSchema.ts
+++ b/src/util/schemas/MemberChangeSchema.ts
@@ -1,4 +1,4 @@
 export interface MemberChangeSchema {
 	roles?: string[];
 	nick?: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/MemberNickChangeSchema.ts b/src/util/schemas/MemberNickChangeSchema.ts
index ed9fdb7b..d863038c 100644
--- a/src/util/schemas/MemberNickChangeSchema.ts
+++ b/src/util/schemas/MemberNickChangeSchema.ts
@@ -1,3 +1,3 @@
 export interface MemberNickChangeSchema {
 	nick: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/MessageAcknowledgeSchema.ts b/src/util/schemas/MessageAcknowledgeSchema.ts
index 1e7fb80d..194bb4b4 100644
--- a/src/util/schemas/MessageAcknowledgeSchema.ts
+++ b/src/util/schemas/MessageAcknowledgeSchema.ts
@@ -1,4 +1,4 @@
 export interface MessageAcknowledgeSchema {
 	manual?: boolean;
 	mention_count?: number;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/MessageCreateSchema.ts b/src/util/schemas/MessageCreateSchema.ts
index 9d77c485..bf3470bb 100644
--- a/src/util/schemas/MessageCreateSchema.ts
+++ b/src/util/schemas/MessageCreateSchema.ts
@@ -30,4 +30,4 @@ export interface MessageCreateSchema {
 	**/
 	attachments?: any[];
 	sticker_ids?: string[];
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/MfaCodesSchema.ts b/src/util/schemas/MfaCodesSchema.ts
index 226c43f1..ac05b9a4 100644
--- a/src/util/schemas/MfaCodesSchema.ts
+++ b/src/util/schemas/MfaCodesSchema.ts
@@ -1,4 +1,4 @@
 export interface MfaCodesSchema {
 	password: string;
 	regenerate?: boolean;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/ModifyGuildStickerSchema.ts b/src/util/schemas/ModifyGuildStickerSchema.ts
index 06bf4ffe..159cc44f 100644
--- a/src/util/schemas/ModifyGuildStickerSchema.ts
+++ b/src/util/schemas/ModifyGuildStickerSchema.ts
@@ -12,4 +12,4 @@ export interface ModifyGuildStickerSchema {
 	 * @maxLength 200
 	 */
 	tags: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/PruneSchema.ts b/src/util/schemas/PruneSchema.ts
index 60601d81..bea5e2b4 100644
--- a/src/util/schemas/PruneSchema.ts
+++ b/src/util/schemas/PruneSchema.ts
@@ -3,4 +3,4 @@ export interface PruneSchema {
 	 * @min 0
 	 */
 	days: number;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/PurgeSchema.ts b/src/util/schemas/PurgeSchema.ts
index 8916be92..f5ab0a20 100644
--- a/src/util/schemas/PurgeSchema.ts
+++ b/src/util/schemas/PurgeSchema.ts
@@ -1,4 +1,4 @@
 export interface PurgeSchema {
 	before: string;
 	after: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/RegisterSchema.ts b/src/util/schemas/RegisterSchema.ts
index c0cc3805..865f55b3 100644
--- a/src/util/schemas/RegisterSchema.ts
+++ b/src/util/schemas/RegisterSchema.ts
@@ -24,4 +24,4 @@ export interface RegisterSchema {
 	captcha_key?: string;
 
 	promotional_email_opt_in?: boolean;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/RelationshipPostSchema.ts b/src/util/schemas/RelationshipPostSchema.ts
index 3ff6eade..774c67f6 100644
--- a/src/util/schemas/RelationshipPostSchema.ts
+++ b/src/util/schemas/RelationshipPostSchema.ts
@@ -1,4 +1,4 @@
 export interface RelationshipPostSchema {
 	discriminator: string;
 	username: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/RelationshipPutSchema.ts b/src/util/schemas/RelationshipPutSchema.ts
index 455f854e..0a7f9720 100644
--- a/src/util/schemas/RelationshipPutSchema.ts
+++ b/src/util/schemas/RelationshipPutSchema.ts
@@ -2,4 +2,4 @@ import { RelationshipType } from "@fosscord/util";
 
 export interface RelationshipPutSchema {
 	type?: RelationshipType;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/RoleModifySchema.ts b/src/util/schemas/RoleModifySchema.ts
index adb0c1a6..f3f4a20e 100644
--- a/src/util/schemas/RoleModifySchema.ts
+++ b/src/util/schemas/RoleModifySchema.ts
@@ -7,4 +7,4 @@ export interface RoleModifySchema {
 	position?: number;
 	icon?: string;
 	unicode_emoji?: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/SelectProtocolSchema.ts b/src/util/schemas/SelectProtocolSchema.ts
index 92958e97..0ba0c23b 100644
--- a/src/util/schemas/SelectProtocolSchema.ts
+++ b/src/util/schemas/SelectProtocolSchema.ts
@@ -1,12 +1,12 @@
 export interface SelectProtocolSchema {
 	protocol: "webrtc" | "udp";
 	data:
-	| string
-	| {
-		address: string;
-		port: number;
-		mode: string;
-	};
+		| string
+		| {
+				address: string;
+				port: number;
+				mode: string;
+		  };
 	sdp?: string;
 	codecs?: {
 		name: "opus" | "VP8" | "VP9" | "H264";
@@ -16,4 +16,4 @@ export interface SelectProtocolSchema {
 		rtx_payload_type?: number | null;
 	}[];
 	rtc_connection_id?: string; // uuid
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/TemplateCreateSchema.ts b/src/util/schemas/TemplateCreateSchema.ts
index 3f98f692..160934f5 100644
--- a/src/util/schemas/TemplateCreateSchema.ts
+++ b/src/util/schemas/TemplateCreateSchema.ts
@@ -1,4 +1,4 @@
 export interface TemplateCreateSchema {
 	name: string;
 	description?: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/TemplateModifySchema.ts b/src/util/schemas/TemplateModifySchema.ts
index 3e6efb74..f9c9d14b 100644
--- a/src/util/schemas/TemplateModifySchema.ts
+++ b/src/util/schemas/TemplateModifySchema.ts
@@ -1,4 +1,4 @@
 export interface TemplateModifySchema {
 	name: string;
 	description?: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/TotpDisableSchema.ts b/src/util/schemas/TotpDisableSchema.ts
index 05192bfa..51446e1c 100644
--- a/src/util/schemas/TotpDisableSchema.ts
+++ b/src/util/schemas/TotpDisableSchema.ts
@@ -1,3 +1,3 @@
 export interface TotpDisableSchema {
 	code: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/TotpEnableSchema.ts b/src/util/schemas/TotpEnableSchema.ts
index 7f6fb5a9..4e3551d9 100644
--- a/src/util/schemas/TotpEnableSchema.ts
+++ b/src/util/schemas/TotpEnableSchema.ts
@@ -2,4 +2,4 @@ export interface TotpEnableSchema {
 	password: string;
 	code?: string;
 	secret?: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/TotpSchema.ts b/src/util/schemas/TotpSchema.ts
index 889cb443..941a92ec 100644
--- a/src/util/schemas/TotpSchema.ts
+++ b/src/util/schemas/TotpSchema.ts
@@ -1,6 +1,6 @@
 export interface TotpSchema {
-	code: string,
-	ticket: string,
-	gift_code_sku_id?: string | null,
-	login_source?: string | null,
-}
\ No newline at end of file
+	code: string;
+	ticket: string;
+	gift_code_sku_id?: string | null;
+	login_source?: string | null;
+}
diff --git a/src/util/schemas/UserModifySchema.ts b/src/util/schemas/UserModifySchema.ts
index 34e0f135..5327e34b 100644
--- a/src/util/schemas/UserModifySchema.ts
+++ b/src/util/schemas/UserModifySchema.ts
@@ -16,4 +16,4 @@ export interface UserModifySchema {
 	code?: string;
 	email?: string;
 	discriminator?: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/Validator.ts b/src/util/schemas/Validator.ts
index b71bf6a1..e85cdf7b 100644
--- a/src/util/schemas/Validator.ts
+++ b/src/util/schemas/Validator.ts
@@ -3,7 +3,14 @@ import addFormats from "ajv-formats";
 import fs from "fs";
 import path from "path";
 
-const SchemaPath = path.join(__dirname, "..", "..", "..", "assets", "schemas.json");
+const SchemaPath = path.join(
+	__dirname,
+	"..",
+	"..",
+	"..",
+	"assets",
+	"schemas.json",
+);
 const schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" }));
 
 export const ajv = new Ajv({
@@ -14,7 +21,7 @@ export const ajv = new Ajv({
 	coerceTypes: true,
 	messages: true,
 	strict: true,
-	strictRequired: true
+	strictRequired: true,
 });
 
 addFormats(ajv);
@@ -41,7 +48,14 @@ export const normalizeBody = (body: any = {}) => {
 		} else {
 			for (const [key, value] of Object.entries(object)) {
 				if (value == null) {
-					if (key === "icon" || key === "avatar" || key === "banner" || key === "splash" || key === "discovery_splash") continue;
+					if (
+						key === "icon" ||
+						key === "avatar" ||
+						key === "banner" ||
+						key === "splash" ||
+						key === "discovery_splash"
+					)
+						continue;
 					delete object[key];
 				} else if (typeof value === "object") {
 					normalizeObject(value);
@@ -51,4 +65,4 @@ export const normalizeBody = (body: any = {}) => {
 	};
 	normalizeObject(body);
 	return body;
-};
\ No newline at end of file
+};
diff --git a/src/util/schemas/VanityUrlSchema.ts b/src/util/schemas/VanityUrlSchema.ts
index 28bf7f2b..4dd9b9da 100644
--- a/src/util/schemas/VanityUrlSchema.ts
+++ b/src/util/schemas/VanityUrlSchema.ts
@@ -4,4 +4,4 @@ export interface VanityUrlSchema {
 	 * @maxLength 20
 	 */
 	code?: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/VoiceIdentifySchema.ts b/src/util/schemas/VoiceIdentifySchema.ts
index d48de347..df023713 100644
--- a/src/util/schemas/VoiceIdentifySchema.ts
+++ b/src/util/schemas/VoiceIdentifySchema.ts
@@ -9,4 +9,4 @@ export interface VoiceIdentifySchema {
 		rid: string;
 		quality: number;
 	}[];
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/VoiceStateUpdateSchema.ts b/src/util/schemas/VoiceStateUpdateSchema.ts
index 5f805f4d..79e93b07 100644
--- a/src/util/schemas/VoiceStateUpdateSchema.ts
+++ b/src/util/schemas/VoiceStateUpdateSchema.ts
@@ -15,8 +15,8 @@ export const VoiceStateUpdateSchema = {
 	$channel_id: String,
 	self_mute: Boolean,
 	self_deaf: Boolean,
-	$self_video: Boolean,	//required in docs but bots don't always send it
+	$self_video: Boolean, //required in docs but bots don't always send it
 	$preferred_region: String,
 	$request_to_speak_timestamp: Date,
 	$suppress: Boolean,
-};
\ No newline at end of file
+};
diff --git a/src/util/schemas/VoiceVideoSchema.ts b/src/util/schemas/VoiceVideoSchema.ts
index 837ee1e7..0ba519e1 100644
--- a/src/util/schemas/VoiceVideoSchema.ts
+++ b/src/util/schemas/VoiceVideoSchema.ts
@@ -12,6 +12,6 @@ export interface VoiceVideoSchema {
 		rtx_ssrc: number;
 		max_bitrate: number;
 		max_framerate: number;
-		max_resolution: { type: string; width: number; height: number; };
+		max_resolution: { type: string; width: number; height: number };
 	}[];
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/WebhookCreateSchema.ts b/src/util/schemas/WebhookCreateSchema.ts
index c32b642d..99f6a12f 100644
--- a/src/util/schemas/WebhookCreateSchema.ts
+++ b/src/util/schemas/WebhookCreateSchema.ts
@@ -5,4 +5,4 @@ export interface WebhookCreateSchema {
 	 */
 	name: string;
 	avatar: string;
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/WidgetModifySchema.ts b/src/util/schemas/WidgetModifySchema.ts
index 3c84b3a1..26d4504f 100644
--- a/src/util/schemas/WidgetModifySchema.ts
+++ b/src/util/schemas/WidgetModifySchema.ts
@@ -1,4 +1,4 @@
 export interface WidgetModifySchema {
 	enabled: boolean; // whether the widget is enabled
 	channel_id: string; // the widget channel id
-}
\ No newline at end of file
+}
diff --git a/src/util/schemas/index.ts b/src/util/schemas/index.ts
index f86552f3..ae80de71 100644
--- a/src/util/schemas/index.ts
+++ b/src/util/schemas/index.ts
@@ -38,4 +38,4 @@ export * from "./VoiceStateUpdateSchema";
 export * from "./VoiceVideoSchema";
 export * from "./IdentifySchema";
 export * from "./ActivitySchema";
-export * from "./LazyRequestSchema";
\ No newline at end of file
+export * from "./LazyRequestSchema";
diff --git a/src/util/util/ApiError.ts b/src/util/util/ApiError.ts
index f1a9b4f6..0fce6882 100644
--- a/src/util/util/ApiError.ts
+++ b/src/util/util/ApiError.ts
@@ -3,23 +3,34 @@ export class ApiError extends Error {
 		readonly message: string,
 		public readonly code: number,
 		public readonly httpStatus: number = 400,
-		public readonly defaultParams?: string[]
+		public readonly defaultParams?: string[],
 	) {
 		super(message);
 	}
 
 	withDefaultParams(): ApiError {
 		if (this.defaultParams)
-			return new ApiError(applyParamsToString(this.message, this.defaultParams), this.code, this.httpStatus);
+			return new ApiError(
+				applyParamsToString(this.message, this.defaultParams),
+				this.code,
+				this.httpStatus,
+			);
 		return this;
 	}
 
 	withParams(...params: (string | number)[]): ApiError {
-		return new ApiError(applyParamsToString(this.message, params), this.code, this.httpStatus);
+		return new ApiError(
+			applyParamsToString(this.message, params),
+			this.code,
+			this.httpStatus,
+		);
 	}
 }
 
-export function applyParamsToString(s: string, params: (string | number)[]): string {
+export function applyParamsToString(
+	s: string,
+	params: (string | number)[],
+): string {
 	let newString = s;
 	params.forEach((a) => {
 		newString = newString.replace("{}", "" + a);
diff --git a/src/util/util/AutoUpdate.ts b/src/util/util/AutoUpdate.ts
index fd65ecf5..769d959f 100644
--- a/src/util/util/AutoUpdate.ts
+++ b/src/util/util/AutoUpdate.ts
@@ -1,6 +1,6 @@
 import "missing-native-js-functions";
 import fetch from "node-fetch";
-import ProxyAgent from 'proxy-agent';
+import ProxyAgent from "proxy-agent";
 import readline from "readline";
 import fs from "fs/promises";
 import path from "path";
@@ -19,14 +19,17 @@ export function enableAutoUpdate(opts: {
 }) {
 	if (!opts.checkInterval) return;
 	var interval = 1000 * 60 * 60 * 24;
-	if (typeof opts.checkInterval === "number") opts.checkInterval = 1000 * interval;
+	if (typeof opts.checkInterval === "number")
+		opts.checkInterval = 1000 * interval;
 
 	const i = setInterval(async () => {
 		const currentVersion = await getCurrentVersion(opts.path);
 		const latestVersion = await getLatestVersion(opts.packageJsonLink);
 		if (currentVersion !== latestVersion) {
 			clearInterval(i);
-			console.log(`[Auto Update] Current version (${currentVersion}) is out of date, updating ...`);
+			console.log(
+				`[Auto Update] Current version (${currentVersion}) is out of date, updating ...`,
+			);
 			await download(opts.downloadUrl, opts.path);
 		}
 	}, interval);
@@ -43,7 +46,7 @@ export function enableAutoUpdate(opts: {
 					} else {
 						console.log(`[Auto update] aborted`);
 					}
-				}
+				},
 			);
 		}
 	});
@@ -65,7 +68,9 @@ async function download(url: string, dir: string) {
 
 async function getCurrentVersion(dir: string) {
 	try {
-		const content = await fs.readFile(path.join(dir, "package.json"), { encoding: "utf8" });
+		const content = await fs.readFile(path.join(dir, "package.json"), {
+			encoding: "utf8",
+		});
 		return JSON.parse(content).version;
 	} catch (error) {
 		throw new Error("[Auto update] couldn't get current version in " + dir);
@@ -76,7 +81,7 @@ async function getLatestVersion(url: string) {
 	try {
 		const agent = new ProxyAgent();
 		const response = await fetch(url, { agent });
-		const content = await response.json() as any;	// TODO: types
+		const content = (await response.json()) as any; // TODO: types
 		return content.version;
 	} catch (error) {
 		throw new Error("[Auto update] check failed for " + url);
diff --git a/src/util/util/BannedWords.ts b/src/util/util/BannedWords.ts
index 891a5980..74a82efe 100644
--- a/src/util/util/BannedWords.ts
+++ b/src/util/util/BannedWords.ts
@@ -6,7 +6,9 @@ var words: string[];
 export const BannedWords = {
 	init: async function init() {
 		if (words) return words;
-		const file = (await fs.readFile(path.join(process.cwd(), "bannedWords"))).toString();
+		const file = (
+			await fs.readFile(path.join(process.cwd(), "bannedWords"))
+		).toString();
 		if (!file) {
 			words = [];
 			return [];
@@ -18,6 +20,6 @@ export const BannedWords = {
 	get: () => words,
 
 	find: (val: string) => {
-		return words.some(x => val.indexOf(x) != -1);
-	}
-};
\ No newline at end of file
+		return words.some((x) => val.indexOf(x) != -1);
+	},
+};
diff --git a/src/util/util/BitField.ts b/src/util/util/BitField.ts
index fb887e05..4e606660 100644
--- a/src/util/util/BitField.ts
+++ b/src/util/util/BitField.ts
@@ -3,7 +3,12 @@
 // https://github.com/discordjs/discord.js/blob/master/src/util/BitField.js
 // Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah
 
-export type BitFieldResolvable = number | BigInt | BitField | string | BitFieldResolvable[];
+export type BitFieldResolvable =
+	| number
+	| BigInt
+	| BitField
+	| string
+	| BitFieldResolvable[];
 
 /**
  * Data structure that makes it easy to interact with a bitfield.
@@ -91,7 +96,8 @@ export class BitField {
 	 */
 	serialize() {
 		const serialized: Record<string, boolean> = {};
-		for (const [flag, bit] of Object.entries(BitField.FLAGS)) serialized[flag] = this.has(bit);
+		for (const [flag, bit] of Object.entries(BitField.FLAGS))
+			serialized[flag] = this.has(bit);
 		return serialized;
 	}
 
@@ -130,14 +136,21 @@ export class BitField {
 	static resolve(bit: BitFieldResolvable = BigInt(0)): bigint {
 		// @ts-ignore
 		const FLAGS = this.FLAGS || this.constructor?.FLAGS;
-		if ((typeof bit === "number" || typeof bit === "bigint") && bit >= BigInt(0)) return BigInt(bit);
+		if (
+			(typeof bit === "number" || typeof bit === "bigint") &&
+			bit >= BigInt(0)
+		)
+			return BigInt(bit);
 		if (bit instanceof BitField) return bit.bitfield;
 		if (Array.isArray(bit)) {
 			// @ts-ignore
 			const resolve = this.constructor?.resolve || this.resolve;
-			return bit.map((p) => resolve.call(this, p)).reduce((prev, p) => BigInt(prev) | BigInt(p), BigInt(0));
+			return bit
+				.map((p) => resolve.call(this, p))
+				.reduce((prev, p) => BigInt(prev) | BigInt(p), BigInt(0));
 		}
-		if (typeof bit === "string" && typeof FLAGS[bit] !== "undefined") return FLAGS[bit];
+		if (typeof bit === "string" && typeof FLAGS[bit] !== "undefined")
+			return FLAGS[bit];
 		throw new RangeError("BITFIELD_INVALID: " + bit);
 	}
 }
diff --git a/src/util/util/Categories.ts b/src/util/util/Categories.ts
index a3c69da7..cd706a8a 100644
--- a/src/util/util/Categories.ts
+++ b/src/util/util/Categories.ts
@@ -1 +1 @@
-//TODO: populate default discord categories + init, get and set methods
\ No newline at end of file
+//TODO: populate default discord categories + init, get and set methods
diff --git a/src/util/util/Config.ts b/src/util/util/Config.ts
index 31b8d97c..7fab7f90 100644
--- a/src/util/util/Config.ts
+++ b/src/util/util/Config.ts
@@ -1,5 +1,9 @@
 import "missing-native-js-functions";
-import { ConfigValue, ConfigEntity, DefaultConfigOptions } from "../entities/Config";
+import {
+	ConfigValue,
+	ConfigEntity,
+	DefaultConfigOptions,
+} from "../entities/Config";
 import path from "path";
 import fs from "fs";
 
@@ -42,7 +46,11 @@ export const Config = {
 function applyConfig(val: ConfigValue) {
 	async function apply(obj: any, key = ""): Promise<any> {
 		if (typeof obj === "object" && obj !== null)
-			return Promise.all(Object.keys(obj).map((k) => apply(obj[k], key ? `${key}_${k}` : k)));
+			return Promise.all(
+				Object.keys(obj).map((k) =>
+					apply(obj[k], key ? `${key}_${k}` : k),
+				),
+			);
 
 		let pair = pairs.find((x) => x.key === key);
 		if (!pair) pair = new ConfigEntity();
@@ -67,7 +75,8 @@ function pairsToConfig(pairs: ConfigEntity[]) {
 		let i = 0;
 
 		for (const key of keys) {
-			if (!isNaN(Number(key)) && !prevObj[prev]?.length) prevObj[prev] = obj = [];
+			if (!isNaN(Number(key)) && !prevObj[prev]?.length)
+				prevObj[prev] = obj = [];
 			if (i++ === keys.length - 1) obj[key] = p.value;
 			else if (!obj[key]) obj[key] = {};
 
diff --git a/src/util/util/Constants.ts b/src/util/util/Constants.ts
index 81a7165d..7c5b7dcb 100644
--- a/src/util/util/Constants.ts
+++ b/src/util/util/Constants.ts
@@ -77,9 +77,9 @@ export const VoiceOPCodes = {
 	RESUME: 7,
 	HELLO: 8,
 	RESUMED: 9,
-	CLIENT_CONNECT: 12,		// incorrect, op 12 is probably used for video
-	CLIENT_DISCONNECT: 13,	// incorrect
-	VERSION: 16,	//not documented
+	CLIENT_CONNECT: 12, // incorrect, op 12 is probably used for video
+	CLIENT_DISCONNECT: 13, // incorrect
+	VERSION: 16, //not documented
 };
 
 export const Events = {
@@ -160,7 +160,13 @@ export const ShardEvents = {
  * sidebar for more information.</warn>
  * @typedef {string} PartialType
  */
-export const PartialTypes = keyMirror(["USER", "CHANNEL", "GUILD_MEMBER", "MESSAGE", "REACTION"]);
+export const PartialTypes = keyMirror([
+	"USER",
+	"CHANNEL",
+	"GUILD_MEMBER",
+	"MESSAGE",
+	"REACTION",
+]);
 
 /**
  * The type of a websocket message event, e.g. `MESSAGE_CREATE`. Here are the available events:
@@ -291,7 +297,7 @@ export const MessageTypes = [
  * @typedef {string} SystemMessageType
  */
 export const SystemMessageTypes = MessageTypes.filter(
-	(type: string | null) => type && type !== "DEFAULT" && type !== "REPLY"
+	(type: string | null) => type && type !== "DEFAULT" && type !== "REPLY",
 );
 
 /**
@@ -305,7 +311,14 @@ export const SystemMessageTypes = MessageTypes.filter(
  * * COMPETING
  * @typedef {string} ActivityType
  */
-export const ActivityTypes = ["PLAYING", "STREAMING", "LISTENING", "WATCHING", "CUSTOM_STATUS", "COMPETING"];
+export const ActivityTypes = [
+	"PLAYING",
+	"STREAMING",
+	"LISTENING",
+	"WATCHING",
+	"CUSTOM_STATUS",
+	"COMPETING",
+];
 
 export const ChannelTypes = {
 	TEXT: 0,
@@ -361,7 +374,11 @@ export const Colors = {
  * * ALL_MEMBERS
  * @typedef {string} ExplicitContentFilterLevel
  */
-export const ExplicitContentFilterLevels = ["DISABLED", "MEMBERS_WITHOUT_ROLES", "ALL_MEMBERS"];
+export const ExplicitContentFilterLevels = [
+	"DISABLED",
+	"MEMBERS_WITHOUT_ROLES",
+	"ALL_MEMBERS",
+];
 
 /**
  * The value set for the verification levels for a guild:
@@ -372,7 +389,13 @@ export const ExplicitContentFilterLevels = ["DISABLED", "MEMBERS_WITHOUT_ROLES",
  * * VERY_HIGH
  * @typedef {string} VerificationLevel
  */
-export const VerificationLevels = ["NONE", "LOW", "MEDIUM", "HIGH", "VERY_HIGH"];
+export const VerificationLevels = [
+	"NONE",
+	"LOW",
+	"MEDIUM",
+	"HIGH",
+	"VERY_HIGH",
+];
 
 /**
  * An error encountered while performing an API request. Here are the potential errors:
@@ -517,7 +540,10 @@ export const VerificationLevels = ["NONE", "LOW", "MEDIUM", "HIGH", "VERY_HIGH"]
  */
 export const DiscordApiErrors = {
 	//https://discord.com/developers/docs/topics/opcodes-and-status-codes#json-json-error-codes
-	GENERAL_ERROR: new ApiError("General error (such as a malformed request body, amongst other things)", 0),
+	GENERAL_ERROR: new ApiError(
+		"General error (such as a malformed request body, amongst other things)",
+		0,
+	),
 	UNKNOWN_ACCOUNT: new ApiError("Unknown account", 10001),
 	UNKNOWN_APPLICATION: new ApiError("Unknown application", 10002),
 	UNKNOWN_CHANNEL: new ApiError("Unknown channel", 10003),
@@ -542,185 +568,410 @@ export const DiscordApiErrors = {
 	UNKNOWN_BUILD: new ApiError("Unknown build", 10030),
 	UNKNOWN_LOBBY: new ApiError("Unknown lobby", 10031),
 	UNKNOWN_BRANCH: new ApiError("Unknown branch", 10032),
-	UNKNOWN_STORE_DIRECTORY_LAYOUT: new ApiError("Unknown store directory layout", 10033),
+	UNKNOWN_STORE_DIRECTORY_LAYOUT: new ApiError(
+		"Unknown store directory layout",
+		10033,
+	),
 	UNKNOWN_REDISTRIBUTABLE: new ApiError("Unknown redistributable", 10036),
 	UNKNOWN_GIFT_CODE: new ApiError("Unknown gift code", 10038),
 	UNKNOWN_STREAM: new ApiError("Unknown stream", 10049),
-	UNKNOWN_PREMIUM_SERVER_SUBSCRIBE_COOLDOWN: new ApiError("Unknown premium server subscribe cooldown", 10050),
+	UNKNOWN_PREMIUM_SERVER_SUBSCRIBE_COOLDOWN: new ApiError(
+		"Unknown premium server subscribe cooldown",
+		10050,
+	),
 	UNKNOWN_GUILD_TEMPLATE: new ApiError("Unknown guild template", 10057),
-	UNKNOWN_DISCOVERABLE_SERVER_CATEGORY: new ApiError("Unknown discoverable server category", 10059),
+	UNKNOWN_DISCOVERABLE_SERVER_CATEGORY: new ApiError(
+		"Unknown discoverable server category",
+		10059,
+	),
 	UNKNOWN_STICKER: new ApiError("Unknown sticker", 10060),
 	UNKNOWN_INTERACTION: new ApiError("Unknown interaction", 10062),
-	UNKNOWN_APPLICATION_COMMAND: new ApiError("Unknown application command", 10063),
-	UNKNOWN_APPLICATION_COMMAND_PERMISSIONS: new ApiError("Unknown application command permissions", 10066),
+	UNKNOWN_APPLICATION_COMMAND: new ApiError(
+		"Unknown application command",
+		10063,
+	),
+	UNKNOWN_APPLICATION_COMMAND_PERMISSIONS: new ApiError(
+		"Unknown application command permissions",
+		10066,
+	),
 	UNKNOWN_STAGE_INSTANCE: new ApiError("Unknown Stage Instance", 10067),
-	UNKNOWN_GUILD_MEMBER_VERIFICATION_FORM: new ApiError("Unknown Guild Member Verification Form", 10068),
-	UNKNOWN_GUILD_WELCOME_SCREEN: new ApiError("Unknown Guild Welcome Screen", 10069),
-	UNKNOWN_GUILD_SCHEDULED_EVENT: new ApiError("Unknown Guild Scheduled Event", 10070),
-	UNKNOWN_GUILD_SCHEDULED_EVENT_USER: new ApiError("Unknown Guild Scheduled Event User", 10071),
-	BOT_PROHIBITED_ENDPOINT: new ApiError("Bots cannot use this endpoint", 20001),
+	UNKNOWN_GUILD_MEMBER_VERIFICATION_FORM: new ApiError(
+		"Unknown Guild Member Verification Form",
+		10068,
+	),
+	UNKNOWN_GUILD_WELCOME_SCREEN: new ApiError(
+		"Unknown Guild Welcome Screen",
+		10069,
+	),
+	UNKNOWN_GUILD_SCHEDULED_EVENT: new ApiError(
+		"Unknown Guild Scheduled Event",
+		10070,
+	),
+	UNKNOWN_GUILD_SCHEDULED_EVENT_USER: new ApiError(
+		"Unknown Guild Scheduled Event User",
+		10071,
+	),
+	BOT_PROHIBITED_ENDPOINT: new ApiError(
+		"Bots cannot use this endpoint",
+		20001,
+	),
 	BOT_ONLY_ENDPOINT: new ApiError("Only bots can use this endpoint", 20002),
 	EXPLICIT_CONTENT_CANNOT_BE_SENT_TO_RECIPIENT: new ApiError(
 		"Explicit content cannot be sent to the desired recipient(s)",
-		20009
+		20009,
 	),
 	ACTION_NOT_AUTHORIZED_ON_APPLICATION: new ApiError(
 		"You are not authorized to perform this action on this application",
-		20012
+		20012,
+	),
+	SLOWMODE_RATE_LIMIT: new ApiError(
+		"This action cannot be performed due to slowmode rate limit",
+		20016,
+	),
+	ONLY_OWNER: new ApiError(
+		"Only the owner of this account can perform this action",
+		20018,
+	),
+	ANNOUNCEMENT_RATE_LIMITS: new ApiError(
+		"This message cannot be edited due to announcement rate limits",
+		20022,
+	),
+	CHANNEL_WRITE_RATELIMIT: new ApiError(
+		"The channel you are writing has hit the write rate limit",
+		20028,
 	),
-	SLOWMODE_RATE_LIMIT: new ApiError("This action cannot be performed due to slowmode rate limit", 20016),
-	ONLY_OWNER: new ApiError("Only the owner of this account can perform this action", 20018),
-	ANNOUNCEMENT_RATE_LIMITS: new ApiError("This message cannot be edited due to announcement rate limits", 20022),
-	CHANNEL_WRITE_RATELIMIT: new ApiError("The channel you are writing has hit the write rate limit", 20028),
 	WORDS_NOT_ALLOWED: new ApiError(
 		"Your Stage topic, server name, server description, or channel names contain words that are not allowed",
-		20031
-	),
-	GUILD_PREMIUM_LEVEL_TOO_LOW: new ApiError("Guild premium subscription level too low", 20035),
-	MAXIMUM_GUILDS: new ApiError("Maximum number of guilds reached ({})", 30001, undefined, ["100"]),
-	MAXIMUM_FRIENDS: new ApiError("Maximum number of friends reached ({})", 30002, undefined, ["1000"]),
-	MAXIMUM_PINS: new ApiError("Maximum number of pins reached for the channel ({})", 30003, undefined, ["50"]),
-	MAXIMUM_NUMBER_OF_RECIPIENTS_REACHED: new ApiError("Maximum number of recipients reached ({})", 30004, undefined, [
-		"10",
-	]),
-	MAXIMUM_ROLES: new ApiError("Maximum number of guild roles reached ({})", 30005, undefined, ["250"]),
-	MAXIMUM_WEBHOOKS: new ApiError("Maximum number of webhooks reached ({})", 30007, undefined, ["10"]),
-	MAXIMUM_NUMBER_OF_EMOJIS_REACHED: new ApiError("Maximum number of emojis reached", 30008),
-	MAXIMUM_REACTIONS: new ApiError("Maximum number of reactions reached ({})", 30010, undefined, ["20"]),
-	MAXIMUM_CHANNELS: new ApiError("Maximum number of guild channels reached ({})", 30013, undefined, ["500"]),
-	MAXIMUM_ATTACHMENTS: new ApiError("Maximum number of attachments in a message reached ({})", 30015, undefined, [
-		"10",
-	]),
-	MAXIMUM_INVITES: new ApiError("Maximum number of invites reached ({})", 30016, undefined, ["1000"]),
-	MAXIMUM_ANIMATED_EMOJIS: new ApiError("Maximum number of animated emojis reached", 30018),
-	MAXIMUM_SERVER_MEMBERS: new ApiError("Maximum number of server members reached", 30019),
+		20031,
+	),
+	GUILD_PREMIUM_LEVEL_TOO_LOW: new ApiError(
+		"Guild premium subscription level too low",
+		20035,
+	),
+	MAXIMUM_GUILDS: new ApiError(
+		"Maximum number of guilds reached ({})",
+		30001,
+		undefined,
+		["100"],
+	),
+	MAXIMUM_FRIENDS: new ApiError(
+		"Maximum number of friends reached ({})",
+		30002,
+		undefined,
+		["1000"],
+	),
+	MAXIMUM_PINS: new ApiError(
+		"Maximum number of pins reached for the channel ({})",
+		30003,
+		undefined,
+		["50"],
+	),
+	MAXIMUM_NUMBER_OF_RECIPIENTS_REACHED: new ApiError(
+		"Maximum number of recipients reached ({})",
+		30004,
+		undefined,
+		["10"],
+	),
+	MAXIMUM_ROLES: new ApiError(
+		"Maximum number of guild roles reached ({})",
+		30005,
+		undefined,
+		["250"],
+	),
+	MAXIMUM_WEBHOOKS: new ApiError(
+		"Maximum number of webhooks reached ({})",
+		30007,
+		undefined,
+		["10"],
+	),
+	MAXIMUM_NUMBER_OF_EMOJIS_REACHED: new ApiError(
+		"Maximum number of emojis reached",
+		30008,
+	),
+	MAXIMUM_REACTIONS: new ApiError(
+		"Maximum number of reactions reached ({})",
+		30010,
+		undefined,
+		["20"],
+	),
+	MAXIMUM_CHANNELS: new ApiError(
+		"Maximum number of guild channels reached ({})",
+		30013,
+		undefined,
+		["500"],
+	),
+	MAXIMUM_ATTACHMENTS: new ApiError(
+		"Maximum number of attachments in a message reached ({})",
+		30015,
+		undefined,
+		["10"],
+	),
+	MAXIMUM_INVITES: new ApiError(
+		"Maximum number of invites reached ({})",
+		30016,
+		undefined,
+		["1000"],
+	),
+	MAXIMUM_ANIMATED_EMOJIS: new ApiError(
+		"Maximum number of animated emojis reached",
+		30018,
+	),
+	MAXIMUM_SERVER_MEMBERS: new ApiError(
+		"Maximum number of server members reached",
+		30019,
+	),
 	MAXIMUM_SERVER_CATEGORIES: new ApiError(
 		"Maximum number of server categories has been reached ({})",
 		30030,
 		undefined,
-		["5"]
+		["5"],
+	),
+	GUILD_ALREADY_HAS_TEMPLATE: new ApiError(
+		"Guild already has a template",
+		30031,
+	),
+	MAXIMUM_THREAD_PARTICIPANTS: new ApiError(
+		"Max number of thread participants has been reached",
+		30033,
 	),
-	GUILD_ALREADY_HAS_TEMPLATE: new ApiError("Guild already has a template", 30031),
-	MAXIMUM_THREAD_PARTICIPANTS: new ApiError("Max number of thread participants has been reached", 30033),
 	MAXIMUM_BANS_FOR_NON_GUILD_MEMBERS: new ApiError(
 		"Maximum number of bans for non-guild members have been exceeded",
-		30035
+		30035,
+	),
+	MAXIMUM_BANS_FETCHES: new ApiError(
+		"Maximum number of bans fetches has been reached",
+		30037,
 	),
-	MAXIMUM_BANS_FETCHES: new ApiError("Maximum number of bans fetches has been reached", 30037),
 	MAXIMUM_STICKERS: new ApiError("Maximum number of stickers reached", 30039),
-	MAXIMUM_PRUNE_REQUESTS: new ApiError("Maximum number of prune requests has been reached. Try again later", 30040),
-	UNAUTHORIZED: new ApiError("Unauthorized. Provide a valid token and try again", 40001),
+	MAXIMUM_PRUNE_REQUESTS: new ApiError(
+		"Maximum number of prune requests has been reached. Try again later",
+		30040,
+	),
+	UNAUTHORIZED: new ApiError(
+		"Unauthorized. Provide a valid token and try again",
+		40001,
+	),
 	ACCOUNT_VERIFICATION_REQUIRED: new ApiError(
 		"You need to verify your account in order to perform this action",
-		40002
+		40002,
+	),
+	OPENING_DIRECT_MESSAGES_TOO_FAST: new ApiError(
+		"You are opening direct messages too fast",
+		40003,
+	),
+	REQUEST_ENTITY_TOO_LARGE: new ApiError(
+		"Request entity too large. Try sending something smaller in size",
+		40005,
+	),
+	FEATURE_TEMPORARILY_DISABLED: new ApiError(
+		"This feature has been temporarily disabled server-side",
+		40006,
 	),
-	OPENING_DIRECT_MESSAGES_TOO_FAST: new ApiError("You are opening direct messages too fast", 40003),
-	REQUEST_ENTITY_TOO_LARGE: new ApiError("Request entity too large. Try sending something smaller in size", 40005),
-	FEATURE_TEMPORARILY_DISABLED: new ApiError("This feature has been temporarily disabled server-side", 40006),
 	USER_BANNED: new ApiError("The user is banned from this guild", 40007),
-	TARGET_USER_IS_NOT_CONNECTED_TO_VOICE: new ApiError("Target user is not connected to voice", 40032),
-	ALREADY_CROSSPOSTED: new ApiError("This message has already been crossposted", 40033),
-	APPLICATION_COMMAND_ALREADY_EXISTS: new ApiError("An application command with that name already exists", 40041),
+	TARGET_USER_IS_NOT_CONNECTED_TO_VOICE: new ApiError(
+		"Target user is not connected to voice",
+		40032,
+	),
+	ALREADY_CROSSPOSTED: new ApiError(
+		"This message has already been crossposted",
+		40033,
+	),
+	APPLICATION_COMMAND_ALREADY_EXISTS: new ApiError(
+		"An application command with that name already exists",
+		40041,
+	),
 	MISSING_ACCESS: new ApiError("Missing access", 50001),
 	INVALID_ACCOUNT_TYPE: new ApiError("Invalid account type", 50002),
-	CANNOT_EXECUTE_ON_DM: new ApiError("Cannot execute action on a DM channel", 50003),
+	CANNOT_EXECUTE_ON_DM: new ApiError(
+		"Cannot execute action on a DM channel",
+		50003,
+	),
 	EMBED_DISABLED: new ApiError("Guild widget disabled", 50004),
-	CANNOT_EDIT_MESSAGE_BY_OTHER: new ApiError("Cannot edit a message authored by another user", 50005),
-	CANNOT_SEND_EMPTY_MESSAGE: new ApiError("Cannot send an empty message", 50006),
-	CANNOT_MESSAGE_USER: new ApiError("Cannot send messages to this user", 50007),
-	CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL: new ApiError("Cannot send messages in a voice channel", 50008),
+	CANNOT_EDIT_MESSAGE_BY_OTHER: new ApiError(
+		"Cannot edit a message authored by another user",
+		50005,
+	),
+	CANNOT_SEND_EMPTY_MESSAGE: new ApiError(
+		"Cannot send an empty message",
+		50006,
+	),
+	CANNOT_MESSAGE_USER: new ApiError(
+		"Cannot send messages to this user",
+		50007,
+	),
+	CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL: new ApiError(
+		"Cannot send messages in a voice channel",
+		50008,
+	),
 	CHANNEL_VERIFICATION_LEVEL_TOO_HIGH: new ApiError(
 		"Channel verification level is too high for you to gain access",
-		50009
+		50009,
+	),
+	OAUTH2_APPLICATION_BOT_ABSENT: new ApiError(
+		"OAuth2 application does not have a bot",
+		50010,
+	),
+	MAXIMUM_OAUTH2_APPLICATIONS: new ApiError(
+		"OAuth2 application limit reached",
+		50011,
 	),
-	OAUTH2_APPLICATION_BOT_ABSENT: new ApiError("OAuth2 application does not have a bot", 50010),
-	MAXIMUM_OAUTH2_APPLICATIONS: new ApiError("OAuth2 application limit reached", 50011),
 	INVALID_OAUTH_STATE: new ApiError("Invalid OAuth2 state", 50012),
-	MISSING_PERMISSIONS: new ApiError("You lack permissions to perform that action ({})", 50013, undefined, [""]),
-	INVALID_AUTHENTICATION_TOKEN: new ApiError("Invalid authentication token provided", 50014),
+	MISSING_PERMISSIONS: new ApiError(
+		"You lack permissions to perform that action ({})",
+		50013,
+		undefined,
+		[""],
+	),
+	INVALID_AUTHENTICATION_TOKEN: new ApiError(
+		"Invalid authentication token provided",
+		50014,
+	),
 	NOTE_TOO_LONG: new ApiError("Note was too long", 50015),
 	INVALID_BULK_DELETE_QUANTITY: new ApiError(
 		"Provided too few or too many messages to delete. Must provide at least {} and fewer than {} messages to delete",
 		50016,
 		undefined,
-		["2", "100"]
+		["2", "100"],
 	),
 	CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL: new ApiError(
 		"A message can only be pinned to the channel it was sent in",
-		50019
-	),
-	INVALID_OR_TAKEN_INVITE_CODE: new ApiError("Invite code was either invalid or taken", 50020),
-	CANNOT_EXECUTE_ON_SYSTEM_MESSAGE: new ApiError("Cannot execute action on a system message", 50021),
-	CANNOT_EXECUTE_ON_THIS_CHANNEL_TYPE: new ApiError("Cannot execute action on this channel type", 50024),
-	INVALID_OAUTH_TOKEN: new ApiError("Invalid OAuth2 access token provided", 50025),
-	MISSING_REQUIRED_OAUTH2_SCOPE: new ApiError("Missing required OAuth2 scope", 50026),
-	INVALID_WEBHOOK_TOKEN_PROVIDED: new ApiError("Invalid webhook token provided", 50027),
+		50019,
+	),
+	INVALID_OR_TAKEN_INVITE_CODE: new ApiError(
+		"Invite code was either invalid or taken",
+		50020,
+	),
+	CANNOT_EXECUTE_ON_SYSTEM_MESSAGE: new ApiError(
+		"Cannot execute action on a system message",
+		50021,
+	),
+	CANNOT_EXECUTE_ON_THIS_CHANNEL_TYPE: new ApiError(
+		"Cannot execute action on this channel type",
+		50024,
+	),
+	INVALID_OAUTH_TOKEN: new ApiError(
+		"Invalid OAuth2 access token provided",
+		50025,
+	),
+	MISSING_REQUIRED_OAUTH2_SCOPE: new ApiError(
+		"Missing required OAuth2 scope",
+		50026,
+	),
+	INVALID_WEBHOOK_TOKEN_PROVIDED: new ApiError(
+		"Invalid webhook token provided",
+		50027,
+	),
 	INVALID_ROLE: new ApiError("Invalid role", 50028),
 	INVALID_RECIPIENT: new ApiError("Invalid Recipient(s)", 50033),
-	BULK_DELETE_MESSAGE_TOO_OLD: new ApiError("A message provided was too old to bulk delete", 50034),
+	BULK_DELETE_MESSAGE_TOO_OLD: new ApiError(
+		"A message provided was too old to bulk delete",
+		50034,
+	),
 	INVALID_FORM_BODY: new ApiError(
 		"Invalid form body (returned for both application/json and multipart/form-data bodies), or invalid Content-Type provided",
-		50035
+		50035,
 	),
 	INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT: new ApiError(
 		"An invite was accepted to a guild the application's bot is not in",
-		50036
+		50036,
 	),
 	INVALID_API_VERSION: new ApiError("Invalid API version provided", 50041),
-	FILE_EXCEEDS_MAXIMUM_SIZE: new ApiError("File uploaded exceeds the maximum size", 50045),
+	FILE_EXCEEDS_MAXIMUM_SIZE: new ApiError(
+		"File uploaded exceeds the maximum size",
+		50045,
+	),
 	INVALID_FILE_UPLOADED: new ApiError("Invalid file uploaded", 50046),
-	CANNOT_SELF_REDEEM_GIFT: new ApiError("Cannot self-redeem this gift", 50054),
-	PAYMENT_SOURCE_REQUIRED: new ApiError("Payment source required to redeem gift", 50070),
+	CANNOT_SELF_REDEEM_GIFT: new ApiError(
+		"Cannot self-redeem this gift",
+		50054,
+	),
+	PAYMENT_SOURCE_REQUIRED: new ApiError(
+		"Payment source required to redeem gift",
+		50070,
+	),
 	CANNOT_DELETE_COMMUNITY_REQUIRED_CHANNEL: new ApiError(
 		"Cannot delete a channel required for Community guilds",
-		50074
+		50074,
 	),
 	INVALID_STICKER_SENT: new ApiError("Invalid sticker sent", 50081),
 	CANNOT_EDIT_ARCHIVED_THREAD: new ApiError(
 		"Tried to perform an operation on an archived thread, such as editing a message or adding a user to the thread",
-		50083
+		50083,
+	),
+	INVALID_THREAD_NOTIFICATION_SETTINGS: new ApiError(
+		"Invalid thread notification settings",
+		50084,
 	),
-	INVALID_THREAD_NOTIFICATION_SETTINGS: new ApiError("Invalid thread notification settings", 50084),
 	BEFORE_EARLIER_THAN_THREAD_CREATION_DATE: new ApiError(
 		"before value is earlier than the thread creation date",
-		50085
+		50085,
+	),
+	SERVER_NOT_AVAILABLE_IN_YOUR_LOCATION: new ApiError(
+		"This server is not available in your location",
+		50095,
 	),
-	SERVER_NOT_AVAILABLE_IN_YOUR_LOCATION: new ApiError("This server is not available in your location", 50095),
 	SERVER_NEEDS_MONETIZATION_ENABLED: new ApiError(
 		"This server needs monetization enabled in order to perform this action",
-		50097
+		50097,
+	),
+	TWO_FACTOR_REQUIRED: new ApiError(
+		"Two factor is required for this operation",
+		60003,
+	),
+	NO_USERS_WITH_DISCORDTAG_EXIST: new ApiError(
+		"No users with DiscordTag exist",
+		80004,
 	),
-	TWO_FACTOR_REQUIRED: new ApiError("Two factor is required for this operation", 60003),
-	NO_USERS_WITH_DISCORDTAG_EXIST: new ApiError("No users with DiscordTag exist", 80004),
 	REACTION_BLOCKED: new ApiError("Reaction was blocked", 90001),
-	RESOURCE_OVERLOADED: new ApiError("API resource is currently overloaded. Try again a little later", 130000),
+	RESOURCE_OVERLOADED: new ApiError(
+		"API resource is currently overloaded. Try again a little later",
+		130000,
+	),
 	STAGE_ALREADY_OPEN: new ApiError("The Stage is already open", 150006),
-	THREAD_ALREADY_CREATED_FOR_THIS_MESSAGE: new ApiError("A thread has already been created for this message", 160004),
+	THREAD_ALREADY_CREATED_FOR_THIS_MESSAGE: new ApiError(
+		"A thread has already been created for this message",
+		160004,
+	),
 	THREAD_IS_LOCKED: new ApiError("Thread is locked", 160005),
-	MAXIMUM_NUMBER_OF_ACTIVE_THREADS: new ApiError("Maximum number of active threads reached", 160006),
+	MAXIMUM_NUMBER_OF_ACTIVE_THREADS: new ApiError(
+		"Maximum number of active threads reached",
+		160006,
+	),
 	MAXIMUM_NUMBER_OF_ACTIVE_ANNOUNCEMENT_THREADS: new ApiError(
 		"Maximum number of active announcement threads reached",
-		160007
+		160007,
+	),
+	INVALID_JSON_FOR_UPLOADED_LOTTIE_FILE: new ApiError(
+		"Invalid JSON for uploaded Lottie file",
+		170001,
 	),
-	INVALID_JSON_FOR_UPLOADED_LOTTIE_FILE: new ApiError("Invalid JSON for uploaded Lottie file", 170001),
 	LOTTIES_CANNOT_CONTAIN_RASTERIZED_IMAGES: new ApiError(
 		"Uploaded Lotties cannot contain rasterized images such as PNG or JPEG",
-		170002
+		170002,
+	),
+	STICKER_MAXIMUM_FRAMERATE: new ApiError(
+		"Sticker maximum framerate exceeded",
+		170003,
+	),
+	STICKER_MAXIMUM_FRAME_COUNT: new ApiError(
+		"Sticker frame count exceeds maximum of {} frames",
+		170004,
+		undefined,
+		["1000"],
+	),
+	LOTTIE_ANIMATION_MAXIMUM_DIMENSIONS: new ApiError(
+		"Lottie animation maximum dimensions exceeded",
+		170005,
 	),
-	STICKER_MAXIMUM_FRAMERATE: new ApiError("Sticker maximum framerate exceeded", 170003),
-	STICKER_MAXIMUM_FRAME_COUNT: new ApiError("Sticker frame count exceeds maximum of {} frames", 170004, undefined, [
-		"1000",
-	]),
-	LOTTIE_ANIMATION_MAXIMUM_DIMENSIONS: new ApiError("Lottie animation maximum dimensions exceeded", 170005),
 	STICKER_FRAME_RATE_TOO_SMALL_OR_TOO_LARGE: new ApiError(
 		"Sticker frame rate is either too small or too large",
-		170006
+		170006,
 	),
 	STICKER_ANIMATION_DURATION_MAXIMUM: new ApiError(
 		"Sticker animation duration exceeds maximum of {} seconds",
 		170007,
 		undefined,
-		["5"]
+		["5"],
 	),
 
 	//Other errors
@@ -731,26 +982,92 @@ export const DiscordApiErrors = {
  * An error encountered while performing an API request (Fosscord only). Here are the potential errors:
  */
 export const FosscordApiErrors = {
-	MANUALLY_TRIGGERED_ERROR: new ApiError("This is an artificial error", 1, 500),
-	PREMIUM_DISABLED_FOR_GUILD: new ApiError("This guild cannot be boosted", 25001),
-	NO_FURTHER_PREMIUM: new ApiError("This guild does not receive further boosts", 25002),
-	GUILD_PREMIUM_DISABLED_FOR_YOU: new ApiError("This guild cannot be boosted by you", 25003, 403),
+	MANUALLY_TRIGGERED_ERROR: new ApiError(
+		"This is an artificial error",
+		1,
+		500,
+	),
+	PREMIUM_DISABLED_FOR_GUILD: new ApiError(
+		"This guild cannot be boosted",
+		25001,
+	),
+	NO_FURTHER_PREMIUM: new ApiError(
+		"This guild does not receive further boosts",
+		25002,
+	),
+	GUILD_PREMIUM_DISABLED_FOR_YOU: new ApiError(
+		"This guild cannot be boosted by you",
+		25003,
+		403,
+	),
 	CANNOT_FRIEND_SELF: new ApiError("Cannot friend oneself", 25009),
-	USER_SPECIFIC_INVITE_WRONG_RECIPIENT: new ApiError("This invite is not meant for you", 25010),
+	USER_SPECIFIC_INVITE_WRONG_RECIPIENT: new ApiError(
+		"This invite is not meant for you",
+		25010,
+	),
 	USER_SPECIFIC_INVITE_FAILED: new ApiError("Failed to invite user", 25011),
-	CANNOT_MODIFY_USER_GROUP: new ApiError("This user cannot manipulate this group", 25050, 403),
-	CANNOT_REMOVE_SELF_FROM_GROUP: new ApiError("This user cannot remove oneself from user group", 25051),
-	CANNOT_BAN_OPERATOR: new ApiError("Non-OPERATOR cannot ban OPERATOR from instance", 25052),
-	CANNOT_LEAVE_GUILD: new ApiError("You are not allowed to leave guilds that you joined by yourself", 25059, 403),
-	EDITS_DISABLED: new ApiError("You are not allowed to edit your own messages", 25060, 403),
-	DELETE_MESSAGE_DISABLED: new ApiError("You are not allowed to delete your own messages", 25061, 403),
-	FEATURE_PERMANENTLY_DISABLED: new ApiError("This feature has been disabled server-side", 45006, 501),
-	MISSING_RIGHTS: new ApiError("You lack rights to perform that action ({})", 50013, undefined, [""]),
-	CANNOT_REPLACE_BY_BACKFILL: new ApiError("Cannot backfill to message ID that already exists", 55002, 409),
-	CANNOT_BACKFILL_TO_THE_FUTURE: new ApiError("You cannot backfill messages in the future", 55003),
-	CANNOT_GRANT_PERMISSIONS_EXCEEDING_RIGHTS: new ApiError("You cannot grant permissions exceeding your own rights", 50050),
-	ROUTES_LOOPING: new ApiError("Loops in the route definition ({})", 50060, undefined, [""]),
-	CANNOT_REMOVE_ROUTE: new ApiError("Cannot remove message route while it is in effect and being used", 50061),
+	CANNOT_MODIFY_USER_GROUP: new ApiError(
+		"This user cannot manipulate this group",
+		25050,
+		403,
+	),
+	CANNOT_REMOVE_SELF_FROM_GROUP: new ApiError(
+		"This user cannot remove oneself from user group",
+		25051,
+	),
+	CANNOT_BAN_OPERATOR: new ApiError(
+		"Non-OPERATOR cannot ban OPERATOR from instance",
+		25052,
+	),
+	CANNOT_LEAVE_GUILD: new ApiError(
+		"You are not allowed to leave guilds that you joined by yourself",
+		25059,
+		403,
+	),
+	EDITS_DISABLED: new ApiError(
+		"You are not allowed to edit your own messages",
+		25060,
+		403,
+	),
+	DELETE_MESSAGE_DISABLED: new ApiError(
+		"You are not allowed to delete your own messages",
+		25061,
+		403,
+	),
+	FEATURE_PERMANENTLY_DISABLED: new ApiError(
+		"This feature has been disabled server-side",
+		45006,
+		501,
+	),
+	MISSING_RIGHTS: new ApiError(
+		"You lack rights to perform that action ({})",
+		50013,
+		undefined,
+		[""],
+	),
+	CANNOT_REPLACE_BY_BACKFILL: new ApiError(
+		"Cannot backfill to message ID that already exists",
+		55002,
+		409,
+	),
+	CANNOT_BACKFILL_TO_THE_FUTURE: new ApiError(
+		"You cannot backfill messages in the future",
+		55003,
+	),
+	CANNOT_GRANT_PERMISSIONS_EXCEEDING_RIGHTS: new ApiError(
+		"You cannot grant permissions exceeding your own rights",
+		50050,
+	),
+	ROUTES_LOOPING: new ApiError(
+		"Loops in the route definition ({})",
+		50060,
+		undefined,
+		[""],
+	),
+	CANNOT_REMOVE_ROUTE: new ApiError(
+		"Cannot remove message route while it is in effect and being used",
+		50061,
+	),
 };
 
 /**
@@ -769,11 +1086,7 @@ export const DefaultMessageNotifications = ["ALL", "MENTIONS", "MUTED"];
  * * INSERTED (Fosscord extension)
  * @typedef {string} MembershipStates
  */
-export const MembershipStates = [
-	"INSERTED",
-	"INVITED",
-	"ACCEPTED",
-];
+export const MembershipStates = ["INSERTED", "INVITED", "ACCEPTED"];
 
 /**
  * The value set for a webhook's type:
@@ -782,15 +1095,10 @@ export const MembershipStates = [
  * * Custom (Fosscord extension)
  * @typedef {string} WebhookTypes
  */
-export const WebhookTypes = [
-	"Custom",
-	"Incoming",
-	"Channel Follower",
-];
+export const WebhookTypes = ["Custom", "Incoming", "Channel Follower"];
 
 function keyMirror(arr: string[]) {
 	let tmp = Object.create(null);
 	for (const value of arr) tmp[value] = value;
 	return tmp;
 }
-
diff --git a/src/util/util/Database.ts b/src/util/util/Database.ts
index ddbea57d..e96be6c4 100644
--- a/src/util/util/Database.ts
+++ b/src/util/util/Database.ts
@@ -9,7 +9,8 @@ import { yellow, green, red } from "picocolors";
 // We want to generate all id's with Snowflakes that's why we have our own BaseEntity class
 
 var dbConnection: DataSource | undefined;
-let dbConnectionString = process.env.DATABASE || path.join(process.cwd(), "database.db");
+let dbConnectionString =
+	process.env.DATABASE || path.join(process.cwd(), "database.db");
 
 export function getDatabase(): DataSource | null {
 	// if (!dbConnection) throw new Error("Tried to get database before it was initialised");
@@ -20,18 +21,24 @@ export function getDatabase(): DataSource | null {
 export async function initDatabase(): Promise<DataSource> {
 	if (dbConnection) return dbConnection;
 
-	const type = dbConnectionString.includes("://") ? dbConnectionString.split(":")[0]?.replace("+srv", "") : "sqlite";
+	const type = dbConnectionString.includes("://")
+		? dbConnectionString.split(":")[0]?.replace("+srv", "")
+		: "sqlite";
 	const isSqlite = type.includes("sqlite");
 
 	console.log(`[Database] ${yellow(`connecting to ${type} db`)}`);
 	if (isSqlite) {
-		console.log(`[Database] ${red(`You are running sqlite! Please keep in mind that we recommend setting up a dedicated database!`)}`);
+		console.log(
+			`[Database] ${red(
+				`You are running sqlite! Please keep in mind that we recommend setting up a dedicated database!`,
+			)}`,
+		);
 	}
 
 	const dataSource = new DataSource({
 		//@ts-ignore
 		type,
-		charset: 'utf8mb4',
+		charset: "utf8mb4",
 		url: isSqlite ? undefined : dbConnectionString,
 		database: isSqlite ? dbConnectionString : undefined,
 		entities: ["dist/util/entities/*.js"],
diff --git a/src/util/util/Email.ts b/src/util/util/Email.ts
index 6885da33..c98ccff0 100644
--- a/src/util/util/Email.ts
+++ b/src/util/util/Email.ts
@@ -15,7 +15,7 @@ export function adjustEmail(email?: string): string | undefined {
 		// replace .dots and +alternatives -> Gmail Dot Trick https://support.google.com/mail/answer/7436150 and https://generator.email/blog/gmail-generator
 		let v = user.replace(/[.]|(\+.*)/g, "") + "@gmail.com";
 	}
-	
+
 	if (domain === "google.com") {
 		// replace .dots and +alternatives -> Google Staff GMail Dot Trick
 		let v = user.replace(/[.]|(\+.*)/g, "") + "@google.com";
diff --git a/src/util/util/Event.ts b/src/util/util/Event.ts
index 20a638a0..c81de951 100644
--- a/src/util/util/Event.ts
+++ b/src/util/util/Event.ts
@@ -5,15 +5,27 @@ import { EVENT, Event } from "../interfaces";
 export const events = new EventEmitter();
 
 export async function emitEvent(payload: Omit<Event, "created_at">) {
-	const id = (payload.channel_id || payload.user_id || payload.guild_id) as string;
+	const id = (payload.channel_id ||
+		payload.user_id ||
+		payload.guild_id) as string;
 	if (!id) return console.error("event doesn't contain any id", payload);
 
 	if (RabbitMQ.connection) {
-		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 });
+		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 });
+		const successful = RabbitMQ.channel?.publish(
+			id,
+			"",
+			Buffer.from(`${data}`),
+			{ type: payload.event },
+		);
 		if (!successful) throw new Error("failed to send event");
 	} else if (process.env.EVENT_TRANSMISSION === "process") {
 		process.send?.({ type: "event", event: payload, id } as ProcessEvent);
@@ -48,10 +60,19 @@ export interface ProcessEvent {
 	id: string;
 }
 
-export async function listenEvent(event: string, callback: (event: EventOpts) => any, opts?: ListenEventOpts) {
+export async function listenEvent(
+	event: string,
+	callback: (event: EventOpts) => any,
+	opts?: ListenEventOpts,
+) {
 	if (RabbitMQ.connection) {
-		// @ts-ignore
-		return rabbitListen(opts?.channel || RabbitMQ.channel, event, callback, { acknowledge: opts?.acknowledge });
+		return rabbitListen(
+			// @ts-ignore
+			opts?.channel || RabbitMQ.channel,
+			event,
+			callback,
+			{ acknowledge: opts?.acknowledge },
+		);
 	} else if (process.env.EVENT_TRANSMISSION === "process") {
 		const cancel = () => {
 			process.removeListener("message", listener);
@@ -59,7 +80,9 @@ export async function listenEvent(event: string, callback: (event: EventOpts) =>
 		};
 
 		const listener = (msg: ProcessEvent) => {
-			msg.type === "event" && msg.id === event && callback({ ...msg.event, cancel });
+			msg.type === "event" &&
+				msg.id === event &&
+				callback({ ...msg.event, cancel });
 		};
 
 		//@ts-ignore apparently theres no function addListener with this signature
@@ -84,10 +107,13 @@ async function rabbitListen(
 	channel: Channel,
 	id: string,
 	callback: (event: EventOpts) => any,
-	opts?: { acknowledge?: boolean }
+	opts?: { acknowledge?: boolean },
 ) {
 	await channel.assertExchange(id, "fanout", { durable: false });
-	const q = await channel.assertQueue("", { exclusive: true, autoDelete: true });
+	const q = await channel.assertQueue("", {
+		exclusive: true,
+		autoDelete: true,
+	});
 
 	const cancel = () => {
 		channel.cancel(q.queue);
@@ -116,7 +142,7 @@ async function rabbitListen(
 		},
 		{
 			noAck: !opts?.acknowledge,
-		}
+		},
 	);
 
 	return cancel;
diff --git a/src/util/util/FieldError.ts b/src/util/util/FieldError.ts
index 406b33e8..24818fed 100644
--- a/src/util/util/FieldError.ts
+++ b/src/util/util/FieldError.ts
@@ -1,6 +1,8 @@
 import "missing-native-js-functions";
 
-export function FieldErrors(fields: Record<string, { code?: string; message: string }>) {
+export function FieldErrors(
+	fields: Record<string, { code?: string; message: string }>,
+) {
 	return new FieldError(
 		50035,
 		"Invalid Form Body",
@@ -11,7 +13,7 @@ export function FieldErrors(fields: Record<string, { code?: string; message: str
 					code: code || "BASE_TYPE_INVALID",
 				},
 			],
-		}))
+		})),
 	);
 }
 
@@ -19,7 +21,11 @@ export function FieldErrors(fields: Record<string, { code?: string; message: str
 // Ensure you use the proper content type (image/jpeg, image/png, image/gif) that matches the image data being provided.
 
 export class FieldError extends Error {
-	constructor(public code: string | number, public message: string, public errors?: any) {
+	constructor(
+		public code: string | number,
+		public message: string,
+		public errors?: any,
+	) {
 		super(message);
 	}
 }
diff --git a/src/util/util/Intents.ts b/src/util/util/Intents.ts
index 1e840b76..b9f4d65a 100644
--- a/src/util/util/Intents.ts
+++ b/src/util/util/Intents.ts
@@ -22,13 +22,12 @@ export class Intents extends BitField {
 		GUILD_POLICY_EXECUTION: BigInt(1) << BigInt(21), // guild policy execution
 		LIVE_MESSAGE_COMPOSITION: BigInt(1) << BigInt(32), // allow composing messages using the gateway
 		GUILD_ROUTES: BigInt(1) << BigInt(41), // message routes affecting the guild
-		DIRECT_MESSAGES_THREADS: BigInt(1) << BigInt(42),  // direct message threads
+		DIRECT_MESSAGES_THREADS: BigInt(1) << BigInt(42), // direct message threads
 		JUMBO_EVENTS: BigInt(1) << BigInt(43), // jumbo events (size limits to be defined later)
 		LOBBIES: BigInt(1) << BigInt(44), // lobbies
-		INSTANCE_ROUTES: BigInt(1) << BigInt(60), // all message route changes 
+		INSTANCE_ROUTES: BigInt(1) << BigInt(60), // all message route changes
 		INSTANCE_GUILD_CHANGES: BigInt(1) << BigInt(61), // all guild create, guild object patch, split, merge and delete events
 		INSTANCE_POLICY_UPDATES: BigInt(1) << BigInt(62), // all instance policy updates
-		INSTANCE_USER_UPDATES: BigInt(1) << BigInt(63) // all instance user updates
+		INSTANCE_USER_UPDATES: BigInt(1) << BigInt(63), // all instance user updates
 	};
 }
-
diff --git a/src/util/util/InvisibleCharacters.ts b/src/util/util/InvisibleCharacters.ts
index a48cfab0..da295d68 100644
--- a/src/util/util/InvisibleCharacters.ts
+++ b/src/util/util/InvisibleCharacters.ts
@@ -1,56 +1,56 @@
-// List from https://invisible-characters.com/

-export const InvisibleCharacters = [

-	'\u{9}',			//Tab

-	//'\u{20}',			//Space	//categories can have spaces in them

-	'\u{ad}',			//Soft hyphen

-	'\u{34f}',			//Combining grapheme joiner

-	'\u{61c}',			//Arabic letter mark

-	'\u{115f}',			//Hangul choseong filler

-	'\u{1160}',			//Hangul jungseong filler

-	'\u{17b4}',			//Khmer vowel inherent AQ

-	'\u{17b5}',			//Khmer vowel inherent AA

-	'\u{180e}',			//Mongolian vowel separator

-	'\u{2000}',			//En quad

-	'\u{2001}',			//Em quad

-	'\u{2002}',			//En space

-	'\u{2003}',			//Em space

-	'\u{2004}',			//Three-per-em space

-	'\u{2005}',			//Four-per-em space

-	'\u{2006}',			//Six-per-em space

-	'\u{2007}',			//Figure space

-	'\u{2008}',			//Punctuation space

-	'\u{2009}',			//Thin space

-	'\u{200a}',			//Hair space

-	'\u{200b}',			//Zero width space

-	'\u{200c}',			//Zero width non-joiner

-	'\u{200d}',			//Zero width joiner

-	'\u{200e}',			//Left-to-right mark

-	'\u{200f}',			//Right-to-left mark

-	'\u{202f}',			//Narrow no-break space

-	'\u{205f}',			//Medium mathematical space

-	'\u{2060}',			//Word joiner

-	'\u{2061}',			//Function application

-	'\u{2062}',			//Invisible times

-	'\u{2063}',			//Invisible separator

-	'\u{2064}',			//Invisible plus

-	'\u{206a}',			//Inhibit symmetric swapping

-	'\u{206b}',			//Activate symmetric swapping

-	'\u{206c}',			//Inhibit arabic form shaping

-	'\u{206d}',			//Activate arabic form shaping

-	'\u{206e}',			//National digit shapes

-	'\u{206f}',			//Nominal digit shapes

-	'\u{3000}',			//Ideographic space

-	'\u{2800}',			//Braille pattern blank

-	'\u{3164}',			//Hangul filler

-	'\u{feff}',			//Zero width no-break space

-	'\u{ffa0}',			//Haldwidth hangul filler

-	'\u{1d159}',		//Musical symbol null notehead

-	'\u{1d173}',		//Musical symbol begin beam 

-	'\u{1d174}',		//Musical symbol end beam

-	'\u{1d175}',		//Musical symbol begin tie

-	'\u{1d176}',		//Musical symbol end tie

-	'\u{1d177}',		//Musical symbol begin slur

-	'\u{1d178}',		//Musical symbol end slur

-	'\u{1d179}',		//Musical symbol begin phrase

-	'\u{1d17a}'			//Musical symbol end phrase

-]; 
\ No newline at end of file
+// List from https://invisible-characters.com/
+export const InvisibleCharacters = [
+	"\u{9}", //Tab
+	//'\u{20}',			//Space	//categories can have spaces in them
+	"\u{ad}", //Soft hyphen
+	"\u{34f}", //Combining grapheme joiner
+	"\u{61c}", //Arabic letter mark
+	"\u{115f}", //Hangul choseong filler
+	"\u{1160}", //Hangul jungseong filler
+	"\u{17b4}", //Khmer vowel inherent AQ
+	"\u{17b5}", //Khmer vowel inherent AA
+	"\u{180e}", //Mongolian vowel separator
+	"\u{2000}", //En quad
+	"\u{2001}", //Em quad
+	"\u{2002}", //En space
+	"\u{2003}", //Em space
+	"\u{2004}", //Three-per-em space
+	"\u{2005}", //Four-per-em space
+	"\u{2006}", //Six-per-em space
+	"\u{2007}", //Figure space
+	"\u{2008}", //Punctuation space
+	"\u{2009}", //Thin space
+	"\u{200a}", //Hair space
+	"\u{200b}", //Zero width space
+	"\u{200c}", //Zero width non-joiner
+	"\u{200d}", //Zero width joiner
+	"\u{200e}", //Left-to-right mark
+	"\u{200f}", //Right-to-left mark
+	"\u{202f}", //Narrow no-break space
+	"\u{205f}", //Medium mathematical space
+	"\u{2060}", //Word joiner
+	"\u{2061}", //Function application
+	"\u{2062}", //Invisible times
+	"\u{2063}", //Invisible separator
+	"\u{2064}", //Invisible plus
+	"\u{206a}", //Inhibit symmetric swapping
+	"\u{206b}", //Activate symmetric swapping
+	"\u{206c}", //Inhibit arabic form shaping
+	"\u{206d}", //Activate arabic form shaping
+	"\u{206e}", //National digit shapes
+	"\u{206f}", //Nominal digit shapes
+	"\u{3000}", //Ideographic space
+	"\u{2800}", //Braille pattern blank
+	"\u{3164}", //Hangul filler
+	"\u{feff}", //Zero width no-break space
+	"\u{ffa0}", //Haldwidth hangul filler
+	"\u{1d159}", //Musical symbol null notehead
+	"\u{1d173}", //Musical symbol begin beam
+	"\u{1d174}", //Musical symbol end beam
+	"\u{1d175}", //Musical symbol begin tie
+	"\u{1d176}", //Musical symbol end tie
+	"\u{1d177}", //Musical symbol begin slur
+	"\u{1d178}", //Musical symbol end slur
+	"\u{1d179}", //Musical symbol begin phrase
+	"\u{1d17a}", //Musical symbol end phrase
+];
diff --git a/src/util/util/Permissions.ts b/src/util/util/Permissions.ts
index a432af76..0c12487e 100644
--- a/src/util/util/Permissions.ts
+++ b/src/util/util/Permissions.ts
@@ -1,6 +1,12 @@
 // https://github.com/discordjs/discord.js/blob/master/src/util/Permissions.js
 // Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah
-import { Channel, ChannelPermissionOverwrite, Guild, Member, Role } from "../entities";
+import {
+	Channel,
+	ChannelPermissionOverwrite,
+	Guild,
+	Member,
+	Role,
+} from "../entities";
 import { BitField } from "./BitField";
 import "missing-native-js-functions";
 import { BitFieldResolvable, BitFlag } from "./BitField";
@@ -13,7 +19,12 @@ try {
 	HTTPError = Error;
 }
 
-export type PermissionResolvable = bigint | number | Permissions | PermissionResolvable[] | PermissionString;
+export type PermissionResolvable =
+	| bigint
+	| number
+	| Permissions
+	| PermissionResolvable[]
+	| PermissionString;
 
 type PermissionString = keyof typeof Permissions.FLAGS;
 
@@ -80,14 +91,20 @@ export class Permissions extends BitField {
 	};
 
 	any(permission: PermissionResolvable, checkAdmin = true) {
-		return (checkAdmin && super.any(Permissions.FLAGS.ADMINISTRATOR)) || super.any(permission);
+		return (
+			(checkAdmin && super.any(Permissions.FLAGS.ADMINISTRATOR)) ||
+			super.any(permission)
+		);
 	}
 
 	/**
 	 * Checks whether the bitfield has a permission, or multiple permissions.
 	 */
 	has(permission: PermissionResolvable, checkAdmin = true) {
-		return (checkAdmin && super.has(Permissions.FLAGS.ADMINISTRATOR)) || super.has(permission);
+		return (
+			(checkAdmin && super.has(Permissions.FLAGS.ADMINISTRATOR)) ||
+			super.has(permission)
+		);
 	}
 
 	/**
@@ -96,28 +113,39 @@ export class Permissions extends BitField {
 	hasThrow(permission: PermissionResolvable) {
 		if (this.has(permission) && this.has("VIEW_CHANNEL")) return true;
 		// @ts-ignore
-		throw new HTTPError(`You are missing the following permissions ${permission}`, 403);
+		throw new HTTPError(
+			`You are missing the following permissions ${permission}`,
+			403,
+		);
 	}
 
 	overwriteChannel(overwrites: ChannelPermissionOverwrite[]) {
 		if (!overwrites) return this;
 		if (!this.cache) throw new Error("permission chache not available");
 		overwrites = overwrites.filter((x) => {
-			if (x.type === 0 && this.cache.roles?.some((r) => r.id === x.id)) return true;
+			if (x.type === 0 && this.cache.roles?.some((r) => r.id === x.id))
+				return true;
 			if (x.type === 1 && x.id == this.cache.user_id) return true;
 			return false;
 		});
-		return new Permissions(Permissions.channelPermission(overwrites, this.bitfield));
+		return new Permissions(
+			Permissions.channelPermission(overwrites, this.bitfield),
+		);
 	}
 
-	static channelPermission(overwrites: ChannelPermissionOverwrite[], init?: bigint) {
+	static channelPermission(
+		overwrites: ChannelPermissionOverwrite[],
+		init?: bigint,
+	) {
 		// TODO: do not deny any permissions if admin
 		return overwrites.reduce((permission, overwrite) => {
 			// apply disallowed permission
 			// * permission: current calculated permission (e.g. 010)
 			// * deny contains all denied permissions (e.g. 011)
 			// * allow contains all explicitly allowed permisions (e.g. 100)
-			return (permission & ~BigInt(overwrite.deny)) | BigInt(overwrite.allow);
+			return (
+				(permission & ~BigInt(overwrite.deny)) | BigInt(overwrite.allow)
+			);
 			// ~ operator inverts deny (e.g. 011 -> 100)
 			// & operator only allows 1 for both ~deny and permission (e.g. 010 & 100 -> 000)
 			// | operators adds both together (e.g. 000 + 100 -> 100)
@@ -126,7 +154,10 @@ export class Permissions extends BitField {
 
 	static rolePermission(roles: Role[]) {
 		// adds all permissions of all roles together (Bit OR)
-		return roles.reduce((permission, role) => permission | BigInt(role.permissions), BigInt(0));
+		return roles.reduce(
+			(permission, role) => permission | BigInt(role.permissions),
+			BigInt(0),
+		);
 	}
 
 	static finalPermission({
@@ -157,7 +188,8 @@ export class Permissions extends BitField {
 		}
 
 		if (channel?.recipient_ids) {
-			if (channel?.owner_id === user.id) return new Permissions("ADMINISTRATOR");
+			if (channel?.owner_id === user.id)
+				return new Permissions("ADMINISTRATOR");
 			if (channel.recipient_ids.includes(user.id)) {
 				// Default dm permissions
 				return new Permissions([
@@ -183,7 +215,10 @@ export class Permissions extends BitField {
 	}
 }
 
-const ALL_PERMISSIONS = Object.values(Permissions.FLAGS).reduce((total, val) => total | val, BigInt(0));
+const ALL_PERMISSIONS = Object.values(Permissions.FLAGS).reduce(
+	(total, val) => total | val,
+	BigInt(0),
+);
 
 export type PermissionCache = {
 	channel?: Channel | undefined;
@@ -204,7 +239,7 @@ export async function getPermission(
 		channel_relations?: string[];
 		member_select?: (keyof Member)[];
 		member_relations?: string[];
-	} = {}
+	} = {},
 ) {
 	if (!user_id) throw new HTTPError("User not found");
 	var channel: Channel | undefined;
@@ -239,16 +274,17 @@ export async function getPermission(
 			],
 			relations: opts.guild_relations,
 		});
-		if (guild.owner_id === user_id) return new Permissions(Permissions.FLAGS.ADMINISTRATOR);
+		if (guild.owner_id === user_id)
+			return new Permissions(Permissions.FLAGS.ADMINISTRATOR);
 
 		member = await Member.findOneOrFail({
 			where: { guild_id, id: user_id },
 			relations: ["roles", ...(opts.member_relations || [])],
 			// select: [
-				// "id",		// TODO: Bug in typeorm? adding these selects breaks the query.
-				// "roles",
-				// @ts-ignore
-				// ...(opts.member_select || []),
+			// "id",		// TODO: Bug in typeorm? adding these selects breaks the query.
+			// "roles",
+			// @ts-ignore
+			// ...(opts.member_select || []),
 			// ],
 		});
 	}
diff --git a/src/util/util/RabbitMQ.ts b/src/util/util/RabbitMQ.ts
index 0f5eb6aa..1bfb3f5c 100644
--- a/src/util/util/RabbitMQ.ts
+++ b/src/util/util/RabbitMQ.ts
@@ -1,7 +1,11 @@
 import amqp, { Connection, Channel } from "amqplib";
 // import Config from "./Config";
 
-export const RabbitMQ: { connection: Connection | null; channel: Channel | null; init: () => Promise<void> } = {
+export const RabbitMQ: {
+	connection: Connection | null;
+	channel: Channel | null;
+	init: () => Promise<void>;
+} = {
 	connection: null,
 	channel: null,
 	init: async function () {
diff --git a/src/util/util/Rights.ts b/src/util/util/Rights.ts
index b28c75b7..659353a6 100644
--- a/src/util/util/Rights.ts
+++ b/src/util/util/Rights.ts
@@ -11,7 +11,12 @@ try {
 	HTTPError = Error;
 }
 
-export type RightResolvable = bigint | number | Rights | RightResolvable[] | RightString;
+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
@@ -60,7 +65,7 @@ export class Rights extends BitField {
 		CREDITABLE: BitFlag(32), // can receive money from monetisation related features
 		KICK_BAN_MEMBERS: BitFlag(33),
 		// can kick or ban guild or group DM members in the guilds/groups that they have KICK_MEMBERS, or BAN_MEMBERS
-		SELF_LEAVE_GROUPS: BitFlag(34), 
+		SELF_LEAVE_GROUPS: BitFlag(34),
 		// can leave the guilds or group DMs that they joined on their own (one can always leave a guild or group DMs they have been force-added)
 		PRESENCE: BitFlag(35),
 		// inverts the presence confidentiality default (OPERATOR's presence is not routed by default, others' are) for a given user
@@ -72,31 +77,44 @@ export class Rights extends BitField {
 		RESPOND_TO_INTERACTIONS: BitFlag(41), // can respond to interactions
 		SEND_BACKDATED_EVENTS: BitFlag(42), // can send backdated events
 		USE_MASS_INVITES: BitFlag(43), // added per @xnacly's request — can accept mass invites
-		ACCEPT_INVITES: BitFlag(44) // added per @xnacly's request — can accept user-specific invites and DM requests
+		ACCEPT_INVITES: BitFlag(44), // added per @xnacly's request — can accept user-specific invites and DM requests
 	};
 
 	any(permission: RightResolvable, checkOperator = true) {
-		return (checkOperator && super.any(Rights.FLAGS.OPERATOR)) || super.any(permission);
+		return (
+			(checkOperator && super.any(Rights.FLAGS.OPERATOR)) ||
+			super.any(permission)
+		);
 	}
 
 	has(permission: RightResolvable, checkOperator = true) {
-		return (checkOperator && super.has(Rights.FLAGS.OPERATOR)) || super.has(permission);
+		return (
+			(checkOperator && super.has(Rights.FLAGS.OPERATOR)) ||
+			super.has(permission)
+		);
 	}
 
 	hasThrow(permission: RightResolvable) {
 		if (this.has(permission)) return true;
 		// @ts-ignore
-		throw new HTTPError(`You are missing the following rights ${permission}`, 403);
+		throw new HTTPError(
+			`You are missing the following rights ${permission}`,
+			403,
+		);
 	}
-	
 }
 
-const ALL_RIGHTS = Object.values(Rights.FLAGS).reduce((total, val) => total | val, BigInt(0));
+const ALL_RIGHTS = Object.values(Rights.FLAGS).reduce(
+	(total, val) => total | val,
+	BigInt(0),
+);
 
-export async function getRights(	user_id: string
+export async function getRights(
+	user_id: string,
 	/**, opts: {
 		in_behalf?: (keyof User)[];
-	} = {} **/) {
+	} = {} **/
+) {
 	let user = await User.findOneOrFail({ where: { id: user_id } });
 	return new Rights(user.rights);
-} 
+}
diff --git a/src/util/util/Snowflake.ts b/src/util/util/Snowflake.ts
index 134d526e..69effb2e 100644
--- a/src/util/util/Snowflake.ts
+++ b/src/util/util/Snowflake.ts
@@ -17,7 +17,9 @@ export class Snowflake {
 	static workerId = BigInt((cluster.worker?.id || 0) % 31); // max 31
 
 	constructor() {
-		throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
+		throw new Error(
+			`The ${this.constructor.name} class may not be instantiated.`,
+		);
 	}
 
 	/**
@@ -83,14 +85,15 @@ export class Snowflake {
 		return dec;
 	}
 
-	static generateWorkerProcess() { // worker process - returns a number
+	static generateWorkerProcess() {
+		// worker process - returns a number
 		var time = BigInt(Date.now() - Snowflake.EPOCH) << BigInt(22);
 		var worker = Snowflake.workerId << 17n;
 		var process = Snowflake.processId << 12n;
 		var increment = Snowflake.INCREMENT++;
 		return BigInt(time | worker | process | increment);
 	}
-	
+
 	static generate() {
 		return Snowflake.generateWorkerProcess().toString();
 	}
@@ -111,7 +114,9 @@ export class Snowflake {
 	 * @returns {DeconstructedSnowflake} Deconstructed snowflake
 	 */
 	static deconstruct(snowflake) {
-		const BINARY = Snowflake.idToBinary(snowflake).toString(2).padStart(64, "0");
+		const BINARY = Snowflake.idToBinary(snowflake)
+			.toString(2)
+			.padStart(64, "0");
 		const res = {
 			timestamp: parseInt(BINARY.substring(0, 42), 2) + Snowflake.EPOCH,
 			workerID: parseInt(BINARY.substring(42, 47), 2),
diff --git a/src/util/util/Token.ts b/src/util/util/Token.ts
index 5ba3e1ec..19e64f47 100644
--- a/src/util/util/Token.ts
+++ b/src/util/util/Token.ts
@@ -17,11 +17,14 @@ export function checkToken(token: string, jwtSecret: string): Promise<any> {
 
 			const user = await User.findOne({
 				where: { id: decoded.id },
-				select: ["data", "bot", "disabled", "deleted", "rights"]
+				select: ["data", "bot", "disabled", "deleted", "rights"],
 			});
 			if (!user) return rej("Invalid Token");
 			// we need to round it to seconds as it saved as seconds in jwt iat and valid_tokens_since is stored in milliseconds
-			if (decoded.iat * 1000 < new Date(user.data.valid_tokens_since).setSeconds(0, 0))
+			if (
+				decoded.iat * 1000 <
+				new Date(user.data.valid_tokens_since).setSeconds(0, 0)
+			)
 				return rej("Invalid Token");
 			if (user.disabled) return rej("User disabled");
 			if (user.deleted) return rej("User not found");
@@ -45,7 +48,7 @@ export async function generateToken(id: string) {
 			(err, token) => {
 				if (err) return rej(err);
 				return res(token);
-			}
+			},
 		);
 	});
 }
diff --git a/src/util/util/TraverseDirectory.ts b/src/util/util/TraverseDirectory.ts
index 3d0d6279..3f5b0385 100644
--- a/src/util/util/TraverseDirectory.ts
+++ b/src/util/util/TraverseDirectory.ts
@@ -1,13 +1,14 @@
 import { Server, traverseDirectory } from "lambert-server";
 
 //if we're using ts-node, use ts files instead of js
-const extension = Symbol.for("ts-node.register.instance") in process ? "ts" : "js"
+const extension =
+	Symbol.for("ts-node.register.instance") in process ? "ts" : "js";
 
-const DEFAULT_FILTER = new RegExp("^([^\.].*)(?<!\.d)\.(" + extension + ")$");
+const DEFAULT_FILTER = new RegExp("^([^.].*)(?<!.d).(" + extension + ")$");
 
 export function registerRoutes(server: Server, root: string) {
 	return traverseDirectory(
 		{ dirname: root, recursive: true, filter: DEFAULT_FILTER },
-		server.registerRoute.bind(server, root)
+		server.registerRoute.bind(server, root),
 	);
 }
diff --git a/src/util/util/cdn.ts b/src/util/util/cdn.ts
index 812a4e1d..6b2c8424 100644
--- a/src/util/util/cdn.ts
+++ b/src/util/util/cdn.ts
@@ -4,7 +4,10 @@ import fetch from "node-fetch";
 import { Attachment } from "../entities";
 import { Config } from "./Config";
 
-export async function uploadFile(path: string, file?: Express.Multer.File): Promise<Attachment> {
+export async function uploadFile(
+	path: string,
+	file?: Express.Multer.File,
+): Promise<Attachment> {
 	if (!file?.buffer) throw new HTTPError("Missing file in body");
 
 	const form = new FormData();
@@ -13,28 +16,38 @@ export async function uploadFile(path: string, file?: Express.Multer.File): Prom
 		filename: file.originalname,
 	});
 
-	const response = await fetch(`${Config.get().cdn.endpointPrivate || "http://localhost:3003"}${path}`, {
-		headers: {
-			signature: Config.get().security.requestSignature,
-			...form.getHeaders(),
+	const response = await fetch(
+		`${Config.get().cdn.endpointPrivate || "http://localhost:3003"}${path}`,
+		{
+			headers: {
+				signature: Config.get().security.requestSignature,
+				...form.getHeaders(),
+			},
+			method: "POST",
+			body: form,
 		},
-		method: "POST",
-		body: form,
-	});
-	const result = await response.json() as Attachment;
+	);
+	const result = (await response.json()) as Attachment;
 
 	if (response.status !== 200) throw result;
 	return result;
 }
 
-export async function handleFile(path: string, body?: string): Promise<string | undefined> {
+export async function handleFile(
+	path: string,
+	body?: string,
+): Promise<string | undefined> {
 	if (!body || !body.startsWith("data:")) return undefined;
 	try {
 		const mimetype = body.split(":")[1].split(";")[0];
 		const buffer = Buffer.from(body.split(",")[1], "base64");
 
 		// @ts-ignore
-		const { id } = await uploadFile(path, { buffer, mimetype, originalname: "banner" });
+		const { id } = await uploadFile(path, {
+			buffer,
+			mimetype,
+			originalname: "banner",
+		});
 		return id;
 	} catch (error) {
 		console.error(error);
@@ -43,12 +56,15 @@ export async function handleFile(path: string, body?: string): Promise<string |
 }
 
 export async function deleteFile(path: string) {
-	const response = await fetch(`${Config.get().cdn.endpointPrivate || "http://localhost:3003"}${path}`, {
-		headers: {
-			signature: Config.get().security.requestSignature,
+	const response = await fetch(
+		`${Config.get().cdn.endpointPrivate || "http://localhost:3003"}${path}`,
+		{
+			headers: {
+				signature: Config.get().security.requestSignature,
+			},
+			method: "DELETE",
 		},
-		method: "DELETE",
-	});
+	);
 	const result = await response.json();
 
 	if (response.status !== 200) throw result;
diff --git a/src/util/util/index.ts b/src/util/util/index.ts
index b2bd6489..aa38e472 100644
--- a/src/util/util/index.ts
+++ b/src/util/util/index.ts
@@ -20,4 +20,4 @@ export * from "./String";
 export * from "./Array";
 export * from "./TraverseDirectory";
 export * from "./InvisibleCharacters";
-export * from "./BannedWords";
\ No newline at end of file
+export * from "./BannedWords";