diff --git a/discord/components.py b/discord/components.py index 43a8f6ffc..2af2d6d20 100644 --- a/discord/components.py +++ b/discord/components.py @@ -170,6 +170,10 @@ class Button(Component): The label of the button, if any. emoji: Optional[:class:`PartialEmoji`] The emoji of the button, if available. + sku_id: Optional[:class:`int`] + The SKU ID this button sends you to, if available. + + .. versionadded:: 2.4 """ __slots__: Tuple[str, ...] = ( @@ -179,6 +183,7 @@ class Button(Component): 'disabled', 'label', 'emoji', + 'sku_id', ) __repr_info__: ClassVar[Tuple[str, ...]] = __slots__ @@ -195,6 +200,11 @@ class Button(Component): except KeyError: self.emoji = None + try: + self.sku_id: Optional[int] = int(data['sku_id']) + except KeyError: + self.sku_id = None + @property def type(self) -> Literal[ComponentType.button]: """:class:`ComponentType`: The type of component.""" @@ -207,6 +217,9 @@ class Button(Component): 'disabled': self.disabled, } + if self.sku_id: + payload['sku_id'] = str(self.sku_id) + if self.label: payload['label'] = self.label diff --git a/discord/enums.py b/discord/enums.py index a8edb2a71..eaf8aef5e 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -603,7 +603,7 @@ class InteractionResponseType(Enum): message_update = 7 # for components autocomplete_result = 8 modal = 9 # for modals - premium_required = 10 + # premium_required = 10 (deprecated) class VideoQualityMode(Enum): @@ -635,6 +635,7 @@ class ButtonStyle(Enum): success = 3 danger = 4 link = 5 + premium = 6 # Aliases blurple = 1 diff --git a/discord/interactions.py b/discord/interactions.py index 5d9d2a680..e0fb7ed86 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -1050,38 +1050,6 @@ class InteractionResponse(Generic[ClientT]): self._parent._state.store_view(modal) self._response_type = InteractionResponseType.modal - async def require_premium(self) -> None: - """|coro| - - Sends a message to the user prompting them that a premium purchase is required for this interaction. - - This type of response is only available for applications that have a premium SKU set up. - - Raises - ------- - HTTPException - Sending the response failed. - InteractionResponded - This interaction has already been responded to before. - """ - if self._response_type: - raise InteractionResponded(self._parent) - - parent = self._parent - adapter = async_context.get() - http = parent._state.http - - params = interaction_response_params(InteractionResponseType.premium_required.value) - await adapter.create_interaction_response( - parent.id, - parent.token, - session=parent._session, - proxy=http.proxy, - proxy_auth=http.proxy_auth, - params=params, - ) - self._response_type = InteractionResponseType.premium_required - async def autocomplete(self, choices: Sequence[Choice[ChoiceT]]) -> None: """|coro| diff --git a/discord/types/components.py b/discord/types/components.py index 218f5cef0..3b1295c13 100644 --- a/discord/types/components.py +++ b/discord/types/components.py @@ -31,7 +31,7 @@ from .emoji import PartialEmoji from .channel import ChannelType ComponentType = Literal[1, 2, 3, 4] -ButtonStyle = Literal[1, 2, 3, 4, 5] +ButtonStyle = Literal[1, 2, 3, 4, 5, 6] TextStyle = Literal[1, 2] DefaultValueType = Literal['user', 'role', 'channel'] @@ -49,6 +49,7 @@ class ButtonComponent(TypedDict): disabled: NotRequired[bool] emoji: NotRequired[PartialEmoji] label: NotRequired[str] + sku_id: NotRequired[str] class SelectOption(TypedDict): diff --git a/discord/ui/button.py b/discord/ui/button.py index 28238a6f0..4d306fd10 100644 --- a/discord/ui/button.py +++ b/discord/ui/button.py @@ -77,6 +77,10 @@ class Button(Item[V]): like to control the relative positioning of the row then passing an index is advised. For example, row=1 will show up before row=2. Defaults to ``None``, which is automatic ordering. The row number must be between 0 and 4 (i.e. zero indexed). + sku_id: Optional[:class:`int`] + The SKU ID this button sends you to. Can't be combined with ``url``. + + .. versionadded:: 2.4 """ __item_repr_attributes__: Tuple[str, ...] = ( @@ -86,6 +90,7 @@ class Button(Item[V]): 'label', 'emoji', 'row', + 'sku_id', ) def __init__( @@ -98,6 +103,7 @@ class Button(Item[V]): url: Optional[str] = None, emoji: Optional[Union[str, Emoji, PartialEmoji]] = None, row: Optional[int] = None, + sku_id: Optional[int] = None, ): super().__init__() if custom_id is not None and url is not None: @@ -113,6 +119,9 @@ class Button(Item[V]): if url is not None: style = ButtonStyle.link + if sku_id is not None: + style = ButtonStyle.premium + if emoji is not None: if isinstance(emoji, str): emoji = PartialEmoji.from_str(emoji) @@ -128,6 +137,7 @@ class Button(Item[V]): label=label, style=style, emoji=emoji, + sku_id=sku_id, ) self.row = row @@ -202,6 +212,19 @@ class Button(Item[V]): else: self._underlying.emoji = None + @property + def sku_id(self) -> Optional[int]: + """Optional[:class:`int`]: The SKU ID this button sends you to. + + .. versionadded:: 2.4 + """ + return self._underlying.sku_id + + @sku_id.setter + def sku_id(self, value: Optional[int]) -> None: + self.style = ButtonStyle.premium + self._underlying.sku_id = value + @classmethod def from_component(cls, button: ButtonComponent) -> Self: return cls( @@ -212,6 +235,7 @@ class Button(Item[V]): url=button.url, emoji=button.emoji, row=None, + sku_id=button.sku_id, ) @property @@ -241,6 +265,7 @@ def button( style: ButtonStyle = ButtonStyle.secondary, emoji: Optional[Union[str, Emoji, PartialEmoji]] = None, row: Optional[int] = None, + sku_id: Optional[int] = None, ) -> Callable[[ItemCallbackType[V, Button[V]]], Button[V]]: """A decorator that attaches a button to a component. @@ -278,6 +303,10 @@ def button( like to control the relative positioning of the row then passing an index is advised. For example, row=1 will show up before row=2. Defaults to ``None``, which is automatic ordering. The row number must be between 0 and 4 (i.e. zero indexed). + sku_id: Optional[:class:`int`] + The SKU ID this button sends you to. Can't be combined with ``url``. + + .. versionadded:: 2.4 """ def decorator(func: ItemCallbackType[V, Button[V]]) -> ItemCallbackType[V, Button[V]]: @@ -293,6 +322,7 @@ def button( 'label': label, 'emoji': emoji, 'row': row, + 'sku_id': sku_id, } return func diff --git a/docs/interactions/api.rst b/docs/interactions/api.rst index 53ad210b3..d467d2b9f 100644 --- a/docs/interactions/api.rst +++ b/docs/interactions/api.rst @@ -334,7 +334,12 @@ Enumerations .. attribute:: link Represents a link button. + .. attribute:: premium + Represents a gradient button denoting that buying a SKU is + required to perform this action. + + .. versionadded:: 2.4 .. attribute:: blurple An alias for :attr:`primary`.