From e7f4f64883f80d7f1712c7bfff73a33b08173a96 Mon Sep 17 00:00:00 2001 From: Jaw0r3k Date: Sat, 6 May 2023 21:37:25 +0200 Subject: [PATCH 1/2] perf(Channel): linear speed position getter (#9497) Co-authored-by: kyra --- src/structures/GuildChannel.js | 20 +++++++++++++++++--- src/util/Util.js | 27 ++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/structures/GuildChannel.js b/src/structures/GuildChannel.js index 481d3cfaf9be..d8730da188fc 100644 --- a/src/structures/GuildChannel.js +++ b/src/structures/GuildChannel.js @@ -3,8 +3,10 @@ const { Channel } = require('./Channel'); const { Error } = require('../errors'); const PermissionOverwriteManager = require('../managers/PermissionOverwriteManager'); -const { VoiceBasedChannelTypes } = require('../util/Constants'); +const { VoiceBasedChannelTypes, ChannelTypes } = require('../util/Constants'); const Permissions = require('../util/Permissions'); +const SnowflakeUtil = require('../util/SnowflakeUtil'); +const Util = require('../util/Util'); /** * Represents a guild channel from any of the following: @@ -145,8 +147,20 @@ 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 === ChannelTypes.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) || !(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/util/Util.js b/src/util/Util.js index 205e9a024bd1..5d8f06d1c831 100644 --- a/src/util/Util.js +++ b/src/util/Util.js @@ -4,7 +4,7 @@ const { parse } = require('node:path'); const process = require('node:process'); const { Collection } = require('@discordjs/collection'); const fetch = require('node-fetch'); -const { Colors, Endpoints } = require('./Constants'); +const { Colors, Endpoints, ChannelTypes } = require('./Constants'); const Options = require('./Options'); const { Error: DiscordError, RangeError, TypeError } = require('../errors'); const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k); @@ -14,6 +14,9 @@ let deprecationEmittedForSplitMessage = false; let deprecationEmittedForRemoveMentions = false; let deprecationEmittedForResolveAutoArchiveMaxLimit = false; +const TextSortableGroupTypes = [ChannelTypes.GUILD_TEXT, ChannelTypes.GUILD_ANNOUCMENT, ChannelTypes.GUILD_FORUM]; +const CategorySortableGroupTypes = [ChannelTypes.GUILD_CATEGORY]; + /** * Contains various general-purpose utility methods. */ @@ -741,6 +744,28 @@ class Util extends null { emoji_name: defaultReaction.name, }; } + + /** + * 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 ChannelTypes.GUILD_TEXT: + case ChannelTypes.GUILD_ANNOUNCEMENT: + case ChannelTypes.GUILD_FORUM: + return TextSortableGroupTypes; + case ChannelTypes.GUILD_CATEGORY: + return CategorySortableGroupTypes; + default: + return [type]; + } + } } module.exports = Util; From 94e718bea340cd63d6a099010e630528f52b0cba Mon Sep 17 00:00:00 2001 From: Jaw0r3k Date: Sat, 6 May 2023 21:49:41 +0200 Subject: [PATCH 2/2] perf(Role): linear speed position getter --- src/structures/GuildChannel.js | 1 - src/structures/Role.js | 9 +++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/structures/GuildChannel.js b/src/structures/GuildChannel.js index d8730da188fc..b1d7c1c07236 100644 --- a/src/structures/GuildChannel.js +++ b/src/structures/GuildChannel.js @@ -5,7 +5,6 @@ const { Error } = require('../errors'); const PermissionOverwriteManager = require('../managers/PermissionOverwriteManager'); const { VoiceBasedChannelTypes, ChannelTypes } = require('../util/Constants'); const Permissions = require('../util/Permissions'); -const SnowflakeUtil = require('../util/SnowflakeUtil'); const Util = require('../util/Util'); /** diff --git a/src/structures/Role.js b/src/structures/Role.js index 76f02aca954e..afe1499f7065 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; } /**