From ac5a936d187ff89d6756e5f33bf0b2965e7b7685 Mon Sep 17 00:00:00 2001 From: Snipy7374 <100313469+Snipy7374@users.noreply.github.com> Date: Sat, 16 Nov 2024 17:46:11 +0100 Subject: [PATCH] feat(member): implement member banners (#1204) Signed-off-by: Snipy7374 <100313469+Snipy7374@users.noreply.github.com> --- changelog/1203.feature.rst | 1 + disnake/asset.py | 13 +++++++++++++ disnake/member.py | 19 +++++++++++++++++++ disnake/types/gateway.py | 1 + 4 files changed, 34 insertions(+) create mode 100644 changelog/1203.feature.rst diff --git a/changelog/1203.feature.rst b/changelog/1203.feature.rst new file mode 100644 index 0000000000..d4412fdf31 --- /dev/null +++ b/changelog/1203.feature.rst @@ -0,0 +1 @@ +Implement new :attr:`.Member.guild_banner` property. diff --git a/disnake/asset.py b/disnake/asset.py index edb0d1c7a6..cf3cf5ac66 100644 --- a/disnake/asset.py +++ b/disnake/asset.py @@ -237,6 +237,19 @@ def _from_guild_avatar( animated=animated, ) + @classmethod + def _from_guild_banner( + cls, state: AnyState, guild_id: int, member_id: int, banner: str + ) -> Self: + animated = banner.startswith("a_") + format = "gif" if animated else "png" + return cls( + state, + url=f"{cls.BASE}/guilds/{guild_id}/users/{member_id}/banners/{banner}.{format}?size=1024", + key=banner, + animated=animated, + ) + @classmethod def _from_icon(cls, state: AnyState, object_id: int, icon_hash: str, path: str) -> Self: return cls( diff --git a/disnake/member.py b/disnake/member.py index 149fc97ecc..7ce63f8c9e 100644 --- a/disnake/member.py +++ b/disnake/member.py @@ -272,6 +272,7 @@ class Member(disnake.abc.Messageable, _UserTag): "_user", "_state", "_avatar", + "_banner", "_communication_disabled_until", "_flags", "_avatar_decoration_data", @@ -340,6 +341,7 @@ def __init__( self.nick: Optional[str] = data.get("nick") self.pending: bool = data.get("pending", False) self._avatar: Optional[str] = data.get("avatar") + self._banner: Optional[str] = data.get("banner") timeout_datetime = utils.parse_time(data.get("communication_disabled_until")) self._communication_disabled_until: Optional[datetime.datetime] = timeout_datetime self._flags: int = data.get("flags", 0) @@ -409,6 +411,7 @@ def _copy(cls, member: Member) -> Self: self.activities = member.activities self._state = member._state self._avatar = member._avatar + self._banner = member._banner self._communication_disabled_until = member.current_timeout self._flags = member._flags @@ -437,6 +440,7 @@ def _update(self, data: GuildMemberUpdateEvent) -> None: self.premium_since = utils.parse_time(data.get("premium_since")) self._roles = utils.SnowflakeList(map(int, data["roles"])) self._avatar = data.get("avatar") + self._banner = data.get("banner") timeout_datetime = utils.parse_time(data.get("communication_disabled_until")) self._communication_disabled_until = timeout_datetime self._flags = data.get("flags", 0) @@ -619,6 +623,21 @@ def guild_avatar(self) -> Optional[Asset]: return None return Asset._from_guild_avatar(self._state, self.guild.id, self.id, self._avatar) + # TODO + # implement a `display_banner` property + # for more info on why this wasn't implemented read this discussion + # https://github.com/DisnakeDev/disnake/pull/1204#discussion_r1685773429 + @property + def guild_banner(self) -> Optional[Asset]: + """Optional[:class:`Asset`]: Returns an :class:`Asset` for the guild banner + the member has. If unavailable, ``None`` is returned. + + .. versionadded:: 2.10 + """ + if self._banner is None: + return None + return Asset._from_guild_banner(self._state, self.guild.id, self.id, self._banner) + @property def activity(self) -> Optional[ActivityTypes]: """Optional[Union[:class:`BaseActivity`, :class:`Spotify`]]: Returns the primary diff --git a/disnake/types/gateway.py b/disnake/types/gateway.py index 736634c944..7f86cd5959 100644 --- a/disnake/types/gateway.py +++ b/disnake/types/gateway.py @@ -453,6 +453,7 @@ class GuildMemberUpdateEvent(TypedDict): user: User nick: NotRequired[Optional[str]] avatar: Optional[str] + banner: Optional[str] joined_at: Optional[str] premium_since: NotRequired[Optional[str]] deaf: NotRequired[bool]