From e6a378b361680311776f7c5a815e3a53d9b3260c Mon Sep 17 00:00:00 2001 From: SpaceEEC Date: Thu, 13 Jun 2019 18:33:07 +0200 Subject: [PATCH] feat(Guild): backport misc properties and setRolePositions (#3337) * feat(Guild): backport misc properties and setRolePositions PRs: * #3168 * #3317 * typings --- src/client/rest/RESTMethods.js | 21 ++---- src/structures/Guild.js | 117 ++++++++++++++++++++++++++++++++- src/util/Constants.js | 2 + typings/index.d.ts | 18 +++++ 4 files changed, 139 insertions(+), 19 deletions(-) diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js index 44715c182..d0e9df3ef 100644 --- a/src/client/rest/RESTMethods.js +++ b/src/client/rest/RESTMethods.js @@ -499,6 +499,10 @@ class RESTMethods { .then(data => this.client.actions.GuildMemberGet.handle(guild, data).member); } + getGuild(guild) { + return this.rest.makeRequest('get', Endpoints.Guild(guild), true); + } + getGuildMember(guild, userID, cache) { return this.rest.makeRequest('get', Endpoints.Guild(guild).Member(userID), true).then(data => { if (cache) return this.client.actions.GuildMemberGet.handle(guild, data).member; @@ -886,23 +890,6 @@ class RESTMethods { .then(() => user); } - updateChannelPositions(guildID, channels) { - const data = new Array(channels.length); - for (let i = 0; i < channels.length; i++) { - data[i] = { - id: this.client.resolver.resolveChannelID(channels[i].channel), - position: channels[i].position, - }; - } - - return this.rest.makeRequest('patch', Endpoints.Guild(guildID).channels, true, data).then(() => - this.client.actions.GuildChannelsPositionUpdate.handle({ - guild_id: guildID, - channels, - }).guild - ); - } - updateEmbed(guildID, embed, reason) { return this.rest.makeRequest('patch', Endpoints.Guild(guildID).embed, true, { enabled: embed.enabled, diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 308dd57cb..b3084d5ac 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -184,6 +184,61 @@ class Guild { this.defaultMessageNotifications = Constants.DefaultMessageNotifications[data.default_message_notifications] || data.default_message_notifications; + /** + * The hash of the guild banner + * @type {?string} + */ + this.banner = data.banner; + + /** + * The description of the guild, if any + * @type {?string} + */ + this.description = data.description; + + /** + * The embed channel ID, if enabled + * @type {?string} + * @name Guild#embedChannelID + */ + if (typeof data.embed_channel_id !== 'undefined') this.embedChannelID = data.embed_channel_id; + + /** + * The maximum amount of members the guild can have + * You will need to fetch the guild using {@link Guild#fetch} if you want to receive this parameter + * @type {?number} + * @name Guild#maximumMembers + */ + if (typeof data.max_members !== 'undefined') this.maximumMembers = data.max_members || 250000; + + /** + * The maximum amount of presences the guild can have + * You will need to fetch the guild using {@link Guild#fetch} if you want to receive this parameter + * @type {?number} + * @name Guild#maximumPresences + */ + if (typeof data.max_presences !== 'undefined') this.maximumPresences = data.max_presences || 5000; + + /** + * Whether widget images are enabled on this guild + * @type {?boolean} + * @name Guild#widgetEnabled + */ + if (typeof data.widget_enabled !== 'undefined') this.widgetEnabled = data.widget_enabled; + + /** + * The widget channel ID, if enabled + * @type {?string} + * @name Guild#widgetChannelID + */ + if (typeof data.widget_channel_id !== 'undefined') this.widgetChannelID = data.widget_channel_id; + + /** + * The vanity URL code of the guild, if any + * @type {?string} + */ + this.vanityURLCode = data.vanity_url_code; + this.id = data.id; this.available = !data.unavailable; this.features = data.features || this.features || []; @@ -272,6 +327,24 @@ class Guild { return new Date(this.createdTimestamp); } + /** + * Embed channel for this guild + * @type {?TextChannel} + * @readonly + */ + get embedChannel() { + return this.channels.get(this.embedChannelID) || null; + } + + /** + * Widget channel for this guild + * @type {?TextChannel} + * @readonly + */ + get widgetChannel() { + return this.channels.get(this.widgetChannelID) || null; + } + /** * The time the client user joined the guild * @type {Date} @@ -300,6 +373,16 @@ class Guild { return Constants.Endpoints.Guild(this).Icon(this.client.options.http.cdn, this.icon); } + /** + * The URL to this guild's banner. + * @type {?string} + * @readonly + */ + get bannerURL() { + if (!this.banner) return null; + return Constants.Endpoints.Guild(this).Banner(this.client.options.http.cdn, this.banner); + } + /** * The acronym that shows up in place of a guild icon. * @type {string} @@ -473,6 +556,18 @@ class Guild { return this.client.resolver.resolveGuildMember(this, user); } + /** + * Fetches this guild. + * @returns {Promise} + */ + fetch() { + return this.client.rest.methods.getGuild(this).then(data => { + this.setup(data); + + return this; + }); + } + /** * An object containing information about a guild member's ban. * @typedef {Object} BanInfo @@ -1115,7 +1210,25 @@ class Guild { * .catch(console.error); */ setChannelPositions(channelPositions) { - return this.client.rest.methods.updateChannelPositions(this.id, channelPositions); + channelPositions = channelPositions.map(({ channel, position }) => ({ id: channel.id || channel, position })); + return this.client.rest.methods.setChannelPositions(this.id, channelPositions); + } + + /** + * The data needed for updating a role's position. + * @typedef {Object} RolePosition + * @property {RoleResolvable} role Role to update + * @property {number} position New position for the role + */ + + /** + * Batch-updates the guild's role's positions. + * @param {RolePosition[]} rolePositions Role positions to update + * @returns {Promise} + */ + setRolePositions(rolePositions) { + rolePositions = rolePositions.map(({ role, position }) => ({ id: role.id || role, position })); + return this.client.rest.methods.setRolePositions(this.id, rolePositions); } /** @@ -1396,7 +1509,7 @@ class Guild { Util.moveElementInArray(updatedChannels, channel, position, relative); - updatedChannels = updatedChannels.map((r, i) => ({ id: r.id, position: i })); + updatedChannels = updatedChannels.map((c, i) => ({ id: c.id, position: i })); return this.client.rest.methods.setChannelPositions(this.id, updatedChannels); } diff --git a/src/util/Constants.js b/src/util/Constants.js index 9110c42dc..3787818b6 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -152,6 +152,7 @@ const Endpoints = exports.Endpoints = { auditLogs: `${base}/audit-logs`, Emoji: emojiID => `${base}/emojis/${emojiID}`, Icon: (root, hash) => Endpoints.CDN(root).Icon(guildID, hash), + Banner: (root, hash) => Endpoints.CDN(root).Banner(guildID, hash), Splash: (root, hash) => Endpoints.CDN(root).Splash(guildID, hash), Role: roleID => `${base}/roles/${roleID}`, Member: memberID => { @@ -210,6 +211,7 @@ const Endpoints = exports.Endpoints = { Asset: name => `${root}/assets/${name}`, Avatar: (userID, hash) => `${root}/avatars/${userID}/${hash}.${hash.startsWith('a_') ? 'gif' : 'png?size=2048'}`, Icon: (guildID, hash) => `${root}/icons/${guildID}/${hash}.jpg`, + Banner: (guildID, hash) => `${root}/banners/${guildID}/${hash}.jpg`, AppIcon: (clientID, hash) => `${root}/app-icons/${clientID}/${hash}.png`, AppAsset: (clientID, hash) => `${root}/app-assets/${clientID}/${hash}.png`, GDMIcon: (channelID, hash) => `${root}/channel-icons/${channelID}/${hash}.jpg?size=2048`, diff --git a/typings/index.d.ts b/typings/index.d.ts index 989d1bdc3..8e48a99dd 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -482,6 +482,9 @@ declare module 'discord.js' { public afkTimeout: number; public applicationID: string; public available: boolean; + public banner: string | null; + public readonly bannerURL: string | null; + public description: string | null; public channels: Collection; public defaultMessageNotifications: DefaultMessageNotifications | number; public readonly client: Client; @@ -489,6 +492,8 @@ declare module 'discord.js' { public readonly createdTimestamp: number; public readonly defaultChannel: TextChannel; public readonly defaultRole: Role; + public readonly embedChannel: TextChannel | null; + public embedChannelID: Snowflake | null; public embedEnabled: boolean; public emojis: Collection; public explicitContentFilter: number; @@ -499,6 +504,8 @@ declare module 'discord.js' { public readonly joinedAt: Date; public joinedTimestamp: number; public large: boolean; + public maximumMembers?: number; + public maximumPresences?: number; public readonly me: GuildMember; public memberCount: number; public members: Collection; @@ -518,9 +525,13 @@ declare module 'discord.js' { public readonly suppressEveryone: boolean; public readonly systemChannel: GuildChannel; public systemChannelID: Snowflake; + public vanityURLCode: string; public readonly verified: boolean; public verificationLevel: number; public readonly voiceConnection: VoiceConnection; + public readonly widgetChannel: TextChannel | null; + public widgetChannelID?: Snowflake; + public widgetEnabled?: boolean; public acknowledge(): Promise; public addMember(user: UserResolvable, options: AddGuildMemberOptions): Promise; public allowDMs(allow: boolean): Promise; @@ -533,6 +544,7 @@ declare module 'discord.js' { public deleteEmoji(emoji: Emoji | string, reason?: string): Promise; public edit(data: GuildEditData, reason?: string): Promise; public equals(guild: Guild): boolean; + public fetch(): Promise; public fetchAuditLogs(options?: GuildAuditLogsFetchOptions): Promise; public fetchBan(user: UserResolvable): Promise; public fetchBans(withReasons?: false): Promise>; @@ -562,6 +574,7 @@ declare module 'discord.js' { public setPosition(position: number, relative?: boolean): Promise; public setRegion(region: string, reason?: string): Promise; public setRolePosition(role: string | Role, position: number, relative?: boolean): Promise; + public setRolePositions(rolePositions: RolePosition[]): Promise; public setSplash(splash: Base64Resolvable, reason?: string): Promise; public setSystemChannel(systemChannel: ChannelResolvable, reason?: string): Promise; public setVerificationLevel(verificationLevel: number, reason?: string): Promise; @@ -2103,6 +2116,11 @@ declare module 'discord.js' { mentionable?: boolean; }; + type RolePosition = { + role: RoleResolvable; + position: number; + }; + type RoleResolvable = Role | string; type Snowflake = string;