discord-api-docs icon indicating copy to clipboard operation
discord-api-docs copied to clipboard

Discord API reports incorrect channel positions

Open touhidurrr opened this issue 2 years ago • 13 comments

Description

Discord API returns incorrect position values in Channel Objects.

Steps to Reproduce

  1. Add your bot in a server with adequate channels.
  2. make a request to GET /guilds/{guild.id}/channels
  3. Sort channels by position output Channel names
  4. Compare the result with your server

Expected Behavior

Channel Positions are Consistent with information viewed from clients.

Current Behavior

Some channels are reporting incorrect positions in the API.

Screenshots/Videos

No response

Client and System Information

User Agent: Axios Encountered in Both API v9 & v10

touhidurrr avatar Mar 06 '22 16:03 touhidurrr

Q: Did I check multiple times before reporting? A: Yes.

Q: Am I the only one facing this? A: No. When I shared this behaviour in Official Discord Server. Someone else tested it and encountered similar behaviour.

Q: Why do I think that this is a Bug? A: If you try to change the orders of the Channels that are reporting incorrect positions and change them back the positions reported in the next API request changes. Thus I think this must be the result of something going wrong from Discord's end.

touhidurrr avatar Mar 06 '22 16:03 touhidurrr

Channels with the same position should be sorted by id

devsnek avatar Mar 06 '22 16:03 devsnek

Channels with the same position should be sorted by id

How can a channel have the same position as another?

gamer0mega avatar Mar 06 '22 16:03 gamer0mega

Channels with the same position should be sorted by id

No same position was reported. Also please don't make up things without actually testing. Snowflakes and positions are not the same thing.

touhidurrr avatar Mar 06 '22 16:03 touhidurrr

You'll also need to take channel types into account. Here's some logic i wrote a big ago (in javascript):

const SortSections = {
  [ChannelTypes.GUILD_NEWS_THREAD]: 1,
  [ChannelTypes.GUILD_PUBLIC_THREAD]: 1,
  [ChannelTypes.GUILD_PRIVATE_THREAD]: 1,

  [ChannelTypes.GUILD_TEXT]: 2,
  [ChannelTypes.GUILD_CATEGORY]: 2,
  [ChannelTypes.GUILD_NEWS]: 2,
  [ChannelTypes.GUILD_STORE]: 2,

  [ChannelTypes.GUILD_VOICE]: 3,
  [ChannelTypes.GUILD_STAGE_VOICE]: 3,
};

function discordSort(a, b) {
  return a.position - b.position || Number(BigInt(a.id) - BigInt(b.id));
}

function channelSort(a, b) {
  const aSec = SortSections[a.type] || 0;
  const bSec = SortSections[b.type] || 0;
  if (aSec !== bSec) {
    return aSec - bSec;
  }
  return discordSort(a, b);
}

devsnek avatar Mar 06 '22 16:03 devsnek

Oh, note that this logic assumes you are already force channels with a parent_id to be under the channel that parent_id refers to.

devsnek avatar Mar 06 '22 16:03 devsnek

You'll also need to take channel types into account. Here's some logic i wrote a big ago (in javascript):

const SortSections = {
  [ChannelTypes.GUILD_NEWS_THREAD]: 1,
  [ChannelTypes.GUILD_PUBLIC_THREAD]: 1,
  [ChannelTypes.GUILD_PRIVATE_THREAD]: 1,

  [ChannelTypes.GUILD_TEXT]: 2,
  [ChannelTypes.GUILD_CATEGORY]: 2,
  [ChannelTypes.GUILD_NEWS]: 2,
  [ChannelTypes.GUILD_STORE]: 2,

  [ChannelTypes.GUILD_VOICE]: 3,
  [ChannelTypes.GUILD_STAGE_VOICE]: 3,
};

function discordSort(a, b) {
  return a.position - b.position || Number(BigInt(a.id) - BigInt(b.id));
}

function channelSort(a, b) {
  const aSec = SortSections[a.type] || 0;
  const bSec = SortSections[b.type] || 0;
  if (aSec !== bSec) {
    return aSec - bSec;
  }
  return discordSort(a, b);
}

Any documentation that backs your code? I don’t think It's relevant. Cause I already mentioned:

  1. No same position was reported or no two channels had the same position. So your code || Number(BigInt(a.id) - BigInt(b.id)) doesn’t change the sort result.
  2. If channel position is changed and then changed back the position returned changes. Also new channels begins reporting wrong positions.

Also I sorting is not the problem here. I only told that so that comparison becomes easier.

Lastly even if your code works (which I don’t think it does), the API returning wrong position is still a bug. Cause your code is not supported by any documentation.

touhidurrr avatar Mar 06 '22 17:03 touhidurrr

This could probably do with some documentation, yes. The positions in the API are not canonicalized. Channels which are never moved do not have a position at all (e.g. you determine their position based on their creation date, which is conveniently their id). Channels also have restrictions based on their type (for example, a voice channel in the same category as a text channel can not be above that text channel). Additionally, clients only update the positions of channels that they have permission to see, since the user can't see channels that they don't have permission to see. So overall there is a lot of processing you need to apply.

devsnek avatar Mar 06 '22 17:03 devsnek

This could probably do with some documentation, yes. The positions in the API are not canonicalized. Channels which are never moved do not have a position at all (e.g. you determine their position based on their creation date, which is conveniently their id). Channels also have restrictions based on their type (for example, a voice channel in the same category as a text channel can not be above that text channel). Additionally, clients only update the positions of channels that they have permission to see, since the user can't see channels that they don't have permission to see. So overall there is a lot of processing you need to apply.

Ok I get it now. I rechecked and yes some channels are reporting duplicate positions. So, basically channels are shown by the following precedence:

  1. parent_id
  2. type
  3. position

Now I have a question. When making a new channel with POST /guilds/{guild.id}/channels is the position parameter required? can I omit this or set it to a relative value like -1 ? Or do I need to get all channels, calculate positions and then set the parameter?

touhidurrr avatar Mar 06 '22 17:03 touhidurrr

@devsnek 😐

touhidurrr avatar Mar 07 '22 10:03 touhidurrr

What devsnek said earlier is actually inaccurate - position is optional, but if not provided, it will default to the next highest value for the given channel type.

(edited)

infinitestory avatar Mar 09 '22 18:03 infinitestory

it is true for roles though. be wary when sorting discord objects.

devsnek avatar Mar 09 '22 18:03 devsnek

@devsnek is this opened or closed XD

jdongdiscord avatar Sep 13 '22 23:09 jdongdiscord

This needs documentation, but is a duplicate of https://github.com/discord/discord-api-docs/issues/1778

yonilerner avatar Oct 03 '22 23:10 yonilerner