Skip to content
Open
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
17 changes: 17 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,7 @@ declare namespace Eris {
interface OldMember {
avatar: string | null;
avatarDecorationData?: AvatarDecorationData | null;
collectibles?: UserCollectibles | null;
communicationDisabledUntil?: number | null;
flags?: number;
nick: string | null;
Expand Down Expand Up @@ -1478,6 +1479,7 @@ declare namespace Eris {
avatar: string | null;
avatarDecorationData?: AvatarDecorationData | null;
banner?: string | null;
collectibles?: UserCollectibles | null;
discriminator: string;
id: string;
username: string;
Expand All @@ -1493,6 +1495,15 @@ declare namespace Eris {
guildIDs: string[];
timeout?: number;
}
interface UserCollectibles {
nameplate?: UserCollectiblesNameplate;
}
interface UserCollectiblesNameplate {
sku_id: number;
palette: string;
label: string;
asset: string;
}

// Message
interface ActionRow {
Expand Down Expand Up @@ -3070,6 +3081,7 @@ declare namespace Eris {
export class Member extends Base implements Presence {
accentColor?: number | null;
activities?: Activity[];
animatedNameplateURL: string | null;
avatar: string | null;
avatarDecorationData?: AvatarDecorationData | null;
avatarDecorationURL: string | null;
Expand All @@ -3078,6 +3090,7 @@ declare namespace Eris {
bannerURL: string | null;
bot: boolean;
clientStatus?: ClientStatus;
collectibles?: UserCollectibles | null;
communicationDisabledUntil?: number | null;
createdAt: number;
defaultAvatar: string;
Expand All @@ -3098,6 +3111,7 @@ declare namespace Eris {
premiumSince?: number | null;
roles: string[];
staticAvatarURL: string;
staticNameplateURL: string | null;
status?: UserStatus;
user: User;
username: string;
Expand Down Expand Up @@ -3508,13 +3522,15 @@ declare namespace Eris {

export class User extends Base {
accentColor?: number | null;
animatedNameplateURL: string | null;
avatar: string | null;
avatarDecorationData?: AvatarDecorationData | null;
avatarDecorationURL: string | null;
avatarURL: string;
banner?: string | null;
bannerURL: string | null;
bot: boolean;
collectibles?: UserCollectibles | null;
createdAt: number;
defaultAvatar: string;
defaultAvatarURL: string;
Expand All @@ -3524,6 +3540,7 @@ declare namespace Eris {
mention: string;
publicFlags?: number;
staticAvatarURL: string;
staticNameplateURL: string | null;
system: boolean;
username: string;
constructor(data: BaseData, client: Client);
Expand Down
1 change: 1 addition & 0 deletions lib/Constants.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ export default interface Constants {
"jpeg",
"png",
"webp",
"webm",
"gif",
];
ImageSizeBoundaries: {
Expand Down
1 change: 1 addition & 0 deletions lib/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ module.exports.ImageFormats = [
"jpeg",
"png",
"webp",
"webm",
"gif",
];

Expand Down
8 changes: 6 additions & 2 deletions lib/gateway/Shard.js
Original file line number Diff line number Diff line change
Expand Up @@ -697,13 +697,14 @@ class Shard extends EventEmitter {
if (packet.d.user.username !== undefined) {
let user = this.client.users.get(packet.d.user.id);
let oldUser = null;
if (user && (user.username !== packet.d.user.username || user.globalName !== packet.d.user.global_name || user.discriminator !== packet.d.user.discriminator || user.avatar !== packet.d.user.avatar || (packet.d.user.avatar_decoration_data && user.avatarDecorationData && user.avatarDecorationData.asset !== packet.d.user.avatar_decoration_data.asset))) {
if (user && (user.username !== packet.d.user.username || user.globalName !== packet.d.user.global_name || user.discriminator !== packet.d.user.discriminator || user.avatar !== packet.d.user.avatar || (packet.d.user.avatar_decoration_data && user.avatarDecorationData && user.avatarDecorationData.asset !== packet.d.user.avatar_decoration_data.asset) || (packet.d.user.collectibles && packet.d.user.collectibles.nameplate && user.collectibles && user.collectibles.nameplate && user.collectibles.nameplate.sku_id !== packet.d.user.collectibles.nameplate.sku_id))) {
oldUser = {
username: user.username,
globalName: user.globalName,
discriminator: user.discriminator,
avatar: user.avatar,
avatarDecorationData: user.avatarDecorationData,
collectibles: user.collectibles,
};
}
if (!user || oldUser) {
Expand All @@ -715,6 +716,7 @@ class Shard extends EventEmitter {
* @prop {Object?} oldUser The old user data. If the user was uncached, this will be null
* @prop {String?} oldUser.avatar The hash of the user's avatar, or null if no avatar
* @prop {Object?} oldUser.avatarDecorationData The data of the user's avatar decoration, including the asset and sku ID, or null if no avatar decoration
* @prop {Object?} oldUser.collectibles The data for the user's collectibles, including their nameplate, or null if no collectibles. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/user#collectibles) for object structure
* @prop {String} oldUser.discriminator The discriminator of the user
* @prop {String?} oldUser.globalName The user's display name, if it is set. For bots, this is the application name
* @prop {String} oldUser.username The username of the user
Expand Down Expand Up @@ -1330,13 +1332,14 @@ class Shard extends EventEmitter {
if (!(this.client.options.intents & Constants.Intents.guildPresences) && packet.d.user.username !== undefined) {
let user = this.client.users.get(packet.d.user.id);
let oldUser = null;
if (user && (user.username !== packet.d.user.username || user.globalName !== packet.d.user.global_name || user.discriminator !== packet.d.user.discriminator || user.avatar !== packet.d.user.avatar || (packet.d.user.avatar_decoration_data && user.avatarDecorationData && user.avatarDecorationData.asset !== packet.d.user.avatar_decoration_data.asset))) {
if (user && (user.username !== packet.d.user.username || user.globalName !== packet.d.user.global_name || user.discriminator !== packet.d.user.discriminator || user.avatar !== packet.d.user.avatar || (packet.d.user.avatar_decoration_data && user.avatarDecorationData && user.avatarDecorationData.asset !== packet.d.user.avatar_decoration_data.asset) || (packet.d.user.collectibles && packet.d.user.collectibles.nameplate && user.collectibles && user.collectibles.nameplate && user.collectibles.nameplate.sku_id !== packet.d.user.collectibles.nameplate.sku_id))) {
oldUser = {
username: user.username,
globalName: user.globalName,
discriminator: user.discriminator,
avatar: user.avatar,
avatarDecorationData: user.avatarDecorationData,
collectibles: user.collectibles,
};
}
if (!user || oldUser) {
Expand Down Expand Up @@ -2013,6 +2016,7 @@ class Shard extends EventEmitter {
discriminator: user.discriminator,
avatar: user.avatar,
avatarDecorationData: user.avatarDecorationData,
collectibles: user.collectibles,
};
}
user = this.client.users.update(packet.d, this.client);
Expand Down
1 change: 1 addition & 0 deletions lib/rest/Endpoints.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions lib/structures/Member.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const VoiceState = require("./VoiceState");
* Represents a server member
* @prop {Number?} accentColor The user's banner color, or null if no banner color (REST only)
* @prop {Array<Object>?} activities The member's current activities
* @prop {String?} animatedNameplateURL The URL of the user's nameplate asset (always a WEBM)
* @prop {String?} avatar The hash of the member's guild avatar, or null if no guild avatar
* @prop {Object?} avatarDecorationData The data of the user's avatar decoration, including the asset and sku ID, or null if no avatar decoration
* @prop {String?} avatarDecorationURL The URL of the user's avatar decoration
Expand All @@ -21,6 +22,7 @@ const VoiceState = require("./VoiceState");
* @prop {String} clientStatus.desktop The member's status on desktop. Either "online", "idle", "dnd", or "offline". Will be "offline" for bots
* @prop {String} clientStatus.mobile The member's status on mobile. Either "online", "idle", "dnd", or "offline". Will be "offline" for bots
* @prop {String} clientStatus.web The member's status on web. Either "online", "idle", "dnd", or "offline". Will be "online" for bots
* @prop {Object?} collectibles The data for the user's collectibles, including their nameplate, or null if no collectibles. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/user#collectibles) for object structure
* @prop {Number?} communicationDisabledUntil Timestamp of timeout expiry. If `null`, the member is not timed out
* @prop {Number} createdAt Timestamp of user creation
* @prop {String} defaultAvatar The hash for the default avatar of a user if there is no avatar set
Expand All @@ -43,6 +45,7 @@ const VoiceState = require("./VoiceState");
* @prop {Number?} premiumSince Timestamp of when the member boosted the guild
* @prop {Array<String>} roles An array of role IDs this member is a part of
* @prop {String} staticAvatarURL The URL of the user's avatar (always a JPG)
* @prop {String?} staticNameplateURL The static URL of the user's nameplate asset (always a PNG)
* @prop {String} status The member's status. Either "online", "idle", "dnd", or "offline"
* @prop {User} user The user object of the member
* @prop {String} username The username of the user
Expand Down Expand Up @@ -138,6 +141,10 @@ class Member extends Base {
return this.user.accentColor;
}

get animatedNameplateURL() {
return this.user.animatedNameplateURL;
}

get avatarDecorationData() {
return this.user.avatarDecorationData;
}
Expand All @@ -162,6 +169,10 @@ class Member extends Base {
return this.user.bot;
}

get collectibles() {
return this.user.collectibles;
}

get createdAt() {
return this.user.createdAt;
}
Expand Down Expand Up @@ -200,6 +211,10 @@ class Member extends Base {
return this.user.staticAvatarURL;
}

get staticNameplateURL() {
return this.user.staticNameplateURL;
}

get username() {
return this.user.username;
}
Expand Down
27 changes: 27 additions & 0 deletions lib/structures/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ const Endpoints = require("../rest/Endpoints");
/**
* Represents a user
* @prop {Number?} accentColor The user's banner color, or null if no banner color (REST only)
* @prop {String?} animatedNameplateURL The URL of the user's nameplate asset (always a WEBM)
* @prop {String?} avatar The hash of the user's avatar, or null if no avatar
* @prop {Object?} avatarDecorationData The data of the user's avatar decoration, including the asset and sku ID, or null if no avatar decoration
* @prop {String?} avatarDecorationURL The URL of the user's avatar decoration
* @prop {String} avatarURL The URL of the user's avatar which can be either a JPG or GIF
* @prop {String?} banner The hash of the user's banner, or null if no banner (REST only)
* @prop {String?} bannerURL The URL of the user's banner
* @prop {Boolean} bot Whether the user is an OAuth bot or not
* @prop {Object?} collectibles The data for the user's collectibles, including their nameplate, or null if no collectibles. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/user#collectibles) for object structure
* @prop {Number} createdAt Timestamp of the user's creation
* @prop {String} defaultAvatar The hash for the default avatar of a user if there is no avatar set
* @prop {String} defaultAvatarURL The URL of the user's default avatar
Expand All @@ -22,6 +24,7 @@ const Endpoints = require("../rest/Endpoints");
* @prop {String} mention A string that mentions the user
* @prop {Number?} publicFlags Publicly visible flags for this user
* @prop {String} staticAvatarURL The URL of the user's avatar (always a JPG)
* @prop {String?} staticNameplateURL The static URL of the user's nameplate asset (always a PNG)
* @prop {Boolean} system Whether the user is an official Discord system user (e.g. urgent messages)
* @prop {String} username The username of the user
*/
Expand Down Expand Up @@ -62,6 +65,19 @@ class User extends Base {
if (data.avatar_decoration_data !== undefined) {
this.avatarDecorationData = data.avatar_decoration_data;
}
if (data.collectibles !== undefined) {
this.collectibles = data.collectibles;
}
}

get animatedNameplateURL() {
if (!this.collectibles || !this.collectibles.nameplate) {
return null;
}
if (this._missingClientError) {
throw this._missingClientError;
}
return this._client._formatImage(Endpoints.USER_NAMEPLATE(this.collectibles.nameplate.asset), "webm");
}

get avatarDecorationURL() {
Expand Down Expand Up @@ -110,6 +126,16 @@ class User extends Base {
return this.avatar ? this._client._formatImage(Endpoints.USER_AVATAR(this.id, this.avatar), "jpg") : this.defaultAvatarURL;
}

get staticNameplateURL() {
if (!this.collectibles || !this.collectibles.nameplate) {
return null;
}
if (this._missingClientError) {
throw this._missingClientError;
}
return this._client._formatImage(Endpoints.USER_NAMEPLATE(this.collectibles.nameplate.asset, true), "png");
}

/**
* Get the user's avatar with the given format and size
* @arg {String} [format] The filetype of the avatar ("jpg", "jpeg", "png", "gif", or "webp")
Expand Down Expand Up @@ -157,6 +183,7 @@ class User extends Base {
"avatarDecorationData",
"banner",
"bot",
"collectibles",
"discriminator",
"globalName",
"publicFlags",
Expand Down