From fd95b80b7560cb9bdcd8bb3f0a714a3e85ca097e Mon Sep 17 00:00:00 2001 From: Snipy7374 <100313469+Snipy7374@users.noreply.github.com> Date: Sat, 19 Jul 2025 18:32:57 +0200 Subject: [PATCH 1/5] implement new RPC fields --- disnake/activity.py | 31 ++++++++++++++++++++++++++++++- disnake/enums.py | 18 ++++++++++++++++++ disnake/types/activity.py | 6 ++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/disnake/activity.py b/disnake/activity.py index 97c4381c14..a3963e2334 100644 --- a/disnake/activity.py +++ b/disnake/activity.py @@ -7,7 +7,7 @@ from .asset import Asset from .colour import Colour -from .enums import ActivityType, try_enum +from .enums import ActivityType, StatusDisplayType, try_enum from .partial_emoji import PartialEmoji __all__ = ( @@ -284,6 +284,18 @@ class Activity(BaseActivity): emoji: Optional[:class:`PartialEmoji`] The emoji that belongs to this activity. + details_url: Optional[:class:`str`] + An URL that is linked when clicking on the details text of an activity. + + .. versionadded:: 2.11 + state_url: Optional[:class:`str`] + An URL that is linked when clicking on the state text of an activity. + + .. versionadded:: 2.11 + status_display_type: Optional[:class:`StatusDisplayType`] + Controls which field is displayed in the user's status activity text in the member list. + + .. versionadded:: 2.11 """ __slots__ = ( @@ -301,6 +313,9 @@ class Activity(BaseActivity): "platform", "sync_id", "session_id", + "details_url", + "state_url", + "status_display_type", ) def __init__( @@ -310,7 +325,9 @@ def __init__( url: Optional[str] = None, type: Optional[Union[ActivityType, int]] = None, state: Optional[str] = None, + state_url: Optional[str] = None, details: Optional[str] = None, + details_url: Optional[str] = None, party: Optional[ActivityParty] = None, application_id: Optional[Union[str, int]] = None, flags: Optional[int] = None, @@ -320,11 +337,14 @@ def __init__( platform: Optional[str] = None, sync_id: Optional[str] = None, session_id: Optional[str] = None, + status_display_type: Optional[Union[StatusDisplayType, int]] = None, **kwargs: Any, ) -> None: super().__init__(**kwargs) self.state: Optional[str] = state + self.state_url: Optional[str] = state_url self.details: Optional[str] = details + self.details_url: Optional[str] = details_url self.party: ActivityParty = party or {} self.application_id: Optional[int] = ( int(application_id) if application_id is not None else None @@ -347,6 +367,12 @@ def __init__( else try_enum(ActivityType, activity_type) ) + self.status_display_type: Optional[StatusDisplayType] = ( + status_display_type + if isinstance(status_display_type, StatusDisplayType) + else try_enum(StatusDisplayType, status_display_type) + ) + self.emoji: Optional[PartialEmoji] = ( PartialEmoji.from_dict(emoji) if emoji is not None else None ) @@ -379,6 +405,9 @@ def to_dict(self) -> Dict[str, Any]: # fix type field ret["type"] = int(self.type) + if self.status_display_type: + ret["status_display_type"] = int(self.status_display_type) + if self.emoji: ret["emoji"] = self.emoji.to_dict() # defined in base class slots diff --git a/disnake/enums.py b/disnake/enums.py index d02b551d56..de3645d624 100644 --- a/disnake/enums.py +++ b/disnake/enums.py @@ -28,6 +28,7 @@ "VerificationLevel", "ContentFilter", "Status", + "StatusDisplayType", "DefaultAvatar", "AuditLogAction", "AuditLogActionCategory", @@ -603,6 +604,23 @@ def __str__(self) -> str: return self.value +class StatusDisplayType(Enum): + """Specifies an :class:`Activity` display status. + + .. versionaddedd:: 2.11 + """ + + name = 0 # type: ignore[reportAssignmentType] + """The name of the activity is displayed, e.g: ``Listening to Spotify``.""" + state = 1 + """The state of the activity is displayed, e.g: ``Listening to Rick Astley``.""" + details = 2 + """The details of the activity are displayed, e.g: ``Listening to Never Gonna Give You Up``.""" + + def __int__(self) -> int: + return self.value + + class DefaultAvatar(Enum): """Represents the default avatar of a Discord :class:`User`.""" diff --git a/disnake/types/activity.py b/disnake/types/activity.py index 39a292f46a..749f015bdc 100644 --- a/disnake/types/activity.py +++ b/disnake/types/activity.py @@ -10,6 +10,7 @@ from .user import User StatusType = Literal["idle", "dnd", "online", "offline"] +StatusDisplayType = Literal[0, 1, 2] class PresenceData(TypedDict): @@ -44,8 +45,10 @@ class ActivityAssets(TypedDict, total=False): # https://discord.com/developers/docs/topics/gateway-events#activity-object-activity-asset-image large_image: str large_text: str + large_url: str small_image: str small_text: str + small_url: str class ActivitySecrets(TypedDict, total=False): @@ -75,7 +78,9 @@ class Activity(SendableActivity, total=False): timestamps: ActivityTimestamps application_id: Snowflake details: Optional[str] + details_url: Optional[str] state: Optional[str] + state_url: Optional[str] emoji: Optional[ActivityEmoji] party: ActivityParty assets: ActivityAssets @@ -90,3 +95,4 @@ class Activity(SendableActivity, total=False): platform: Optional[str] sync_id: Optional[str] session_id: Optional[str] + status_display_type: Optional[StatusDisplayType] From f923153ce08817de41b06d3934ac66c6df730081 Mon Sep 17 00:00:00 2001 From: Snipy7374 <100313469+Snipy7374@users.noreply.github.com> Date: Sat, 19 Jul 2025 18:41:16 +0200 Subject: [PATCH 2/5] add changelog entry --- changelog/1307.feature.rst | 1 + disnake/enums.py | 2 +- docs/api/activities.rst | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 changelog/1307.feature.rst diff --git a/changelog/1307.feature.rst b/changelog/1307.feature.rst new file mode 100644 index 0000000000..fffc2d4eac --- /dev/null +++ b/changelog/1307.feature.rst @@ -0,0 +1 @@ +Add the new :attr:`Activity.details_url`, :attr:`Activity.state_url`, :attr:`Activity.status_display_type` and :class:`StatusDisplayType` RPC attributes and enum. diff --git a/disnake/enums.py b/disnake/enums.py index de3645d624..9d3aee7b04 100644 --- a/disnake/enums.py +++ b/disnake/enums.py @@ -607,7 +607,7 @@ def __str__(self) -> str: class StatusDisplayType(Enum): """Specifies an :class:`Activity` display status. - .. versionaddedd:: 2.11 + .. versionadded:: 2.11 """ name = 0 # type: ignore[reportAssignmentType] diff --git a/docs/api/activities.rst b/docs/api/activities.rst index 6dd6b34bf2..300e69dedc 100644 --- a/docs/api/activities.rst +++ b/docs/api/activities.rst @@ -83,6 +83,12 @@ Status .. autoclass:: Status() :members: +StatusDisplayType +~~~~~~~~~~~~~~~~~ + +.. autoclass:: StatusDisplayType() + :members: + Events ------ From 40b6182bb261fcdb4bfaef6fc03e38ff1a67f35c Mon Sep 17 00:00:00 2001 From: Snipy7374 <100313469+Snipy7374@users.noreply.github.com> Date: Fri, 22 Aug 2025 11:14:04 +0200 Subject: [PATCH 3/5] Update disnake/activity.py Co-authored-by: vi <8530778+shiftinv@users.noreply.github.com> Signed-off-by: Snipy7374 <100313469+Snipy7374@users.noreply.github.com> --- disnake/activity.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/disnake/activity.py b/disnake/activity.py index a3963e2334..a7cd031842 100644 --- a/disnake/activity.py +++ b/disnake/activity.py @@ -368,9 +368,9 @@ def __init__( ) self.status_display_type: Optional[StatusDisplayType] = ( - status_display_type - if isinstance(status_display_type, StatusDisplayType) - else try_enum(StatusDisplayType, status_display_type) + try_enum(StatusDisplayType, status_display_type) + if isinstance(status_display_type, int) + else status_display_type ) self.emoji: Optional[PartialEmoji] = ( From 07ae7341771deb3a2eb6176a936672c8b9033ad7 Mon Sep 17 00:00:00 2001 From: Snipy7374 <100313469+Snipy7374@users.noreply.github.com> Date: Sat, 23 Aug 2025 09:42:44 +0200 Subject: [PATCH 4/5] add docs and add new properties to _BaseActivity --- disnake/activity.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/disnake/activity.py b/disnake/activity.py index a7cd031842..392a997dca 100644 --- a/disnake/activity.py +++ b/disnake/activity.py @@ -192,6 +192,22 @@ def small_image_text(self) -> Optional[str]: """ return self.assets.get("small_text", None) + @property + def large_image_link(self) -> Optional[str]: + """Optional[:class:`str`]: Returns the large image asset URL of this activity, if applicable. + + .. versionadded:: 2.11 + """ + return self.assets.get("large_url") + + @property + def small_image_link(self) -> Optional[str]: + """Optional[:class:`str`]: Returns the small image asset URL of this activity, if applicable. + + .. versionadded:: 2.11 + """ + return self.assets.get("small_url") + # tag type for user-settable activities class BaseActivity(_BaseActivity): @@ -267,8 +283,10 @@ class Activity(BaseActivity): - ``large_image``: A string representing the ID for the large image asset. - ``large_text``: A string representing the text when hovering over the large image asset. + - ``large_url``: A string representing an URL that is opened when clicking on the large image. - ``small_image``: A string representing the ID for the small image asset. - ``small_text``: A string representing the text when hovering over the small image asset. + - ``small_url``: A string representing a URL that is opened when clicking on the small image. party: :class:`dict` A dictionary representing the activity party. It contains the following optional keys: From f606347776169b014874ddcc5cfd3827f11dc0bf Mon Sep 17 00:00:00 2001 From: Snipy7374 <100313469+Snipy7374@users.noreply.github.com> Date: Sat, 23 Aug 2025 09:43:29 +0200 Subject: [PATCH 5/5] remove technical debt from d.py --- disnake/activity.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/disnake/activity.py b/disnake/activity.py index 392a997dca..32761f3844 100644 --- a/disnake/activity.py +++ b/disnake/activity.py @@ -181,7 +181,7 @@ def large_image_text(self) -> Optional[str]: .. versionchanged:: 2.10 Moved from :class:`Activity` to base type, making this available to all activity types. """ - return self.assets.get("large_text", None) + return self.assets.get("large_text") @property def small_image_text(self) -> Optional[str]: @@ -190,7 +190,7 @@ def small_image_text(self) -> Optional[str]: .. versionchanged:: 2.10 Moved from :class:`Activity` to base type, making this available to all activity types. """ - return self.assets.get("small_text", None) + return self.assets.get("small_text") @property def large_image_link(self) -> Optional[str]: