diff --git a/discord/asset.py b/discord/asset.py index 07c7ca8e7b..2ec7d51a20 100644 --- a/discord/asset.py +++ b/discord/asset.py @@ -300,6 +300,31 @@ def _from_scheduled_event_image( animated=False, ) + @classmethod + def _from_user_tag(cls, state, guild_id: int, badge_id: str) -> Asset: + """Creates an Asset for a user's clan (tag) badge. + + Parameters + ---------- + state: ConnectionState + The connection state. + guild_id: int + The ID of the guild (clan). + badge_id: str + The badge hash/id. + + Returns + ------- + :class:`Asset` + The clan badge asset. + """ + return cls( + state, + url=f"{cls.BASE}/clan-badges/{guild_id}/{badge_id}.png?size=256", + key=badge_id, + animated=False, + ) + def __str__(self) -> str: return self._url diff --git a/discord/guild.py b/discord/guild.py index 337abd31c0..8fd78d6980 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -56,6 +56,7 @@ EntitlementOwnerType, NotificationLevel, NSFWLevel, + OnboardingMode, ScheduledEventLocationType, ScheduledEventPrivacyLevel, VerificationLevel, @@ -77,7 +78,7 @@ from .member import Member, VoiceState from .mixins import Hashable from .monetization import Entitlement -from .onboarding import Onboarding +from .onboarding import Onboarding, OnboardingPrompt from .permissions import PermissionOverwrite from .role import Role from .scheduled_events import ScheduledEvent, ScheduledEventLocation diff --git a/discord/types/user.py b/discord/types/user.py index a0383e4f04..29df04b1e6 100644 --- a/discord/types/user.py +++ b/discord/types/user.py @@ -27,6 +27,8 @@ from typing import Literal, TypedDict +from discord.asset import Asset + from .snowflake import Snowflake @@ -41,6 +43,13 @@ class PartialUser(TypedDict): PremiumType = Literal[0, 1, 2, 3] +class Tag(TypedDict, total=False): + identity_guild_id: Snowflake | None + identity_enabled: bool | None + tag: str | None + badge: str | None + + class User(PartialUser, total=False): bot: bool system: bool diff --git a/discord/user.py b/discord/user.py index 9fa995cf66..d524ec8fac 100644 --- a/discord/user.py +++ b/discord/user.py @@ -28,6 +28,7 @@ from typing import TYPE_CHECKING, Any, TypeVar import discord.abc +from discord.types.user import Tag from .asset import Asset from .colour import Colour @@ -76,6 +77,7 @@ class BaseUser(_UserTag): "_public_flags", "_avatar_decoration", "_state", + "_clan", ) if TYPE_CHECKING: @@ -91,6 +93,7 @@ class BaseUser(_UserTag): _accent_colour: int | None _avatar_decoration: dict | None _public_flags: int + _clan: dict | None def __init__( self, *, state: ConnectionState, data: UserPayload | PartialUserPayload @@ -146,6 +149,7 @@ def _update(self, data: UserPayload) -> None: self._public_flags = data.get("public_flags", 0) self.bot = data.get("bot", False) self.system = data.get("system", False) + self._clan = data.get("clan", None) @classmethod def _copy(cls: type[BU], user: BU) -> BU: @@ -162,6 +166,7 @@ def _copy(cls: type[BU], user: BU) -> BU: self.bot = user.bot self._state = user._state self._public_flags = user._public_flags + self._clan = user._clan return self @@ -296,6 +301,29 @@ def mention(self) -> str: """Returns a string that allows you to mention the given user.""" return f"<@{self.id}>" + @property + def tag(self) -> Tag: + """Returns a :class:`Tag` object that contains the user's tag information. + + .. versionadded:: 2.5 + + .. note:: + This information is only available via :meth:`Client.fetch_user`. + """ + if self._clan: + return Tag( + guild_id=self._clan.get("identity_guild_id"), + enabled=self._clan.get("identity_enabled", False), + tag=self._clan.get("tag", str(self)), + badge=self._clan.get("badge"), + ) + return Tag( + identity_guild_id=None, + identity_enabled=False, + tag=str(self), + badge=None, + ) + @property def created_at(self) -> datetime: """Returns the user's creation time in UTC.