Organise structure methods

This commit is contained in:
Schuyler Cebulskie
2016-09-07 02:07:39 -04:00
parent 73cb34ed37
commit 818649b94f
13 changed files with 493 additions and 577 deletions

File diff suppressed because one or more lines are too long

View File

@@ -37,61 +37,21 @@ class DMChannel extends Channel {
return this.recipient.toString();
}
sendMessage() {
return;
}
sendTTSMessage() {
return;
}
sendFile() {
return;
}
_cacheMessage() {
return;
}
fetchMessages() {
return;
}
fetchMessage() {
return;
}
bulkDelete() {
return;
}
startTyping() {
return;
}
stopTyping() {
return;
}
get typing() {
return;
}
get typingCount() {
return;
}
fetchPinnedMessages() {
return;
}
createCollector() {
return;
}
awaitMessages() {
return;
}
// These are here only for documentation purposes - they are implemented by TextBasedChannel
sendMessage() { return; }
sendTTSMessage() { return; }
sendFile() { return; }
fetchMessage() { return; }
fetchMessages() { return; }
fetchPinnedMessages() { return; }
startTyping() { return; }
stopTyping() { return; }
get typing() { return; }
get typingCount() { return; }
createCollector() { return; }
awaitMessages() { return; }
bulkDelete() { return; }
_cacheMessage() { return; }
}
TextBasedChannel.applyToClass(DMChannel, true);

View File

@@ -77,77 +77,58 @@ class GroupDMChannel extends Channel {
this._typing = new Map();
}
equals(other) {
const equal = other &&
this.id === other.id &&
this.name === other.name &&
this.icon === other.icon &&
this.owner.id === other.owner_id;
/**
* Whether this channel equals another channel. It compares all properties, so for most operations
* it is advisable to just compare `channel.id === channel2.id` as it is much faster and is often
* what most users need.
* @param {GroupDMChannel} channel The channel to compare to
* @returns {boolean}
*/
equals(channel) {
const equal = channel &&
this.id === channel.id &&
this.name === channel.name &&
this.icon === channel.icon &&
this.owner.id === channel.owner_id;
if (equal) {
const thisIDs = this.recipients.array().map(r => r.id);
const otherIDs = other.recipients.map(r => r.id);
const otherIDs = channel.recipients.map(r => r.id);
return arraysEqual(thisIDs, otherIDs);
}
return equal;
}
sendMessage() {
return;
/**
* When concatenated with a string, this automatically concatenates the Channel's name instead of the Channel object.
* @returns {string}
* @example
* // logs: Hello from My Group DM!
* console.log(`Hello from ${channel}!`);
* @example
* // logs: Hello from My Group DM!
* console.log(`Hello from ' + channel + '!');
*/
toString() {
return this.name;
}
sendTTSMessage() {
return;
}
sendFile() {
return;
}
_cacheMessage() {
return;
}
fetchMessages() {
return;
}
fetchMessage() {
return;
}
bulkDelete() {
return;
}
startTyping() {
return;
}
stopTyping() {
return;
}
get typing() {
return;
}
get typingCount() {
return;
}
fetchPinnedMessages() {
return;
}
createCollector() {
return;
}
awaitMessages() {
return;
}
// These are here only for documentation purposes - they are implemented by TextBasedChannel
sendMessage() { return; }
sendTTSMessage() { return; }
sendFile() { return; }
fetchMessage() { return; }
fetchMessages() { return; }
fetchPinnedMessages() { return; }
startTyping() { return; }
stopTyping() { return; }
get typing() { return; }
get typingCount() { return; }
createCollector() { return; }
awaitMessages() { return; }
bulkDelete() { return; }
_cacheMessage() { return; }
}
TextBasedChannel.applyToClass(GroupDMChannel, true);

View File

@@ -190,151 +190,6 @@ class Guild {
}
}
_checkChunks() {
if (this._fetchWaiter) {
if (this.members.size === this.memberCount) {
this._fetchWaiter(this);
this._fetchWaiter = null;
}
}
}
_addMember(guildUser, noEvent) {
if (!(guildUser.user instanceof User)) guildUser.user = this.client.dataManager.newUser(guildUser.user);
guildUser.joined_at = guildUser.joined_at || 0;
const member = new GuildMember(this, guildUser);
this.members.set(member.id, member);
if (this._rawVoiceStates && this._rawVoiceStates.get(member.user.id)) {
const voiceState = this._rawVoiceStates.get(member.user.id);
member.serverMute = voiceState.mute;
member.serverDeaf = voiceState.deaf;
member.selfMute = voiceState.self_mute;
member.selfDeaf = voiceState.self_deaf;
member.voiceSessionID = voiceState.session_id;
member.voiceChannelID = voiceState.channel_id;
this.channels.get(voiceState.channel_id).members.set(member.user.id, member);
}
/**
* Emitted whenever a user joins a guild.
* @event Client#guildMemberAdd
* @param {Guild} guild The guild that the user has joined
* @param {GuildMember} member The member that has joined
*/
if (this.client.ws.status === Constants.Status.READY && !noEvent) {
this.client.emit(Constants.Events.GUILD_MEMBER_ADD, this, member);
}
this._checkChunks();
return member;
}
_updateMember(member, data) {
const oldMember = cloneObject(member);
if (data.roles) member._roles = data.roles;
else member.nickname = data.nick;
const notSame = member.nickname !== oldMember.nickname && !arraysEqual(member._roles, oldMember._roles);
if (this.client.ws.status === Constants.Status.READY && notSame) {
/**
* Emitted whenever a Guild Member changes - i.e. new role, removed role, nickname
* @event Client#guildMemberUpdate
* @param {Guild} guild The guild that the update affects
* @param {GuildMember} oldMember The member before the update
* @param {GuildMember} newMember The member after the update
*/
this.client.emit(Constants.Events.GUILD_MEMBER_UPDATE, this, oldMember, member);
}
return {
old: oldMember,
mem: member,
};
}
_removeMember(guildMember) {
this.members.delete(guildMember.id);
this._checkChunks();
}
/**
* When concatenated with a string, this automatically concatenates the Guild's name instead of the Guild object.
* @returns {string}
* @example
* // logs: Hello from My Guild!
* console.log(`Hello from ${guild}!`);
* @example
* // logs: Hello from My Guild!
* console.log(`Hello from ' + guild + '!');
*/
toString() {
return this.name;
}
/**
* Returns the GuildMember form of a User object, if the User is present in the guild.
* @param {UserResolvable} user The user that you want to obtain the GuildMember of
* @returns {?GuildMember}
* @example
* // get the guild member of a user
* const member = guild.member(message.author);
*/
member(user) {
return this.client.resolver.resolveGuildMember(this, user);
}
/**
* Whether this Guild equals another Guild. It compares all properties, so for most operations
* it is advisable to just compare `guild.id === guild2.id` as it is much faster and is often
* what most users need.
* @param {Guild} guild The guild to compare
* @returns {boolean}
*/
equals(guild) {
let equal =
guild &&
this.id === guild.id &&
this.available === !guild.unavailable &&
this.splash === guild.splash &&
this.region === guild.region &&
this.name === guild.name &&
this.memberCount === guild.member_count &&
this.large === guild.large &&
this.icon === guild.icon &&
arraysEqual(this.features, guild.features) &&
this.ownerID === guild.owner_id &&
this.verificationLevel === guild.verification_level &&
this.embedEnabled === guild.embed_enabled;
if (equal) {
if (this.embedChannel) {
if (this.embedChannel.id !== guild.embed_channel_id) equal = false;
} else if (guild.embed_channel_id) {
equal = false;
}
}
return equal;
}
_memberSpeakUpdate(user, speaking) {
const member = this.members.get(user);
if (member && member.speaking !== speaking) {
member.speaking = speaking;
/**
* Emitted once a Guild Member starts/stops speaking
* @event Client#guildMemberSpeaking
* @param {GuildMember} member The member that started/stopped speaking
* @param {boolean} speaking Whether or not the member is speaking
*/
this.client.emit(Constants.Events.GUILD_MEMBER_SPEAKING, member, speaking);
}
}
/**
* The time the guild was created
* @readonly
@@ -353,65 +208,22 @@ class Guild {
}
/**
* Creates a new Channel in the Guild.
* @param {string} name The name of the new channel
* @param {string} type The type of the new channel, either `text` or `voice`
* @returns {Promise<TextChannel|VoiceChannel>}
* @example
* // create a new text channel
* guild.createChannel('new general', 'text')
* .then(channel => console.log(`Created new channel ${channel}`))
* .catch(console.log);
* Gets the URL to this guild's icon (if it has one, otherwise it returns null)
* @type {?string}
* @readonly
*/
createChannel(name, type) {
return this.client.rest.methods.createChannel(this, name, type);
get iconURL() {
if (!this.icon) return null;
return Constants.Endpoints.guildIcon(this.id, this.icon);
}
/**
* Creates a new role in the guild, and optionally updates it with the given information.
* @param {RoleData} [data] The data to update the role with
* @returns {Promise<Role>}
* @example
* // create a new role
* guild.createRole()
* .then(role => console.log(`Created role ${role}`))
* .catch(console.log);
* @example
* // create a new role with data
* guild.createRole({ name: 'Super Cool People' })
* .then(role => console.log(`Created role ${role}`))
* .catch(console.log)
* The owner of the Guild
* @type {GuildMember}
* @readonly
*/
createRole(data) {
const create = this.client.rest.methods.createGuildRole(this);
if (!data) return create;
return create.then(role => role.edit(data));
}
/**
* Causes the Client to leave the guild.
* @returns {Promise<Guild>}
* @example
* // leave a guild
* guild.leave()
* .then(g => console.log(`Left the guild ${g}`))
* .catch(console.log);
*/
leave() {
return this.client.rest.methods.leaveGuild(this);
}
/**
* Causes the Client to delete the guild.
* @returns {Promise<Guild>}
* @example
* // delete a guild
* guild.delete()
* .then(g => console.log(`Deleted the guild ${g}`))
* .catch(console.log);
*/
delete() {
return this.client.rest.methods.deleteGuild(this);
get owner() {
return this.members.get(this.ownerID);
}
/**
@@ -543,6 +355,18 @@ class Guild {
return this.edit({ splash });
}
/**
* Returns the GuildMember form of a User object, if the User is present in the guild.
* @param {UserResolvable} user The user that you want to obtain the GuildMember of
* @returns {?GuildMember}
* @example
* // get the guild member of a user
* const member = guild.member(message.author);
*/
member(user) {
return this.client.resolver.resolveGuildMember(this, user);
}
/**
* Bans a user from the guild.
* @param {UserResolvable} user The user to ban
@@ -627,30 +451,204 @@ class Guild {
}
/**
* Gets the URL to this guild's icon (if it has one, otherwise it returns null)
* @type {?string}
* @readonly
* Creates a new Channel in the Guild.
* @param {string} name The name of the new channel
* @param {string} type The type of the new channel, either `text` or `voice`
* @returns {Promise<TextChannel|VoiceChannel>}
* @example
* // create a new text channel
* guild.createChannel('new general', 'text')
* .then(channel => console.log(`Created new channel ${channel}`))
* .catch(console.log);
*/
get iconURL() {
if (!this.icon) return null;
return Constants.Endpoints.guildIcon(this.id, this.icon);
createChannel(name, type) {
return this.client.rest.methods.createChannel(this, name, type);
}
/**
* The owner of the Guild
* @type {GuildMember}
* @readonly
* Creates a new role in the guild, and optionally updates it with the given information.
* @param {RoleData} [data] The data to update the role with
* @returns {Promise<Role>}
* @example
* // create a new role
* guild.createRole()
* .then(role => console.log(`Created role ${role}`))
* .catch(console.log);
* @example
* // create a new role with data
* guild.createRole({ name: 'Super Cool People' })
* .then(role => console.log(`Created role ${role}`))
* .catch(console.log)
*/
get owner() {
return this.members.get(this.ownerID);
createRole(data) {
const create = this.client.rest.methods.createGuildRole(this);
if (!data) return create;
return create.then(role => role.edit(data));
}
/**
* Causes the Client to leave the guild.
* @returns {Promise<Guild>}
* @example
* // leave a guild
* guild.leave()
* .then(g => console.log(`Left the guild ${g}`))
* .catch(console.log);
*/
leave() {
return this.client.rest.methods.leaveGuild(this);
}
/**
* Causes the Client to delete the guild.
* @returns {Promise<Guild>}
* @example
* // delete a guild
* guild.delete()
* .then(g => console.log(`Deleted the guild ${g}`))
* .catch(console.log);
*/
delete() {
return this.client.rest.methods.deleteGuild(this);
}
/**
* Syncs this guild (already done automatically every 30 seconds). Only applicable to user accounts.
*/
sync() {
if (!this.client.user.bot) {
this.client.syncGuilds([this]);
if (!this.client.user.bot) this.client.syncGuilds([this]);
}
/**
* Whether this Guild equals another Guild. It compares all properties, so for most operations
* it is advisable to just compare `guild.id === guild2.id` as it is much faster and is often
* what most users need.
* @param {Guild} guild The guild to compare
* @returns {boolean}
*/
equals(guild) {
let equal =
guild &&
this.id === guild.id &&
this.available === !guild.unavailable &&
this.splash === guild.splash &&
this.region === guild.region &&
this.name === guild.name &&
this.memberCount === guild.member_count &&
this.large === guild.large &&
this.icon === guild.icon &&
arraysEqual(this.features, guild.features) &&
this.ownerID === guild.owner_id &&
this.verificationLevel === guild.verification_level &&
this.embedEnabled === guild.embed_enabled;
if (equal) {
if (this.embedChannel) {
if (this.embedChannel.id !== guild.embed_channel_id) equal = false;
} else if (guild.embed_channel_id) {
equal = false;
}
}
return equal;
}
/**
* When concatenated with a string, this automatically concatenates the Guild's name instead of the Guild object.
* @returns {string}
* @example
* // logs: Hello from My Guild!
* console.log(`Hello from ${guild}!`);
* @example
* // logs: Hello from My Guild!
* console.log(`Hello from ' + guild + '!');
*/
toString() {
return this.name;
}
_addMember(guildUser, noEvent) {
if (!(guildUser.user instanceof User)) guildUser.user = this.client.dataManager.newUser(guildUser.user);
guildUser.joined_at = guildUser.joined_at || 0;
const member = new GuildMember(this, guildUser);
this.members.set(member.id, member);
if (this._rawVoiceStates && this._rawVoiceStates.get(member.user.id)) {
const voiceState = this._rawVoiceStates.get(member.user.id);
member.serverMute = voiceState.mute;
member.serverDeaf = voiceState.deaf;
member.selfMute = voiceState.self_mute;
member.selfDeaf = voiceState.self_deaf;
member.voiceSessionID = voiceState.session_id;
member.voiceChannelID = voiceState.channel_id;
this.channels.get(voiceState.channel_id).members.set(member.user.id, member);
}
/**
* Emitted whenever a user joins a guild.
* @event Client#guildMemberAdd
* @param {Guild} guild The guild that the user has joined
* @param {GuildMember} member The member that has joined
*/
if (this.client.ws.status === Constants.Status.READY && !noEvent) {
this.client.emit(Constants.Events.GUILD_MEMBER_ADD, this, member);
}
this._checkChunks();
return member;
}
_updateMember(member, data) {
const oldMember = cloneObject(member);
if (data.roles) member._roles = data.roles;
else member.nickname = data.nick;
const notSame = member.nickname !== oldMember.nickname && !arraysEqual(member._roles, oldMember._roles);
if (this.client.ws.status === Constants.Status.READY && notSame) {
/**
* Emitted whenever a Guild Member changes - i.e. new role, removed role, nickname
* @event Client#guildMemberUpdate
* @param {Guild} guild The guild that the update affects
* @param {GuildMember} oldMember The member before the update
* @param {GuildMember} newMember The member after the update
*/
this.client.emit(Constants.Events.GUILD_MEMBER_UPDATE, this, oldMember, member);
}
return {
old: oldMember,
mem: member,
};
}
_removeMember(guildMember) {
this.members.delete(guildMember.id);
this._checkChunks();
}
_memberSpeakUpdate(user, speaking) {
const member = this.members.get(user);
if (member && member.speaking !== speaking) {
member.speaking = speaking;
/**
* Emitted once a Guild Member starts/stops speaking
* @event Client#guildMemberSpeaking
* @param {GuildMember} member The member that started/stopped speaking
* @param {boolean} speaking Whether or not the member is speaking
*/
this.client.emit(Constants.Events.GUILD_MEMBER_SPEAKING, member, speaking);
}
}
_checkChunks() {
if (this._fetchWaiter) {
if (this.members.size === this.memberCount) {
this._fetchWaiter(this);
this._fetchWaiter = null;
}
}
}
}

View File

@@ -48,33 +48,6 @@ class GuildChannel extends Channel {
}
}
/**
* Checks if this channel has the same type, topic, position, name, overwrites and ID as another channel.
* In most cases, a simple `channel.id === channel2.id` will do, and is much faster too.
* @param {GuildChannel} channel The channel to compare this channel to
* @returns {boolean}
*/
equals(channel) {
let equal = channel &&
this.id === channel.id &&
this.type === channel.type &&
this.topic === channel.topic &&
this.position === channel.position &&
this.name === channel.name;
if (equal) {
if (channel.permission_overwrites) {
const thisIDSet = Array.from(this.permissionOverwrites.keys());
const otherIDSet = channel.permission_overwrites.map(overwrite => overwrite.id);
equal = arraysEqual(thisIDSet, otherIDSet);
} else {
equal = false;
}
}
return equal;
}
/**
* Gets the overall set of permissions for a user in this channel, taking into account roles and permission
* overwrites.
@@ -237,20 +210,6 @@ class GuildChannel extends Channel {
return this.client.rest.methods.updateChannel(this, { topic });
}
/**
* When concatenated with a string, this automatically returns the Channel's mention instead of the Channel object.
* @returns {string}
* @example
* // Outputs: Hello from #general
* console.log(`Hello from ${channel}`);
* @example
* // Outputs: Hello from #general
* console.log('Hello from ' + channel);
*/
toString() {
return `<#${this.id}>`;
}
/**
* Options given when creating a Guild Channel Invite:
* ```js
@@ -271,6 +230,47 @@ class GuildChannel extends Channel {
createInvite(options = {}) {
return this.client.rest.methods.createChannelInvite(this, options);
}
/**
* Checks if this channel has the same type, topic, position, name, overwrites and ID as another channel.
* In most cases, a simple `channel.id === channel2.id` will do, and is much faster too.
* @param {GuildChannel} channel The channel to compare this channel to
* @returns {boolean}
*/
equals(channel) {
let equal = channel &&
this.id === channel.id &&
this.type === channel.type &&
this.topic === channel.topic &&
this.position === channel.position &&
this.name === channel.name;
if (equal) {
if (channel.permission_overwrites) {
const thisIDSet = Array.from(this.permissionOverwrites.keys());
const otherIDSet = channel.permission_overwrites.map(overwrite => overwrite.id);
equal = arraysEqual(thisIDSet, otherIDSet);
} else {
equal = false;
}
}
return equal;
}
/**
* When concatenated with a string, this automatically returns the Channel's mention instead of the Channel object.
* @returns {string}
* @example
* // Outputs: Hello from #general
* console.log(`Hello from ${channel}`);
* @example
* // Outputs: Hello from #general
* console.log('Hello from ' + channel);
*/
toString() {
return `<#${this.id}>`;
}
}
module.exports = GuildChannel;

View File

@@ -286,17 +286,10 @@ class GuildMember {
return this.client.rest.methods.banGuildMember(this.guild, this, deleteDays);
}
sendMessage() {
return;
}
sendTTSMessage() {
return;
}
sendFile() {
return;
}
// These are here only for documentation purposes - they are implemented by TextBasedChannel
sendMessage() { return; }
sendTTSMessage() { return; }
sendFile() { return; }
}
TextBasedChannel.applyToClass(GuildMember);

View File

@@ -220,36 +220,6 @@ class Message {
}
}
/**
* Used mainly internally. Whether two messages are identical in properties. If you want to compare messages
* without checking all the properties, use `message.id === message2.id`, which is much more efficient. This
* method allows you to see if there are differences in content, embeds, attachments, nonce and tts properties.
* @param {Message} message The message to compare it to
* @param {Object} rawData Raw data passed through the WebSocket about this message
* @returns {boolean}
*/
equals(message, rawData) {
if (!message) return false;
const embedUpdate = !message.author && !message.attachments;
if (embedUpdate) return this.id === message.id && this.embeds.length === message.embeds.length;
let equal = this.id === message.id &&
this.author.id === message.author.id &&
this.content === message.content &&
this.tts === message.tts &&
this.nonce === message.nonce &&
this.embeds.length === message.embeds.length &&
this.attachments.length === message.attachments.length;
if (equal && rawData) {
equal = this.mentions.everyone === message.mentions.everyone &&
this._timestamp === new Date(rawData.timestamp).getTime() &&
this._editedTimestamp === new Date(rawData.edited_timestamp).getTime();
}
return equal;
}
/**
* Deletes the message
* @param {number} [timeout=0] How long to wait to delete the message in milliseconds
@@ -327,6 +297,36 @@ class Message {
unpin() {
return this.client.rest.methods.unpinMessage(this);
}
/**
* Used mainly internally. Whether two messages are identical in properties. If you want to compare messages
* without checking all the properties, use `message.id === message2.id`, which is much more efficient. This
* method allows you to see if there are differences in content, embeds, attachments, nonce and tts properties.
* @param {Message} message The message to compare it to
* @param {Object} rawData Raw data passed through the WebSocket about this message
* @returns {boolean}
*/
equals(message, rawData) {
if (!message) return false;
const embedUpdate = !message.author && !message.attachments;
if (embedUpdate) return this.id === message.id && this.embeds.length === message.embeds.length;
let equal = this.id === message.id &&
this.author.id === message.author.id &&
this.content === message.content &&
this.tts === message.tts &&
this.nonce === message.nonce &&
this.embeds.length === message.embeds.length &&
this.attachments.length === message.attachments.length;
if (equal && rawData) {
equal = this.mentions.everyone === message.mentions.everyone &&
this._timestamp === new Date(rawData.timestamp).getTime() &&
this._editedTimestamp === new Date(rawData.edited_timestamp).getTime();
}
return equal;
}
}
module.exports = Message;

View File

@@ -9,11 +9,13 @@ class MessageAttachment {
*/
this.client = message.client;
Object.defineProperty(this, 'client', { enumerable: false, configurable: false });
/**
* The message this attachment is part of.
* @type {Message}
*/
this.message = message;
this.setup(data);
}
@@ -23,31 +25,37 @@ class MessageAttachment {
* @type {string}
*/
this.id = data.id;
/**
* The file name of this attachment
* @type {string}
*/
this.filename = data.filename;
/**
* The size of this attachment in bytes
* @type {number}
*/
this.filesize = data.size;
/**
* The URL to this attachment
* @type {string}
*/
this.url = data.url;
/**
* The Proxy URL to this attachment
* @type {string}
*/
this.proxyURL = data.url;
/**
* The height of this attachment (if an image)
* @type {?number}
*/
this.height = data.height;
/**
* The width of this attachment (if an image)
* @type {?number}

View File

@@ -3,17 +3,19 @@
*/
class MessageEmbed {
constructor(message, data) {
/**
* The message this embed is part of
* @type {Message}
*/
this.message = message;
/**
* The client that instantiated this embed
* @type {Client}
*/
this.client = message.client;
Object.defineProperty(this, 'client', { enumerable: false, configurable: false });
/**
* The message this embed is part of
* @type {Message}
*/
this.message = message;
this.setup(data);
}
@@ -23,42 +25,42 @@ class MessageEmbed {
* @type {?string}
*/
this.title = data.title;
/**
* The type of this embed
* @type {string}
*/
this.type = data.type;
/**
* The description of this embed, if there is one
* @type {?string}
*/
this.description = data.description;
/**
* The URL of this embed
* @type {string}
*/
this.url = data.url;
if (data.thumbnail) {
/**
* The thumbnail of this embed, if there is one
* @type {MessageEmbedThumbnail}
*/
this.thumbnail = new MessageEmbedThumbnail(this, data.thumbnail);
}
if (data.author) {
/**
* The author of this embed, if there is one
* @type {MessageEmbedAuthor}
*/
this.author = new MessageEmbedAuthor(this, data.author);
}
if (data.provider) {
/**
* The provider of this embed, if there is one
* @type {MessageEmbedProvider}
*/
this.provider = new MessageEmbedProvider(this, data.provider);
}
/**
* The thumbnail of this embed, if there is one
* @type {MessageEmbedThumbnail}
*/
this.thumbnail = data.thumbnail ? new MessageEmbedThumbnail(this, data.thumbnail) : null;
/**
* The author of this embed, if there is one
* @type {MessageEmbedAuthor}
*/
this.author = data.author ? new MessageEmbedAuthor(this, data.author) : null;
/**
* The provider of this embed, if there is one
* @type {MessageEmbedProvider}
*/
this.provider = data.provider ? new MessageEmbedProvider(this, data.provider) : null;
}
}
@@ -72,6 +74,7 @@ class MessageEmbedThumbnail {
* @type {MessageEmbed}
*/
this.embed = embed;
this.setup(data);
}
@@ -81,16 +84,19 @@ class MessageEmbedThumbnail {
* @type {string}
*/
this.url = data.url;
/**
* The Proxy URL for this thumbnail
* @type {string}
*/
this.proxyURL = data.proxy_url;
/**
* The height of the thumbnail
* @type {number}
*/
this.height = data.height;
/**
* The width of the thumbnail
* @type {number}
@@ -109,6 +115,7 @@ class MessageEmbedProvider {
* @type {MessageEmbed}
*/
this.embed = embed;
this.setup(data);
}
@@ -118,6 +125,7 @@ class MessageEmbedProvider {
* @type {string}
*/
this.name = data.name;
/**
* The URL of this provider
* @type {string}
@@ -136,6 +144,7 @@ class MessageEmbedAuthor {
* @type {MessageEmbed}
*/
this.embed = embed;
this.setup(data);
}
@@ -145,6 +154,7 @@ class MessageEmbedAuthor {
* @type {string}
*/
this.name = data.name;
/**
* The URL of this author
* @type {string}

View File

@@ -65,17 +65,6 @@ class Role {
this.managed = data.managed;
}
equals(role) {
return role &&
this.id === role.id &&
this.name === role.name &&
this.color === role.color &&
this.hoist === role.hoist &&
this.position === role.position &&
this.permissions === role.permissions &&
this.managed === role.managed;
}
/**
* The time the role was created
* @readonly
@@ -216,14 +205,6 @@ class Role {
return (this.permissions & permission) > 0;
}
/**
* When concatenated with a string, this automatically concatenates the Role mention rather than the Role object.
* @returns {string}
*/
toString() {
return `<@&${this.id}>`;
}
/**
* The hexadecimal version of the role color, with a leading hashtag.
* @type {string}
@@ -234,6 +215,32 @@ class Role {
while (col.length < 6) col = `0${col}`;
return `#${col}`;
}
/**
* Whether this role equals another role. It compares all properties, so for most operations
* it is advisable to just compare `role.id === role2.id` as it is much faster and is often
* what most users need.
* @param {Role} role The role to compare to
* @returns {boolean}
*/
equals(role) {
return role &&
this.id === role.id &&
this.name === role.name &&
this.color === role.color &&
this.hoist === role.hoist &&
this.position === role.position &&
this.permissions === role.permissions &&
this.managed === role.managed;
}
/**
* When concatenated with a string, this automatically concatenates the Role mention rather than the Role object.
* @returns {string}
*/
toString() {
return `<@&${this.id}>`;
}
}
module.exports = Role;

View File

@@ -27,61 +27,21 @@ class TextChannel extends GuildChannel {
this._typing = new Map();
}
sendMessage() {
return;
}
sendTTSMessage() {
return;
}
sendFile() {
return;
}
_cacheMessage() {
return;
}
fetchMessages() {
return;
}
fetchMessage() {
return;
}
bulkDelete() {
return;
}
startTyping() {
return;
}
stopTyping() {
return;
}
get typing() {
return;
}
get typingCount() {
return;
}
fetchPinnedMessages() {
return;
}
createCollector() {
return;
}
awaitMessages() {
return;
}
// These are here only for documentation purposes - they are implemented by TextBasedChannel
sendMessage() { return; }
sendTTSMessage() { return; }
sendFile() { return; }
fetchMessage() { return; }
fetchMessages() { return; }
fetchPinnedMessages() { return; }
startTyping() { return; }
stopTyping() { return; }
get typing() { return; }
get typingCount() { return; }
createCollector() { return; }
awaitMessages() { return; }
bulkDelete() { return; }
_cacheMessage() { return; }
}
TextBasedChannel.applyToClass(TextChannel, true);

View File

@@ -74,17 +74,6 @@ class User {
return new Date((this.id / 4194304) + 1420070400000);
}
/**
* When concatenated with a string, this automatically concatenates the User's mention instead of the User object.
* @returns {string}
* @example
* // logs: Hello from <@123456789>!
* console.log(`Hello from ${user}!`);
*/
toString() {
return `<@${this.id}>`;
}
/**
* A link to the user's avatar (if they have one, otherwise null)
* @type {?string}
@@ -125,17 +114,21 @@ class User {
return equal;
}
sendMessage() {
return;
/**
* When concatenated with a string, this automatically concatenates the User's mention instead of the User object.
* @returns {string}
* @example
* // logs: Hello from <@123456789>!
* console.log(`Hello from ${user}!`);
*/
toString() {
return `<@${this.id}>`;
}
sendTTSMessage() {
return;
}
sendFile() {
return;
}
// These are here only for documentation purposes - they are implemented by TextBasedChannel
sendMessage() { return; }
sendTTSMessage() { return; }
sendFile() { return; }
}
TextBasedChannel.applyToClass(User);

View File

@@ -22,18 +22,6 @@ class TextBasedChannel {
this.lastMessageID = null;
}
/**
* Bulk delete a given Collection or Array of messages in one go. Returns the deleted messages after.
* @param {Collection<string, Message>|Message[]} messages The messages to delete
* @returns {Collection<string, Message>}
*/
bulkDelete(messages) {
if (messages instanceof Collection) messages = messages.array();
if (!(messages instanceof Array)) return Promise.reject(new TypeError('messages must be an array or collection'));
const messageIDs = messages.map(m => m.id);
return this.client.rest.methods.bulkDeleteMessages(this, messageIDs);
}
/**
* Options that can be passed into sendMessage or sendTTSMessage:
* ```js
@@ -102,6 +90,28 @@ class TextBasedChannel {
});
}
/**
* Gets a single message from this channel, regardless of it being cached or not.
* @param {string} messageID The ID of the message to get
* @returns {Promise<Message>}
* @example
* // get message
* channel.fetchMessage('99539446449315840')
* .then(message => console.log(message.content))
* .catch(console.error);
*/
fetchMessage(messageID) {
return new Promise((resolve, reject) => {
this.client.rest.methods.getChannelMessage(this, messageID).then(data => {
let msg = data;
if (!(msg instanceof Message)) msg = new Message(this, data, this.client);
this._cacheMessage(msg);
resolve(msg);
}).catch(reject);
});
}
/**
* The parameters to pass in when requesting previous messages from a channel. `around`, `before` and
* `after` are mutually exclusive. All the parameters are optional.
@@ -141,23 +151,19 @@ class TextBasedChannel {
}
/**
* Gets a single message from this channel, regardless of it being cached or not.
* @param {string} messageID The ID of the message to get
* @returns {Promise<Message>}
* @example
* // get message
* channel.fetchMessage('99539446449315840')
* .then(message => console.log(message.content))
* .catch(console.error);
* Fetches the pinned messages of this Channel and returns a Collection of them.
* @returns {Promise<Collection<string, Message>>}
*/
fetchMessage(messageID) {
fetchPinnedMessages() {
return new Promise((resolve, reject) => {
this.client.rest.methods.getChannelMessage(this, messageID).then(data => {
let msg = data;
if (!(msg instanceof Message)) msg = new Message(this, data, this.client);
this._cacheMessage(msg);
resolve(msg);
this.client.rest.methods.getChannelPinnedMessages(this).then(data => {
const messages = new Collection();
for (const message of data) {
const msg = new Message(this, message, this.client);
messages.set(message.id, msg);
this._cacheMessage(msg);
}
resolve(messages);
}).catch(reject);
});
}
@@ -280,6 +286,18 @@ class TextBasedChannel {
});
}
/**
* Bulk delete a given Collection or Array of messages in one go. Returns the deleted messages after.
* @param {Collection<string, Message>|Message[]} messages The messages to delete
* @returns {Collection<string, Message>}
*/
bulkDelete(messages) {
if (messages instanceof Collection) messages = messages.array();
if (!(messages instanceof Array)) return Promise.reject(new TypeError('messages must be an array or collection'));
const messageIDs = messages.map(m => m.id);
return this.client.rest.methods.bulkDeleteMessages(this, messageIDs);
}
_cacheMessage(message) {
const maxSize = this.client.options.max_message_cache;
if (maxSize === 0) return null;
@@ -288,24 +306,6 @@ class TextBasedChannel {
this.messages.set(message.id, message);
return message;
}
/**
* Fetches the pinned messages of this Channel and returns a Collection of them.
* @returns {Promise<Collection<string, Message>>}
*/
fetchPinnedMessages() {
return new Promise((resolve, reject) => {
this.client.rest.methods.getChannelPinnedMessages(this).then(data => {
const messages = new Collection();
for (const message of data) {
const msg = new Message(this, message, this.client);
messages.set(message.id, msg);
this._cacheMessage(msg);
}
resolve(messages);
}).catch(reject);
});
}
}
/**
@@ -344,33 +344,39 @@ class MessageCollector extends EventEmitter {
*/
constructor(channel, filter, options = {}) {
super();
/**
* The channel this collector is operating on
* @type {Channel}
*/
this.channel = channel;
/**
* A function used to filter messages that the collector collects.
* @type {CollectorFilterFunction}
*/
this.filter = filter;
/**
* Options for the collecor.
* @type {CollectorOptions}
*/
this.options = options;
/**
* Whether this collector has stopped collecting Messages.
* @type {boolean}
*/
this.ended = false;
this.listener = message => this.verify(message);
this.channel.client.on('message', this.listener);
/**
* A collection of collected messages, mapped by message ID.
* @type {Collection<string, Message>}
*/
this.collected = new Collection();
this.listener = message => this.verify(message);
this.channel.client.on('message', this.listener);
if (options.time) this.channel.client.setTimeout(() => this.stop('time'), options.time);
}