From 84baae279e40e0a7370748d15c55131545526bda Mon Sep 17 00:00:00 2001 From: DjDeveloperr Date: Sun, 21 Feb 2021 18:44:14 +0530 Subject: [PATCH] use bigint for bitfield (perms) --- src/types/permissionFlags.ts | 65 ++++++++++++++++++------------------ src/utils/bitfield.ts | 61 ++++++++++++++++++--------------- src/utils/permissions.ts | 19 +++++------ 3 files changed, 75 insertions(+), 70 deletions(-) diff --git a/src/types/permissionFlags.ts b/src/types/permissionFlags.ts index 9cb3040..928a16f 100644 --- a/src/types/permissionFlags.ts +++ b/src/types/permissionFlags.ts @@ -1,35 +1,36 @@ // https://discord.com/developers/docs/topics/permissions#permissions-bitwise-permission-flags -export const PermissionFlags: { [key: string]: number } = { - CREATE_INSTANT_INVITE: 1 << 0, - KICK_MEMBERS: 1 << 1, - BAN_MEMBERS: 1 << 2, - ADMINISTRATOR: 1 << 3, - MANAGE_CHANNELS: 1 << 4, - MANAGE_GUILD: 1 << 5, - ADD_REACTIONS: 1 << 6, - VIEW_AUDIT_LOG: 1 << 7, - PRIORITY_SPEAKER: 1 << 8, - STREAM: 1 << 9, - VIEW_CHANNEL: 1 << 10, - SEND_MESSAGES: 1 << 11, - SEND_TTS_MESSAGES: 1 << 12, - MANAGE_MESSAGES: 1 << 13, - EMBED_LINKS: 1 << 14, - ATTACH_FILES: 1 << 15, - READ_MESSAGE_HISTORY: 1 << 16, - MENTION_EVERYONE: 1 << 17, - USE_EXTERNAL_EMOJIS: 1 << 18, - VIEW_GUILD_INSIGHTS: 1 << 19, - CONNECT: 1 << 20, - SPEAK: 1 << 21, - MUTE_MEMBERS: 1 << 22, - DEAFEN_MEMBERS: 1 << 23, - MOVE_MEMBERS: 1 << 24, - USE_VAD: 1 << 25, - CHANGE_NICKNAME: 1 << 26, - MANAGE_NICKNAMES: 1 << 27, - MANAGE_ROLES: 1 << 28, - MANAGE_WEBHOOKS: 1 << 29, - MANAGE_EMOJIS: 1 << 30 +export const PermissionFlags: { [key: string]: bigint } = { + 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, + USE_SLASH_COMMANDS: 1n << 31n } diff --git a/src/utils/bitfield.ts b/src/utils/bitfield.ts index eb7a67c..8631f1f 100644 --- a/src/utils/bitfield.ts +++ b/src/utils/bitfield.ts @@ -6,34 +6,36 @@ export type BitFieldResolvable = | string | string[] | BitField[] + | bigint + | Array /** Bit Field utility to work with Bits and Flags */ export class BitField { - flags: { [name: string]: number } = {} - bitfield: number + #flags: { [name: string]: number | bigint } = {} + bitfield: bigint - constructor(flags: { [name: string]: number }, bits: any) { - this.flags = flags - this.bitfield = BitField.resolve(this.flags, bits) + constructor(flags: { [name: string]: number | bigint }, bits: any) { + this.#flags = flags + this.bitfield = BitField.resolve(this.#flags, bits) } any(bit: BitFieldResolvable): boolean { - return (this.bitfield & BitField.resolve(this.flags, bit)) !== 0 + return (this.bitfield & BitField.resolve(this.#flags, bit)) !== 0n } equals(bit: BitFieldResolvable): boolean { - return this.bitfield === BitField.resolve(this.flags, bit) + return this.bitfield === BitField.resolve(this.#flags, bit) } has(bit: BitFieldResolvable, ...args: any[]): boolean { if (Array.isArray(bit)) return (bit.every as any)((p: any) => this.has(p)) - bit = BitField.resolve(this.flags, bit) + bit = BitField.resolve(this.#flags, bit) return (this.bitfield & bit) === bit } missing(bits: any, ...hasParams: any[]): string[] { if (!Array.isArray(bits)) - bits = new BitField(this.flags, bits).toArray(false) + bits = new BitField(this.#flags, bits).toArray(false) return bits.filter((p: any) => !this.has(p, ...hasParams)) } @@ -42,48 +44,52 @@ export class BitField { } add(...bits: BitFieldResolvable[]): BitField { - let total = 0 + let total = 0n for (const bit of bits) { - total |= BitField.resolve(this.flags, bit) + total |= BitField.resolve(this.#flags, bit) } if (Object.isFrozen(this)) - return new BitField(this.flags, this.bitfield | total) + return new BitField(this.#flags, this.bitfield | total) this.bitfield |= total return this } remove(...bits: BitFieldResolvable[]): BitField { - let total = 0 + let total = 0n for (const bit of bits) { - total |= BitField.resolve(this.flags, bit) + total |= BitField.resolve(this.#flags, bit) } if (Object.isFrozen(this)) - return new BitField(this.flags, this.bitfield & ~total) + return new BitField(this.#flags, this.bitfield & ~total) this.bitfield &= ~total return this } - serialize(...hasParams: any[]): { [key: string]: any } { - const serialized: { [key: string]: any } = {} - for (const [flag, bit] of Object.entries(this.flags)) + flags(): { [name: string]: bigint | number } { + return this.#flags + } + + serialize(...hasParams: any[]): { [key: string]: boolean } { + const serialized: { [key: string]: boolean } = {} + for (const [flag, bit] of Object.entries(this.#flags)) serialized[flag] = this.has( - BitField.resolve(this.flags, bit), + BitField.resolve(this.#flags, bit), ...hasParams ) return serialized } toArray(...hasParams: any[]): string[] { - return Object.keys(this.flags).filter((bit) => - this.has(BitField.resolve(this.flags, bit), ...hasParams) + return Object.keys(this.#flags).filter((bit) => + this.has(BitField.resolve(this.#flags, bit), ...hasParams) ) } - toJSON(): number { - return this.bitfield + toJSON(): string { + return this.bitfield.toString() } - valueOf(): number { + valueOf(): bigint { return this.bitfield } @@ -91,9 +97,10 @@ export class BitField { yield* this.toArray() } - static resolve(flags: any, bit: BitFieldResolvable = 0): number { - if (typeof bit === 'string' && !isNaN(parseInt(bit))) return parseInt(bit) - if (typeof bit === 'number' && bit >= 0) return bit + static resolve(flags: any, bit: BitFieldResolvable = 0n): bigint { + if (typeof bit === 'bigint') return bit + if (typeof bit === 'string' && !isNaN(parseInt(bit))) return BigInt(bit) + if (typeof bit === 'number' && bit >= 0) return BigInt(bit) if (bit instanceof BitField) return this.resolve(flags, bit.bitfield) if (Array.isArray(bit)) return (bit.map as any)((p: any) => this.resolve(flags, p)).reduce( diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index 03b4b82..8d7a488 100644 --- a/src/utils/permissions.ts +++ b/src/utils/permissions.ts @@ -2,18 +2,15 @@ import { PermissionFlags } from '../types/permissionFlags.ts' import { BitField, BitFieldResolvable } from './bitfield.ts' -export type PermissionResolvable = - | string - | string[] - | number - | number[] - | Permissions - | PermissionResolvable[] +export type PermissionResolvable = BitFieldResolvable /** Manages Discord's Bit-based Permissions */ export class Permissions extends BitField { - static DEFAULT = 104324673 - static ALL = Object.values(PermissionFlags).reduce((all, p) => all | p, 0) + static DEFAULT = 104324673n + static ALL = Object.values(PermissionFlags).reduce( + (all, p) => BigInt(all) | BigInt(p), + 0n + ) constructor(bits: BitFieldResolvable) { super(PermissionFlags, bits) @@ -21,14 +18,14 @@ export class Permissions extends BitField { any(permission: PermissionResolvable, checkAdmin = true): boolean { return ( - (checkAdmin && super.has(this.flags.ADMINISTRATOR)) || + (checkAdmin && super.has(this.flags().ADMINISTRATOR)) || super.any(permission as any) ) } has(permission: PermissionResolvable, checkAdmin = true): boolean { return ( - (checkAdmin && super.has(this.flags.ADMINISTRATOR)) || + (checkAdmin && super.has(this.flags().ADMINISTRATOR)) || super.has(permission as any) ) }