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