Skip to content

Commit

Permalink
feat(GuildMember): add guild avatars (#5696)
Browse files Browse the repository at this point in the history
Co-authored-by: Sugden <28943913+NotSugden@users.noreply.github.com>
Co-authored-by: Shubham Parihar <shubhamparihar391@gmail.com>
Co-authored-by: GoldenAngel <50855202+GoldenAngel2@users.noreply.github.com>
  • Loading branch information
4 people committed Sep 28, 2021
1 parent 7cba676 commit dfd7b40
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 1 deletion.
35 changes: 34 additions & 1 deletion src/structures/GuildMember.js
Expand Up @@ -71,6 +71,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 = data.premium_since ? new Date(data.premium_since).getTime() : null;
Expand Down Expand Up @@ -112,6 +121,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}
Expand Down Expand Up @@ -323,6 +352,7 @@ class GuildMember extends Base {
this.guild.id === member.guild.id &&
this.joinedTimestamp === member.joinedTimestamp &&
this.nickname === member.nickname &&
this.avatar === member.avatar &&
this.pending === member.pending &&
(this._roles === member._roles ||
(this._roles.length === member._roles.length && this._roles.every((role, i) => role === member._roles[i])))
Expand All @@ -341,12 +371,15 @@ class GuildMember extends Base {
}

toJSON() {
return super.toJSON({
const json = super.toJSON({
guild: 'guildId',
user: 'userId',
displayName: true,
roles: true,
});
json.avatarURL = this.avatarURL();
json.displayAvatarURL = this.displayAvatarURL();
return json;
}

// These are here only for documentation purposes - they are implemented by TextBasedChannel
Expand Down
4 changes: 4 additions & 0 deletions src/util/Constants.js
Expand Up @@ -49,6 +49,10 @@ exports.Endpoints = {
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: (id, hash, format, size, dynamic = false) => {
if (dynamic && hash.startsWith('a_')) format = 'gif';
return makeImageUrl(`${root}/banners/${id}/${hash}`, { format, size });
Expand Down
11 changes: 11 additions & 0 deletions typings/index.d.ts
Expand Up @@ -873,6 +873,7 @@ export class GuildEmoji extends BaseGuildEmoji {

export class GuildMember extends PartialTextBasedChannel(Base) {
public constructor(client: Client, data: RawGuildMemberData, guild: Guild);
public avatar: string | null;
public readonly bannable: boolean;
public deleted: boolean;
public readonly displayColor: number;
Expand All @@ -894,10 +895,12 @@ export class GuildMember extends PartialTextBasedChannel(Base) {
public readonly roles: GuildMemberRoleManager;
public user: User;
public readonly voice: VoiceState;
public avatarURL(options?: ImageURLOptions): string | null;
public ban(options?: BanOptions): Promise<GuildMember>;
public fetch(force?: boolean): Promise<GuildMember>;
public createDM(force?: boolean): Promise<DMChannel>;
public deleteDM(): Promise<DMChannel>;
public displayAvatarURL(options?: ImageURLOptions): string;
public edit(data: GuildMemberEditData, reason?: string): Promise<GuildMember>;
public kick(reason?: string): Promise<GuildMember>;
public permissionsIn(channel: GuildChannelResolvable): Readonly<Permissions>;
Expand Down Expand Up @@ -2297,6 +2300,14 @@ export const Constants: {
size: AllowedImageSize,
dynamic: boolean,
) => string;
GuildMemberAvatar: (
guildId: Snowflake,
memberId: Snowflake,
hash: string,
format?: DynamicImageFormat,
size?: AllowedImageSize,
dynamic?: boolean,
) => string;
Icon: (
guildId: Snowflake,
hash: string,
Expand Down

0 comments on commit dfd7b40

Please sign in to comment.