mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-08-30 15:01:42 +00:00
Add support for user collectibles
This commit is contained in:
parent
69f06c9456
commit
cbff6ddef9
@ -75,6 +75,7 @@ from .subscription import *
|
|||||||
from .presences import *
|
from .presences import *
|
||||||
from .primary_guild import *
|
from .primary_guild import *
|
||||||
from .onboarding import *
|
from .onboarding import *
|
||||||
|
from .collectible import *
|
||||||
|
|
||||||
|
|
||||||
class VersionInfo(NamedTuple):
|
class VersionInfo(NamedTuple):
|
||||||
|
@ -355,6 +355,16 @@ class Asset(AssetMixin):
|
|||||||
animated=False,
|
animated=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _from_user_collectible(cls, state: _State, asset: str, animated: bool = False) -> Self:
|
||||||
|
name = 'static.png' if not animated else 'asset.webm'
|
||||||
|
return cls(
|
||||||
|
state,
|
||||||
|
url=f'{cls.BASE}/assets/collectibles/{asset}{name}',
|
||||||
|
key=asset,
|
||||||
|
animated=animated,
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self._url
|
return self._url
|
||||||
|
|
||||||
|
109
discord/collectible.py
Normal file
109
discord/collectible.py
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
"""
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015-present Rapptz
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Optional, TYPE_CHECKING
|
||||||
|
|
||||||
|
|
||||||
|
from .asset import Asset
|
||||||
|
from .enums import NameplatePalette, CollectibleType, try_enum
|
||||||
|
from .utils import parse_time
|
||||||
|
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from .state import ConnectionState
|
||||||
|
from .types.user import (
|
||||||
|
Collectible as CollectiblePayload,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ('Collectible',)
|
||||||
|
|
||||||
|
|
||||||
|
class Collectible:
|
||||||
|
"""Represents a user's collectible.
|
||||||
|
|
||||||
|
.. versionadded:: 2.7
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
----------
|
||||||
|
label: :class:`str`
|
||||||
|
The label of the collectible.
|
||||||
|
palette: Optional[:class:`NameplatePalette`]
|
||||||
|
The palette of the collectible.
|
||||||
|
This is only available if ``type`` is
|
||||||
|
:class:`CollectibleType.nameplate`.
|
||||||
|
sku_id: :class:`int`
|
||||||
|
The SKU ID of the collectible.
|
||||||
|
type: :class:`CollectibleType`
|
||||||
|
The type of the collectible.
|
||||||
|
expires_at: Optional[:class:`datetime.datetime`]
|
||||||
|
The expiration date of the collectible. If applicable.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__slots__ = (
|
||||||
|
'type',
|
||||||
|
'sku_id',
|
||||||
|
'label',
|
||||||
|
'expires_at',
|
||||||
|
'palette',
|
||||||
|
'_state',
|
||||||
|
'_asset',
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, *, state: ConnectionState, type: str, data: CollectiblePayload) -> None:
|
||||||
|
self._state: ConnectionState = state
|
||||||
|
self.type: CollectibleType = try_enum(CollectibleType, type)
|
||||||
|
self._asset: str = data['asset']
|
||||||
|
self.sku_id: int = int(data['sku_id'])
|
||||||
|
self.label: str = data['label']
|
||||||
|
self.expires_at: Optional[datetime] = parse_time(data.get('expires_at'))
|
||||||
|
|
||||||
|
# nameplate
|
||||||
|
self.palette: Optional[NameplatePalette]
|
||||||
|
try:
|
||||||
|
self.palette = try_enum(NameplatePalette, data['palette']) # type: ignore
|
||||||
|
except KeyError:
|
||||||
|
self.palette = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def static(self) -> Asset:
|
||||||
|
""":class:`Asset`: The static asset of the collectible."""
|
||||||
|
return Asset._from_user_collectible(self._state, self._asset)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def animated(self) -> Asset:
|
||||||
|
""":class:`Asset`: The animated asset of the collectible."""
|
||||||
|
return Asset._from_user_collectible(self._state, self._asset, animated=True)
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
attrs = ['sku_id']
|
||||||
|
if self.palette:
|
||||||
|
attrs.append('palette')
|
||||||
|
|
||||||
|
joined_attrs = ' '.join(f'{attr}={getattr(self, attr)!r}' for attr in attrs)
|
||||||
|
return f'<{self.type.name.title()} {joined_attrs}>'
|
@ -83,6 +83,8 @@ __all__ = (
|
|||||||
'OnboardingMode',
|
'OnboardingMode',
|
||||||
'SeparatorSpacing',
|
'SeparatorSpacing',
|
||||||
'MediaItemLoadingState',
|
'MediaItemLoadingState',
|
||||||
|
'CollectibleType',
|
||||||
|
'NameplatePalette',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -968,6 +970,24 @@ class MediaItemLoadingState(Enum):
|
|||||||
not_found = 3
|
not_found = 3
|
||||||
|
|
||||||
|
|
||||||
|
class CollectibleType(Enum):
|
||||||
|
nameplate = 'nameplate'
|
||||||
|
|
||||||
|
|
||||||
|
class NameplatePalette(Enum):
|
||||||
|
crimson = 'crimson'
|
||||||
|
berry = 'berry'
|
||||||
|
sky = 'sky'
|
||||||
|
teal = 'teal'
|
||||||
|
forest = 'forest'
|
||||||
|
bubble_gum = 'bubble_gum'
|
||||||
|
violet = 'violet'
|
||||||
|
cobalt = 'cobalt'
|
||||||
|
clover = 'clover'
|
||||||
|
lemon = 'lemon'
|
||||||
|
white = 'white'
|
||||||
|
|
||||||
|
|
||||||
def create_unknown_value(cls: Type[E], val: Any) -> E:
|
def create_unknown_value(cls: Type[E], val: Any) -> E:
|
||||||
value_cls = cls._enum_value_cls_ # type: ignore # This is narrowed below
|
value_cls = cls._enum_value_cls_ # type: ignore # This is narrowed below
|
||||||
name = f'unknown_{val}'
|
name = f'unknown_{val}'
|
||||||
|
@ -75,6 +75,7 @@ if TYPE_CHECKING:
|
|||||||
VoiceState as VoiceStatePayload,
|
VoiceState as VoiceStatePayload,
|
||||||
)
|
)
|
||||||
from .primary_guild import PrimaryGuild
|
from .primary_guild import PrimaryGuild
|
||||||
|
from .collectible import Collectible
|
||||||
|
|
||||||
VocalGuildChannel = Union[VoiceChannel, StageChannel]
|
VocalGuildChannel = Union[VoiceChannel, StageChannel]
|
||||||
|
|
||||||
@ -311,6 +312,7 @@ class Member(discord.abc.Messageable, _UserTag):
|
|||||||
avatar_decoration: Optional[Asset]
|
avatar_decoration: Optional[Asset]
|
||||||
avatar_decoration_sku_id: Optional[int]
|
avatar_decoration_sku_id: Optional[int]
|
||||||
primary_guild: PrimaryGuild
|
primary_guild: PrimaryGuild
|
||||||
|
collectibles: List[Collectible]
|
||||||
|
|
||||||
def __init__(self, *, data: MemberWithUserPayload, guild: Guild, state: ConnectionState):
|
def __init__(self, *, data: MemberWithUserPayload, guild: Guild, state: ConnectionState):
|
||||||
self._state: ConnectionState = state
|
self._state: ConnectionState = state
|
||||||
|
@ -27,11 +27,38 @@ from typing import Literal, Optional, TypedDict
|
|||||||
from typing_extensions import NotRequired
|
from typing_extensions import NotRequired
|
||||||
|
|
||||||
|
|
||||||
class AvatarDecorationData(TypedDict):
|
PremiumType = Literal[0, 1, 2, 3]
|
||||||
|
NameplatePallete = Literal['crimson', 'berry', 'sky', 'teal', 'forest', 'bubble_gum', 'violet', 'cobalt', 'clover']
|
||||||
|
|
||||||
|
|
||||||
|
class _UserSKU(TypedDict):
|
||||||
asset: str
|
asset: str
|
||||||
sku_id: Snowflake
|
sku_id: Snowflake
|
||||||
|
|
||||||
|
|
||||||
|
AvatarDecorationData = _UserSKU
|
||||||
|
|
||||||
|
|
||||||
|
class PrimaryGuild(TypedDict):
|
||||||
|
identity_guild_id: Optional[int]
|
||||||
|
identity_enabled: Optional[bool]
|
||||||
|
tag: Optional[str]
|
||||||
|
badge: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
|
class Collectible(_UserSKU):
|
||||||
|
label: str
|
||||||
|
expires_at: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
|
class NameplateCollectible(Collectible):
|
||||||
|
palette: str
|
||||||
|
|
||||||
|
|
||||||
|
class UserCollectibles(TypedDict):
|
||||||
|
nameplate: NameplateCollectible
|
||||||
|
|
||||||
|
|
||||||
class PartialUser(TypedDict):
|
class PartialUser(TypedDict):
|
||||||
id: Snowflake
|
id: Snowflake
|
||||||
username: str
|
username: str
|
||||||
@ -39,9 +66,8 @@ class PartialUser(TypedDict):
|
|||||||
avatar: Optional[str]
|
avatar: Optional[str]
|
||||||
global_name: Optional[str]
|
global_name: Optional[str]
|
||||||
avatar_decoration_data: NotRequired[AvatarDecorationData]
|
avatar_decoration_data: NotRequired[AvatarDecorationData]
|
||||||
|
primary_guild: NotRequired[PrimaryGuild]
|
||||||
|
collectibles: NotRequired[UserCollectibles]
|
||||||
PremiumType = Literal[0, 1, 2, 3]
|
|
||||||
|
|
||||||
|
|
||||||
class User(PartialUser, total=False):
|
class User(PartialUser, total=False):
|
||||||
@ -54,10 +80,3 @@ class User(PartialUser, total=False):
|
|||||||
flags: int
|
flags: int
|
||||||
premium_type: PremiumType
|
premium_type: PremiumType
|
||||||
public_flags: int
|
public_flags: int
|
||||||
|
|
||||||
|
|
||||||
class PrimaryGuild(TypedDict):
|
|
||||||
identity_guild_id: Optional[int]
|
|
||||||
identity_enabled: Optional[bool]
|
|
||||||
tag: Optional[str]
|
|
||||||
badge: Optional[str]
|
|
||||||
|
@ -33,6 +33,7 @@ from .enums import DefaultAvatar
|
|||||||
from .flags import PublicUserFlags
|
from .flags import PublicUserFlags
|
||||||
from .utils import snowflake_time, _bytes_to_base64_data, MISSING, _get_as_snowflake
|
from .utils import snowflake_time, _bytes_to_base64_data, MISSING, _get_as_snowflake
|
||||||
from .primary_guild import PrimaryGuild
|
from .primary_guild import PrimaryGuild
|
||||||
|
from .collectible import Collectible
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing_extensions import Self
|
from typing_extensions import Self
|
||||||
@ -49,6 +50,7 @@ if TYPE_CHECKING:
|
|||||||
User as UserPayload,
|
User as UserPayload,
|
||||||
AvatarDecorationData,
|
AvatarDecorationData,
|
||||||
PrimaryGuild as PrimaryGuildPayload,
|
PrimaryGuild as PrimaryGuildPayload,
|
||||||
|
UserCollectibles as UserCollectiblesPayload,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -78,6 +80,7 @@ class BaseUser(_UserTag):
|
|||||||
'_state',
|
'_state',
|
||||||
'_avatar_decoration_data',
|
'_avatar_decoration_data',
|
||||||
'_primary_guild',
|
'_primary_guild',
|
||||||
|
'_collectibles',
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -94,6 +97,7 @@ class BaseUser(_UserTag):
|
|||||||
_public_flags: int
|
_public_flags: int
|
||||||
_avatar_decoration_data: Optional[AvatarDecorationData]
|
_avatar_decoration_data: Optional[AvatarDecorationData]
|
||||||
_primary_guild: Optional[PrimaryGuildPayload]
|
_primary_guild: Optional[PrimaryGuildPayload]
|
||||||
|
_collectibles: Optional[UserCollectiblesPayload]
|
||||||
|
|
||||||
def __init__(self, *, state: ConnectionState, data: Union[UserPayload, PartialUserPayload]) -> None:
|
def __init__(self, *, state: ConnectionState, data: Union[UserPayload, PartialUserPayload]) -> None:
|
||||||
self._state = state
|
self._state = state
|
||||||
@ -132,6 +136,7 @@ class BaseUser(_UserTag):
|
|||||||
self.system = data.get('system', False)
|
self.system = data.get('system', False)
|
||||||
self._avatar_decoration_data = data.get('avatar_decoration_data')
|
self._avatar_decoration_data = data.get('avatar_decoration_data')
|
||||||
self._primary_guild = data.get('primary_guild', None)
|
self._primary_guild = data.get('primary_guild', None)
|
||||||
|
self._collectibles = data.get('collectibles', None)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _copy(cls, user: Self) -> Self:
|
def _copy(cls, user: Self) -> Self:
|
||||||
@ -149,6 +154,7 @@ class BaseUser(_UserTag):
|
|||||||
self._public_flags = user._public_flags
|
self._public_flags = user._public_flags
|
||||||
self._avatar_decoration_data = user._avatar_decoration_data
|
self._avatar_decoration_data = user._avatar_decoration_data
|
||||||
self._primary_guild = user._primary_guild
|
self._primary_guild = user._primary_guild
|
||||||
|
self._collectibles = user._collectibles
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@ -324,6 +330,16 @@ class BaseUser(_UserTag):
|
|||||||
return PrimaryGuild(state=self._state, data=self._primary_guild)
|
return PrimaryGuild(state=self._state, data=self._primary_guild)
|
||||||
return PrimaryGuild._default(self._state)
|
return PrimaryGuild._default(self._state)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def collectibles(self) -> List[Collectible]:
|
||||||
|
"""List[:class:`Collectible`]: Returns a list of the user's collectibles.
|
||||||
|
|
||||||
|
.. versionadded:: 2.7
|
||||||
|
"""
|
||||||
|
if self._collectibles is None:
|
||||||
|
return []
|
||||||
|
return [Collectible(state=self._state, type=key, data=value) for key, value in self._collectibles.items() if value] # type: ignore
|
||||||
|
|
||||||
def mentioned_in(self, message: Message) -> bool:
|
def mentioned_in(self, message: Message) -> bool:
|
||||||
"""Checks if the user is mentioned in the specified message.
|
"""Checks if the user is mentioned in the specified message.
|
||||||
|
|
||||||
|
70
docs/api.rst
70
docs/api.rst
@ -4052,8 +4052,6 @@ of :class:`enum.Enum`.
|
|||||||
|
|
||||||
Default channels and questions count towards onboarding constraints.
|
Default channels and questions count towards onboarding constraints.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. class:: MediaItemLoadingState
|
.. class:: MediaItemLoadingState
|
||||||
|
|
||||||
Represents a :class:`UnfurledMediaItem` load state.
|
Represents a :class:`UnfurledMediaItem` load state.
|
||||||
@ -4074,6 +4072,66 @@ of :class:`enum.Enum`.
|
|||||||
|
|
||||||
The media item was not found.
|
The media item was not found.
|
||||||
|
|
||||||
|
.. class:: CollectibleType
|
||||||
|
|
||||||
|
Represents the type of a :class:`Collectible`.
|
||||||
|
|
||||||
|
.. versionadded:: 2.7
|
||||||
|
|
||||||
|
.. attribute:: nameplate
|
||||||
|
|
||||||
|
The collectible is a nameplate.
|
||||||
|
|
||||||
|
.. class:: NameplatePalette
|
||||||
|
|
||||||
|
Represents the available palettes for a nameplate.
|
||||||
|
|
||||||
|
.. versionadded:: 2.7
|
||||||
|
|
||||||
|
.. attribute:: crimson
|
||||||
|
|
||||||
|
The collectible nameplate palette is crimson.
|
||||||
|
|
||||||
|
.. attribute:: berry
|
||||||
|
|
||||||
|
The collectible nameplate palette is berry.
|
||||||
|
|
||||||
|
.. attribute:: sky
|
||||||
|
|
||||||
|
The collectible nameplate palette is sky.
|
||||||
|
|
||||||
|
.. attribute:: teal
|
||||||
|
|
||||||
|
The collectible nameplate palette is teal.
|
||||||
|
|
||||||
|
.. attribute:: forest
|
||||||
|
|
||||||
|
The collectible nameplate palette is forest.
|
||||||
|
|
||||||
|
.. attribute:: bubble_gum
|
||||||
|
|
||||||
|
The collectible nameplate palette is bubble gum.
|
||||||
|
|
||||||
|
.. attribute:: violet
|
||||||
|
|
||||||
|
The collectible nameplate palette is violet.
|
||||||
|
|
||||||
|
.. attribute:: cobalt
|
||||||
|
|
||||||
|
The collectible nameplate palette is cobalt.
|
||||||
|
|
||||||
|
.. attribute:: clover
|
||||||
|
|
||||||
|
The collectible nameplate palette is clover.
|
||||||
|
|
||||||
|
.. attribute:: lemon
|
||||||
|
|
||||||
|
The collectible nameplate palette is lemon.
|
||||||
|
|
||||||
|
.. attribute:: white
|
||||||
|
|
||||||
|
The collectible nameplate palette is white.
|
||||||
|
|
||||||
.. _discord-api-audit-logs:
|
.. _discord-api-audit-logs:
|
||||||
|
|
||||||
Audit Log Data
|
Audit Log Data
|
||||||
@ -5770,6 +5828,14 @@ PrimaryGuild
|
|||||||
.. autoclass:: PrimaryGuild()
|
.. autoclass:: PrimaryGuild()
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
Collectible
|
||||||
|
~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. attributetable:: Collectible
|
||||||
|
|
||||||
|
.. autoclass:: Collectible()
|
||||||
|
:members:
|
||||||
|
|
||||||
CallMessage
|
CallMessage
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user