Merge branch 'master' into voice-rewrite

This commit is contained in:
Amish Shah
2018-01-05 21:24:23 +00:00
9 changed files with 85 additions and 62 deletions

View File

@@ -10,20 +10,17 @@ class APIRequest {
this.rest = rest; this.rest = rest;
this.client = rest.client; this.client = rest.client;
this.method = method; this.method = method;
this.path = path.toString();
this.route = options.route; this.route = options.route;
this.options = options; this.options = options;
const queryString = (querystring.stringify(options.query).match(/[^=&?]+=[^=&?]+/g) || []).join('&');
this.path = `${path}${queryString ? `?${queryString}` : ''}`;
} }
gen() { gen() {
const API = this.options.versioned === false ? this.client.options.http.api : const API = this.options.versioned === false ? this.client.options.http.api :
`${this.client.options.http.api}/v${this.client.options.http.version}`; `${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 }); const request = snekfetch[this.method](`${API}${this.path}`, { agent });
if (this.options.auth !== false) request.set('Authorization', this.rest.getAuth()); if (this.options.auth !== false) request.set('Authorization', this.rest.getAuth());

View File

@@ -72,21 +72,22 @@ class GuildMemberStore extends DataStore {
* @returns {Promise<GuildMember>|Promise<Collection<Snowflake, GuildMember>>} * @returns {Promise<GuildMember>|Promise<Collection<Snowflake, GuildMember>>}
* @example * @example
* // Fetch all members from a guild * // Fetch all members from a guild
* guild.members.fetch(); * guild.members.fetch()
* .then(console.log)
* .catch(console.error);
* @example * @example
* // Fetch a single member * // Fetch a single member
* guild.members.fetch('66564597481480192'); * guild.members.fetch('66564597481480192')
* guild.members.fetch(user); * .then(console.log)
* guild.members.fetch({ user, cache: false }); // Fetch and don't cache * .catch(console.error);
* guild.members.fetch({ user, cache: false }) // Fetch and don't cache
* .then(console.log)
* .catch(console.error);
* @example * @example
* // Fetch by query * // Fetch by query
* guild.members.fetch({ * guild.members.fetch({ query: 'hydra' })
* query: 'hydra', * .then(console.log)
* }); * .catch(console.error);
* guild.members.fetch({
* query: 'hydra',
* limit: 10,
* });
*/ */
fetch(options) { fetch(options) {
if (!options) return this._fetchMany(); if (!options) return this._fetchMany();

View File

@@ -52,14 +52,25 @@ class Channel extends Base {
return new Date(this.createdTimestamp); 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. * Deletes this channel.
* @returns {Promise<Channel>} * @returns {Promise<Channel>}
* @example * @example
* // Delete the channel * // Delete the channel
* channel.delete() * channel.delete()
* .then() // Success * then(console.log)
* .catch(console.error); // Log error * .catch(console.error);
*/ */
delete() { delete() {
return this.client.api.channels(this.id).delete().then(() => this); return this.client.api.channels(this.id).delete().then(() => this);

View File

@@ -514,6 +514,11 @@ class Guild extends Base {
* @param {UserResolvable} [options.user] Only show entries involving this user * @param {UserResolvable} [options.user] Only show entries involving this user
* @param {AuditLogAction|number} [options.type] Only show entries involving this action type * @param {AuditLogAction|number} [options.type] Only show entries involving this action type
* @returns {Promise<GuildAuditLogs>} * @returns {Promise<GuildAuditLogs>}
* @example
* // Output audit log entries
* guild.fetchAuditLogs()
* .then(audit => console.log(audit.entries))
* .catch(console.error);
*/ */
fetchAuditLogs(options = {}) { fetchAuditLogs(options = {}) {
if (options.before && options.before instanceof GuildAuditLogs.Entry) options.before = options.before.id; if (options.before && options.before instanceof GuildAuditLogs.Entry) options.before = options.before.id;
@@ -921,8 +926,8 @@ class Guild extends Base {
* @returns {Promise<GuildChannel>} * @returns {Promise<GuildChannel>}
* @example * @example
* // Create a new text channel * // Create a new text channel
* guild.createChannel('new-general', 'text') * guild.createChannel('new-general', { reason: 'Cool new channel' })
* .then(channel => console.log(`Created new channel ${channel}`)) * .then(console.log)
* .catch(console.error); * .catch(console.error);
*/ */
createChannel(name, { type, nsfw, bitrate, userLimit, parent, overwrites, reason } = {}) { createChannel(name, { type, nsfw, bitrate, userLimit, parent, overwrites, reason } = {}) {

View File

@@ -272,8 +272,8 @@ class GuildChannel extends Channel {
* @returns {Promise<GuildChannel>} * @returns {Promise<GuildChannel>}
* @example * @example
* // Edit a channel * // Edit a channel
* channel.edit({name: 'new-channel'}) * channel.edit({ name: 'new-channel' })
* .then(c => console.log(`Edited channel ${c}`)) * .then(console.log)
* .catch(console.error); * .catch(console.error);
*/ */
async edit(data, reason) { 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 {boolean} [options.unique=false] Create a unique invite, or use an existing one with similar settings
* @param {string} [options.reason] Reason for creating this * @param {string} [options.reason] Reason for creating this
* @returns {Promise<Invite>} * @returns {Promise<Invite>}
* @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 } = {}) { createInvite({ temporary = false, maxAge = 86400, maxUses = 0, unique, reason } = {}) {
return this.client.api.channels(this.id).invites.post({ data: { return this.client.api.channels(this.id).invites.post({ data: {
@@ -489,17 +494,6 @@ class GuildChannel extends Channel {
return MessageNotificationTypes[3]; 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; module.exports = GuildChannel;

View File

@@ -300,11 +300,12 @@ class GuildMember extends Base {
/** /**
* Checks if any of the member's roles have a permission. * Checks if any of the member's roles have a permission.
* @param {PermissionResolvable|PermissionResolvable[]} permission Permission(s) to check for * @param {PermissionResolvable|PermissionResolvable[]} permission Permission(s) to check for
* @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override * @param {Object} [options] Options
* @param {boolean} [checkOwner=true] Whether to allow being the guild's owner to override * @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} * @returns {boolean}
*/ */
hasPermission(permission, checkAdmin = true, checkOwner = true) { hasPermission(permission, { checkAdmin = true, checkOwner = true } = {}) {
if (checkOwner && this.user.id === this.guild.ownerID) return true; if (checkOwner && this.user.id === this.guild.ownerID) return true;
return this.roles.some(r => r.permissions.has(permission, checkAdmin)); return this.roles.some(r => r.permissions.has(permission, checkAdmin));
} }
@@ -395,6 +396,16 @@ class GuildMember extends Base {
* @param {Collection<Snowflake, Role>|RoleResolvable[]} roles The roles or role IDs to apply * @param {Collection<Snowflake, Role>|RoleResolvable[]} roles The roles or role IDs to apply
* @param {string} [reason] Reason for applying the roles * @param {string} [reason] Reason for applying the roles
* @returns {Promise<GuildMember>} * @returns {Promise<GuildMember>}
* @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) { setRoles(roles, reason) {
return this.edit({ roles }, reason); return this.edit({ roles }, reason);
@@ -527,7 +538,9 @@ class GuildMember extends Base {
* @returns {Promise<GuildMember>} * @returns {Promise<GuildMember>}
* @example * @example
* // ban a guild member * // ban a guild member
* guildMember.ban(7); * guildMember.ban({ days: 7, reason: 'They deserved it' })
* .then(console.log)
* .catch(console.error);
*/ */
ban(options) { ban(options) {
return this.guild.ban(this, options); return this.guild.ban(this, options);

View File

@@ -273,10 +273,8 @@ class Message extends Base {
* @returns {ReactionCollector} * @returns {ReactionCollector}
* @example * @example
* // Create a reaction collector * // Create a reaction collector
* const collector = message.createReactionCollector( * const filter = (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someID';
* (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someID', * const collector = message.createReactionCollector(filter, { time: 15000 });
* { time: 15000 }
* );
* collector.on('collect', r => console.log(`Collected ${r.emoji.name}`)); * collector.on('collect', r => console.log(`Collected ${r.emoji.name}`));
* collector.on('end', collected => console.log(`Collected ${collected.size} items`)); * 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 {CollectorFilter} filter The filter function to use
* @param {AwaitReactionsOptions} [options={}] Optional options to pass to the internal collector * @param {AwaitReactionsOptions} [options={}] Optional options to pass to the internal collector
* @returns {Promise<Collection<string, MessageReaction>>} * @returns {Promise<Collection<string, MessageReaction>>}
* @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 = {}) { awaitReactions(filter, options = {}) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

View File

@@ -195,10 +195,8 @@ class TextBasedChannel {
* @returns {MessageCollector} * @returns {MessageCollector}
* @example * @example
* // Create a message collector * // Create a message collector
* const collector = channel.createMessageCollector( * const filter = m => m.content.includes('discord');
* m => m.content.includes('discord'), * const collector = channel.createMessageCollector(filter, { time: 15000 });
* { time: 15000 }
* );
* collector.on('collect', m => console.log(`Collected ${m.content}`)); * collector.on('collect', m => console.log(`Collected ${m.content}`));
* collector.on('end', collected => console.log(`Collected ${collected.size} items`)); * collector.on('end', collected => console.log(`Collected ${collected.size} items`));
*/ */
@@ -246,6 +244,11 @@ class TextBasedChannel {
* Messages or number of messages to delete * Messages or number of messages to delete
* @param {boolean} [filterOld=false] Filter messages to remove those which are older than two weeks automatically * @param {boolean} [filterOld=false] Filter messages to remove those which are older than two weeks automatically
* @returns {Promise<Collection<Snowflake, Message>>} Deleted messages * @returns {Promise<Collection<Snowflake, Message>>} 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) { async bulkDelete(messages, filterOld = false) {
if (messages instanceof Array || messages instanceof Collection) { if (messages instanceof Array || messages instanceof Collection) {

View File

@@ -77,15 +77,10 @@ class Util {
*/ */
static parseEmoji(text) { static parseEmoji(text) {
if (text.includes('%')) text = decodeURIComponent(text); if (text.includes('%')) text = decodeURIComponent(text);
if (text.includes(':')) { if (!text.includes(':')) return { animated: false, name: text, id: null };
const m = text.match(/<?(a)?:(\w{2,32}):(\d{17,19})>?/); const m = text.match(/<?(a)?:?(\w{2,32}):(\d{17,19})>?/);
if (!m) { if (!m) return null;
return null; return { animated: Boolean(m[1]), name: m[2], id: m[3] };
}
return { animated: Boolean(m[1]), name: m[2], id: m[3] };
} else {
return { animated: false, name: text, id: null };
}
} }
/** /**
@@ -184,11 +179,11 @@ class Util {
* @private * @private
*/ */
static makePlainError(err) { static makePlainError(err) {
const obj = {}; return {
obj.name = err.name; name: err.name,
obj.message = err.message; message: err.message,
obj.stack = err.stack; stack: err.stack,
return obj; };
} }
/** /**
@@ -318,8 +313,8 @@ class Util {
* @private * @private
*/ */
static basename(path, ext) { static basename(path, ext) {
let f = splitPathRe.exec(path).slice(1)[2]; let f = splitPathRe.exec(path)[3];
if (ext && f.substr(-1 * ext.length) === ext) f = f.substr(0, f.length - ext.length); if (ext && f.endsWith(ext)) f = f.slice(0, -ext.length);
return f; return f;
} }