From 7ca90874b94d30c396268c17b9583018ed3f80bd Mon Sep 17 00:00:00 2001 From: Rapptz Date: Sat, 3 Jul 2021 00:30:32 -0400 Subject: [PATCH] Raise an exception if an interaction has been responded before Fix #7153 --- discord/errors.py | 19 +++++++++++++++++++ discord/interactions.py | 24 ++++++++++++++++++++---- docs/api.rst | 3 +++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/discord/errors.py b/discord/errors.py index 2e694318b..a6d2ce45e 100644 --- a/discord/errors.py +++ b/discord/errors.py @@ -36,6 +36,7 @@ __all__ = ( 'LoginFailure', 'ConnectionClosed', 'PrivilegedIntentsRequired', + 'InteractionResponded', ) class DiscordException(Exception): @@ -213,3 +214,21 @@ class PrivilegedIntentsRequired(ClientException): 'and explicitly enable the privileged intents within your application\'s page. If this is not ' \ 'possible, then consider disabling the privileged intents instead.' super().__init__(msg % shard_id) + +class InteractionResponded(ClientException): + """Exception that's raised when sending another interaction response using + :class:`InteractionResponse` when one has already been done before. + + An interaction can only respond once. + + .. versionadded:: 2.0 + + Attributes + ----------- + interaction: :class:`Interaction` + The interaction that's already been responded to. + """ + + def __init__(self, interaction): + self.interaction = interaction + super().__init__('This interaction has already been responded to before') diff --git a/discord/interactions.py b/discord/interactions.py index 46128f3d6..1a6c6a5bb 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -30,6 +30,7 @@ from typing import Any, Dict, List, Optional, TYPE_CHECKING, Tuple, Union from . import utils from .enums import try_enum, InteractionType, InteractionResponseType +from .errors import InteractionResponded from .user import User from .member import Member @@ -189,6 +190,13 @@ class InteractionResponse: self._parent: Interaction = parent self._responded: bool = False + def is_done(self) -> bool: + """:class:`bool`: Indicates whether an interaction response has been done before. + + An interaction can only be responded to once. + """ + return self._responded + async def defer(self, *, ephemeral: bool = False) -> None: """|coro| @@ -207,9 +215,11 @@ class InteractionResponse: ------- HTTPException Deferring the interaction failed. + InteractionResponsed + This interaction has already been responded to before. """ if self._responded: - return + raise InteractionResponded(self._parent) defer_type: int = 0 data: Optional[Dict[str, Any]] = None @@ -239,9 +249,11 @@ class InteractionResponse: ------- HTTPException Ponging the interaction failed. + InteractionResponsed + This interaction has already been responded to before. """ if self._responded: - return + raise InteractionResponded(self._parent) parent = self._parent if parent.type is InteractionType.ping: @@ -292,9 +304,11 @@ class InteractionResponse: You specified both ``embed`` and ``embeds``. ValueError The length of ``embeds`` was invalid. + InteractionResponsed + This interaction has already been responded to before. """ if self._responded: - return + raise InteractionResponded(self._parent) payload: Dict[str, Any] = { 'tts': tts, @@ -374,9 +388,11 @@ class InteractionResponse: Editing the message failed. TypeError You specified both ``embed`` and ``embeds``. + InteractionResponsed + This interaction has already been responded to before. """ if self._responded: - return + raise InteractionResponded(self._parent) parent = self._parent msg = parent.message diff --git a/docs/api.rst b/docs/api.rst index 392adc425..83dbca4ea 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -3862,6 +3862,8 @@ The following exceptions are thrown by the library. .. autoexception:: PrivilegedIntentsRequired +.. autoexception:: InteractionResponded + .. autoexception:: discord.opus.OpusError .. autoexception:: discord.opus.OpusNotLoaded @@ -3879,6 +3881,7 @@ Exception Hierarchy - :exc:`LoginFailure` - :exc:`ConnectionClosed` - :exc:`PrivilegedIntentsRequired` + - :exc:`InteractionResponded` - :exc:`NoMoreItems` - :exc:`GatewayNotFound` - :exc:`HTTPException`