From 8ac0e1e5d6df9c51fd3a41d9f8c9dbe8f786229a Mon Sep 17 00:00:00 2001 From: Danial Raza Date: Tue, 15 Jul 2025 01:35:00 +0200 Subject: [PATCH] feat(User): add `collectibles` (#10939) * feat(User): add `collectibles` * docs: nullable collectibles and nameplate data Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com> --------- Co-Authored-By: Jiralite <33201955+Jiralite@users.noreply.github.com> --- packages/discord.js/src/structures/User.js | 37 +++++++++++++++++++- packages/discord.js/src/util/APITypes.js | 5 +++ packages/discord.js/src/util/Transformers.js | 21 +++++++++++ packages/discord.js/typings/index.d.ts | 13 +++++++ 4 files changed, 75 insertions(+), 1 deletion(-) diff --git a/packages/discord.js/src/structures/User.js b/packages/discord.js/src/structures/User.js index 6c9849589..0ded5cf47 100644 --- a/packages/discord.js/src/structures/User.js +++ b/packages/discord.js/src/structures/User.js @@ -5,6 +5,7 @@ const { calculateUserDefaultAvatarIndex } = require('@discordjs/rest'); const { DiscordSnowflake } = require('@sapphire/snowflake'); const Base = require('./Base'); const TextBasedChannel = require('./interfaces/TextBasedChannel'); +const { _transformCollectibles } = require('../util/Transformers.js'); const UserFlagsBitField = require('../util/UserFlagsBitField'); const { emitDeprecationWarningForUserFetchFlags } = require('../util/Util'); @@ -153,6 +154,30 @@ class User extends Base { } else { this.avatarDecorationData = null; } + + /** + * @typedef {Object} NameplateData + * @property {Snowflake} skuId The id of the nameplate's SKU + * @property {string} asset The nameplate's asset path + * @property {string} label The nameplate's label + * @property {NameplatePalette} palette Background color of the nameplate + */ + + /** + * @typedef {Object} Collectibles + * @property {?NameplateData} nameplate The user's nameplate data + */ + + if (data.collectibles) { + /** + * The user's collectibles + * + * @type {?Collectibles} + */ + this.collectibles = _transformCollectibles(data.collectibles); + } else { + this.collectibles = null; + } } /** @@ -314,7 +339,11 @@ class User extends Base { this.accentColor === user.accentColor && this.avatarDecoration === user.avatarDecoration && this.avatarDecorationData?.asset === user.avatarDecorationData?.asset && - this.avatarDecorationData?.skuId === user.avatarDecorationData?.skuId + this.avatarDecorationData?.skuId === user.avatarDecorationData?.skuId && + this.collectibles?.nameplate?.skuId === user.collectibles?.nameplate?.skuId && + this.collectibles?.nameplate?.asset === user.collectibles?.nameplate?.asset && + this.collectibles?.nameplate?.label === user.collectibles?.nameplate?.label && + this.collectibles?.nameplate?.palette === user.collectibles?.nameplate?.palette ); } @@ -339,6 +368,12 @@ class User extends Base { ('avatar_decoration_data' in user ? this.avatarDecorationData?.asset === user.avatar_decoration_data?.asset && this.avatarDecorationData?.skuId === user.avatar_decoration_data?.sku_id + : true) && + ('collectibles' in user + ? this.collectibles?.nameplate?.skuId === user.collectibles?.nameplate?.sku_id && + this.collectibles?.nameplate?.asset === user.collectibles?.nameplate?.asset && + this.collectibles?.nameplate?.label === user.collectibles?.nameplate?.label && + this.collectibles?.nameplate?.palette === user.collectibles?.nameplate?.palette : true) ); } diff --git a/packages/discord.js/src/util/APITypes.js b/packages/discord.js/src/util/APITypes.js index b20dc26f9..70520cebc 100644 --- a/packages/discord.js/src/util/APITypes.js +++ b/packages/discord.js/src/util/APITypes.js @@ -550,6 +550,11 @@ * @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/MessageFlags} */ +/** + * @external NameplatePalette + * @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/NameplatePalette} + */ + /** * @external OAuth2Scopes * @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/OAuth2Scopes} diff --git a/packages/discord.js/src/util/Transformers.js b/packages/discord.js/src/util/Transformers.js index 4b47e18e1..d875ae19d 100644 --- a/packages/discord.js/src/util/Transformers.js +++ b/packages/discord.js/src/util/Transformers.js @@ -95,10 +95,31 @@ function _transformAPIIncidentsData(data) { }; } +/** + * Transforms a collectibles object to a camel-cased variant. + * + * @param {APICollectibles} collectibles The collectibles to transform + * @returns {Collectibles} + * @ignore + */ +function _transformCollectibles(collectibles) { + if (!collectibles.nameplate) return { nameplate: null }; + + return { + nameplate: { + skuId: collectibles.nameplate.sku_id, + asset: collectibles.nameplate.asset, + label: collectibles.nameplate.label, + palette: collectibles.nameplate.palette, + }, + }; +} + module.exports = { toSnakeCase, _transformAPIAutoModerationAction, _transformAPIMessageInteractionMetadata, _transformGuildScheduledEventRecurrenceRule, _transformAPIIncidentsData, + _transformCollectibles, }; diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index a306b4dbc..9b6dbd900 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -80,6 +80,7 @@ import { InteractionType, InviteTargetType, MessageType, + NameplatePalette, OAuth2Scopes, RESTPostAPIApplicationCommandsJSONBody, Snowflake, @@ -3794,6 +3795,17 @@ export interface AvatarDecorationData { skuId: Snowflake; } +export interface NameplateData { + asset: string; + label: string; + palette: NameplatePalette; + skuId: Snowflake; +} + +export interface Collectibles { + nameplate: NameplateData | null; +} + export interface UnfurledMediaItemData { url: string; } @@ -3819,6 +3831,7 @@ export class User extends Base { public bot: boolean; public get createdAt(): Date; public get createdTimestamp(): number; + public collectibles: Collectibles | null; public discriminator: string; public get displayName(): string; public get defaultAvatarURL(): string;