Slash command interaction is expired on arrival
diogoriba opened this issue · comments
When testing a simple slash command using dislash, when i get to the callback that handles the slash command, the interaction is already expired. The code i'm using to test this:
@slash_commands.command(
name="maybe_this_works",
description="testing slash commands",
guild_ids=[GUILD_ID]
)
async def maybe_this_works(self, inter:Interaction):
logger.debug(inter)
logger.debug("snowflake time: " + inter.created_at.isoformat())
logger.debug("current time: " + dt.datetime.utcnow().isoformat())
logger.debug("is expired: " + str(inter.expired))
logger.debug("is sent: " + str(inter._sent))
await inter.reply("hello!")
Output in discord:
Output in logs:
vote | maybe_this_works | 47 | DEBUG | snowflake time: 2021-08-04T15:21:41.611000
vote | maybe_this_works | 48 | DEBUG | current time: 2021-08-04T18:21:41.803420
vote | maybe_this_works | 49 | DEBUG | is expired: True
vote | maybe_this_works | 50 | DEBUG | is sent: False
Result of the logs show that the time being reported by interaction.created_at
is not calculated as UTC.
It seems interaction.expired
uses interaction.created_at
which in turn uses a dislash.py specific implementation of snowflake_time
that does not force the timestamp to be created in UTC+0:
dislash.py/dislash/interactions/interaction.py
Lines 15 to 18 in 5b6d6b1
dislash.py/dislash/interactions/interaction.py
Lines 98 to 110 in 5b6d6b1
This differs from discord.py's implementation, which forces the timestamp to be calculated in UTC+0:
def snowflake_time(id: int) -> datetime.datetime:
"""
Parameters
-----------
id: :class:`int`
The snowflake ID.
Returns
--------
:class:`datetime.datetime`
An aware datetime in UTC representing the creation time of the snowflake.
"""
timestamp = ((id >> 22) + DISCORD_EPOCH) / 1000
return datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc)
If I change dislash's function to use either datetime.datetime.utcfromtimestamp
, or discord.py's implementation of snowflake_time
, the problem goes away and the interaction is no longer considered expired on arrival.
I can make a pull request to fix that if it would help, I just needed to know which route would you rather use to fix that (change dislash.py's implementation or adopt discord.py's function instead).
Seems like I messed up while making a custom snowflake_time function...
I added this function in order to avoid some problems with dpy 2.0 utils subpackage, thanks for sharing this issue, you can make the PR of course
I noticed that on some devices snowflake_time
seems to offset the timestamp a little bit (3-4 seconds to the past), which causes the self.expired
property to fail.
I decided to solve this problem by creating an extra attribute for BaseInteraction
called received_at
. I just call datetime.utcnow()
in __init__
an that's all.
I understand that this method may lead to some inaccuracies in detecting the expiration of an interaction, but I believe it will be practically more useful than the old unstable method
thank you for the quick response, and for sharing the other updates to BaseInteraction
@EQUENOS! i'm already downloading the new version here, these changes are going to be super helpful!
You're welcome