diff --git a/src/models/commandClient.ts b/src/models/commandClient.ts index 94d01ba..67d121d 100644 --- a/src/models/commandClient.ts +++ b/src/models/commandClient.ts @@ -1,6 +1,5 @@ import { Message } from '../structures/message.ts' import { GuildTextChannel } from '../structures/textChannel.ts' -import { awaitSync } from '../utils/mixedPromise.ts' import { Client, ClientOptions } from './client.ts' import { CategoriesManager, @@ -129,35 +128,29 @@ export class CommandClient extends Client implements CommandClientOptions { async processMessage(msg: Message): Promise { if (!this.allowBots && msg.author.bot === true) return - const isUserBlacklisted = await awaitSync( - this.isUserBlacklisted(msg.author.id) - ) - if (isUserBlacklisted === true) return + const isUserBlacklisted = await this.isUserBlacklisted(msg.author.id) + if (isUserBlacklisted) return - const isChannelBlacklisted = await awaitSync( - this.isChannelBlacklisted(msg.channel.id) - ) - if (isChannelBlacklisted === true) return + const isChannelBlacklisted = await this.isChannelBlacklisted(msg.channel.id) + if (isChannelBlacklisted) return if (msg.guild !== undefined) { - const isGuildBlacklisted = await awaitSync( - this.isGuildBlacklisted(msg.guild.id) - ) - if (isGuildBlacklisted === true) return + const isGuildBlacklisted = await this.isGuildBlacklisted(msg.guild.id) + if (isGuildBlacklisted) return } let prefix: string | string[] = [] if (typeof this.prefix === 'string') prefix = [...prefix, this.prefix] else prefix = [...prefix, ...this.prefix] - const userPrefix = await awaitSync(this.getUserPrefix(msg.author.id)) + const userPrefix = await this.getUserPrefix(msg.author.id) if (userPrefix !== undefined) { if (typeof userPrefix === 'string') prefix = [...prefix, userPrefix] else prefix = [...prefix, ...userPrefix] } if (msg.guild !== undefined) { - const guildPrefix = await awaitSync(this.getGuildPrefix(msg.guild.id)) + const guildPrefix = await this.getGuildPrefix(msg.guild.id) if (guildPrefix !== undefined) { if (typeof guildPrefix === 'string') prefix = [...prefix, guildPrefix] else prefix = [...prefix, ...guildPrefix] @@ -361,10 +354,10 @@ export class CommandClient extends Client implements CommandClientOptions { try { this.emit('commandUsed', ctx) - const beforeExecute = await awaitSync(command.beforeExecute(ctx)) + const beforeExecute = await command.beforeExecute(ctx) if (beforeExecute === false) return - const result = await awaitSync(command.execute(ctx)) + const result = await command.execute(ctx) command.afterExecute(ctx, result) } catch (e) { this.emit('commandError', ctx, e) diff --git a/src/test/index.ts b/src/test/index.ts index 1d3d7d9..ba93b2a 100644 --- a/src/test/index.ts +++ b/src/test/index.ts @@ -201,7 +201,7 @@ client.on('messageCreate', async (msg: Message) => { ) .join('\n\n')}` ) - } else if (msg.content === '!getPermissions') { + } else if (msg.content === '!perms') { if (msg.channel.type !== ChannelTypes.GUILD_TEXT) { return msg.channel.send("This isn't a guild text channel!") } @@ -210,7 +210,11 @@ client.on('messageCreate', async (msg: Message) => { // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion msg.member as Member ) - msg.channel.send(`Your permissions:\n${permissions.toArray().join('\n')}`) + msg.channel.send( + Object.entries(permissions.serialize()) + .map((e) => `${e[0]}: ${e[1] === true ? '`✅`' : '`❌`'}`) + .join('\n') + ) } }) 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 d2f5f03..8631f1f 100644 --- a/src/utils/bitfield.ts +++ b/src/utils/bitfield.ts @@ -6,19 +6,21 @@ 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) { + 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 { @@ -42,7 +44,7 @@ export class BitField { } add(...bits: BitFieldResolvable[]): BitField { - let total = 0 + let total = 0n for (const bit of bits) { total |= BitField.resolve(this.#flags, bit) } @@ -53,7 +55,7 @@ export class BitField { } remove(...bits: BitFieldResolvable[]): BitField { - let total = 0 + let total = 0n for (const bit of bits) { total |= BitField.resolve(this.#flags, bit) } @@ -63,12 +65,12 @@ export class BitField { return this } - flags(): { [name: string]: number } { + flags(): { [name: string]: bigint | number } { return this.#flags } - serialize(...hasParams: any[]): { [key: string]: any } { - const serialized: { [key: string]: any } = {} + 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), @@ -83,11 +85,11 @@ export class BitField { ) } - toJSON(): number { - return this.bitfield + toJSON(): string { + return this.bitfield.toString() } - valueOf(): number { + valueOf(): bigint { return this.bitfield } @@ -95,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/mixedPromise.ts b/src/utils/mixedPromise.ts deleted file mode 100644 index 4f1b297..0000000 --- a/src/utils/mixedPromise.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const awaitSync = async (val: any | Promise): Promise => { - return val instanceof Promise ? await val : val -} diff --git a/src/utils/permissions.ts b/src/utils/permissions.ts index 99b258e..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)