Clean up a bunch of stuff

- Channel typing data is now a Map
- Client properties on structures are now non-enumerable and
non-configurable
This commit is contained in:
Schuyler Cebulskie
2016-09-07 00:24:45 -04:00
parent 3a790e74f4
commit b7f582b7f0
22 changed files with 411 additions and 316 deletions

View File

@@ -9,21 +9,13 @@ class TypingStartHandler extends AbstractHandler {
const user = client.users.get(data.user_id);
const timestamp = new Date(data.timestamp * 1000);
function tooLate() {
return client.setTimeout(() => {
client.emit(Constants.Events.TYPING_STOP, channel, user, channel.typingMap[user.id]);
delete channel.typingMap[user.id];
}, 6000);
}
if (channel && user) {
if (channel.typingMap[user.id]) {
// already typing, renew
const mapping = channel.typingMap[user.id];
mapping.lastTimestamp = timestamp;
mapping.resetTimeout(tooLate());
if (channel._typing.has(user.id)) {
const typing = channel._typing.get(user.id);
typing.lastTimestamp = timestamp;
typing.resetTimeout(tooLate(channel, user));
} else {
channel.typingMap[user.id] = new TypingData(timestamp, timestamp, tooLate());
channel._typing.set(user.id, new TypingData(timestamp, timestamp, tooLate(channel, user)));
client.emit(Constants.Events.TYPING_START, channel, user);
}
}
@@ -47,6 +39,13 @@ class TypingData {
}
}
function tooLate(channel, user) {
return channel.client.setTimeout(() => {
channel.client.emit(Constants.Events.TYPING_STOP, channel, user, channel._typing[user.id]);
delete channel._typing[user.id];
}, 6000);
}
/**
* Emitted whenever a user starts typing in a channel
* @event Client#typingStart

View File

@@ -8,8 +8,8 @@ class Channel {
* @type {Client}
*/
this.client = client;
this.typingMap = {};
this.typingTimeouts = [];
Object.defineProperty(this, 'client', { enumerable: false, configurable: false });
/**
* The type of the channel, either:
* * `dm` - a DM channel
@@ -19,6 +19,8 @@ class Channel {
* @type {string}
*/
this.type = null;
this._typing = new Map();
if (data) this.setup(data);
}

View File

@@ -7,11 +7,13 @@ const User = require('./User');
class ClientUser extends User {
setup(data) {
super.setup(data);
/**
* Whether or not this account has been verified
* @type {boolean}
*/
this.verified = data.verified;
/**
* The email of this account
* @type {string}

View File

@@ -16,18 +16,15 @@ class DMChannel extends Channel {
setup(data) {
super.setup(data);
const recipient = this.client.users.get(data.recipients[0].id) || new User(this.client, data.recipients[0]);
/**
* The recipient on the other end of the DM
* @type {User}
*/
this.recipient = recipient;
/**
* The ID of the last sent message, if available
* @type {?string}
*/
this.lastMessageID = data.last_message_id;
this.recipient = this.client.users.get(data.recipients[0].id) || new User(this.client, data.recipients[0]);
this.type = 'dm';
this.lastMessageID = data.last_message_id;
}
/**

View File

@@ -11,11 +11,14 @@ class Emoji {
* @type {Client}
*/
this.client = guild.client;
Object.defineProperty(this, 'client', { enumerable: false, configurable: false });
/**
* The Guild this emoji is part of
* @type {Guild}
*/
this.guild = guild;
this.setup(data);
}
@@ -25,22 +28,26 @@ class Emoji {
* @type {string}
*/
this.id = data.id;
/**
* The name of the Emoji
* @type {string}
*/
this.name = data.name;
this.roleIDS = data.roles;
/**
* Whether or not this emoji requires colons surrounding it
* @type {boolean}
*/
this.requiresColons = data.require_colons;
/**
* Whether this emoji is managed by an external service
* @type {boolean}
*/
this.managed = data.managed;
this._roles = data.roles;
}
/**
@@ -59,8 +66,8 @@ class Emoji {
*/
get roles() {
const roles = new Collection();
for (const role of this.roleIDS) {
if (this.guild.roles.get(role)) roles.set(role, this.guild.roles.get(role));
for (const role of this._roles) {
if (this.guild.roles.has(role)) roles.set(role, this.guild.roles.get(role));
}
return roles;
}

View File

@@ -10,6 +10,7 @@ class EvaluatedPermissions {
* @type {GuildMember}
*/
this.member = member;
/**
* A number representing the packed permissions.
* @private

View File

@@ -36,25 +36,27 @@ class GroupDMChannel extends Channel {
this.messages = new Collection();
}
equals(other) {
const equal = other &&
this.id === other.id &&
this.name === other.name &&
this.icon === other.icon &&
this.owner.id === other.owner_id;
if (equal) {
const thisIDs = this.recipients.array().map(r => r.id);
const otherIDs = other.recipients.map(r => r.id);
return arraysEqual(thisIDs, otherIDs);
}
return equal;
}
setup(data) {
super.setup(data);
/**
* The name of this Group DM, can be null if one isn't set.
* @type {string}
*/
this.name = data.name;
/**
* A hash of the Group DM icon.
* @type {string}
*/
this.icon = data.icon;
/**
* The owner of this Group DM.
* @type {User}
*/
this.owner = this.client.users.get(data.owner_id);
if (!this.recipients) {
/**
* A collection of the recipients of this DM, mapped by their ID.
@@ -70,32 +72,25 @@ class GroupDMChannel extends Channel {
}
}
/**
* The name of this Group DM, can be null if one isn't set.
* @type {string}
*/
this.name = data.name;
/**
* The ID of this Group DM Channel.
* @type {string}
*/
this.id = data.id;
/**
* A hash of the Group DM icon.
* @type {string}
*/
this.icon = data.icon;
/**
* The ID of the last message in the channel, if one was sent.
* @type {?string}
*/
this.lastMessageID = data.last_message_id;
/**
* The owner of this Group DM.
* @type {User}
*/
this.owner = this.client.users.get(data.owner_id);
this.type = 'group';
this.lastMessageID = data.last_message_id;
}
equals(other) {
const equal = other &&
this.id === other.id &&
this.name === other.name &&
this.icon === other.icon &&
this.owner.id === other.owner_id;
if (equal) {
const thisIDs = this.recipients.array().map(r => r.id);
const otherIDs = other.recipients.map(r => r.id);
return arraysEqual(thisIDs, otherIDs);
}
return equal;
}
sendMessage() {

View File

@@ -19,6 +19,7 @@ class Guild {
* @type {Client}
*/
this.client = client;
Object.defineProperty(this, 'client', { enumerable: false, configurable: false });
/**
* A Collection of members that are in this Guild. The key is the member's ID, the value is the member.
@@ -39,13 +40,13 @@ class Guild {
this.roles = new Collection();
if (!data) return;
if (data.unavailable) {
/**
* Whether the Guild is available to access. If it is not available, it indicates a server outage.
* @type {boolean}
*/
this.available = false;
/**
* The Unique ID of the Guild, useful for comparisons.
* @type {string}
@@ -57,6 +58,138 @@ class Guild {
}
}
/**
* Sets up the Guild
* @param {*} data The raw data of the guild
* @private
*/
setup(data) {
/**
* The name of the guild
* @type {string}
*/
this.name = data.name;
/**
* The hash of the guild icon, or null if there is no icon.
* @type {?string}
*/
this.icon = data.icon;
/**
* The hash of the guild splash image, or null if no splash (VIP only)
* @type {?string}
*/
this.splash = data.splash;
/**
* The region the guild is located in
* @type {string}
*/
this.region = data.region;
/**
* The full amount of members in this Guild as of `READY`
* @type {number}
*/
this.memberCount = data.member_count;
/**
* Whether the guild is "large" (has more than 250 members)
* @type {boolean}
*/
this.large = data.large;
/**
* An array of guild features.
* @type {Object[]}
*/
this.features = data.features;
/**
* An array of guild emojis.
* @type {Object[]}
*/
this.emojis = new Collection();
for (const emoji of data.emojis) this.emojis.set(emoji.id, new Emoji(this, emoji));
/**
* The time in seconds before a user is counted as "away from keyboard".
* @type {?number}
*/
this.afkTimeout = data.afk_timeout;
/**
* The ID of the voice channel where AFK members are moved.
* @type {?string}
*/
this.afkChannelID = data.afk_channel_id;
/**
* Whether embedded images are enabled on this guild.
* @type {boolean}
*/
this.embedEnabled = data.embed_enabled;
/**
* The verification level of the guild.
* @type {number}
*/
this.verificationLevel = data.verification_level;
this.id = data.id;
this.available = !data.unavailable;
this.features = data.features || [];
this._joinDate = new Date(data.joined_at).getTime();
if (data.members) {
this.members.clear();
for (const guildUser of data.members) this._addMember(guildUser);
}
if (data.owner_id) this.ownerID = data.owner_id;
if (data.channels) {
this.channels.clear();
for (const channel of data.channels) this.client.dataManager.newChannel(channel, this);
}
if (data.roles) {
this.roles.clear();
for (const role of data.roles) {
const newRole = new Role(this, role);
this.roles.set(newRole.id, newRole);
}
}
if (data.presences) {
for (const presence of data.presences) {
const user = this.client.users.get(presence.user.id);
if (user) {
user.status = presence.status;
user.game = presence.game;
}
}
}
this._rawVoiceStates = new Collection();
if (data.voice_states) {
for (const voiceState of data.voice_states) {
this._rawVoiceStates.set(voiceState.user_id, voiceState);
const member = this.members.get(voiceState.user_id);
if (member) {
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);
}
}
}
}
_checkChunks() {
if (this._fetchWaiter) {
if (this.members.size === this.memberCount) {
@@ -83,6 +216,7 @@ class Guild {
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
@@ -201,127 +335,6 @@ class Guild {
}
}
/**
* Sets up the Guild
* @param {*} data The raw data of the guild
* @private
*/
setup(data) {
this.id = data.id;
this.available = !data.unavailable;
/**
* The hash of the guild splash image, or null if no splash (VIP only)
* @type {?string}
*/
this.splash = data.splash;
/**
* The region the guild is located in
* @type {string}
*/
this.region = data.region;
/**
* The name of the guild
* @type {string}
*/
this.name = data.name;
/**
* The full amount of members in this Guild as of `READY`
* @type {number}
*/
this.memberCount = data.member_count;
/**
* Whether the guild is "large" (has more than 250 members)
* @type {boolean}
*/
this.large = data.large;
this._joinDate = new Date(data.joined_at).getTime();
/**
* The hash of the guild icon, or null if there is no icon.
* @type {?string}
*/
this.icon = data.icon;
/**
* An array of guild features.
* @type {Object[]}
*/
this.features = data.features;
/**
* An array of guild emojis.
* @type {Object[]}
*/
this.emojis = new Collection();
for (const emoji of data.emojis) this.emojis.set(emoji.id, new Emoji(this, emoji));
/**
* The time in seconds before a user is counted as "away from keyboard".
* @type {?number}
*/
this.afkTimeout = data.afk_timeout;
/**
* The ID of the voice channel where AFK members are moved.
* @type {?string}
*/
this.afkChannelID = data.afk_channel_id;
/**
* Whether embedded images are enabled on this guild.
* @type {boolean}
*/
this.embedEnabled = data.embed_enabled;
/**
* The verification level of the guild.
* @type {number}
*/
this.verificationLevel = data.verification_level;
this.features = data.features || [];
if (data.members) {
this.members.clear();
for (const guildUser of data.members) this._addMember(guildUser);
}
if (data.owner_id) this.ownerID = data.owner_id;
if (data.channels) {
this.channels.clear();
for (const channel of data.channels) this.client.dataManager.newChannel(channel, this);
}
if (data.roles) {
this.roles.clear();
for (const role of data.roles) {
const newRole = new Role(this, role);
this.roles.set(newRole.id, newRole);
}
}
if (data.presences) {
for (const presence of data.presences) {
const user = this.client.users.get(presence.user.id);
if (user) {
user.status = presence.status;
user.game = presence.game;
}
}
}
this._rawVoiceStates = new Collection();
if (data.voice_states) {
for (const voiceState of data.voice_states) {
this._rawVoiceStates.set(voiceState.user_id, voiceState);
const member = this.members.get(voiceState.user_id);
if (member) {
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);
}
}
}
}
/**
* The time the guild was created
* @readonly

View File

@@ -13,6 +13,7 @@ const arraysEqual = require('../util/ArraysEqual');
class GuildChannel extends Channel {
constructor(guild, data) {
super(guild.client, data);
/**
* The guild the channel is in
* @type {Guild}
@@ -22,17 +23,19 @@ class GuildChannel extends Channel {
setup(data) {
super.setup(data);
/**
* The position of the channel in the list.
* @type {number}
*/
this.position = data.position;
/**
* The name of the Guild Channel
* @type {string}
*/
this.name = data.name;
this.ow = data.permission_overwrites;
/**
* The position of the channel in the list.
* @type {number}
*/
this.position = data.position;
/**
* A map of permission overwrites in this channel for roles and users.
* @type {Collection<string, PermissionOverwrites>}
@@ -53,11 +56,11 @@ class GuildChannel extends Channel {
*/
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 &&
this.id === channel.id;
this.name === channel.name;
if (equal) {
if (channel.permission_overwrites) {

View File

@@ -13,64 +13,76 @@ class GuildMember {
* @type {Client}
*/
this.client = guild.client;
Object.defineProperty(this, 'client', { enumerable: false, configurable: false });
/**
* The guild that this member is part of
* @type {Guild}
*/
this.guild = guild;
/**
* The user that this guild member instance Represents
* @type {User}
*/
this.user = {};
this._roles = [];
if (data) this.setup(data);
}
setup(data) {
this.user = data.user;
/**
* Whether this member is deafened server-wide
* @type {boolean}
*/
this.serverDeaf = data.deaf;
/**
* Whether this member is muted server-wide
* @type {boolean}
*/
this.serverMute = data.mute;
/**
* Whether this member is self-muted
* @type {boolean}
*/
this.selfMute = data.self_mute;
/**
* Whether this member is self-deafened
* @type {boolean}
*/
this.selfDeaf = data.self_deaf;
/**
* The voice session ID of this member, if any
* @type {?string}
*/
this.voiceSessionID = data.session_id;
/**
* The voice channel ID of this member, if any
* @type {?string}
*/
this.voiceChannelID = data.channel_id;
this._joinDate = new Date(data.joined_at).getTime();
/**
* Whether this meember is speaking
* @type {?boolean}
*/
this.speaking = this.speaking;
/**
* The nickname of this Guild Member, if they have one
* @type {?string}
*/
this.nickname = data.nick;
this.user = data.user;
this._roles = data.roles;
this._joinDate = new Date(data.joined_at).getTime();
}
/**

View File

@@ -32,22 +32,24 @@ class Invite {
* @type {Client}
*/
this.client = client;
Object.defineProperty(this, 'client', { enumerable: false, configurable: false });
this.setup(data);
}
setup(data) {
/**
* The maximum age of the invite, in seconds
* @type {?number}
* The Guild the invite is for. If this Guild is already known, this will be a Guild object. If the Guild is
* unknown, this will be a Partial Guild.
* @type {Guild|PartialGuild}
*/
this.maxAge = data.max_age;
this.guild = this.client.guilds.get(data.guild.id) || new PartialGuild(this.client, data.guild);
/**
* The code for this invite
* @type {string}
*/
this.code = data.code;
this._creationDate = new Date(data.created_at).getTime();
/**
* Whether or not this invite is temporary
@@ -55,6 +57,12 @@ class Invite {
*/
this.temporary = data.temporary;
/**
* The maximum age of the invite, in seconds
* @type {?number}
*/
this.maxAge = data.max_age;
/**
* How many times this invite has been used
* @type {number}
@@ -73,19 +81,22 @@ class Invite {
*/
this.inviter = this.client.dataManager.newUser(data.inviter);
/**
* The Guild the invite is for. If this Guild is already known, this will be a Guild object. If the Guild is
* unknown, this will be a Partial Guild.
* @type {Guild|PartialGuild}
*/
this.guild = this.client.guilds.get(data.guild.id) || new PartialGuild(this.client, data.guild);
/**
* The Channel the invite is for. If this Channel is already known, this will be a GuildChannel object.
* If the Channel is unknown, this will be a Partial Guild Channel.
* @type {GuildChannel|PartialGuildChannel}
*/
this.channels = this.client.channels.get(data.channel.id) || new PartialGuildChannel(this.client, data.channel);
this.channel = this.client.channels.get(data.channel.id) || new PartialGuildChannel(this.client, data.channel);
this._createdAt = new Date(data.created_at).getTime();
}
/**
* The creation date of the invite
* @type {Date}
*/
get createdAt() {
return new Date(this._createdAt);
}
/**
@@ -93,7 +104,7 @@ class Invite {
* @type {Date}
*/
get creationDate() {
return new Date(this._creationDate);
return new Date(this._createdAt);
}
/**

View File

@@ -7,76 +7,91 @@ const Collection = require('../util/Collection');
*/
class Message {
constructor(channel, data, client) {
this._type = 'message';
/**
* The client that instantiated the Message
* @type {Client}
*/
this.client = client;
Object.defineProperty(this, 'client', { enumerable: false, configurable: false });
/**
* The channel that the message was sent in
* @type {TextChannel|DMChannel|GroupDMChannel}
*/
this.channel = channel;
if (channel.guild) {
/**
* If the message was sent in a guild, this will be the guild the message was sent in
* @type {?Guild}
*/
this.guild = channel.guild;
}
/**
* The client that instantiated the Message
* @type {Client}
* If the message was sent in a guild, this will be the guild the message was sent in
* @type {?Guild}
*/
this.client = client;
this.guild = channel.guild || null;
if (data) this.setup(data);
}
setup(data) {
/**
* Whether or not this message is pinned
* @type {boolean}
* The ID of the message (unique in the channel it was sent)
* @type {string}
*/
this.pinned = data.pinned;
/**
* The author of the message
* @type {User}
*/
this.author = this.client.dataManager.newUser(data.author);
if (this.guild) {
/**
* Represents the Author of the message as a Guild Member. Only available if the message comes from a Guild
* where the author is still a member.
* @type {GuildMember}
*/
this.member = this.guild.member(this.author);
}
this.id = data.id;
/**
* The content of the message
* @type {string}
*/
this.content = data.content;
this._timestamp = new Date(data.timestamp).getTime();
this._editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp).getTime() : null;
/**
* The author of the message
* @type {User}
*/
this.author = this.client.dataManager.newUser(data.author);
/**
* Represents the Author of the message as a Guild Member. Only available if the message comes from a Guild
* where the author is still a member.
* @type {GuildMember}
*/
this.member = this.guild ? this.guild.member(this.author) || null : null;
/**
* Whether or not this message is pinned
* @type {boolean}
*/
this.pinned = data.pinned;
/**
* Whether or not the message was Text-To-Speech
* @type {boolean}
*/
this.tts = data.tts;
/**
* A random number used for checking message delivery
* @type {string}
*/
this.nonce = data.nonce;
/**
* Whether or not this message was sent by Discord, not actually a user (e.g. pin notifications)
* @type {boolean}
*/
this.system = data.type === 6;
/**
* A list of embeds in the message - e.g. YouTube Player
* @type {Embed[]}
*/
this.embeds = data.embeds.map(e => new Embed(this, e));
/**
* A collection of attachments in the message - e.g. Pictures - mapped by their ID.
* @type {Collection<string, MessageAttachment>}
*/
this.attachments = new Collection();
for (const attachment of data.attachments) this.attachments.set(attachment.id, new Attachment(this, attachment));
/**
* An object containing a further users, roles or channels collections
* @type {Object}
@@ -92,11 +107,6 @@ class Message {
channels: new Collection(),
everyone: data.mention_everyone,
};
/**
* The ID of the message (unique in the channel it was sent)
* @type {string}
*/
this.id = data.id;
for (const mention of data.mentions) {
let user = this.client.users.get(mention.id);
@@ -123,14 +133,9 @@ class Message {
}
}
this._timestamp = new Date(data.timestamp).getTime();
this._editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp).getTime() : null;
this._edits = [];
/**
* Whether or not this message was sent by Discord, not actually a user (e.g. pin notifications)
* @type {boolean}
*/
this.system = false;
if (data.type === 6) this.system = true;
}
/**

View File

@@ -8,6 +8,7 @@ class MessageAttachment {
* @type {Client}
*/
this.client = message.client;
Object.defineProperty(this, 'client', { enumerable: false, configurable: false });
/**
* The message this attachment is part of.
* @type {Message}

View File

@@ -13,6 +13,7 @@ class MessageEmbed {
* @type {Client}
*/
this.client = message.client;
Object.defineProperty(this, 'client', { enumerable: false, configurable: false });
this.setup(data);
}

View File

@@ -15,30 +15,35 @@ class PartialGuild {
* @type {Client}
*/
this.client = client;
Object.defineProperty(this, 'client', { enumerable: false, configurable: false });
this.setup(data);
}
setup(data) {
/**
* The hash of the guild splash image, or null if no splash (VIP only)
* @type {?string}
*/
this.splash = data.splash;
/**
* The ID of this guild
* @type {string}
*/
this.id = data.id;
/**
* The hash of this guild's icon, or null if there is none.
* @type {?string}
*/
this.icon = data.icon;
/**
* The name of this guild
* @type {string}
*/
this.name = data.name;
/**
* The hash of this guild's icon, or null if there is none.
* @type {?string}
*/
this.icon = data.icon;
/**
* The hash of the guild splash image, or null if no splash (VIP only)
* @type {?string}
*/
this.splash = data.splash;
}
}

View File

@@ -14,6 +14,8 @@ class PartialGuildChannel {
* @type {Client}
*/
this.client = client;
Object.defineProperty(this, 'client', { enumerable: false, configurable: false });
this.setup(data);
}
@@ -23,11 +25,13 @@ class PartialGuildChannel {
* @type {string}
*/
this.id = data.id;
/**
* The name of this Guild Channel
* @type {string}
*/
this.name = data.name;
/**
* The type of this Guild Channel - `text` or `voice`
* @type {string}

View File

@@ -8,20 +8,23 @@ class PermissionOverwrites {
* @type {GuildChannel}
*/
this.channel = guildChannel;
if (data) this.setup(data);
}
setup(data) {
/**
* The type of this overwrite
* @type {string}
*/
this.type = data.type;
/**
* The ID of this overwrite, either a User ID or a Role ID
* @type {string}
*/
this.id = data.id;
/**
* The type of this overwrite
* @type {string}
*/
this.type = data.type;
this.denyData = data.deny;
this.allowData = data.allow;
}

View File

@@ -5,19 +5,66 @@ const Constants = require('../util/Constants');
*/
class Role {
constructor(guild, data) {
/**
* The guild that the role belongs to
* @type {Guild}
*/
this.guild = guild;
/**
* The client that instantiated the role
* @type {Client}
*/
this.client = guild.client;
Object.defineProperty(this, 'client', { enumerable: false, configurable: false });
/**
* The guild that the role belongs to
* @type {Guild}
*/
this.guild = guild;
if (data) this.setup(data);
}
setup(data) {
/**
* The ID of the role (unique to the guild it is part of)
* @type {string}
*/
this.id = data.id;
/**
* The name of the role
* @type {string}
*/
this.name = data.name;
/**
* The base 10 color of the role
* @type {number}
*/
this.color = data.color;
/**
* If true, users that are part of this role will appear in a separate category in the users list
* @type {boolean}
*/
this.hoist = data.hoist;
/**
* The position of the role in the role manager
* @type {number}
*/
this.position = data.position;
/**
* The evaluated permissions number
* @type {number}
*/
this.permissions = data.permissions;
/**
* Whether or not the role is managed by an external service
* @type {boolean}
*/
this.managed = data.managed;
}
equals(role) {
return role &&
this.id === role.id &&
@@ -29,44 +76,6 @@ class Role {
this.managed === role.managed;
}
setup(data) {
/**
* The ID of the role (unique to the guild it is part of)
* @type {string}
*/
this.id = data.id;
/**
* The name of the role
* @type {string}
*/
this.name = data.name;
/**
* The base 10 color of the role
* @type {number}
*/
this.color = data.color;
/**
* If true, users that are part of this role will appear in a separate category in the users list
* @type {boolean}
*/
this.hoist = data.hoist;
/**
* The position of the role in the role manager
* @type {number}
*/
this.position = data.position;
/**
* The evaluated permissions number
* @type {number}
*/
this.permissions = data.permissions;
/**
* Whether or not the role is managed by an external service
* @type {boolean}
*/
this.managed = data.managed;
}
/**
* The time the role was created
* @readonly

View File

@@ -15,16 +15,19 @@ class TextChannel extends GuildChannel {
setup(data) {
super.setup(data);
/**
* The topic of the Guild Channel, if there is one.
* @type {?string}
*/
this.topic = data.topic;
/**
* The ID of the last message in the channel, if one was sent.
* @type {?string}
*/
this.lastMessageID = data.last_message_id;
this.type = 'text';
}

View File

@@ -7,36 +7,47 @@ const Constants = require('../util/Constants');
*/
class User {
constructor(client, data) {
/**
* The Client that created the instance of the the User.
* @type {Client}
*/
this.client = client;
Object.defineProperty(this, 'client', { enumerable: false, configurable: false });
if (data) this.setup(data);
}
setup(data) {
/**
* The username of the User
* @type {string}
*/
this.username = data.username;
/**
* The ID of the User
* @type {string}
*/
this.id = data.id;
/**
* The username of the User
* @type {string}
*/
this.username = data.username;
/**
* A discriminator based on username for the User
* @type {string}
*/
this.discriminator = data.discriminator;
/**
* The ID of the user's avatar
* @type {string}
*/
this.avatar = data.avatar;
/**
* Whether or not the User is a Bot.
* @type {boolean}
*/
this.bot = Boolean(data.bot);
/**
* The status of the user:
*
@@ -46,6 +57,7 @@ class User {
* @type {string}
*/
this.status = data.status || this.status || 'offline';
/**
* The game that the user is playing, `null` if they aren't playing a game.
* @type {string}
@@ -99,8 +111,8 @@ class User {
*/
equals(user) {
let equal = user &&
this.username === user.username &&
this.id === user.id &&
this.username === user.username &&
this.discriminator === user.discriminator &&
this.avatar === user.avatar &&
this.bot === Boolean(user.bot);

View File

@@ -8,6 +8,7 @@ const Collection = require('../util/Collection');
class VoiceChannel extends GuildChannel {
constructor(guild, data) {
super(guild, data);
/**
* The members in this Voice Channel.
* @type {Collection<string, GuildMember>}
@@ -17,16 +18,19 @@ class VoiceChannel extends GuildChannel {
setup(data) {
super.setup(data);
/**
* The bitrate of this voice channel
* @type {number}
*/
this.bitrate = data.bitrate;
/**
* The maximum amount of users allowed in this channel - 0 means unlimited.
* @type {number}
*/
this.userLimit = data.user_limit;
this.type = 'voice';
}

View File

@@ -14,6 +14,12 @@ class TextBasedChannel {
* @type {Collection<string, Message>}
*/
this.messages = new Collection();
/**
* The ID of the last message in the channel, if one was sent.
* @type {?string}
*/
this.lastMessageID = null;
}
/**