summary refs log tree commit diff
path: root/src/util/entities
diff options
context:
space:
mode:
authorMadeline <46743919+MaddyUnderStars@users.noreply.github.com>2022-08-25 00:44:13 +1000
committerMadeline <46743919+MaddyUnderStars@users.noreply.github.com>2022-08-25 00:44:13 +1000
commit314a4787ce55a091cb89ef4281d7ba09e8323fa4 (patch)
treed77142c009e9c6d45390a8fe01c9aee966d7a4cc /src/util/entities
parentMerge remote-tracking branch 'upstream/staging' into feat/captchaVerify (diff)
parentcase insensitive header for rate limits, fix rate limit default settings (diff)
downloadserver-314a4787ce55a091cb89ef4281d7ba09e8323fa4.tar.xz
Merge remote-tracking branch 'upstream/staging' into feat/captchaVerify
Diffstat (limited to 'src/util/entities')
-rw-r--r--src/util/entities/Application.ts58
-rw-r--r--src/util/entities/Attachment.ts2
-rw-r--r--src/util/entities/AuditLog.ts18
-rw-r--r--src/util/entities/BackupCodes.ts4
-rw-r--r--src/util/entities/Ban.ts4
-rw-r--r--src/util/entities/Categories.ts24
-rw-r--r--src/util/entities/Channel.ts774
-rw-r--r--src/util/entities/ClientRelease.ts2
-rw-r--r--src/util/entities/Config.ts2
-rw-r--r--src/util/entities/ConnectedAccount.ts2
-rw-r--r--src/util/entities/Emoji.ts5
-rw-r--r--src/util/entities/Encryption.ts40
-rw-r--r--src/util/entities/Group.ts8
-rw-r--r--src/util/entities/Guild.ts47
-rw-r--r--src/util/entities/Invite.ts12
-rw-r--r--src/util/entities/Member.ts116
-rw-r--r--src/util/entities/Message.ts41
-rw-r--r--src/util/entities/Migration.ts4
-rw-r--r--src/util/entities/Note.ts2
-rw-r--r--src/util/entities/ReadState.ts9
-rw-r--r--src/util/entities/Recipient.ts4
-rw-r--r--src/util/entities/Relationship.ts8
-rw-r--r--src/util/entities/Role.ts2
-rw-r--r--src/util/entities/Session.ts16
-rw-r--r--src/util/entities/Sticker.ts12
-rw-r--r--src/util/entities/StickerPack.ts4
-rw-r--r--src/util/entities/Team.ts4
-rw-r--r--src/util/entities/TeamMember.ts6
-rw-r--r--src/util/entities/User.ts39
-rw-r--r--src/util/entities/UserGroup.ts14
-rw-r--r--src/util/entities/UserSettings.ts208
-rw-r--r--src/util/entities/VoiceState.ts8
-rw-r--r--src/util/entities/Webhook.ts12
-rw-r--r--src/util/entities/index.ts8
34 files changed, 716 insertions, 803 deletions
diff --git a/src/util/entities/Application.ts b/src/util/entities/Application.ts
index 103f8e84..35fc496d 100644
--- a/src/util/entities/Application.ts
+++ b/src/util/entities/Application.ts
@@ -1,6 +1,5 @@
-import { Column, Entity, JoinColumn, ManyToOne, OneToOne, RelationId } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, OneToOne } from "typeorm";
 import { BaseClass } from "./BaseClass";
-import { Guild } from "./Guild";
 import { Team } from "./Team";
 import { User } from "./User";
 
@@ -8,77 +7,77 @@ import { User } from "./User";
 export class Application extends BaseClass {
 	@Column()
 	name: string;
-	
+
 	@Column({ nullable: true })
 	icon?: string;
-	
+
 	@Column({ nullable: true })
 	description: string;
-	
+
 	@Column({ nullable: true })
 	summary: string = "";
-	
+
 	@Column({ type: "simple-json", nullable: true })
 	type?: any;
-	
+
 	@Column()
 	hook: boolean = true;
-	
+
 	@Column()
 	bot_public?: boolean = true;
-	
+
 	@Column()
 	bot_require_code_grant?: boolean = false;
-	
+
 	@Column()
 	verify_key: string;
-	
+
 	@JoinColumn({ name: "owner_id" })
 	@ManyToOne(() => User)
 	owner: User;
-	
+
 	@Column()
 	flags: number = 0;
-	
+
 	@Column({ type: "simple-array", nullable: true })
 	redirect_uris: string[] = [];
-	
+
 	@Column({ nullable: true })
 	rpc_application_state: number = 0;
-	
+
 	@Column({ nullable: true })
 	store_application_state: number = 1;
-	
+
 	@Column({ nullable: true })
 	verification_state: number = 1;
-	
+
 	@Column({ nullable: true })
 	interactions_endpoint_url?: string;
-	
+
 	@Column({ nullable: true })
 	integration_public: boolean = true;
-	
+
 	@Column({ nullable: true })
 	integration_require_code_grant: boolean = false;
-	
+
 	@Column({ nullable: true })
 	discoverability_state: number = 1;
-	
+
 	@Column({ nullable: true })
 	discovery_eligibility_flags: number = 2240;
-	
+
 	@JoinColumn({ name: "bot_user_id" })
 	@OneToOne(() => User)
 	bot?: User;
-	
+
 	@Column({ type: "simple-array", nullable: true })
 	tags?: string[];
-	
+
 	@Column({ nullable: true })
 	cover_image?: string; // the application's default rich presence invite cover image hash
-	
+
 	@Column({ type: "simple-json", nullable: true })
-	install_params?: {scopes: string[], permissions: string};
+	install_params?: { scopes: string[]; permissions: string };
 
 	@Column({ nullable: true })
 	terms_of_service_url?: string;
@@ -90,7 +89,7 @@ export class Application extends BaseClass {
 
 	//@Column({ type: "simple-array", nullable: true })
 	//rpc_origins?: string[];
-	
+
 	//@JoinColumn({ name: "guild_id" })
 	//@ManyToOne(() => Guild)
 	//guild?: Guild; // if this application is a game sold, this field will be the guild to which it has been linked
@@ -107,8 +106,7 @@ export class Application extends BaseClass {
 		nullable: true
 	})
 	team?: Team;
-
-  }
+}
 
 export interface ApplicationCommand {
 	id: string;
@@ -140,7 +138,7 @@ export enum ApplicationCommandOptionType {
 	BOOLEAN = 5,
 	USER = 6,
 	CHANNEL = 7,
-	ROLE = 8,
+	ROLE = 8
 }
 
 export interface ApplicationCommandInteractionData {
diff --git a/src/util/entities/Attachment.ts b/src/util/entities/Attachment.ts
index 7b4b17eb..8392f415 100644
--- a/src/util/entities/Attachment.ts
+++ b/src/util/entities/Attachment.ts
@@ -32,7 +32,7 @@ export class Attachment extends BaseClass {
 
 	@JoinColumn({ name: "message_id" })
 	@ManyToOne(() => require("./Message").Message, (message: import("./Message").Message) => message.attachments, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	message: import("./Message").Message;
 
diff --git a/src/util/entities/AuditLog.ts b/src/util/entities/AuditLog.ts
index b003e7ba..6f394f42 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,18 +79,18 @@ 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_UPDATE = 226,
+	ROUTE_CREATE = 225,
+	ROUTE_UPDATE = 226
 }
 
 @Entity("audit_logs")
diff --git a/src/util/entities/BackupCodes.ts b/src/util/entities/BackupCodes.ts
index 9092c14e..503b1dbd 100644
--- a/src/util/entities/BackupCodes.ts
+++ b/src/util/entities/BackupCodes.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
 import { BaseClass } from "./BaseClass";
 import { User } from "./User";
 
@@ -16,4 +16,4 @@ export class BackupCode extends BaseClass {
 
 	@Column()
 	expired: boolean;
-}
\ No newline at end of file
+}
diff --git a/src/util/entities/Ban.ts b/src/util/entities/Ban.ts
index 9504bd8e..27c75278 100644
--- a/src/util/entities/Ban.ts
+++ b/src/util/entities/Ban.ts
@@ -11,7 +11,7 @@ export class Ban extends BaseClass {
 
 	@JoinColumn({ name: "user_id" })
 	@ManyToOne(() => User, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	user: User;
 
@@ -21,7 +21,7 @@ export class Ban extends BaseClass {
 
 	@JoinColumn({ name: "guild_id" })
 	@ManyToOne(() => Guild, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	guild: Guild;
 
diff --git a/src/util/entities/Categories.ts b/src/util/entities/Categories.ts
index 81fbc303..08a79112 100644
--- a/src/util/entities/Categories.ts
+++ b/src/util/entities/Categories.ts
@@ -1,4 +1,4 @@
-import { PrimaryColumn, Column, Entity} from "typeorm";
+import { Column, Entity, PrimaryColumn } 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 a576d7af..23fc6544 100644
--- a/src/util/entities/Channel.ts
+++ b/src/util/entities/Channel.ts
@@ -1,391 +1,383 @@
-import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";

-import { OrmUtils } from "../util/imports/OrmUtils";

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

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

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

-import { HTTPError } from "../util/imports/HTTPError";

-import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial, InvisibleCharacters } 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({ nullable: true })

-	nsfw?: boolean;

-

-	@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[];

-

-	@Column({ nullable: true })

-	flags?: number = 0;

-	

-	@Column({ nullable: true })

-	default_thread_rate_limit_per_user?: number = 0;

-

-

-	// 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 (let character of InvisibleCharacters)

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

-						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);

-			}

-

-			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([

-			OrmUtils.mergeDeep(new Channel(), 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);

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

-

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

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

-		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;

-						ur = OrmUtils.mergeDeep(ur, { closed: false });

-						await ur.save();

-					}

-				}

-			}

-		}

-

-		if (channel == null) {

-			name = trimSpecial(name);

-

-			channel = await (

-				OrmUtils.mergeDeep(new Channel(), {

-					name,

-					type,

-					owner_id: type === ChannelType.DM ? undefined : null, // 1:1 DMs are ownerless in fosscord-server

-					created_at: new Date(),

-					last_message_id: null,

-					recipients: channelRecipients.map((x) =>

-						OrmUtils.mergeDeep(new Recipient(), {

-							user_id: x,

-							closed: !(type === ChannelType.GROUP_DM || x === creator_user_id),

-						})

-					),

-				}) as Channel

-			).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 { DmChannelDTO } from "../dtos";
+import { ChannelCreateEvent, ChannelRecipientRemoveEvent } from "../interfaces";
+import { containsAll, emitEvent, getPermission, InvisibleCharacters, Snowflake, trimSpecial } from "../util";
+import { HTTPError } from "../util/imports/HTTPError";
+import { OrmUtils } from "../util/imports/OrmUtils";
+import { BaseClass } from "./BaseClass";
+import { Guild } from "./Guild";
+import { Invite } from "./Invite";
+import { Message } from "./Message";
+import { ReadState } from "./ReadState";
+import { Recipient } from "./Recipient";
+import { PublicUserProjection, User } from "./User";
+import { VoiceState } from "./VoiceState";
+import { Webhook } from "./Webhook";
+
+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({ nullable: true })
+	nsfw?: boolean;
+
+	@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[];
+
+	@Column({ nullable: true })
+	flags?: number = 0;
+
+	@Column({ nullable: true })
+	default_thread_rate_limit_per_user?: number = 0;
+
+	// 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 (let character of InvisibleCharacters)
+					if (channel.name.includes(character)) 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);
+			}
+
+			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([
+			OrmUtils.mergeDeep(new Channel(), 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);
+		const otherRecipientsUsers = await User.find({ where: recipients.map((x) => ({ id: x })) });
+
+		// TODO: check config for max number of recipients
+		/** if you want to disallow note to self channels, uncomment the conditional below
+		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;
+						ur = OrmUtils.mergeDeep(ur, { closed: false });
+						await ur.save();
+					}
+				}
+			}
+		}
+
+		if (channel == null) {
+			name = trimSpecial(name);
+
+			channel = await (
+				OrmUtils.mergeDeep(new Channel(), {
+					name,
+					type,
+					owner_id: type === ChannelType.DM ? undefined : null, // 1:1 DMs are ownerless in fosscord-server
+					created_at: new Date(),
+					last_message_id: null,
+					recipients: channelRecipients.map((x) =>
+						OrmUtils.mergeDeep(new Recipient(), {
+							user_id: x,
+							closed: !(type === ChannelType.GROUP_DM || x === creator_user_id)
+						})
+					)
+				}) as Channel
+			).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 606fe901..fc33bb65 100644
--- a/src/util/entities/Config.ts
+++ b/src/util/entities/Config.ts
@@ -8,4 +8,4 @@ export class ConfigEntity extends BaseClassWithoutId {
 
 	@Column({ type: "simple-json", nullable: true })
 	value: number | boolean | null | string | undefined;
-}
\ No newline at end of file
+}
diff --git a/src/util/entities/ConnectedAccount.ts b/src/util/entities/ConnectedAccount.ts
index 09ae30ab..018b3995 100644
--- a/src/util/entities/ConnectedAccount.ts
+++ b/src/util/entities/ConnectedAccount.ts
@@ -12,7 +12,7 @@ export class ConnectedAccount extends BaseClass {
 
 	@JoinColumn({ name: "user_id" })
 	@ManyToOne(() => User, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	user: User;
 
diff --git a/src/util/entities/Emoji.ts b/src/util/entities/Emoji.ts
index a3615b7d..a2552995 100644
--- a/src/util/entities/Emoji.ts
+++ b/src/util/entities/Emoji.ts
@@ -2,7 +2,6 @@ import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
 import { User } from ".";
 import { BaseClass } from "./BaseClass";
 import { Guild } from "./Guild";
-import { Role } from "./Role";
 
 @Entity("emojis")
 export class Emoji extends BaseClass {
@@ -17,7 +16,7 @@ export class Emoji extends BaseClass {
 
 	@JoinColumn({ name: "guild_id" })
 	@ManyToOne(() => Guild, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	guild: Guild;
 
@@ -40,7 +39,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 6b578d15..43f02962 100644
--- a/src/util/entities/Encryption.ts
+++ b/src/util/entities/Encryption.ts
@@ -1,35 +1,25 @@
-import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";
+import { Column, Entity } from "typeorm";
+import { Snowflake } from "../util";
+import { BitField } from "../util/BitField";
 import { BaseClass } from "./BaseClass";
-import { Guild } from "./Guild";
-import { PublicUserProjection, User } from "./User";
-import { HTTPError } from "..";
-import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial, InvisibleCharacters } from "../util";
-import { BitField, BitFieldResolvable, BitFlag } from "../util/BitField";
-import { Recipient } from "./Recipient";
-import { Message } from "./Message";
-import { ReadState } from "./ReadState";
-import { Invite } from "./Invite";
-import { DmChannelDTO } from "../dtos";
 
 @Entity("security_settings")
 export class SecuritySettings extends BaseClass {
+	@Column({ nullable: true })
+	guild_id: Snowflake;
 
-  @Column({nullable: true})
-  guild_id: Snowflake;
+	@Column({ nullable: true })
+	channel_id: Snowflake;
 
-  @Column({nullable: true})
-  channel_id: Snowflake;
+	@Column()
+	encryption_permission_mask: BitField;
 
-  @Column()
-  encryption_permission_mask: BitField;
+	@Column()
+	allowed_algorithms: string[];
 
-  @Column()
-  allowed_algorithms: string[];
-
-  @Column()
-  current_algorithm: string;
-
-  @Column({nullable: true})
-  used_since_message: Snowflake;
+	@Column()
+	current_algorithm: string;
 
+	@Column({ nullable: true })
+	used_since_message: Snowflake;
 }
diff --git a/src/util/entities/Group.ts b/src/util/entities/Group.ts
index b24d38cf..23aaabf2 100644
--- a/src/util/entities/Group.ts
+++ b/src/util/entities/Group.ts
@@ -1,11 +1,11 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
+import { Column, Entity } from "typeorm";
 
 import { BaseClass } from "./BaseClass";
 
 @Entity("groups")
 export class UserGroup extends BaseClass {
-  @Column({ nullable: true })
-  parent?: BigInt;
+	@Column({ nullable: true })
+	parent?: BigInt;
 
 	@Column()
 	color: number;
@@ -13,7 +13,7 @@ export class UserGroup extends BaseClass {
 	@Column()
 	hoist: boolean;
 
- 	@Column()
+	@Column()
 	mentionable: boolean;
 
 	@Column()
diff --git a/src/util/entities/Guild.ts b/src/util/entities/Guild.ts
index d146e577..015c6d04 100644
--- a/src/util/entities/Guild.ts
+++ b/src/util/entities/Guild.ts
@@ -1,6 +1,6 @@
-import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, OneToMany, OneToOne, RelationId } from "typeorm";
-import { OrmUtils } from "../util/imports/OrmUtils";
+import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";
 import { Config, handleFile, Snowflake } from "..";
+import { OrmUtils } from "../util/imports/OrmUtils";
 import { Ban } from "./Ban";
 import { BaseClass } from "./BaseClass";
 import { Channel } from "./Channel";
@@ -32,15 +32,7 @@ import { Webhook } from "./Webhook";
 // 		"Gacha"
 // 	],
 
-export const PublicGuildRelations = [
-	"channels",
-	"emojis",
-	"members",
-	"roles",
-	"stickers",
-	"voice_states",
-	"members.user",
-];
+export const PublicGuildRelations = ["channels", "emojis", "members", "roles", "stickers", "voice_states", "members.user"];
 
 @Entity("guilds")
 export class Guild extends BaseClass {
@@ -63,7 +55,7 @@ export class Guild extends BaseClass {
 	@JoinColumn({ name: "ban_ids" })
 	@OneToMany(() => Ban, (ban: Ban) => ban.guild, {
 		cascade: true,
-		orphanedRowAction: "delete",
+		orphanedRowAction: "delete"
 	})
 	bans: Ban[];
 
@@ -113,7 +105,7 @@ export class Guild extends BaseClass {
 	@OneToMany(() => Member, (member: Member) => member.guild, {
 		cascade: true,
 		orphanedRowAction: "delete",
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	members: Member[];
 
@@ -121,14 +113,14 @@ export class Guild extends BaseClass {
 	@OneToMany(() => Role, (role: Role) => role.guild, {
 		cascade: true,
 		orphanedRowAction: "delete",
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	roles: Role[];
 
 	@JoinColumn({ name: "channel_ids" })
 	@OneToMany(() => Channel, (channel: Channel) => channel.guild, {
 		cascade: true,
-		orphanedRowAction: "delete",
+		orphanedRowAction: "delete"
 	})
 	channels: Channel[];
 
@@ -144,7 +136,7 @@ export class Guild extends BaseClass {
 	@OneToMany(() => Emoji, (emoji: Emoji) => emoji.guild, {
 		cascade: true,
 		orphanedRowAction: "delete",
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	emojis: Emoji[];
 
@@ -152,7 +144,7 @@ export class Guild extends BaseClass {
 	@OneToMany(() => Sticker, (sticker: Sticker) => sticker.guild, {
 		cascade: true,
 		orphanedRowAction: "delete",
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	stickers: Sticker[];
 
@@ -160,7 +152,7 @@ export class Guild extends BaseClass {
 	@OneToMany(() => Invite, (invite: Invite) => invite.guild, {
 		cascade: true,
 		orphanedRowAction: "delete",
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	invites: Invite[];
 
@@ -168,7 +160,7 @@ export class Guild extends BaseClass {
 	@OneToMany(() => VoiceState, (voicestate: VoiceState) => voicestate.guild, {
 		cascade: true,
 		orphanedRowAction: "delete",
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	voice_states: VoiceState[];
 
@@ -176,7 +168,7 @@ export class Guild extends BaseClass {
 	@OneToMany(() => Webhook, (webhook: Webhook) => webhook.guild, {
 		cascade: true,
 		orphanedRowAction: "delete",
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	webhooks: Webhook[];
 
@@ -282,12 +274,7 @@ export class Guild extends BaseClass {
 	@Column({ nullable: true })
 	premium_progress_bar_enabled: boolean = false;
 
-	static async createGuild(body: {
-		name?: string;
-		icon?: string | null;
-		owner_id?: string;
-		channels?: Partial<Channel>[];
-	}) {
+	static async createGuild(body: { name?: string; icon?: string | null; owner_id?: string; channels?: Partial<Channel>[] }) {
 		const guild_id = Snowflake.generate();
 
 		const guild: Guild = OrmUtils.mergeDeep(new Guild(), {
@@ -318,9 +305,9 @@ export class Guild extends BaseClass {
 			welcome_screen: {
 				enabled: false,
 				description: "Fill in your description",
-				welcome_channels: [],
+				welcome_channels: []
 			},
-			widget_enabled: true, // NB: don't set it as false to prevent artificial restrictions
+			widget_enabled: true // NB: don't set it as false to prevent artificial restrictions
 		});
 		await guild.save();
 
@@ -338,7 +325,7 @@ export class Guild extends BaseClass {
 			permissions: String("2251804225"),
 			position: 0,
 			icon: null,
-			unicode_emoji: null,
+			unicode_emoji: null
 		});
 		await role.save();
 
@@ -361,7 +348,7 @@ export class Guild extends BaseClass {
 				keepId: true,
 				skipExistsCheck: true,
 				skipPermissionCheck: true,
-				skipEventEmit: true,
+				skipEventEmit: true
 			});
 		}
 
diff --git a/src/util/entities/Invite.ts b/src/util/entities/Invite.ts
index 1e0ebe52..f6ba85d7 100644
--- a/src/util/entities/Invite.ts
+++ b/src/util/entities/Invite.ts
@@ -1,10 +1,10 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId, PrimaryColumn } from "typeorm";
-import { Member } from "./Member";
+import { random } from "@fosscord/api";
+import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn, RelationId } from "typeorm";
 import { BaseClassWithoutId } from "./BaseClass";
 import { Channel } from "./Channel";
 import { Guild } from "./Guild";
+import { Member } from "./Member";
 import { User } from "./User";
-import { random } from "@fosscord/api";
 
 export const PublicInviteRelation = ["inviter", "guild", "channel"];
 
@@ -37,7 +37,7 @@ export class Invite extends BaseClassWithoutId {
 
 	@JoinColumn({ name: "guild_id" })
 	@ManyToOne(() => Guild, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	guild: Guild;
 
@@ -47,7 +47,7 @@ export class Invite extends BaseClassWithoutId {
 
 	@JoinColumn({ name: "channel_id" })
 	@ManyToOne(() => Channel, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	channel: Channel;
 
@@ -67,7 +67,7 @@ export class Invite extends BaseClassWithoutId {
 
 	@JoinColumn({ name: "target_user_id" })
 	@ManyToOne(() => User, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	target_user?: string; // could be used for "User specific invites" https://github.com/fosscord/fosscord/issues/62
 
diff --git a/src/util/entities/Member.ts b/src/util/entities/Member.ts
index baac58ed..42a014d4 100644
--- a/src/util/entities/Member.ts
+++ b/src/util/entities/Member.ts
@@ -1,31 +1,14 @@
-import { PublicUser, User } from "./User";
-import { BaseClass } from "./BaseClass";
-import {
-	Column,
-	Entity,
-	Index,
-	JoinColumn,
-	JoinTable,
-	ManyToMany,
-	ManyToOne,
-	PrimaryGeneratedColumn,
-	RelationId,
-} from "typeorm";
-import { Guild } from "./Guild";
-import { Config, emitEvent } from "../util";
-import {
-	GuildCreateEvent,
-	GuildDeleteEvent,
-	GuildMemberAddEvent,
-	GuildMemberRemoveEvent,
-	GuildMemberUpdateEvent,
-} from "../interfaces";
-import { HTTPError } from "../util/imports/HTTPError";
-import { Role } from "./Role";
-import { BaseClassWithoutId } from "./BaseClass";
+import { Column, Entity, Index, JoinColumn, JoinTable, ManyToMany, ManyToOne, PrimaryGeneratedColumn, RelationId } from "typeorm";
 import { Ban, PublicGuildRelations } from ".";
+import { GuildCreateEvent, GuildDeleteEvent, GuildMemberAddEvent, GuildMemberRemoveEvent, GuildMemberUpdateEvent } from "../interfaces";
+import { Config, emitEvent } from "../util";
 import { DiscordApiErrors } from "../util/Constants";
+import { HTTPError } from "../util/imports/HTTPError";
 import { OrmUtils } from "../util/imports/OrmUtils";
+import { BaseClassWithoutId } from "./BaseClass";
+import { Guild } from "./Guild";
+import { Role } from "./Role";
+import { PublicUser, User } from "./User";
 
 export const MemberPrivateProjection: (keyof Member)[] = [
 	"id",
@@ -40,7 +23,7 @@ export const MemberPrivateProjection: (keyof Member)[] = [
 	"premium_since",
 	"roles",
 	"settings",
-	"user",
+	"user"
 ];
 
 @Entity("members")
@@ -55,7 +38,7 @@ export class Member extends BaseClassWithoutId {
 
 	@JoinColumn({ name: "id" })
 	@ManyToOne(() => User, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	user: User;
 
@@ -65,7 +48,7 @@ export class Member extends BaseClassWithoutId {
 
 	@JoinColumn({ name: "guild_id" })
 	@ManyToOne(() => Guild, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	guild: Guild;
 
@@ -77,8 +60,8 @@ export class Member extends BaseClassWithoutId {
 		joinColumn: { name: "index", referencedColumnName: "index" },
 		inverseJoinColumn: {
 			name: "role_id",
-			referencedColumnName: "id",
-		},
+			referencedColumnName: "id"
+		}
 	})
 	@ManyToMany(() => Role, { cascade: true })
 	roles: Role[];
@@ -133,22 +116,22 @@ export class Member extends BaseClassWithoutId {
 		return Promise.all([
 			Member.delete({
 				id: user_id,
-				guild_id,
+				guild_id
 			}),
 			//Guild.decrement({ id: guild_id }, "member_count", -1),
 
 			emitEvent({
 				event: "GUILD_DELETE",
 				data: {
-					id: guild_id,
+					id: guild_id
 				},
-				user_id: user_id,
+				user_id: user_id
 			} as GuildDeleteEvent),
 			emitEvent({
 				event: "GUILD_MEMBER_REMOVE",
 				data: { guild_id, user: member.user },
-				guild_id,
-			} as GuildMemberRemoveEvent),
+				guild_id
+			} as GuildMemberRemoveEvent)
 		]);
 	}
 
@@ -158,9 +141,9 @@ export class Member extends BaseClassWithoutId {
 			Member.findOneOrFail({
 				where: { id: user_id, guild_id },
 				relations: ["user", "roles"], // we don't want to load  the role objects just the ids
-				select: ["index"],
+				select: ["index"]
 			}),
-			Role.findOneOrFail({ where: { id: role_id, guild_id }, select: ["id"] }),
+			Role.findOneOrFail({ where: { id: role_id, guild_id }, select: ["id"] })
 		]);
 		member.roles.push(OrmUtils.mergeDeep(new Role(), { id: role_id }));
 
@@ -171,10 +154,10 @@ export class Member extends BaseClassWithoutId {
 				data: {
 					guild_id,
 					user: member.user,
-					roles: member.roles.map((x) => x.id),
+					roles: member.roles.map((x) => x.id)
 				},
-				guild_id,
-			} as GuildMemberUpdateEvent),
+				guild_id
+			} as GuildMemberUpdateEvent)
 		]);
 	}
 
@@ -184,9 +167,9 @@ export class Member extends BaseClassWithoutId {
 			Member.findOneOrFail({
 				where: { id: user_id, guild_id },
 				relations: ["user", "roles"], // we don't want to load  the role objects just the ids
-				select: ["index"],
+				select: ["index"]
 			}),
-			await Role.findOneOrFail({ where: { id: role_id, guild_id } }),
+			await Role.findOneOrFail({ where: { id: role_id, guild_id } })
 		]);
 		member.roles = member.roles.filter((x) => x.id == role_id);
 
@@ -197,10 +180,10 @@ export class Member extends BaseClassWithoutId {
 				data: {
 					guild_id,
 					user: member.user,
-					roles: member.roles.map((x) => x.id),
+					roles: member.roles.map((x) => x.id)
 				},
-				guild_id,
-			} as GuildMemberUpdateEvent),
+				guild_id
+			} as GuildMemberUpdateEvent)
 		]);
 	}
 
@@ -208,9 +191,9 @@ export class Member extends BaseClassWithoutId {
 		const member = await Member.findOneOrFail({
 			where: {
 				id: user_id,
-				guild_id,
+				guild_id
 			},
-			relations: ["user"],
+			relations: ["user"]
 		});
 		member.nick = nickname;
 
@@ -222,10 +205,10 @@ export class Member extends BaseClassWithoutId {
 				data: {
 					guild_id,
 					user: member.user,
-					nick: nickname,
+					nick: nickname
 				},
-				guild_id,
-			} as GuildMemberUpdateEvent),
+				guild_id
+			} as GuildMemberUpdateEvent)
 		]);
 	}
 
@@ -243,9 +226,9 @@ export class Member extends BaseClassWithoutId {
 
 		const guild = await Guild.findOneOrFail({
 			where: {
-				id: guild_id,
+				id: guild_id
 			},
-			relations: PublicGuildRelations,
+			relations: PublicGuildRelations
 		});
 
 		if (await Member.count({ where: { id: user.id, guild: { id: guild_id } } }))
@@ -260,7 +243,7 @@ export class Member extends BaseClassWithoutId {
 			premium_since: null,
 			deaf: false,
 			mute: false,
-			pending: false,
+			pending: false
 		};
 		//TODO: check for bugs
 		if (guild.member_count) guild.member_count++;
@@ -276,8 +259,8 @@ export class Member extends BaseClassWithoutId {
 					muted: false,
 					suppress_everyone: false,
 					suppress_roles: false,
-					version: 0,
-				},
+					version: 0
+				}
 				// Member.save is needed because else the roles relations wouldn't be updated
 			}).save(),
 			//Guild.increment({ id: guild_id }, "member_count", 1),
@@ -286,9 +269,9 @@ export class Member extends BaseClassWithoutId {
 				data: {
 					...member,
 					user,
-					guild_id,
+					guild_id
 				},
-				guild_id,
+				guild_id
 			} as GuildMemberAddEvent),
 			emitEvent({
 				event: "GUILD_CREATE",
@@ -301,10 +284,10 @@ export class Member extends BaseClassWithoutId {
 					joined_at: member.joined_at,
 					presences: [],
 					stage_instances: [],
-					threads: [],
+					threads: []
 				},
-				user_id,
-			} as GuildCreateEvent),
+				user_id
+			} as GuildCreateEvent)
 		]);
 	}
 }
@@ -330,16 +313,7 @@ export interface MuteConfig {
 	selected_time_window: number;
 }
 
-export type PublicMemberKeys =
-	| "id"
-	| "guild_id"
-	| "nick"
-	| "roles"
-	| "joined_at"
-	| "pending"
-	| "deaf"
-	| "mute"
-	| "premium_since";
+export type PublicMemberKeys = "id" | "guild_id" | "nick" | "roles" | "joined_at" | "pending" | "deaf" | "mute" | "premium_since";
 
 export const PublicMemberProjection: PublicMemberKeys[] = [
 	"id",
@@ -350,7 +324,7 @@ export const PublicMemberProjection: PublicMemberKeys[] = [
 	"pending",
 	"deaf",
 	"mute",
-	"premium_since",
+	"premium_since"
 ];
 
 // @ts-ignore
diff --git a/src/util/entities/Message.ts b/src/util/entities/Message.ts
index ba3d4f2d..8122b532 100644
--- a/src/util/entities/Message.ts
+++ b/src/util/entities/Message.ts
@@ -1,28 +1,15 @@
-import { User } from "./User";
-import { Member } from "./Member";
-import { Role } from "./Role";
-import { Channel } from "./Channel";
+import { Column, CreateDateColumn, Entity, Index, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToMany, RelationId } from "typeorm";
 import { InteractionType } from "../interfaces/Interaction";
 import { Application } from "./Application";
-import {
-	Column,
-	CreateDateColumn,
-	Entity,
-	Index,
-	JoinColumn,
-	JoinTable,
-	ManyToMany,
-	ManyToOne,
-	OneToMany,
-	RelationId,
-	RemoveOptions,
-	UpdateDateColumn,
-} from "typeorm";
+import { Attachment } from "./Attachment";
 import { BaseClass } from "./BaseClass";
+import { Channel } from "./Channel";
 import { Guild } from "./Guild";
-import { Webhook } from "./Webhook";
+import { Member } from "./Member";
+import { Role } from "./Role";
 import { Sticker } from "./Sticker";
-import { Attachment } from "./Attachment";
+import { User } from "./User";
+import { Webhook } from "./Webhook";
 
 export enum MessageType {
 	DEFAULT = 0,
@@ -62,7 +49,7 @@ export class Message extends BaseClass {
 
 	@JoinColumn({ name: "channel_id" })
 	@ManyToOne(() => Channel, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	channel: Channel;
 
@@ -72,7 +59,7 @@ export class Message extends BaseClass {
 
 	@JoinColumn({ name: "guild_id" })
 	@ManyToOne(() => Guild, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	guild?: Guild;
 
@@ -83,7 +70,7 @@ export class Message extends BaseClass {
 
 	@JoinColumn({ name: "author_id", referencedColumnName: "id" })
 	@ManyToOne(() => User, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	author?: User;
 
@@ -93,7 +80,7 @@ export class Message extends BaseClass {
 
 	@JoinColumn({ name: "member_id", referencedColumnName: "id" })
 	@ManyToOne(() => User, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	member?: Member;
 
@@ -147,7 +134,7 @@ export class Message extends BaseClass {
 
 	@OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, {
 		cascade: true,
-		orphanedRowAction: "delete",
+		orphanedRowAction: "delete"
 	})
 	attachments?: Attachment[];
 
@@ -212,7 +199,7 @@ export interface MessageComponent {
 export enum MessageComponentType {
 	Script = 0, // self command script
 	ActionRow = 1,
-	Button = 2,
+	Button = 2
 }
 
 export interface Embed {
@@ -253,7 +240,7 @@ export enum EmbedType {
 	video = "video",
 	gifv = "gifv",
 	article = "article",
-	link = "link",
+	link = "link"
 }
 
 export interface EmbedImage {
diff --git a/src/util/entities/Migration.ts b/src/util/entities/Migration.ts
index 3f39ae72..626ec429 100644
--- a/src/util/entities/Migration.ts
+++ b/src/util/entities/Migration.ts
@@ -1,9 +1,7 @@
 import { Column, Entity, ObjectIdColumn, PrimaryGeneratedColumn } from "typeorm";
 import { BaseClassWithoutId } from ".";
 
-export const PrimaryIdAutoGenerated = process.env.DATABASE?.startsWith("mongodb")
-	? ObjectIdColumn
-	: PrimaryGeneratedColumn;
+export const PrimaryIdAutoGenerated = process.env.DATABASE?.startsWith("mongodb") ? ObjectIdColumn : PrimaryGeneratedColumn;
 
 @Entity("migrations")
 export class Migration extends BaseClassWithoutId {
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..77d2c08a 100644
--- a/src/util/entities/ReadState.ts
+++ b/src/util/entities/ReadState.ts
@@ -1,7 +1,6 @@
 import { Column, Entity, Index, JoinColumn, ManyToOne, RelationId } from "typeorm";
 import { BaseClass } from "./BaseClass";
 import { Channel } from "./Channel";
-import { Message } from "./Message";
 import { User } from "./User";
 
 // for read receipts
@@ -17,7 +16,7 @@ export class ReadState extends BaseClass {
 
 	@JoinColumn({ name: "channel_id" })
 	@ManyToOne(() => Channel, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	channel: Channel;
 
@@ -27,14 +26,14 @@ export class ReadState extends BaseClass {
 
 	@JoinColumn({ name: "user_id" })
 	@ManyToOne(() => User, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	user: User;
 
 	// 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/Recipient.ts b/src/util/entities/Recipient.ts
index a945f938..fc9e629b 100644
--- a/src/util/entities/Recipient.ts
+++ b/src/util/entities/Recipient.ts
@@ -9,7 +9,7 @@ export class Recipient extends BaseClass {
 
 	@JoinColumn({ name: "channel_id" })
 	@ManyToOne(() => require("./Channel").Channel, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	channel: import("./Channel").Channel;
 
@@ -19,7 +19,7 @@ export class Recipient extends BaseClass {
 
 	@JoinColumn({ name: "user_id" })
 	@ManyToOne(() => require("./User").User, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	user: import("./User").User;
 
diff --git a/src/util/entities/Relationship.ts b/src/util/entities/Relationship.ts
index c3592c76..b55d9e64 100644
--- a/src/util/entities/Relationship.ts
+++ b/src/util/entities/Relationship.ts
@@ -6,7 +6,7 @@ export enum RelationshipType {
 	outgoing = 4,
 	incoming = 3,
 	blocked = 2,
-	friends = 1,
+	friends = 1
 }
 
 @Entity("relationships")
@@ -18,7 +18,7 @@ export class Relationship extends BaseClass {
 
 	@JoinColumn({ name: "from_id" })
 	@ManyToOne(() => User, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	from: User;
 
@@ -28,7 +28,7 @@ export class Relationship extends BaseClass {
 
 	@JoinColumn({ name: "to_id" })
 	@ManyToOne(() => User, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	to: User;
 
@@ -43,7 +43,7 @@ export class Relationship extends BaseClass {
 			id: this.to?.id || this.to_id,
 			type: this.type,
 			nickname: this.nickname,
-			user: this.to?.toPublicUser(),
+			user: this.to?.toPublicUser()
 		};
 	}
 }
diff --git a/src/util/entities/Role.ts b/src/util/entities/Role.ts
index 4b721b5b..b1fd9bb1 100644
--- a/src/util/entities/Role.ts
+++ b/src/util/entities/Role.ts
@@ -11,7 +11,7 @@ export class Role extends BaseClass {
 
 	@JoinColumn({ name: "guild_id" })
 	@ManyToOne(() => Guild, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	guild: Guild;
 
diff --git a/src/util/entities/Session.ts b/src/util/entities/Session.ts
index 969efa89..0cb4c309 100644
--- a/src/util/entities/Session.ts
+++ b/src/util/entities/Session.ts
@@ -1,8 +1,8 @@
-import { User } from "./User";
-import { BaseClass } from "./BaseClass";
 import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
-import { Status } from "../interfaces/Status";
 import { Activity } from "../interfaces/Activity";
+import { Status } from "../interfaces/Status";
+import { BaseClass } from "./BaseClass";
+import { User } from "./User";
 
 //TODO we need to remove all sessions on server start because if the server crashes without closing websockets it won't delete them
 
@@ -14,7 +14,7 @@ export class Session extends BaseClass {
 
 	@JoinColumn({ name: "user_id" })
 	@ManyToOne(() => User, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	user: User;
 
@@ -37,10 +37,4 @@ export class Session extends BaseClass {
 	status: Status; //TODO enum
 }
 
-export const PrivateSessionProjection: (keyof Session)[] = [
-	"user_id",
-	"session_id",
-	"activities",
-	"client_info",
-	"status",
-];
+export const PrivateSessionProjection: (keyof Session)[] = ["user_id", "session_id", "activities", "client_info", "status"];
diff --git a/src/util/entities/Sticker.ts b/src/util/entities/Sticker.ts
index 37bc6fbe..69836e62 100644
--- a/src/util/entities/Sticker.ts
+++ b/src/util/entities/Sticker.ts
@@ -1,18 +1,18 @@
 import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
-import { User } from "./User";
 import { BaseClass } from "./BaseClass";
 import { Guild } from "./Guild";
+import { User } from "./User";
 
 export enum StickerType {
 	STANDARD = 1,
-	GUILD = 2,
+	GUILD = 2
 }
 
 export enum StickerFormatType {
 	GIF = 0, // gif is a custom format type and not in discord spec
 	PNG = 1,
 	APNG = 2,
-	LOTTIE = 3,
+	LOTTIE = 3
 }
 
 @Entity("stickers")
@@ -36,7 +36,7 @@ export class Sticker extends BaseClass {
 	@JoinColumn({ name: "pack_id" })
 	@ManyToOne(() => require("./StickerPack").StickerPack, {
 		onDelete: "CASCADE",
-		nullable: true,
+		nullable: true
 	})
 	pack: import("./StickerPack").StickerPack;
 
@@ -45,7 +45,7 @@ export class Sticker extends BaseClass {
 
 	@JoinColumn({ name: "guild_id" })
 	@ManyToOne(() => Guild, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	guild?: Guild;
 
@@ -54,7 +54,7 @@ export class Sticker extends BaseClass {
 
 	@JoinColumn({ name: "user_id" })
 	@ManyToOne(() => User, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	user?: User;
 
diff --git a/src/util/entities/StickerPack.ts b/src/util/entities/StickerPack.ts
index ec8c69a2..4619af34 100644
--- a/src/util/entities/StickerPack.ts
+++ b/src/util/entities/StickerPack.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToOne, OneToMany, OneToOne, RelationId } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";
 import { Sticker } from ".";
 import { BaseClass } from "./BaseClass";
 
@@ -15,7 +15,7 @@ export class StickerPack extends BaseClass {
 
 	@OneToMany(() => Sticker, (sticker: Sticker) => sticker.pack, {
 		cascade: true,
-		orphanedRowAction: "delete",
+		orphanedRowAction: "delete"
 	})
 	stickers: Sticker[];
 
diff --git a/src/util/entities/Team.ts b/src/util/entities/Team.ts
index 22140b7f..1d2d7002 100644
--- a/src/util/entities/Team.ts
+++ b/src/util/entities/Team.ts
@@ -1,4 +1,4 @@
-import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, OneToMany, RelationId } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";
 import { BaseClass } from "./BaseClass";
 import { TeamMember } from "./TeamMember";
 import { User } from "./User";
@@ -10,7 +10,7 @@ export class Team extends BaseClass {
 
 	@JoinColumn({ name: "member_ids" })
 	@OneToMany(() => TeamMember, (member: TeamMember) => member.team, {
-		orphanedRowAction: "delete",
+		orphanedRowAction: "delete"
 	})
 	members: TeamMember[];
 
diff --git a/src/util/entities/TeamMember.ts b/src/util/entities/TeamMember.ts
index b726e1e8..d11ebf95 100644
--- a/src/util/entities/TeamMember.ts
+++ b/src/util/entities/TeamMember.ts
@@ -4,7 +4,7 @@ import { User } from "./User";
 
 export enum TeamMemberState {
 	INVITED = 1,
-	ACCEPTED = 2,
+	ACCEPTED = 2
 }
 
 @Entity("team_members")
@@ -21,7 +21,7 @@ export class TeamMember extends BaseClass {
 
 	@JoinColumn({ name: "team_id" })
 	@ManyToOne(() => require("./Team").Team, (team: import("./Team").Team) => team.members, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	team: import("./Team").Team;
 
@@ -31,7 +31,7 @@ export class TeamMember extends BaseClass {
 
 	@JoinColumn({ name: "user_id" })
 	@ManyToOne(() => User, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	user: User;
 }
diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts
index 5432f298..1237b676 100644
--- a/src/util/entities/User.ts
+++ b/src/util/entities/User.ts
@@ -1,11 +1,11 @@
 import { Column, Entity, FindOneOptions, FindOptionsSelectByString, JoinColumn, OneToMany, OneToOne } from "typeorm";
+import { Member, Session, UserSettings } from ".";
+import { Config, FieldErrors, Snowflake, trimSpecial } from "..";
+import { BitField } from "../util/BitField";
 import { OrmUtils } from "../util/imports/OrmUtils";
 import { BaseClass } from "./BaseClass";
-import { BitField } from "../util/BitField";
-import { Relationship } from "./Relationship";
 import { ConnectedAccount } from "./ConnectedAccount";
-import { Config, FieldErrors, Snowflake, trimSpecial } from "..";
-import { Member, Session, UserSettings } from ".";
+import { Relationship } from "./Relationship";
 
 export enum PublicUserEnum {
 	username,
@@ -17,7 +17,7 @@ export enum PublicUserEnum {
 	banner,
 	bio,
 	bot,
-	premium_since,
+	premium_since
 }
 export type PublicUserKeys = keyof typeof PublicUserEnum;
 
@@ -31,17 +31,15 @@ export enum PrivateUserEnum {
 	premium,
 	premium_type,
 	disabled,
-	settings,
+	settings
 	// locale
 }
 export type PrivateUserKeys = keyof typeof PrivateUserEnum | PublicUserKeys;
 
-export const PublicUserProjection = Object.values(PublicUserEnum).filter(
-	(x) => typeof x === "string"
-) as PublicUserKeys[];
+export const PublicUserProjection = Object.values(PublicUserEnum).filter((x) => typeof x === "string") as PublicUserKeys[];
 export const PrivateUserProjection = [
 	...PublicUserProjection,
-	...Object.values(PrivateUserEnum).filter((x) => typeof x === "string"),
+	...Object.values(PrivateUserEnum).filter((x) => typeof x === "string")
 ] as PrivateUserKeys[];
 
 // Private user data that should never get sent to the client
@@ -148,14 +146,14 @@ export class User extends BaseClass {
 	@JoinColumn({ name: "relationship_ids" })
 	@OneToMany(() => Relationship, (relationship: Relationship) => relationship.from, {
 		cascade: true,
-		orphanedRowAction: "delete",
+		orphanedRowAction: "delete"
 	})
 	relationships: Relationship[];
 
 	@JoinColumn({ name: "connected_account_ids" })
 	@OneToMany(() => ConnectedAccount, (account: ConnectedAccount) => account.user, {
 		cascade: true,
-		orphanedRowAction: "delete",
+		orphanedRowAction: "delete"
 	})
 	connected_accounts: ConnectedAccount[];
 
@@ -168,8 +166,7 @@ export class User extends BaseClass {
 	@Column({ type: "simple-array", select: false })
 	fingerprints: string[] = []; // array of fingerprints -> used to prevent multiple accounts
 
-	
-	@OneToOne(()=> UserSettings, {
+	@OneToOne(() => UserSettings, {
 		cascade: true,
 		orphanedRowAction: "delete",
 		eager: false
@@ -185,7 +182,7 @@ export class User extends BaseClass {
 	notes: { [key: string]: string } = {}; //key is ID of user
 
 	async save(): Promise<any> {
-		if(!this.settings) this.settings = new UserSettings();
+		if (!this.settings) this.settings = new UserSettings();
 		this.settings.id = this.id;
 		//await this.settings.save();
 		return super.save();
@@ -203,7 +200,7 @@ export class User extends BaseClass {
 		return await User.findOneOrFail({
 			where: { id: user_id },
 			select: [...PublicUserProjection, ...((opts?.select as FindOptionsSelectByString<User>) || [])],
-			...opts,
+			...opts
 		});
 	}
 
@@ -241,7 +238,7 @@ export class User extends BaseClass {
 		username,
 		password,
 		date_of_birth,
-		req,
+		req
 	}: {
 		username: string;
 		password?: string;
@@ -258,8 +255,8 @@ export class User extends BaseClass {
 			throw FieldErrors({
 				username: {
 					code: "USERNAME_TOO_MANY_USERS",
-					message: req?.t("auth:register.USERNAME_TOO_MANY_USERS"),
-				},
+					message: req?.t("auth:register.USERNAME_TOO_MANY_USERS")
+				}
 			});
 		}
 
@@ -276,7 +273,7 @@ export class User extends BaseClass {
 			email: email,
 			data: {
 				hash: password,
-				valid_tokens_since: new Date(),
+				valid_tokens_since: new Date()
 			},
 			settings: { ...new UserSettings(), locale: language }
 		});
@@ -319,6 +316,6 @@ export class UserFlags extends BitField {
 		VERIFIED_BOT: BigInt(1) << BigInt(16),
 		EARLY_VERIFIED_BOT_DEVELOPER: BigInt(1) << BigInt(17),
 		CERTIFIED_MODERATOR: BigInt(1) << BigInt(18),
-		BOT_HTTP_INTERACTIONS: BigInt(1) << BigInt(19),
+		BOT_HTTP_INTERACTIONS: BigInt(1) << BigInt(19)
 	};
 }
diff --git a/src/util/entities/UserGroup.ts b/src/util/entities/UserGroup.ts
index 709b9d0b..08d68a4e 100644
--- a/src/util/entities/UserGroup.ts
+++ b/src/util/entities/UserGroup.ts
@@ -1,7 +1,6 @@
-import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
+import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
 
 import { BaseClass } from "./BaseClass";
-import { Guild } from "./Guild";
 import { User } from "./User";
 
 @Entity("groups")
@@ -11,11 +10,11 @@ export class UserGroup extends BaseClass {
 
 	@Column()
 	hoist: boolean;
-	
+
 	@JoinColumn({ name: "controller", referencedColumnName: "id" })
 	@ManyToOne(() => User)
 	controller?: User;
-	 
+
 	@Column()
 	mentionable_by?: string;
 
@@ -27,11 +26,10 @@ export class UserGroup extends BaseClass {
 
 	@Column({ nullable: true })
 	icon: string;
-	
+
 	@Column({ nullable: true })
 	parent?: string;
-	
-	@Column({ type: "simple-array", nullable: true})
-	associciations: string[];
 
+	@Column({ type: "simple-array", nullable: true })
+	associciations: string[];
 }
diff --git a/src/util/entities/UserSettings.ts b/src/util/entities/UserSettings.ts
index ef6f95af..9fa18a4d 100644
--- a/src/util/entities/UserSettings.ts
+++ b/src/util/entities/UserSettings.ts
@@ -1,119 +1,119 @@
-import { Column, Entity, JoinColumn } from "typeorm";
+import { Column, Entity } from "typeorm";
 import { BaseClassWithoutId, PrimaryIdColumn } from ".";
 
 @Entity("user_settings")
 export class UserSettings extends BaseClassWithoutId {
-    @PrimaryIdColumn()
+	@PrimaryIdColumn()
 	id: string;
 
 	@Column({ nullable: true })
-    afk_timeout: number = 3600;
-
-	@Column({ nullable: true })
-    allow_accessibility_detection: boolean = true;
-	
-    @Column({ nullable: true })
-    animate_emoji: boolean = true;
-	
-    @Column({ nullable: true })
-    animate_stickers: number = 0;
-	
-    @Column({ nullable: true })
-    contact_sync_enabled: boolean = false;
-	
-    @Column({ nullable: true })
-    convert_emoticons: boolean = false;
-	
-    @Column({ nullable: true, type: "simple-json" })
-    custom_status: CustomStatus | null = null;
-	
-    @Column({ nullable: true })
-    default_guilds_restricted: boolean = false;
-	
-    @Column({ nullable: true })
-    detect_platform_accounts: boolean = false;
-	
-    @Column({ nullable: true })
-    developer_mode: boolean = true;
-	
-    @Column({ nullable: true })
-    disable_games_tab: boolean = true;
-	
-    @Column({ nullable: true })
-    enable_tts_command: boolean = false;
-	
-    @Column({ nullable: true })
-    explicit_content_filter: number = 0;
-	
-    @Column({ nullable: true, type: "simple-json" })
-    friend_source_flags: FriendSourceFlags = { all: true };
-	
-    @Column({ nullable: true })
-    gateway_connected: boolean = false;
-	
-    @Column({ nullable: true })
-    gif_auto_play: boolean = false;
-	
-    @Column({ nullable: true, type: "simple-json" })
-    guild_folders: GuildFolder[] = []; // every top guild is displayed as a "folder"
-	
-    @Column({ nullable: true, type: "simple-json" })
-    guild_positions: string[] = []; // guild ids ordered by position
-	
-    @Column({ nullable: true })
-    inline_attachment_media: boolean = true;
-	
-    @Column({ nullable: true })
-    inline_embed_media: boolean = true;
-	
-    @Column({ nullable: true })
-    locale: string = "en-US"; // en_US
-	
-    @Column({ nullable: true })
-    message_display_compact: boolean = false;
-	
-    @Column({ nullable: true })
-    native_phone_integration_enabled: boolean = true;
-	
-    @Column({ nullable: true })
-    render_embeds: boolean = true;
-	
-    @Column({ nullable: true })
-    render_reactions: boolean = true;
-	
-    @Column({ nullable: true, type: "simple-json" })
-    restricted_guilds: string[] = [];
-	
-    @Column({ nullable: true })
-    show_current_game: boolean = true;
-	
-    @Column({ nullable: true })
-    status: "online" | "offline" | "dnd" | "idle" | "invisible" = "online";
-	
-    @Column({ nullable: true })
-    stream_notifications_enabled: boolean = false;
-	
-    @Column({ nullable: true })
-    theme: "dark" | "white" = "dark"; // dark
-	
-    @Column({ nullable: true })
-    timezone_offset: number = 0; // e.g -60
+	afk_timeout: number = 3600;
+
+	@Column({ nullable: true })
+	allow_accessibility_detection: boolean = true;
+
+	@Column({ nullable: true })
+	animate_emoji: boolean = true;
+
+	@Column({ nullable: true })
+	animate_stickers: number = 0;
+
+	@Column({ nullable: true })
+	contact_sync_enabled: boolean = false;
+
+	@Column({ nullable: true })
+	convert_emoticons: boolean = false;
+
+	@Column({ nullable: true, type: "simple-json" })
+	custom_status: CustomStatus | null = null;
+
+	@Column({ nullable: true })
+	default_guilds_restricted: boolean = false;
+
+	@Column({ nullable: true })
+	detect_platform_accounts: boolean = false;
+
+	@Column({ nullable: true })
+	developer_mode: boolean = true;
+
+	@Column({ nullable: true })
+	disable_games_tab: boolean = true;
+
+	@Column({ nullable: true })
+	enable_tts_command: boolean = false;
+
+	@Column({ nullable: true })
+	explicit_content_filter: number = 0;
+
+	@Column({ nullable: true, type: "simple-json" })
+	friend_source_flags: FriendSourceFlags = { all: true };
+
+	@Column({ nullable: true })
+	gateway_connected: boolean = false;
+
+	@Column({ nullable: true })
+	gif_auto_play: boolean = false;
+
+	@Column({ nullable: true, type: "simple-json" })
+	guild_folders: GuildFolder[] = []; // every top guild is displayed as a "folder"
+
+	@Column({ nullable: true, type: "simple-json" })
+	guild_positions: string[] = []; // guild ids ordered by position
+
+	@Column({ nullable: true })
+	inline_attachment_media: boolean = true;
+
+	@Column({ nullable: true })
+	inline_embed_media: boolean = true;
+
+	@Column({ nullable: true })
+	locale: string = "en-US"; // en_US
+
+	@Column({ nullable: true })
+	message_display_compact: boolean = false;
+
+	@Column({ nullable: true })
+	native_phone_integration_enabled: boolean = true;
+
+	@Column({ nullable: true })
+	render_embeds: boolean = true;
+
+	@Column({ nullable: true })
+	render_reactions: boolean = true;
+
+	@Column({ nullable: true, type: "simple-json" })
+	restricted_guilds: string[] = [];
+
+	@Column({ nullable: true })
+	show_current_game: boolean = true;
+
+	@Column({ nullable: true })
+	status: "online" | "offline" | "dnd" | "idle" | "invisible" = "online";
+
+	@Column({ nullable: true })
+	stream_notifications_enabled: boolean = false;
+
+	@Column({ nullable: true })
+	theme: "dark" | "white" = "dark"; // dark
+
+	@Column({ nullable: true })
+	timezone_offset: number = 0; // e.g -60
 }
 
 interface CustomStatus {
-    emoji_id?: string;
-    emoji_name?: string;
-    expires_at?: number;
-    text?: string;
+	emoji_id?: string;
+	emoji_name?: string;
+	expires_at?: number;
+	text?: string;
 }
 
 interface GuildFolder {
-    color: number;
-    guild_ids: string[];
-    id: number;
-    name: string;
+	color: number;
+	guild_ids: string[];
+	id: number;
+	name: string;
 }
 
-interface FriendSourceFlags { 
-    all: boolean
-}
\ No newline at end of file
+interface FriendSourceFlags {
+	all: boolean;
+}
diff --git a/src/util/entities/VoiceState.ts b/src/util/entities/VoiceState.ts
index 75748a01..baf2c687 100644
--- a/src/util/entities/VoiceState.ts
+++ b/src/util/entities/VoiceState.ts
@@ -2,8 +2,8 @@ import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
 import { BaseClass } from "./BaseClass";
 import { Channel } from "./Channel";
 import { Guild } from "./Guild";
-import { User } from "./User";
 import { Member } from "./Member";
+import { User } from "./User";
 
 //https://gist.github.com/vassjozsef/e482c65df6ee1facaace8b3c9ff66145#file-voice_state-ex
 @Entity("voice_states")
@@ -14,7 +14,7 @@ export class VoiceState extends BaseClass {
 
 	@JoinColumn({ name: "guild_id" })
 	@ManyToOne(() => Guild, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	guild?: Guild;
 
@@ -24,7 +24,7 @@ export class VoiceState extends BaseClass {
 
 	@JoinColumn({ name: "channel_id" })
 	@ManyToOne(() => Channel, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	channel: Channel;
 
@@ -34,7 +34,7 @@ export class VoiceState extends BaseClass {
 
 	@JoinColumn({ name: "user_id" })
 	@ManyToOne(() => User, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	user: User;
 
diff --git a/src/util/entities/Webhook.ts b/src/util/entities/Webhook.ts
index 89538417..3d94ddb6 100644
--- a/src/util/entities/Webhook.ts
+++ b/src/util/entities/Webhook.ts
@@ -7,7 +7,7 @@ import { User } from "./User";
 
 export enum WebhookType {
 	Incoming = 1,
-	ChannelFollower = 2,
+	ChannelFollower = 2
 }
 
 @Entity("webhooks")
@@ -30,7 +30,7 @@ export class Webhook extends BaseClass {
 
 	@JoinColumn({ name: "guild_id" })
 	@ManyToOne(() => Guild, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	guild: Guild;
 
@@ -40,7 +40,7 @@ export class Webhook extends BaseClass {
 
 	@JoinColumn({ name: "channel_id" })
 	@ManyToOne(() => Channel, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	channel: Channel;
 
@@ -50,7 +50,7 @@ export class Webhook extends BaseClass {
 
 	@JoinColumn({ name: "application_id" })
 	@ManyToOne(() => Application, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	application: Application;
 
@@ -60,7 +60,7 @@ export class Webhook extends BaseClass {
 
 	@JoinColumn({ name: "user_id" })
 	@ManyToOne(() => User, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	user: User;
 
@@ -70,7 +70,7 @@ export class Webhook extends BaseClass {
 
 	@JoinColumn({ name: "source_guild_id" })
 	@ManyToOne(() => Guild, {
-		onDelete: "CASCADE",
+		onDelete: "CASCADE"
 	})
 	source_guild: Guild;
 }
diff --git a/src/util/entities/index.ts b/src/util/entities/index.ts
index c6f12022..2b91c2ba 100644
--- a/src/util/entities/index.ts
+++ b/src/util/entities/index.ts
@@ -1,10 +1,12 @@
 export * from "./Application";
 export * from "./Attachment";
 export * from "./AuditLog";
+export * from "./BackupCodes";
 export * from "./Ban";
 export * from "./BaseClass";
 export * from "./Categories";
 export * from "./Channel";
+export * from "./ClientRelease";
 export * from "./Config";
 export * from "./ConnectedAccount";
 export * from "./Emoji";
@@ -13,6 +15,7 @@ export * from "./Invite";
 export * from "./Member";
 export * from "./Message";
 export * from "./Migration";
+export * from "./Note";
 export * from "./RateLimit";
 export * from "./ReadState";
 export * from "./Recipient";
@@ -25,9 +28,6 @@ export * from "./Team";
 export * from "./TeamMember";
 export * from "./Template";
 export * from "./User";
+export * from "./UserSettings";
 export * from "./VoiceState";
 export * from "./Webhook";
-export * from "./ClientRelease";
-export * from "./BackupCodes";
-export * from "./Note";
-export * from "./UserSettings";