From 6082e0fed95b2347f4c364daf19cd6bb2cf778fe Mon Sep 17 00:00:00 2001 From: Paillat Date: Sat, 21 Jun 2025 19:04:59 +0200 Subject: [PATCH 01/12] :sparkles: add Nameplate class and integration in user model --- discord/collectibles.py | 55 +++++++++++++++++++++++++++++++++++ discord/types/collectibles.py | 50 +++++++++++++++++++++++++++++++ discord/user.py | 7 +++++ 3 files changed, 112 insertions(+) create mode 100644 discord/collectibles.py create mode 100644 discord/types/collectibles.py diff --git a/discord/collectibles.py b/discord/collectibles.py new file mode 100644 index 0000000000..598c7da9dd --- /dev/null +++ b/discord/collectibles.py @@ -0,0 +1,55 @@ +""" +The MIT License (MIT) + +Copyright (c) 2021-present Pycord Development + +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 typing import TYPE_CHECKING + +if TYPE_CHECKING: + from .state import ConnectionState + +from .asset import Asset +from .types.collectibles import Nameplate as NameplatePayload +from .types.collectibles import NameplatePalette + + +class Nameplate: + """ + Represents a Discord [Nameplate](https://support.discord.com/hc/en-us/articles/30408457944215-Nameplates-FAQ) + + Attributes + ---------- + sku_id: int + The SKU ID of the nameplate. + palette: NameplatePalette + The color palette of the nameplate. + """ + + def __init__(self, data: NameplatePayload, state: "ConnectionState") -> None: + self.sku_id: int = data["sku_id"] + self.palette: NameplatePalette = data["palette"] + self._label: str = data["label"] + self._asset: str = data["asset"] + self._state: "ConnectionState" = state + + def __repr__(self) -> str: + return f"" diff --git a/discord/types/collectibles.py b/discord/types/collectibles.py new file mode 100644 index 0000000000..6daffdea3b --- /dev/null +++ b/discord/types/collectibles.py @@ -0,0 +1,50 @@ +""" +The MIT License (MIT) + +Copyright (c) 2021-present Pycord Development + +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 Literal, TypedDict + +from .snowflake import Snowflake + +NameplatePalette = Literal[ + "crimson", + "berry", + "sky", + "teal", + "forest", + "bubble_gum", + "violet", + "cobalt", + "clover", + "lemon", + "white", +] + + +class Nameplate(TypedDict): + sku_id: Snowflake + asset: str + label: str + palette: NameplatePalette diff --git a/discord/user.py b/discord/user.py index 9fa995cf66..0e4d8bd660 100644 --- a/discord/user.py +++ b/discord/user.py @@ -30,6 +30,7 @@ import discord.abc from .asset import Asset +from .collectibles import Nameplate from .colour import Colour from .flags import PublicUserFlags from .iterators import EntitlementIterator @@ -76,6 +77,7 @@ class BaseUser(_UserTag): "_public_flags", "_avatar_decoration", "_state", + "nameplate", ) if TYPE_CHECKING: @@ -143,6 +145,11 @@ def _update(self, data: UserPayload) -> None: self._banner = data.get("banner", None) self._accent_colour = data.get("accent_color", None) self._avatar_decoration = data.get("avatar_decoration_data", None) + nameplate = (data.get("collectibles") or {}).get("nameplate", None) + if nameplate: + self.nameplate = Nameplate(data=nameplate, state=self._state) + else: + self.nameplate = None self._public_flags = data.get("public_flags", 0) self.bot = data.get("bot", False) self.system = data.get("system", False) From 6466dd5be9d0e00a417d7f29804f8c5b674747a3 Mon Sep 17 00:00:00 2001 From: Paillat Date: Sat, 21 Jun 2025 19:07:55 +0200 Subject: [PATCH 02/12] :label: feat: add nameplate attribute to User class --- discord/user.py | 1 + 1 file changed, 1 insertion(+) diff --git a/discord/user.py b/discord/user.py index 0e4d8bd660..2e273b355f 100644 --- a/discord/user.py +++ b/discord/user.py @@ -93,6 +93,7 @@ class BaseUser(_UserTag): _accent_colour: int | None _avatar_decoration: dict | None _public_flags: int + nameplate: Nameplate | None def __init__( self, *, state: ConnectionState, data: UserPayload | PartialUserPayload From 5f2ab4d9ce2061b83fdfd52c91464951102a6126 Mon Sep 17 00:00:00 2001 From: Paillat Date: Sun, 22 Jun 2025 00:38:23 +0200 Subject: [PATCH 03/12] :sparkles: add NameplatePalette enum and enhance Nameplate class with asset retrieval --- discord/__init__.py | 1 + discord/collectibles.py | 22 +++++++++++++++++++++- discord/enums.py | 16 ++++++++++++++++ discord/types/collectibles.py | 17 ++--------------- docs/api/enums.rst | 6 ++++++ docs/api/models.rst | 10 ++++++++++ 6 files changed, 56 insertions(+), 16 deletions(-) diff --git a/discord/__init__.py b/discord/__init__.py index d6031ce3ac..afe3002e00 100644 --- a/discord/__init__.py +++ b/discord/__init__.py @@ -35,6 +35,7 @@ from .channel import * from .client import * from .cog import * +from .collectibles import * from .colour import * from .commands import * from .components import * diff --git a/discord/collectibles.py b/discord/collectibles.py index 598c7da9dd..53578ddf53 100644 --- a/discord/collectibles.py +++ b/discord/collectibles.py @@ -28,8 +28,8 @@ from .state import ConnectionState from .asset import Asset +from .enums import NameplatePalette from .types.collectibles import Nameplate as NameplatePayload -from .types.collectibles import NameplatePalette class Nameplate: @@ -53,3 +53,23 @@ def __init__(self, data: NameplatePayload, state: "ConnectionState") -> None: def __repr__(self) -> str: return f"" + + def get_asset(self, animated: bool = False) -> Asset: + """Returns the asset of the nameplate. + + Parameters + ---------- + animated: :class:`bool` + Whether to return the animated version of the asset, in webm version. Defaults to ``False``. + """ + fn = "static.png" if not animated else "asset.webm" + return Asset( + state=self._state, + url=f"{Asset.BASE}/assets/collectibles/{self._asset}{fn}", + key=self._asset.split("/")[-1], + animated=animated, + ) + + +__all__ = ("Nameplate", "NameplatePalette") +"""https://cdn.discordapp.com/assets/collectibles/nameplates/nameplates/twilight/asset.webm""" diff --git a/discord/enums.py b/discord/enums.py index 01d10275c8..99c7221feb 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -1078,6 +1078,22 @@ class SubscriptionStatus(Enum): inactive = 2 +class NameplatePalette(Enum): + """A nameplate color palette.""" + + CRIMSON = ("crimson",) + BERRY = "berry" + SKY = "sky" + TEAL = "teal" + FOREST = "forest" + BUBBLE_GUM = "bubble_gum" + VIOLET = "violet" + COBALT = "cobalt" + CLOVER = "clover" + LEMON = "lemon" + WHITE = "white" + + T = TypeVar("T") diff --git a/discord/types/collectibles.py b/discord/types/collectibles.py index 6daffdea3b..d284776917 100644 --- a/discord/types/collectibles.py +++ b/discord/types/collectibles.py @@ -24,24 +24,11 @@ from __future__ import annotations -from typing import Literal, TypedDict +from typing import TypedDict +from ..enums import NameplatePalette from .snowflake import Snowflake -NameplatePalette = Literal[ - "crimson", - "berry", - "sky", - "teal", - "forest", - "bubble_gum", - "violet", - "cobalt", - "clover", - "lemon", - "white", -] - class Nameplate(TypedDict): sku_id: Snowflake diff --git a/docs/api/enums.rst b/docs/api/enums.rst index 4d278e3758..c13300f0d0 100644 --- a/docs/api/enums.rst +++ b/docs/api/enums.rst @@ -2519,3 +2519,9 @@ of :class:`enum.Enum`. .. attribute:: inactive The subscription is inactive and the subscription owner is not being charged. + +.. class:: NameplatePalette + + A nameplate color palette. + + .. versionadded:: 2.7 diff --git a/docs/api/models.rst b/docs/api/models.rst index cb702b2c38..8cfaaf3a17 100644 --- a/docs/api/models.rst +++ b/docs/api/models.rst @@ -602,3 +602,13 @@ Webhooks .. autoclass:: PartialWebhookChannel() :members: + + + +Collectibles +------------ + +.. attributetable:: Nameplate + +.. autoclass:: Nameplate() + :members: From 8f063a465a4d4afccc0af53dbdf00bd145fe7035 Mon Sep 17 00:00:00 2001 From: Paillat Date: Sun, 22 Jun 2025 00:40:22 +0200 Subject: [PATCH 04/12] :memo: add nameplate attribute to User class documentation --- discord/user.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/discord/user.py b/discord/user.py index 2e273b355f..368381191c 100644 --- a/discord/user.py +++ b/discord/user.py @@ -542,6 +542,10 @@ class User(BaseUser, discord.abc.Messageable): Specifies if the user is a bot account. system: :class:`bool` Specifies if the user is a system user (i.e. represents Discord officially). + nameplate: Optional[:class:`Nameplate`] + The user's nameplate, if the user has one. + + .. versionadded:: 2.7 """ __slots__ = ("_stored",) From 318b70c466d9a0ff74dfd4e57f08ccaf0ca7baae Mon Sep 17 00:00:00 2001 From: Paillat Date: Sun, 22 Jun 2025 00:44:08 +0200 Subject: [PATCH 05/12] :memo: CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fdfdc6d896..47c79c66ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,6 +57,8 @@ These changes are available on the `master` branch, but have not yet been releas ([#2747](https://github.com/Pycord-Development/pycord/pull/2747)) - Added `discord.Interaction.created_at`. ([#2801](https://github.com/Pycord-Development/pycord/pull/2801)) +- Added `User.nameplate` property. + ([#2817](https://github.com/Pycord-Development/pycord/pull/2817)) ### Fixed From ee49b77ca67a46ab38c32cd721a547bf975c1269 Mon Sep 17 00:00:00 2001 From: Paillat Date: Sun, 22 Jun 2025 00:52:16 +0200 Subject: [PATCH 06/12] :memo: add versionadded directive for Nameplate class and NameplatePalette enum --- discord/collectibles.py | 2 ++ discord/enums.py | 5 ++++- docs/api/enums.rst | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/discord/collectibles.py b/discord/collectibles.py index 53578ddf53..0d3f16f2ba 100644 --- a/discord/collectibles.py +++ b/discord/collectibles.py @@ -36,6 +36,8 @@ class Nameplate: """ Represents a Discord [Nameplate](https://support.discord.com/hc/en-us/articles/30408457944215-Nameplates-FAQ) + .. versionadded:: 2.7 + Attributes ---------- sku_id: int diff --git a/discord/enums.py b/discord/enums.py index 99c7221feb..c083bcbb9e 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -1079,7 +1079,10 @@ class SubscriptionStatus(Enum): class NameplatePalette(Enum): - """A nameplate color palette.""" + """A nameplate color palette. + + .. versionadded:: 2.7 + """ CRIMSON = ("crimson",) BERRY = "berry" diff --git a/docs/api/enums.rst b/docs/api/enums.rst index c13300f0d0..45bf494a9c 100644 --- a/docs/api/enums.rst +++ b/docs/api/enums.rst @@ -2525,3 +2525,5 @@ of :class:`enum.Enum`. A nameplate color palette. .. versionadded:: 2.7 + + :members: From 2235deec5fc737a76be434cb59dd8f0d75c4ca2a Mon Sep 17 00:00:00 2001 From: Paillat Date: Sun, 22 Jun 2025 00:56:27 +0200 Subject: [PATCH 07/12] :memo: update Nameplate class documentation to include undocumented members --- docs/api/models.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/models.rst b/docs/api/models.rst index 8cfaaf3a17..cb3e4f9e71 100644 --- a/docs/api/models.rst +++ b/docs/api/models.rst @@ -611,4 +611,4 @@ Collectibles .. attributetable:: Nameplate .. autoclass:: Nameplate() - :members: + :undoc-members: From 4c747a508d143c69cab0513f06d6b33e1245b16a Mon Sep 17 00:00:00 2001 From: Paillat Date: Sun, 22 Jun 2025 01:02:24 +0200 Subject: [PATCH 08/12] :pencil2: Fix typo in NameplatePalette --- discord/enums.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discord/enums.py b/discord/enums.py index c083bcbb9e..a97dfce07c 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -1084,7 +1084,7 @@ class NameplatePalette(Enum): .. versionadded:: 2.7 """ - CRIMSON = ("crimson",) + CRIMSON = "crimson" BERRY = "berry" SKY = "sky" TEAL = "teal" From f2eace984bc0ba6de00d546a2e2c59b24519a9f1 Mon Sep 17 00:00:00 2001 From: Paillat Date: Sun, 22 Jun 2025 01:08:01 +0200 Subject: [PATCH 09/12] :memo: standardize nameplate color attributes to lowercase and document each color in enums --- discord/enums.py | 22 +++++++++++----------- docs/api/enums.rst | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/discord/enums.py b/discord/enums.py index a97dfce07c..0ceefcc441 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -1084,17 +1084,17 @@ class NameplatePalette(Enum): .. versionadded:: 2.7 """ - CRIMSON = "crimson" - BERRY = "berry" - SKY = "sky" - TEAL = "teal" - FOREST = "forest" - BUBBLE_GUM = "bubble_gum" - VIOLET = "violet" - COBALT = "cobalt" - CLOVER = "clover" - LEMON = "lemon" - WHITE = "white" + crimson = "crimson" + berry = "berry" + sky = "sky" + teal = "teal" + forest = "forest" + bubble_gum = "bubble_gum" + violet = "violet" + cobalt = "cobalt" + clover = "clover" + lemon = "lemon" + white = "white" T = TypeVar("T") diff --git a/docs/api/enums.rst b/docs/api/enums.rst index 45bf494a9c..8527f47c8b 100644 --- a/docs/api/enums.rst +++ b/docs/api/enums.rst @@ -2526,4 +2526,46 @@ of :class:`enum.Enum`. .. versionadded:: 2.7 - :members: + .. attribute:: crimson + + Crimson nameplate color palette. + + .. attribute:: berry + + Berry nameplate color palette. + + .. attribute:: sky + + Sky nameplate color palette. + + .. attribute:: teal + + Teal nameplate color palette. + + .. attribute:: forest + + Forest nameplate color palette. + + .. attribute:: bubble_gum + + Bubble_gum nameplate color palette. + + .. attribute:: violet + + Violet nameplate color palette. + + .. attribute:: cobalt + + Cobalt nameplate color palette. + + .. attribute:: clover + + Clover nameplate color palette. + + .. attribute:: lemon + + Lemon nameplate color palette. + + .. attribute:: white + + White nameplate color palette. From 6725ef3d15814ae163a36163f959dc7097472444 Mon Sep 17 00:00:00 2001 From: Paillat Date: Sun, 22 Jun 2025 01:11:43 +0200 Subject: [PATCH 10/12] :memo: refine Nameplate class docstring for clarity --- discord/collectibles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discord/collectibles.py b/discord/collectibles.py index 0d3f16f2ba..43de0eb9b1 100644 --- a/discord/collectibles.py +++ b/discord/collectibles.py @@ -34,7 +34,7 @@ class Nameplate: """ - Represents a Discord [Nameplate](https://support.discord.com/hc/en-us/articles/30408457944215-Nameplates-FAQ) + Represents a Discord Nameplate. .. versionadded:: 2.7 From e7685c9fabab6ef5d25151884cd8e6c1f4cadcb9 Mon Sep 17 00:00:00 2001 From: Paillat Date: Sun, 22 Jun 2025 13:33:56 +0200 Subject: [PATCH 11/12] Update discord/collectibles.py Signed-off-by: Paillat --- discord/collectibles.py | 1 - 1 file changed, 1 deletion(-) diff --git a/discord/collectibles.py b/discord/collectibles.py index 43de0eb9b1..925b604688 100644 --- a/discord/collectibles.py +++ b/discord/collectibles.py @@ -74,4 +74,3 @@ def get_asset(self, animated: bool = False) -> Asset: __all__ = ("Nameplate", "NameplatePalette") -"""https://cdn.discordapp.com/assets/collectibles/nameplates/nameplates/twilight/asset.webm""" From 3a8ddce1a34864ea5caaacd771fa077bd446a9ab Mon Sep 17 00:00:00 2001 From: Paillat Date: Sat, 2 Aug 2025 17:56:11 +0200 Subject: [PATCH 12/12] :recycle: remove NameplatePalette enum and change palette type to str --- discord/collectibles.py | 7 +++-- discord/enums.py | 19 ------------- discord/types/collectibles.py | 3 +-- docs/api/enums.rst | 50 ----------------------------------- 4 files changed, 4 insertions(+), 75 deletions(-) diff --git a/discord/collectibles.py b/discord/collectibles.py index 925b604688..4ae489621a 100644 --- a/discord/collectibles.py +++ b/discord/collectibles.py @@ -28,7 +28,6 @@ from .state import ConnectionState from .asset import Asset -from .enums import NameplatePalette from .types.collectibles import Nameplate as NameplatePayload @@ -42,13 +41,13 @@ class Nameplate: ---------- sku_id: int The SKU ID of the nameplate. - palette: NameplatePalette + palette: str The color palette of the nameplate. """ def __init__(self, data: NameplatePayload, state: "ConnectionState") -> None: self.sku_id: int = data["sku_id"] - self.palette: NameplatePalette = data["palette"] + self.palette: str = data["palette"] self._label: str = data["label"] self._asset: str = data["asset"] self._state: "ConnectionState" = state @@ -73,4 +72,4 @@ def get_asset(self, animated: bool = False) -> Asset: ) -__all__ = ("Nameplate", "NameplatePalette") +__all__ = ("Nameplate",) diff --git a/discord/enums.py b/discord/enums.py index 0ceefcc441..01d10275c8 100644 --- a/discord/enums.py +++ b/discord/enums.py @@ -1078,25 +1078,6 @@ class SubscriptionStatus(Enum): inactive = 2 -class NameplatePalette(Enum): - """A nameplate color palette. - - .. versionadded:: 2.7 - """ - - crimson = "crimson" - berry = "berry" - sky = "sky" - teal = "teal" - forest = "forest" - bubble_gum = "bubble_gum" - violet = "violet" - cobalt = "cobalt" - clover = "clover" - lemon = "lemon" - white = "white" - - T = TypeVar("T") diff --git a/discord/types/collectibles.py b/discord/types/collectibles.py index d284776917..ae035b0ec9 100644 --- a/discord/types/collectibles.py +++ b/discord/types/collectibles.py @@ -26,7 +26,6 @@ from typing import TypedDict -from ..enums import NameplatePalette from .snowflake import Snowflake @@ -34,4 +33,4 @@ class Nameplate(TypedDict): sku_id: Snowflake asset: str label: str - palette: NameplatePalette + palette: str diff --git a/docs/api/enums.rst b/docs/api/enums.rst index 8527f47c8b..4d278e3758 100644 --- a/docs/api/enums.rst +++ b/docs/api/enums.rst @@ -2519,53 +2519,3 @@ of :class:`enum.Enum`. .. attribute:: inactive The subscription is inactive and the subscription owner is not being charged. - -.. class:: NameplatePalette - - A nameplate color palette. - - .. versionadded:: 2.7 - - .. attribute:: crimson - - Crimson nameplate color palette. - - .. attribute:: berry - - Berry nameplate color palette. - - .. attribute:: sky - - Sky nameplate color palette. - - .. attribute:: teal - - Teal nameplate color palette. - - .. attribute:: forest - - Forest nameplate color palette. - - .. attribute:: bubble_gum - - Bubble_gum nameplate color palette. - - .. attribute:: violet - - Violet nameplate color palette. - - .. attribute:: cobalt - - Cobalt nameplate color palette. - - .. attribute:: clover - - Clover nameplate color palette. - - .. attribute:: lemon - - Lemon nameplate color palette. - - .. attribute:: white - - White nameplate color palette.