diff --git a/src/client/actions/GuildChannelsPositionUpdate.js b/src/client/actions/GuildChannelsPositionUpdate.js index ea184eff6..863d7dc51 100644 --- a/src/client/actions/GuildChannelsPositionUpdate.js +++ b/src/client/actions/GuildChannelsPositionUpdate.js @@ -8,7 +8,7 @@ class GuildChannelsPositionUpdate extends Action { if (guild) { for (const partialChannel of data.channels) { const channel = guild.channels.get(partialChannel.id); - if (channel) channel.position = partialChannel.position; + if (channel) channel.rawPosition = partialChannel.position; } } diff --git a/src/client/actions/GuildRolesPositionUpdate.js b/src/client/actions/GuildRolesPositionUpdate.js index 9094965cd..af29702ad 100644 --- a/src/client/actions/GuildRolesPositionUpdate.js +++ b/src/client/actions/GuildRolesPositionUpdate.js @@ -8,7 +8,7 @@ class GuildRolesPositionUpdate extends Action { if (guild) { for (const partialRole of data.roles) { const role = guild.roles.get(partialRole.id); - if (role) role.position = partialRole.position; + if (role) role.rawPosition = partialRole.position; } } diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 0438510c1..21ec24ed1 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -1,9 +1,6 @@ -const Long = require('long'); -const Role = require('./Role'); const Invite = require('./Invite'); const GuildAuditLogs = require('./GuildAuditLogs'); const Webhook = require('./Webhook'); -const GuildChannel = require('./GuildChannel'); const GuildMember = require('./GuildMember'); const VoiceRegion = require('./VoiceRegion'); const Constants = require('../util/Constants'); @@ -413,16 +410,6 @@ class Guild extends Base { return this.members.get(this.client.user.id); } - /** - * Fetches a collection of roles in the current guild sorted by position - * @type {Collection} - * @readonly - * @private - */ - get _sortedRoles() { - return this._sortPositionWithID(this.roles); - } - /** * Returns the GuildMember form of a User object, if the user is present in the guild. * @param {UserResolvable} user The user that you want to obtain the GuildMember of @@ -945,38 +932,6 @@ class Guild extends Base { * @property {number} position New position for the channel */ - /** - * Set the position of a channel in this guild. - * @param {ChannelResolvable} channel The channel to edit, can be a channel object or a channel ID - * @param {number} position The new position of the channel - * @param {boolean} [relative=false] Position Moves the channel relative to its current position - * @returns {Promise} - */ - setChannelPosition(channel, position, relative = false) { - if (typeof channel === 'string') { - channel = this.channels.get(channel); - } - if (!(channel instanceof GuildChannel)) { - return Promise.reject(new TypeError('INVALID_TYPE', 'channel', 'GuildChannel nor a Snowflake')); - } - - position = Number(position); - if (isNaN(position)) return Promise.reject(new TypeError('INVALID_TYPE', 'position', 'number')); - - let updatedChannels = this._sortedChannels(channel.type).array(); - - Util.moveElementInArray(updatedChannels, channel, position, relative); - - updatedChannels = updatedChannels.map((r, i) => ({ id: r.id, position: i })); - return this.client.api.guilds(this.id).channels.patch({ data: updatedChannels }) - .then(() => - this.client.actions.GuildChannelsPositionUpdate.handle({ - guild_id: this.id, - channels: updatedChannels, - }).guild - ); - } - /** * Batch-updates the guild's channels' positions. * @param {ChannelPosition[]} channelPositions Channel positions to update @@ -1172,49 +1127,15 @@ class Guild extends Base { } } - /** - * Set the position of a role in this guild. - * @param {RoleResolvable} role The role to edit, can be a role object or a role ID - * @param {number} position The new position of the role - * @param {boolean} [relative=false] Position Moves the role relative to its current position - * @returns {Promise} - */ - setRolePosition(role, position, relative = false) { - if (typeof role === 'string') { - role = this.roles.get(role); - } - if (!(role instanceof Role)) return Promise.reject(new TypeError('INVALID_TYPE', 'role', 'Role nor a Snowflake')); - - position = Number(position); - if (isNaN(position)) return Promise.reject(new TypeError('INVALID_TYPE', 'position', 'number')); - - let updatedRoles = this._sortedRoles.array(); - - Util.moveElementInArray(updatedRoles, role, position, relative); - - updatedRoles = updatedRoles.map((r, i) => ({ id: r.id, position: i })); - return this.client.api.guilds(this.id).roles.patch({ data: updatedRoles }) - .then(() => - this.client.actions.GuildRolesPositionUpdate.handle({ - guild_id: this.id, - roles: updatedRoles, - }).guild - ); + _sortedRoles() { + return Util.discordSort(this.roles); } - /** - * Fetches a collection of channels in the current guild sorted by position. - * @param {Channel} channel Channel - * @returns {Collection} - * @private - */ _sortedChannels(channel) { - const sort = col => col - .sort((a, b) => a.rawPosition - b.rawPosition || Long.fromString(a.id).sub(Long.fromString(b.id)).toNumber()); if (channel.type === Constants.ChannelTypes.CATEGORY) { - return sort(this.channels.filter(c => c.type === Constants.ChannelTypes.CATEGORY)); + return Util.discordSort(this.channels.filter(c => c.type === Constants.ChannelTypes.CATEGORY)); } - return sort(this.channels.filter(c => c.parent === channel.parent)); + return Util.discordSort(this.channels.filter(c => c.parent === channel.parent)); } } diff --git a/src/structures/GuildChannel.js b/src/structures/GuildChannel.js index 88269a632..2fd05c937 100644 --- a/src/structures/GuildChannel.js +++ b/src/structures/GuildChannel.js @@ -268,33 +268,6 @@ class GuildChannel extends Channel { return this.edit({ name }, reason); } - /** - * Set a new position for the guild channel. - * @param {number} position The new position for the guild channel - * @param {boolean} [relative=false] Move the position relative to its current value - * @returns {Promise} - * @example - * // Set a new channel position - * channel.setPosition(2) - * .then(newChannel => console.log(`Channel's new position is ${newChannel.position}`)) - * .catch(console.error); - */ - setPosition(position, { relative, reason }) { - position = Number(position); - if (isNaN(position)) return Promise.reject(new TypeError('INVALID_TYPE', 'position', 'number')); - let updatedChannels = this.guild._sortedChannels(this).array(); - Util.moveElementInArray(updatedChannels, this, position, relative); - updatedChannels = updatedChannels.map((r, i) => ({ id: r.id, position: i })); - return this.client.api.guilds(this.id).channels.patch({ data: updatedChannels, reason }) - .then(() => { - this.client.actions.GuildChannelsPositionUpdate.handle({ - guild_id: this.id, - channels: updatedChannels, - }); - return this; - }); - } - /** * Set the category parent of this channel. * @param {GuildChannel|Snowflake} channel Parent channel @@ -324,6 +297,31 @@ class GuildChannel extends Channel { return this.edit({ topic }, reason); } + /** + * Set a new position for the guild channel. + * @param {number} position The new position for the guild channel + * @param {Object} [options] Options for setting position + * @param {boolean} [options.relative=false] Change the position relative to its current value + * @param {boolean} [options.reason] Reasion for changing the position + * @returns {Promise} + * @example + * // Set a new channel position + * channel.setPosition(2) + * .then(newChannel => console.log(`Channel's new position is ${newChannel.position}`)) + * .catch(console.error); + */ + setPosition(position, { relative, reason } = {}) { + return Util.setPosition(this, position, relative, + this.guild._sortedChannels(this), this.client.api.guilds(this.guild.id).channels, reason) + .then(updatedChannels => { + this.client.actions.GuildChannelsPositionUpdate.handle({ + guild_id: this.id, + channels: updatedChannels, + }); + return this; + }); + } + /** * Create an invite to this guild channel. * @param {Object} [options={}] Options for the invite diff --git a/src/structures/Role.js b/src/structures/Role.js index 47020ff59..724e8bb19 100644 --- a/src/structures/Role.js +++ b/src/structures/Role.js @@ -47,10 +47,10 @@ class Role extends Base { this.hoist = data.hoist; /** - * The position of the role from the API + * The raw position of the role from the API * @type {number} */ - this.position = data.position; + this.rawPosition = data.position; /** * The permissions of the role @@ -126,8 +126,8 @@ class Role extends Base { * @type {number} * @readonly */ - get calculatedPosition() { - const sorted = this.guild._sortedRoles; + get position() { + const sorted = this.guild._sortedRoles(); return sorted.array().indexOf(sorted.get(this.id)); } @@ -264,21 +264,6 @@ class Role extends Base { return this.edit({ hoist }, reason); } - /** - * Set the position of the role. - * @param {number} position The position of the role - * @param {boolean} [relative=false] Move the position relative to its current value - * @returns {Promise} - * @example - * // Set the position of the role - * role.setPosition(1) - * .then(r => console.log(`Role position: ${r.position}`)) - * .catch(console.error); - */ - setPosition(position, relative) { - return this.guild.setRolePosition(this, position, relative).then(() => this); - } - /** * Set the permissions of the role. * @param {PermissionResolvable[]} permissions The permissions of the role @@ -309,6 +294,31 @@ class Role extends Base { return this.edit({ mentionable }, reason); } + /** + * Set the position of the role. + * @param {number} position The position of the role + * @param {Object} [options] Options for setting position + * @param {boolean} [options.relative=false] Change the position relative to its current value + * @param {boolean} [options.reason] Reasion for changing the position + * @returns {Promise} + * @example + * // Set the position of the role + * role.setPosition(1) + * .then(r => console.log(`Role position: ${r.position}`)) + * .catch(console.error); + */ + setPosition(position, { relative, reason } = {}) { + return Util.setPosition(this, position, relative, + this.guild._sortedRoles(), this.client.api.guilds(this.guild.id).roles, reason) + .then(updatedRoles => { + this.client.actions.GuildRolesPositionUpdate.handle({ + guild_id: this.id, + channels: updatedRoles, + }); + return this; + }); + } + /** * Deletes the role. * @param {string} [reason] Reason for deleting this role diff --git a/src/util/Util.js b/src/util/Util.js index 1a710eea8..fe197e74f 100644 --- a/src/util/Util.js +++ b/src/util/Util.js @@ -1,3 +1,4 @@ +const Long = require('long'); const snekfetch = require('snekfetch'); const Constants = require('./Constants'); const ConstantsHttp = Constants.DefaultOptions.http; @@ -290,6 +291,23 @@ class Util { return color; } + + /** + * Sort by discord's position then ID thing + * @param {Collection} collection Collection of objects to sort + * @returns {Collection} + */ + static discordSort(collection) { + return collection + .sort((a, b) => a.rawPosition - b.rawPosition || Long.fromString(a.id).sub(Long.fromString(b.id)).toNumber()); + } + + static setPosition(item, position, relative, sorted, route, handle, reason) { + let updatedItems = sorted.array(); + Util.moveElementInArray(updatedItems, item, position, relative); + updatedItems = updatedItems.map((r, i) => ({ id: r.id, position: i })); + return route.patch({ data: updatedItems, reason }).then(handle || (x => x)); + } } module.exports = Util;