diff --git a/CHANGELOG.md b/CHANGELOG.md index 05c28562fd..04eace050e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ These changes are available on the `master` branch, but have not yet been releas - Added `Guild.fetch_role` method. ([#2528](https://github.com/Pycord-Development/pycord/pull/2528)) +- Added `Member.guild_banner` and `Member.display_banner` properties. + ([#2556](https://github.com/Pycord-Development/pycord/pull/2556)) ### Fixed diff --git a/discord/asset.py b/discord/asset.py index c8a33e61e3..07c7ca8e7b 100644 --- a/discord/asset.py +++ b/discord/asset.py @@ -212,6 +212,19 @@ def _from_guild_avatar( animated=animated, ) + @classmethod + def _from_guild_banner( + cls, state, guild_id: int, member_id: int, banner: str + ) -> Asset: + 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=512", + key=banner, + animated=animated, + ) + @classmethod def _from_icon(cls, state, object_id: int, icon_hash: str, path: str) -> Asset: return cls( diff --git a/discord/member.py b/discord/member.py index 18ebf1267f..f1a546c918 100644 --- a/discord/member.py +++ b/discord/member.py @@ -288,6 +288,7 @@ class Member(discord.abc.Messageable, _UserTag): "_user", "_state", "_avatar", + "_banner", "communication_disabled_until", "flags", ) @@ -328,6 +329,7 @@ def __init__( self.nick: str | None = data.get("nick", None) self.pending: bool = data.get("pending", False) self._avatar: str | None = data.get("avatar") + self._banner: str | None = data.get("banner") self.communication_disabled_until: datetime.datetime | None = utils.parse_time( data.get("communication_disabled_until") ) @@ -406,6 +408,7 @@ def _copy(cls: type[M], member: M) -> M: self.activities = member.activities self._state = member._state self._avatar = member._avatar + self._banner = member._banner self.communication_disabled_until = member.communication_disabled_until self.flags = member.flags @@ -434,6 +437,7 @@ def _update(self, data: MemberPayload) -> 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") self.communication_disabled_until = utils.parse_time( data.get("communication_disabled_until") ) @@ -603,6 +607,31 @@ def guild_avatar(self) -> Asset | None: self._state, self.guild.id, self.id, self._avatar ) + @property + def display_banner(self) -> Asset | None: + """Returns the member's display banner. + + For regular members this is just their banner, but + if they have a guild specific banner then that + is returned instead. + + .. versionadded:: 2.7 + """ + return self.guild_banner or self._user.banner + + @property + def guild_banner(self) -> Asset | None: + """Returns an :class:`Asset` for the guild banner + the member has. If unavailable, ``None`` is returned. + + .. versionadded:: 2.7 + """ + 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) -> ActivityTypes | None: """Returns the primary diff --git a/discord/types/member.py b/discord/types/member.py index 0bc1071fb1..618bb13efe 100644 --- a/discord/types/member.py +++ b/discord/types/member.py @@ -42,6 +42,7 @@ class PartialMember(TypedDict): class Member(PartialMember, total=False): avatar: str + banner: str user: User nick: str premium_since: str