Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 67 additions & 12 deletions packages/discord.js/src/structures/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,18 +141,22 @@ class User extends Base {
* @property {string} asset The avatar decoration hash
* @property {Snowflake} skuId The id of the avatar decoration's SKU
*/

if (data.avatar_decoration_data) {
/**
* The user avatar decoration's data
* @type {?AvatarDecorationData}
*/
this.avatarDecorationData = {
asset: data.avatar_decoration_data.asset,
skuId: data.avatar_decoration_data.sku_id,
};
if ('avatar_decoration_data' in data) {
if (data.avatar_decoration_data) {
/**
* The user avatar decoration's data
*
* @type {?AvatarDecorationData}
*/
this.avatarDecorationData = {
asset: data.avatar_decoration_data.asset,
skuId: data.avatar_decoration_data.sku_id,
};
} else {
this.avatarDecorationData = null;
}
} else {
this.avatarDecorationData = null;
this.avatarDecorationData ??= null;
}

/**
Expand All @@ -178,6 +182,34 @@ class User extends Base {
} else {
this.collectibles = null;
}

/**
* @typedef {Object} UserPrimaryGuild
* @property {?Snowflake} identityGuildId The id of the user's primary guild
* @property {?boolean} identityEnabled Whether the user is displaying the primary guild's tag
* @property {?string} tag The user's guild tag. Limited to 4 characters
* @property {?string} badge The guild tag badge hash
*/

if ('primary_guild' in data) {
if (data.primary_guild) {
/**
* The primary guild of the user
*
* @type {?UserPrimaryGuild}
*/
this.primaryGuild = {
identityGuildId: data.primary_guild.identity_guild_id,
identityEnabled: data.primary_guild.identity_enabled,
tag: data.primary_guild.tag,
badge: data.primary_guild.badge,
};
} else {
this.primaryGuild = null;
}
} else {
this.primaryGuild ??= null;
}
}

/**
Expand Down Expand Up @@ -269,6 +301,18 @@ class User extends Base {
return this.banner && this.client.rest.cdn.banner(this.id, this.banner, options);
}

/**
* A link to the user's guild tag badge.
*
* @param {ImageURLOptions} [options={}] Options for the image URL
* @returns {?string}
*/
guildTagBadgeURL(options = {}) {
return this.primaryGuild?.badge
? this.client.rest.cdn.guildTagBadge(this.primaryGuild.identityGuildId, this.primaryGuild.badge, options)
: null;
}

/**
* The tag of this user
* <info>This user's username, or their legacy tag (e.g. `hydrabolt#0001`)
Expand Down Expand Up @@ -343,7 +387,11 @@ class User extends Base {
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
this.collectibles?.nameplate?.palette === user.collectibles?.nameplate?.palette &&
this.primaryGuild?.identityGuildId === user.primaryGuild?.identityGuildId &&
this.primaryGuild?.identityEnabled === user.primaryGuild?.identityEnabled &&
this.primaryGuild?.tag === user.primaryGuild?.tag &&
this.primaryGuild?.badge === user.primaryGuild?.badge
);
}

Expand Down Expand Up @@ -374,6 +422,12 @@ class User extends Base {
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) &&
('primary_guild' in user
? this.primaryGuild?.identityGuildId === user.primary_guild?.identity_guild_id &&
this.primaryGuild?.identityEnabled === user.primary_guild?.identity_enabled &&
this.primaryGuild?.tag === user.primary_guild?.tag &&
this.primaryGuild?.badge === user.primary_guild?.badge
: true)
);
}
Expand Down Expand Up @@ -423,6 +477,7 @@ class User extends Base {
json.avatarURL = this.avatarURL();
json.displayAvatarURL = this.displayAvatarURL();
json.bannerURL = this.banner ? this.bannerURL() : this.banner;
json.guildTagBadgeURL = this.guildTagBadgeURL();
return json;
}
}
Expand Down
17 changes: 13 additions & 4 deletions packages/discord.js/typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3803,17 +3803,24 @@ export interface AvatarDecorationData {
skuId: Snowflake;
}

export interface Collectibles {
nameplate: NameplateData | null;
}

export interface UserPrimaryGuild {
badge: string | null;
identityEnabled: boolean | null;
identityGuildId: Snowflake | null;
tag: string | null;
}

export interface NameplateData {
asset: string;
label: string;
palette: NameplatePalette;
skuId: Snowflake;
}

export interface Collectibles {
nameplate: NameplateData | null;
}

export interface UnfurledMediaItemData {
url: string;
}
Expand Down Expand Up @@ -3849,12 +3856,14 @@ export class User extends Base {
public get hexAccentColor(): HexColorString | null | undefined;
public id: Snowflake;
public get partial(): false;
public primaryGuild: UserPrimaryGuild | null;
public system: boolean;
public get tag(): string;
public username: string;
public avatarURL(options?: ImageURLOptions): string | null;
public avatarDecorationURL(options?: BaseImageURLOptions): string | null;
public bannerURL(options?: ImageURLOptions): string | null | undefined;
public guildTagBadgeURL(options?: ImageURLOptions): string | null;
public createDM(force?: boolean): Promise<DMChannel>;
public deleteDM(): Promise<DMChannel>;
public displayAvatarURL(options?: ImageURLOptions): string;
Expand Down
4 changes: 4 additions & 0 deletions packages/rest/__tests__/CDN.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ test('soundboardSound', () => {
expect(cdn.soundboardSound(id)).toEqual(`${baseCDN}/soundboard-sounds/${id}`);
});

test('guildTagBadge', () => {
expect(cdn.guildTagBadge(id, hash)).toEqual(`${baseCDN}/guild-tag-badges/${id}/${hash}.webp`);
});

test('makeURL throws on invalid size', () => {
expect(() => cdn.avatar(id, animatedHash, { size: 5 })).toThrow(RangeError);
});
Expand Down
11 changes: 11 additions & 0 deletions packages/rest/src/lib/CDN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,17 @@ export class CDN {
return `${this.cdn}${CDNRoutes.soundboardSound(soundId)}`;
}

/**
* Generates a URL for a guild tag badge.
*
* @param guildId - The guild id
* @param badgeHash - The hash of the badge
* @param options - Optional options for the badge
*/
public guildTagBadge(guildId: string, badgeHash: string, options?: Readonly<BaseImageURLOptions>): string {
return this.makeURL(`/guild-tag-badges/${guildId}/${badgeHash}`, options);
}

/**
* Constructs the URL for the resource, checking whether or not `hash` starts with `a_` if `dynamic` is set to `true`.
*
Expand Down