From 998cddc9771ab638fa21cfceef6a216ed7435727 Mon Sep 17 00:00:00 2001 From: AAGaming Date: Sat, 21 May 2022 14:57:50 -0400 Subject: [PATCH] backport #5696 --- src/structures/GuildMember.js | 34 +++++++++++++++++++++++++++++++++- src/util/Constants.js | 6 +++++- typings/index.d.ts | 4 ++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js index 1bd0dfd1dc09..930488a0a984 100644 --- a/src/structures/GuildMember.js +++ b/src/structures/GuildMember.js @@ -78,6 +78,15 @@ class GuildMember extends Base { } if ('nick' in data) this.nickname = data.nick; + if ('avatar' in data) { + /** + * The guild member's avatar hash + * @type {?string} + */ + this.avatar = data.avatar; + } else if (typeof this.avatar !== 'string') { + this.avatar = null; + } if ('joined_at' in data) this.joinedTimestamp = new Date(data.joined_at).getTime(); if ('premium_since' in data) this.premiumSinceTimestamp = new Date(data.premium_since).getTime(); if ('roles' in data) this._roles = data.roles; @@ -128,6 +137,26 @@ class GuildMember extends Base { return this.guild.voiceStates.cache.get(this.id) || new VoiceState(this.guild, { user_id: this.id }); } + /** + * A link to the member's guild avatar. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {?string} + */ + avatarURL({ format, size, dynamic } = {}) { + if (!this.avatar) return null; + return this.client.rest.cdn.GuildMemberAvatar(this.guild.id, this.id, this.avatar, format, size, dynamic); + } + + /** + * A link to the member's guild avatar if they have one. + * Otherwise, a link to their {@link User#displayAvatarURL} will be returned. + * @param {ImageURLOptions} [options={}] Options for the Image URL + * @returns {string} + */ + displayAvatarURL(options) { + return this.avatarURL(options) ?? this.user.displayAvatarURL(options); + } + /** * The time this member joined the guild * @type {?Date} @@ -393,7 +422,7 @@ class GuildMember extends Base { } toJSON() { - return super.toJSON({ + const json = super.toJSON({ guild: 'guildID', user: 'userID', displayName: true, @@ -402,6 +431,9 @@ class GuildMember extends Base { lastMessageID: false, roles: true, }); + json.avatarURL = this.avatarURL(); + json.displayAvatarURL = this.displayAvatarURL(); + return json; } // These are here only for documentation purposes - they are implemented by TextBasedChannel diff --git a/src/util/Constants.js b/src/util/Constants.js index 3d2d1b795f1c..01b5c0ba7cda 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -131,9 +131,13 @@ exports.Endpoints = { Asset: name => `${root}/assets/${name}`, DefaultAvatar: discriminator => `${root}/embed/avatars/${discriminator}.png`, Avatar: (userID, hash, format = 'webp', size, dynamic = false) => { - if (dynamic) format = hash.startsWith('a_') ? 'gif' : format; + if (dynamic && hash.startsWith('a_')) format = 'gif'; return makeImageUrl(`${root}/avatars/${userID}/${hash}`, { format, size }); }, + GuildMemberAvatar: (guildId, memberId, hash, format = 'webp', size, dynamic = false) => { + if (dynamic && hash.startsWith('a_')) format = 'gif'; + return makeImageUrl(`${root}/guilds/${guildId}/users/${memberId}/avatars/${hash}`, { format, size }); + }, Banner: (guildID, hash, format = 'webp', size) => makeImageUrl(`${root}/banners/${guildID}/${hash}`, { format, size }), Icon: (guildID, hash, format = 'webp', size, dynamic = false) => { diff --git a/typings/index.d.ts b/typings/index.d.ts index 0d204a9522b0..a1dd272f05dc 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -357,6 +357,7 @@ declare module 'better-discord.js' { Emoji: (emojiID: string, format: 'png' | 'gif') => string; Avatar: (userID: string | number, hash: string, format: 'default' | AllowedImageFormat, size: number) => string; Banner: (guildID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; + GuildMemberAvatar: (guildId: string | number, memberId: string | number, hash: string, format: 'default' | AllowedImageFormat, size: number) => string; Icon: (userID: string | number, hash: string, format: 'default' | AllowedImageFormat, size: number) => string; AppIcon: (userID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; AppAsset: (userID: string | number, hash: string, format: AllowedImageFormat, size: number) => string; @@ -821,6 +822,7 @@ declare module 'better-discord.js' { export class GuildMember extends PartialTextBasedChannel(Base) { constructor(client: Client, data: object, guild: Guild); + public avatar: string | null; public readonly bannable: boolean; public deleted: boolean; public readonly displayColor: number; @@ -842,10 +844,12 @@ declare module 'better-discord.js' { public readonly roles: GuildMemberRoleManager; public user: User; public readonly voice: VoiceState; + public avatarURL(options?: ImageURLOptions): string | null; public ban(options?: BanOptions): Promise; public fetch(force?: boolean): Promise; public createDM(force?: boolean): Promise; public deleteDM(): Promise; + public displayAvatarURL(options?: ImageURLOptions): string; public edit(data: GuildMemberEditData, reason?: string): Promise; public hasPermission( permission: PermissionResolvable,