discord-net/Discord.Net

Request: Easy bypass for Defer 3 Second clock sync issue

mcmonkey4eva opened this issue · 5 comments

The Issue

This code here:

public static bool CanSendResponse(IDiscordInteraction interaction)
{
return (DateTime.UtcNow - interaction.CreatedAt).TotalSeconds < ResponseTimeLimit;
}

wherein ResponseTimeLimit = 3.0

Is triggered when trying to DeferAsync, and throws an exception if it's false.

This means that the end system clock must be exactly in sync with Discord's server clocks*, otherwise it will misbehave and throw invalid exceptions.
*(If we assume latency of ~1 second from network travel and initial processing, the local system clock only needs to be 2 seconds delayed for this call to be a guaranteed reject every time)

While of course we all dream of running services in datacenters with perfect atomic clock sync, in reality bots are running wherever, even eg on a home computer (that's where I run while testing my bot for example), and in real world applications, a few seconds of offset of the system clock is very normal.

The Proposed Solution

In general I disagree with the idea that this check should be made at all (should let the Discord remote server respond with a refusal if it's too late)*, however I'd be more than happy with just a way to manually disable the check that I would personally be using at least in any dev environment. If I can just DeferAsync(unchecked: true), or set DiscordSocketConfig.NoDeferTimeCheck = true or anything like that, that would suffice.

*(Noting as well that eg if the delay is 2.9 seconds, the check will pass and send along... and then after network latency, Discord will end up rejecting it anyway, ie we already rely on Discord's servers handling appropriate rejections here)

The other valid solution here is to reformulate the check to base the comparison relative to when the interaction was received by Discord.Net rather than relative to Discord's clocks, as that will work as-expected for any/all cases as long as local system clock doesn't jump during processing (can use Environment.TickCount64 to ensure even that case is not mishandled).

In general I disagree with the idea that this check should be made at all

Agreed, I really don't get why this is being done