diff --git a/src/index.ts b/src/index.ts
index 1d501baf..5605997c 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,7 +1,7 @@
-import { checkToken } from "./checkToken";
-import Config, { DefaultOptions } from "./Config";
-import db from "./Database";
-import * as Constants from "./Constants";
+import { checkToken } from "./util/checkToken";
+import Config, { DefaultOptions } from "./util/Config";
+import db from "./util/Database";
+import * as Constants from "./util/Constants";
import { Channel } from "./models/Channel";
import { Emoji } from "./models/Emoji";
import { Guild } from "./models/Guild";
@@ -9,5 +9,24 @@ import { Invite } from "./models/Invite";
import { Member } from "./models/Member";
import { Role } from "./models/Role";
import { User } from "./models/User";
+import { EmojiSchema } from "./Schema/Emoji";
+import { ActivitySchema } from "./Schema/Activity";
+import { IdentifySchema } from "./Schema/Identify";
-export { checkToken, Config, Constants, db, DefaultOptions, Channel, Emoji, Guild, Invite, Member, Role, User };
+export {
+ checkToken,
+ Config,
+ Constants,
+ db,
+ DefaultOptions,
+ Channel,
+ Emoji,
+ Guild,
+ Invite,
+ Member,
+ Role,
+ User,
+ EmojiSchema,
+ ActivitySchema,
+ IdentifySchema,
+};
diff --git a/src/util/BitField.ts b/src/util/BitField.ts
new file mode 100644
index 00000000..17eef796
--- /dev/null
+++ b/src/util/BitField.ts
@@ -0,0 +1,138 @@
+"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(bits);
+ }
+
+ /**
+ * Checks whether the bitfield has a bit, or any of multiple bits.
+ */
+ any(bit: BitFieldResolvable): boolean {
+ return (this.bitfield & BitField.resolve(bit)) !== 0n;
+ }
+
+ /**
+ * Checks if this bitfield equals another
+ */
+ equals(bit: BitFieldResolvable): boolean {
+ return this.bitfield === BitField.resolve(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(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(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(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 {
+ if ((typeof bit === "number" || typeof bit === "bigint") && bit >= 0n) return BigInt(bit);
+ if (bit instanceof BitField) return bit.bitfield;
+ if (Array.isArray(bit))
+ return bit.map((p) => this.resolve(p)).reduce((prev, p) => BigInt(prev) | BigInt(p), 0n);
+ if (typeof bit === "string" && typeof this.FLAGS[bit] !== "undefined") return this.FLAGS[bit];
+ throw new RangeError("BITFIELD_INVALID: " + bit);
+ }
+}
diff --git a/src/Config.ts b/src/util/Config.ts
index b22e88e0..b22e88e0 100644
--- a/src/Config.ts
+++ b/src/util/Config.ts
diff --git a/src/Constants.ts b/src/util/Constants.ts
index 808d234b..808d234b 100644
--- a/src/Constants.ts
+++ b/src/util/Constants.ts
diff --git a/src/Database.ts b/src/util/Database.ts
index d842ac6b..d842ac6b 100644
--- a/src/Database.ts
+++ b/src/util/Database.ts
diff --git a/src/util/Intents.ts b/src/util/Intents.ts
new file mode 100644
index 00000000..b96f6af9
--- /dev/null
+++ b/src/util/Intents.ts
@@ -0,0 +1,21 @@
+import { BitField } from "./BitField";
+
+export class Intents extends BitField {
+ static FLAGS = {
+ GUILDS: 1n << 0n,
+ GUILD_MEMBERS: 1n << 1n,
+ GUILD_BANS: 1n << 2n,
+ GUILD_EMOJIS: 1n << 3n,
+ GUILD_INTEGRATIONS: 1n << 4n,
+ GUILD_WEBHOOKS: 1n << 5n,
+ GUILD_INVITES: 1n << 6n,
+ GUILD_VOICE_STATES: 1n << 7n,
+ GUILD_PRESENCES: 1n << 8n,
+ GUILD_MESSAGES: 1n << 9n,
+ GUILD_MESSAGE_REACTIONS: 1n << 10n,
+ GUILD_MESSAGE_TYPING: 1n << 11n,
+ DIRECT_MESSAGES: 1n << 12n,
+ DIRECT_MESSAGE_REACTIONS: 1n << 13n,
+ DIRECT_MESSAGE_TYPING: 1n << 14n,
+ };
+}
diff --git a/src/util/MessageFlags.ts b/src/util/MessageFlags.ts
new file mode 100644
index 00000000..d3e6a07a
--- /dev/null
+++ b/src/util/MessageFlags.ts
@@ -0,0 +1,14 @@
+// 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: 1n << 0n,
+ IS_CROSSPOST: 1n << 1n,
+ SUPPRESS_EMBEDS: 1n << 2n,
+ SOURCE_MESSAGE_DELETED: 1n << 3n,
+ URGENT: 1n << 4n,
+ };
+}
diff --git a/src/util/Permissions.ts b/src/util/Permissions.ts
new file mode 100644
index 00000000..f076e0c2
--- /dev/null
+++ b/src/util/Permissions.ts
@@ -0,0 +1,56 @@
+// https://github.com/discordjs/discord.js/blob/master/src/util/Permissions.js
+// Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah
+
+import { BitField } from "./BitField";
+
+export type PermissionResolvable = string | number | Permissions | PermissionResolvable[];
+
+export class Permissions extends BitField {
+ static FLAGS = {
+ CREATE_INSTANT_INVITE: 1n << 0n,
+ KICK_MEMBERS: 1n << 1n,
+ BAN_MEMBERS: 1n << 2n,
+ ADMINISTRATOR: 1n << 3n,
+ MANAGE_CHANNELS: 1n << 4n,
+ MANAGE_GUILD: 1n << 5n,
+ ADD_REACTIONS: 1n << 6n,
+ VIEW_AUDIT_LOG: 1n << 7n,
+ PRIORITY_SPEAKER: 1n << 8n,
+ STREAM: 1n << 9n,
+ VIEW_CHANNEL: 1n << 10n,
+ SEND_MESSAGES: 1n << 11n,
+ SEND_TTS_MESSAGES: 1n << 12n,
+ MANAGE_MESSAGES: 1n << 13n,
+ EMBED_LINKS: 1n << 14n,
+ ATTACH_FILES: 1n << 15n,
+ READ_MESSAGE_HISTORY: 1n << 16n,
+ MENTION_EVERYONE: 1n << 17n,
+ USE_EXTERNAL_EMOJIS: 1n << 18n,
+ VIEW_GUILD_INSIGHTS: 1n << 19n,
+ CONNECT: 1n << 20n,
+ SPEAK: 1n << 21n,
+ MUTE_MEMBERS: 1n << 22n,
+ DEAFEN_MEMBERS: 1n << 23n,
+ MOVE_MEMBERS: 1n << 24n,
+ USE_VAD: 1n << 25n,
+ CHANGE_NICKNAME: 1n << 26n,
+ MANAGE_NICKNAMES: 1n << 27n,
+ MANAGE_ROLES: 1n << 28n,
+ MANAGE_WEBHOOKS: 1n << 29n,
+ MANAGE_EMOJIS: 1n << 30n,
+ };
+
+ any(permission: PermissionResolvable, checkAdmin = true) {
+ return (checkAdmin && super.has(Permissions.FLAGS.ADMINISTRATOR)) || super.any(permission);
+ }
+
+ /**
+ * Checks whether the bitfield has a permission, or multiple permissions.
+ * @param {PermissionResolvable} permission Permission(s) to check for
+ * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
+ * @returns {boolean}
+ */
+ has(permission: PermissionResolvable, checkAdmin = true) {
+ return (checkAdmin && super.has(Permissions.FLAGS.ADMINISTRATOR)) || super.has(permission);
+ }
+}
diff --git a/src/util/Snowflake.ts b/src/util/Snowflake.ts
new file mode 100644
index 00000000..9e94bbd9
--- /dev/null
+++ b/src/util/Snowflake.ts
@@ -0,0 +1,126 @@
+// @ts-nocheck
+
+// 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 = 0n; // max 31
+ static workerId = 0n; // 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;
+ }
+
+ /**
+ * 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) + 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/src/util/String.ts b/src/util/String.ts
new file mode 100644
index 00000000..afbfc1e6
--- /dev/null
+++ b/src/util/String.ts
@@ -0,0 +1,6 @@
+export const DOUBLE_WHITE_SPACE = /\s\s+/g;
+export const SPECIAL_CHAR = /[@#`:\r\n\t\f\v\p{C}]/gu;
+
+export function trimSpecial(str: string) {
+ return str.replace(SPECIAL_CHAR, "").replace(DOUBLE_WHITE_SPACE, " ").trim();
+}
diff --git a/src/util/UserFlags.ts b/src/util/UserFlags.ts
new file mode 100644
index 00000000..6e532f93
--- /dev/null
+++ b/src/util/UserFlags.ts
@@ -0,0 +1,22 @@
+// 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: 1n << 0n,
+ PARTNERED_SERVER_OWNER: 1n << 1n,
+ HYPESQUAD_EVENTS: 1n << 2n,
+ BUGHUNTER_LEVEL_1: 1n << 3n,
+ HOUSE_BRAVERY: 1n << 6n,
+ HOUSE_BRILLIANCE: 1n << 7n,
+ HOUSE_BALANCE: 1n << 8n,
+ EARLY_SUPPORTER: 1n << 9n,
+ TEAM_USER: 1n << 10n,
+ SYSTEM: 1n << 12n,
+ BUGHUNTER_LEVEL_2: 1n << 14n,
+ VERIFIED_BOT: 1n << 16n,
+ EARLY_VERIFIED_BOT_DEVELOPER: 1n << 17n,
+ };
+}
diff --git a/src/checkToken.ts b/src/util/checkToken.ts
index 96c7806a..96c7806a 100644
--- a/src/checkToken.ts
+++ b/src/util/checkToken.ts
|