From 64cbb98fb3c23f97e2c6535c5501480c123090c6 Mon Sep 17 00:00:00 2001 From: bdistin Date: Mon, 11 Sep 2017 12:33:30 -0500 Subject: [PATCH] Channel permissionLock support (syncing with category permissions) (#1924) * add permissionsLocked * wip permissionLock() * should be good * better method name * see if this fixes channel jumping * fix property names * each overwrite is a different instance, and thus the pointers do not equal, even if the values do. * add more documentation to the edit method --- src/errors/Messages.js | 1 + src/structures/GuildChannel.js | 46 ++++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/errors/Messages.js b/src/errors/Messages.js index d1d2535df..60e010a06 100644 --- a/src/errors/Messages.js +++ b/src/errors/Messages.js @@ -79,6 +79,7 @@ const Messages = { MESSAGE_SPLIT_MISSING: 'Message exceeds the max length and contains no split characters.', GUILD_CHANNEL_RESOLVE: 'Could not resolve channel to a guild channel.', + GUILD_CHANNEL_ORPHAN: 'Could not find a parent to this guild channel.', GUILD_OWNED: 'Guild is owned by the client.', GUILD_RESTRICTED: (state = false) => `Guild is ${state ? 'already' : 'not'} restricted.`, GUILD_MEMBERS_TIMEOUT: 'Members didn\'t arrive in time.', diff --git a/src/structures/GuildChannel.js b/src/structures/GuildChannel.js index 9a03e5b46..c1b9043f2 100644 --- a/src/structures/GuildChannel.js +++ b/src/structures/GuildChannel.js @@ -6,7 +6,7 @@ const Util = require('../util/Util'); const Permissions = require('../util/Permissions'); const Collection = require('../util/Collection'); const Constants = require('../util/Constants'); -const { TypeError } = require('../errors'); +const { Error, TypeError } = require('../errors'); /** * Represents a guild channel (e.g. text channels and voice channels). @@ -65,6 +65,22 @@ class GuildChannel extends Channel { return this.guild.channels.get(this.parentID); } + /** + * If the permissionOverwrites match the parent channel, null if no parent + * @type {?boolean} + * @readonly + */ + get permissionsLocked() { + if (!this.parent) return null; + if (this.permissionOverwrites.size !== this.parent.permissionOverwrites.size) return false; + return !this.permissionOverwrites.find((value, key) => { + const testVal = this.parent.permissionOverwrites.get(key); + return testVal === undefined || + testVal.denied.bitfield !== value.denied.bitfield || + testVal.allowed.bitfield !== value.allowed.bitfield; + }); + } + /** * The position of the channel * @type {number} @@ -196,6 +212,21 @@ class GuildChannel extends Channel { .then(() => this); } + /** + * Locks in the permission overwrites from the parent channel. + * @returns {Promise} + */ + lockPermissions() { + if (!this.parent) return Promise.reject(new Error('GUILD_CHANNEL_ORPHAN')); + const permissionOverwrites = this.parent.permissionOverwrites.map(overwrite => ({ + deny: overwrite.denied.bitfield, + allow: overwrite.allowed.bitfield, + id: overwrite.id, + type: overwrite.type, + })); + return this.edit({ permissionOverwrites }); + } + /** * A collection of members that can see this channel, mapped by their ID * @type {Collection} @@ -221,6 +252,16 @@ class GuildChannel extends Channel { * @property {number} [userLimit] The user limit of the voice channel * @property {Snowflake} [parentID] The parent ID of the channel * @property {boolean} [lockPermissions] Lock the permissions of the channel to what the parent's permissions are + * @property {OverwriteData[]} [permissionOverwrites] An array of overwrites to set for the channel + */ + + /** + * The data for a permission overwrite + * @typedef {Object} OverwriteData + * @property {string} id The id of the overwrite + * @property {string} type The type of the overwrite, either role or member + * @property {number} allow The bitfield for the allowed permissions + * @property {number} deny The bitfield for the denied permissions */ /** @@ -239,11 +280,12 @@ class GuildChannel extends Channel { data: { name: (data.name || this.name).trim(), topic: data.topic, - position: data.position || this.position, + position: data.position || this.rawPosition, bitrate: data.bitrate || (this.bitrate ? this.bitrate * 1000 : undefined), user_limit: data.userLimit != null ? data.userLimit : this.userLimit, // eslint-disable-line eqeqeq parent_id: data.parentID, lock_permissions: data.lockPermissions, + permission_overwrites: data.permissionOverwrites, }, reason, }).then(newData => {