feat: Implement with_response For Interaction Callbacks
Summary
Implements with_response for interaction callbacks.
This will update Interaction._original_response to avoid needing to make an API request when calling Interaction.original_response()
It also adds InteractionCallback which contains .is_loading() and .is_ephemeral() and is referenced through Interaction.callback
It was decided to always enable with_response instead of allowing the user to specify if they want it per #discussion on Discord.
The #type: ignore comment is because I copy pasted that code from somewhere else. They did not specify why they were ignoring.
Information
- [ ] This PR fixes an issue.
- [x] This PR adds something new (e.g. new method or parameters).
- [ ] This PR is a breaking change (e.g. methods or parameters removed/renamed).
- [ ] This PR is not a code change (e.g. documentation, README, typehinting, examples, ...).
Checklist
- [x] I have searched the open pull requests for duplicates.
- [x] If code changes were made then they have been tested.
- [x] I have updated the documentation to reflect the changes.
- [x] If
type: ignorecomments were used, a comment is also left explaining why. - [x] I have updated the changelog to include these changes.
After testing, I found that:
-
interaction.is_loading()is always returningFalse, regardless of context. - I might be misunderstanding its purpose or usage.
I tested interaction.is_loading() in several scenarios:
- After deferring a command
- After deferring a component interaction
- After a normal message interaction
In all cases, the result was still False.
-
interaction.messagereturns correctly ✅ -
interaction.is_ephemeralworks as expected ✅
if there is something else to test pls tell me
perhaps a large change, but it might be better if we had a proper InteractionCallback object that users can referenced via interaction.callback, which can be used for processing
@Lumabots I cannot reproduce. I am getting the correct values for .is_loading()
@bot.command()
async def with_response(ctx: discord.ApplicationContext):
i = await ctx.defer()
print("Loading: " + str(ctx.interaction.is_loading()))
perhaps a large change, but it might be better if we had a proper
InteractionCallbackobject that users can referenced viainteraction.callback, which can be used for processing
~~I dont really think this is needed, let me know if you think it would be much better for it to be a separate attribute.~~ Nevermind it probably is for the best. I am not going to bother exposing the message via this route though because it will already be exposed through original_response
~~It may be better for is_loading() and is_ephemeral() to return None before the interaction has been responded to.~~ The callback object will be None instead.
When component interactions are deferred with invisible=True (py-cords default) it does not count as loading based on Discords response. Not sure if this is intended behavior on Discords side.
When component interactions are deferred with
invisible=True(py-cords default) it does not count as loading based on Discords response. Not sure if this is intended behavior on Discords side.
Remind me later. I'm gonna check up with staff
@Lulalaby status? This would be nice to have in 2.7
can u resolve the merge conflicts. i'll check out the rest meanwhile
What's the reason the new message isn't attached to the message attribute rather than having to await the original_response method?
What's the reason the new message isn't attached to the
messageattribute rather than having to await theoriginal_responsemethod?
Interaction.message is the message that the interaction originates from.
Interaction.original_response() is
- The same as
Interaction.messageif the interaction response type wasUPDATE_MESSAGE - A different message if the interaction response type was
CHANNEL_MESSAGE_WITH_SOURCE - Any other interaction response types have it fall back to the same message as
Interaction.message. This case is how it was and is not affected by the PR.
When component interactions are deferred with
invisible=True(py-cords default) it does not count as loading based on Discords response. Not sure if this is intended behavior on Discords side.Remind me later. I'm gonna check up with staff
This is not the case anymore, was something changed or did I test wrong ?
Test Code
from discord import *
from dotenv import load_dotenv
import os
import logging
logging.basicConfig(level=logging.INFO)
load_dotenv()
bot = Bot(intents=Intents.all())
@bot.slash_command()
async def test(ctx: ApplicationContext):
await ctx.defer()
await asyncio.sleep(6)
m = await ctx.respond(f"Hello, world!, loading: {ctx.interaction.callback.is_loading()}, ephemeral: {ctx.interaction.callback.is_ephemeral()}")
await m.reply(f"Hello again, world!, loading: {ctx.interaction.callback.is_loading()}, ephemeral: {ctx.interaction.callback.is_ephemeral()}")
bot.run(os.getenv("TOKEN_2"))
This is not the case anymore, was something changed or did I test wrong ?
Invisible only applies to component interactions