From 66dd1ca4226fbce29c9a544e890c99275cd552bc Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Fri, 12 Feb 2021 18:41:03 +0600 Subject: [PATCH 01/23] feat: PermissionOverwriteManager --- src/managers/PermissionOverwriteManager.js | 137 +++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 src/managers/PermissionOverwriteManager.js diff --git a/src/managers/PermissionOverwriteManager.js b/src/managers/PermissionOverwriteManager.js new file mode 100644 index 000000000000..cd8fbb4ea5ce --- /dev/null +++ b/src/managers/PermissionOverwriteManager.js @@ -0,0 +1,137 @@ +'use strict'; + +const BaseManager = require('./BaseManager'); +const { TypeError } = require('../errors'); +const PermissionOverwrites = require('../structures/PermissionOverwrites'); +const Role = require('../structures/Role'); +const Collection = require('../util/Collection'); + +/** + * Manages API methods for guild channel permission overwrites and stores their cache. + * @extends {BaseManager} + */ +class PermissionOverwriteManager extends BaseManager { + constructor(channel, iterable) { + super(channel.client, iterable, PermissionOverwrites); + + /** + * The channel of the permission overwrite this manager belongs to + * @type {GuildChannel} + */ + this.channel = channel; + } + + /** + * The cache of this Manager + * @type {Collection} + * @name PermissionOverwriteManager#cache + */ + + add(data, cache) { + return super.add(data, cache, { extras: [this.channel] }); + } + + /** + * Replaces the permission overwrites in this channel. + * @param {OverwriteResolvable[]|Collection} overwrites + * Permission overwrites the channel gets updated with + * @param {string} [reason] Reason for updating the channel overwrites + * @returns {Promise} + * @example + * message.channel.permissionOverwrites.set([ + * { + * id: message.author.id, + * deny: [Permissions.FLAGS.VIEW_CHANNEL], + * }, + * ], 'Needed to change permissions'); + */ + async set(overwrites, reason) { + if (!Array.isArray(overwrites) && !(overwrites instanceof Collection)) { + throw new TypeError('INVALID_TYPE', 'overwrites', 'Array or Collection of Permission Overwrites', true); + } + await this.channel.edit({ permissionOverwrites: overwrites, reason }); + return this.channel; + } + + /** + * Edits permission overwrites for a user or role in this channel, or creates an entry if not already present. + * @param {RoleResolvable|UserResolvable} userOrRole The user or role to update + * @param {PermissionOverwriteOptions} options The options for the update + * @param {string} [reason] Reason for creating/editing this overwrite + * @returns {Promise} + * @example + * // Edit or Create permission overwrites for a message author + * message.channel.permissionOverwrites.edit(message.author, { + * SEND_MESSAGES: false + * }) + * .then(channel => console.log(channel.permissionOverwrites.cache.get(message.author.id))) + * .catch(console.error); + */ + async edit(userOrRole, options, reason) { + userOrRole = this.channel.guild.roles.resolve(userOrRole) ?? this.client.users.resolve(userOrRole); + if (!userOrRole) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role'); + + const type = userOrRole instanceof Role ? 'role' : 'member'; + const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options); + + const existing = this.cache.get(userOrRole.id); + if (existing) { + await this.client.api + .channels(this.channel.id) + .permissions(userOrRole.id) + .put({ + data: { id: userOrRole.id, type, allow, deny }, + reason, + }); + return this.channel; + } + return this.create(userOrRole, options, reason); + } + + /** + * Creates permission overwrites for a user or role in this channel, or replaces them if already present. + * @param {RoleResolvable|UserResolvable} userOrRole The user or role to update + * @param {PermissionOverwriteOptions} options The options for the update + * @param {string} [reason] Reason for creating/editing this overwrite + * @returns {Promise} + * @example + * // Create or Replace permission overwrites for a message author + * message.channel.permissionOverwrites.create(message.author, { + * SEND_MESSAGES: false + * }) + * .then(channel => console.log(channel.permissionOverwrites.cache.get(message.author.id))) + * .catch(console.error); + */ + async create(userOrRole, options, reason) { + userOrRole = this.channel.guild.roles.resolve(userOrRole) ?? this.client.users.resolve(userOrRole); + if (!userOrRole) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role'); + + const type = userOrRole instanceof Role ? 'role' : 'member'; + const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options); + + await this.client.api + .channels(this.channel.id) + .permissions(userOrRole.id) + .put({ + data: { id: userOrRole.id, type, allow, deny }, + reason, + }); + return this.channel; + } + + /** + * Deletes permission overwrites for a user or role in this channel + * @param {UserResolvable|RoleResolvable} userOrRole The user or role to delete + * @param {string} [reason] The reason for deleting the overwrite + * @returns {GuildChannel} + */ + async delete(userOrRole, reason) { + userOrRole = this.channel.guild.roles.resolve(userOrRole) ?? this.client.users.resolve(userOrRole); + if (!userOrRole) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role'); + + await this.client.api.channels(this.channel.id).permissions(userOrRole.id).delete({ reason }); + return this.channel; + } +} + +module.exports = PermissionOverwriteManager; From a8f38b5f8366d5636d6a36c97c967f811fa9ede9 Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Fri, 12 Feb 2021 18:42:20 +0600 Subject: [PATCH 02/23] refactor: GuildChannel --- src/structures/GuildChannel.js | 98 +++------------------------------- 1 file changed, 6 insertions(+), 92 deletions(-) diff --git a/src/structures/GuildChannel.js b/src/structures/GuildChannel.js index 1a53fc7f4177..3250fe57d39f 100644 --- a/src/structures/GuildChannel.js +++ b/src/structures/GuildChannel.js @@ -3,11 +3,10 @@ const Channel = require('./Channel'); const Invite = require('./Invite'); const PermissionOverwrites = require('./PermissionOverwrites'); -const Role = require('./Role'); -const { Error, TypeError } = require('../errors'); +const { Error } = require('../errors'); +const PermissionOverwriteManager = require('../managers/PermissionOverwriteManager'); const Collection = require('../util/Collection'); const { ChannelTypes } = require('../util/Constants'); -const { OverwriteTypes } = require('../util/Constants'); const Permissions = require('../util/Permissions'); const Util = require('../util/Util'); @@ -58,13 +57,13 @@ class GuildChannel extends Channel { this.parentID = data.parent_id || null; /** - * A map of permission overwrites in this channel for roles and users - * @type {Collection} + * A manager of permission overwrites that belong to this channel + * @type {PermissionOverwriteManager} */ - this.permissionOverwrites = new Collection(); + this.permissionOverwrites = new PermissionOverwriteManager(this); if (data.permission_overwrites) { for (const overwrite of data.permission_overwrites) { - this.permissionOverwrites.set(overwrite.id, new PermissionOverwrites(this, overwrite)); + this.permissionOverwrites.add(overwrite); } } } @@ -191,91 +190,6 @@ class GuildChannel extends Channel { .freeze(); } - /** - * Replaces the permission overwrites in this channel. - * @param {OverwriteResolvable[]|Collection} overwrites - * Permission overwrites the channel gets updated with - * @param {string} [reason] Reason for updating the channel overwrites - * @returns {Promise} - * @example - * channel.overwritePermissions([ - * { - * id: message.author.id, - * deny: [Permissions.FLAGS.VIEW_CHANNEL], - * }, - * ], 'Needed to change permissions'); - */ - async overwritePermissions(overwrites, reason) { - if (!Array.isArray(overwrites) && !(overwrites instanceof Collection)) { - throw new TypeError('INVALID_TYPE', 'overwrites', 'Array or Collection of Permission Overwrites', true); - } - await this.edit({ permissionOverwrites: overwrites, reason }); - return this; - } - - /** - * Updates permission overwrites for a user or role in this channel, or creates an entry if not already present. - * @param {RoleResolvable|UserResolvable} userOrRole The user or role to update - * @param {PermissionOverwriteOptions} options The options for the update - * @param {string} [reason] Reason for creating/editing this overwrite - * @returns {Promise} - * @example - * // Update or Create permission overwrites for a message author - * message.channel.updateOverwrite(message.author, { - * SEND_MESSAGES: false - * }) - * .then(channel => console.log(channel.permissionOverwrites.get(message.author.id))) - * .catch(console.error); - */ - async updateOverwrite(userOrRole, options, reason) { - userOrRole = this.guild.roles.resolve(userOrRole) || this.client.users.resolve(userOrRole); - if (!userOrRole) return Promise.reject(new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role')); - - const existing = this.permissionOverwrites.get(userOrRole.id); - if (existing) { - await existing.update(options, reason); - } else { - await this.createOverwrite(userOrRole, options, reason); - } - return this; - } - - /** - * Creates permission overwrites for a user or role in this channel, or replaces them if already present. - * @param {RoleResolvable|UserResolvable} userOrRole The user or role to update - * @param {PermissionOverwriteOptions} options The options for the update - * @param {string} [reason] Reason for creating/editing this overwrite - * @returns {Promise} - * @example - * // Create or Replace permission overwrites for a message author - * message.channel.createOverwrite(message.author, { - * SEND_MESSAGES: false - * }) - * .then(channel => console.log(channel.permissionOverwrites.get(message.author.id))) - * .catch(console.error); - */ - createOverwrite(userOrRole, options, reason) { - userOrRole = this.guild.roles.resolve(userOrRole) || this.client.users.resolve(userOrRole); - if (!userOrRole) return Promise.reject(new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role')); - - const type = userOrRole instanceof Role ? OverwriteTypes.role : OverwriteTypes.member; - const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options); - - return this.client.api - .channels(this.id) - .permissions(userOrRole.id) - .put({ - data: { - id: userOrRole.id, - type, - allow, - deny, - }, - reason, - }) - .then(() => this); - } - /** * Locks in the permission overwrites from the parent channel. * @returns {Promise} From 304a96e27b6da05b86031f2a2f62ae674f3f1d4a Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Fri, 12 Feb 2021 18:43:32 +0600 Subject: [PATCH 03/23] refactor: PermissionOverwrites --- src/structures/PermissionOverwrites.js | 32 +++++++++----------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/src/structures/PermissionOverwrites.js b/src/structures/PermissionOverwrites.js index b8990136c2f9..20a5968e38e5 100644 --- a/src/structures/PermissionOverwrites.js +++ b/src/structures/PermissionOverwrites.js @@ -1,5 +1,6 @@ 'use strict'; +const Base = require('./Base'); const Role = require('./Role'); const { TypeError } = require('../errors'); const { OverwriteTypes } = require('../util/Constants'); @@ -8,15 +9,17 @@ const Permissions = require('../util/Permissions'); /** * Represents a permission overwrite for a role or member in a guild channel. */ -class PermissionOverwrites { - constructor(guildChannel, data) { +class PermissionOverwrites extends Base { + constructor(client, data, channel) { + super(client); + /** * The GuildChannel this overwrite is for * @name PermissionOverwrites#channel * @type {GuildChannel} * @readonly */ - Object.defineProperty(this, 'channel', { value: guildChannel }); + Object.defineProperty(this, 'channel', { value: channel }); if (data) this._patch(data); } @@ -48,33 +51,20 @@ class PermissionOverwrites { } /** - * Updates this permissionOverwrites. + * Edits this Permission Overwrite. * @param {PermissionOverwriteOptions} options The options for the update * @param {string} [reason] Reason for creating/editing this overwrite * @returns {Promise} * @example * // Update permission overwrites - * permissionOverwrites.update({ + * permissionOverwrites.edit({ * SEND_MESSAGES: false * }) * .then(channel => console.log(channel.permissionOverwrites.get(message.author.id))) * .catch(console.error); */ - async update(options, reason) { - const { allow, deny } = this.constructor.resolveOverwriteOptions(options, this); - - await this.channel.client.api - .channels(this.channel.id) - .permissions(this.id) - .put({ - data: { - id: this.id, - type: OverwriteTypes[this.type], - allow, - deny, - }, - reason, - }); + async edit(options, reason) { + await this.channel.permissionOverwrites.edit(this.id, options, reason); return this; } @@ -84,7 +74,7 @@ class PermissionOverwrites { * @returns {Promise} */ async delete(reason) { - await this.channel.client.api.channels(this.channel.id).permissions(this.id).delete({ reason }); + await this.channel.permissionOverwrites.delete(this.id, reason); return this; } From aacc25cf91995a001cdd69493245a2c646129b0f Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Fri, 12 Feb 2021 18:44:51 +0600 Subject: [PATCH 04/23] typings: various stuff --- typings/index.d.ts | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 5f6874f37407..847902dceba0 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1175,14 +1175,14 @@ declare module 'discord.js' { public iconURL(options?: ImageURLOptions): string | null; } - export class PermissionOverwrites { - constructor(guildChannel: GuildChannel, data?: object); + export class PermissionOverwrites extends Base { + constructor(client: Client, data: object, channel: GuildChannel); public allow: Readonly; public readonly channel: GuildChannel; public deny: Readonly; public id: Snowflake; public type: OverwriteType; - public update(options: PermissionOverwriteOption, reason?: string): Promise; + public edit(options: PermissionOverwriteOption, reason?: string): Promise; public delete(reason?: string): Promise; public toJSON(): object; public static resolveOverwriteOptions( @@ -2000,6 +2000,28 @@ declare module 'discord.js' { constructor(client: Client, iterable?: Iterable); } + export class PermissionOverwriteManager extends BaseManager { + constructor(client: Client, iterable?: Iterable); + public set( + overwrites: readonly OverwriteResolvable[] | Collection, + reason?: string, + ): Promise; + public edit( + userOrRole: RoleResolvable | UserResolvable, + options: PermissionOverwriteOption, + reason?: string, + ): Promise; + public create( + userOrRole: RoleResolvable | UserResolvable, + options: PermissionOverwriteOption, + reason?: string, + ): Promise; + public delete( + userOrRole: RoleResolvable | UserResolvable, + reason?: string, + ): Promise; + } + export class ReactionManager extends BaseManager { constructor(message: Message, iterable?: Iterable); public message: Message; @@ -3014,6 +3036,8 @@ declare module 'discord.js' { type PermissionResolvable = BitFieldResolvable; + type PermissionOverwriteResolvable = Snowflake | PermissionOverwrites; + type PermissionString = | 'CREATE_INSTANT_INVITE' | 'KICK_MEMBERS' From b1b2e70b0018a72933c8658168b12caf60ef036f Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Fri, 12 Feb 2021 19:08:41 +0600 Subject: [PATCH 05/23] index: export PermissionOverwriteManager --- src/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.js b/src/index.js index d83e1bfa83e6..deee549112df 100644 --- a/src/index.js +++ b/src/index.js @@ -45,6 +45,7 @@ module.exports = { ReactionUserManager: require('./managers/ReactionUserManager'), MessageManager: require('./managers/MessageManager'), PresenceManager: require('./managers/PresenceManager'), + PermissionOverwriteManager: require('./managers/PermissionOverwriteManager'), RoleManager: require('./managers/RoleManager'), UserManager: require('./managers/UserManager'), From f15fbb4f896a56942e3897851b7f806965e37d7c Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Fri, 12 Feb 2021 19:09:50 +0600 Subject: [PATCH 06/23] esm: export PermissionOverwriteManager --- esm/discord.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/esm/discord.mjs b/esm/discord.mjs index d4625a0b9448..9b69da1680a8 100644 --- a/esm/discord.mjs +++ b/esm/discord.mjs @@ -40,6 +40,7 @@ export const { ReactionUserManager, MessageManager, PresenceManager, + PermisssionOverwriteManager, RoleManager, UserManager, discordSort, From 4b451da8fd53bf22181467b51145043c6919ab86 Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Fri, 12 Feb 2021 19:26:13 +0600 Subject: [PATCH 07/23] typings: fix order --- typings/index.d.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 847902dceba0..58df249ae0ee 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1996,10 +1996,6 @@ declare module 'discord.js' { public set(key: any): any; } - export class PresenceManager extends BaseManager { - constructor(client: Client, iterable?: Iterable); - } - export class PermissionOverwriteManager extends BaseManager { constructor(client: Client, iterable?: Iterable); public set( @@ -2022,6 +2018,10 @@ declare module 'discord.js' { ): Promise; } + export class PresenceManager extends BaseManager { + constructor(client: Client, iterable?: Iterable); + } + export class ReactionManager extends BaseManager { constructor(message: Message, iterable?: Iterable); public message: Message; From 255f7be8101a7da75d0cc437fd97720047182ea4 Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Fri, 12 Feb 2021 19:27:43 +0600 Subject: [PATCH 08/23] index: fix export order --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index deee549112df..ca15e57d7a98 100644 --- a/src/index.js +++ b/src/index.js @@ -44,8 +44,8 @@ module.exports = { ReactionManager: require('./managers/ReactionManager'), ReactionUserManager: require('./managers/ReactionUserManager'), MessageManager: require('./managers/MessageManager'), - PresenceManager: require('./managers/PresenceManager'), PermissionOverwriteManager: require('./managers/PermissionOverwriteManager'), + PresenceManager: require('./managers/PresenceManager'), RoleManager: require('./managers/RoleManager'), UserManager: require('./managers/UserManager'), From 32bec3086d464141365d0062b11f8661fc971144 Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Fri, 12 Feb 2021 19:28:43 +0600 Subject: [PATCH 09/23] esm: fix export order --- esm/discord.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esm/discord.mjs b/esm/discord.mjs index 9b69da1680a8..d8273945569d 100644 --- a/esm/discord.mjs +++ b/esm/discord.mjs @@ -39,8 +39,8 @@ export const { ReactionManager, ReactionUserManager, MessageManager, - PresenceManager, PermisssionOverwriteManager, + PresenceManager, RoleManager, UserManager, discordSort, From 38ea934ee39619897a908c317be5d474815da799 Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Fri, 12 Feb 2021 20:05:58 +0600 Subject: [PATCH 10/23] feat(PermissionOverwriteManager): make use of OverwriteTypes --- src/managers/PermissionOverwriteManager.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/managers/PermissionOverwriteManager.js b/src/managers/PermissionOverwriteManager.js index cd8fbb4ea5ce..bdaf9fed842b 100644 --- a/src/managers/PermissionOverwriteManager.js +++ b/src/managers/PermissionOverwriteManager.js @@ -5,6 +5,7 @@ const { TypeError } = require('../errors'); const PermissionOverwrites = require('../structures/PermissionOverwrites'); const Role = require('../structures/Role'); const Collection = require('../util/Collection'); +const { OverwriteTypes } = require('../util/Constants'); /** * Manages API methods for guild channel permission overwrites and stores their cache. @@ -71,7 +72,7 @@ class PermissionOverwriteManager extends BaseManager { userOrRole = this.channel.guild.roles.resolve(userOrRole) ?? this.client.users.resolve(userOrRole); if (!userOrRole) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role'); - const type = userOrRole instanceof Role ? 'role' : 'member'; + const type = userOrRole instanceof Role ? OverwriteTypes.role : OverwriteTypes.member; const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options); const existing = this.cache.get(userOrRole.id); @@ -106,7 +107,7 @@ class PermissionOverwriteManager extends BaseManager { userOrRole = this.channel.guild.roles.resolve(userOrRole) ?? this.client.users.resolve(userOrRole); if (!userOrRole) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role'); - const type = userOrRole instanceof Role ? 'role' : 'member'; + const type = userOrRole instanceof Role ? OverwriteTypes.role : OverwriteTypes.member; const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options); await this.client.api From d3ceb2b57cad551dd8a8673c1d741f62f64c32a4 Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Fri, 12 Feb 2021 20:19:39 +0600 Subject: [PATCH 11/23] typings: add more resolvables --- typings/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 58df249ae0ee..fd635b225532 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -3036,7 +3036,7 @@ declare module 'discord.js' { type PermissionResolvable = BitFieldResolvable; - type PermissionOverwriteResolvable = Snowflake | PermissionOverwrites; + type PermissionOverwriteResolvable = UserResolvable | RoleResolvable | PermissionOverwrites; type PermissionString = | 'CREATE_INSTANT_INVITE' From 83bf1889a7a0599f9f033c2a5fb5c0188b55be83 Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Mon, 10 May 2021 17:18:01 +0600 Subject: [PATCH 12/23] typings: rebase --- typings/index.d.ts | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 2e58a75ef491..db4c6321e4bc 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -779,7 +779,7 @@ declare module 'discord.js' { public name: string; public readonly parent: CategoryChannel | null; public parentID: Snowflake | null; - public permissionOverwrites: Collection; + public permissionOverwrites: PermissionOverwriteManager; public readonly permissionsLocked: boolean | null; public readonly position: number; public rawPosition: number; @@ -787,19 +787,10 @@ declare module 'discord.js' { public readonly viewable: boolean; public clone(options?: GuildChannelCloneOptions): Promise; public createInvite(options?: InviteOptions): Promise; - public createOverwrite( - userOrRole: RoleResolvable | UserResolvable, - options: PermissionOverwriteOption, - reason?: string, - ): Promise; public edit(data: ChannelData, reason?: string): Promise; public equals(channel: GuildChannel): boolean; public fetchInvites(): Promise>; public lockPermissions(): Promise; - public overwritePermissions( - overwrites: readonly OverwriteResolvable[] | Collection, - reason?: string, - ): Promise; public permissionsFor(memberOrRole: GuildMember | Role): Readonly; public permissionsFor(memberOrRole: GuildMemberResolvable | RoleResolvable): Readonly | null; public setName(name: string, reason?: string): Promise; @@ -809,11 +800,6 @@ declare module 'discord.js' { ): Promise; public setPosition(position: number, options?: { relative?: boolean; reason?: string }): Promise; public setTopic(topic: string | null, reason?: string): Promise; - public updateOverwrite( - userOrRole: RoleResolvable | UserResolvable, - options: PermissionOverwriteOption, - reason?: string, - ): Promise; public isText(): this is TextChannel | NewsChannel; } @@ -2058,12 +2044,6 @@ declare module 'discord.js' { public delete(message: MessageResolvable): Promise; } - // Hacky workaround because changing the signature of an overridden method errors - class OverridableManager extends BaseManager { - public add(data: any, cache: any): any; - public set(key: any): any; - } - export class PermissionOverwriteManager extends BaseManager { constructor(client: Client, iterable?: Iterable); public set( From 48f3550a6e0ac4fb432605f6d67d79ada74d432e Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Tue, 11 May 2021 23:37:00 +0600 Subject: [PATCH 13/23] feat: address requested changes --- src/managers/PermissionOverwriteManager.js | 99 ++++++++++++---------- 1 file changed, 55 insertions(+), 44 deletions(-) diff --git a/src/managers/PermissionOverwriteManager.js b/src/managers/PermissionOverwriteManager.js index bdaf9fed842b..b503105a4ca4 100644 --- a/src/managers/PermissionOverwriteManager.js +++ b/src/managers/PermissionOverwriteManager.js @@ -46,54 +46,57 @@ class PermissionOverwriteManager extends BaseManager { * }, * ], 'Needed to change permissions'); */ - async set(overwrites, reason) { + set(overwrites, reason) { if (!Array.isArray(overwrites) && !(overwrites instanceof Collection)) { throw new TypeError('INVALID_TYPE', 'overwrites', 'Array or Collection of Permission Overwrites', true); } - await this.channel.edit({ permissionOverwrites: overwrites, reason }); - return this.channel; + return this.channel.edit({ permissionOverwrites: overwrites, reason }); } /** - * Edits permission overwrites for a user or role in this channel, or creates an entry if not already present. + * Extra information about the overwrite + * @typedef {Object} GuildChannelOverwriteOptions + * @property {string} [reason] Reason for creating/editing this overwrite + * @property {number} [type] The type of overwrite, either `0` for a role or `1` for a member. Use this to bypass + * automatic resolution of type that results in an error for uncached structure + */ + + /** + * Creates or edits permission overwrites for a user or role in this channel. * @param {RoleResolvable|UserResolvable} userOrRole The user or role to update * @param {PermissionOverwriteOptions} options The options for the update - * @param {string} [reason] Reason for creating/editing this overwrite + * @param {GuildChannelOverwriteOptions} [overwriteOptions] The extra information for the update + * @param {PermissionOverwrites} [existing] The existing overwrites to merge with this update * @returns {Promise} - * @example - * // Edit or Create permission overwrites for a message author - * message.channel.permissionOverwrites.edit(message.author, { - * SEND_MESSAGES: false - * }) - * .then(channel => console.log(channel.permissionOverwrites.cache.get(message.author.id))) - * .catch(console.error); */ - async edit(userOrRole, options, reason) { - userOrRole = this.channel.guild.roles.resolve(userOrRole) ?? this.client.users.resolve(userOrRole); - if (!userOrRole) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role'); + async upsert(userOrRole, options, overwriteOptions = {}, existing) { + let userOrRoleID = this.channel.guild.roles.resolveID(userOrRole) ?? this.client.users.resolveID(userOrRole); + let { type, reason } = overwriteOptions; + if (typeof type !== 'number') { + userOrRole = this.channel.guild.roles.resolve(userOrRole) ?? this.client.users.resolve(userOrRole); + if (!userOrRole) return Promise.reject(new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role')); + type = userOrRole instanceof Role ? OverwriteTypes.role : OverwriteTypes.member; + } - const type = userOrRole instanceof Role ? OverwriteTypes.role : OverwriteTypes.member; - const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options); + const { allow, deny } = existing + ? PermissionOverwrites.resolveOverwriteOptions(options) + : PermissionOverwrites.resolveOverwriteOptions(options, existing); - const existing = this.cache.get(userOrRole.id); - if (existing) { - await this.client.api - .channels(this.channel.id) - .permissions(userOrRole.id) - .put({ - data: { id: userOrRole.id, type, allow, deny }, - reason, - }); - return this.channel; - } - return this.create(userOrRole, options, reason); + await this.client.api + .channels(this.channel.id) + .permissions(userOrRoleID) + .put({ + data: { id: userOrRoleID, type, allow, deny }, + reason, + }); + return this.channel; } /** * Creates permission overwrites for a user or role in this channel, or replaces them if already present. * @param {RoleResolvable|UserResolvable} userOrRole The user or role to update * @param {PermissionOverwriteOptions} options The options for the update - * @param {string} [reason] Reason for creating/editing this overwrite + * @param {GuildChannelOverwriteOptions} [overwriteOptions] The extra information for the update * @returns {Promise} * @example * // Create or Replace permission overwrites for a message author @@ -103,21 +106,29 @@ class PermissionOverwriteManager extends BaseManager { * .then(channel => console.log(channel.permissionOverwrites.cache.get(message.author.id))) * .catch(console.error); */ - async create(userOrRole, options, reason) { - userOrRole = this.channel.guild.roles.resolve(userOrRole) ?? this.client.users.resolve(userOrRole); - if (!userOrRole) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role'); - - const type = userOrRole instanceof Role ? OverwriteTypes.role : OverwriteTypes.member; - const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options); + create(userOrRole, options, overwriteOptions) { + return this.upsert(userOrRole, options, overwriteOptions); + } - await this.client.api - .channels(this.channel.id) - .permissions(userOrRole.id) - .put({ - data: { id: userOrRole.id, type, allow, deny }, - reason, - }); - return this.channel; + /** + * Edits permission overwrites for a user or role in this channel, or creates an entry if not already present. + * @param {RoleResolvable|UserResolvable} userOrRole The user or role to update + * @param {PermissionOverwriteOptions} options The options for the update + * @param {GuildChannelOverwriteOptions} [overwriteOptions] The extra information for the update + * @returns {Promise} + * @example + * // Edit or Create permission overwrites for a message author + * message.channel.permissionOverwrites.edit(message.author, { + * SEND_MESSAGES: false + * }) + * .then(channel => console.log(channel.permissionOverwrites.cache.get(message.author.id))) + * .catch(console.error); + */ + edit(userOrRole, options, overwriteOptions) { + userOrRole = this.channel.guild.roles.resolveID(userOrRole) ?? this.client.users.resolveID(userOrRole); + const existing = this.cache.get(userOrRole); + if (existing) return this.upsert(userOrRole, options, overwriteOptions, existing); + return this.create(userOrRole, options, overwriteOptions); } /** From eda6462e3778ac0a19dfa6dc23e36c6ca98edfaa Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Tue, 11 May 2021 23:39:05 +0600 Subject: [PATCH 14/23] typings: +1 --- typings/index.d.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index db4c6321e4bc..6ca36d8bc6e1 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2050,15 +2050,21 @@ declare module 'discord.js' { overwrites: readonly OverwriteResolvable[] | Collection, reason?: string, ): Promise; - public edit( + public upsert( userOrRole: RoleResolvable | UserResolvable, options: PermissionOverwriteOption, - reason?: string, + overwriteOptions?: GuildChannelOverwriteOptions, + existing?: PermissionOverwrites, ): Promise; public create( userOrRole: RoleResolvable | UserResolvable, options: PermissionOverwriteOption, - reason?: string, + overwriteOptions?: GuildChannelOverwriteOptions, + ): Promise; + public edit( + userOrRole: RoleResolvable | UserResolvable, + options: PermissionOverwriteOption, + overwriteOptions?: GuildChannelOverwriteOptions, ): Promise; public delete( userOrRole: RoleResolvable | UserResolvable, @@ -2693,6 +2699,11 @@ declare module 'discord.js' { interface GuildChannelCloneOptions extends GuildCreateChannelOptions { name?: string; } + + interface GuildChannelOverwriteOptions { + reason?: string; + type?: number; + } interface GuildCreateOptions { afkChannelID?: number; From 98d1c7f9e86eb73d0acb7fe3cffe0b5cb3d637a5 Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Wed, 12 May 2021 00:07:51 +0600 Subject: [PATCH 15/23] feat: remove unnecessary check Co-authored-by: Vlad Frangu --- src/managers/PermissionOverwriteManager.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/managers/PermissionOverwriteManager.js b/src/managers/PermissionOverwriteManager.js index b503105a4ca4..0b419005f5f1 100644 --- a/src/managers/PermissionOverwriteManager.js +++ b/src/managers/PermissionOverwriteManager.js @@ -78,9 +78,7 @@ class PermissionOverwriteManager extends BaseManager { type = userOrRole instanceof Role ? OverwriteTypes.role : OverwriteTypes.member; } - const { allow, deny } = existing - ? PermissionOverwrites.resolveOverwriteOptions(options) - : PermissionOverwrites.resolveOverwriteOptions(options, existing); + const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options, existing); await this.client.api .channels(this.channel.id) From 358aa739120306c23f8a5d27daa2678efcf7c884 Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Wed, 12 May 2021 00:08:34 +0600 Subject: [PATCH 16/23] feat: remove unnecessary check x2 Co-authored-by: Vlad Frangu --- src/managers/PermissionOverwriteManager.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/managers/PermissionOverwriteManager.js b/src/managers/PermissionOverwriteManager.js index 0b419005f5f1..dc2e259a4072 100644 --- a/src/managers/PermissionOverwriteManager.js +++ b/src/managers/PermissionOverwriteManager.js @@ -125,8 +125,7 @@ class PermissionOverwriteManager extends BaseManager { edit(userOrRole, options, overwriteOptions) { userOrRole = this.channel.guild.roles.resolveID(userOrRole) ?? this.client.users.resolveID(userOrRole); const existing = this.cache.get(userOrRole); - if (existing) return this.upsert(userOrRole, options, overwriteOptions, existing); - return this.create(userOrRole, options, overwriteOptions); + return this.upsert(userOrRole, options, overwriteOptions, existing); } /** From 814fc7034c9fcf03e5bc1205e7adb3e4091a9f50 Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Wed, 12 May 2021 00:44:28 +0600 Subject: [PATCH 17/23] feat: more changes! --- src/structures/PermissionOverwrites.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/PermissionOverwrites.js b/src/structures/PermissionOverwrites.js index 20a5968e38e5..a99e95e49053 100644 --- a/src/structures/PermissionOverwrites.js +++ b/src/structures/PermissionOverwrites.js @@ -64,7 +64,7 @@ class PermissionOverwrites extends Base { * .catch(console.error); */ async edit(options, reason) { - await this.channel.permissionOverwrites.edit(this.id, options, reason); + await this.channel.permissionOverwrites.upsert(this.id, options, { type: OverwriteTypes[this.type], reason }, this); return this; } From 7b57c30439853e461f4bbd3bbfddb94ec9082aa2 Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Wed, 12 May 2021 00:45:31 +0600 Subject: [PATCH 18/23] feat: missed change --- src/managers/PermissionOverwriteManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/PermissionOverwriteManager.js b/src/managers/PermissionOverwriteManager.js index dc2e259a4072..8fff3b4bf5a9 100644 --- a/src/managers/PermissionOverwriteManager.js +++ b/src/managers/PermissionOverwriteManager.js @@ -135,7 +135,7 @@ class PermissionOverwriteManager extends BaseManager { * @returns {GuildChannel} */ async delete(userOrRole, reason) { - userOrRole = this.channel.guild.roles.resolve(userOrRole) ?? this.client.users.resolve(userOrRole); + userOrRole = this.channel.guild.roles.resolveID(userOrRole) ?? this.client.users.resolveID(userOrRole); if (!userOrRole) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role'); await this.client.api.channels(this.channel.id).permissions(userOrRole.id).delete({ reason }); From f01e805e86b6ebe92fe3a3141bb39b31224ddcbf Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Wed, 12 May 2021 01:12:26 +0600 Subject: [PATCH 19/23] typings: fix fucked up trailing whitespace --- typings/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 6ca36d8bc6e1..3c82d119a7a9 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2699,7 +2699,7 @@ declare module 'discord.js' { interface GuildChannelCloneOptions extends GuildCreateChannelOptions { name?: string; } - + interface GuildChannelOverwriteOptions { reason?: string; type?: number; From a6fa160d39492063dc35451a28489c0105994ca8 Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Fri, 28 May 2021 16:31:43 +0600 Subject: [PATCH 20/23] feat: use PermissionOverwriteOptions over PermissionOverwriteOption --- typings/index.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/typings/index.d.ts b/typings/index.d.ts index 7bbe47bf32b4..35092984d352 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2229,18 +2229,18 @@ declare module 'discord.js' { ): Promise; public upsert( userOrRole: RoleResolvable | UserResolvable, - options: PermissionOverwriteOption, + options: PermissionOverwriteOptions, overwriteOptions?: GuildChannelOverwriteOptions, existing?: PermissionOverwrites, ): Promise; public create( userOrRole: RoleResolvable | UserResolvable, - options: PermissionOverwriteOption, + options: PermissionOverwriteOptions, overwriteOptions?: GuildChannelOverwriteOptions, ): Promise; public edit( userOrRole: RoleResolvable | UserResolvable, - options: PermissionOverwriteOption, + options: PermissionOverwriteOptions, overwriteOptions?: GuildChannelOverwriteOptions, ): Promise; public delete( From 73d8beb3ab2b7e314f23fc5b60d33a2aeee60a3b Mon Sep 17 00:00:00 2001 From: Ishmaam Khan Date: Mon, 7 Jun 2021 00:16:09 +0600 Subject: [PATCH 21/23] feat: delete index.mjs --- esm/discord.mjs | 110 ------------------------------------------------ 1 file changed, 110 deletions(-) delete mode 100644 esm/discord.mjs diff --git a/esm/discord.mjs b/esm/discord.mjs deleted file mode 100644 index dea127672fe6..000000000000 --- a/esm/discord.mjs +++ /dev/null @@ -1,110 +0,0 @@ -import Discord from '../src/index.js'; - -export default Discord; - -export const { - BaseClient, - Client, - Shard, - ShardClientUtil, - ShardingManager, - WebhookClient, - ActivityFlags, - ApplicationFlags, - BitField, - Collection, - Constants, - DataResolver, - BaseManager, - DiscordAPIError, - HTTPError, - MessageFlags, - Intents, - Permissions, - Speaking, - SnowflakeUtil, - Structures, - SystemChannelFlags, - UserFlags, - Util, - version, - ApplicationCommandManager, - BaseGuildEmojiManager, - ChannelManager, - GuildApplicationCommandManager, - GuildBanManager, - GuildChannelManager, - GuildEmojiManager, - GuildEmojiRoleManager, - GuildMemberManager, - GuildMemberRoleManager, - GuildManager, - ReactionManager, - ReactionUserManager, - MessageManager, - PermisssionOverwriteManager, - PresenceManager, - RoleManager, - UserManager, - discordSort, - escapeMarkdown, - fetchRecommendedShards, - resolveColor, - verifyString, - splitMessage, - Application, - ApplicationCommand, - Base, - Activity, - APIMessage, - BaseGuild, - BaseGuildEmoji, - BaseGuildVoiceChannel, - CategoryChannel, - Channel, - ClientApplication, - ClientUser, - Collector, - CommandInteraction, - DMChannel, - Emoji, - Guild, - GuildAuditLogs, - GuildBan, - GuildChannel, - GuildEmoji, - GuildMember, - GuildPreview, - GuildTemplate, - Integration, - IntegrationApplication, - Interaction, - Invite, - Message, - MessageAttachment, - MessageCollector, - MessageEmbed, - MessageMentions, - MessageReaction, - NewsChannel, - OAuth2Guild, - PermissionOverwrites, - Presence, - ClientPresence, - ReactionCollector, - ReactionEmoji, - RichPresenceAssets, - Role, - Sticker, - StoreChannel, - StageChannel, - Team, - TeamMember, - TextChannel, - User, - VoiceChannel, - VoiceRegion, - VoiceState, - Webhook, - WebSocket -} = Discord; From 370019929f83da13a311ac51ad5863343d19d165 Mon Sep 17 00:00:00 2001 From: extroonie Date: Wed, 23 Jun 2021 01:13:01 +0600 Subject: [PATCH 22/23] feat: address requested changes --- src/managers/PermissionOverwriteManager.js | 3 ++- src/structures/GuildChannel.js | 11 +++++------ src/structures/PermissionOverwrites.js | 1 + typings/index.d.ts | 13 +++++++------ 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/managers/PermissionOverwriteManager.js b/src/managers/PermissionOverwriteManager.js index 8fff3b4bf5a9..bd619828124d 100644 --- a/src/managers/PermissionOverwriteManager.js +++ b/src/managers/PermissionOverwriteManager.js @@ -68,6 +68,7 @@ class PermissionOverwriteManager extends BaseManager { * @param {GuildChannelOverwriteOptions} [overwriteOptions] The extra information for the update * @param {PermissionOverwrites} [existing] The existing overwrites to merge with this update * @returns {Promise} + * @private */ async upsert(userOrRole, options, overwriteOptions = {}, existing) { let userOrRoleID = this.channel.guild.roles.resolveID(userOrRole) ?? this.client.users.resolveID(userOrRole); @@ -129,7 +130,7 @@ class PermissionOverwriteManager extends BaseManager { } /** - * Deletes permission overwrites for a user or role in this channel + * Deletes permission overwrites for a user or role in this channel. * @param {UserResolvable|RoleResolvable} userOrRole The user or role to delete * @param {string} [reason] The reason for deleting the overwrite * @returns {GuildChannel} diff --git a/src/structures/GuildChannel.js b/src/structures/GuildChannel.js index 916568b5065e..a13281ef9c1f 100644 --- a/src/structures/GuildChannel.js +++ b/src/structures/GuildChannel.js @@ -36,7 +36,11 @@ class GuildChannel extends Channel { this.guild = guild; this.parentID = this.parentID ?? null; - this.permissionOverwrites = this.permissionOverwrites ?? new Collection(); + /** + * A manager of permission overwrites that belong to this channel + * @type {PermissionOverwriteManager} + */ + this.permissionOverwrites = new PermissionOverwriteManager(this); } _patch(data) { @@ -66,11 +70,6 @@ class GuildChannel extends Channel { this.parentID = data.parent_id; } - /** - * A manager of permission overwrites that belong to this channel - * @type {PermissionOverwriteManager} - */ - this.permissionOverwrites = new PermissionOverwriteManager(this); if ('permission_overwrites' in data) { for (const overwrite of data.permission_overwrites) { this.permissionOverwrites.add(overwrite); diff --git a/src/structures/PermissionOverwrites.js b/src/structures/PermissionOverwrites.js index 1300021982b4..8626fbf5b3e1 100644 --- a/src/structures/PermissionOverwrites.js +++ b/src/structures/PermissionOverwrites.js @@ -8,6 +8,7 @@ const Permissions = require('../util/Permissions'); /** * Represents a permission overwrite for a role or member in a guild channel. + * @extends {Base} */ class PermissionOverwrites extends Base { constructor(client, data, channel) { diff --git a/typings/index.d.ts b/typings/index.d.ts index 35c00e8a8cb7..d3e49c4817cf 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2281,13 +2281,17 @@ declare module 'discord.js' { public unpin(message: MessageResolvable): Promise; } - export class PermissionOverwriteManager extends BaseManager { + export class PermissionOverwriteManager extends BaseManager< + Snowflake, + PermissionOverwrites, + PermissionOverwriteResolvable + > { constructor(client: Client, iterable?: Iterable); public set( overwrites: readonly OverwriteResolvable[] | Collection, reason?: string, ): Promise; - public upsert( + private upsert( userOrRole: RoleResolvable | UserResolvable, options: PermissionOverwriteOptions, overwriteOptions?: GuildChannelOverwriteOptions, @@ -2303,10 +2307,7 @@ declare module 'discord.js' { options: PermissionOverwriteOptions, overwriteOptions?: GuildChannelOverwriteOptions, ): Promise; - public delete( - userOrRole: RoleResolvable | UserResolvable, - reason?: string, - ): Promise; + public delete(userOrRole: RoleResolvable | UserResolvable, reason?: string): Promise; } export class PresenceManager extends BaseManager { From c6120293a6b14b78c3416955129cbe0bc3a1bce4 Mon Sep 17 00:00:00 2001 From: extroonie Date: Sat, 3 Jul 2021 01:04:59 +0600 Subject: [PATCH 23/23] feat: address requested changes x2 --- src/structures/GuildChannel.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/structures/GuildChannel.js b/src/structures/GuildChannel.js index c011ef3a444f..e7848e397c2e 100644 --- a/src/structures/GuildChannel.js +++ b/src/structures/GuildChannel.js @@ -27,7 +27,7 @@ class GuildChannel extends Channel { * @param {APIChannel} data The data for the guild channel */ constructor(guild, data) { - super(guild.client, data); + super(guild.client, data, false); /** * The guild the channel is in @@ -41,6 +41,8 @@ class GuildChannel extends Channel { * @type {PermissionOverwriteManager} */ this.permissionOverwrites = new PermissionOverwriteManager(this); + + this._patch(data); } _patch(data) { @@ -71,6 +73,7 @@ class GuildChannel extends Channel { } if ('permission_overwrites' in data) { + this.permissionOverwrites.cache.clear(); for (const overwrite of data.permission_overwrites) { this.permissionOverwrites.add(overwrite); }