88from .api .models .misc import DictSerializerMixin , Snowflake
99from .api .models .user import User
1010from .base import CustomFormatter , Data
11- from .enums import ComponentType , InteractionCallbackType , InteractionType
11+ from .enums import InteractionCallbackType , InteractionType
1212from .models .command import Choice
1313from .models .component import ActionRow , Button , Component , Modal , SelectMenu
1414from .models .misc import InteractionData
@@ -134,7 +134,7 @@ async def defer(self, ephemeral: Optional[bool] = False) -> None:
134134 :type ephemeral: Optional[bool]
135135 """
136136 self .deferred = True
137- _ephemeral : int = (1 << 6 ) if bool ( ephemeral ) else 0
137+ _ephemeral : int = (1 << 6 ) if ephemeral else 0
138138 # ephemeral doesn't change callback typings. just data json
139139 if self .type == InteractionType .MESSAGE_COMPONENT :
140140 self .callback = InteractionCallbackType .DEFERRED_UPDATE_MESSAGE
@@ -191,20 +191,26 @@ async def send(
191191
192192 if isinstance (components , ActionRow ):
193193 _components [0 ]["components" ] = [component ._json for component in components .components ]
194- elif isinstance (components , (Button , SelectMenu )):
194+ elif isinstance (components , Button ):
195+ _components [0 ]["components" ] = [] if components is None else [components ._json ]
196+ elif isinstance (components , SelectMenu ):
197+ components ._json ["options" ] = [option ._json for option in components .options ]
195198 _components [0 ]["components" ] = [] if components is None else [components ._json ]
196199 else :
197200 _components = [] if components is None else [components ]
198201
199- _ephemeral : int = (1 << 6 ) if bool ( ephemeral ) else 0
202+ _ephemeral : int = (1 << 6 ) if ephemeral else 0
200203
201- if not self .deferred :
204+ if not self .deferred and self . type != InteractionType . MESSAGE_COMPONENT :
202205 self .callback = (
203206 InteractionCallbackType .CHANNEL_MESSAGE_WITH_SOURCE
204207 if self .type == InteractionType .APPLICATION_COMMAND
205208 else InteractionCallbackType .UPDATE_MESSAGE
206209 )
207210
211+ if not self .deferred and self .type == InteractionType .MESSAGE_COMPONENT :
212+ self .callback = InteractionCallbackType .CHANNEL_MESSAGE_WITH_SOURCE
213+
208214 # TODO: post-v4: Add attachments into Message obj.
209215 payload : Message = Message (
210216 content = _content ,
@@ -220,8 +226,18 @@ async def send(
220226 _payload : dict = {"type" : self .callback .value , "data" : payload ._json }
221227
222228 async def func ():
223- if self .responded or self .deferred :
224- if self .type == InteractionType .APPLICATION_COMMAND and self .deferred :
229+ if (
230+ self .responded
231+ or self .deferred
232+ or self .type == InteractionType .MESSAGE_COMPONENT
233+ and self .callback == InteractionCallbackType .DEFERRED_UPDATE_MESSAGE
234+ ):
235+ if (
236+ self .type == InteractionType .APPLICATION_COMMAND
237+ and self .deferred
238+ or self .type == InteractionType .MESSAGE_COMPONENT
239+ and self .deferred
240+ ):
225241 res = await self .client .edit_interaction_response (
226242 data = payload ._json ,
227243 token = self .token ,
@@ -280,8 +296,12 @@ async def edit(
280296
281297 if isinstance (components , ActionRow ):
282298 _components [0 ]["components" ] = [component ._json for component in components .components ]
283- elif isinstance (components , (Button , SelectMenu )):
299+ elif isinstance (components , Button ):
300+ _components [0 ]["components" ] = [] if components is None else [components ._json ]
301+ elif isinstance (components , SelectMenu ):
302+ components ._json ["options" ] = [option ._json for option in components .options ]
284303 _components [0 ]["components" ] = [] if components is None else [components ._json ]
304+
285305 else :
286306 _components = []
287307
@@ -297,14 +317,28 @@ async def edit(
297317
298318 async def func ():
299319 if self .deferred :
300- if self .type == InteractionType .MESSAGE_COMPONENT :
320+ if (
321+ self .type == InteractionType .MESSAGE_COMPONENT
322+ and self .callback != InteractionCallbackType .DEFERRED_UPDATE_MESSAGE
323+ ):
301324 await self .client ._post_followup (
302325 data = payload ._json ,
303326 token = self .token ,
304327 application_id = str (self .application_id ),
305328 )
306329 else :
307- if hasattr (self .message , "id" ) and self .message .id is not None :
330+ if (
331+ self .callback == InteractionCallbackType .DEFERRED_UPDATE_MESSAGE
332+ and self .type == InteractionType .MESSAGE_COMPONENT
333+ ):
334+ res = await self .client .edit_interaction_response (
335+ data = payload ._json ,
336+ token = self .token ,
337+ application_id = str (self .application_id ),
338+ )
339+ self .responded = True
340+ self .message = Message (** res )
341+ elif hasattr (self .message , "id" ) and self .message .id is not None :
308342 res = await self .client .edit_message (
309343 int (self .channel_id ), int (self .message .id ), payload = payload ._json
310344 )
@@ -325,6 +359,11 @@ async def func():
325359 )
326360 self .message = Message (** res )
327361 else :
362+ self .callback = (
363+ InteractionCallbackType .UPDATE_MESSAGE
364+ if self .type == InteractionType .MESSAGE_COMPONENT
365+ else self .callback
366+ )
328367 res = await self .client .edit_interaction_response (
329368 token = self .token ,
330369 application_id = str (self .application_id ),
@@ -459,5 +498,32 @@ class ComponentContext(CommandContext):
459498
460499 def __init__ (self , ** kwargs ) -> None :
461500 super ().__init__ (** kwargs )
462- self .type = ComponentType (self .type )
501+ self .type = InteractionType (self .type )
463502 self .responded = False # remind components that it was not responded to.
503+ self .deferred = False # remind components they not have been deferred
504+
505+ async def defer (
506+ self , ephemeral : Optional [bool ] = False , edit_origin : Optional [bool ] = False
507+ ) -> None :
508+ """
509+ This "defers" an component response, allowing up
510+ to a 15-minute delay between invocation and responding.
511+
512+ :param ephemeral?: Whether the deferred state is hidden or not.
513+ :type ephemeral: Optional[bool]
514+ :param edit_origin?: Whether you want to edit the original message or send a followup message
515+ :type edit_origin: Optional[bool]
516+ """
517+ self .deferred = True
518+ _ephemeral : int = (1 << 6 ) if bool (ephemeral ) else 0
519+ # ephemeral doesn't change callback typings. just data json
520+ if self .type == InteractionType .MESSAGE_COMPONENT and edit_origin :
521+ self .callback = InteractionCallbackType .DEFERRED_UPDATE_MESSAGE
522+ elif self .type == InteractionType .MESSAGE_COMPONENT and not edit_origin :
523+ self .callback = InteractionCallbackType .DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE
524+
525+ await self .client .create_interaction_response (
526+ token = self .token ,
527+ application_id = int (self .id ),
528+ data = {"type" : self .callback .value , "data" : {"flags" : _ephemeral }},
529+ )
0 commit comments