Pycord-Development/pycord

`Message.publish` has unusual and undocumented failure conditions

otc-cirdan opened this issue · 2 comments

Summary

When rate-limited, await Message.publish() will hang for an hour or more.

Reproduction Steps

I wrote a slash command that posts multiple messages to an announcement channel, and attempts to publish them. There is a 10 published messages per hour limit. I noticed that - once the limit had been reached - calls to the command would post the first message, and then would not publish it, would not post any further messages, would not raise any exception, and would not print anything to the console.

Minimal Reproducible Code

@commands.slash_command()
    async def post_and_publish(self, ctx):
        channel = ctx.channel # doesn't matter, any announcement channel
        await ctx.respond("doesn't matter, just responding to the interaction")
         for x in range(20):
            message = await channel.send(content=f"this is message number {x}")
            try:
                await message.publish()
            except Exception as e:
                LOG.critical(e)

Expected Results

I expected the command to finish executing and at least post all of the messages. If it was not possible to publish the message, I expected to receive an error response or catchable exception, so that I could decide whether to retry and whether to finish executing my command.

Actual Results

My command posted the first message and then idled for one hour, before continuing to execute. No exceptions or console output were available.

Intents

none

System Information

  • Python v3.11.4-final
  • py-cord v2.4.1-final
  • aiohttp v3.8.6
  • system info: Linux 5.15.133.1-microsoft-standard-WSL2 #1 SMP Thu Oct 5 21:02:42 UTC 2023

Checklist

  • I have searched the open issues for duplicates.
  • I have shown the entire traceback, if possible.
  • I have removed my token from display, if visible.

Additional Context

I think it should raise an exception, or at the very least, the documentation should say that this coroutine can wait for an hour or more, and should accept a "timeout" parameter.

Upon digging into code, including the custom HTTP request code used by pycord, I found that there would be some relevant DEBUG logs, enabled DEBUG logging, and got this:

DEBUG:discord.http:POST https://discord.com/api/v10/channels/redacted_channel_id/messages/redacted_message_id/crosspost with None has returned 429
WARNING:discord.http:We are being rate limited. Retrying in 2773.40 seconds. Handled under the bucket "redacted_channel_id:None:/channels/{channel_id}/messages/{message_id}/crosspost"

Even if I were to interact with this low level custom HTTP API, I don't see any possible way to specify a maximum timeout, or ask it not to wait. It's possible that I could do so by calling requests directly instead of message.publish().

Since it's a ratelimit thing and the ratelimit implementation queues it up there's no real reason to throw exception.
So it's working as intended.

We might consider for the feature to add a RatelimitException and a way to cancel the queued request, but that has to be discussed.