From 954a1c8d1afdf50f068ca9ca9320d265f6cb0633 Mon Sep 17 00:00:00 2001 From: Darqam Date: Wed, 3 Jan 2018 18:00:39 -0600 Subject: [PATCH 1/7] updating channelCreate example to reflect recent changes (#2194) * updating channelCreate example to reflect recent changes Type is now part of the options object, so the example should reflect that. * changing type to reason per comment --- src/structures/Guild.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 5f9674585..b11548b56 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -921,7 +921,7 @@ class Guild extends Base { * @returns {Promise} * @example * // Create a new text channel - * guild.createChannel('new-general', 'text') + * guild.createChannel('new-general', { reason: 'My reason here.' }) * .then(channel => console.log(`Created new channel ${channel}`)) * .catch(console.error); */ From abb93c9eb99ee1cf1580b3d09e46679186e8b6b7 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Wed, 3 Jan 2018 18:01:39 -0600 Subject: [PATCH 2/7] fix location of toString for channels (#2202) --- src/structures/Channel.js | 11 +++++++++++ src/structures/GuildChannel.js | 11 ----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/structures/Channel.js b/src/structures/Channel.js index 04867b118..833d9ef12 100644 --- a/src/structures/Channel.js +++ b/src/structures/Channel.js @@ -52,6 +52,17 @@ class Channel extends Base { return new Date(this.createdTimestamp); } + /** + * When concatenated with a string, this automatically returns the channel's mention instead of the Channel object. + * @returns {string} + * @example + * // Logs: Hello from <#123456789012345678>! + * console.log(`Hello from ${channel}!`); + */ + toString() { + return `<#${this.id}>`; + } + /** * Deletes this channel. * @returns {Promise} diff --git a/src/structures/GuildChannel.js b/src/structures/GuildChannel.js index 0862f1455..25c26274b 100644 --- a/src/structures/GuildChannel.js +++ b/src/structures/GuildChannel.js @@ -489,17 +489,6 @@ class GuildChannel extends Channel { return MessageNotificationTypes[3]; } } - - /** - * When concatenated with a string, this automatically returns the channel's mention instead of the Channel object. - * @returns {string} - * @example - * // Logs: Hello from <#123456789012345678>! - * console.log(`Hello from ${channel}!`); - */ - toString() { - return `<#${this.id}>`; - } } module.exports = GuildChannel; From 61da73fee00078a88401d82b66fa3402e0d2785d Mon Sep 17 00:00:00 2001 From: Isabella Date: Wed, 3 Jan 2018 18:04:19 -0600 Subject: [PATCH 3/7] GuildMember#permissionsFor takes object (#2210) --- src/structures/GuildMember.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js index 21f84ec98..f0e3952dd 100644 --- a/src/structures/GuildMember.js +++ b/src/structures/GuildMember.js @@ -300,11 +300,12 @@ class GuildMember extends Base { /** * Checks if any of the member's roles have a permission. * @param {PermissionResolvable|PermissionResolvable[]} permission Permission(s) to check for - * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override - * @param {boolean} [checkOwner=true] Whether to allow being the guild's owner to override + * @param {Object} [options] Options + * @param {boolean} [options.checkAdmin=true] Whether to allow the administrator permission to override + * @param {boolean} [options.checkOwner=true] Whether to allow being the guild's owner to override * @returns {boolean} */ - hasPermission(permission, checkAdmin = true, checkOwner = true) { + hasPermission(permission, { checkAdmin = true, checkOwner = true } = {}) { if (checkOwner && this.user.id === this.guild.ownerID) return true; return this.roles.some(r => r.permissions.has(permission, checkAdmin)); } From 45127bb408e668f6e1ca4b001b857f64314243c9 Mon Sep 17 00:00:00 2001 From: Isabella Date: Wed, 3 Jan 2018 18:12:05 -0600 Subject: [PATCH 4/7] docs: improve examples (master branch) (#2209) * docs: improve examples * more improvements fix maybe this another example collectors * stuff --- src/stores/GuildMemberStore.js | 23 ++++++++++--------- src/structures/Channel.js | 4 ++-- src/structures/Guild.js | 9 ++++++-- src/structures/GuildChannel.js | 9 ++++++-- src/structures/GuildMember.js | 14 ++++++++++- src/structures/Message.js | 12 ++++++---- src/structures/interfaces/TextBasedChannel.js | 11 +++++---- 7 files changed, 56 insertions(+), 26 deletions(-) diff --git a/src/stores/GuildMemberStore.js b/src/stores/GuildMemberStore.js index ad0acbed9..692d72784 100644 --- a/src/stores/GuildMemberStore.js +++ b/src/stores/GuildMemberStore.js @@ -72,21 +72,22 @@ class GuildMemberStore extends DataStore { * @returns {Promise|Promise>} * @example * // Fetch all members from a guild - * guild.members.fetch(); + * guild.members.fetch() + * .then(console.log) + * .catch(console.error); * @example * // Fetch a single member - * guild.members.fetch('66564597481480192'); - * guild.members.fetch(user); - * guild.members.fetch({ user, cache: false }); // Fetch and don't cache + * guild.members.fetch('66564597481480192') + * .then(console.log) + * .catch(console.error); + * guild.members.fetch({ user, cache: false }) // Fetch and don't cache + * .then(console.log) + * .catch(console.error); * @example * // Fetch by query - * guild.members.fetch({ - * query: 'hydra', - * }); - * guild.members.fetch({ - * query: 'hydra', - * limit: 10, - * }); + * guild.members.fetch({ query: 'hydra' }) + * .then(console.log) + * .catch(console.error); */ fetch(options) { if (!options) return this._fetchMany(); diff --git a/src/structures/Channel.js b/src/structures/Channel.js index 833d9ef12..af17de57d 100644 --- a/src/structures/Channel.js +++ b/src/structures/Channel.js @@ -69,8 +69,8 @@ class Channel extends Base { * @example * // Delete the channel * channel.delete() - * .then() // Success - * .catch(console.error); // Log error + * then(console.log) + * .catch(console.error); */ delete() { return this.client.api.channels(this.id).delete().then(() => this); diff --git a/src/structures/Guild.js b/src/structures/Guild.js index b11548b56..c47fd74f5 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -514,6 +514,11 @@ class Guild extends Base { * @param {UserResolvable} [options.user] Only show entries involving this user * @param {AuditLogAction|number} [options.type] Only show entries involving this action type * @returns {Promise} + * @example + * // Output audit log entries + * guild.fetchAuditLogs() + * .then(audit => console.log(audit.entries)) + * .catch(console.error); */ fetchAuditLogs(options = {}) { if (options.before && options.before instanceof GuildAuditLogs.Entry) options.before = options.before.id; @@ -921,8 +926,8 @@ class Guild extends Base { * @returns {Promise} * @example * // Create a new text channel - * guild.createChannel('new-general', { reason: 'My reason here.' }) - * .then(channel => console.log(`Created new channel ${channel}`)) + * guild.createChannel('new-general', { reason: 'Cool new channel' }) + * .then(console.log) * .catch(console.error); */ createChannel(name, { type, nsfw, bitrate, userLimit, parent, overwrites, reason } = {}) { diff --git a/src/structures/GuildChannel.js b/src/structures/GuildChannel.js index 25c26274b..518e12253 100644 --- a/src/structures/GuildChannel.js +++ b/src/structures/GuildChannel.js @@ -272,8 +272,8 @@ class GuildChannel extends Channel { * @returns {Promise} * @example * // Edit a channel - * channel.edit({name: 'new-channel'}) - * .then(c => console.log(`Edited channel ${c}`)) + * channel.edit({ name: 'new-channel' }) + * .then(console.log) * .catch(console.error); */ async edit(data, reason) { @@ -386,6 +386,11 @@ class GuildChannel extends Channel { * @param {boolean} [options.unique=false] Create a unique invite, or use an existing one with similar settings * @param {string} [options.reason] Reason for creating this * @returns {Promise} + * @example + * // Create an invite to a channel + * channel.createInvite() + * .then(invite => console.log(`Created an invite with a code of ${invite.code}`)) + * .catch(console.error); */ createInvite({ temporary = false, maxAge = 86400, maxUses = 0, unique, reason } = {}) { return this.client.api.channels(this.id).invites.post({ data: { diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js index f0e3952dd..8a22c0e4d 100644 --- a/src/structures/GuildMember.js +++ b/src/structures/GuildMember.js @@ -396,6 +396,16 @@ class GuildMember extends Base { * @param {Collection|RoleResolvable[]} roles The roles or role IDs to apply * @param {string} [reason] Reason for applying the roles * @returns {Promise} + * @example + * // Set the member's roles to a single role + * guildMember.setRoles(['391156570408615936']) + * .then(console.log) + * .catch(console.error); + * @example + * // Remove all the roles from a member + * guildMember.setRoles([]) + * .then(member => console.log(`Member roles is now of ${member.roles.size} size`)) + * .catch(console.error); */ setRoles(roles, reason) { return this.edit({ roles }, reason); @@ -528,7 +538,9 @@ class GuildMember extends Base { * @returns {Promise} * @example * // ban a guild member - * guildMember.ban(7); + * guildMember.ban({ days: 7, reason: 'They deserved it' }) + * .then(console.log) + * .catch(console.error); */ ban(options) { return this.guild.ban(this, options); diff --git a/src/structures/Message.js b/src/structures/Message.js index 9b86279ea..050adae9f 100644 --- a/src/structures/Message.js +++ b/src/structures/Message.js @@ -273,10 +273,8 @@ class Message extends Base { * @returns {ReactionCollector} * @example * // Create a reaction collector - * const collector = message.createReactionCollector( - * (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someID', - * { time: 15000 } - * ); + * const filter = (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someID'; + * const collector = message.createReactionCollector(filter, { time: 15000 }); * collector.on('collect', r => console.log(`Collected ${r.emoji.name}`)); * collector.on('end', collected => console.log(`Collected ${collected.size} items`)); */ @@ -296,6 +294,12 @@ class Message extends Base { * @param {CollectorFilter} filter The filter function to use * @param {AwaitReactionsOptions} [options={}] Optional options to pass to the internal collector * @returns {Promise>} + * @example + * // Create a reaction collector + * const filter = (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someID' + * message.awaitReactions(filter, { time: 15000 }) + * .then(collected => console.log(`Collected ${collected.size} reactions`)) + * .catch(console.error); */ awaitReactions(filter, options = {}) { return new Promise((resolve, reject) => { diff --git a/src/structures/interfaces/TextBasedChannel.js b/src/structures/interfaces/TextBasedChannel.js index 39aac0937..701d56036 100644 --- a/src/structures/interfaces/TextBasedChannel.js +++ b/src/structures/interfaces/TextBasedChannel.js @@ -195,10 +195,8 @@ class TextBasedChannel { * @returns {MessageCollector} * @example * // Create a message collector - * const collector = channel.createMessageCollector( - * m => m.content.includes('discord'), - * { time: 15000 } - * ); + * const filter = m => m.content.includes('discord'); + * const collector = channel.createMessageCollector(filter, { time: 15000 }); * collector.on('collect', m => console.log(`Collected ${m.content}`)); * collector.on('end', collected => console.log(`Collected ${collected.size} items`)); */ @@ -246,6 +244,11 @@ class TextBasedChannel { * Messages or number of messages to delete * @param {boolean} [filterOld=false] Filter messages to remove those which are older than two weeks automatically * @returns {Promise>} Deleted messages + * @example + * // Bulk delete messages + * channel.bulkDelete(5) + * .then(messages => console.log(`Bulk deleted ${messages.size} messages`)) + * .catch(console.error); */ async bulkDelete(messages, filterOld = false) { if (messages instanceof Array || messages instanceof Collection) { From 01f1f1b58e5b4a3ba5de77c85802520ab4cafee3 Mon Sep 17 00:00:00 2001 From: 1Computer1 <1Computer1@users.noreply.github.com> Date: Wed, 3 Jan 2018 19:17:15 -0500 Subject: [PATCH 5/7] Fix query string on requests after ratelimited (#2215) * Fix querystring being appended multiple times when ratelimited * Better way? * Better better way * Fix empty queries --- src/rest/APIRequest.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/rest/APIRequest.js b/src/rest/APIRequest.js index ae4a352f3..e0527320d 100644 --- a/src/rest/APIRequest.js +++ b/src/rest/APIRequest.js @@ -10,20 +10,17 @@ class APIRequest { this.rest = rest; this.client = rest.client; this.method = method; - this.path = path.toString(); this.route = options.route; this.options = options; + + const queryString = (querystring.stringify(options.query).match(/[^=&?]+=[^=&?]+/g) || []).join('&'); + this.path = `${path}${queryString ? `?${queryString}` : ''}`; } gen() { const API = this.options.versioned === false ? this.client.options.http.api : `${this.client.options.http.api}/v${this.client.options.http.version}`; - if (this.options.query) { - const queryString = (querystring.stringify(this.options.query).match(/[^=&?]+=[^=&?]+/g) || []).join('&'); - this.path += `?${queryString}`; - } - const request = snekfetch[this.method](`${API}${this.path}`, { agent }); if (this.options.auth !== false) request.set('Authorization', this.rest.getAuth()); From 780a311c0a63d0e06bb13362ccb546b819cfbff9 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 4 Jan 2018 02:18:56 +0200 Subject: [PATCH 6/7] Minor refactor to Util methods (#2213) * Minor refactor to Util methods * Fix derp --- src/util/Util.js | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/util/Util.js b/src/util/Util.js index f1758000d..1d6f2d17b 100644 --- a/src/util/Util.js +++ b/src/util/Util.js @@ -77,15 +77,10 @@ class Util { */ static parseEmoji(text) { if (text.includes('%')) text = decodeURIComponent(text); - if (text.includes(':')) { - const m = text.match(/?/); - if (!m) { - return null; - } - return { animated: Boolean(m[1]), name: m[2], id: m[3] }; - } else { - return { animated: false, name: text, id: null }; - } + if (!text.includes(':')) return { animated: false, name: text, id: null }; + const m = text.match(/?/); + if (!m) return null; + return { animated: Boolean(m[1]), name: m[2], id: m[3] }; } /** @@ -184,11 +179,11 @@ class Util { * @private */ static makePlainError(err) { - const obj = {}; - obj.name = err.name; - obj.message = err.message; - obj.stack = err.stack; - return obj; + return { + name: err.name, + message: err.message, + stack: err.stack, + }; } /** @@ -318,8 +313,8 @@ class Util { * @private */ static basename(path, ext) { - let f = splitPathRe.exec(path).slice(1)[2]; - if (ext && f.substr(-1 * ext.length) === ext) f = f.substr(0, f.length - ext.length); + let f = splitPathRe.exec(path)[3]; + if (ext && f.endsWith(ext)) f = f.slice(0, -ext.length); return f; } From 2318812f7f2229e0934a28967b406c4ef7f58073 Mon Sep 17 00:00:00 2001 From: SpaceEEC Date: Thu, 4 Jan 2018 20:29:32 +0100 Subject: [PATCH 7/7] fix: allow the Util#parseEmoji regex to match emoji identifier (#2229) --- src/util/Util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/Util.js b/src/util/Util.js index 1d6f2d17b..c1020ec10 100644 --- a/src/util/Util.js +++ b/src/util/Util.js @@ -78,7 +78,7 @@ class Util { static parseEmoji(text) { if (text.includes('%')) text = decodeURIComponent(text); if (!text.includes(':')) return { animated: false, name: text, id: null }; - const m = text.match(/?/); + const m = text.match(/?/); if (!m) return null; return { animated: Boolean(m[1]), name: m[2], id: m[3] }; }