Skip to content

Commit

Permalink
Add support for user banners (#1238)
Browse files Browse the repository at this point in the history
  • Loading branch information
conorwastakenwastaken authored Oct 5, 2021
1 parent daedb2b commit 558bbe5
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 15 deletions.
25 changes: 17 additions & 8 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,9 @@ declare namespace Eris {
roles: string[];
}
interface PartialUser {
accentColor?: number | null;
avatar: string | null;
banner?: string | null;
discriminator: string;
id: string;
username: string;
Expand Down Expand Up @@ -2017,7 +2019,7 @@ declare namespace Eris {
recipients: Collection<User>;
type: 3;
addRecipient(userID: string): Promise<void>;
dynamicIconURL(format?: ImageFormat, size?: number): string;
dynamicIconURL(format?: ImageFormat, size?: number): string | null;
edit(options: { icon?: string; name?: string; ownerID?: string }): Promise<GroupChannel>;
removeRecipient(userID: string): Promise<void>;
}
Expand Down Expand Up @@ -2113,10 +2115,10 @@ declare namespace Eris {
deleteIntegration(integrationID: string): Promise<void>;
deleteRole(roleID: string): Promise<void>;
deleteTemplate(code: string): Promise<GuildTemplate>;
dynamicBannerURL(format?: ImageFormat, size?: number): string;
dynamicDiscoverySplashURL(format?: ImageFormat, size?: number): string;
dynamicIconURL(format?: ImageFormat, size?: number): string;
dynamicSplashURL(format?: ImageFormat, size?: number): string;
dynamicBannerURL(format?: ImageFormat, size?: number): string | null;
dynamicDiscoverySplashURL(format?: ImageFormat, size?: number): string | null;
dynamicIconURL(format?: ImageFormat, size?: number): string | null;
dynamicSplashURL(format?: ImageFormat, size?: number): string | null;
edit(options: GuildOptions, reason?: string): Promise<Guild>;
editDiscovery(options?: DiscoveryOptions): Promise<DiscoveryMetadata>;
editEmoji(emojiID: string, options: { name: string; roles?: string[] }, reason?: string): Promise<Emoji>;
Expand Down Expand Up @@ -2252,9 +2254,9 @@ declare namespace Eris {
splash: string | null;
splashURL: string | null;
constructor(data: BaseData, client: Client);
dynamicDiscoverySplashURL(format?: ImageFormat, size?: number): string;
dynamicIconURL(format?: ImageFormat, size?: number): string;
dynamicSplashURL(format?: ImageFormat, size?: number): string;
dynamicDiscoverySplashURL(format?: ImageFormat, size?: number): string | null;
dynamicIconURL(format?: ImageFormat, size?: number): string | null;
dynamicSplashURL(format?: ImageFormat, size?: number): string | null;
}

export class GuildTemplate {
Expand Down Expand Up @@ -2301,9 +2303,12 @@ declare namespace Eris {
}

export class Member extends Base implements Presence {
accentColor?: number | null;
activities?: Activity[];
avatar: string | null;
avatarURL: string;
banner?: string | null;
bannerURL: string | null;
bot: boolean;
clientStatus?: ClientStatus;
createdAt: number;
Expand Down Expand Up @@ -2694,8 +2699,11 @@ declare namespace Eris {
}

export class User extends Base {
accentColor?: number | null;
avatar: string | null;
avatarURL: string;
banner?: string | null;
bannerURL: string | null;
bot: boolean;
createdAt: number;
defaultAvatar: string;
Expand All @@ -2711,6 +2719,7 @@ declare namespace Eris {
addRelationship(block?: boolean): Promise<void>;
deleteNote(): Promise<void>;
dynamicAvatarURL(format?: ImageFormat, size?: number): string;
dynamicBannerURL(format?: ImageFormat, size?: number): string | null;
editNote(note: string): Promise<void>;
getDMChannel(): Promise<PrivateChannel>;
getProfile(): Promise<UserProfile>;
Expand Down
6 changes: 3 additions & 3 deletions lib/gateway/Shard.js
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ 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.avatar !== packet.d.user.avatar || user.discriminator !== packet.d.user.discriminator)) {
if(user && (user.username !== packet.d.user.username || user.discriminator !== packet.d.user.discriminator || user.avatar !== packet.d.user.avatar)) {
oldUser = {
username: user.username,
discriminator: user.discriminator,
Expand All @@ -613,7 +613,7 @@ class Shard extends EventEmitter {
if(!user || oldUser) {
user = this.client.users.update(packet.d.user, this.client);
/**
* Fired when a user's username, avatar, or discriminator changes
* Fired when a user's avatar, discriminator or username changes
* @event Client#userUpdate
* @prop {User} user The updated user
* @prop {Object?} oldUser The old user data
Expand Down Expand Up @@ -1115,7 +1115,7 @@ 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.avatar !== packet.d.user.avatar || user.discriminator !== packet.d.user.discriminator)) {
if(user && (user.username !== packet.d.user.username || user.discriminator !== packet.d.user.discriminator || user.avatar !== packet.d.user.avatar)) {
oldUser = {
username: user.username,
discriminator: user.discriminator,
Expand Down
2 changes: 1 addition & 1 deletion lib/rest/Endpoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,11 @@ module.exports.WEBHOOK_TOKEN_SLACK = (hookID, token)
module.exports.ACHIEVEMENT_ICON = (applicationID, achievementID, icon) => `/app-assets/${applicationID}/achievements/${achievementID}/icons/${icon}`;
module.exports.APPLICATION_ASSET = (applicationID, asset) => `/app-assets/${applicationID}/${asset}`;
module.exports.APPLICATION_ICON = (applicationID, icon) => `/app-icons/${applicationID}/${icon}`;
module.exports.BANNER = (guildOrUserID, hash) => `/banners/${guildOrUserID}/${hash}`;
module.exports.CHANNEL_ICON = (chanID, chanIcon) => `/channel-icons/${chanID}/${chanIcon}`;
module.exports.CUSTOM_EMOJI = (emojiID) => `/emojis/${emojiID}`;
module.exports.DEFAULT_USER_AVATAR = (userDiscriminator) => `/embed/avatars/${userDiscriminator}`;
module.exports.GUILD_AVATAR = (guildID, userID, guildAvatar) => `/guilds/${guildID}/users/${userID}/avatars/${guildAvatar}`;
module.exports.GUILD_BANNER = (guildID, guildBanner) => `/banners/${guildID}/${guildBanner}`;
module.exports.GUILD_DISCOVERY_SPLASH = (guildID, guildDiscoverySplash) => `/discovery-splashes/${guildID}/${guildDiscoverySplash}`;
module.exports.GUILD_ICON = (guildID, guildIcon) => `/icons/${guildID}/${guildIcon}`;
module.exports.GUILD_SPLASH = (guildID, guildSplash) => `/splashes/${guildID}/${guildSplash}`;
Expand Down
1 change: 1 addition & 0 deletions lib/structures/GroupChannel.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class GroupChannel extends PrivateChannel { // (╯°□°)╯︵ ┻━┻
* Get the group's icon with the given format and size
* @arg {String} [format] The filetype of the icon ("jpg", "jpeg", "png", "gif", or "webp")
* @arg {Number} [size] The size of the icon (any power of two between 16 and 4096)
* @returns {String?}
*/
dynamicIconURL(format, size) {
return this.icon ? this.client._formatImage(Endpoints.CHANNEL_ICON(this.id, this.icon), format, size) : null;
Expand Down
8 changes: 6 additions & 2 deletions lib/structures/Guild.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ class Guild extends Base {
}

get bannerURL() {
return this.banner ? this._client._formatImage(Endpoints.GUILD_BANNER(this.id, this.banner)) : null;
return this.banner ? this._client._formatImage(Endpoints.BANNER(this.id, this.banner)) : null;
}

get iconURL() {
Expand Down Expand Up @@ -456,15 +456,17 @@ class Guild extends Base {
* Get the guild's banner with the given format and size
* @arg {String} [format] The filetype of the icon ("jpg", "jpeg", "png", "gif", or "webp")
* @arg {Number} [size] The size of the icon (any power of two between 16 and 4096)
* @returns {String?}
*/
dynamicBannerURL(format, size) {
return this.banner ? this._client._formatImage(Endpoints.GUILD_BANNER(this.id, this.banner), format, size) : null;
return this.banner ? this._client._formatImage(Endpoints.BANNER(this.id, this.banner), format, size) : null;
}

/**
* Get the guild's discovery splash with the given format and size
* @arg {String} [format] The filetype of the icon ("jpg", "jpeg", "png", "gif", or "webp")
* @arg {Number} [size] The size of the icon (any power of two between 16 and 4096)
* @returns {String?}
*/
dynamicDiscoverySplashURL(format, size) {
return this.discoverySplash ? this._client._formatImage(Endpoints.GUILD_DISCOVERY_SPLASH(this.id, this.discoverySplash), format, size) : null;
Expand All @@ -474,6 +476,7 @@ class Guild extends Base {
* Get the guild's icon with the given format and size
* @arg {String} [format] The filetype of the icon ("jpg", "jpeg", "png", "gif", or "webp")
* @arg {Number} [size] The size of the icon (any power of two between 16 and 4096)
* @returns {String?}
*/
dynamicIconURL(format, size) {
return this.icon ? this._client._formatImage(Endpoints.GUILD_ICON(this.id, this.icon), format, size) : null;
Expand All @@ -483,6 +486,7 @@ class Guild extends Base {
* Get the guild's splash with the given format and size
* @arg {String} [format] The filetype of the icon ("jpg", "jpeg", "png", "gif", or "webp")
* @arg {Number} [size] The size of the icon (any power of two between 16 and 4096)
* @returns {String?}
*/
dynamicSplashURL(format, size) {
return this.splash ? this._client._formatImage(Endpoints.GUILD_SPLASH(this.id, this.splash), format, size) : null;
Expand Down
3 changes: 3 additions & 0 deletions lib/structures/GuildPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class GuildPreview extends Base {
* Get the guild's splash with the given format and size
* @arg {String} [format] The filetype of the icon ("jpg", "jpeg", "png", "gif", or "webp")
* @arg {Number} [size] The size of the icon (any power of two between 16 and 4096)
* @returns {String?}
*/
dynamicDiscoverySplashURL(format, size) {
return this.discoverySplash ? this._client._formatImage(Endpoints.GUILD_DISCOVERY_SPLASH(this.id, this.discoverySplash), format, size) : null;
Expand All @@ -61,6 +62,7 @@ class GuildPreview extends Base {
* Get the guild's icon with the given format and size
* @arg {String} [format] The filetype of the icon ("jpg", "jpeg", "png", "gif", or "webp")
* @arg {Number} [size] The size of the icon (any power of two between 16 and 4096)
* @returns {String?}
*/
dynamicIconURL(format, size) {
return this.icon ? this._client._formatImage(Endpoints.GUILD_ICON(this.id, this.icon), format, size) : null;
Expand All @@ -70,6 +72,7 @@ class GuildPreview extends Base {
* Get the guild's splash with the given format and size
* @arg {String} [format] The filetype of the icon ("jpg", "jpeg", "png", "gif", or "webp")
* @arg {Number} [size] The size of the icon (any power of two between 16 and 4096)
* @returns {String?}
*/
dynamicSplashURL(format, size) {
return this.splash ? this._client._formatImage(Endpoints.GUILD_SPLASH(this.id, this.splash), format, size) : null;
Expand Down
15 changes: 15 additions & 0 deletions lib/structures/Member.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ 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?} avatar The hash of the member's guild avatar, or null if no guild avatar
* @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?} clientStatus The member's per-client status
* @prop {String} clientStatus.web The member's status on web. Either "online", "idle", "dnd", or "offline". Will be "online" for bots
Expand Down Expand Up @@ -104,10 +107,22 @@ class Member extends Base {
}
}

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

get avatarURL() {
return this.avatar ? this.guild.shard.client._formatImage(Endpoints.GUILD_AVATAR(this.guild.id, this.id, this.avatar)) : this.user.avatarURL;
}

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

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

get bot() {
return this.user.bot;
}
Expand Down
46 changes: 45 additions & 1 deletion lib/structures/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ 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?} avatar The hash of the user's avatar, or null if no avatar
* @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 {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
Expand Down Expand Up @@ -44,6 +47,12 @@ class User extends Base {
if(data.public_flags !== undefined) {
this.publicFlags = data.public_flags;
}
if(data.banner !== undefined) {
this.banner = data.banner;
}
if(data.accent_color !== undefined) {
this.accentColor = data.accent_color;
}
}

get avatarURL() {
Expand All @@ -53,6 +62,16 @@ class User extends Base {
return this.avatar ? this._client._formatImage(Endpoints.USER_AVATAR(this.id, this.avatar)) : this.defaultAvatarURL;
}

get bannerURL() {
if(!this.banner) {
return null;
}
if(this._missingClientError) {
throw this._missingClientError;
}
return this._client._formatImage(Endpoints.BANNER(this.id, this.banner));
}

get defaultAvatar() {
return this.discriminator % 5;
}
Expand Down Expand Up @@ -92,9 +111,32 @@ class User extends Base {
* 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")
* @arg {Number} [size] The size of the avatar (any power of two between 16 and 4096)
* @returns {String}
*/
dynamicAvatarURL(format, size) {
return this.avatar ? this._client._formatImage(Endpoints.USER_AVATAR(this.id, this.avatar), format, size) : this.defaultAvatarURL;
if(!this.avatar) {
return this.defaultAvatarURL;
}
if(this._missingClientError) {
throw this._missingClientError;
}
return this._client._formatImage(Endpoints.USER_AVATAR(this.id, this.avatar), format, size);
}

/**
* Get the user's banner with the given format and size
* @arg {String} [format] The filetype of the banner ("jpg", "jpeg", "png", "gif", or "webp")
* @arg {Number} [size] The size of the banner (any power of two between 16 and 4096)
* @returns {String?}
*/
dynamicBannerURL(format, size) {
if(!this.banner) {
return null;
}
if(this._missingClientError) {
throw this._missingClientError;
}
return this._client._formatImage(Endpoints.BANNER(this.id, this.banner), format, size);
}

/**
Expand Down Expand Up @@ -132,7 +174,9 @@ class User extends Base {

toJSON(props = []) {
return super.toJSON([
"accentColor",
"avatar",
"banner",
"bot",
"discriminator",
"publicFlags",
Expand Down

0 comments on commit 558bbe5

Please sign in to comment.