diff --git a/interactions/client/context.py b/interactions/client/context.py index e8e49f139..e4260de61 100644 --- a/interactions/client/context.py +++ b/interactions/client/context.py @@ -1,4 +1,5 @@ import asyncio +from contextlib import suppress from datetime import datetime from logging import Logger from typing import TYPE_CHECKING, List, Optional, Tuple, Union @@ -160,6 +161,55 @@ async def get_guild(self) -> Guild: res = await self._client.get_guild(int(self.guild_id)) return Guild(**res, _client=self._client) + async def defer( + self, ephemeral: Optional[bool] = False, edit_origin: Optional[bool] = False + ) -> Message: + """ + .. versionchanged:: 4.4.0 + Now returns the created message object + + This "defers" an interaction response, allowing up + to a 15-minute delay between invocation and responding. + + :param Optional[bool] ephemeral: Whether the deferred state is hidden or not. + :param Optional[bool] edit_origin: Whether you want to edit the original message or send a followup message + :return: The deferred message + :rtype: Message + """ + if edit_origin and self.type in { + InteractionType.APPLICATION_COMMAND, + InteractionType.APPLICATION_COMMAND_AUTOCOMPLETE, + }: + raise LibraryException( + message="You cannot defer with edit_origin parameter in this type of interaction" + ) + + if not self.responded: + self.deferred = True + is_ephemeral: int = MessageFlags.EPHEMERAL.value if bool(ephemeral) else 0 + # ephemeral doesn't change callback typings. just data json + self.callback = ( + InteractionCallbackType.DEFERRED_UPDATE_MESSAGE + if edit_origin + else InteractionCallbackType.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE + ) + + await self._client.create_interaction_response( + token=self.token, + application_id=int(self.id), + data={"type": self.callback.value, "data": {"flags": is_ephemeral}}, + ) + + with suppress(LibraryException): + res = await self._client.get_original_interaction_response( + self.token, str(self.application_id) + ) + self.message = Message(**res, _client=self._client) + + self.responded = True + + return self.message + async def send( self, content: Optional[str] = MISSING, @@ -301,6 +351,9 @@ async def edit( :return: The edited message. """ + if self.message is None: + raise LibraryException(message="There is no message to edit.") + payload = {} if self.message.content is not None or content is not MISSING: @@ -541,55 +594,23 @@ async def edit( else: self.message = msg = Message(**res, _client=self._client) else: - try: - res = await self._client.edit_interaction_response( - token=self.token, - application_id=str(self.application_id), - data=payload, - files=files, - ) - except LibraryException as e: - if e.code in {10015, 10018}: - log.warning(f"You can't edit hidden messages." f"({e.message}).") - else: - # if its not ephemeral or some other thing. - raise e from e - else: - self.message = msg = Message(**res, _client=self._client) - - return msg if msg is not None else Message(**payload, _client=self._client) - - async def defer(self, ephemeral: Optional[bool] = False) -> Message: - """ - .. versionchanged:: 4.4.0 - Now returns the created message object - - This "defers" an interaction response, allowing up - to a 15-minute delay between invocation and responding. - - :param Optional[bool] ephemeral: Whether the deferred state is hidden or not. - :return: The deferred message - :rtype: Message - """ - if not self.responded: - self.deferred = True - _ephemeral: int = MessageFlags.EPHEMERAL.value if ephemeral else 0 - self.callback = InteractionCallbackType.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE + self.callback = InteractionCallbackType.UPDATE_MESSAGE await self._client.create_interaction_response( + data={"type": self.callback.value, "data": payload}, + files=files, token=self.token, application_id=int(self.id), - data={"type": self.callback.value, "data": {"flags": _ephemeral}}, ) - try: - _msg = await self._client.get_original_interaction_response( + + with suppress(LibraryException): + res = await self._client.get_original_interaction_response( self.token, str(self.application_id) ) - except LibraryException: - pass - else: - self.message = Message(**_msg, _client=self._client) + self.message = msg = Message(**res, _client=self._client) + self.responded = True - return self.message + + return msg or Message(**payload, _client=self._client) async def send(self, content: Optional[str] = MISSING, **kwargs) -> Message: payload, files = await super().send(content, **kwargs) @@ -616,20 +637,15 @@ async def send(self, content: Optional[str] = MISSING, **kwargs) -> Message: files=files, ) - try: - _msg = await self._client.get_original_interaction_response( + with suppress(LibraryException): + res = await self._client.get_original_interaction_response( self.token, str(self.application_id) ) - except LibraryException: - pass - else: - self.message = msg = Message(**_msg, _client=self._client) + self.message = msg = Message(**res, _client=self._client) self.responded = True - if msg is not None: - return msg - return Message( + return msg or Message( **payload, _client=self._client, author={"_client": self._client, "id": None, "username": None, "discriminator": None}, @@ -712,14 +728,12 @@ async def edit(self, content: Optional[str] = MISSING, **kwargs) -> Message: application_id=int(self.id), ) - try: - _msg = await self._client.get_original_interaction_response( + with suppress(LibraryException): + res = await self._client.get_original_interaction_response( self.token, str(self.application_id) ) - except LibraryException: - pass - else: - self.message = msg = Message(**_msg, _client=self._client) + + self.message = msg = Message(**res, _client=self._client) self.responded = True elif self.callback != InteractionCallbackType.DEFERRED_UPDATE_MESSAGE: @@ -739,7 +753,7 @@ async def edit(self, content: Optional[str] = MISSING, **kwargs) -> Message: self.responded = True self.message = msg = Message(**res, _client=self._client) - return msg if msg is not None else Message(**payload, _client=self._client) + return msg or Message(**payload, _client=self._client) async def send(self, content: Optional[str] = MISSING, **kwargs) -> Message: payload, files = await super().send(content, **kwargs) @@ -766,60 +780,16 @@ async def send(self, content: Optional[str] = MISSING, **kwargs) -> Message: files=files, ) - try: - _msg = await self._client.get_original_interaction_response( + with suppress(LibraryException): + res = await self._client.get_original_interaction_response( self.token, str(self.application_id) ) - except LibraryException: - pass - else: - self.message = msg = Message(**_msg, _client=self._client) + self.message = msg = Message(**res, _client=self._client) self.responded = True return msg if msg is not None else Message(**payload, _client=self._client) - async def defer( - self, ephemeral: Optional[bool] = False, edit_origin: Optional[bool] = False - ) -> Message: - """ - .. versionchanged:: 4.4.0 - Now returns the created message object - - This "defers" a component response, allowing up - to a 15-minute delay between invocation and responding. - - :param Optional[bool] ephemeral: Whether the deferred state is hidden or not. - :param Optional[bool] edit_origin: Whether you want to edit the original message or send a followup message - :return: The deferred message - :rtype: Message - """ - if not self.responded: - - self.deferred = True - _ephemeral: int = MessageFlags.EPHEMERAL.value if bool(ephemeral) else 0 - # ephemeral doesn't change callback typings. just data json - if edit_origin: - self.callback = InteractionCallbackType.DEFERRED_UPDATE_MESSAGE - else: - self.callback = InteractionCallbackType.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE - - await self._client.create_interaction_response( - token=self.token, - application_id=int(self.id), - data={"type": self.callback.value, "data": {"flags": _ephemeral}}, - ) - try: - _msg = await self._client.get_original_interaction_response( - self.token, str(self.application_id) - ) - except LibraryException: - pass - else: - self.message = Message(**_msg, _client=self._client) - self.responded = True - return self.message - async def disable_all_components( self, respond_to_interaction: Optional[bool] = True, **other_kwargs: Optional[dict] ) -> Message: