|
|
@ -24,16 +24,18 @@ DEALINGS IN THE SOFTWARE. |
|
|
|
|
|
|
|
from __future__ import annotations |
|
|
|
|
|
|
|
from typing import TYPE_CHECKING, List, Optional |
|
|
|
from typing import TYPE_CHECKING, List, Optional, Tuple |
|
|
|
|
|
|
|
from . import utils |
|
|
|
from .application import ApplicationInstallParams |
|
|
|
from .asset import Asset, AssetMixin |
|
|
|
from .colour import Colour |
|
|
|
from .connections import PartialConnection |
|
|
|
from .enums import PremiumType, try_enum |
|
|
|
from .flags import ApplicationFlags |
|
|
|
from .member import Member |
|
|
|
from .mixins import Hashable |
|
|
|
from .partial_emoji import PartialEmoji |
|
|
|
from .user import User |
|
|
|
|
|
|
|
if TYPE_CHECKING: |
|
|
@ -45,11 +47,13 @@ if TYPE_CHECKING: |
|
|
|
Profile as ProfilePayload, |
|
|
|
ProfileApplication as ProfileApplicationPayload, |
|
|
|
ProfileBadge as ProfileBadgePayload, |
|
|
|
ProfileMetadata as ProfileMetadataPayload, |
|
|
|
MutualGuild as MutualGuildPayload, |
|
|
|
) |
|
|
|
from .types.user import PartialUser as PartialUserPayload |
|
|
|
|
|
|
|
__all__ = ( |
|
|
|
'ProfileMetadata', |
|
|
|
'ApplicationProfile', |
|
|
|
'MutualGuild', |
|
|
|
'ProfileBadge', |
|
|
@ -71,6 +75,7 @@ class Profile: |
|
|
|
mutual_friends: List[PartialUserPayload] = kwargs.pop('mutual_friends', None) |
|
|
|
|
|
|
|
member = data.get('guild_member') |
|
|
|
member_profile = data.get('guild_member_profile') |
|
|
|
if member is not None: |
|
|
|
member['user'] = user |
|
|
|
kwargs['data'] = member |
|
|
@ -84,6 +89,11 @@ class Profile: |
|
|
|
super().__init__(**kwargs) |
|
|
|
state = self._state |
|
|
|
|
|
|
|
self.metadata = ProfileMetadata(id=self.id, state=state, data=profile) |
|
|
|
if member is not None: |
|
|
|
self.guild_metadata = ProfileMetadata(id=self.id, state=state, data=member_profile) |
|
|
|
|
|
|
|
self.legacy_username: Optional[str] = data.get('legacy_username') |
|
|
|
self.bio: Optional[str] = user['bio'] or None |
|
|
|
|
|
|
|
# We need to do a bit of a hack here because premium_since is massively overloaded |
|
|
@ -91,9 +101,7 @@ class Profile: |
|
|
|
if guild_premium_since is not utils.MISSING: |
|
|
|
self.guild_premium_since = guild_premium_since |
|
|
|
|
|
|
|
self.premium_type: Optional[PremiumType] = ( |
|
|
|
try_enum(PremiumType, data.get('premium_type') or 0) if profile else None |
|
|
|
) |
|
|
|
self.premium_type: Optional[PremiumType] = try_enum(PremiumType, data.get('premium_type') or 0) if profile else None |
|
|
|
self.premium_since: Optional[datetime] = utils.parse_time(data.get('premium_since')) |
|
|
|
self.premium_guild_since: Optional[datetime] = utils.parse_time(data.get('premium_guild_since')) |
|
|
|
self.connections: List[PartialConnection] = [PartialConnection(d) for d in data['connected_accounts']] |
|
|
@ -137,6 +145,110 @@ class Profile: |
|
|
|
return self.premium_since is not None |
|
|
|
|
|
|
|
|
|
|
|
class ProfileMetadata: |
|
|
|
"""Represents global or per-user Discord profile metadata. |
|
|
|
|
|
|
|
.. versionadded:: 2.1 |
|
|
|
|
|
|
|
Attributes |
|
|
|
------------ |
|
|
|
bio: Optional[:class:`str`] |
|
|
|
The profile's "about me" field. Could be ``None``. |
|
|
|
pronouns: Optional[:class:`str`] |
|
|
|
The profile's pronouns, if any. |
|
|
|
effect_id: Optional[:class:`int`] |
|
|
|
The ID of the profile effect the user has, if any. |
|
|
|
""" |
|
|
|
|
|
|
|
__slots__ = ( |
|
|
|
'_id', |
|
|
|
'_state', |
|
|
|
'bio', |
|
|
|
'pronouns', |
|
|
|
'emoji', |
|
|
|
'popout_animation_particle_type', |
|
|
|
'effect_id', |
|
|
|
'_banner', |
|
|
|
'_accent_colour', |
|
|
|
'_theme_colours', |
|
|
|
'_guild_id', |
|
|
|
) |
|
|
|
|
|
|
|
def __init__(self, *, id: int, state: ConnectionState, data: Optional[ProfileMetadataPayload]) -> None: |
|
|
|
self._id = id |
|
|
|
self._state = state |
|
|
|
|
|
|
|
# user_profile is null if blocked |
|
|
|
if data is None: |
|
|
|
data = {'pronouns': ''} |
|
|
|
|
|
|
|
self.bio: Optional[str] = data.get('bio') or None |
|
|
|
self.pronouns: Optional[str] = data.get('pronouns') or None |
|
|
|
self.emoji: Optional[PartialEmoji] = PartialEmoji.from_dict_stateful(data['emoji'], state) if data.get('emoji') else None # type: ignore |
|
|
|
self.popout_animation_particle_type: Optional[int] = utils._get_as_snowflake(data, 'popout_animation_particle_type') |
|
|
|
self.effect_id: Optional[int] = utils._get_as_snowflake(data['profile_effect'], 'id') if data.get('profile_effect') else None # type: ignore |
|
|
|
self._banner: Optional[str] = data.get('banner') |
|
|
|
self._accent_colour: Optional[int] = data.get('accent_color') |
|
|
|
self._theme_colours: Optional[Tuple[int, int]] = tuple(data['theme_colors']) if data.get('theme_colors') else None # type: ignore |
|
|
|
self._guild_id: Optional[int] = utils._get_as_snowflake(data, 'guild_id') |
|
|
|
|
|
|
|
def __repr__(self) -> str: |
|
|
|
return f'<ProfileMetadata bio={self.bio!r} pronouns={self.pronouns!r}>' |
|
|
|
|
|
|
|
@property |
|
|
|
def banner(self) -> Optional[Asset]: |
|
|
|
"""Optional[:class:`Asset`]: Returns the user's banner asset, if available.""" |
|
|
|
if self._banner is None: |
|
|
|
return None |
|
|
|
return Asset._from_user_banner(self._state, self._id, self._banner) |
|
|
|
|
|
|
|
@property |
|
|
|
def accent_colour(self) -> Optional[Colour]: |
|
|
|
"""Optional[:class:`Colour`]: Returns the profile's accent colour, if applicable. |
|
|
|
|
|
|
|
A user's accent colour is only shown if they do not have a banner. |
|
|
|
This will only be available if the user explicitly sets a colour. |
|
|
|
|
|
|
|
There is an alias for this named :attr:`accent_color`. |
|
|
|
""" |
|
|
|
if self._accent_colour is None: |
|
|
|
return None |
|
|
|
return Colour(self._accent_colour) |
|
|
|
|
|
|
|
@property |
|
|
|
def accent_color(self) -> Optional[Colour]: |
|
|
|
"""Optional[:class:`Colour`]: Returns the profile's accent color, if applicable. |
|
|
|
|
|
|
|
A user's accent color is only shown if they do not have a banner. |
|
|
|
This will only be available if the user explicitly sets a color. |
|
|
|
|
|
|
|
There is an alias for this named :attr:`accent_colour`. |
|
|
|
""" |
|
|
|
return self.accent_colour |
|
|
|
|
|
|
|
@property |
|
|
|
def theme_colours(self) -> Optional[Tuple[Colour, Colour]]: |
|
|
|
"""Optional[Tuple[:class:`Colour`, :class:`Colour`]]: Returns the profile's theme colours, if applicable. |
|
|
|
|
|
|
|
The first colour is the user's background colour and the second is the user's foreground colour. |
|
|
|
|
|
|
|
There is an alias for this named :attr:`theme_colors`. |
|
|
|
""" |
|
|
|
if self._theme_colours is None: |
|
|
|
return None |
|
|
|
return tuple(Colour(c) for c in self._theme_colours) # type: ignore |
|
|
|
|
|
|
|
@property |
|
|
|
def theme_colors(self) -> Optional[Tuple[Colour, Colour]]: |
|
|
|
"""Optional[Tuple[:class:`Colour`, :class:`Colour`]]: Returns the profile's theme colors, if applicable. |
|
|
|
|
|
|
|
The first color is the user's background color and the second is the user's foreground color. |
|
|
|
|
|
|
|
There is an alias for this named :attr:`theme_colours`. |
|
|
|
""" |
|
|
|
return self.theme_colours |
|
|
|
|
|
|
|
|
|
|
|
class ApplicationProfile(Hashable): |
|
|
|
"""Represents a Discord application profile. |
|
|
|
|
|
|
@ -362,6 +474,14 @@ class UserProfile(Profile, User): |
|
|
|
----------- |
|
|
|
application: Optional[:class:`ApplicationProfile`] |
|
|
|
The application profile of the user, if it is a bot. |
|
|
|
metadata: :class:`ProfileMetadata` |
|
|
|
The global profile metadata of the user. |
|
|
|
|
|
|
|
.. versionadded:: 2.1 |
|
|
|
legacy_username: Optional[:class:`str`] |
|
|
|
The user's legacy username (Username#Discriminator), if public. |
|
|
|
|
|
|
|
.. versionadded:: 2.1 |
|
|
|
bio: Optional[:class:`str`] |
|
|
|
The user's "about me" field. Could be ``None``. |
|
|
|
premium_type: Optional[:class:`PremiumType`] |
|
|
@ -449,6 +569,14 @@ class MemberProfile(Profile, Member): |
|
|
|
----------- |
|
|
|
application: Optional[:class:`ApplicationProfile`] |
|
|
|
The application profile of the user, if it is a bot. |
|
|
|
metadata: :class:`ProfileMetadata` |
|
|
|
The global profile metadata of the user. |
|
|
|
|
|
|
|
.. versionadded:: 2.1 |
|
|
|
legacy_username: Optional[:class:`str`] |
|
|
|
The user's legacy username (Username#Discriminator), if public. |
|
|
|
|
|
|
|
.. versionadded:: 2.1 |
|
|
|
bio: Optional[:class:`str`] |
|
|
|
The user's "about me" field. Could be ``None``. |
|
|
|
guild_bio: Optional[:class:`str`] |
|
|
|