summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorxnacly <matteogropp@gmail.com>2021-04-08 15:56:11 +0200
committerxnacly <matteogropp@gmail.com>2021-04-08 15:56:11 +0200
commitf01fe1ba3ac22d33ecf61659d1f65c5ac1ba4e17 (patch)
tree1a3361f31dbbf700efb84513c95388cfbfb2e58f /src
parentadded hasThrow (diff)
parent:bug: move dev dependencies to normal (diff)
downloadserver-f01fe1ba3ac22d33ecf61659d1f65c5ac1ba4e17.tar.xz
Merge branch 'main' of https://github.com/fosscord/fosscord-server-util
Diffstat (limited to 'src')
-rw-r--r--src/index.ts29
-rw-r--r--src/models/Activity.ts72
-rw-r--r--src/models/Application.ts6
-rw-r--r--src/models/AuditLog.ts66
-rw-r--r--src/models/Ban.ts12
-rw-r--r--src/models/Channel.ts34
-rw-r--r--src/models/Emoji.ts12
-rw-r--r--src/models/Event.ts281
-rw-r--r--src/models/Guild.ts78
-rw-r--r--src/models/Interaction.ts8
-rw-r--r--src/models/Invite.ts22
-rw-r--r--src/models/Member.ts35
-rw-r--r--src/models/Message.ts97
-rw-r--r--src/models/Role.ts15
-rw-r--r--src/models/User.ts106
-rw-r--r--src/models/VoiceState.ts12
-rw-r--r--src/models/index.ts36
-rw-r--r--src/util/Database.ts76
-rw-r--r--src/util/Permissions.ts22
-rw-r--r--src/util/Snowflake.ts2
-rw-r--r--src/util/index.ts7
21 files changed, 611 insertions, 417 deletions
diff --git a/src/index.ts b/src/index.ts
index 8484565a..343a7496 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,31 +1,10 @@
 export * from "./util/checkToken";
 
 export * as Constants from "./util/Constants";
-export * from "./models/Ban";
-export * from "./models/Channel";
-export * from "./models/Emoji";
-export * from "./models/Guild";
-export * from "./models/Invite";
-export * from "./models/Member";
-export * from "./models/Role";
-export * from "./models/User";
-export * from "./models/Activity";
-export * from "./models/Application";
-export * from "./models/Interaction";
-export * from "./models/Message";
-export * from "./models/Status";
-export * from "./models/VoiceState";
-
-export * from "./util/String";
-export * from "./util/BitField";
-export * from "./util/Intents";
-export * from "./util/MessageFlags";
-export * from "./util/Permissions";
-export * from "./util/Snowflake";
-export * from "./util/UserFlags";
-export * from "./models/Event";
+export * from "./models/index";
+export * from "./util/index";
 
 import Config, { DefaultOptions } from "./util/Config";
-import db, { MongooseCache } from "./util/Database";
+import db, { MongooseCache, toObject } from "./util/Database";
 
-export { Config, db, DefaultOptions, MongooseCache };
+export { Config, db, DefaultOptions, MongooseCache, toObject };
diff --git a/src/models/Activity.ts b/src/models/Activity.ts
index beaa43e8..340590c4 100644
--- a/src/models/Activity.ts
+++ b/src/models/Activity.ts
@@ -4,7 +4,7 @@ import { Schema, model, Types, Document } from "mongoose";
 
 export interface Presence {
 	user: User;
-	guild_id?: bigint;
+	guild_id?: string;
 	status: Status;
 	activities: Activity[];
 	client_status: ClientStatus;
@@ -14,17 +14,17 @@ export interface Activity {
 	name: string;
 	type: ActivityType;
 	url?: string;
-	created_at: Date;
+	created_at?: Date;
 	timestamps?: {
-		start: number;
-		end: number;
+		start?: number;
+		end?: number;
 	}[];
-	application_id?: bigint;
+	application_id?: string;
 	details?: string;
 	state?: string;
 	emoji?: {
 		name: string;
-		id?: bigint;
+		id?: string;
 		amimated?: boolean;
 	};
 	party?: {
@@ -32,10 +32,10 @@ export interface Activity {
 		size?: [number, number];
 	};
 	assets?: {
-		large_image: string;
-		large_text: string;
-		small_image: string;
-		small_text: string;
+		large_image?: string;
+		large_text?: string;
+		small_image?: string;
+		small_text?: string;
 	};
 	secrets?: {
 		join?: string;
@@ -49,39 +49,39 @@ export interface Activity {
 export const Activity = {
 	name: String,
 	type: Number,
-	url: String,
-	created_at: Date,
-	timestamps: [
+	$url: String,
+	$created_at: Date,
+	$timestamps: [
 		{
-			start: Number,
-			end: Number,
+			$start: Number,
+			$end: Number,
 		},
 	],
-	application_id: Types.Long,
-	details: String,
-	state: String,
-	emoji: {
-		name: String,
-		id: Types.Long,
-		amimated: Boolean,
+	$application_id: String,
+	$details: String,
+	$state: String,
+	$emoji: {
+		$name: String,
+		$id: String,
+		$amimated: Boolean,
 	},
-	party: {
-		id: String,
-		size: [Number, Number],
+	$party: {
+		$id: String,
+		$size: [Number, Number],
 	},
-	assets: {
-		large_image: String,
-		large_text: String,
-		small_image: String,
-		small_text: String,
+	$assets: {
+		$large_image: String,
+		$large_text: String,
+		$small_image: String,
+		$small_text: String,
 	},
-	secrets: {
-		join: String,
-		spectate: String,
-		match: String,
+	$secrets: {
+		$join: String,
+		$spectate: String,
+		$match: String,
 	},
-	instance: Boolean,
-	flags: Types.Long,
+	$instance: Boolean,
+	$flags: Types.Long,
 };
 
 export enum ActivityType {
diff --git a/src/models/Application.ts b/src/models/Application.ts
index ea443dc9..4c519ff2 100644
--- a/src/models/Application.ts
+++ b/src/models/Application.ts
@@ -1,6 +1,6 @@
 export interface ApplicationCommand {
-	id: bigint;
-	application_id: bigint;
+	id: string;
+	application_id: string;
 	name: string;
 	description: string;
 	options?: ApplicationCommandOption[];
@@ -32,7 +32,7 @@ export enum ApplicationCommandOptionType {
 }
 
 export interface ApplicationCommandInteractionData {
-	id: bigint;
+	id: string;
 	name: string;
 	options?: ApplicationCommandInteractionDataOption[];
 }
diff --git a/src/models/AuditLog.ts b/src/models/AuditLog.ts
index a0f91a82..c1f83c13 100644
--- a/src/models/AuditLog.ts
+++ b/src/models/AuditLog.ts
@@ -11,17 +11,17 @@ export interface AuditLogResponse {
 }
 
 export interface AuditLogEntries {
-	target_id?: bigint;
-	user_id: bigint;
-	id: bigint;
+	target_id?: string;
+	user_id: string;
+	id: string;
 	action_type: AuditLogEvents;
 	options?: {
 		delete_member_days?: string;
 		members_removed?: string;
-		channel_id?: bigint;
-		messaged_id?: bigint;
+		channel_id?: string;
+		messaged_id?: string;
 		count?: string;
-		id?: bigint;
+		id?: string;
 		type?: string;
 		role_name?: string;
 	};
@@ -42,13 +42,13 @@ export interface AuditLogChangeValue {
 	splash_hash?: string;
 	discovery_splash_hash?: string;
 	banner_hash?: string;
-	owner_id?: bigint;
+	owner_id?: string;
 	region?: string;
 	preferred_locale?: string;
-	afk_channel_id?: bigint;
+	afk_channel_id?: string;
 	afk_timeout?: number;
-	rules_channel_id?: bigint;
-	public_updates_channel_id?: bigint;
+	rules_channel_id?: string;
+	public_updates_channel_id?: string;
 	mfa_level?: number;
 	verification_level?: number;
 	explicit_content_filter?: number;
@@ -58,14 +58,14 @@ export interface AuditLogChangeValue {
 	$remove?: {}[];
 	prune_delete_days?: number;
 	widget_enabled?: boolean;
-	widget_channel_id?: bigint;
-	system_channel_id?: bigint;
+	widget_channel_id?: string;
+	system_channel_id?: string;
 	position?: number;
 	topic?: string;
 	bitrate?: number;
 	permission_overwrites?: ChannelPermissionOverwrite[];
 	nsfw?: boolean;
-	application_id?: bigint;
+	application_id?: string;
 	rate_limit_per_user?: number;
 	permissions?: string;
 	color?: number;
@@ -74,8 +74,8 @@ export interface AuditLogChangeValue {
 	allow?: string;
 	deny?: string;
 	code?: string;
-	channel_id?: bigint;
-	inviter_id?: bigint;
+	channel_id?: string;
+	inviter_id?: string;
 	max_uses?: number;
 	uses?: number;
 	max_age?: number;
@@ -84,7 +84,7 @@ export interface AuditLogChangeValue {
 	mute?: boolean;
 	nick?: string;
 	avatar_hash?: string;
-	id?: bigint;
+	id?: string;
 	type?: number;
 	enable_emoticons?: boolean;
 	expire_behavior?: number;
@@ -93,7 +93,7 @@ export interface AuditLogChangeValue {
 }
 
 export interface AuditLogEntriesDocument extends Document, AuditLogEntries {
-	id: bigint;
+	id: string;
 }
 
 export const AuditLogChanges = {
@@ -103,13 +103,13 @@ export const AuditLogChanges = {
 	splash_hash: String,
 	discovery_splash_hash: String,
 	banner_hash: String,
-	owner_id: Types.Long,
+	owner_id: String,
 	region: String,
 	preferred_locale: String,
-	afk_channel_id: Types.Long,
+	afk_channel_id: String,
 	afk_timeout: Number,
-	rules_channel_id: Types.Long,
-	public_updates_channel_id: Types.Long,
+	rules_channel_id: String,
+	public_updates_channel_id: String,
 	mfa_level: Number,
 	verification_level: Number,
 	explicit_content_filter: Number,
@@ -119,14 +119,14 @@ export const AuditLogChanges = {
 	$remove: [{}],
 	prune_delete_days: Number,
 	widget_enabled: Boolean,
-	widget_channel_id: Types.Long,
-	system_channel_id: Types.Long,
+	widget_channel_id: String,
+	system_channel_id: String,
 	position: Number,
 	topic: String,
 	bitrate: Number,
 	permission_overwrites: [{}],
 	nsfw: Boolean,
-	application_id: Types.Long,
+	application_id: String,
 	rate_limit_per_user: Number,
 	permissions: String,
 	color: Number,
@@ -135,8 +135,8 @@ export const AuditLogChanges = {
 	allow: String,
 	deny: String,
 	code: String,
-	channel_id: Types.Long,
-	inviter_id: Types.Long,
+	channel_id: String,
+	inviter_id: String,
 	max_uses: Number,
 	uses: Number,
 	max_age: Number,
@@ -145,7 +145,7 @@ export const AuditLogChanges = {
 	mute: Boolean,
 	nick: String,
 	avatar_hash: String,
-	id: Types.Long,
+	id: String,
 	type: Number,
 	enable_emoticons: Boolean,
 	expire_behavior: Number,
@@ -154,17 +154,17 @@ export const AuditLogChanges = {
 };
 
 export const AuditLogSchema = new Schema({
-	target_id: Types.Long,
-	user_id: { type: Types.Long, required: true },
-	id: { type: Types.Long, required: true },
+	target_id: String,
+	user_id: { type: String, required: true },
+	id: { type: String, required: true },
 	action_type: { type: Number, required: true },
 	options: {
 		delete_member_days: String,
 		members_removed: String,
-		channel_id: Types.Long,
-		messaged_id: Types.Long,
+		channel_id: String,
+		messaged_id: String,
 		count: String,
-		id: Types.Long,
+		id: String,
 		type: String,
 		role_name: String,
 	},
diff --git a/src/models/Ban.ts b/src/models/Ban.ts
index 8fc3b124..27893029 100644
--- a/src/models/Ban.ts
+++ b/src/models/Ban.ts
@@ -2,17 +2,17 @@ import { Schema, model, Types, Document } from "mongoose";
 import db from "../util/Database";
 
 export interface Ban extends Document {
-	user_id: bigint;
-	guild_id: bigint;
-	executor_id: bigint;
+	user_id: string;
+	guild_id: string;
+	executor_id: string;
 	ip: string;
 	reason?: string;
 }
 
 export const BanSchema = new Schema({
-	user_id: { type: Types.Long, required: true },
-	guild_id: { type: Types.Long, required: true },
-	executor_id: { type: Types.Long, required: true },
+	user_id: { type: String, required: true },
+	guild_id: { type: String, required: true },
+	executor_id: { type: String, required: true },
 	reason: String,
 	ip: String, // ? Should we store this in here, or in the UserModel?
 });
diff --git a/src/models/Channel.ts b/src/models/Channel.ts
index bf03c939..82ad2999 100644
--- a/src/models/Channel.ts
+++ b/src/models/Channel.ts
@@ -4,20 +4,20 @@ import db from "../util/Database";
 export interface AnyChannel extends Channel, DMChannel, TextChannel, VoiceChannel {}
 
 export interface ChannelDocument extends Document, AnyChannel {
-	id: bigint;
+	id: string;
 }
 
 export const ChannelSchema = new Schema({
-	id: Types.Long,
+	id: String,
 	created_at: { type: Schema.Types.Date, required: true },
 	name: { type: String, required: true },
 	type: { type: Number, required: true },
-	guild_id: Types.Long,
-	owner_id: Types.Long,
-	parent_id: Types.Long,
-	recipients: [Types.Long],
+	guild_id: String,
+	owner_id: String,
+	parent_id: String,
+	recipients: [String],
 	position: Number,
-	last_message_id: Types.Long,
+	last_message_id: String,
 	last_pin_timestamp: Date,
 	nsfw: Boolean,
 	rate_limit_per_user: Number,
@@ -26,7 +26,7 @@ export const ChannelSchema = new Schema({
 		{
 			allow: Types.Long,
 			deny: Types.Long,
-			id: Types.Long,
+			id: String,
 			type: Number,
 		},
 	],
@@ -36,28 +36,28 @@ export const ChannelSchema = new Schema({
 export const ChannelModel = db.model<ChannelDocument>("Channel", ChannelSchema, "channels");
 
 export interface Channel {
-	id: bigint;
+	id: string;
 	created_at: Date;
 	name: string;
 	type: number;
 }
 
 export interface TextBasedChannel {
-	last_message_id?: bigint;
+	last_message_id?: string;
 	last_pin_timestamp?: number;
 }
 
 export interface GuildChannel extends Channel {
-	guild_id: bigint;
+	guild_id: string;
 	position: number;
-	parent_id?: bigint;
+	parent_id?: string;
 	permission_overwrites: ChannelPermissionOverwrite[];
 }
 
 export interface ChannelPermissionOverwrite {
-	allow: bigint;
-	deny: bigint;
-	id: bigint;
+	allow: bigint; // for bitfields we use bigints
+	deny: bigint; // for bitfields we use bigints
+	id: string;
 	type: ChannelPermissionOverwriteType;
 }
 
@@ -75,8 +75,8 @@ export interface TextChannel extends GuildChannel, TextBasedChannel {
 }
 
 export interface DMChannel extends Channel, TextBasedChannel {
-	owner_id: bigint;
-	recipients: bigint[];
+	owner_id: string;
+	recipients: string[];
 }
 
 export enum ChannelType {
diff --git a/src/models/Emoji.ts b/src/models/Emoji.ts
index 530c2cc7..3e5cad53 100644
--- a/src/models/Emoji.ts
+++ b/src/models/Emoji.ts
@@ -2,27 +2,27 @@ import { Schema, model, Types, Document } from "mongoose";
 import db from "../util/Database";
 
 export interface Emoji extends Document {
-	id: bigint;
+	id: string;
 	animated: boolean;
 	available: boolean;
-	guild_id: bigint;
+	guild_id: string;
 	managed: boolean;
 	name: string;
 	require_colons: boolean;
 	url: string;
-	roles: bigint[]; // roles this emoji is whitelisted to
+	roles: string[]; // roles this emoji is whitelisted to (new discord feature?)
 }
 
 export const EmojiSchema = new Schema({
-	id: { type: Types.Long, required: true },
+	id: { type: String, required: true },
 	animated: Boolean,
 	available: Boolean,
-	guild_id: Types.Long,
+	guild_id: String,
 	managed: Boolean,
 	name: String,
 	require_colons: Boolean,
 	url: String,
-	roles: [Types.Long],
+	roles: [String],
 });
 
 // @ts-ignore
diff --git a/src/models/Event.ts b/src/models/Event.ts
index 40cbcb20..9a5b5283 100644
--- a/src/models/Event.ts
+++ b/src/models/Event.ts
@@ -1,7 +1,7 @@
-import { ConnectedAccount, User, UserSettings } from "./User";
+import { ConnectedAccount, PublicUser, User, UserSettings } from "./User";
 import { DMChannel, Channel } from "./Channel";
 import { Guild } from "./Guild";
-import { PublicMember, UserGuildSettings } from "./Member";
+import { Member, PublicMember, UserGuildSettings } from "./Member";
 import { Emoji } from "./Emoji";
 import { Presence } from "./Activity";
 import { Role } from "./Role";
@@ -14,9 +14,9 @@ import { Schema, model, Types, Document } from "mongoose";
 import db from "../util/Database";
 
 export interface Event {
-	guild_id?: bigint;
-	user_id?: bigint;
-	channel_id?: bigint;
+	guild_id?: string;
+	user_id?: string;
+	channel_id?: string;
 	created_at?: Date;
 	event: EVENT;
 	data?: any;
@@ -25,9 +25,9 @@ export interface Event {
 export interface EventDocument extends Event, Document {}
 
 export const EventSchema = new Schema({
-	guild_id: Types.Long,
-	user_id: Types.Long,
-	channel_id: Types.Long,
+	guild_id: String,
+	user_id: String,
+	channel_id: String,
 	created_at: { type: Date, required: true },
 	event: { type: String, required: true },
 	data: Object,
@@ -44,60 +44,78 @@ export interface InvalidatedEvent extends Event {
 
 // ! END Custom Events that shouldn't get sent to the client but processed by the server
 
-export interface ReadyEvent extends Event {
-	event: "READY";
-	data: {
-		v: number;
-		user: Omit<User, "guilds" | "user_settings" | "valid_tokens_since" | "connected_accounts" | "relationships">;
-		private_channels: DMChannel[]; // this will be empty for bots
-		session_id: string; // resuming
-		guilds: Guild[];
-		analytics_token?: string;
-		connected_accounts?: ConnectedAccount[];
-		consents?: {
-			personalization?: {
-				consented?: boolean;
-			};
-		};
-		country_code?: string; // e.g. DE
-		friend_suggestion_count?: number;
-		geo_ordered_rtc_regions?: string[]; // ["europe","russie","india","us-east","us-central"]
-		experiments?: [number, number, number, number, number][];
-		guild_experiments?: [
-			// ? what are guild_experiments?
-			// this is the structure of it:
-			number,
-			null,
-			number,
-			[[number, { e: number; s: number }[]]],
-			[number, [[number, [number, number]]]],
-			{ b: number; k: bigint[] }[]
-		][];
-		guild_join_requests?: []; // ? what is this? this is new
-		shard?: [number, number];
-		user_settings?: UserSettings;
-		relationships?: [];
-		user_guild_settings?: {
-			entries: UserGuildSettings[];
-			version: number;
-			partial: boolean;
-		};
-		application?: {
-			id: bigint;
-			flags: bigint;
+export interface ReadyEventData {
+	v: number;
+	user: PublicUser & {
+		mobile: boolean;
+		desktop: boolean;
+		email: string;
+		flags: bigint;
+		mfa_enabled: boolean;
+		nsfw_allowed: boolean;
+		phone: string;
+		premium: boolean;
+		premium_type: number;
+		verified: boolean;
+		bot: boolean;
+	};
+	private_channels: DMChannel[]; // this will be empty for bots
+	session_id: string; // resuming
+	guilds: Guild[];
+	analytics_token?: string;
+	connected_accounts?: ConnectedAccount[];
+	consents?: {
+		personalization?: {
+			consented?: boolean;
 		};
-
-		merged_members?: PublicMember[][]; // every guild member object for the current user
-		// probably all users who the user is in contact with
-		users?: {
-			avatar?: string;
-			discriminator: string;
-			id: bigint;
-			username: string;
-			bot: boolean;
-			public_flags: bigint;
-		}[];
 	};
+	country_code?: string; // e.g. DE
+	friend_suggestion_count?: number;
+	geo_ordered_rtc_regions?: string[]; // ["europe","russie","india","us-east","us-central"]
+	experiments?: [number, number, number, number, number][];
+	guild_experiments?: [
+		// ? what are guild_experiments?
+		// this is the structure of it:
+		number,
+		null,
+		number,
+		[[number, { e: number; s: number }[]]],
+		[number, [[number, [number, number]]]],
+		{ b: number; k: bigint[] }[]
+	][];
+	guild_join_requests?: []; // ? what is this? this is new
+	shard?: [number, number];
+	user_settings?: UserSettings;
+	relationships?: []; // TODO
+	read_state: {
+		entries: []; // TODO
+		partial: boolean;
+		version: number;
+	};
+	user_guild_settings?: {
+		entries: UserGuildSettings[];
+		version: number;
+		partial: boolean;
+	};
+	application?: {
+		id: string;
+		flags: bigint;
+	};
+	merged_members?: Omit<Member, "settings" | "user">[][];
+	// probably all users who the user is in contact with
+	users?: {
+		avatar?: string;
+		discriminator: string;
+		id: string;
+		username: string;
+		bot: boolean;
+		public_flags: bigint;
+	}[];
+}
+
+export interface ReadyEvent extends Event {
+	event: "READY";
+	data: ReadyEventData;
 }
 
 export interface ChannelCreateEvent extends Event {
@@ -118,8 +136,8 @@ export interface ChannelDeleteEvent extends Event {
 export interface ChannelPinsUpdateEvent extends Event {
 	event: "CHANNEL_PINS_UPDATE";
 	data: {
-		guild_id?: bigint;
-		channel_id: bigint;
+		guild_id?: string;
+		channel_id: string;
 		last_pin_timestamp: number;
 	};
 }
@@ -137,7 +155,7 @@ export interface GuildUpdateEvent extends Event {
 export interface GuildDeleteEvent extends Event {
 	event: "GUILD_DELETE";
 	data: {
-		id: bigint;
+		id: string;
 		unavailable?: boolean;
 	};
 }
@@ -145,7 +163,7 @@ export interface GuildDeleteEvent extends Event {
 export interface GuildBanAddEvent extends Event {
 	event: "GUILD_BAN_ADD";
 	data: {
-		guild_id: bigint;
+		guild_id: string;
 		user: User;
 	};
 }
@@ -153,7 +171,7 @@ export interface GuildBanAddEvent extends Event {
 export interface GuildBanRemoveEvent extends Event {
 	event: "GUILD_BAN_REMOVE";
 	data: {
-		guild_id: bigint;
+		guild_id: string;
 		user: User;
 	};
 }
@@ -161,7 +179,7 @@ export interface GuildBanRemoveEvent extends Event {
 export interface GuildEmojiUpdateEvent extends Event {
 	event: "GUILD_EMOJI_UPDATE";
 	data: {
-		guild_id: bigint;
+		guild_id: string;
 		emojis: Emoji[];
 	};
 }
@@ -169,21 +187,21 @@ export interface GuildEmojiUpdateEvent extends Event {
 export interface GuildIntegrationUpdateEvent extends Event {
 	event: "GUILD_INTEGRATIONS_UPDATE";
 	data: {
-		guild_id: bigint;
+		guild_id: string;
 	};
 }
 
 export interface GuildMemberAddEvent extends Event {
 	event: "GUILD_MEMBER_ADD";
 	data: PublicMember & {
-		guild_id: bigint;
+		guild_id: string;
 	};
 }
 
 export interface GuildMemberRemoveEvent extends Event {
 	event: "GUILD_MEMBER_REMOVE";
 	data: {
-		guild_id: bigint;
+		guild_id: string;
 		user: User;
 	};
 }
@@ -191,8 +209,8 @@ export interface GuildMemberRemoveEvent extends Event {
 export interface GuildMemberUpdateEvent extends Event {
 	event: "GUILD_MEMBER_UPDATE";
 	data: {
-		guild_id: bigint;
-		roles: bigint[];
+		guild_id: string;
+		roles: string[];
 		user: User;
 		nick?: string;
 		joined_at: Date;
@@ -204,11 +222,11 @@ export interface GuildMemberUpdateEvent extends Event {
 export interface GuildMembersChunkEvent extends Event {
 	event: "GUILD_MEMBERS_CHUNK";
 	data: {
-		guild_id: bigint;
+		guild_id: string;
 		members: PublicMember[];
 		chunk_index: number;
 		chunk_count: number;
-		not_found: bigint[];
+		not_found: string[];
 		presences: Presence[];
 		nonce?: string;
 	};
@@ -217,7 +235,7 @@ export interface GuildMembersChunkEvent extends Event {
 export interface GuildRoleCreateEvent extends Event {
 	event: "GUILD_ROLE_CREATE";
 	data: {
-		guild_id: bigint;
+		guild_id: string;
 		role: Role;
 	};
 }
@@ -225,7 +243,7 @@ export interface GuildRoleCreateEvent extends Event {
 export interface GuildRoleUpdateEvent extends Event {
 	event: "GUILD_ROLE_UPDATE";
 	data: {
-		guild_id: bigint;
+		guild_id: string;
 		role: Role;
 	};
 }
@@ -233,31 +251,31 @@ export interface GuildRoleUpdateEvent extends Event {
 export interface GuildRoleDeleteEvent extends Event {
 	event: "GUILD_ROLE_DELETE";
 	data: {
-		guild_id: bigint;
-		role_id: bigint;
+		guild_id: string;
+		role_id: string;
 	};
 }
 
 export interface InviteCreateEvent extends Event {
 	event: "INVITE_CREATE";
 	data: Omit<Invite, "guild" | "channel"> & {
-		channel_id: bigint;
-		guild_id?: bigint;
+		channel_id: string;
+		guild_id?: string;
 	};
 }
 
 export interface InviteDeleteEvent extends Event {
 	event: "INVITE_DELETE";
 	data: {
-		channel_id: bigint;
-		guild_id?: bigint;
+		channel_id: string;
+		guild_id?: string;
 		code: string;
 	};
 }
 
 export type MessagePayload = Omit<Message, "author_id"> & {
-	channel_id: bigint;
-	guild_id?: bigint;
+	channel_id: string;
+	guild_id?: string;
 	author: User;
 	member: PublicMember;
 	mentions: (User & { member: PublicMember })[];
@@ -276,28 +294,28 @@ export interface MessageUpdateEvent extends Event {
 export interface MessageDeleteEvent extends Event {
 	event: "MESSAGE_DELETE";
 	data: {
-		id: bigint;
-		channel_id: bigint;
-		guild_id?: bigint;
+		id: string;
+		channel_id: string;
+		guild_id?: string;
 	};
 }
 
 export interface MessageDeleteBulkEvent extends Event {
 	event: "MESSAGE_DELETE_BULK";
 	data: {
-		ids: bigint[];
-		channel_id: bigint;
-		guild_id?: bigint;
+		ids: string[];
+		channel_id: string;
+		guild_id?: string;
 	};
 }
 
 export interface MessageReactionAddEvent extends Event {
 	event: "MESSAGE_REACTION_ADD";
 	data: {
-		user_id: bigint;
-		channel_id: bigint;
-		message_id: bigint;
-		guild_id?: bigint;
+		user_id: string;
+		channel_id: string;
+		message_id: string;
+		guild_id?: string;
 		member?: PublicMember;
 		emoji: PartialEmoji;
 	};
@@ -306,10 +324,10 @@ export interface MessageReactionAddEvent extends Event {
 export interface MessageReactionRemoveEvent extends Event {
 	event: "MESSAGE_REACTION_REMOVE";
 	data: {
-		user_id: bigint;
-		channel_id: bigint;
-		message_id: bigint;
-		guild_id?: bigint;
+		user_id: string;
+		channel_id: string;
+		message_id: string;
+		guild_id?: string;
 		emoji: PartialEmoji;
 	};
 }
@@ -317,18 +335,18 @@ export interface MessageReactionRemoveEvent extends Event {
 export interface MessageReactionRemoveAllEvent extends Event {
 	event: "MESSAGE_REACTION_REMOVE_ALL";
 	data: {
-		channel_id: bigint;
-		message_id: bigint;
-		guild_id?: bigint;
+		channel_id: string;
+		message_id: string;
+		guild_id?: string;
 	};
 }
 
 export interface MessageReactionRemoveEmojiEvent extends Event {
 	event: "MESSAGE_REACTION_REMOVE_EMOJI";
 	data: {
-		channel_id: bigint;
-		message_id: bigint;
-		guild_id?: bigint;
+		channel_id: string;
+		message_id: string;
+		guild_id?: string;
 		emoji: PartialEmoji;
 	};
 }
@@ -341,10 +359,10 @@ export interface PresenceUpdateEvent extends Event {
 export interface TypingStartEvent extends Event {
 	event: "TYPING_START";
 	data: {
-		channel_id: bigint;
-		user_id: bigint;
+		channel_id: string;
+		user_id: string;
 		timestamp: number;
-		guild_id?: bigint;
+		guild_id?: string;
 		member?: PublicMember;
 	};
 }
@@ -365,7 +383,7 @@ export interface VoiceServerUpdateEvent extends Event {
 	event: "VOICE_SERVER_UPDATE";
 	data: {
 		token: string;
-		guild_id: bigint;
+		guild_id: string;
 		endpoint: string;
 	};
 }
@@ -373,13 +391,13 @@ export interface VoiceServerUpdateEvent extends Event {
 export interface WebhooksUpdateEvent extends Event {
 	event: "WEBHOOKS_UPDATE";
 	data: {
-		guild_id: bigint;
-		channel_id: bigint;
+		guild_id: string;
+		channel_id: string;
 	};
 }
 
 export type ApplicationCommandPayload = ApplicationCommand & {
-	guild_id: bigint;
+	guild_id: string;
 };
 
 export interface ApplicationCommandCreateEvent extends Event {
@@ -404,6 +422,49 @@ export interface InteractionCreateEvent extends Event {
 
 // located in collection events
 
+export enum EVENTEnum {
+	Ready = "READY",
+	ChannelCreate = "CHANNEL_CREATE",
+	ChannelUpdate = "CHANNEL_UPDATE",
+	ChannelDelete = "CHANNEL_DELETE",
+	ChannelPinsUpdate = "CHANNEL_PINS_UPDATE",
+	GuildCreate = "GUILD_CREATE",
+	GuildUpdate = "GUILD_UPDATE",
+	GuildDelete = "GUILD_DELETE",
+	GuildBanAdd = "GUILD_BAN_ADD",
+	GuildBanRemove = "GUILD_BAN_REMOVE",
+	GuildEmojUpdate = "GUILD_EMOJI_UPDATE",
+	GuildIntegrationsUpdate = "GUILD_INTEGRATIONS_UPDATE",
+	GuildMemberAdd = "GUILD_MEMBER_ADD",
+	GuildMemberRempve = "GUILD_MEMBER_REMOVE",
+	GuildMemberUpdate = "GUILD_MEMBER_UPDATE",
+	GuildMemberSpeaking = "GUILD_MEMBER_SPEAKING",
+	GuildMembersChunk = "GUILD_MEMBERS_CHUNK",
+	GuildRoleCreate = "GUILD_ROLE_CREATE",
+	GuildRoleDelete = "GUILD_ROLE_DELETE",
+	GuildRoleUpdate = "GUILD_ROLE_UPDATE",
+	InviteCreate = "INVITE_CREATE",
+	InviteDelete = "INVITE_DELETE",
+	MessageCreate = "MESSAGE_CREATE",
+	MessageUpdate = "MESSAGE_UPDATE",
+	MessageDelete = "MESSAGE_DELETE",
+	MessageDeleteBulk = "MESSAGE_DELETE_BULK",
+	MessageReactionAdd = "MESSAGE_REACTION_ADD",
+	MessageReactionRemove = "MESSAGE_REACTION_REMOVE",
+	MessageReactionRemoveAll = "MESSAGE_REACTION_REMOVE_ALL",
+	MessageReactionRemoveEmoji = "MESSAGE_REACTION_REMOVE_EMOJI",
+	PresenceUpdate = "PRESENCE_UPDATE",
+	TypingStart = "TYPING_START",
+	UserUpdate = "USER_UPDATE",
+	WebhooksUpdate = "WEBHOOKS_UPDATE",
+	InteractionCreate = "INTERACTION_CREATE",
+	VoiceStateUpdate = "VOICE_STATE_UPDATE",
+	VoiceServerUpdate = "VOICE_SERVER_UPDATE",
+	ApplicationCommandCreate = "APPLICATION_COMMAND_CREATE",
+	ApplicationCommandUpdate = "APPLICATION_COMMAND_UPDATE",
+	ApplicationCommandDelete = "APPLICATION_COMMAND_DELETE",
+}
+
 export type EVENT =
 	| "READY"
 	| "CHANNEL_CREATE"
diff --git a/src/models/Guild.ts b/src/models/Guild.ts
index b25be7aa..819ac840 100644
--- a/src/models/Guild.ts
+++ b/src/models/Guild.ts
@@ -1,15 +1,19 @@
 import { Schema, model, Types, Document } from "mongoose";
 import db from "../util/Database";
+import { ChannelModel } from "./Channel";
+import { EmojiModel } from "./Emoji";
+import { MemberModel } from "./Member";
+import { RoleModel } from "./Role";
 
 export interface GuildDocument extends Document, Guild {
-	id: bigint;
+	id: string;
 }
 
 export interface Guild {
-	id: bigint;
-	afk_channel_id?: bigint;
+	id: string;
+	afk_channel_id?: string;
 	afk_timeout?: number;
-	application_id?: bigint;
+	application_id?: string;
 	banner?: string;
 	default_message_notifications?: number;
 	description?: string;
@@ -30,29 +34,29 @@ export interface Guild {
 	// voice_states: []; // * voice_states are stored in a seperate collection
 	mfa_level?: number;
 	name: string;
-	owner_id: bigint;
+	owner_id: string;
 	preferred_locale?: string; // only community guilds can choose this
 	premium_subscription_count?: number;
 	premium_tier?: number; // nitro boost level
-	public_updates_channel_id?: bigint;
+	public_updates_channel_id?: string;
 	region?: string;
-	rules_channel_id?: bigint;
+	rules_channel_id?: string;
 	splash?: string;
 	system_channel_flags?: number;
-	system_channel_id?: bigint;
+	system_channel_id?: string;
 	unavailable?: boolean;
 	vanity_url_code?: string;
 	verification_level?: number;
 	welcome_screen: []; // welcome splash screen if a user joins guild
-	widget_channel_id?: bigint;
+	widget_channel_id?: string;
 	widget_enabled?: boolean;
 }
 
 export const GuildSchema = new Schema({
-	id: { type: Types.Long, required: true },
-	afk_channel_id: Types.Long,
+	id: { type: String, required: true },
+	afk_channel_id: String,
 	afk_timeout: Number,
-	application_id: Types.Long,
+	application_id: String,
 	banner: String,
 	default_message_notifications: Number,
 	description: String,
@@ -68,26 +72,64 @@ export const GuildSchema = new Schema({
 	presence_count: Number,
 	mfa_level: Number,
 	name: { type: String, required: true },
-	owner_id: { type: Types.Long, required: true },
+	owner_id: { type: String, required: true },
 	preferred_locale: String,
 	premium_subscription_count: Number,
 	premium_tier: Number,
-	public_updates_channel_id: Types.Long,
+	public_updates_channel_id: String,
 	region: String,
-	rules_channel_id: Types.Long,
+	rules_channel_id: String,
 	splash: String,
 	system_channel_flags: Number,
-	system_channel_id: Types.Long,
+	system_channel_id: String,
 	unavailable: Boolean,
 	vanity_url_code: String,
 	verification_level: Number,
 	voice_states: { type: [Object], default: [] },
 	welcome_screen: { type: [Object], default: [] },
-	widget_channel_id: Types.Long,
+	widget_channel_id: String,
 	widget_enabled: Boolean,
 });
 
-// GuildSchema.virtual
+GuildSchema.virtual("channels", {
+	ref: ChannelModel,
+	localField: "id",
+	foreignField: "guild_id",
+	justOne: false,
+	autopopulate: true,
+});
+GuildSchema.virtual("roles", {
+	ref: RoleModel,
+	localField: "id",
+	foreignField: "guild_id",
+	justOne: false,
+	autopopulate: true,
+});
+
+// nested populate is needed for member users: https://gist.github.com/yangsu/5312204
+GuildSchema.virtual("members", {
+	ref: MemberModel,
+	localField: "id",
+	foreignField: "guild_id",
+	justOne: false,
+});
+
+GuildSchema.virtual("emojis", {
+	ref: EmojiModel,
+	localField: "id",
+	foreignField: "guild_id",
+	justOne: false,
+	autopopulate: true,
+});
+
+GuildSchema.virtual("joined_at", {
+	ref: MemberModel,
+	localField: "id",
+	foreignField: "guild_id",
+	justOne: true,
+}).get((member: any, virtual: any, doc: any) => {
+	return member.joined_at;
+});
 
 // @ts-ignore
 export const GuildModel = db.model<GuildDocument>("Guild", GuildSchema, "guilds");
diff --git a/src/models/Interaction.ts b/src/models/Interaction.ts
index 6f36c14a..764247a5 100644
--- a/src/models/Interaction.ts
+++ b/src/models/Interaction.ts
@@ -1,12 +1,12 @@
 import { AllowedMentions, Embed } from "./Message";
 
 export interface Interaction {
-	id: bigint;
+	id: string;
 	type: InteractionType;
 	data?: {};
-	guild_id: bigint;
-	channel_id: bigint;
-	member_id: bigint;
+	guild_id: string;
+	channel_id: string;
+	member_id: string;
 	token: string;
 	version: number;
 }
diff --git a/src/models/Invite.ts b/src/models/Invite.ts
index fc60b93c..590a4598 100644
--- a/src/models/Invite.ts
+++ b/src/models/Invite.ts
@@ -8,14 +8,13 @@ export interface Invite extends Document {
 	max_uses: number;
 	max_age: number;
 	created_at: Date;
-	guild_id: bigint;
-	channel_id: bigint;
-	inviter_id: bigint;
+	guild_id: string;
+	channel_id: string;
+	inviter_id: string;
 
-	//! What the fucking shit is this
-	target_user_id?: bigint;
+	// ? What the fucking shit is this
+	target_user_id?: string;
 	target_user_type?: number;
-	// !
 }
 
 export const InviteSchema = new Schema({
@@ -25,14 +24,13 @@ export const InviteSchema = new Schema({
 	max_uses: Number,
 	max_age: Number,
 	created_at: Date,
-	guild_id: Types.Long,
-	channel_id: Types.Long,
-	inviter_id: Types.Long,
+	guild_id: String,
+	channel_id: String,
+	inviter_id: String,
 
-	//! What the fucking shit is this
-	target_user_id: Types.Long,
+	// ? What the fucking shit is this
+	target_user_id: String,
 	target_user_type: Number,
-	// !
 });
 
 // @ts-ignore
diff --git a/src/models/Member.ts b/src/models/Member.ts
index 145b5df4..52151235 100644
--- a/src/models/Member.ts
+++ b/src/models/Member.ts
@@ -1,12 +1,24 @@
-import { PublicUser, User, UserModel } from "./User";
+import { PublicUser, PublicUserProjection, User, UserModel } from "./User";
 import { Schema, Types, Document } from "mongoose";
 import db from "../util/Database";
 
+export const PublicMemberProjection = {
+	id: true,
+	guild_id: true,
+	nick: true,
+	roles: true,
+	joined_at: true,
+	pending: true,
+	deaf: true,
+	mute: true,
+	premium_since: true,
+};
+
 export interface Member {
-	id: bigint;
-	guild_id: bigint;
+	id: string;
+	guild_id: string;
 	nick?: string;
-	roles: bigint[];
+	roles: string[];
 	joined_at: Date;
 	premium_since?: number;
 	deaf: boolean;
@@ -17,12 +29,12 @@ export interface Member {
 }
 
 export interface MemberDocument extends Member, Document {
-	id: bigint;
+	id: string;
 }
 
 export interface UserGuildSettings {
 	channel_overrides: {
-		channel_id: bigint;
+		channel_id: string;
 		message_notifications: number;
 		mute_config: MuteConfig;
 		muted: boolean;
@@ -47,10 +59,10 @@ const MuteConfig = {
 };
 
 export const MemberSchema = new Schema({
-	id: { type: Types.Long, required: true },
-	guild_id: Types.Long,
+	id: { type: String, required: true },
+	guild_id: String,
 	nick: String,
-	roles: [Types.Long],
+	roles: [String],
 	joined_at: Date,
 	premium_since: Number,
 	deaf: Boolean,
@@ -59,7 +71,7 @@ export const MemberSchema = new Schema({
 	settings: {
 		channel_overrides: [
 			{
-				channel_id: Types.Long,
+				channel_id: String,
 				message_notifications: Number,
 				mute_config: MuteConfig,
 				muted: Boolean,
@@ -80,6 +92,9 @@ MemberSchema.virtual("user", {
 	localField: "id",
 	foreignField: "id",
 	justOne: true,
+	autopopulate: {
+		select: PublicUserProjection,
+	},
 });
 
 // @ts-ignore
diff --git a/src/models/Message.ts b/src/models/Message.ts
index e80ec1f8..15ff57d3 100644
--- a/src/models/Message.ts
+++ b/src/models/Message.ts
@@ -1,24 +1,25 @@
 import { Schema, Types, Document } from "mongoose";
 import db from "../util/Database";
-import { UserModel } from "./User";
-import { MemberModel } from "./Member";
-import { RoleModel } from "./Role";
+import { PublicUser, PublicUserProjection, UserModel } from "./User";
+import { MemberModel, PublicMember, PublicMemberProjection } from "./Member";
+import { Role, RoleModel } from "./Role";
+import { Channel } from "./Channel";
 
 export interface Message {
-	id: bigint;
-	channel_id: bigint;
-	guild_id?: bigint;
-	author_id?: bigint;
-	webhook_id?: bigint;
-	application_id?: bigint;
+	id: string;
+	channel_id: string;
+	guild_id?: string;
+	author_id?: string;
+	webhook_id?: string;
+	application_id?: string;
 	content?: string;
 	timestamp: Date;
 	edited_timestamp?: Date;
 	tts?: boolean;
 	mention_everyone?: boolean;
-	mention_user_ids: bigint[];
-	mention_role_ids: bigint[];
-	mention_channels_ids: bigint[];
+	mention_user_ids: string[];
+	mention_role_ids: string[];
+	mention_channels_ids: string[];
 	attachments: Attachment[];
 	embeds: Embed[];
 	reactions: Reaction[];
@@ -32,14 +33,20 @@ export interface Message {
 	flags?: bigint;
 	stickers?: [];
 	message_reference?: {
-		message_id: bigint;
-		channel_id?: bigint;
-		guild_id?: bigint;
+		message_id: string;
+		channel_id?: string;
+		guild_id?: string;
 	};
+	// mongoose virtuals:
+	author?: PublicUser;
+	member?: PublicMember;
+	mentions?: PublicUser[];
+	mention_roles?: Role[];
+	mention_channels?: Channel[];
 }
 
 export interface MessageDocument extends Document, Message {
-	id: bigint;
+	id: string;
 }
 
 export enum MessageType {
@@ -63,7 +70,7 @@ export enum MessageType {
 }
 
 export interface Attachment {
-	id: bigint; // attachment id
+	id: string; // attachment id
 	filename: string; // name of file attached
 	size: number; // size of file in bytes
 	url: string; // source url of file
@@ -118,20 +125,20 @@ export interface Reaction {
 }
 
 export interface PartialEmoji {
-	id?: bigint;
+	id?: string;
 	name: string;
 	animated?: boolean;
 }
 
 export interface AllowedMentions {
 	parse?: ("users" | "roles" | "everyone")[];
-	roles?: bigint[];
-	users?: bigint[];
+	roles?: string[];
+	users?: string[];
 	replied_user?: boolean;
 }
 
 export const Attachment = {
-	id: Types.Long, // attachment id
+	id: String, // attachment id
 	filename: String, // name of file attached
 	size: Number, // size of file in bytes
 	url: String, // source url of file
@@ -150,7 +157,7 @@ export const EmbedImage = {
 const Reaction = {
 	count: Number,
 	emoji: {
-		id: Types.Long,
+		id: String,
 		name: String,
 		animated: Boolean,
 	},
@@ -191,20 +198,20 @@ export const Embed = {
 };
 
 export const MessageSchema = new Schema({
-	id: Types.Long,
-	channel_id: Types.Long,
-	author_id: Types.Long,
-	webhook_id: Types.Long,
-	guild_id: Types.Long,
-	application_id: Types.Long,
+	id: String,
+	channel_id: String,
+	author_id: String,
+	webhook_id: String,
+	guild_id: String,
+	application_id: String,
 	content: String,
 	timestamp: Date,
 	edited_timestamp: Date,
 	tts: Boolean,
 	mention_everyone: Boolean,
-	mention_user_ids: [Types.Long],
-	mention_role_ids: [Types.Long],
-	mention_channel_ids: [Types.Long],
+	mention_user_ids: [String],
+	mention_role_ids: [String],
+	mention_channel_ids: [String],
 	attachments: [Attachment],
 	embeds: [Embed],
 	reactions: [Reaction],
@@ -218,10 +225,18 @@ export const MessageSchema = new Schema({
 	flags: Types.Long,
 	stickers: [],
 	message_reference: {
-		message_id: Types.Long,
-		channel_id: Types.Long,
-		guild_id: Types.Long,
+		message_id: String,
+		channel_id: String,
+		guild_id: String,
 	},
+	// virtual:
+	// author: {
+	// 	ref: UserModel,
+	// 	localField: "author_id",
+	// 	foreignField: "id",
+	// 	justOne: true,
+	// 	autopopulate: { select: { id: true, user_data: false } },
+	// },
 });
 
 MessageSchema.virtual("author", {
@@ -229,6 +244,7 @@ MessageSchema.virtual("author", {
 	localField: "author_id",
 	foreignField: "id",
 	justOne: true,
+	autopopulate: { select: PublicUserProjection },
 });
 
 MessageSchema.virtual("member", {
@@ -242,23 +258,28 @@ MessageSchema.virtual("mentions", {
 	ref: UserModel,
 	localField: "mention_user_ids",
 	foreignField: "id",
-	justOne: true,
+	justOne: false,
+	autopopulate: { select: PublicUserProjection },
 });
 
 MessageSchema.virtual("mention_roles", {
 	ref: RoleModel,
 	localField: "mention_role_ids",
 	foreignField: "id",
-	justOne: true,
+	justOne: false,
+	autopopulate: true,
 });
 
 MessageSchema.virtual("mention_channels", {
 	ref: RoleModel,
-	localField: "mention_role_ids",
+	localField: "mention_channel_ids",
 	foreignField: "id",
-	justOne: true,
+	justOne: false,
+	autopopulate: { select: { id: true, guild_id: true, type: true, name: true } },
 });
 
+MessageSchema.set("removeResponse", ["mention_channel_ids", "mention_role_ids", "mention_user_ids", "author_id"]);
+
 // TODO: missing Application Model
 // MessageSchema.virtual("application", {
 // 	ref: Application,
diff --git a/src/models/Role.ts b/src/models/Role.ts
index fe716593..84ad55d0 100644
--- a/src/models/Role.ts
+++ b/src/models/Role.ts
@@ -2,8 +2,8 @@ import { Schema, model, Types, Document } from "mongoose";
 import db from "../util/Database";
 
 export interface Role {
-	id: bigint;
-	guild_id: bigint;
+	id: string;
+	guild_id: string;
 	color: number;
 	hoist: boolean;
 	managed: boolean;
@@ -12,17 +12,17 @@ export interface Role {
 	permissions: bigint;
 	position: number;
 	tags?: {
-		bot_id?: bigint;
+		bot_id?: string;
 	};
 }
 
 export interface RoleDocument extends Document, Role {
-	id: bigint;
+	id: string;
 }
 
 export const RoleSchema = new Schema({
-	id: Types.Long,
-	guild_id: Types.Long,
+	id: String,
+	guild_id: String,
 	color: Number,
 	hoist: Boolean,
 	managed: Boolean,
@@ -31,9 +31,10 @@ export const RoleSchema = new Schema({
 	permissions: Types.Long,
 	position: Number,
 	tags: {
-		bot_id: Types.Long,
+		bot_id: String,
 	},
 });
+RoleSchema.set("removeResponse", ["guild_id"]);
 
 // @ts-ignore
 export const RoleModel = db.model<RoleDocument>("Role", RoleSchema, "roles");
diff --git a/src/models/User.ts b/src/models/User.ts
index 971e8d20..1f01e837 100644
--- a/src/models/User.ts
+++ b/src/models/User.ts
@@ -3,12 +3,18 @@ import { ClientStatus, Status } from "./Status";
 import { Schema, Types, Document } from "mongoose";
 import db from "../util/Database";
 
+export const PublicUserProjection = {
+	username: true,
+	discriminator: true,
+	id: true,
+	public_flags: true,
+	avatar: true,
+};
 export interface User {
-	id: bigint;
+	id: string;
 	username: string; // username max length 32, min 2
 	discriminator: string; // #0001 4 digit long string from #0001 - #9999
 	avatar: string | null; // hash of the user avatar
-	fingerprints: string[]; // array of fingerprints -> used to prevent multiple accounts
 	phone?: string; // phone number of the user
 	desktop: boolean; // if the user has desktop app installed
 	mobile: boolean; // if the user has mobile app installed
@@ -16,7 +22,6 @@ export interface User {
 	premium_type: number; // nitro level
 	bot: boolean; // if user is bot
 	system: boolean; // shouldn't be used, the api sents this field type true, if the genetaed message comes from a system generated author
-	level: string; // organization permission level (owner, moderator, user)
 	nsfw_allowed: boolean; // if the user is older than 18 (resp. Config)
 	mfa_enabled: boolean; // if multi factor authentication is enabled
 	created_at: Date; // registration date
@@ -24,12 +29,9 @@ export interface User {
 	email?: string; // email of the user
 	flags: bigint; // UserFlags
 	public_flags: bigint;
-	hash: string; // hash of the password, salt is saved in password (bcrypt)
-	guilds: bigint[]; // array of guild ids the user is part of
-	valid_tokens_since: Date; // all tokens with a previous issue date are invalid
 	user_settings: UserSettings;
-	relationships: Relationship[];
-	connected_accounts: ConnectedAccount[];
+	guilds: string[]; // array of guild ids the user is part of
+	user_data: UserData;
 	presence: {
 		status: Status;
 		activities: Activity[];
@@ -37,12 +39,21 @@ export interface User {
 	};
 }
 
+// Privat user data:
+export interface UserData {
+	valid_tokens_since: Date; // all tokens with a previous issue date are invalid
+	relationships: Relationship[];
+	connected_accounts: ConnectedAccount[];
+	hash: string; // hash of the password, salt is saved in password (bcrypt)
+	fingerprints: string[]; // array of fingerprints -> used to prevent multiple accounts
+}
+
 export interface UserDocument extends User, Document {
-	id: bigint;
+	id: string;
 }
 
 export interface PublicUser {
-	id: bigint;
+	id: string;
 	discriminator: string;
 	username: string;
 	avatar?: string;
@@ -62,10 +73,10 @@ export interface ConnectedAccount {
 }
 
 export interface Relationship {
-	id: bigint;
+	id: string;
 	nickname?: string;
 	type: number;
-	user_id: bigint;
+	user_id: string;
 }
 
 export interface UserSettings {
@@ -76,7 +87,7 @@ export interface UserSettings {
 	contact_sync_enabled: boolean;
 	convert_emoticons: boolean;
 	custom_status: {
-		emoji_id: bigint | null;
+		emoji_id: string | null;
 		emoji_name: string | null;
 		expires_at: number | null;
 		text: string | null;
@@ -93,11 +104,11 @@ export interface UserSettings {
 	guild_folders: // every top guild is displayed as a "folder"
 	{
 		color: number;
-		guild_ids: bigint[];
+		guild_ids: string[];
 		id: number;
 		name: string;
 	}[];
-	guild_positions: bigint[]; // guild ids ordered by position
+	guild_positions: string[]; // guild ids ordered by position
 	inline_attachment_media: boolean;
 	inline_embed_media: boolean;
 	locale: string; // en_US
@@ -105,7 +116,7 @@ export interface UserSettings {
 	native_phone_integration_enabled: boolean;
 	render_embeds: boolean;
 	render_reactions: boolean;
-	restricted_guilds: bigint[];
+	restricted_guilds: string[];
 	show_current_game: boolean;
 	status: "online" | "offline" | "dnd" | "idle";
 	stream_notifications_enabled: boolean;
@@ -114,11 +125,10 @@ export interface UserSettings {
 }
 
 export const UserSchema = new Schema({
-	id: Types.Long,
+	id: String,
 	username: String,
 	discriminator: String,
 	avatar: String,
-	fingerprints: [String],
 	phone: String,
 	desktop: Boolean,
 	mobile: Boolean,
@@ -133,9 +143,33 @@ export const UserSchema = new Schema({
 	email: String,
 	flags: Types.Long, // TODO: automatically convert Types.Long to BitField of UserFlags
 	public_flags: Types.Long,
-	hash: String, // hash of the password, salt is saved in password (bcrypt)
-	guilds: [Types.Long], // array of guild ids the user is part of
-	valid_tokens_since: Date, // all tokens with a previous issue date are invalid
+	guilds: [String], // array of guild ids the user is part of
+	user_data: {
+		fingerprints: [String],
+		hash: String, // hash of the password, salt is saved in password (bcrypt)
+		valid_tokens_since: Date, // all tokens with a previous issue date are invalid
+		relationships: [
+			{
+				id: String,
+				nickname: String,
+				type: Number,
+				user_id: String,
+			},
+		],
+		connected_accounts: [
+			{
+				access_token: String,
+				friend_sync: Boolean,
+				id: String,
+				name: String,
+				revoked: Boolean,
+				show_activity: Boolean,
+				type: String,
+				verifie: Boolean,
+				visibility: Number,
+			},
+		],
+	},
 	user_settings: {
 		afk_timeout: Number,
 		allow_accessibility_detection: Boolean,
@@ -144,7 +178,7 @@ export const UserSchema = new Schema({
 		contact_sync_enabled: Boolean,
 		convert_emoticons: Boolean,
 		custom_status: {
-			emoji_id: Types.Long,
+			emoji_id: String,
 			emoji_name: String,
 			expires_at: Number,
 			text: String,
@@ -162,12 +196,12 @@ export const UserSchema = new Schema({
 		guild_folders: [
 			{
 				color: Number,
-				guild_ids: [Types.Long],
+				guild_ids: [String],
 				id: Number,
 				name: String,
 			},
 		],
-		guild_positions: [Types.Long], // guild ids ordered by position
+		guild_positions: [String], // guild ids ordered by position
 		inline_attachment_media: Boolean,
 		inline_embed_media: Boolean,
 		locale: String, // en_US
@@ -175,34 +209,14 @@ export const UserSchema = new Schema({
 		native_phone_integration_enabled: Boolean,
 		render_embeds: Boolean,
 		render_reactions: Boolean,
-		restricted_guilds: [Types.Long],
+		restricted_guilds: [String],
 		show_current_game: Boolean,
 		status: String,
 		stream_notifications_enabled: Boolean,
 		theme: String, // dark
 		timezone_offset: Number, // e.g -60,
 	},
-	relationships: [
-		{
-			id: Types.Long,
-			nickname: String,
-			type: Number,
-			user_id: Types.Long,
-		},
-	],
-	connected_accounts: [
-		{
-			access_token: String,
-			friend_sync: Boolean,
-			id: String,
-			name: String,
-			revoked: Boolean,
-			show_activity: Boolean,
-			type: String,
-			verifie: Boolean,
-			visibility: Number,
-		},
-	],
+
 	presence: {
 		status: String,
 		activities: [Activity],
diff --git a/src/models/VoiceState.ts b/src/models/VoiceState.ts
index 30439feb..c1f90edd 100644
--- a/src/models/VoiceState.ts
+++ b/src/models/VoiceState.ts
@@ -3,9 +3,9 @@ import { Schema, model, Types, Document } from "mongoose";
 import db from "../util/Database";
 
 export interface VoiceState extends Document {
-	guild_id?: bigint;
-	channel_id: bigint;
-	user_id: bigint;
+	guild_id?: string;
+	channel_id: string;
+	user_id: string;
 	session_id: string;
 	deaf: boolean;
 	mute: boolean;
@@ -17,9 +17,9 @@ export interface VoiceState extends Document {
 }
 
 export const VoiceSateSchema = new Schema({
-	guild_id: Types.Long,
-	channel_id: Types.Long,
-	user_id: Types.Long,
+	guild_id: String,
+	channel_id: String,
+	user_id: String,
 	session_id: String,
 	deaf: Boolean,
 	mute: Boolean,
diff --git a/src/models/index.ts b/src/models/index.ts
new file mode 100644
index 00000000..876e5984
--- /dev/null
+++ b/src/models/index.ts
@@ -0,0 +1,36 @@
+import mongoose from "mongoose";
+import { Schema } from "mongoose";
+import mongooseAutoPopulate from "mongoose-autopopulate";
+
+mongoose.plugin(mongooseAutoPopulate);
+
+mongoose.plugin((schema: Schema, opts: any) => {
+	schema.set("toObject", {
+		virtuals: true,
+		versionKey: false,
+		transform(doc: any, ret: any) {
+			delete ret._id;
+			delete ret.__v;
+			const props = schema.get("removeResponse") || [];
+			props.forEach((prop: string) => {
+				delete ret[prop];
+			});
+		},
+	});
+});
+
+export * from "./Ban";
+export * from "./Channel";
+export * from "./Emoji";
+export * from "./Guild";
+export * from "./Invite";
+export * from "./Member";
+export * from "./Role";
+export * from "./User";
+export * from "./Activity";
+export * from "./Application";
+export * from "./Interaction";
+export * from "./Message";
+export * from "./Status";
+export * from "./VoiceState";
+export * from "./Event";
diff --git a/src/util/Database.ts b/src/util/Database.ts
index 2304378c..5d9afab9 100644
--- a/src/util/Database.ts
+++ b/src/util/Database.ts
@@ -1,13 +1,26 @@
 import "./MongoBigInt";
-import mongoose, { Collection, Connection } from "mongoose";
+import mongoose, { Collection, Connection, LeanDocument } from "mongoose";
 import { ChangeStream, ChangeEvent, Long } from "mongodb";
 import EventEmitter from "events";
+import { Document } from "mongoose";
 const uri = process.env.MONGO_URL || "mongodb://localhost:27017/fosscord?readPreference=secondaryPreferred";
 
-const connection = mongoose.createConnection(uri, { autoIndex: true });
+console.log(`[DB] connect: ${uri}`);
+
+const connection = mongoose.createConnection(uri, { autoIndex: true, useNewUrlParser: true, useUnifiedTopology: true });
 
 export default <Connection>connection;
 
+function transform<T>(document: T) {
+	// @ts-ignore
+	return document.toObject({ virtuals: true });
+}
+
+export function toObject<T>(document: T): LeanDocument<T> {
+	// @ts-ignore
+	return Array.isArray(document) ? document.map((x) => transform<T>(x)) : transform(document);
+}
+
 export interface MongooseCache {
 	on(event: "delete", listener: (id: string) => void): this;
 	on(event: "change", listener: (data: any) => void): this;
@@ -29,7 +42,8 @@ export class MongooseCache extends EventEmitter {
 		super();
 	}
 
-	async init() {
+	init = async () => {
+		// @ts-ignore
 		this.stream = this.collection.watch(this.pipeline, { fullDocument: "updateLookup" });
 
 		this.stream.on("change", this.change);
@@ -40,9 +54,9 @@ export class MongooseCache extends EventEmitter {
 			const arr = await this.collection.aggregate(this.pipeline).toArray();
 			this.data = arr.length ? arr[0] : arr;
 		}
-	}
+	};
 
-	convertResult(obj: any) {
+	convertResult = (obj: any) => {
 		if (obj instanceof Long) return BigInt(obj.toString());
 		if (typeof obj === "object") {
 			Object.keys(obj).forEach((key) => {
@@ -51,40 +65,44 @@ export class MongooseCache extends EventEmitter {
 		}
 
 		return obj;
-	}
+	};
 
 	change = (doc: ChangeEvent) => {
-		// @ts-ignore
-		if (doc.fullDocument) {
+		try {
 			// @ts-ignore
-			if (!this.opts.onlyEvents) this.data = doc.fullDocument;
-		}
+			if (doc.fullDocument) {
+				// @ts-ignore
+				if (!this.opts.onlyEvents) this.data = doc.fullDocument;
+			}
 
-		switch (doc.operationType) {
-			case "dropDatabase":
-				return this.destroy();
-			case "drop":
-				return this.destroy();
-			case "delete":
-				return this.emit("delete", doc.documentKey._id.toHexString());
-			case "insert":
-				return this.emit("insert", doc.fullDocument);
-			case "update":
-			case "replace":
-				return this.emit("change", doc.fullDocument);
-			case "invalidate":
-				return this.destroy();
-			default:
-				return;
+			switch (doc.operationType) {
+				case "dropDatabase":
+					return this.destroy();
+				case "drop":
+					return this.destroy();
+				case "delete":
+					return this.emit("delete", doc.documentKey._id.toHexString());
+				case "insert":
+					return this.emit("insert", doc.fullDocument);
+				case "update":
+				case "replace":
+					return this.emit("change", doc.fullDocument);
+				case "invalidate":
+					return this.destroy();
+				default:
+					return;
+			}
+		} catch (error) {
+			this.emit("error", error);
 		}
 	};
 
-	destroy() {
-		this.stream.off("change", this.change);
+	destroy = () => {
+		this.stream?.off("change", this.change);
 		this.emit("close");
 
 		if (this.stream.isClosed()) return;
 
 		return this.stream.close();
-	}
+	};
 }
diff --git a/src/util/Permissions.ts b/src/util/Permissions.ts
index 88a54954..c7a41594 100644
--- a/src/util/Permissions.ts
+++ b/src/util/Permissions.ts
@@ -131,7 +131,7 @@ export class Permissions extends BitField {
 		guild,
 		channel,
 	}: {
-		user: { id: bigint; roles: bigint[] };
+		user: { id: string; roles: string[] };
 		guild: { roles: Role[] };
 		channel?: {
 			overwrites?: ChannelPermissionOverwrite[];
@@ -154,22 +154,24 @@ export class Permissions extends BitField {
 }
 
 export async function getPermission(
-	user_id: bigint,
-	guild_id: bigint,
-	channel_id?: bigint,
-	cache?: { channel?: ChannelDocument | null; member?: MemberDocument | null }
+	user_id: string,
+	guild_id: string,
+	channel_id?: string,
+	cache?: { channel?: ChannelDocument | null; member?: MemberDocument | null; guild?: GuildDocument | null }
 ) {
-	var { channel, member } = cache || {};
+	var { channel, member, guild } = cache || {};
 
-	const guild = await GuildModel.findOne({ id: guild_id }, { owner_id: true }).exec();
+	if (!guild) guild = await GuildModel.findOne({ id: guild_id }, { owner_id: true }).exec();
 	if (!guild) throw new Error("Guild not found");
 	if (guild.owner_id === user_id) return new Permissions(Permissions.FLAGS.ADMINISTRATOR);
 
-	member = await MemberModel.findOne({ guild_id, id: user_id }, "roles").exec();
+	if (!member) member = await MemberModel.findOne({ guild_id, id: user_id }, "roles").exec();
 	if (!member) throw new Error("Member not found");
 
-	var roles = await RoleModel.find({ guild_id, id: { $in: member.roles } }).exec();
-	if (channel_id) {
+	var roles = await RoleModel.find({ guild_id, id: { $in: member.roles } })
+		.lean()
+		.exec();
+	if (channel_id && !channel) {
 		channel = await ChannelModel.findOne({ id: channel_id }, "permission_overwrites").exec();
 	}
 
diff --git a/src/util/Snowflake.ts b/src/util/Snowflake.ts
index 9e94bbd9..1ccae43c 100644
--- a/src/util/Snowflake.ts
+++ b/src/util/Snowflake.ts
@@ -87,7 +87,7 @@ export class Snowflake {
 		var worker = Snowflake.workerId << 17n;
 		var process = Snowflake.processId << 12n;
 		var increment = Snowflake.INCREMENT++;
-		return time | worker | process | increment;
+		return (time | worker | process | increment).toString();
 	}
 
 	/**
diff --git a/src/util/index.ts b/src/util/index.ts
new file mode 100644
index 00000000..b0c7fe62
--- /dev/null
+++ b/src/util/index.ts
@@ -0,0 +1,7 @@
+export * from "./String";
+export * from "./BitField";
+export * from "./Intents";
+export * from "./MessageFlags";
+export * from "./Permissions";
+export * from "./Snowflake";
+export * from "./UserFlags";