Skip to content

feat: add premium buttons #1701

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions interactions/models/discord/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import discord_typings

import interactions.models.discord as d_models
from interactions.models.discord.snowflake import Snowflake
from interactions.models.discord.snowflake import Snowflake, Snowflake_Type
from interactions.client.const import ACTION_ROW_MAX_ITEMS, MISSING
from interactions.client.mixins.serialization import DictSerializationMixin
from interactions.models.discord.base import DiscordObject
Expand Down Expand Up @@ -212,6 +212,7 @@ class Button(InteractiveComponent):
label optional[str]: The text that appears on the button, max 80 characters.
emoji optional[Union[PartialEmoji, dict, str]]: The emoji that appears on the button.
custom_id Optional[str]: A developer-defined identifier for the button, max 100 characters.
sku_id: Optional[Snowflake_Type]: Identifier for a purchasable SKU, only available when using premium-style buttons
url Optional[str]: A url for link-style buttons.
disabled bool: Disable the button and make it not interactable, default false.

Expand All @@ -226,13 +227,15 @@ def __init__(
label: str | None = None,
emoji: "PartialEmoji | None | str" = None,
custom_id: str | None = None,
sku_id: Snowflake_Type | None = None,
url: str | None = None,
disabled: bool = False,
) -> None:
self.style: ButtonStyle = ButtonStyle(style)
self.label: str | None = label
self.emoji: "PartialEmoji | None" = emoji
self.custom_id: str | None = custom_id
self.sku_id: Snowflake_Type | None = sku_id
self.url: str | None = url
self.disabled: bool = disabled

Expand All @@ -244,10 +247,17 @@ def __init__(
if self.url is None:
raise ValueError("URL buttons must have a url.")

elif self.style == ButtonStyle.PREMIUM:
if any(p is not None for p in (self.custom_id, self.url, self.emoji, self.label)):
raise ValueError("Premium buttons cannot have a custom_id, url, emoji, or label.")
if self.sku_id is None:
raise ValueError("Premium buttons must have a sku_id.")

elif self.custom_id is None:
self.custom_id = str(uuid.uuid4())
if not self.label and not self.emoji:
raise ValueError("Buttons must have a label or an emoji.")

if self.style != ButtonStyle.PREMIUM and not self.label and not self.emoji:
raise ValueError("Non-premium buttons must have a label or an emoji.")

if isinstance(self.emoji, str):
self.emoji = PartialEmoji.from_str(self.emoji)
Expand All @@ -261,12 +271,13 @@ def from_dict(cls, data: discord_typings.ButtonComponentData) -> "Button":
label=data.get("label"),
emoji=emoji,
custom_id=data.get("custom_id"),
sku_id=data.get("sku_id"),
url=data.get("url"),
disabled=data.get("disabled", False),
)

def __repr__(self) -> str:
return f"<{self.__class__.__name__} type={self.type} style={self.style} label={self.label} emoji={self.emoji} custom_id={self.custom_id} url={self.url} disabled={self.disabled}>"
return f"<{self.__class__.__name__} type={self.type} style={self.style} label={self.label} emoji={self.emoji} custom_id={self.custom_id} sku_id={self.sku_id} url={self.url} disabled={self.disabled}>"

def to_dict(self) -> discord_typings.ButtonComponentData:
emoji = self.emoji.to_dict() if self.emoji else None
Expand All @@ -279,6 +290,7 @@ def to_dict(self) -> discord_typings.ButtonComponentData:
"label": self.label,
"emoji": emoji,
"custom_id": self.custom_id,
"sku_id": self.sku_id,
"url": self.url,
"disabled": self.disabled,
}
Expand Down
2 changes: 2 additions & 0 deletions interactions/models/discord/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,8 @@ class ButtonStyle(CursedIntEnum):
"""red"""
LINK = 5
"""url button"""
PREMIUM = 6
"""premium button"""

# Aliases
BLUE = 1
Expand Down
4 changes: 4 additions & 0 deletions interactions/models/internal/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,10 @@ async def send_premium_required(self) -> None:
"""
Send a premium required response.

!!! warn
This response has been deprecated by Discord and will be removed in the future.
Use a button with the PREMIUM type instead.

When used, the user will be prompted to subscribe to premium to use this feature.
Only available for applications with monetization enabled.
"""
Expand Down
Loading