Merge pull request #107 from DjDeveloperr/permissions
fix: use bigint for bitfield (permissions)
This commit is contained in:
		
						commit
						4d93d66757
					
				
					 3 changed files with 75 additions and 70 deletions
				
			
		|  | @ -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 | ||||
| } | ||||
|  |  | |||
|  | @ -6,34 +6,36 @@ export type BitFieldResolvable = | |||
|   | string | ||||
|   | string[] | ||||
|   | BitField[] | ||||
|   | bigint | ||||
|   | Array<bigint> | ||||
| 
 | ||||
| /** 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( | ||||
|  |  | |||
|  | @ -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) | ||||
|     ) | ||||
|   } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue