Merge pull request #107 from DjDeveloperr/permissions

fix: use bigint for bitfield (permissions)
This commit is contained in:
DjDeveloper 2021-02-22 19:14:22 +05:30 committed by GitHub
commit 4d93d66757
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 75 additions and 70 deletions

View File

@ -1,35 +1,36 @@
// https://discord.com/developers/docs/topics/permissions#permissions-bitwise-permission-flags // https://discord.com/developers/docs/topics/permissions#permissions-bitwise-permission-flags
export const PermissionFlags: { [key: string]: number } = { export const PermissionFlags: { [key: string]: bigint } = {
CREATE_INSTANT_INVITE: 1 << 0, CREATE_INSTANT_INVITE: 1n << 0n,
KICK_MEMBERS: 1 << 1, KICK_MEMBERS: 1n << 1n,
BAN_MEMBERS: 1 << 2, BAN_MEMBERS: 1n << 2n,
ADMINISTRATOR: 1 << 3, ADMINISTRATOR: 1n << 3n,
MANAGE_CHANNELS: 1 << 4, MANAGE_CHANNELS: 1n << 4n,
MANAGE_GUILD: 1 << 5, MANAGE_GUILD: 1n << 5n,
ADD_REACTIONS: 1 << 6, ADD_REACTIONS: 1n << 6n,
VIEW_AUDIT_LOG: 1 << 7, VIEW_AUDIT_LOG: 1n << 7n,
PRIORITY_SPEAKER: 1 << 8, PRIORITY_SPEAKER: 1n << 8n,
STREAM: 1 << 9, STREAM: 1n << 9n,
VIEW_CHANNEL: 1 << 10, VIEW_CHANNEL: 1n << 10n,
SEND_MESSAGES: 1 << 11, SEND_MESSAGES: 1n << 11n,
SEND_TTS_MESSAGES: 1 << 12, SEND_TTS_MESSAGES: 1n << 12n,
MANAGE_MESSAGES: 1 << 13, MANAGE_MESSAGES: 1n << 13n,
EMBED_LINKS: 1 << 14, EMBED_LINKS: 1n << 14n,
ATTACH_FILES: 1 << 15, ATTACH_FILES: 1n << 15n,
READ_MESSAGE_HISTORY: 1 << 16, READ_MESSAGE_HISTORY: 1n << 16n,
MENTION_EVERYONE: 1 << 17, MENTION_EVERYONE: 1n << 17n,
USE_EXTERNAL_EMOJIS: 1 << 18, USE_EXTERNAL_EMOJIS: 1n << 18n,
VIEW_GUILD_INSIGHTS: 1 << 19, VIEW_GUILD_INSIGHTS: 1n << 19n,
CONNECT: 1 << 20, CONNECT: 1n << 20n,
SPEAK: 1 << 21, SPEAK: 1n << 21n,
MUTE_MEMBERS: 1 << 22, MUTE_MEMBERS: 1n << 22n,
DEAFEN_MEMBERS: 1 << 23, DEAFEN_MEMBERS: 1n << 23n,
MOVE_MEMBERS: 1 << 24, MOVE_MEMBERS: 1n << 24n,
USE_VAD: 1 << 25, USE_VAD: 1n << 25n,
CHANGE_NICKNAME: 1 << 26, CHANGE_NICKNAME: 1n << 26n,
MANAGE_NICKNAMES: 1 << 27, MANAGE_NICKNAMES: 1n << 27n,
MANAGE_ROLES: 1 << 28, MANAGE_ROLES: 1n << 28n,
MANAGE_WEBHOOKS: 1 << 29, MANAGE_WEBHOOKS: 1n << 29n,
MANAGE_EMOJIS: 1 << 30 MANAGE_EMOJIS: 1n << 30n,
USE_SLASH_COMMANDS: 1n << 31n
} }

View File

@ -6,34 +6,36 @@ export type BitFieldResolvable =
| string | string
| string[] | string[]
| BitField[] | BitField[]
| bigint
| Array<bigint>
/** Bit Field utility to work with Bits and Flags */ /** Bit Field utility to work with Bits and Flags */
export class BitField { export class BitField {
flags: { [name: string]: number } = {} #flags: { [name: string]: number | bigint } = {}
bitfield: number bitfield: bigint
constructor(flags: { [name: string]: number }, bits: any) { constructor(flags: { [name: string]: number | bigint }, bits: any) {
this.flags = flags this.#flags = flags
this.bitfield = BitField.resolve(this.flags, bits) this.bitfield = BitField.resolve(this.#flags, bits)
} }
any(bit: BitFieldResolvable): boolean { 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 { 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 { has(bit: BitFieldResolvable, ...args: any[]): boolean {
if (Array.isArray(bit)) return (bit.every as any)((p: any) => this.has(p)) 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 return (this.bitfield & bit) === bit
} }
missing(bits: any, ...hasParams: any[]): string[] { missing(bits: any, ...hasParams: any[]): string[] {
if (!Array.isArray(bits)) 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)) return bits.filter((p: any) => !this.has(p, ...hasParams))
} }
@ -42,48 +44,52 @@ export class BitField {
} }
add(...bits: BitFieldResolvable[]): BitField { add(...bits: BitFieldResolvable[]): BitField {
let total = 0 let total = 0n
for (const bit of bits) { for (const bit of bits) {
total |= BitField.resolve(this.flags, bit) total |= BitField.resolve(this.#flags, bit)
} }
if (Object.isFrozen(this)) if (Object.isFrozen(this))
return new BitField(this.flags, this.bitfield | total) return new BitField(this.#flags, this.bitfield | total)
this.bitfield |= total this.bitfield |= total
return this return this
} }
remove(...bits: BitFieldResolvable[]): BitField { remove(...bits: BitFieldResolvable[]): BitField {
let total = 0 let total = 0n
for (const bit of bits) { for (const bit of bits) {
total |= BitField.resolve(this.flags, bit) total |= BitField.resolve(this.#flags, bit)
} }
if (Object.isFrozen(this)) if (Object.isFrozen(this))
return new BitField(this.flags, this.bitfield & ~total) return new BitField(this.#flags, this.bitfield & ~total)
this.bitfield &= ~total this.bitfield &= ~total
return this return this
} }
serialize(...hasParams: any[]): { [key: string]: any } { flags(): { [name: string]: bigint | number } {
const serialized: { [key: string]: any } = {} return this.#flags
for (const [flag, bit] of Object.entries(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( serialized[flag] = this.has(
BitField.resolve(this.flags, bit), BitField.resolve(this.#flags, bit),
...hasParams ...hasParams
) )
return serialized return serialized
} }
toArray(...hasParams: any[]): string[] { toArray(...hasParams: any[]): string[] {
return Object.keys(this.flags).filter((bit) => return Object.keys(this.#flags).filter((bit) =>
this.has(BitField.resolve(this.flags, bit), ...hasParams) this.has(BitField.resolve(this.#flags, bit), ...hasParams)
) )
} }
toJSON(): number { toJSON(): string {
return this.bitfield return this.bitfield.toString()
} }
valueOf(): number { valueOf(): bigint {
return this.bitfield return this.bitfield
} }
@ -91,9 +97,10 @@ export class BitField {
yield* this.toArray() yield* this.toArray()
} }
static resolve(flags: any, bit: BitFieldResolvable = 0): number { static resolve(flags: any, bit: BitFieldResolvable = 0n): bigint {
if (typeof bit === 'string' && !isNaN(parseInt(bit))) return parseInt(bit) if (typeof bit === 'bigint') return bit
if (typeof bit === 'number' && bit >= 0) 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 (bit instanceof BitField) return this.resolve(flags, bit.bitfield)
if (Array.isArray(bit)) if (Array.isArray(bit))
return (bit.map as any)((p: any) => this.resolve(flags, p)).reduce( return (bit.map as any)((p: any) => this.resolve(flags, p)).reduce(

View File

@ -2,18 +2,15 @@
import { PermissionFlags } from '../types/permissionFlags.ts' import { PermissionFlags } from '../types/permissionFlags.ts'
import { BitField, BitFieldResolvable } from './bitfield.ts' import { BitField, BitFieldResolvable } from './bitfield.ts'
export type PermissionResolvable = export type PermissionResolvable = BitFieldResolvable
| string
| string[]
| number
| number[]
| Permissions
| PermissionResolvable[]
/** Manages Discord's Bit-based Permissions */ /** Manages Discord's Bit-based Permissions */
export class Permissions extends BitField { export class Permissions extends BitField {
static DEFAULT = 104324673 static DEFAULT = 104324673n
static ALL = Object.values(PermissionFlags).reduce((all, p) => all | p, 0) static ALL = Object.values(PermissionFlags).reduce(
(all, p) => BigInt(all) | BigInt(p),
0n
)
constructor(bits: BitFieldResolvable) { constructor(bits: BitFieldResolvable) {
super(PermissionFlags, bits) super(PermissionFlags, bits)
@ -21,14 +18,14 @@ export class Permissions extends BitField {
any(permission: PermissionResolvable, checkAdmin = true): boolean { any(permission: PermissionResolvable, checkAdmin = true): boolean {
return ( return (
(checkAdmin && super.has(this.flags.ADMINISTRATOR)) || (checkAdmin && super.has(this.flags().ADMINISTRATOR)) ||
super.any(permission as any) super.any(permission as any)
) )
} }
has(permission: PermissionResolvable, checkAdmin = true): boolean { has(permission: PermissionResolvable, checkAdmin = true): boolean {
return ( return (
(checkAdmin && super.has(this.flags.ADMINISTRATOR)) || (checkAdmin && super.has(this.flags().ADMINISTRATOR)) ||
super.has(permission as any) super.has(permission as any)
) )
} }