summary refs log tree commit diff
path: root/rtc/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'rtc/src/util')
-rw-r--r--rtc/src/util/BitField.ts143
-rw-r--r--rtc/src/util/Config.ts284
-rw-r--r--rtc/src/util/Constants.ts28
-rw-r--r--rtc/src/util/Database.ts151
-rw-r--r--rtc/src/util/Intents.ts21
-rw-r--r--rtc/src/util/MessageFlags.ts14
-rw-r--r--rtc/src/util/MongoBigInt.ts82
-rw-r--r--rtc/src/util/Permissions.ts262
-rw-r--r--rtc/src/util/RabbitMQ.ts18
-rw-r--r--rtc/src/util/Regex.ts3
-rw-r--r--rtc/src/util/Snowflake.ts127
-rw-r--r--rtc/src/util/String.ts7
-rw-r--r--rtc/src/util/UserFlags.ts22
-rw-r--r--rtc/src/util/checkToken.ts24
-rw-r--r--rtc/src/util/index.ts9
-rw-r--r--rtc/src/util/toBigInt.ts3
16 files changed, 0 insertions, 1198 deletions
diff --git a/rtc/src/util/BitField.ts b/rtc/src/util/BitField.ts
deleted file mode 100644
index 728dc632..00000000
--- a/rtc/src/util/BitField.ts
+++ /dev/null
@@ -1,143 +0,0 @@
-"use strict";
-
-// https://github.com/discordjs/discord.js/blob/master/src/util/BitField.js
-// Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah
-
-export type BitFieldResolvable = number | BigInt | BitField | string | BitFieldResolvable[];
-
-/**
- * Data structure that makes it easy to interact with a bitfield.
- */
-export class BitField {
-	public bitfield: bigint = BigInt(0);
-
-	public static FLAGS: Record<string, bigint> = {};
-
-	constructor(bits: BitFieldResolvable = 0) {
-		this.bitfield = BitField.resolve.call(this, bits);
-	}
-
-	/**
-	 * Checks whether the bitfield has a bit, or any of multiple bits.
-	 */
-	any(bit: BitFieldResolvable): boolean {
-		return (this.bitfield & BitField.resolve.call(this, bit)) !== 0n;
-	}
-
-	/**
-	 * Checks if this bitfield equals another
-	 */
-	equals(bit: BitFieldResolvable): boolean {
-		return this.bitfield === BitField.resolve.call(this, bit);
-	}
-
-	/**
-	 * Checks whether the bitfield has a bit, or multiple bits.
-	 */
-	has(bit: BitFieldResolvable): boolean {
-		if (Array.isArray(bit)) return bit.every((p) => this.has(p));
-		const BIT = BitField.resolve.call(this, bit);
-		return (this.bitfield & BIT) === BIT;
-	}
-
-	/**
-	 * Gets all given bits that are missing from the bitfield.
-	 */
-	missing(bits: BitFieldResolvable) {
-		if (!Array.isArray(bits)) bits = new BitField(bits).toArray();
-		return bits.filter((p) => !this.has(p));
-	}
-
-	/**
-	 * Freezes these bits, making them immutable.
-	 */
-	freeze(): Readonly<BitField> {
-		return Object.freeze(this);
-	}
-
-	/**
-	 * Adds bits to these ones.
-	 * @param {...BitFieldResolvable} [bits] Bits to add
-	 * @returns {BitField} These bits or new BitField if the instance is frozen.
-	 */
-	add(...bits: BitFieldResolvable[]): BitField {
-		let total = 0n;
-		for (const bit of bits) {
-			total |= BitField.resolve.call(this, bit);
-		}
-		if (Object.isFrozen(this)) return new BitField(this.bitfield | total);
-		this.bitfield |= total;
-		return this;
-	}
-
-	/**
-	 * Removes bits from these.
-	 * @param {...BitFieldResolvable} [bits] Bits to remove
-	 */
-	remove(...bits: BitFieldResolvable[]) {
-		let total = 0n;
-		for (const bit of bits) {
-			total |= BitField.resolve.call(this, bit);
-		}
-		if (Object.isFrozen(this)) return new BitField(this.bitfield & ~total);
-		this.bitfield &= ~total;
-		return this;
-	}
-
-	/**
-	 * Gets an object mapping field names to a {@link boolean} indicating whether the
-	 * bit is available.
-	 * @param {...*} hasParams Additional parameters for the has method, if any
-	 */
-	serialize() {
-		const serialized: Record<string, boolean> = {};
-		for (const [flag, bit] of Object.entries(BitField.FLAGS)) serialized[flag] = this.has(bit);
-		return serialized;
-	}
-
-	/**
-	 * Gets an {@link Array} of bitfield names based on the bits available.
-	 */
-	toArray(): string[] {
-		return Object.keys(BitField.FLAGS).filter((bit) => this.has(bit));
-	}
-
-	toJSON() {
-		return this.bitfield;
-	}
-
-	valueOf() {
-		return this.bitfield;
-	}
-
-	*[Symbol.iterator]() {
-		yield* this.toArray();
-	}
-
-	/**
-	 * Data that can be resolved to give a bitfield. This can be:
-	 * * A bit number (this can be a number literal or a value taken from {@link BitField.FLAGS})
-	 * * An instance of BitField
-	 * * An Array of BitFieldResolvable
-	 * @typedef {number|BitField|BitFieldResolvable[]} BitFieldResolvable
-	 */
-
-	/**
-	 * Resolves bitfields to their numeric form.
-	 * @param {BitFieldResolvable} [bit=0] - bit(s) to resolve
-	 * @returns {number}
-	 */
-	static resolve(bit: BitFieldResolvable = 0n): bigint {
-		// @ts-ignore
-		const FLAGS = this.FLAGS || this.constructor?.FLAGS;
-		if ((typeof bit === "number" || typeof bit === "bigint") && bit >= 0n) return BigInt(bit);
-		if (bit instanceof BitField) return bit.bitfield;
-		if (Array.isArray(bit)) {
-			// @ts-ignore
-			const resolve = this.constructor?.resolve || this.resolve;
-			return bit.map((p) => resolve.call(this, p)).reduce((prev, p) => BigInt(prev) | BigInt(p), 0n);
-		}
-		if (typeof bit === "string" && typeof FLAGS[bit] !== "undefined") return FLAGS[bit];
-		throw new RangeError("BITFIELD_INVALID: " + bit);
-	}
-}
diff --git a/rtc/src/util/Config.ts b/rtc/src/util/Config.ts
deleted file mode 100644
index 78b44315..00000000
--- a/rtc/src/util/Config.ts
+++ /dev/null
@@ -1,284 +0,0 @@
-import { Schema, model, Types, Document } from "mongoose";
-import "missing-native-js-functions";
-import db, { MongooseCache } from "./Database";
-import { Snowflake } from "./Snowflake";
-import crypto from "crypto";
-
-var config: any;
-
-export default {
-	init: async function init(defaultOpts: any = DefaultOptions) {
-		config = await db.collection("config").findOne({});
-		return this.set((config || {}).merge(defaultOpts));
-	},
-	get: function get() {
-		return config as DefaultOptions;
-	},
-	set: function set(val: any) {
-		return db.collection("config").updateOne({}, { $set: val }, { upsert: true });
-	},
-};
-
-export interface RateLimitOptions {
-	bot?: number;
-	count: number;
-	window: number;
-	onyIp?: boolean;
-}
-
-export interface Region {
-	id: string;
-	name: string;
-	vip: boolean;
-	custom: boolean;
-	deprecated: boolean;
-	optimal: boolean;
-}
-
-export interface KafkaBroker {
-	ip: string;
-	port: number;
-}
-
-export interface DefaultOptions {
-	gateway: {
-		endpoint: string | null;
-	};
-	cdn: {
-		endpoint: string | null;
-	};
-	general: {
-		instance_id: string;
-	};
-	permissions: {
-		user: {
-			createGuilds: boolean;
-		};
-	};
-	limits: {
-		user: {
-			maxGuilds: number;
-			maxUsername: number;
-			maxFriends: number;
-		};
-		guild: {
-			maxRoles: number;
-			maxMembers: number;
-			maxChannels: number;
-			maxChannelsInCategory: number;
-			hideOfflineMember: number;
-		};
-		message: {
-			maxCharacters: number;
-			maxTTSCharacters: number;
-			maxReactions: number;
-			maxAttachmentSize: number;
-			maxBulkDelete: number;
-		};
-		channel: {
-			maxPins: number;
-			maxTopic: number;
-		};
-		rate: {
-			ip: Omit<RateLimitOptions, "bot_count">;
-			global: RateLimitOptions;
-			error: RateLimitOptions;
-			routes: {
-				guild: RateLimitOptions;
-				webhook: RateLimitOptions;
-				channel: RateLimitOptions;
-				auth: {
-					login: RateLimitOptions;
-					register: RateLimitOptions;
-				};
-				// TODO: rate limit configuration for all routes
-			};
-		};
-	};
-	security: {
-		requestSignature: string;
-		jwtSecret: string;
-		forwadedFor: string | null; // header to get the real user ip address
-		captcha: {
-			enabled: boolean;
-			service: "recaptcha" | "hcaptcha" | null; // TODO: hcaptcha, custom
-			sitekey: string | null;
-			secret: string | null;
-		};
-		ipdataApiKey: string | null;
-	};
-	login: {
-		requireCaptcha: boolean;
-	};
-	register: {
-		email: {
-			necessary: boolean; // we have to use necessary instead of required as the cli tool uses json schema and can't use required
-			allowlist: boolean;
-			blocklist: boolean;
-			domains: string[];
-		};
-		dateOfBirth: {
-			necessary: boolean;
-			minimum: number; // in years
-		};
-		requireCaptcha: boolean;
-		requireInvite: boolean;
-		allowNewRegistration: boolean;
-		allowMultipleAccounts: boolean;
-		blockProxies: boolean;
-		password: {
-			minLength: number;
-			minNumbers: number;
-			minUpperCase: number;
-			minSymbols: number;
-		};
-	};
-	regions: {
-		default: string;
-		available: Region[];
-	};
-	rabbitmq: {
-		host: string | null;
-	};
-	kafka: {
-		brokers: KafkaBroker[] | null;
-	};
-}
-
-export const DefaultOptions: DefaultOptions = {
-	gateway: {
-		endpoint: null,
-	},
-	cdn: {
-		endpoint: null,
-	},
-	general: {
-		instance_id: Snowflake.generate(),
-	},
-	permissions: {
-		user: {
-			createGuilds: true,
-		},
-	},
-	limits: {
-		user: {
-			maxGuilds: 100,
-			maxUsername: 32,
-			maxFriends: 1000,
-		},
-		guild: {
-			maxRoles: 250,
-			maxMembers: 250000,
-			maxChannels: 500,
-			maxChannelsInCategory: 50,
-			hideOfflineMember: 1000,
-		},
-		message: {
-			maxCharacters: 2000,
-			maxTTSCharacters: 200,
-			maxReactions: 20,
-			maxAttachmentSize: 8388608,
-			maxBulkDelete: 100,
-		},
-		channel: {
-			maxPins: 50,
-			maxTopic: 1024,
-		},
-		rate: {
-			ip: {
-				count: 500,
-				window: 5,
-			},
-			global: {
-				count: 20,
-				window: 5,
-				bot: 250,
-			},
-			error: {
-				count: 10,
-				window: 5,
-			},
-			routes: {
-				guild: {
-					count: 5,
-					window: 5,
-				},
-				webhook: {
-					count: 5,
-					window: 5,
-				},
-				channel: {
-					count: 5,
-					window: 5,
-				},
-				auth: {
-					login: {
-						count: 5,
-						window: 60,
-					},
-					register: {
-						count: 2,
-						window: 60 * 60 * 12,
-					},
-				},
-			},
-		},
-	},
-	security: {
-		requestSignature: crypto.randomBytes(32).toString("base64"),
-		jwtSecret: crypto.randomBytes(256).toString("base64"),
-		forwadedFor: null,
-		// forwadedFor: "X-Forwarded-For" // nginx/reverse proxy
-		// forwadedFor: "CF-Connecting-IP" // cloudflare:
-		captcha: {
-			enabled: false,
-			service: null,
-			sitekey: null,
-			secret: null,
-		},
-		ipdataApiKey: "eca677b284b3bac29eb72f5e496aa9047f26543605efe99ff2ce35c9",
-	},
-	login: {
-		requireCaptcha: false,
-	},
-	register: {
-		email: {
-			necessary: true,
-			allowlist: false,
-			blocklist: true,
-			domains: [], // TODO: efficiently save domain blocklist in database
-			// domains: fs.readFileSync(__dirname + "/blockedEmailDomains.txt", { encoding: "utf8" }).split("\n"),
-		},
-		dateOfBirth: {
-			necessary: true,
-			minimum: 13,
-		},
-		requireInvite: false,
-		requireCaptcha: true,
-		allowNewRegistration: true,
-		allowMultipleAccounts: true,
-		blockProxies: true,
-		password: {
-			minLength: 8,
-			minNumbers: 2,
-			minUpperCase: 2,
-			minSymbols: 0,
-		},
-	},
-	regions: {
-		default: "fosscord",
-		available: [{ id: "fosscord", name: "Fosscord", vip: false, custom: false, deprecated: false, optimal: false }],
-	},
-	rabbitmq: {
-		host: null,
-	},
-	kafka: {
-		brokers: null,
-	},
-};
-
-export const ConfigSchema = new Schema({}, { strict: false });
-
-export interface DefaultOptionsDocument extends DefaultOptions, Document {}
-
-export const ConfigModel = model<DefaultOptionsDocument>("Config", ConfigSchema, "config");
diff --git a/rtc/src/util/Constants.ts b/rtc/src/util/Constants.ts
deleted file mode 100644
index a9978c51..00000000
--- a/rtc/src/util/Constants.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { VerifyOptions } from "jsonwebtoken";
-
-export const JWTOptions: VerifyOptions = { algorithms: ["HS256"] };
-
-export enum MessageType {
-	DEFAULT = 0,
-	RECIPIENT_ADD = 1,
-	RECIPIENT_REMOVE = 2,
-	CALL = 3,
-	CHANNEL_NAME_CHANGE = 4,
-	CHANNEL_ICON_CHANGE = 5,
-	CHANNEL_PINNED_MESSAGE = 6,
-	GUILD_MEMBER_JOIN = 7,
-	USER_PREMIUM_GUILD_SUBSCRIPTION = 8,
-	USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1 = 9,
-	USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2 = 10,
-	USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3 = 11,
-	CHANNEL_FOLLOW_ADD = 12,
-	GUILD_DISCOVERY_DISQUALIFIED = 14,
-	GUILD_DISCOVERY_REQUALIFIED = 15,
-	GUILD_DISCOVERY_GRACE_PERIOD_INITIAL_WARNING = 16,
-	GUILD_DISCOVERY_GRACE_PERIOD_FINAL_WARNING = 17,
-	THREAD_CREATED = 18,
-	REPLY = 19,
-	APPLICATION_COMMAND = 20,
-	THREAD_STARTER_MESSAGE = 21,
-	GUILD_INVITE_REMINDER = 22,
-}
diff --git a/rtc/src/util/Database.ts b/rtc/src/util/Database.ts
deleted file mode 100644
index 8c6847a8..00000000
--- a/rtc/src/util/Database.ts
+++ /dev/null
@@ -1,151 +0,0 @@
-import "./MongoBigInt";
-import mongoose, { Collection, Connection, LeanDocument } from "mongoose";
-import { ChangeStream, ChangeEvent, Long } from "mongodb";
-import EventEmitter from "events";
-const uri = process.env.MONGO_URL || "mongodb://localhost:27017/fosscord?readPreference=secondaryPreferred";
-import { URL } from "url";
-
-const url = new URL(uri.replace("mongodb://", "http://"));
-
-const connection = mongoose.createConnection(uri, {
-	autoIndex: true,
-	useNewUrlParser: true,
-	useUnifiedTopology: true,
-	useFindAndModify: false,
-});
-console.log(`[Database] connect: mongodb://${url.username}@${url.host}${url.pathname}${url.search}`);
-
-export default <Connection>connection;
-
-function transform<T>(document: T) {
-	// @ts-ignore
-	if (!document || !document.toObject) {
-		try {
-			// @ts-ignore
-			delete document._id;
-			// @ts-ignore
-			delete document.__v;
-		} catch (error) {}
-		return document;
-	}
-	// @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;
-	on(event: "insert", listener: (data: any) => void): this;
-	on(event: "close", listener: () => void): this;
-}
-
-export class MongooseCache extends EventEmitter {
-	public stream: ChangeStream;
-	public data: any;
-	public initalizing?: Promise<void>;
-
-	constructor(
-		public collection: Collection,
-		public pipeline: Array<Record<string, unknown>>,
-		public opts: {
-			onlyEvents: boolean;
-			array?: boolean;
-		}
-	) {
-		super();
-		if (this.opts.array == null) this.opts.array = true;
-	}
-
-	init = () => {
-		if (this.initalizing) return this.initalizing;
-		this.initalizing = new Promise(async (resolve, reject) => {
-			// @ts-ignore
-			this.stream = this.collection.watch(this.pipeline, { fullDocument: "updateLookup" });
-
-			this.stream.on("change", this.change);
-			this.stream.on("close", this.destroy);
-			this.stream.on("error", console.error);
-
-			if (!this.opts.onlyEvents) {
-				const arr = await this.collection.aggregate(this.pipeline).toArray();
-				if (this.opts.array) this.data = arr || [];
-				else this.data = arr?.[0];
-			}
-			resolve();
-		});
-		return this.initalizing;
-	};
-
-	changeStream = (pipeline: any) => {
-		this.pipeline = pipeline;
-		this.destroy();
-		this.init();
-	};
-
-	convertResult = (obj: any) => {
-		if (obj instanceof Long) return BigInt(obj.toString());
-		if (typeof obj === "object") {
-			Object.keys(obj).forEach((key) => {
-				obj[key] = this.convertResult(obj[key]);
-			});
-		}
-
-		return obj;
-	};
-
-	change = (doc: ChangeEvent) => {
-		try {
-			switch (doc.operationType) {
-				case "dropDatabase":
-					return this.destroy();
-				case "drop":
-					return this.destroy();
-				case "delete":
-					if (!this.opts.onlyEvents) {
-						if (this.opts.array) {
-							this.data = this.data.filter((x: any) => doc.documentKey?._id?.equals(x._id));
-						} else this.data = null;
-					}
-					return this.emit("delete", doc.documentKey._id.toHexString());
-				case "insert":
-					if (!this.opts.onlyEvents) {
-						if (this.opts.array) this.data.push(doc.fullDocument);
-						else this.data = doc.fullDocument;
-					}
-					return this.emit("insert", doc.fullDocument);
-				case "update":
-				case "replace":
-					if (!this.opts.onlyEvents) {
-						if (this.opts.array) {
-							const i = this.data.findIndex((x: any) => doc.fullDocument?._id?.equals(x._id));
-							if (i == -1) this.data.push(doc.fullDocument);
-							else this.data[i] = doc.fullDocument;
-						} else this.data = doc.fullDocument;
-					}
-
-					return this.emit("change", doc.fullDocument);
-				case "invalidate":
-					return this.destroy();
-				default:
-					return;
-			}
-		} catch (error) {
-			this.emit("error", error);
-		}
-	};
-
-	destroy = () => {
-		this.data = null;
-		this.stream?.off("change", this.change);
-		this.emit("close");
-
-		if (this.stream.isClosed()) return;
-
-		return this.stream.close();
-	};
-}
diff --git a/rtc/src/util/Intents.ts b/rtc/src/util/Intents.ts
deleted file mode 100644
index 943b29cf..00000000
--- a/rtc/src/util/Intents.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { BitField } from "./BitField";
-
-export class Intents extends BitField {
-	static FLAGS = {
-		GUILDS: BigInt(1) << BigInt(0),
-		GUILD_MEMBERS: BigInt(1) << BigInt(1),
-		GUILD_BANS: BigInt(1) << BigInt(2),
-		GUILD_EMOJIS: BigInt(1) << BigInt(3),
-		GUILD_INTEGRATIONS: BigInt(1) << BigInt(4),
-		GUILD_WEBHOOKS: BigInt(1) << BigInt(5),
-		GUILD_INVITES: BigInt(1) << BigInt(6),
-		GUILD_VOICE_STATES: BigInt(1) << BigInt(7),
-		GUILD_PRESENCES: BigInt(1) << BigInt(8),
-		GUILD_MESSAGES: BigInt(1) << BigInt(9),
-		GUILD_MESSAGE_REACTIONS: BigInt(1) << BigInt(10),
-		GUILD_MESSAGE_TYPING: BigInt(1) << BigInt(11),
-		DIRECT_MESSAGES: BigInt(1) << BigInt(12),
-		DIRECT_MESSAGE_REACTIONS: BigInt(1) << BigInt(13),
-		DIRECT_MESSAGE_TYPING: BigInt(1) << BigInt(14),
-	};
-}
diff --git a/rtc/src/util/MessageFlags.ts b/rtc/src/util/MessageFlags.ts
deleted file mode 100644
index c76be4c8..00000000
--- a/rtc/src/util/MessageFlags.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-// https://github.com/discordjs/discord.js/blob/master/src/util/MessageFlags.js
-// Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah
-
-import { BitField } from "./BitField";
-
-export class MessageFlags extends BitField {
-	static FLAGS = {
-		CROSSPOSTED: BigInt(1) << BigInt(0),
-		IS_CROSSPOST: BigInt(1) << BigInt(1),
-		SUPPRESS_EMBEDS: BigInt(1) << BigInt(2),
-		SOURCE_MESSAGE_DELETED: BigInt(1) << BigInt(3),
-		URGENT: BigInt(1) << BigInt(4),
-	};
-}
diff --git a/rtc/src/util/MongoBigInt.ts b/rtc/src/util/MongoBigInt.ts
deleted file mode 100644
index fc451925..00000000
--- a/rtc/src/util/MongoBigInt.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-import mongoose from "mongoose";
-
-class LongSchema extends mongoose.SchemaType {
-	public $conditionalHandlers = {
-		$lt: this.handleSingle,
-		$lte: this.handleSingle,
-		$gt: this.handleSingle,
-		$gte: this.handleSingle,
-		$ne: this.handleSingle,
-		$in: this.handleArray,
-		$nin: this.handleArray,
-		$mod: this.handleArray,
-		$all: this.handleArray,
-		$bitsAnySet: this.handleArray,
-		$bitsAllSet: this.handleArray,
-	};
-
-	handleSingle(val: any) {
-		return this.cast(val, null, null, "handle");
-	}
-
-	handleArray(val: any) {
-		var self = this;
-		return val.map(function (m: any) {
-			return self.cast(m, null, null, "handle");
-		});
-	}
-
-	checkRequired(val: any) {
-		return null != val;
-	}
-
-	cast(val: any, scope?: any, init?: any, type?: string) {
-		if (null === val) return val;
-		if ("" === val) return null;
-		if (typeof val === "bigint") {
-			return mongoose.mongo.Long.fromString(val.toString());
-		}
-
-		if (val instanceof mongoose.mongo.Long) {
-			if (type === "handle" || init == false) return val;
-			return BigInt(val.toString());
-		}
-		if (val instanceof Number || "number" == typeof val) return BigInt(val);
-		if (!Array.isArray(val) && val.toString) return BigInt(val.toString());
-
-		//@ts-ignore
-		throw new SchemaType.CastError("Long", val);
-	}
-
-	castForQuery($conditional: string, value: any) {
-		var handler;
-		if (2 === arguments.length) {
-			// @ts-ignore
-			handler = this.$conditionalHandlers[$conditional];
-			if (!handler) {
-				throw new Error("Can't use " + $conditional + " with Long.");
-			}
-			return handler.call(this, value);
-		} else {
-			return this.cast($conditional, null, null, "query");
-		}
-	}
-}
-
-LongSchema.cast = mongoose.SchemaType.cast;
-LongSchema.set = mongoose.SchemaType.set;
-LongSchema.get = mongoose.SchemaType.get;
-
-declare module "mongoose" {
-	namespace Types {
-		class Long extends mongoose.mongo.Long {}
-	}
-	namespace Schema {
-		namespace Types {
-			class Long extends LongSchema {}
-		}
-	}
-}
-
-mongoose.Schema.Types.Long = LongSchema;
-mongoose.Types.Long = mongoose.mongo.Long;
diff --git a/rtc/src/util/Permissions.ts b/rtc/src/util/Permissions.ts
deleted file mode 100644
index 445e901f..00000000
--- a/rtc/src/util/Permissions.ts
+++ /dev/null
@@ -1,262 +0,0 @@
-// https://github.com/discordjs/discord.js/blob/master/src/util/Permissions.js
-// Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah
-import { MemberDocument, MemberModel } from "../models/Member";
-import { ChannelDocument, ChannelModel } from "../models/Channel";
-import { ChannelPermissionOverwrite } from "../models/Channel";
-import { Role, RoleDocument, RoleModel } from "../models/Role";
-import { BitField } from "./BitField";
-import { GuildDocument, GuildModel } from "../models/Guild";
-// TODO: check role hierarchy permission
-
-var HTTPError: any;
-
-try {
-	HTTPError = require("lambert-server").HTTPError;
-} catch (e) {
-	HTTPError = Error;
-}
-
-export type PermissionResolvable = bigint | number | Permissions | PermissionResolvable[] | PermissionString;
-
-type PermissionString =
-	| "CREATE_INSTANT_INVITE"
-	| "KICK_MEMBERS"
-	| "BAN_MEMBERS"
-	| "ADMINISTRATOR"
-	| "MANAGE_CHANNELS"
-	| "MANAGE_GUILD"
-	| "ADD_REACTIONS"
-	| "VIEW_AUDIT_LOG"
-	| "PRIORITY_SPEAKER"
-	| "STREAM"
-	| "VIEW_CHANNEL"
-	| "SEND_MESSAGES"
-	| "SEND_TTS_MESSAGES"
-	| "MANAGE_MESSAGES"
-	| "EMBED_LINKS"
-	| "ATTACH_FILES"
-	| "READ_MESSAGE_HISTORY"
-	| "MENTION_EVERYONE"
-	| "USE_EXTERNAL_EMOJIS"
-	| "VIEW_GUILD_INSIGHTS"
-	| "CONNECT"
-	| "SPEAK"
-	| "MUTE_MEMBERS"
-	| "DEAFEN_MEMBERS"
-	| "MOVE_MEMBERS"
-	| "USE_VAD"
-	| "CHANGE_NICKNAME"
-	| "MANAGE_NICKNAMES"
-	| "MANAGE_ROLES"
-	| "MANAGE_WEBHOOKS"
-	| "MANAGE_EMOJIS";
-
-const CUSTOM_PERMISSION_OFFSET = BigInt(1) << BigInt(48); // 16 free custom permission bits, and 16 for discord to add new ones
-
-export class Permissions extends BitField {
-	cache: PermissionCache = {};
-
-	static FLAGS = {
-		CREATE_INSTANT_INVITE: BigInt(1) << BigInt(0),
-		KICK_MEMBERS: BigInt(1) << BigInt(1),
-		BAN_MEMBERS: BigInt(1) << BigInt(2),
-		ADMINISTRATOR: BigInt(1) << BigInt(3),
-		MANAGE_CHANNELS: BigInt(1) << BigInt(4),
-		MANAGE_GUILD: BigInt(1) << BigInt(5),
-		ADD_REACTIONS: BigInt(1) << BigInt(6),
-		VIEW_AUDIT_LOG: BigInt(1) << BigInt(7),
-		PRIORITY_SPEAKER: BigInt(1) << BigInt(8),
-		STREAM: BigInt(1) << BigInt(9),
-		VIEW_CHANNEL: BigInt(1) << BigInt(10),
-		SEND_MESSAGES: BigInt(1) << BigInt(11),
-		SEND_TTS_MESSAGES: BigInt(1) << BigInt(12),
-		MANAGE_MESSAGES: BigInt(1) << BigInt(13),
-		EMBED_LINKS: BigInt(1) << BigInt(14),
-		ATTACH_FILES: BigInt(1) << BigInt(15),
-		READ_MESSAGE_HISTORY: BigInt(1) << BigInt(16),
-		MENTION_EVERYONE: BigInt(1) << BigInt(17),
-		USE_EXTERNAL_EMOJIS: BigInt(1) << BigInt(18),
-		VIEW_GUILD_INSIGHTS: BigInt(1) << BigInt(19),
-		CONNECT: BigInt(1) << BigInt(20),
-		SPEAK: BigInt(1) << BigInt(21),
-		MUTE_MEMBERS: BigInt(1) << BigInt(22),
-		DEAFEN_MEMBERS: BigInt(1) << BigInt(23),
-		MOVE_MEMBERS: BigInt(1) << BigInt(24),
-		USE_VAD: BigInt(1) << BigInt(25),
-		CHANGE_NICKNAME: BigInt(1) << BigInt(26),
-		MANAGE_NICKNAMES: BigInt(1) << BigInt(27),
-		MANAGE_ROLES: BigInt(1) << BigInt(28),
-		MANAGE_WEBHOOKS: BigInt(1) << BigInt(29),
-		MANAGE_EMOJIS: BigInt(1) << BigInt(30),
-		/**
-		 * CUSTOM PERMISSIONS ideas:
-		 * - allow user to dm members
-		 * - allow user to pin messages (without MANAGE_MESSAGES)
-		 * - allow user to publish messages (without MANAGE_MESSAGES)
-		 */
-		// CUSTOM_PERMISSION: BigInt(1) << BigInt(0) + CUSTOM_PERMISSION_OFFSET
-	};
-
-	any(permission: PermissionResolvable, checkAdmin = true) {
-		return (checkAdmin && super.any(Permissions.FLAGS.ADMINISTRATOR)) || super.any(permission);
-	}
-
-	/**
-	 * Checks whether the bitfield has a permission, or multiple permissions.
-	 */
-	has(permission: PermissionResolvable, checkAdmin = true) {
-		return (checkAdmin && super.has(Permissions.FLAGS.ADMINISTRATOR)) || super.has(permission);
-	}
-
-	/**
-	 * Checks whether the bitfield has a permission, or multiple permissions, but throws an Error if user fails to match auth criteria.
-	 */
-	hasThrow(permission: PermissionResolvable) {
-		if (this.has(permission) && this.has("VIEW_CHANNEL")) return true;
-		// @ts-ignore
-		throw new HTTPError(`You are missing the following permissions ${permission}`, 403);
-	}
-
-	overwriteChannel(overwrites: ChannelPermissionOverwrite[]) {
-		if (!this.cache) throw new Error("permission chache not available");
-		overwrites = overwrites.filter((x) => {
-			if (x.type === 0 && this.cache.roles?.some((r) => r.id === x.id)) return true;
-			if (x.type === 1 && x.id == this.cache.user_id) return true;
-			return false;
-		});
-		return new Permissions(Permissions.channelPermission(overwrites, this.bitfield));
-	}
-
-	static channelPermission(overwrites: ChannelPermissionOverwrite[], init?: bigint) {
-		// TODO: do not deny any permissions if admin
-		return overwrites.reduce((permission, overwrite) => {
-			// apply disallowed permission
-			// * permission: current calculated permission (e.g. 010)
-			// * deny contains all denied permissions (e.g. 011)
-			// * allow contains all explicitly allowed permisions (e.g. 100)
-			return (permission & ~BigInt(overwrite.deny)) | BigInt(overwrite.allow);
-			// ~ operator inverts deny (e.g. 011 -> 100)
-			// & operator only allows 1 for both ~deny and permission (e.g. 010 & 100 -> 000)
-			// | operators adds both together (e.g. 000 + 100 -> 100)
-		}, init || 0n);
-	}
-
-	static rolePermission(roles: Role[]) {
-		// adds all permissions of all roles together (Bit OR)
-		return roles.reduce((permission, role) => permission | BigInt(role.permissions), 0n);
-	}
-
-	static finalPermission({
-		user,
-		guild,
-		channel,
-	}: {
-		user: { id: string; roles: string[] };
-		guild: { roles: Role[] };
-		channel?: {
-			overwrites?: ChannelPermissionOverwrite[];
-			recipient_ids?: string[] | null;
-			owner_id?: string;
-		};
-	}) {
-		if (user.id === "0") return new Permissions("ADMINISTRATOR"); // system user id
-
-		let roles = guild.roles.filter((x) => user.roles.includes(x.id));
-		let permission = Permissions.rolePermission(roles);
-
-		if (channel?.overwrites) {
-			let overwrites = channel.overwrites.filter((x) => {
-				if (x.type === 0 && user.roles.includes(x.id)) return true;
-				if (x.type === 1 && x.id == user.id) return true;
-				return false;
-			});
-			permission = Permissions.channelPermission(overwrites, permission);
-		}
-
-		if (channel?.recipient_ids) {
-			if (channel?.owner_id === user.id) return new Permissions("ADMINISTRATOR");
-			if (channel.recipient_ids.includes(user.id)) {
-				// Default dm permissions
-				return new Permissions([
-					"VIEW_CHANNEL",
-					"SEND_MESSAGES",
-					"STREAM",
-					"ADD_REACTIONS",
-					"EMBED_LINKS",
-					"ATTACH_FILES",
-					"READ_MESSAGE_HISTORY",
-					"MENTION_EVERYONE",
-					"USE_EXTERNAL_EMOJIS",
-					"CONNECT",
-					"SPEAK",
-					"MANAGE_CHANNELS",
-				]);
-			}
-
-			return new Permissions();
-		}
-
-		return new Permissions(permission);
-	}
-}
-
-export type PermissionCache = {
-	channel?: ChannelDocument | null;
-	member?: MemberDocument | null;
-	guild?: GuildDocument | null;
-	roles?: RoleDocument[] | null;
-	user_id?: string;
-};
-
-export async function getPermission(
-	user_id?: string,
-	guild_id?: string,
-	channel_id?: string,
-	cache: PermissionCache = {}
-) {
-	var { channel, member, guild, roles } = cache;
-
-	if (!user_id) throw new HTTPError("User not found");
-
-	if (channel_id && !channel) {
-		channel = await ChannelModel.findOne(
-			{ id: channel_id },
-			{ permission_overwrites: true, recipient_ids: true, owner_id: true, guild_id: true }
-		).exec();
-		if (!channel) throw new HTTPError("Channel not found", 404);
-		if (channel.guild_id) guild_id = channel.guild_id;
-	}
-
-	if (guild_id) {
-		if (!guild) guild = await GuildModel.findOne({ id: guild_id }, { owner_id: true }).exec();
-		if (!guild) throw new HTTPError("Guild not found");
-		if (guild.owner_id === user_id) return new Permissions(Permissions.FLAGS.ADMINISTRATOR);
-
-		if (!member) member = await MemberModel.findOne({ guild_id, id: user_id }, "roles").exec();
-		if (!member) throw new HTTPError("Member not found");
-
-		if (!roles) roles = await RoleModel.find({ guild_id, id: { $in: member.roles } }).exec();
-	}
-
-	var permission = Permissions.finalPermission({
-		user: {
-			id: user_id,
-			roles: member?.roles || [],
-		},
-		guild: {
-			roles: roles || [],
-		},
-		channel: {
-			overwrites: channel?.permission_overwrites,
-			owner_id: channel?.owner_id,
-			recipient_ids: channel?.recipient_ids,
-		},
-	});
-
-	const obj = new Permissions(permission);
-
-	// pass cache to permission for possible future getPermission calls
-	obj.cache = { guild, member, channel, roles, user_id };
-
-	return obj;
-}
diff --git a/rtc/src/util/RabbitMQ.ts b/rtc/src/util/RabbitMQ.ts
deleted file mode 100644
index 9da41990..00000000
--- a/rtc/src/util/RabbitMQ.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import amqp, { Connection, Channel } from "amqplib";
-import Config from "./Config";
-
-export const RabbitMQ: { connection: Connection | null; channel: Channel | null; init: () => Promise<void> } = {
-	connection: null,
-	channel: null,
-	init: async function () {
-		const host = Config.get().rabbitmq.host;
-		if (!host) return;
-		console.log(`[RabbitMQ] connect: ${host}`);
-		this.connection = await amqp.connect(host, {
-			timeout: 1000 * 60,
-		});
-		console.log(`[RabbitMQ] connected`);
-		this.channel = await this.connection.createChannel();
-		console.log(`[RabbitMQ] channel created`);
-	},
-};
diff --git a/rtc/src/util/Regex.ts b/rtc/src/util/Regex.ts
deleted file mode 100644
index bbd48bca..00000000
--- a/rtc/src/util/Regex.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export const DOUBLE_WHITE_SPACE = /\s\s+/g;
-export const SPECIAL_CHAR = /[@#`:\r\n\t\f\v\p{C}]/gu;
-export const CHANNEL_MENTION = /<#(\d+)>/g;
diff --git a/rtc/src/util/Snowflake.ts b/rtc/src/util/Snowflake.ts
deleted file mode 100644
index 1d725710..00000000
--- a/rtc/src/util/Snowflake.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-// @ts-nocheck
-import cluster from "cluster";
-
-// https://github.com/discordjs/discord.js/blob/master/src/util/Snowflake.js
-// Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah
-("use strict");
-
-// Discord epoch (2015-01-01T00:00:00.000Z)
-
-/**
- * A container for useful snowflake-related methods.
- */
-export class Snowflake {
-	static readonly EPOCH = 1420070400000;
-	static INCREMENT = 0n; // max 4095
-	static processId = BigInt(process.pid % 31); // max 31
-	static workerId = BigInt((cluster.worker?.id || 0) % 31); // max 31
-
-	constructor() {
-		throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
-	}
-
-	/**
-	 * A Twitter snowflake, except the epoch is 2015-01-01T00:00:00.000Z
-	 * ```
-	 * If we have a snowflake '266241948824764416' we can represent it as binary:
-	 *
-	 * 64                                          22     17     12          0
-	 *  000000111011000111100001101001000101000000  00001  00000  000000000000
-	 *       number of ms since Discord epoch       worker  pid    increment
-	 * ```
-	 * @typedef {string} Snowflake
-	 */
-
-	/**
-	 * Transforms a snowflake from a decimal string to a bit string.
-	 * @param  {Snowflake} num Snowflake to be transformed
-	 * @returns {string}
-	 * @private
-	 */
-	static idToBinary(num) {
-		let bin = "";
-		let high = parseInt(num.slice(0, -10)) || 0;
-		let low = parseInt(num.slice(-10));
-		while (low > 0 || high > 0) {
-			bin = String(low & 1) + bin;
-			low = Math.floor(low / 2);
-			if (high > 0) {
-				low += 5000000000 * (high % 2);
-				high = Math.floor(high / 2);
-			}
-		}
-		return bin;
-	}
-
-	/**
-	 * Transforms a snowflake from a bit string to a decimal string.
-	 * @param  {string} num Bit string to be transformed
-	 * @returns {Snowflake}
-	 * @private
-	 */
-	static binaryToID(num) {
-		let dec = "";
-
-		while (num.length > 50) {
-			const high = parseInt(num.slice(0, -32), 2);
-			const low = parseInt((high % 10).toString(2) + num.slice(-32), 2);
-
-			dec = (low % 10).toString() + dec;
-			num =
-				Math.floor(high / 10).toString(2) +
-				Math.floor(low / 10)
-					.toString(2)
-					.padStart(32, "0");
-		}
-
-		num = parseInt(num, 2);
-		while (num > 0) {
-			dec = (num % 10).toString() + dec;
-			num = Math.floor(num / 10);
-		}
-
-		return dec;
-	}
-
-	static generate() {
-		var time = BigInt(Date.now() - Snowflake.EPOCH) << 22n;
-		var worker = Snowflake.workerId << 17n;
-		var process = Snowflake.processId << 12n;
-		var increment = Snowflake.INCREMENT++;
-		return (time | worker | process | increment).toString();
-	}
-
-	/**
-	 * A deconstructed snowflake.
-	 * @typedef {Object} DeconstructedSnowflake
-	 * @property {number} timestamp Timestamp the snowflake was created
-	 * @property {Date} date Date the snowflake was created
-	 * @property {number} workerID Worker ID in the snowflake
-	 * @property {number} processID Process ID in the snowflake
-	 * @property {number} increment Increment in the snowflake
-	 * @property {string} binary Binary representation of the snowflake
-	 */
-
-	/**
-	 * Deconstructs a Discord snowflake.
-	 * @param {Snowflake} snowflake Snowflake to deconstruct
-	 * @returns {DeconstructedSnowflake} Deconstructed snowflake
-	 */
-	static deconstruct(snowflake) {
-		const BINARY = Snowflake.idToBinary(snowflake).toString(2).padStart(64, "0");
-		const res = {
-			timestamp: parseInt(BINARY.substring(0, 42), 2) + Snowflake.EPOCH,
-			workerID: parseInt(BINARY.substring(42, 47), 2),
-			processID: parseInt(BINARY.substring(47, 52), 2),
-			increment: parseInt(BINARY.substring(52, 64), 2),
-			binary: BINARY,
-		};
-		Object.defineProperty(res, "date", {
-			get: function get() {
-				return new Date(this.timestamp);
-			},
-			enumerable: true,
-		});
-		return res;
-	}
-}
diff --git a/rtc/src/util/String.ts b/rtc/src/util/String.ts
deleted file mode 100644
index 55f11e8d..00000000
--- a/rtc/src/util/String.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { SPECIAL_CHAR } from "./Regex";
-
-export function trimSpecial(str?: string): string {
-	// @ts-ignore
-	if (!str) return;
-	return str.replace(SPECIAL_CHAR, "").trim();
-}
diff --git a/rtc/src/util/UserFlags.ts b/rtc/src/util/UserFlags.ts
deleted file mode 100644
index 72394eff..00000000
--- a/rtc/src/util/UserFlags.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-// https://github.com/discordjs/discord.js/blob/master/src/util/UserFlags.js
-// Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah
-
-import { BitField } from "./BitField";
-
-export class UserFlags extends BitField {
-	static FLAGS = {
-		DISCORD_EMPLOYEE: BigInt(1) << BigInt(0),
-		PARTNERED_SERVER_OWNER: BigInt(1) << BigInt(1),
-		HYPESQUAD_EVENTS: BigInt(1) << BigInt(2),
-		BUGHUNTER_LEVEL_1: BigInt(1) << BigInt(3),
-		HOUSE_BRAVERY: BigInt(1) << BigInt(6),
-		HOUSE_BRILLIANCE: BigInt(1) << BigInt(7),
-		HOUSE_BALANCE: BigInt(1) << BigInt(8),
-		EARLY_SUPPORTER: BigInt(1) << BigInt(9),
-		TEAM_USER: BigInt(1) << BigInt(10),
-		SYSTEM: BigInt(1) << BigInt(12),
-		BUGHUNTER_LEVEL_2: BigInt(1) << BigInt(14),
-		VERIFIED_BOT: BigInt(1) << BigInt(16),
-		EARLY_VERIFIED_BOT_DEVELOPER: BigInt(1) << BigInt(17),
-	};
-}
diff --git a/rtc/src/util/checkToken.ts b/rtc/src/util/checkToken.ts
deleted file mode 100644
index 91bf08d5..00000000
--- a/rtc/src/util/checkToken.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { JWTOptions } from "./Constants";
-import jwt from "jsonwebtoken";
-import { UserModel } from "../models";
-
-export function checkToken(token: string, jwtSecret: string): Promise<any> {
-	return new Promise((res, rej) => {
-		token = token.replace("Bot ", ""); // TODO: proper bot support
-		jwt.verify(token, jwtSecret, JWTOptions, async (err, decoded: any) => {
-			if (err || !decoded) return rej("Invalid Token");
-
-			const user = await UserModel.findOne(
-				{ id: decoded.id },
-				{ "user_data.valid_tokens_since": true, bot: true, disabled: true, deleted: true }
-			).exec();
-			if (!user) return rej("Invalid Token");
-			// we need to round it to seconds as it saved as seconds in jwt iat and valid_tokens_since is stored in milliseconds
-			if (decoded.iat * 1000 < user.user_data.valid_tokens_since.setSeconds(0, 0)) return rej("Invalid Token");
-			if (user.disabled) return rej("User disabled");
-			if (user.deleted) return rej("User not found");
-
-			return res({ decoded, user });
-		});
-	});
-}
diff --git a/rtc/src/util/index.ts b/rtc/src/util/index.ts
deleted file mode 100644
index 7523a6ad..00000000
--- a/rtc/src/util/index.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-export * from "./String";
-export * from "./BitField";
-export * from "./Intents";
-export * from "./MessageFlags";
-export * from "./Permissions";
-export * from "./Snowflake";
-export * from "./UserFlags";
-export * from "./toBigInt";
-export * from "./RabbitMQ";
diff --git a/rtc/src/util/toBigInt.ts b/rtc/src/util/toBigInt.ts
deleted file mode 100644
index d57c4568..00000000
--- a/rtc/src/util/toBigInt.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function toBigInt(string: String): BigInt {
-	return BigInt(string);
-}