Clean up nearly all promises to utilise chaining, other small fixes

This commit is contained in:
Schuyler Cebulskie
2016-10-30 16:27:28 -04:00
parent 8306d50bd8
commit 60e0d507f0
10 changed files with 482 additions and 620 deletions

View File

@@ -282,10 +282,11 @@ class Client extends EventEmitter {
/** /**
* Fetch a webhook by ID. * Fetch a webhook by ID.
* @param {string} id ID of the webhook * @param {string} id ID of the webhook
* @param {string} [token] Token for the webhook
* @returns {Promise<Webhook>} * @returns {Promise<Webhook>}
*/ */
fetchWebhook(id) { fetchWebhook(id, token) {
return this.rest.methods.getWebhook(id); return this.rest.methods.getWebhook(id, token);
} }
/** /**

View File

@@ -91,11 +91,9 @@ class ClientDataResolver {
*/ */
resolveGuildMember(guild, user) { resolveGuildMember(guild, user) {
if (user instanceof GuildMember) return user; if (user instanceof GuildMember) return user;
guild = this.resolveGuild(guild); guild = this.resolveGuild(guild);
user = this.resolveUser(user); user = this.resolveUser(user);
if (!guild || !user) return null; if (!guild || !user) return null;
return guild.members.get(user.id) || null; return guild.members.get(user.id) || null;
} }
@@ -136,7 +134,6 @@ class ClientDataResolver {
resolveInviteCode(data) { resolveInviteCode(data) {
const inviteRegex = /discord(?:app)?\.(?:gg|com\/invite)\/([a-z0-9]{5})/i; const inviteRegex = /discord(?:app)?\.(?:gg|com\/invite)\/([a-z0-9]{5})/i;
const match = inviteRegex.exec(data); const match = inviteRegex.exec(data);
if (match && match[1]) return match[1]; if (match && match[1]) return match[1];
return data; return data;
} }
@@ -240,6 +237,8 @@ class ClientDataResolver {
* @returns {Promise<Buffer>} * @returns {Promise<Buffer>}
*/ */
resolveFile(resource) { resolveFile(resource) {
if (resource instanceof Buffer) return Promise.resolve(resource);
if (typeof resource === 'string') { if (typeof resource === 'string') {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (/^https?:\/\//.test(resource)) { if (/^https?:\/\//.test(resource)) {
@@ -259,8 +258,7 @@ class ClientDataResolver {
}); });
} }
if (resource instanceof Buffer) return Promise.resolve(resource); return Promise.reject(new TypeError('The resource must be a string or Buffer.'));
return Promise.reject(new TypeError('Resource must be a string or Buffer.'));
} }
} }

View File

@@ -25,15 +25,12 @@ class RESTMethods {
} }
loginEmailPassword(email, password) { loginEmailPassword(email, password) {
return new Promise((resolve, reject) => { this.rest.client.emit('warn', 'Client launched using email and password - should use token instead');
this.rest.client.emit('warn', 'Client launched using email and password - should use token instead'); this.rest.client.email = email;
this.rest.client.email = email; this.rest.client.password = password;
this.rest.client.password = password; return this.rest.makeRequest('post', Constants.Endpoints.login, false, { email, password }).then(data =>
this.rest.makeRequest('post', Constants.Endpoints.login, false, { email, password }) this.loginToken(data.token)
.then(data => { );
resolve(this.loginToken(data.token));
}, reject);
});
} }
logout() { logout() {
@@ -41,12 +38,9 @@ class RESTMethods {
} }
getGateway() { getGateway() {
return new Promise((resolve, reject) => { return this.rest.makeRequest('get', Constants.Endpoints.gateway, true).then(res => {
this.rest.makeRequest('get', Constants.Endpoints.gateway, true) this.rest.client.ws.gateway = `${res.url}/?encoding=json&v=${Constants.PROTOCOL_VERSION}`;
.then(res => { return this.rest.client.ws.gateway;
this.rest.client.ws.gateway = `${res.url}/?encoding=json&v=${Constants.PROTOCOL_VERSION}`;
resolve(this.rest.client.ws.gateway);
}, reject);
}); });
} }
@@ -108,99 +102,78 @@ class RESTMethods {
} }
deleteMessage(message) { deleteMessage(message) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('del', Constants.Endpoints.channelMessage(message.channel.id, message.id), true)
this.rest.makeRequest('del', Constants.Endpoints.channelMessage(message.channel.id, message.id), true) .then(() =>
.then(() => { this.rest.client.actions.MessageDelete.handle({
resolve(this.rest.client.actions.MessageDelete.handle({ id: message.id,
id: message.id, channel_id: message.channel.id,
channel_id: message.channel.id, }).message
}).message); );
}, reject);
});
} }
bulkDeleteMessages(channel, messages) { bulkDeleteMessages(channel, messages) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('post', `${Constants.Endpoints.channelMessages(channel.id)}/bulk_delete`, true, {
const options = { messages }; messages,
this.rest.makeRequest('post', `${Constants.Endpoints.channelMessages(channel.id)}/bulk_delete`, true, options) }).then(() =>
.then(() => { this.rest.client.actions.MessageDeleteBulk.handle({
resolve(this.rest.client.actions.MessageDeleteBulk.handle({ channel_id: channel.id,
channel_id: channel.id, ids: messages,
ids: messages, }).messages
}).messages); );
}, reject);
});
} }
updateMessage(message, content) { updateMessage(message, content) {
return new Promise((resolve, reject) => { content = this.rest.client.resolver.resolveString(content);
content = this.rest.client.resolver.resolveString(content); return this.rest.makeRequest('patch', Constants.Endpoints.channelMessage(message.channel.id, message.id), true, {
content,
this.rest.makeRequest('patch', Constants.Endpoints.channelMessage(message.channel.id, message.id), true, { }).then(data => this.rest.client.actions.MessageUpdate.handle(data).updated);
content,
}).then(data => {
resolve(this.rest.client.actions.MessageUpdate.handle(data).updated);
}, reject);
});
} }
createChannel(guild, channelName, channelType) { createChannel(guild, channelName, channelType) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('post', Constants.Endpoints.guildChannels(guild.id), true, {
this.rest.makeRequest('post', Constants.Endpoints.guildChannels(guild.id), true, { name: channelName,
name: channelName, type: channelType,
type: channelType, }).then(data => this.rest.client.actions.ChannelCreate.handle(data).channel);
}).then(data => {
resolve(this.rest.client.actions.ChannelCreate.handle(data).channel);
}, reject);
});
}
getExistingDM(recipient) {
return this.rest.client.channels.filter(channel =>
channel.recipient && channel.recipient.id === recipient.id
).first();
} }
createDM(recipient) { createDM(recipient) {
return new Promise((resolve, reject) => { const dmChannel = this.getExistingDM(recipient);
const dmChannel = this.getExistingDM(recipient); if (dmChannel) return Promise.resolve(dmChannel);
if (dmChannel) return resolve(dmChannel); return this.rest.makeRequest('post', Constants.Endpoints.userChannels(this.rest.client.user.id), true, {
return this.rest.makeRequest('post', Constants.Endpoints.userChannels(this.rest.client.user.id), true, { recipient_id: recipient.id,
recipient_id: recipient.id, }).then(data => this.rest.client.actions.ChannelCreate.handle(data).channel);
}).then(data => resolve(this.rest.client.actions.ChannelCreate.handle(data).channel), reject); }
});
getExistingDM(recipient) {
return this.rest.client.channels.find(channel =>
channel.recipient && channel.recipient.id === recipient.id
);
} }
deleteChannel(channel) { deleteChannel(channel) {
return new Promise((resolve, reject) => { if (channel instanceof User || channel instanceof GuildMember) channel = this.getExistingDM(channel);
if (channel instanceof User || channel instanceof GuildMember) channel = this.getExistingDM(channel); if (!channel) return Promise.reject(new Error('No channel to delete.'));
this.rest.makeRequest('del', Constants.Endpoints.channel(channel.id), true).then(data => { return this.rest.makeRequest('del', Constants.Endpoints.channel(channel.id), true).then(data => {
data.id = channel.id; data.id = channel.id;
resolve(this.rest.client.actions.ChannelDelete.handle(data).channel); return this.rest.client.actions.ChannelDelete.handle(data).channel;
}, reject);
}); });
} }
updateChannel(channel, data) { updateChannel(channel, data) {
return new Promise((resolve, reject) => { data.name = (data.name || channel.name).trim();
data.name = (data.name || channel.name).trim(); data.topic = data.topic || channel.topic;
data.topic = data.topic || channel.topic; data.position = data.position || channel.position;
data.position = data.position || channel.position; data.bitrate = data.bitrate || channel.bitrate;
data.bitrate = data.bitrate || channel.bitrate; return this.rest.makeRequest('patch', Constants.Endpoints.channel(channel.id), true, data).then(newData =>
this.rest.client.actions.ChannelUpdate.handle(newData).updated
this.rest.makeRequest('patch', Constants.Endpoints.channel(channel.id), true, data).then(newData => { );
resolve(this.rest.client.actions.ChannelUpdate.handle(newData).updated);
}, reject);
});
} }
leaveGuild(guild) { leaveGuild(guild) {
if (guild.ownerID === this.rest.client.user.id) return this.deleteGuild(guild); if (guild.ownerID === this.rest.client.user.id) return Promise.reject(new Error('Guild is owned by the client.'));
return new Promise((resolve, reject) => { return this.rest.makeRequest('del', Constants.Endpoints.meGuild(guild.id), true).then(() =>
this.rest.makeRequest('del', Constants.Endpoints.meGuild(guild.id), true).then(() => { this.rest.client.actions.GuildDelete.handle({ id: guild.id }).guild
resolve(this.rest.client.actions.GuildDelete.handle({ id: guild.id }).guild); );
}, reject);
});
} }
createGuild(options) { createGuild(options) {
@@ -208,15 +181,23 @@ class RESTMethods {
options.region = options.region || 'us-central'; options.region = options.region || 'us-central';
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.rest.makeRequest('post', Constants.Endpoints.guilds, true, options).then(data => { this.rest.makeRequest('post', Constants.Endpoints.guilds, true, options).then(data => {
if (this.rest.client.guilds.has(data.id)) resolve(this.rest.client.guilds.get(data.id)); if (this.rest.client.guilds.has(data.id)) {
resolve(this.rest.client.guilds.get(data.id));
return;
}
const handleGuild = guild => { const handleGuild = guild => {
if (guild.id === data.id) resolve(guild); if (guild.id === data.id) {
this.rest.client.removeListener('guildCreate', handleGuild); this.rest.client.removeListener('guildCreate', handleGuild);
this.rest.client.clearTimeout(timeout);
resolve(guild);
}
}; };
this.rest.client.on('guildCreate', handleGuild); this.rest.client.on('guildCreate', handleGuild);
this.rest.client.setTimeout(() => {
const timeout = this.rest.client.setTimeout(() => {
this.rest.client.removeListener('guildCreate', handleGuild); this.rest.client.removeListener('guildCreate', handleGuild);
reject(new Error('Took too long to receive guild data')); reject(new Error('Took too long to receive guild data.'));
}, 10000); }, 10000);
}, reject); }, reject);
}); });
@@ -224,151 +205,126 @@ class RESTMethods {
// untested but probably will work // untested but probably will work
deleteGuild(guild) { deleteGuild(guild) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('del', Constants.Endpoints.guild(guild.id), true).then(() =>
this.rest.makeRequest('del', Constants.Endpoints.guild(guild.id), true).then(() => { this.rest.client.actions.GuildDelete.handle({ id: guild.id }).guild
resolve(this.rest.client.actions.GuildDelete.handle({ id: guild.id }).guild); );
}, reject);
});
} }
getUser(userID) { getUser(userID) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('get', Constants.Endpoints.user(userID), true).then(data =>
this.rest.makeRequest('get', Constants.Endpoints.user(userID), true).then(data => { this.rest.client.actions.UserGet.handle(data).user
resolve(this.rest.client.actions.UserGet.handle(data).user); );
}, reject);
});
} }
updateCurrentUser(_data) { updateCurrentUser(_data) {
return new Promise((resolve, reject) => { const user = this.rest.client.user;
const user = this.rest.client.user; const data = {};
data.username = _data.username || user.username;
const data = {}; data.avatar = this.rest.client.resolver.resolveBase64(_data.avatar) || user.avatar;
data.username = _data.username || user.username; if (!user.bot) {
data.avatar = this.rest.client.resolver.resolveBase64(_data.avatar) || user.avatar; data.email = _data.email || user.email;
if (!user.bot) { data.password = this.rest.client.password;
data.email = _data.email || user.email; if (_data.new_password) data.new_password = _data.newPassword;
data.password = this.rest.client.password; }
if (_data.new_password) data.new_password = _data.newPassword; return this.rest.makeRequest('patch', Constants.Endpoints.me, true, data).then(newData =>
} this.rest.client.actions.UserUpdate.handle(newData).updated
);
this.rest.makeRequest('patch', Constants.Endpoints.me, true, data)
.then(newData => resolve(this.rest.client.actions.UserUpdate.handle(newData).updated), reject);
});
} }
updateGuild(guild, _data) { updateGuild(guild, _data) {
return new Promise((resolve, reject) => { const data = {};
const data = {}; if (_data.name) data.name = _data.name;
if (_data.name) data.name = _data.name; if (_data.region) data.region = _data.region;
if (_data.region) data.region = _data.region; if (_data.verificationLevel) data.verification_level = Number(_data.verificationLevel);
if (_data.verificationLevel) data.verification_level = Number(_data.verificationLevel); if (_data.afkChannel) data.afk_channel_id = this.rest.client.resolver.resolveChannel(_data.afkChannel).id;
if (_data.afkChannel) data.afk_channel_id = this.rest.client.resolver.resolveChannel(_data.afkChannel).id; if (_data.afkTimeout) data.afk_timeout = Number(_data.afkTimeout);
if (_data.afkTimeout) data.afk_timeout = Number(_data.afkTimeout); if (_data.icon) data.icon = this.rest.client.resolver.resolveBase64(_data.icon);
if (_data.icon) data.icon = this.rest.client.resolver.resolveBase64(_data.icon); if (_data.owner) data.owner_id = this.rest.client.resolver.resolveUser(_data.owner).id;
if (_data.owner) data.owner_id = this.rest.client.resolver.resolveUser(_data.owner).id; if (_data.splash) data.splash = this.rest.client.resolver.resolveBase64(_data.splash);
if (_data.splash) data.splash = this.rest.client.resolver.resolveBase64(_data.splash); return this.rest.makeRequest('patch', Constants.Endpoints.guild(guild.id), true, data).then(newData =>
this.rest.client.actions.GuildUpdate.handle(newData).updated
this.rest.makeRequest('patch', Constants.Endpoints.guild(guild.id), true, data) );
.then(newData => resolve(this.rest.client.actions.GuildUpdate.handle(newData).updated), reject);
});
} }
kickGuildMember(guild, member) { kickGuildMember(guild, member) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('del', Constants.Endpoints.guildMember(guild.id, member.id), true).then(() =>
this.rest.makeRequest('del', Constants.Endpoints.guildMember(guild.id, member.id), true).then(() => { this.rest.client.actions.GuildMemberRemove.handle({
resolve(this.rest.client.actions.GuildMemberRemove.handle({ guild_id: guild.id,
guild_id: guild.id, user: member.user,
user: member.user, }).member
}).member); );
}, reject);
});
} }
createGuildRole(guild) { createGuildRole(guild) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('post', Constants.Endpoints.guildRoles(guild.id), true).then(role =>
this.rest.makeRequest('post', Constants.Endpoints.guildRoles(guild.id), true).then(role => { this.rest.client.actions.GuildRoleCreate.handle({
resolve(this.rest.client.actions.GuildRoleCreate.handle({ guild_id: guild.id,
guild_id: guild.id, role,
role, }).role
}).role); );
}, reject);
});
} }
deleteGuildRole(role) { deleteGuildRole(role) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('del', Constants.Endpoints.guildRole(role.guild.id, role.id), true).then(() =>
this.rest.makeRequest('del', Constants.Endpoints.guildRole(role.guild.id, role.id), true).then(() => { this.rest.client.actions.GuildRoleDelete.handle({
resolve(this.rest.client.actions.GuildRoleDelete.handle({ guild_id: role.guild.id,
guild_id: role.guild.id, role_id: role.id,
role_id: role.id, }).role
}).role); );
}, reject);
});
} }
setChannelOverwrite(channel, payload) { setChannelOverwrite(channel, payload) {
return new Promise((resolve, reject) => { return this.rest.makeRequest(
this.rest.makeRequest('put', `${Constants.Endpoints.channelPermissions(channel.id)}/${payload.id}`, true, payload) 'put', `${Constants.Endpoints.channelPermissions(channel.id)}/${payload.id}`, true, payload
.then(resolve, reject); );
});
} }
deletePermissionOverwrites(overwrite) { deletePermissionOverwrites(overwrite) {
return new Promise((resolve, reject) => { return this.rest.makeRequest(
const endpoint = `${Constants.Endpoints.channelPermissions(overwrite.channel.id)}/${overwrite.id}`; 'del', `${Constants.Endpoints.channelPermissions(overwrite.channel.id)}/${overwrite.id}`, true
this.rest.makeRequest('del', endpoint, true).then(() => resolve(overwrite), reject); ).then(() => overwrite);
});
} }
getChannelMessages(channel, payload = {}) { getChannelMessages(channel, payload = {}) {
return new Promise((resolve, reject) => { const params = [];
const params = []; if (payload.limit) params.push(`limit=${payload.limit}`);
if (payload.limit) params.push(`limit=${payload.limit}`); if (payload.around) params.push(`around=${payload.around}`);
if (payload.around) params.push(`around=${payload.around}`); else if (payload.before) params.push(`before=${payload.before}`);
else if (payload.before) params.push(`before=${payload.before}`); else if (payload.after) params.push(`after=${payload.after}`);
else if (payload.after) params.push(`after=${payload.after}`);
let endpoint = Constants.Endpoints.channelMessages(channel.id); let endpoint = Constants.Endpoints.channelMessages(channel.id);
if (params.length > 0) endpoint += `?${params.join('&')}`; if (params.length > 0) endpoint += `?${params.join('&')}`;
this.rest.makeRequest('get', endpoint, true).then(resolve, reject); return this.rest.makeRequest('get', endpoint, true);
});
} }
getChannelMessage(channel, messageID) { getChannelMessage(channel, messageID) {
return new Promise((resolve, reject) => { const msg = channel.messages.get(messageID);
const msg = channel.messages.get(messageID); if (msg) return Promise.resolve(msg);
if (msg) return resolve(msg); return this.rest.makeRequest('get', Constants.Endpoints.channelMessage(channel.id, messageID), true);
const endpoint = Constants.Endpoints.channelMessage(channel.id, messageID);
return this.rest.makeRequest('get', endpoint, true).then(resolve, reject);
});
} }
getGuildMember(guild, user) { getGuildMember(guild, user) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('get', Constants.Endpoints.guildMember(guild.id, user.id), true).then(data =>
this.rest.makeRequest('get', Constants.Endpoints.guildMember(guild.id, user.id), true).then(data => { this.rest.client.actions.GuildMemberGet.handle(guild, data).member
resolve(this.rest.client.actions.GuildMemberGet.handle(guild, data).member); );
}, reject);
});
} }
updateGuildMember(member, data) { updateGuildMember(member, data) {
return new Promise((resolve, reject) => { if (data.channel) data.channel_id = this.rest.client.resolver.resolveChannel(data.channel).id;
if (data.channel) data.channel_id = this.rest.client.resolver.resolveChannel(data.channel).id; if (data.roles) data.roles = data.roles.map(role => role instanceof Role ? role.id : role);
if (data.roles) data.roles = data.roles.map(role => role instanceof Role ? role.id : role);
let endpoint = Constants.Endpoints.guildMember(member.guild.id, member.id); let endpoint = Constants.Endpoints.guildMember(member.guild.id, member.id);
// fix your endpoints, discord ;-; // fix your endpoints, discord ;-;
if (member.id === this.rest.client.user.id) { if (member.id === this.rest.client.user.id) {
if (Object.keys(data).length === 1 && Object.keys(data)[0] === 'nick') { const keys = Object.keys(data);
endpoint = Constants.Endpoints.stupidInconsistentGuildEndpoint(member.guild.id); if (keys.length === 1 && keys[0] === 'nick') {
} endpoint = Constants.Endpoints.stupidInconsistentGuildEndpoint(member.guild.id);
} }
}
this.rest.makeRequest('patch', endpoint, true, data) return this.rest.makeRequest('patch', endpoint, true, data).then(newData =>
.then(resData => resolve(member.guild._updateMember(member, resData).mem), reject); member.guild._updateMember(member, newData).mem
}); );
} }
sendTyping(channelID) { sendTyping(channelID) {
@@ -376,26 +332,20 @@ class RESTMethods {
} }
banGuildMember(guild, member, deleteDays = 0) { banGuildMember(guild, member, deleteDays = 0) {
return new Promise((resolve, reject) => { const id = this.rest.client.resolver.resolveUserID(member);
const id = this.rest.client.resolver.resolveUserID(member); if (!id) return Promise.reject(new Error('Couldn\'t resolve the user ID to ban.'));
if (!id) throw new Error('Couldn\'t resolve the user ID to ban.'); return this.rest.makeRequest(
'put', `${Constants.Endpoints.guildBans(guild.id)}/${id}?delete-message-days=${deleteDays}`, true, {
this.rest.makeRequest('put', 'delete-message-days': deleteDays,
`${Constants.Endpoints.guildBans(guild.id)}/${id}?delete-message-days=${deleteDays}`, true, { }
'delete-message-days': deleteDays, ).then(() => {
}).then(() => { if (member instanceof GuildMember) return member;
if (member instanceof GuildMember) { const user = this.rest.client.resolver.resolveUser(id);
resolve(member); if (user) {
return; member = this.rest.client.resolver.resolveGuildMember(guild, user);
} return member || user;
const user = this.rest.client.resolver.resolveUser(id); }
if (user) { return id;
member = this.rest.client.resolver.resolveGuildMember(guild, user);
resolve(member || user);
return;
}
resolve(id);
}, reject);
}); });
} }
@@ -407,71 +357,76 @@ class RESTMethods {
const listener = (eGuild, eUser) => { const listener = (eGuild, eUser) => {
if (eGuild.id === guild.id && eUser.id === id) { if (eGuild.id === guild.id && eUser.id === id) {
this.rest.client.removeListener(Constants.Events.GUILD_BAN_REMOVE, listener); this.rest.client.removeListener(Constants.Events.GUILD_BAN_REMOVE, listener);
this.rest.client.clearTimeout(timeout);
resolve(eUser); resolve(eUser);
} }
}; };
this.rest.client.on(Constants.Events.GUILD_BAN_REMOVE, listener); this.rest.client.on(Constants.Events.GUILD_BAN_REMOVE, listener);
this.rest.makeRequest('del', `${Constants.Endpoints.guildBans(guild.id)}/${id}`, true).catch(reject);
const timeout = this.rest.client.setTimeout(() => {
this.rest.client.removeListener(Constants.Events.GUILD_BAN_REMOVE, listener);
reject(new Error('Took too long to receive the ban remove event.'));
}, 10000);
this.rest.makeRequest('del', `${Constants.Endpoints.guildBans(guild.id)}/${id}`, true).catch(err => {
this.rest.client.removeListener(Constants.Events.GUILD_BAN_REMOVE, listener);
this.rest.client.clearTimeout(timeout);
reject(err);
});
}); });
} }
getGuildBans(guild) { getGuildBans(guild) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('get', Constants.Endpoints.guildBans(guild.id), true).then(banItems => {
this.rest.makeRequest('get', Constants.Endpoints.guildBans(guild.id), true).then(banItems => { const bannedUsers = new Collection();
const bannedUsers = new Collection(); for (const banItem of banItems) {
for (const banItem of banItems) { const user = this.rest.client.dataManager.newUser(banItem.user);
const user = this.rest.client.dataManager.newUser(banItem.user); bannedUsers.set(user.id, user);
bannedUsers.set(user.id, user); }
} return bannedUsers;
resolve(bannedUsers);
}, reject);
}); });
} }
updateGuildRole(role, _data) { updateGuildRole(role, _data) {
return new Promise((resolve, reject) => { const data = {};
const data = {}; data.name = _data.name || role.name;
data.name = _data.name || role.name; data.position = typeof _data.position !== 'undefined' ? _data.position : role.position;
data.position = typeof _data.position !== 'undefined' ? _data.position : role.position; data.color = _data.color || role.color;
data.color = _data.color || role.color; if (typeof data.color === 'string' && data.color.startsWith('#')) {
if (typeof data.color === 'string' && data.color.startsWith('#')) { data.color = parseInt(data.color.replace('#', ''), 16);
data.color = parseInt(data.color.replace('#', ''), 16); }
} data.hoist = typeof _data.hoist !== 'undefined' ? _data.hoist : role.hoist;
data.hoist = typeof _data.hoist !== 'undefined' ? _data.hoist : role.hoist; data.mentionable = typeof _data.mentionable !== 'undefined' ? _data.mentionable : role.mentionable;
data.mentionable = typeof _data.mentionable !== 'undefined' ? _data.mentionable : role.mentionable;
if (_data.permissions) { if (_data.permissions) {
let perms = 0; let perms = 0;
for (let perm of _data.permissions) { for (let perm of _data.permissions) {
if (typeof perm === 'string') perm = Constants.PermissionFlags[perm]; if (typeof perm === 'string') perm = Constants.PermissionFlags[perm];
perms |= perm; perms |= perm;
}
data.permissions = perms;
} else {
data.permissions = role.permissions;
} }
data.permissions = perms;
} else {
data.permissions = role.permissions;
}
this.rest.makeRequest('patch', Constants.Endpoints.guildRole(role.guild.id, role.id), true, data).then(_role => { return this.rest.makeRequest(
resolve(this.rest.client.actions.GuildRoleUpdate.handle({ 'patch', Constants.Endpoints.guildRole(role.guild.id, role.id), true, data
role: _role, ).then(_role =>
guild_id: role.guild.id, this.rest.client.actions.GuildRoleUpdate.handle({
}).updated); role: _role,
}, reject); guild_id: role.guild.id,
}); }).updated
);
} }
pinMessage(message) { pinMessage(message) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('put', `${Constants.Endpoints.channel(message.channel.id)}/pins/${message.id}`, true)
this.rest.makeRequest('put', `${Constants.Endpoints.channel(message.channel.id)}/pins/${message.id}`, true) .then(() => message);
.then(() => resolve(message), reject);
});
} }
unpinMessage(message) { unpinMessage(message) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('del', `${Constants.Endpoints.channel(message.channel.id)}/pins/${message.id}`, true)
this.rest.makeRequest('del', `${Constants.Endpoints.channel(message.channel.id)}/pins/${message.id}`, true) .then(() => message);
.then(() => resolve(message), reject);
});
} }
getChannelPinnedMessages(channel) { getChannelPinnedMessages(channel) {
@@ -479,123 +434,85 @@ class RESTMethods {
} }
createChannelInvite(channel, options) { createChannelInvite(channel, options) {
return new Promise((resolve, reject) => { const payload = {};
const payload = {}; payload.temporary = options.temporary;
payload.temporary = options.temporary; payload.max_age = options.maxAge;
payload.max_age = options.maxAge; payload.max_uses = options.maxUses;
payload.max_uses = options.maxUses; return this.rest.makeRequest('post', `${Constants.Endpoints.channelInvites(channel.id)}`, true, payload)
.then(invite => new Invite(this.rest.client, invite));
this.rest.makeRequest('post', `${Constants.Endpoints.channelInvites(channel.id)}`, true, payload)
.then(invite => resolve(new Invite(this.rest.client, invite)), reject);
});
} }
deleteInvite(invite) { deleteInvite(invite) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('del', Constants.Endpoints.invite(invite.code), true).then(() => invite);
this.rest.makeRequest('del', Constants.Endpoints.invite(invite.code), true)
.then(() => resolve(invite), reject);
});
} }
getInvite(code) { getInvite(code) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('get', Constants.Endpoints.invite(code), true).then(invite =>
this.rest.makeRequest('get', Constants.Endpoints.invite(code), true) new Invite(this.rest.client, invite)
.then(invite => resolve(new Invite(this.rest.client, invite)), reject); );
});
} }
getGuildInvites(guild) { getGuildInvites(guild) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('get', Constants.Endpoints.guildInvites(guild.id), true).then(inviteItems => {
this.rest.makeRequest('get', Constants.Endpoints.guildInvites(guild.id), true).then(inviteItems => { const invites = new Collection();
const invites = new Collection(); for (const inviteItem of inviteItems) {
for (const inviteItem of inviteItems) { const invite = new Invite(this.rest.client, inviteItem);
const invite = new Invite(this.rest.client, inviteItem); invites.set(invite.code, invite);
invites.set(invite.code, invite); }
} return invites;
resolve(invites);
}, reject);
}); });
} }
pruneGuildMembers(guild, days, dry) { pruneGuildMembers(guild, days, dry) {
return new Promise((resolve, reject) => { return this.rest.makeRequest(dry ? 'get' : 'post', `${Constants.Endpoints.guildPrune(guild.id)}?days=${days}`, true)
this.rest.makeRequest(dry ? 'get' : 'post', `${Constants.Endpoints.guildPrune(guild.id)}?days=${days}`, true) .then(data => data.pruned);
.then(data => resolve(data.pruned), reject);
});
} }
createEmoji(guild, image, name) { createEmoji(guild, image, name) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('post', `${Constants.Endpoints.guildEmojis(guild.id)}`, true, { name, image })
this.rest.makeRequest('post', `${Constants.Endpoints.guildEmojis(guild.id)}`, true, { name: name, image: image }) .then(data => this.rest.client.actions.EmojiCreate.handle(data, guild).emoji);
.then(data => {
resolve(this.rest.client.actions.EmojiCreate.handle(data, guild).emoji);
}, reject);
});
} }
deleteEmoji(emoji) { deleteEmoji(emoji) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('delete', `${Constants.Endpoints.guildEmojis(emoji.guild.id)}/${emoji.id}`, true)
this.rest.makeRequest('delete', `${Constants.Endpoints.guildEmojis(emoji.guild.id)}/${emoji.id}`, true) .then(() => this.rest.client.actions.EmojiDelete.handle(emoji).data);
.then(() => {
resolve(this.rest.client.actions.EmojiDelete.handle(emoji).data);
}, reject);
});
} }
getWebhook(id, token) { getWebhook(id, token) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('get', Constants.Endpoints.webhook(id, token), !token).then(data =>
this.rest.makeRequest('get', Constants.Endpoints.webhook(id, token), require('util').isUndefined(token)) new Webhook(this.rest.client, data)
.then(data => { );
resolve(new Webhook(this.rest.client, data));
}, reject);
});
} }
getGuildWebhooks(guild) { getGuildWebhooks(guild) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('get', Constants.Endpoints.guildWebhooks(guild.id), true).then(data => {
this.rest.makeRequest('get', Constants.Endpoints.guildWebhooks(guild.id), true) const hooks = new Collection();
.then(data => { for (const hook of data) hooks.set(hook.id, new Webhook(this.rest.client, hook));
const hooks = new Collection(); return hooks;
for (const hook of data) {
hooks.set(hook.id, new Webhook(this.rest.client, hook));
}
resolve(hooks);
}, reject);
}); });
} }
getChannelWebhooks(channel) { getChannelWebhooks(channel) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('get', Constants.Endpoints.channelWebhooks(channel.id), true).then(data => {
this.rest.makeRequest('get', Constants.Endpoints.channelWebhooks(channel.id), true) const hooks = new Collection();
.then(data => { for (const hook of data) hooks.set(hook.id, new Webhook(this.rest.client, hook));
const hooks = new Collection(); return hooks;
for (const hook of data) {
hooks.set(hook.id, new Webhook(this.rest.client, hook));
}
resolve(hooks);
}, reject);
}); });
} }
createWebhook(channel, name, avatar) { createWebhook(channel, name, avatar) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('post', Constants.Endpoints.channelWebhooks(channel.id), true, { name, avatar })
this.rest.makeRequest('post', Constants.Endpoints.channelWebhooks(channel.id), true, { .then(data => new Webhook(this.rest.client, data));
name,
avatar,
}).then(data => resolve(new Webhook(this.rest.client, data)), reject);
});
} }
editWebhook(webhook, name, avatar) { editWebhook(webhook, name, avatar) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('patch', Constants.Endpoints.webhook(webhook.id, webhook.token), false, {
this.rest.makeRequest('patch', Constants.Endpoints.webhook(webhook.id, webhook.token), false, { name,
name, avatar,
avatar, }).then(data => {
}).then(data => { webhook.name = data.name;
webhook.name = data.name; webhook.avatar = data.avatar;
webhook.avatar = data.avatar; return webhook;
resolve(webhook);
}, reject);
}); });
} }
@@ -604,123 +521,100 @@ class RESTMethods {
} }
sendWebhookMessage(webhook, content, { avatarURL, tts, disableEveryone, embeds } = {}, file = null) { sendWebhookMessage(webhook, content, { avatarURL, tts, disableEveryone, embeds } = {}, file = null) {
return new Promise((resolve, reject) => { if (typeof content !== 'undefined') content = this.rest.client.resolver.resolveString(content);
if (typeof content !== 'undefined') content = this.rest.client.resolver.resolveString(content); if (content) {
if (disableEveryone || (typeof disableEveryone === 'undefined' && this.rest.client.options.disableEveryone)) { if (disableEveryone || (typeof disableEveryone === 'undefined' && this.rest.client.options.disableEveryone)) {
content = content.replace('@everyone', '@\u200beveryone').replace('@here', '@\u200bhere'); content = content.replace(/@(everyone|here)/g, '@\u200b$1');
} }
}
this.rest.makeRequest('post', `${Constants.Endpoints.webhook(webhook.id, webhook.token)}?wait=true`, false, { return this.rest.makeRequest('post', `${Constants.Endpoints.webhook(webhook.id, webhook.token)}?wait=true`, false, {
content: content, username: webhook.name, avatar_url: avatarURL, tts: tts, file: file, embeds: embeds, username: webhook.name,
}).then(data => resolve(data), reject); avatar_url: avatarURL,
content,
tts,
file,
embeds,
}); });
} }
sendSlackWebhookMessage(webhook, body) { sendSlackWebhookMessage(webhook, body) {
return new Promise((resolve, reject) => { return this.rest.makeRequest(
this.rest.makeRequest( 'post', `${Constants.Endpoints.webhook(webhook.id, webhook.token)}/slack?wait=true`, false, body
'post', );
`${Constants.Endpoints.webhook(webhook.id, webhook.token)}/slack?wait=true`,
false,
body
).then(data => resolve(data), reject);
});
}
addFriend(user) {
return new Promise((resolve, reject) => {
this.rest.makeRequest('post', Constants.Endpoints.relationships('@me'), true, {
discriminator: user.discriminator,
username: user.username,
}).then(() => resolve(user), reject);
});
}
removeFriend(user) {
return new Promise((resolve, reject) => {
this.rest.makeRequest('delete', `${Constants.Endpoints.relationships('@me')}/${user.id}`, true)
.then(() => resolve(user), reject);
});
} }
fetchUserProfile(user) { fetchUserProfile(user) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('get', Constants.Endpoints.userProfile(user.id), true).then(data =>
this.rest.makeRequest('get', Constants.Endpoints.userProfile(user.id), true) new UserProfile(user, data)
.then(data => resolve(new UserProfile(user, data)), reject); );
}); }
addFriend(user) {
return this.rest.makeRequest('post', Constants.Endpoints.relationships('@me'), true, {
username: user.username,
discriminator: user.discriminator,
}).then(() => user);
}
removeFriend(user) {
return this.rest.makeRequest('delete', `${Constants.Endpoints.relationships('@me')}/${user.id}`, true)
.then(() => user);
} }
blockUser(user) { blockUser(user) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('put', `${Constants.Endpoints.relationships('@me')}/${user.id}`, true, { type: 2 })
this.rest.makeRequest('put', `${Constants.Endpoints.relationships('@me')}/${user.id}`, true, { type: 2 }) .then(() => user);
.then(() => resolve(user), reject);
});
} }
unblockUser(user) { unblockUser(user) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('delete', `${Constants.Endpoints.relationships('@me')}/${user.id}`, true)
this.rest.makeRequest('delete', `${Constants.Endpoints.relationships('@me')}/${user.id}`, true) .then(() => user);
.then(() => resolve(user), reject);
});
} }
setRolePositions(guildID, roles) { setRolePositions(guildID, roles) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('patch', Constants.Endpoints.guildRoles(guildID), true, roles).then(() =>
this.rest.makeRequest('patch', Constants.Endpoints.guildRoles(guildID), true, roles) this.rest.client.actions.GuildRolesPositionUpdate.handle({
.then(() => { guild_id: guildID,
resolve(this.rest.client.actions.GuildRolesPositionUpdate.handle({ roles,
guild_id: guildID, }).guild
roles, );
}).guild);
}, reject);
});
} }
addMessageReaction(channelID, messageID, emoji) { addMessageReaction(channelID, messageID, emoji) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('put', Constants.Endpoints.selfMessageReaction(channelID, messageID, emoji), true)
this.rest.makeRequest('put', Constants.Endpoints.selfMessageReaction(channelID, messageID, emoji), true) .then(() =>
.then(() => { this.rest.client.actions.MessageReactionAdd.handle({
resolve(this.rest.client.actions.MessageReactionAdd.handle({ user_id: this.rest.client.user.id,
user_id: this.rest.client.user.id, message_id: messageID,
message_id: messageID, emoji: parseEmoji(emoji),
emoji: parseEmoji(emoji), channel_id: channelID,
channel_id: channelID, }).reaction
}).reaction); );
}, reject);
});
} }
removeMessageReaction(channelID, messageID, emoji, userID) { removeMessageReaction(channelID, messageID, emoji, userID) {
return new Promise((resolve, reject) => { let endpoint = Constants.Endpoints.selfMessageReaction(channelID, messageID, emoji);
let endpoint = Constants.Endpoints.selfMessageReaction(channelID, messageID, emoji); if (userID !== this.rest.client.user.id) {
if (userID !== this.rest.client.user.id) { endpoint = Constants.Endpoints.userMessageReaction(channelID, messageID, emoji, null, userID);
endpoint = Constants.Endpoints.userMessageReaction(channelID, messageID, emoji, null, userID); }
} return this.rest.makeRequest('delete', endpoint, true).then(() =>
this.rest.makeRequest('delete', endpoint, true) this.rest.client.actions.MessageReactionRemove.handle({
.then(() => { user_id: userID,
resolve(this.rest.client.actions.MessageReactionRemove.handle({ message_id: messageID,
user_id: userID, emoji: parseEmoji(emoji),
message_id: messageID, channel_id: channelID,
emoji: parseEmoji(emoji), }).reaction
channel_id: channelID, );
}).reaction);
}, reject);
});
} }
getMessageReactionUsers(channelID, messageID, emoji, limit = 100) { getMessageReactionUsers(channelID, messageID, emoji, limit = 100) {
return new Promise((resolve, reject) => { return this.rest.makeRequest('get', Constants.Endpoints.messageReaction(channelID, messageID, emoji, limit), true);
this.rest.makeRequest('get', Constants.Endpoints.messageReaction(channelID, messageID, emoji, limit), true)
.then(resolve, reject);
});
} }
getMyApp() { getMyApp() {
return new Promise((resolve, reject) => { return this.rest.makeRequest('get', Constants.Endpoints.myApp, true).then(app =>
this.rest.makeRequest('get', Constants.Endpoints.myApp, true) new ClientOAuth2App(this.rest.client, app)
.then(app => resolve(new ClientOAuth2App(this.rest.client, app)), reject); );
});
} }
} }

View File

@@ -105,19 +105,17 @@ class ShardingManager extends EventEmitter {
* @returns {Promise<Collection<number, Shard>>} * @returns {Promise<Collection<number, Shard>>}
*/ */
spawn(amount = this.totalShards, delay = 5500) { spawn(amount = this.totalShards, delay = 5500) {
return new Promise((resolve, reject) => { if (amount === 'auto') {
if (amount === 'auto') { return fetchRecommendedShards(this.token).then(count => {
fetchRecommendedShards(this.token).then(count => { this.totalShards = count;
this.totalShards = count; return this._spawn(count, delay);
resolve(this._spawn(count, delay)); });
}, reject); } else {
} else { if (typeof amount !== 'number' || isNaN(amount)) throw new TypeError('Amount of shards must be a number.');
if (typeof amount !== 'number' || isNaN(amount)) throw new TypeError('Amount of shards must be a number.'); if (amount < 1) throw new RangeError('Amount of shards must be at least 1.');
if (amount < 1) throw new RangeError('Amount of shards must be at least 1.'); if (amount !== Math.floor(amount)) throw new TypeError('Amount of shards must be an integer.');
if (amount !== Math.floor(amount)) throw new TypeError('Amount of shards must be an integer.'); return this._spawn(amount, delay);
resolve(this._spawn(amount, delay)); }
}
});
} }
/** /**

View File

@@ -90,7 +90,7 @@ class ClientUser extends User {
/** /**
* Set the avatar of the logged in Client. * Set the avatar of the logged in Client.
* @param {FileResolvable|Base64Resolveable} avatar The new avatar * @param {FileResolvable|Base64Resolvable} avatar The new avatar
* @returns {Promise<ClientUser>} * @returns {Promise<ClientUser>}
* @example * @example
* // set avatar * // set avatar
@@ -99,15 +99,13 @@ class ClientUser extends User {
* .catch(console.error); * .catch(console.error);
*/ */
setAvatar(avatar) { setAvatar(avatar) {
return new Promise(resolve => { if (avatar.startsWith('data:')) {
if (avatar.startsWith('data:')) { return this.client.rest.methods.updateCurrentUser({ avatar });
resolve(this.client.rest.methods.updateCurrentUser({ avatar })); } else {
} else { return this.client.resolver.resolveFile(avatar).then(data =>
this.client.resolver.resolveFile(avatar).then(data => { this.client.rest.methods.updateCurrentUser({ avatar: data })
resolve(this.client.rest.methods.updateCurrentUser({ avatar: data })); );
}); }
}
});
} }
/** /**
@@ -172,16 +170,14 @@ class ClientUser extends User {
* @returns {Promise<Guild>} The guild that was created * @returns {Promise<Guild>} The guild that was created
*/ */
createGuild(name, region, icon = null) { createGuild(name, region, icon = null) {
return new Promise(resolve => { if (!icon) return this.client.rest.methods.createGuild({ name, icon, region });
if (!icon) resolve(this.client.rest.methods.createGuild({ name, icon, region })); if (icon.startsWith('data:')) {
if (icon.startsWith('data:')) { return this.client.rest.methods.createGuild({ name, icon, region });
resolve(this.client.rest.methods.createGuild({ name, icon, region })); } else {
} else { return this.client.resolver.resolveFile(icon).then(data =>
this.client.resolver.resolveFile(icon).then(data => { this.client.rest.methods.createGuild({ name, icon: data, region })
resolve(this.client.rest.methods.createGuild({ name, icon: data, region })); );
}); }
}
});
} }
/** /**

View File

@@ -582,7 +582,7 @@ class Guild {
/** /**
* Creates a new custom emoji in the guild. * Creates a new custom emoji in the guild.
* @param {FileResolveable} attachment The image for the emoji. * @param {FileResolvable} attachment The image for the emoji.
* @param {string} name The name for the emoji. * @param {string} name The name for the emoji.
* @returns {Promise<Emoji>} The created emoji. * @returns {Promise<Emoji>} The created emoji.
* @example * @example
@@ -597,13 +597,10 @@ class Guild {
* .catch(console.error); * .catch(console.error);
*/ */
createEmoji(attachment, name) { createEmoji(attachment, name) {
return new Promise((resolve, reject) => { return this.client.resolver.resolveFile(attachment).then(file => {
this.client.resolver.resolveFile(attachment).then(file => { let base64 = new Buffer(file, 'binary').toString('base64');
let base64 = new Buffer(file, 'binary').toString('base64'); let dataURI = `data:;base64,${base64}`;
let dataURI = `data:;base64,${base64}`; return this.client.rest.methods.createEmoji(this, dataURI, name);
this.client.rest.methods.createEmoji(this, dataURI, name)
.then(resolve).catch(reject);
}).catch(reject);
}); });
} }

View File

@@ -1,54 +1,6 @@
const Collection = require('../util/Collection'); const Collection = require('../util/Collection');
const Emoji = require('./Emoji'); const Emoji = require('./Emoji');
/**
* Represents a limited emoji set used for both custom and unicode emojis. Custom emojis
* will use this class opposed to the Emoji class when the client doesn't know enough
* information about them.
*/
class ReactionEmoji {
constructor(reaction, name, id) {
/**
* The message reaction this emoji refers to
* @type {MessageReaction}
*/
this.reaction = reaction;
/**
* The name of this reaction emoji.
* @type {string}
*/
this.name = name;
/**
* The ID of this reaction emoji.
* @type {string}
*/
this.id = id;
}
/**
* The identifier of this emoji, used for message reactions
* @readonly
* @type {string}
*/
get identifier() {
if (this.id) {
return `${this.name}:${this.id}`;
}
return encodeURIComponent(this.name);
}
/**
* Creates the text required to form a graphical emoji on Discord.
* @example
* // send the emoji used in a reaction to the channel the reaction is part of
* reaction.message.channel.sendMessage(`The emoji used is ${reaction.emoji}`);
* @returns {string}
*/
toString() {
return this.id ? `<:${this.name}:${this.id}>` : this.name;
}
}
/** /**
* Represents a reaction to a message * Represents a reaction to a message
*/ */
@@ -59,22 +11,26 @@ class MessageReaction {
* @type {Message} * @type {Message}
*/ */
this.message = message; this.message = message;
/** /**
* Whether the client has given this reaction * Whether the client has given this reaction
* @type {boolean} * @type {boolean}
*/ */
this.me = me; this.me = me;
this._emoji = new ReactionEmoji(this, emoji.name, emoji.id);
/** /**
* The number of people that have given the same reaction. * The number of people that have given the same reaction.
* @type {number} * @type {number}
*/ */
this.count = count || 0; this.count = count || 0;
/** /**
* The users that have given this reaction, mapped by their ID. * The users that have given this reaction, mapped by their ID.
* @type {Collection<string, User>} * @type {Collection<string, User>}
*/ */
this.users = new Collection(); this.users = new Collection();
this._emoji = new ReactionEmoji(this, emoji.name, emoji.id);
} }
/** /**
@@ -83,9 +39,7 @@ class MessageReaction {
* @type {Emoji|ReactionEmoji} * @type {Emoji|ReactionEmoji}
*/ */
get emoji() { get emoji() {
if (this._emoji instanceof Emoji) { if (this._emoji instanceof Emoji) return this._emoji;
return this._emoji;
}
// check to see if the emoji has become known to the client // check to see if the emoji has become known to the client
if (this._emoji.id) { if (this._emoji.id) {
const emojis = this.message.client.emojis; const emojis = this.message.client.emojis;
@@ -106,11 +60,10 @@ class MessageReaction {
remove(user = this.message.client.user) { remove(user = this.message.client.user) {
const message = this.message; const message = this.message;
user = this.message.client.resolver.resolveUserID(user); user = this.message.client.resolver.resolveUserID(user);
if (!user) return Promise.reject('Couldn\'t resolve the user ID to remove from the reaction.');
if (!user) return Promise.reject('A UserIDResolvable is required (string, user, member, message, guild)');
return message.client.rest.methods.removeMessageReaction( return message.client.rest.methods.removeMessageReaction(
message.channel.id, message.id, this.emoji.identifier, user); message.channel.id, message.id, this.emoji.identifier, user
);
} }
/** /**
@@ -121,19 +74,66 @@ class MessageReaction {
*/ */
fetchUsers(limit = 100) { fetchUsers(limit = 100) {
const message = this.message; const message = this.message;
return new Promise((resolve, reject) => { return message.client.rest.methods.getMessageReactionUsers(
message.client.rest.methods.getMessageReactionUsers(message.channel.id, message.id, this.emoji.identifier, limit) message.channel.id, message.id, this.emoji.identifier, limit
.then(users => { ).then(users => {
this.users = new Collection(); this.users = new Collection();
for (const rawUser of users) { for (const rawUser of users) {
const user = this.message.client.dataManager.newUser(rawUser); const user = this.message.client.dataManager.newUser(rawUser);
this.users.set(user.id, user); this.users.set(user.id, user);
} }
this.count = this.users.size; this.count = this.users.size;
resolve(this.users); return users;
}, reject);
}); });
} }
} }
/**
* Represents a limited emoji set used for both custom and unicode emojis. Custom emojis
* will use this class opposed to the Emoji class when the client doesn't know enough
* information about them.
*/
class ReactionEmoji {
constructor(reaction, name, id) {
/**
* The message reaction this emoji refers to
* @type {MessageReaction}
*/
this.reaction = reaction;
/**
* The name of this reaction emoji.
* @type {string}
*/
this.name = name;
/**
* The ID of this reaction emoji.
* @type {string}
*/
this.id = id;
}
/**
* The identifier of this emoji, used for message reactions
* @readonly
* @type {string}
*/
get identifier() {
if (this.id) return `${this.name}:${this.id}`;
return encodeURIComponent(this.name);
}
/**
* Creates the text required to form a graphical emoji on Discord.
* @example
* // send the emoji used in a reaction to the channel the reaction is part of
* reaction.message.channel.sendMessage(`The emoji used is ${reaction.emoji}`);
* @returns {string}
*/
toString() {
return this.id ? `<:${this.name}:${this.id}>` : this.name;
}
}
module.exports = MessageReaction; module.exports = MessageReaction;

View File

@@ -61,17 +61,14 @@ class TextChannel extends GuildChannel {
* .catch(console.error) * .catch(console.error)
*/ */
createWebhook(name, avatar) { createWebhook(name, avatar) {
return new Promise((resolve, reject) => { if (avatar) {
if (avatar) { return this.client.resolver.resolveFile(avatar).then(file => {
this.client.resolver.resolveFile(avatar).then(file => { let base64 = new Buffer(file, 'binary').toString('base64');
let base64 = new Buffer(file, 'binary').toString('base64'); let dataURI = `data:;base64,${base64}`;
let dataURI = `data:;base64,${base64}`; return this.client.rest.methods.createWebhook(this, name, dataURI);
resolve(this.client.rest.methods.createWebhook(this, name, dataURI)); });
}, reject); }
} else { return this.client.rest.methods.createWebhook(this, name);
resolve(this.client.rest.methods.createWebhook(this, name));
}
});
} }
// These are here only for documentation purposes - they are implemented by TextBasedChannel // These are here only for documentation purposes - they are implemented by TextBasedChannel

View File

@@ -143,14 +143,12 @@ class Webhook {
fileName = 'file.jpg'; fileName = 'file.jpg';
} }
} }
return new Promise((resolve, reject) => { return this.client.resolver.resolveFile(attachment).then(file =>
this.client.resolver.resolveFile(attachment).then(file => { this.client.rest.methods.sendWebhookMessage(this, content, options, {
resolve(this.client.rest.methods.sendWebhookMessage(this, content, options, { file,
file, name: fileName,
name: fileName, })
})); );
}, reject);
});
} }
/** /**
@@ -177,18 +175,15 @@ class Webhook {
* @returns {Promise<Webhook>} * @returns {Promise<Webhook>}
*/ */
edit(name = this.name, avatar) { edit(name = this.name, avatar) {
return new Promise((resolve, reject) => { if (avatar) {
if (avatar) { return this.client.resolver.resolveFile(avatar).then(file => {
this.client.resolver.resolveFile(avatar).then(file => { const dataURI = this.client.resolver.resolveBase64(file);
const dataURI = this.client.resolver.resolveBase64(file); return this.client.rest.methods.editWebhook(this, name, dataURI);
resolve(this.client.rest.methods.editWebhook(this, name, dataURI)); });
}, reject); }
} else { return this.client.rest.methods.editWebhook(this, name).then(data => {
this.client.rest.methods.editWebhook(this, name).then(data => { this.setup(data);
this.setup(data); return this;
resolve(this);
}, reject);
}
}); });
} }

View File

@@ -92,14 +92,12 @@ class TextBasedChannel {
fileName = 'file.jpg'; fileName = 'file.jpg';
} }
} }
return new Promise((resolve, reject) => { return this.client.resolver.resolveFile(attachment).then(file =>
this.client.resolver.resolveFile(attachment).then(file => { this.client.rest.methods.sendMessage(this, content, options, {
this.client.rest.methods.sendMessage(this, content, options, { file,
file, name: fileName,
name: fileName, })
}).then(resolve, reject); );
}, reject);
});
} }
/** /**
@@ -131,14 +129,10 @@ class TextBasedChannel {
* .catch(console.error); * .catch(console.error);
*/ */
fetchMessage(messageID) { fetchMessage(messageID) {
return new Promise((resolve, reject) => { return this.client.rest.methods.getChannelMessage(this, messageID).then(data => {
this.client.rest.methods.getChannelMessage(this, messageID).then(data => { const msg = data instanceof Message ? data : new Message(this, data, this.client);
let msg = data; this._cacheMessage(msg);
if (!(msg instanceof Message)) msg = new Message(this, data, this.client); return msg;
this._cacheMessage(msg);
resolve(msg);
}, reject);
}); });
} }
@@ -163,16 +157,14 @@ class TextBasedChannel {
* .catch(console.error); * .catch(console.error);
*/ */
fetchMessages(options = {}) { fetchMessages(options = {}) {
return new Promise((resolve, reject) => { return this.client.rest.methods.getChannelMessages(this, options).then(data => {
this.client.rest.methods.getChannelMessages(this, options).then(data => { const messages = new Collection();
const messages = new Collection(); for (const message of data) {
for (const message of data) { const msg = new Message(this, message, this.client);
const msg = new Message(this, message, this.client); messages.set(message.id, msg);
messages.set(message.id, msg); this._cacheMessage(msg);
this._cacheMessage(msg); }
} return messages;
resolve(messages);
}, reject);
}); });
} }
@@ -181,16 +173,14 @@ class TextBasedChannel {
* @returns {Promise<Collection<string, Message>>} * @returns {Promise<Collection<string, Message>>}
*/ */
fetchPinnedMessages() { fetchPinnedMessages() {
return new Promise((resolve, reject) => { return this.client.rest.methods.getChannelPinnedMessages(this).then(data => {
this.client.rest.methods.getChannelPinnedMessages(this).then(data => { const messages = new Collection();
const messages = new Collection(); for (const message of data) {
for (const message of data) { const msg = new Message(this, message, this.client);
const msg = new Message(this, message, this.client); messages.set(message.id, msg);
messages.set(message.id, msg); this._cacheMessage(msg);
this._cacheMessage(msg); }
} return messages;
resolve(messages);
}, reject);
}); });
} }
@@ -317,16 +307,12 @@ class TextBasedChannel {
* @returns {Promise<Collection<string, Message>>} Deleted messages * @returns {Promise<Collection<string, Message>>} Deleted messages
*/ */
bulkDelete(messages) { bulkDelete(messages) {
return new Promise((resolve, reject) => { if (!isNaN(messages)) return this.fetchMessages({ limit: messages }).then(msgs => this.bulkDelete(msgs));
if (!isNaN(messages)) { if (messages instanceof Array || messages instanceof Collection) {
this.fetchMessages({ limit: messages }).then(msgs => resolve(this.bulkDelete(msgs))); const messageIDs = messages instanceof Collection ? messages.keyArray() : messages.map(m => m.id);
} else if (messages instanceof Array || messages instanceof Collection) { return this.client.rest.methods.bulkDeleteMessages(this, messageIDs);
const messageIDs = messages instanceof Collection ? messages.keyArray() : messages.map(m => m.id); }
resolve(this.client.rest.methods.bulkDeleteMessages(this, messageIDs)); throw new TypeError('The messages must be an Array, Collection, or number.');
} else {
reject(new TypeError('Messages must be an Array, Collection, or number.'));
}
});
} }
_cacheMessage(message) { _cacheMessage(message) {