diff --git a/src/structures/User.js b/src/structures/User.js index b7731e69a8f2..4af93f5f2f1a 100644 --- a/src/structures/User.js +++ b/src/structures/User.js @@ -75,6 +75,28 @@ class User extends Base { this.avatar = null; } + if ('banner' in data) { + /** + * The user banner's hash + * The user must be force fetched for this property to be present + * @type {?string} + */ + this.banner = data.banner; + } else if (typeof this.banner !== 'string') { + this.banner = null; + } + + if ('accent_color' in data) { + /** + * The base 10 accent color of the user's banner + * The user must be force fetched for this property to be present + * @type {?number} + */ + this.accentColor = data.accent_color; + } else if (typeof this.accentColor === 'undefined') { + this.accentColor = null; + } + if ('system' in data) { /** * Whether the user is an Official Discord System user (part of the urgent message system) @@ -150,6 +172,28 @@ class User extends Base { return this.avatarURL(options) ?? this.defaultAvatarURL; } + /** + * The hexadecimal version of the user accent color, with a leading hash + * The user must be force fetched for this property to be present + * @type {?string} + * @readonly + */ + get hexAccentColor() { + if (!this.accentColor) return null; + return `#${this.accentColor.toString(16).padStart(6, '0')}`; + } + + /** + * A link to the user's banner. + * The user must be force fetched for this property to be present + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} + */ + bannerURL({ format, size, dynamic } = {}) { + if (!this.banner) return null; + return this.client.rest.cdn.Banner(this.id, this.banner, format, size, dynamic); + } + /** * The Discord "tag" (e.g. `hydrabolt#0001`) for this user * @type {?string} @@ -200,7 +244,8 @@ class User extends Base { } /** - * Checks if the user is equal to another. It compares id, username, discriminator, avatar, and bot flags. + * Checks if the user is equal to another. + * It compares id, username, discriminator, avatar, banner, accent color, and bot flags. * It is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties. * @param {User} user User to compare with * @returns {boolean} @@ -211,7 +256,9 @@ class User extends Base { this.id === user.id && this.username === user.username && this.discriminator === user.discriminator && - this.avatar === user.avatar; + this.avatar === user.avatar && + this.banner === user.banner && + this.accentColor === user.accentColor; return equal; } @@ -253,12 +300,14 @@ class User extends Base { { createdTimestamp: true, defaultAvatarURL: true, + hexAccentColor: true, tag: true, }, ...props, ); json.avatarURL = this.avatarURL(); json.displayAvatarURL = this.displayAvatarURL(); + json.bannerURL = this.bannerURL(); return json; } diff --git a/src/util/Constants.js b/src/util/Constants.js index dd6f5136c9fd..cb7d7abd739e 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -49,8 +49,10 @@ exports.Endpoints = { if (dynamic) format = hash.startsWith('a_') ? 'gif' : format; return makeImageUrl(`${root}/avatars/${userId}/${hash}`, { format, size }); }, - Banner: (guildId, hash, format = 'webp', size) => - makeImageUrl(`${root}/banners/${guildId}/${hash}`, { format, size }), + Banner: (id, hash, format = 'webp', size, dynamic = false) => { + if (dynamic) format = hash.startsWith('a_') ? 'gif' : format; + return makeImageUrl(`${root}/banners/${id}/${hash}`, { format, size }); + }, Icon: (guildId, hash, format = 'webp', size, dynamic = false) => { if (dynamic) format = hash.startsWith('a_') ? 'gif' : format; return makeImageUrl(`${root}/icons/${guildId}/${hash}`, { format, size }); diff --git a/typings/index.d.ts b/typings/index.d.ts index 6155282bee79..9a55e9ff4071 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1823,7 +1823,9 @@ export class Typing extends Base { export class User extends PartialTextBasedChannel(Base) { public constructor(client: Client, data: RawUserData); + public accentColor: number | null; public avatar: string | null; + public banner: string | null; public bot: boolean; public readonly createdAt: Date; public readonly createdTimestamp: number; @@ -1831,12 +1833,14 @@ export class User extends PartialTextBasedChannel(Base) { public readonly defaultAvatarURL: string; public readonly dmChannel: DMChannel | null; public flags: Readonly | null; + public readonly hexAccentColor: HexColorString | null; public id: Snowflake; public readonly partial: false; public system: boolean; public readonly tag: string; public username: string; public avatarURL(options?: ImageURLOptions): string | null; + public bannerURL(options?: ImageURLOptions): string | null; public createDM(): Promise; public deleteDM(): Promise; public displayAvatarURL(options?: ImageURLOptions): string; @@ -2151,7 +2155,13 @@ export const Constants: { size: AllowedImageSize, dynamic: boolean, ) => string; - Banner: (guildId: Snowflake, hash: string, format: AllowedImageFormat, size: AllowedImageSize) => string; + Banner: ( + id: Snowflake, + hash: string, + format: DynamicImageFormat, + size: AllowedImageSize, + dynamic: boolean, + ) => string; Icon: ( guildId: Snowflake, hash: string,