diff --git a/src/structures/GuildChannel.js b/src/structures/GuildChannel.js index 481d3cf..527a253 100644 --- a/src/structures/GuildChannel.js +++ b/src/structures/GuildChannel.js @@ -5,6 +5,7 @@ const { Error } = require('../errors'); const PermissionOverwriteManager = require('../managers/PermissionOverwriteManager'); const { VoiceBasedChannelTypes } = require('../util/Constants'); const Permissions = require('../util/Permissions'); +const Util = require('../util/Util'); /** * Represents a guild channel from any of the following: @@ -145,8 +146,21 @@ class GuildChannel extends Channel { * @readonly */ get position() { - const sorted = this.guild._sortedChannels(this); - return [...sorted.values()].indexOf(sorted.get(this.id)); + const selfIsCategory = this.type === 'GUILD_CATEGORY'; + const types = Util.getSortableGroupTypes(this.type); + + let count = 0; + for (const channel of this.guild.channels.cache.values()) { + if (!types.includes(channel.type)) continue; + if (!selfIsCategory && channel.parentId !== this.parentId) continue; + if (this.rawPosition === channel.rawPosition) { + if (BigInt(channel.id) < BigInt(this.id)) count++; + } else if (this.rawPosition > channel.rawPosition) { + count++; + } + } + + return count; } /** diff --git a/src/structures/Role.js b/src/structures/Role.js index 76f02ac..afe1499 100644 --- a/src/structures/Role.js +++ b/src/structures/Role.js @@ -228,8 +228,13 @@ class Role extends Base { * @readonly */ get position() { - const sorted = this.guild._sortedRoles(); - return [...sorted.values()].indexOf(sorted.get(this.id)); + let count = 0; + for (const role of this.guild.roles.cache.values()) { + if (this.rawPosition > role.rawPosition) count++; + else if (this.rawPosition === role.rawPosition && BigInt(this.id) > BigInt(role.id)) count++; + } + + return count; } /** diff --git a/src/util/Util.js b/src/util/Util.js index b308676..5c581d1 100644 --- a/src/util/Util.js +++ b/src/util/Util.js @@ -12,6 +12,10 @@ const isObject = d => typeof d === 'object' && d !== null; let deprecationEmittedForSplitMessage = false; let deprecationEmittedForRemoveMentions = false; +const TextSortableGroupTypes = ['GUILD_TEXT', 'GUILD_ANNOUCMENT', 'GUILD_FORUM']; +const VoiceSortableGroupTypes = ['GUILD_VOICE', 'GUILD_STAGE_VOICE']; +const CategorySortableGroupTypes = ['GUILD_CATEGORY']; + /** * Contains various general-purpose utility methods. */ @@ -747,6 +751,31 @@ class Util extends null { } } + /** + * Gets an array of the channel types that can be moved in the channel group. For example, a GuildText channel would + * return an array containing the types that can be ordered within the text channels (always at the top), and a voice + * channel would return an array containing the types that can be ordered within the voice channels (always at the + * bottom). + * @param {ChannelType} type The type of the channel + * @returns {ChannelType[]} + * @ignore + */ + static getSortableGroupTypes(type) { + switch (type) { + case 'GUILD_TEXT': + case 'GUILD_ANNOUNCEMENT': + case 'GUILD_FORUM': + return TextSortableGroupTypes; + case 'GUILD_VOICE': + case 'GUILD_STAGE_VOICE': + return VoiceSortableGroupTypes; + case 'GUILD_CATEGORY': + return CategorySortableGroupTypes; + default: + return [type]; + } + } + /** * Calculates the default avatar index for a given user id. * @param {Snowflake} userId - The user id to calculate the default avatar index for