@@ -20,12 +20,14 @@ class SlashContext:
2020 :ivar name: Name of the command.
2121 :ivar subcommand_name: Subcommand of the command.
2222 :ivar subcommand_group: Subcommand group of the command.
23- :ivar interaction_id : Interaction ID of the command message.
23+ :ivar _interaction_id : Interaction ID of the command message.
2424 :ivar command_id: ID of the command.
2525 :ivar _http: :class:`.http.SlashCommandRequest` of the client.
2626 :ivar bot: discord.py client.
27- :ivar logger: Logger instance.
28- :ivar sent: Whether you sent the initial response.
27+ :ivar _logger: Logger instance.
28+ :ivar _deffered: Whether the command is current deffered (loading state)
29+ :ivar _deffered_hidden: Internal var to check that state stays the same
30+ :ivar _sent: Whether you sent the initial response.
2931 :ivar guild_id: Guild ID of the command message. If the command was invoked in DM, then it is ``None``
3032 :ivar author_id: User ID representing author of the command message.
3133 :ivar channel_id: Channel ID representing channel of the command message.
@@ -42,12 +44,14 @@ def __init__(self,
4244 self .name = self .command = self .invoked_with = _json ["data" ]["name" ]
4345 self .subcommand_name = self .invoked_subcommand = self .subcommand_passed = None
4446 self .subcommand_group = self .invoked_subcommand_group = self .subcommand_group_passed = None
45- self .interaction_id = _json ["id" ]
47+ self ._interaction_id = _json ["id" ]
4648 self .command_id = _json ["data" ]["id" ]
4749 self ._http = _http
4850 self .bot = _discord
49- self .logger = logger
50- self .sent = False
51+ self ._logger = logger
52+ self ._deffered = False
53+ self ._sent = False
54+ self ._deffered_hidden = False # To check if the patch to the deffered response matches
5155 self .guild_id = int (_json ["guild_id" ]) if "guild_id" in _json .keys () else None
5256 self .author_id = int (_json ["member" ]["user" ]["id" ] if "member" in _json .keys () else _json ["user" ]["id" ])
5357 self .channel_id = int (_json ["channel_id" ])
@@ -76,39 +80,18 @@ def channel(self) -> typing.Optional[typing.Union[discord.abc.GuildChannel, disc
7680 """
7781 return self .bot .get_channel (self .channel_id )
7882
79- async def respond (self , eat : bool = False ):
83+ async def defer (self , hidden : bool = False ):
8084 """
81- Sends command invoke response.\n
82- You should call this first.
85+ 'Deferes' the response, showing a loading state to the user
8386
84- .. note::
85- - If `eat` is ``False``, there is a chance that ``message`` variable is present.
86- - While it is recommended to be manually called, this will still be automatically called
87- if this isn't called but :meth:`.send()` is called.
88-
89- :param eat: Whether to eat user's input. Default ``False``.
87+ :param hidden: Whether the deffered response should be ephemeral . Default ``False``.
9088 """
91- base = {"type" : 2 if eat else 5 }
92- _task = self .bot .loop .create_task (self ._http .post (base , self .interaction_id , self .__token , True ))
93- self .sent = True
94- if not eat and (not self .guild_id or (self .channel and self .channel .permissions_for (self .guild .me ).view_channel )):
95- with suppress (asyncio .TimeoutError ):
96- def check (message : discord .Message ):
97- user_id = self .author_id
98- is_author = message .author .id == user_id
99- channel_id = self .channel_id
100- is_channel = channel_id == message .channel .id
101- is_user_input = message .type == 20
102- is_correct_command = message .content .startswith (f"</{ self .name } :{ self .command_id } >" )
103- return is_author and is_channel and is_user_input and is_correct_command
104-
105- self .message = await self .bot .wait_for ("message" , timeout = 3 , check = check )
106- await _task
107-
108- @property
109- def ack (self ):
110- """Alias of :meth:`.respond`."""
111- return self .respond
89+ base = {"type" : 5 }
90+ if hidden :
91+ base ["data" ] = {"flags" : 64 }
92+ self ._deffered_hidden = True
93+ await self ._http .post_initial_response (base , self ._interaction_id , self .__token )
94+ self ._deffered = True
11295
11396 async def send (self ,
11497 content : str = "" , * ,
@@ -129,6 +112,7 @@ async def send(self,
129112 .. warning::
130113 - Since Release 1.0.9, this is completely changed. If you are migrating from older version, please make sure to fix the usage.
131114 - You can't use both ``embed`` and ``embeds`` at the same time, also applies to ``file`` and ``files``.
115+ - You cannot send files in the initial response
132116
133117 :param content: Content of the response.
134118 :type content: str
@@ -152,13 +136,6 @@ async def send(self,
152136 """
153137 if isinstance (content , int ) and 2 <= content <= 5 :
154138 raise error .IncorrectFormat ("`.send` Method is rewritten at Release 1.0.9. Please read the docs and fix all the usages." )
155- if not self .sent :
156- self .logger .info (f"At command `{ self .name } `: It is recommended to call `.respond()` first!" )
157- await self .respond (eat = hidden )
158- if hidden :
159- if embeds or embed or files or file :
160- self .logger .warning ("Embed/File is not supported for `hidden`!" )
161- return await self .send_hidden (content )
162139 if embed and embeds :
163140 raise error .IncorrectFormat ("You can't use both `embed` and `embeds`!" )
164141 if embed :
@@ -180,27 +157,38 @@ async def send(self,
180157 "allowed_mentions" : allowed_mentions .to_dict () if allowed_mentions
181158 else self .bot .allowed_mentions .to_dict () if self .bot .allowed_mentions else {}
182159 }
160+ if hidden :
161+ if embeds or files :
162+ self ._logger .warning ("Embed/File is not supported for `hidden`!" )
163+ base ["flags" ] = 64
164+
165+ initial_message = False
166+ if not self ._sent :
167+ initial_message = True
168+ if files :
169+ raise error .IncorrectFormat ("You cannot send files in the initial response!" )
170+ if self ._deffered :
171+ if self ._deffered_hidden != hidden :
172+ self ._logger .warning (
173+ "Deffered response might not be what you set it to! (hidden / visible) "
174+ "This is because it was deffered in a different state"
175+ )
176+ resp = await self ._http .edit (base , self .__token )
177+ self ._deffered = False
178+ else :
179+ base ["type" ] = 4
180+ resp = await self ._http .post_initial_response (base , self ._interaction_id , self .__token )
181+ self ._sent = True
182+ else :
183+ resp = await self ._http .post_followup (base , self .__token , files = files )
183184
184- resp = await self ._http .post (base , self .interaction_id , self .__token , files = files )
185185 smsg = model .SlashMessage (state = self .bot ._connection ,
186186 data = resp ,
187187 channel = self .channel or discord .Object (id = self .channel_id ),
188188 _http = self ._http ,
189189 interaction_token = self .__token )
190190 if delete_after :
191191 self .bot .loop .create_task (smsg .delete (delay = delete_after ))
192+ if initial_message :
193+ self .message = smsg
192194 return smsg
193-
194- def send_hidden (self , content : str = "" ):
195- """
196- Sends hidden response.\n
197- This is automatically used if you pass ``hidden=True`` at :meth:`.send`.
198-
199- :param content: Message content.
200- :return: Coroutine
201- """
202- base = {
203- "content" : content ,
204- "flags" : 64
205- }
206- return self ._http .post (base , self .interaction_id , self .__token )
0 commit comments