aboutsummaryrefslogtreecommitdiff
path: root/node_modules/discord.js/src/client/websocket
diff options
context:
space:
mode:
authorAlee14 <alee14498@gmail.com>2017-03-26 15:18:10 -0400
committerAlee14 <alee14498@gmail.com>2017-03-26 15:18:10 -0400
commit29433e2f7dbd0e4a73d3c78ffe1005b922fb5982 (patch)
treeaa0ad3fe59468cbe452ee597e914839b68c01436 /node_modules/discord.js/src/client/websocket
parent878fefb4c4e1f12b804ae5c0def433fa873f4c8b (diff)
downloadAleeBot-29433e2f7dbd0e4a73d3c78ffe1005b922fb5982.tar.gz
AleeBot-29433e2f7dbd0e4a73d3c78ffe1005b922fb5982.tar.bz2
AleeBot-29433e2f7dbd0e4a73d3c78ffe1005b922fb5982.zip
Don't mind me i'm adding the discord.js files
Diffstat (limited to 'node_modules/discord.js/src/client/websocket')
-rw-r--r--node_modules/discord.js/src/client/websocket/WebSocketManager.js373
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/WebSocketPacketManager.js125
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/AbstractHandler.js11
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/ChannelCreate.js17
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/ChannelDelete.js20
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/ChannelPinsUpdate.js31
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/ChannelUpdate.js11
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/GuildBanAdd.js23
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/GuildBanRemove.js20
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/GuildCreate.js22
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/GuildDelete.js19
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/GuildEmojisUpdate.js40
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/GuildMemberAdd.js17
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/GuildMemberRemove.js13
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/GuildMemberUpdate.js18
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/GuildMembersChunk.js28
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/GuildRoleCreate.js11
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/GuildRoleDelete.js11
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/GuildRoleUpdate.js11
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/GuildSync.js11
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/GuildUpdate.js11
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/MessageCreate.js19
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/MessageDelete.js19
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/MessageDeleteBulk.js17
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/MessageReactionAdd.js11
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/MessageReactionRemove.js11
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/MessageReactionRemoveAll.js11
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/MessageUpdate.js11
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/PresenceUpdate.js72
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/Ready.js69
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/RelationshipAdd.js19
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/RelationshipRemove.js19
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/TypingStart.js68
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/UserNoteUpdate.js12
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/UserUpdate.js11
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/VoiceServerUpdate.js19
-rw-r--r--node_modules/discord.js/src/client/websocket/packets/handlers/VoiceStateUpdate.js49
37 files changed, 1280 insertions, 0 deletions
diff --git a/node_modules/discord.js/src/client/websocket/WebSocketManager.js b/node_modules/discord.js/src/client/websocket/WebSocketManager.js
new file mode 100644
index 0000000..b67af59
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/WebSocketManager.js
@@ -0,0 +1,373 @@
+const browser = typeof window !== 'undefined';
+const EventEmitter = require('events').EventEmitter;
+const Constants = require('../../util/Constants');
+const convertArrayBuffer = require('../../util/ConvertArrayBuffer');
+const pako = require('pako');
+const zlib = require('zlib');
+const PacketManager = require('./packets/WebSocketPacketManager');
+
+let WebSocket, erlpack;
+let serialize = JSON.stringify;
+if (browser) {
+ WebSocket = window.WebSocket; // eslint-disable-line no-undef
+} else {
+ try {
+ WebSocket = require('uws');
+ } catch (err) {
+ WebSocket = require('ws');
+ }
+
+ try {
+ erlpack = require('erlpack');
+ serialize = erlpack.pack;
+ } catch (err) {
+ erlpack = null;
+ }
+}
+
+/**
+ * The WebSocket Manager of the Client
+ * @private
+ */
+class WebSocketManager extends EventEmitter {
+ constructor(client) {
+ super();
+ /**
+ * The Client that instantiated this WebSocketManager
+ * @type {Client}
+ */
+ this.client = client;
+
+ /**
+ * A WebSocket Packet manager, it handles all the messages
+ * @type {PacketManager}
+ */
+ this.packetManager = new PacketManager(this);
+
+ /**
+ * The status of the WebSocketManager, a type of Constants.Status. It defaults to IDLE.
+ * @type {number}
+ */
+ this.status = Constants.Status.IDLE;
+
+ /**
+ * The session ID of the connection, null if not yet available.
+ * @type {?string}
+ */
+ this.sessionID = null;
+
+ /**
+ * The packet count of the client, null if not yet available.
+ * @type {?number}
+ */
+ this.sequence = -1;
+
+ /**
+ * The gateway address for this WebSocket connection, null if not yet available.
+ * @type {?string}
+ */
+ this.gateway = null;
+
+ /**
+ * Whether READY was emitted normally (all packets received) or not
+ * @type {boolean}
+ */
+ this.normalReady = false;
+
+ /**
+ * The WebSocket connection to the gateway
+ * @type {?WebSocket}
+ */
+ this.ws = null;
+
+ /**
+ * An object with keys that are websocket event names that should be ignored
+ * @type {Object}
+ */
+ this.disabledEvents = {};
+ for (const event of client.options.disabledEvents) this.disabledEvents[event] = true;
+
+ this.first = true;
+
+ this.lastHeartbeatAck = true;
+ }
+
+ /**
+ * Connects the client to a given gateway
+ * @param {string} gateway The gateway to connect to
+ */
+ _connect(gateway) {
+ this.client.emit('debug', `Connecting to gateway ${gateway}`);
+ this.normalReady = false;
+ if (this.status !== Constants.Status.RECONNECTING) this.status = Constants.Status.CONNECTING;
+ this.ws = new WebSocket(gateway);
+ if (browser) this.ws.binaryType = 'arraybuffer';
+ this.ws.onopen = this.eventOpen.bind(this);
+ this.ws.onmessage = this.eventMessage.bind(this);
+ this.ws.onclose = this.eventClose.bind(this);
+ this.ws.onerror = this.eventError.bind(this);
+ this._queue = [];
+ this._remaining = 120;
+ this.client.setInterval(() => {
+ this._remaining = 120;
+ this._remainingReset = Date.now();
+ }, 60e3);
+ }
+
+ connect(gateway) {
+ gateway = `${gateway}&encoding=${erlpack ? 'etf' : 'json'}`;
+ if (this.first) {
+ this._connect(gateway);
+ this.first = false;
+ } else {
+ this.client.setTimeout(() => this._connect(gateway), 5500);
+ }
+ }
+
+ heartbeat(normal) {
+ if (normal && !this.lastHeartbeatAck) {
+ this.ws.close(1007);
+ return;
+ }
+
+ this.client.emit('debug', 'Sending heartbeat');
+ this.client._pingTimestamp = Date.now();
+ this.client.ws.send({
+ op: Constants.OPCodes.HEARTBEAT,
+ d: this.sequence,
+ }, true);
+
+ this.lastHeartbeatAck = false;
+ }
+
+ /**
+ * Sends a packet to the gateway
+ * @param {Object} data An object that can be JSON stringified
+ * @param {boolean} force Whether or not to send the packet immediately
+ */
+ send(data, force = false) {
+ if (force) {
+ this._send(serialize(data));
+ return;
+ }
+ this._queue.push(serialize(data));
+ this.doQueue();
+ }
+
+ destroy() {
+ this.ws.close(1000);
+ this._queue = [];
+ this.status = Constants.Status.IDLE;
+ }
+
+ _send(data) {
+ if (this.ws.readyState === WebSocket.OPEN) {
+ this.emit('send', data);
+ this.ws.send(data);
+ }
+ }
+
+ doQueue() {
+ const item = this._queue[0];
+ if (!(this.ws.readyState === WebSocket.OPEN && item)) return;
+ if (this.remaining === 0) {
+ this.client.setTimeout(this.doQueue.bind(this), Date.now() - this.remainingReset);
+ return;
+ }
+ this._remaining--;
+ this._send(item);
+ this._queue.shift();
+ this.doQueue();
+ }
+
+ /**
+ * Run whenever the gateway connections opens up
+ */
+ eventOpen() {
+ this.client.emit('debug', 'Connection to gateway opened');
+ this.lastHeartbeatAck = true;
+ if (this.status === Constants.Status.RECONNECTING) this._sendResume();
+ else this._sendNewIdentify();
+ }
+
+ /**
+ * Sends a gateway resume packet, in cases of unexpected disconnections.
+ */
+ _sendResume() {
+ if (!this.sessionID) {
+ this._sendNewIdentify();
+ return;
+ }
+ this.client.emit('debug', 'Identifying as resumed session');
+ const payload = {
+ token: this.client.token,
+ session_id: this.sessionID,
+ seq: this.sequence,
+ };
+
+ this.send({
+ op: Constants.OPCodes.RESUME,
+ d: payload,
+ });
+ }
+
+ /**
+ * Sends a new identification packet, in cases of new connections or failed reconnections.
+ */
+ _sendNewIdentify() {
+ this.reconnecting = false;
+ const payload = this.client.options.ws;
+ payload.token = this.client.token;
+ if (this.client.options.shardCount > 0) {
+ payload.shard = [Number(this.client.options.shardId), Number(this.client.options.shardCount)];
+ }
+ this.client.emit('debug', 'Identifying as new session');
+ this.send({
+ op: Constants.OPCodes.IDENTIFY,
+ d: payload,
+ });
+ this.sequence = -1;
+ }
+
+ /**
+ * @external CloseEvent
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent}
+ */
+
+ /**
+ * Run whenever the connection to the gateway is closed, it will try to reconnect the client.
+ * @param {CloseEvent} event The WebSocket close event
+ */
+ eventClose(event) {
+ this.emit('close', event);
+ this.client.clearInterval(this.client.manager.heartbeatInterval);
+ this.status = Constants.Status.DISCONNECTED;
+ this._queue = [];
+ /**
+ * Emitted whenever the client websocket is disconnected
+ * @event Client#disconnect
+ * @param {CloseEvent} event The WebSocket close event
+ */
+ if (!this.reconnecting) this.client.emit(Constants.Events.DISCONNECT, event);
+ if (event.code === 4004) return;
+ if (event.code === 4010) return;
+ if (!this.reconnecting && event.code !== 1000) this.tryReconnect();
+ }
+
+ /**
+ * Run whenever a message is received from the WebSocket. Returns `true` if the message
+ * was handled properly.
+ * @param {Object} event The received websocket data
+ * @returns {boolean}
+ */
+ eventMessage(event) {
+ const data = this.tryParseEventData(event.data);
+ if (data === null) {
+ this.eventError(new Error(Constants.Errors.BAD_WS_MESSAGE));
+ return false;
+ }
+
+ this.client.emit('raw', data);
+
+ if (data.op === Constants.OPCodes.HELLO) this.client.manager.setupKeepAlive(data.d.heartbeat_interval);
+ return this.packetManager.handle(data);
+ }
+
+ /**
+ * Parses the raw data from a websocket event, inflating it if necessary
+ * @param {*} data Event data
+ * @returns {Object}
+ */
+ parseEventData(data) {
+ if (erlpack) {
+ if (data instanceof ArrayBuffer) data = convertArrayBuffer(data);
+ return erlpack.unpack(data);
+ } else {
+ if (data instanceof ArrayBuffer) data = pako.inflate(data, { to: 'string' });
+ else if (data instanceof Buffer) data = zlib.inflateSync(data).toString();
+ return JSON.parse(data);
+ }
+ }
+
+ /**
+ * Tries to call `parseEventData()` and return its result, or returns `null` upon thrown errors.
+ * @param {*} data Event data
+ * @returns {?Object}
+ */
+ tryParseEventData(data) {
+ try {
+ return this.parseEventData(data);
+ } catch (err) {
+ return null;
+ }
+ }
+
+ /**
+ * Run whenever an error occurs with the WebSocket connection. Tries to reconnect
+ * @param {Error} err The encountered error
+ */
+ eventError(err) {
+ /**
+ * Emitted whenever the Client encounters a serious connection error
+ * @event Client#error
+ * @param {Error} error The encountered error
+ */
+ if (this.client.listenerCount('error') > 0) this.client.emit('error', err);
+ this.tryReconnect();
+ }
+
+ _emitReady(normal = true) {
+ /**
+ * Emitted when the Client becomes ready to start working
+ * @event Client#ready
+ */
+ this.status = Constants.Status.READY;
+ this.client.emit(Constants.Events.READY);
+ this.packetManager.handleQueue();
+ this.normalReady = normal;
+ }
+
+ /**
+ * Runs on new packets before `READY` to see if the Client is ready yet, if it is prepares
+ * the `READY` event.
+ */
+ checkIfReady() {
+ if (this.status !== Constants.Status.READY && this.status !== Constants.Status.NEARLY) {
+ let unavailableCount = 0;
+ for (const guildID of this.client.guilds.keys()) {
+ unavailableCount += this.client.guilds.get(guildID).available ? 0 : 1;
+ }
+ if (unavailableCount === 0) {
+ this.status = Constants.Status.NEARLY;
+ if (this.client.options.fetchAllMembers) {
+ const promises = this.client.guilds.map(g => g.fetchMembers());
+ Promise.all(promises).then(() => this._emitReady(), e => {
+ this.client.emit(Constants.Events.WARN, 'Error in pre-ready guild member fetching');
+ this.client.emit(Constants.Events.ERROR, e);
+ this._emitReady();
+ });
+ return;
+ }
+ this._emitReady();
+ }
+ }
+ }
+
+ /**
+ * Tries to reconnect the client, changing the status to Constants.Status.RECONNECTING.
+ */
+ tryReconnect() {
+ if (this.status === Constants.Status.RECONNECTING || this.status === Constants.Status.CONNECTING) return;
+ this.status = Constants.Status.RECONNECTING;
+ this.ws.close();
+ this.packetManager.handleQueue();
+ /**
+ * Emitted when the Client tries to reconnect after being disconnected
+ * @event Client#reconnecting
+ */
+ this.client.emit(Constants.Events.RECONNECTING);
+ this.connect(this.client.ws.gateway);
+ }
+}
+
+module.exports = WebSocketManager;
diff --git a/node_modules/discord.js/src/client/websocket/packets/WebSocketPacketManager.js b/node_modules/discord.js/src/client/websocket/packets/WebSocketPacketManager.js
new file mode 100644
index 0000000..78f5777
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/WebSocketPacketManager.js
@@ -0,0 +1,125 @@
+const Constants = require('../../../util/Constants');
+
+const BeforeReadyWhitelist = [
+ Constants.WSEvents.READY,
+ Constants.WSEvents.GUILD_CREATE,
+ Constants.WSEvents.GUILD_DELETE,
+ Constants.WSEvents.GUILD_MEMBERS_CHUNK,
+ Constants.WSEvents.GUILD_MEMBER_ADD,
+ Constants.WSEvents.GUILD_MEMBER_REMOVE,
+];
+
+class WebSocketPacketManager {
+ constructor(websocketManager) {
+ this.ws = websocketManager;
+ this.handlers = {};
+ this.queue = [];
+
+ this.register(Constants.WSEvents.READY, require('./handlers/Ready'));
+ this.register(Constants.WSEvents.GUILD_CREATE, require('./handlers/GuildCreate'));
+ this.register(Constants.WSEvents.GUILD_DELETE, require('./handlers/GuildDelete'));
+ this.register(Constants.WSEvents.GUILD_UPDATE, require('./handlers/GuildUpdate'));
+ this.register(Constants.WSEvents.GUILD_BAN_ADD, require('./handlers/GuildBanAdd'));
+ this.register(Constants.WSEvents.GUILD_BAN_REMOVE, require('./handlers/GuildBanRemove'));
+ this.register(Constants.WSEvents.GUILD_MEMBER_ADD, require('./handlers/GuildMemberAdd'));
+ this.register(Constants.WSEvents.GUILD_MEMBER_REMOVE, require('./handlers/GuildMemberRemove'));
+ this.register(Constants.WSEvents.GUILD_MEMBER_UPDATE, require('./handlers/GuildMemberUpdate'));
+ this.register(Constants.WSEvents.GUILD_ROLE_CREATE, require('./handlers/GuildRoleCreate'));
+ this.register(Constants.WSEvents.GUILD_ROLE_DELETE, require('./handlers/GuildRoleDelete'));
+ this.register(Constants.WSEvents.GUILD_ROLE_UPDATE, require('./handlers/GuildRoleUpdate'));
+ this.register(Constants.WSEvents.GUILD_EMOJIS_UPDATE, require('./handlers/GuildEmojisUpdate'));
+ this.register(Constants.WSEvents.GUILD_MEMBERS_CHUNK, require('./handlers/GuildMembersChunk'));
+ this.register(Constants.WSEvents.CHANNEL_CREATE, require('./handlers/ChannelCreate'));
+ this.register(Constants.WSEvents.CHANNEL_DELETE, require('./handlers/ChannelDelete'));
+ this.register(Constants.WSEvents.CHANNEL_UPDATE, require('./handlers/ChannelUpdate'));
+ this.register(Constants.WSEvents.CHANNEL_PINS_UPDATE, require('./handlers/ChannelPinsUpdate'));
+ this.register(Constants.WSEvents.PRESENCE_UPDATE, require('./handlers/PresenceUpdate'));
+ this.register(Constants.WSEvents.USER_UPDATE, require('./handlers/UserUpdate'));
+ this.register(Constants.WSEvents.USER_NOTE_UPDATE, require('./handlers/UserNoteUpdate'));
+ this.register(Constants.WSEvents.VOICE_STATE_UPDATE, require('./handlers/VoiceStateUpdate'));
+ this.register(Constants.WSEvents.TYPING_START, require('./handlers/TypingStart'));
+ this.register(Constants.WSEvents.MESSAGE_CREATE, require('./handlers/MessageCreate'));
+ this.register(Constants.WSEvents.MESSAGE_DELETE, require('./handlers/MessageDelete'));
+ this.register(Constants.WSEvents.MESSAGE_UPDATE, require('./handlers/MessageUpdate'));
+ this.register(Constants.WSEvents.MESSAGE_DELETE_BULK, require('./handlers/MessageDeleteBulk'));
+ this.register(Constants.WSEvents.VOICE_SERVER_UPDATE, require('./handlers/VoiceServerUpdate'));
+ this.register(Constants.WSEvents.GUILD_SYNC, require('./handlers/GuildSync'));
+ this.register(Constants.WSEvents.RELATIONSHIP_ADD, require('./handlers/RelationshipAdd'));
+ this.register(Constants.WSEvents.RELATIONSHIP_REMOVE, require('./handlers/RelationshipRemove'));
+ this.register(Constants.WSEvents.MESSAGE_REACTION_ADD, require('./handlers/MessageReactionAdd'));
+ this.register(Constants.WSEvents.MESSAGE_REACTION_REMOVE, require('./handlers/MessageReactionRemove'));
+ this.register(Constants.WSEvents.MESSAGE_REACTION_REMOVE_ALL, require('./handlers/MessageReactionRemoveAll'));
+ }
+
+ get client() {
+ return this.ws.client;
+ }
+
+ register(event, Handler) {
+ this.handlers[event] = new Handler(this);
+ }
+
+ handleQueue() {
+ this.queue.forEach((element, index) => {
+ this.handle(this.queue[index]);
+ this.queue.splice(index, 1);
+ });
+ }
+
+ setSequence(s) {
+ if (s && s > this.ws.sequence) this.ws.sequence = s;
+ }
+
+ handle(packet) {
+ if (packet.op === Constants.OPCodes.RECONNECT) {
+ this.setSequence(packet.s);
+ this.ws.tryReconnect();
+ return false;
+ }
+
+ if (packet.op === Constants.OPCodes.INVALID_SESSION) {
+ if (packet.d) {
+ setTimeout(() => {
+ this.ws._sendResume();
+ }, 2500);
+ } else {
+ this.ws.sessionID = null;
+ this.ws._sendNewIdentify();
+ }
+ return false;
+ }
+
+ if (packet.op === Constants.OPCodes.HEARTBEAT_ACK) {
+ this.ws.client._pong(this.ws.client._pingTimestamp);
+ this.ws.lastHeartbeatAck = true;
+ this.ws.client.emit('debug', 'Heartbeat acknowledged');
+ } else if (packet.op === Constants.OPCodes.HEARTBEAT) {
+ this.client.ws.send({
+ op: Constants.OPCodes.HEARTBEAT,
+ d: this.client.ws.sequence,
+ });
+ this.ws.client.emit('debug', 'Received gateway heartbeat');
+ }
+
+ if (this.ws.status === Constants.Status.RECONNECTING) {
+ this.ws.reconnecting = false;
+ this.ws.checkIfReady();
+ }
+
+ this.setSequence(packet.s);
+
+ if (this.ws.disabledEvents[packet.t] !== undefined) return false;
+
+ if (this.ws.status !== Constants.Status.READY) {
+ if (BeforeReadyWhitelist.indexOf(packet.t) === -1) {
+ this.queue.push(packet);
+ return false;
+ }
+ }
+
+ if (this.handlers[packet.t]) return this.handlers[packet.t].handle(packet);
+ return false;
+ }
+}
+
+module.exports = WebSocketPacketManager;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/AbstractHandler.js b/node_modules/discord.js/src/client/websocket/packets/handlers/AbstractHandler.js
new file mode 100644
index 0000000..c1c2a5a
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/AbstractHandler.js
@@ -0,0 +1,11 @@
+class AbstractHandler {
+ constructor(packetManager) {
+ this.packetManager = packetManager;
+ }
+
+ handle(packet) {
+ return packet;
+ }
+}
+
+module.exports = AbstractHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/ChannelCreate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/ChannelCreate.js
new file mode 100644
index 0000000..04cb298
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/ChannelCreate.js
@@ -0,0 +1,17 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class ChannelCreateHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.actions.ChannelCreate.handle(data);
+ }
+}
+
+/**
+ * Emitted whenever a channel is created.
+ * @event Client#channelCreate
+ * @param {Channel} channel The channel that was created
+ */
+
+module.exports = ChannelCreateHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/ChannelDelete.js b/node_modules/discord.js/src/client/websocket/packets/handlers/ChannelDelete.js
new file mode 100644
index 0000000..b25f585
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/ChannelDelete.js
@@ -0,0 +1,20 @@
+const AbstractHandler = require('./AbstractHandler');
+
+const Constants = require('../../../../util/Constants');
+
+class ChannelDeleteHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ const response = client.actions.ChannelDelete.handle(data);
+ if (response.channel) client.emit(Constants.Events.CHANNEL_DELETE, response.channel);
+ }
+}
+
+/**
+ * Emitted whenever a channel is deleted.
+ * @event Client#channelDelete
+ * @param {Channel} channel The channel that was deleted
+ */
+
+module.exports = ChannelDeleteHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/ChannelPinsUpdate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/ChannelPinsUpdate.js
new file mode 100644
index 0000000..636df81
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/ChannelPinsUpdate.js
@@ -0,0 +1,31 @@
+const AbstractHandler = require('./AbstractHandler');
+const Constants = require('../../../../util/Constants');
+
+/*
+{ t: 'CHANNEL_PINS_UPDATE',
+ s: 666,
+ op: 0,
+ d:
+ { last_pin_timestamp: '2016-08-28T17:37:13.171774+00:00',
+ channel_id: '314866471639044027' } }
+*/
+
+class ChannelPinsUpdate extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ const channel = client.channels.get(data.channel_id);
+ const time = new Date(data.last_pin_timestamp);
+ if (channel && time) client.emit(Constants.Events.CHANNEL_PINS_UPDATE, channel, time);
+ }
+}
+
+/**
+ * Emitted whenever the pins of a channel are updated. Due to the nature of the WebSocket event, not much information
+ * can be provided easily here - you need to manually check the pins yourself.
+ * @event Client#channelPinsUpdate
+ * @param {Channel} channel The channel that the pins update occured in
+ * @param {Date} time The time of the pins update
+ */
+
+module.exports = ChannelPinsUpdate;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/ChannelUpdate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/ChannelUpdate.js
new file mode 100644
index 0000000..fa535b1
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/ChannelUpdate.js
@@ -0,0 +1,11 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class ChannelUpdateHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.actions.ChannelUpdate.handle(data);
+ }
+}
+
+module.exports = ChannelUpdateHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/GuildBanAdd.js b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildBanAdd.js
new file mode 100644
index 0000000..60ce72d
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildBanAdd.js
@@ -0,0 +1,23 @@
+// ##untested handler##
+
+const AbstractHandler = require('./AbstractHandler');
+const Constants = require('../../../../util/Constants');
+
+class GuildBanAddHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ const guild = client.guilds.get(data.guild_id);
+ const user = client.users.get(data.user.id);
+ if (guild && user) client.emit(Constants.Events.GUILD_BAN_ADD, guild, user);
+ }
+}
+
+/**
+ * Emitted whenever a member is banned from a guild.
+ * @event Client#guildBanAdd
+ * @param {Guild} guild The guild that the ban occurred in
+ * @param {User} user The user that was banned
+ */
+
+module.exports = GuildBanAddHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/GuildBanRemove.js b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildBanRemove.js
new file mode 100644
index 0000000..c4edbde
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildBanRemove.js
@@ -0,0 +1,20 @@
+// ##untested handler##
+
+const AbstractHandler = require('./AbstractHandler');
+
+class GuildBanRemoveHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.actions.GuildBanRemove.handle(data);
+ }
+}
+
+/**
+ * Emitted whenever a member is unbanned from a guild.
+ * @event Client#guildBanRemove
+ * @param {Guild} guild The guild that the unban occurred in
+ * @param {User} user The user that was unbanned
+ */
+
+module.exports = GuildBanRemoveHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/GuildCreate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildCreate.js
new file mode 100644
index 0000000..c7fbd7e
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildCreate.js
@@ -0,0 +1,22 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class GuildCreateHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+
+ const guild = client.guilds.get(data.id);
+ if (guild) {
+ if (!guild.available && !data.unavailable) {
+ // a newly available guild
+ guild.setup(data);
+ this.packetManager.ws.checkIfReady();
+ }
+ } else {
+ // a new guild
+ client.dataManager.newGuild(data);
+ }
+ }
+}
+
+module.exports = GuildCreateHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/GuildDelete.js b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildDelete.js
new file mode 100644
index 0000000..35e3c53
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildDelete.js
@@ -0,0 +1,19 @@
+const AbstractHandler = require('./AbstractHandler');
+const Constants = require('../../../../util/Constants');
+
+class GuildDeleteHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ const response = client.actions.GuildDelete.handle(data);
+ if (response.guild) client.emit(Constants.Events.GUILD_DELETE, response.guild);
+ }
+}
+
+/**
+ * Emitted whenever a guild is deleted/left.
+ * @event Client#guildDelete
+ * @param {Guild} guild The guild that was deleted
+ */
+
+module.exports = GuildDeleteHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/GuildEmojisUpdate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildEmojisUpdate.js
new file mode 100644
index 0000000..c6ebdaa
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildEmojisUpdate.js
@@ -0,0 +1,40 @@
+const AbstractHandler = require('./AbstractHandler');
+
+function mappify(iterable) {
+ const map = new Map();
+ for (const x of iterable) map.set(...x);
+ return map;
+}
+
+class GuildEmojisUpdate extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ const guild = client.guilds.get(data.guild_id);
+ if (!guild || !guild.emojis) return;
+
+ const deletions = mappify(guild.emojis.entries());
+
+ for (const emoji of data.emojis) {
+ // determine type of emoji event
+ const cachedEmoji = guild.emojis.get(emoji.id);
+ if (cachedEmoji) {
+ deletions.delete(emoji.id);
+ if (!cachedEmoji.equals(emoji, true)) {
+ // emoji updated
+ client.actions.GuildEmojiUpdate.handle(cachedEmoji, emoji);
+ }
+ } else {
+ // emoji added
+ client.actions.GuildEmojiCreate.handle(guild, emoji);
+ }
+ }
+
+ for (const emoji of deletions.values()) {
+ // emoji deleted
+ client.actions.GuildEmojiDelete.handle(emoji);
+ }
+ }
+}
+
+module.exports = GuildEmojisUpdate;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/GuildMemberAdd.js b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildMemberAdd.js
new file mode 100644
index 0000000..d4d122f
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildMemberAdd.js
@@ -0,0 +1,17 @@
+// ##untested handler##
+
+const AbstractHandler = require('./AbstractHandler');
+
+class GuildMemberAddHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ const guild = client.guilds.get(data.guild_id);
+ if (guild) {
+ guild.memberCount++;
+ guild._addMember(data);
+ }
+ }
+}
+
+module.exports = GuildMemberAddHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/GuildMemberRemove.js b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildMemberRemove.js
new file mode 100644
index 0000000..6ec1bfe
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildMemberRemove.js
@@ -0,0 +1,13 @@
+// ##untested handler##
+
+const AbstractHandler = require('./AbstractHandler');
+
+class GuildMemberRemoveHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.actions.GuildMemberRemove.handle(data);
+ }
+}
+
+module.exports = GuildMemberRemoveHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/GuildMemberUpdate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildMemberUpdate.js
new file mode 100644
index 0000000..94ac71f
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildMemberUpdate.js
@@ -0,0 +1,18 @@
+// ##untested handler##
+
+const AbstractHandler = require('./AbstractHandler');
+
+class GuildMemberUpdateHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+
+ const guild = client.guilds.get(data.guild_id);
+ if (guild) {
+ const member = guild.members.get(data.user.id);
+ if (member) guild._updateMember(member, data);
+ }
+ }
+}
+
+module.exports = GuildMemberUpdateHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/GuildMembersChunk.js b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildMembersChunk.js
new file mode 100644
index 0000000..02a3c3c
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildMembersChunk.js
@@ -0,0 +1,28 @@
+// ##untested##
+
+const AbstractHandler = require('./AbstractHandler');
+const Constants = require('../../../../util/Constants');
+
+class GuildMembersChunkHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ const guild = client.guilds.get(data.guild_id);
+ if (!guild) return;
+
+ const members = data.members.map(member => guild._addMember(member, false));
+
+ guild._checkChunks();
+ client.emit(Constants.Events.GUILD_MEMBERS_CHUNK, members);
+
+ client.ws.lastHeartbeatAck = true;
+ }
+}
+
+/**
+ * Emitted whenever a chunk of guild members is received (all members come from the same guild)
+ * @event Client#guildMembersChunk
+ * @param {GuildMember[]} members The members in the chunk
+ */
+
+module.exports = GuildMembersChunkHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/GuildRoleCreate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildRoleCreate.js
new file mode 100644
index 0000000..8581d53
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildRoleCreate.js
@@ -0,0 +1,11 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class GuildRoleCreateHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.actions.GuildRoleCreate.handle(data);
+ }
+}
+
+module.exports = GuildRoleCreateHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/GuildRoleDelete.js b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildRoleDelete.js
new file mode 100644
index 0000000..63439b0
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildRoleDelete.js
@@ -0,0 +1,11 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class GuildRoleDeleteHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.actions.GuildRoleDelete.handle(data);
+ }
+}
+
+module.exports = GuildRoleDeleteHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/GuildRoleUpdate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildRoleUpdate.js
new file mode 100644
index 0000000..6fbdc10
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildRoleUpdate.js
@@ -0,0 +1,11 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class GuildRoleUpdateHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.actions.GuildRoleUpdate.handle(data);
+ }
+}
+
+module.exports = GuildRoleUpdateHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/GuildSync.js b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildSync.js
new file mode 100644
index 0000000..0b9f5aa
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildSync.js
@@ -0,0 +1,11 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class GuildSyncHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.actions.GuildSync.handle(data);
+ }
+}
+
+module.exports = GuildSyncHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/GuildUpdate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildUpdate.js
new file mode 100644
index 0000000..70eff52
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/GuildUpdate.js
@@ -0,0 +1,11 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class GuildUpdateHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.actions.GuildUpdate.handle(data);
+ }
+}
+
+module.exports = GuildUpdateHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/MessageCreate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/MessageCreate.js
new file mode 100644
index 0000000..058dc85
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/MessageCreate.js
@@ -0,0 +1,19 @@
+const AbstractHandler = require('./AbstractHandler');
+const Constants = require('../../../../util/Constants');
+
+class MessageCreateHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ const response = client.actions.MessageCreate.handle(data);
+ if (response.message) client.emit(Constants.Events.MESSAGE_CREATE, response.message);
+ }
+}
+
+/**
+ * Emitted whenever a message is created
+ * @event Client#message
+ * @param {Message} message The created message
+ */
+
+module.exports = MessageCreateHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/MessageDelete.js b/node_modules/discord.js/src/client/websocket/packets/handlers/MessageDelete.js
new file mode 100644
index 0000000..b06ce98
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/MessageDelete.js
@@ -0,0 +1,19 @@
+const AbstractHandler = require('./AbstractHandler');
+const Constants = require('../../../../util/Constants');
+
+class MessageDeleteHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ const response = client.actions.MessageDelete.handle(data);
+ if (response.message) client.emit(Constants.Events.MESSAGE_DELETE, response.message);
+ }
+}
+
+/**
+ * Emitted whenever a message is deleted
+ * @event Client#messageDelete
+ * @param {Message} message The deleted message
+ */
+
+module.exports = MessageDeleteHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/MessageDeleteBulk.js b/node_modules/discord.js/src/client/websocket/packets/handlers/MessageDeleteBulk.js
new file mode 100644
index 0000000..6cd3648
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/MessageDeleteBulk.js
@@ -0,0 +1,17 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class MessageDeleteBulkHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.actions.MessageDeleteBulk.handle(data);
+ }
+}
+
+/**
+ * Emitted whenever messages are deleted in bulk
+ * @event Client#messageDeleteBulk
+ * @param {Collection<string, Message>} messages The deleted messages, mapped by their ID
+ */
+
+module.exports = MessageDeleteBulkHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/MessageReactionAdd.js b/node_modules/discord.js/src/client/websocket/packets/handlers/MessageReactionAdd.js
new file mode 100644
index 0000000..a58db70
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/MessageReactionAdd.js
@@ -0,0 +1,11 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class MessageReactionAddHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.actions.MessageReactionAdd.handle(data);
+ }
+}
+
+module.exports = MessageReactionAddHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/MessageReactionRemove.js b/node_modules/discord.js/src/client/websocket/packets/handlers/MessageReactionRemove.js
new file mode 100644
index 0000000..cddde70
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/MessageReactionRemove.js
@@ -0,0 +1,11 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class MessageReactionRemove extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.actions.MessageReactionRemove.handle(data);
+ }
+}
+
+module.exports = MessageReactionRemove;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/MessageReactionRemoveAll.js b/node_modules/discord.js/src/client/websocket/packets/handlers/MessageReactionRemoveAll.js
new file mode 100644
index 0000000..303da9c
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/MessageReactionRemoveAll.js
@@ -0,0 +1,11 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class MessageReactionRemoveAll extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.actions.MessageReactionRemoveAll.handle(data);
+ }
+}
+
+module.exports = MessageReactionRemoveAll;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/MessageUpdate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/MessageUpdate.js
new file mode 100644
index 0000000..527632d
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/MessageUpdate.js
@@ -0,0 +1,11 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class MessageUpdateHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.actions.MessageUpdate.handle(data);
+ }
+}
+
+module.exports = MessageUpdateHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/PresenceUpdate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/PresenceUpdate.js
new file mode 100644
index 0000000..09d78a0
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/PresenceUpdate.js
@@ -0,0 +1,72 @@
+const AbstractHandler = require('./AbstractHandler');
+const Constants = require('../../../../util/Constants');
+const cloneObject = require('../../../../util/CloneObject');
+
+class PresenceUpdateHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ let user = client.users.get(data.user.id);
+ const guild = client.guilds.get(data.guild_id);
+
+ // step 1
+ if (!user) {
+ if (data.user.username) {
+ user = client.dataManager.newUser(data.user);
+ } else {
+ return;
+ }
+ }
+
+ const oldUser = cloneObject(user);
+ user.patch(data.user);
+ if (!user.equals(oldUser)) {
+ client.emit(Constants.Events.USER_UPDATE, oldUser, user);
+ }
+
+ if (guild) {
+ let member = guild.members.get(user.id);
+ if (!member && data.status !== 'offline') {
+ member = guild._addMember({
+ user,
+ roles: data.roles,
+ deaf: false,
+ mute: false,
+ }, false);
+ client.emit(Constants.Events.GUILD_MEMBER_AVAILABLE, member);
+ }
+ if (member) {
+ const oldMember = cloneObject(member);
+ if (member.presence) {
+ oldMember.frozenPresence = cloneObject(member.presence);
+ }
+ guild._setPresence(user.id, data);
+ client.emit(Constants.Events.PRESENCE_UPDATE, oldMember, member);
+ } else {
+ guild._setPresence(user.id, data);
+ }
+ }
+ }
+}
+
+/**
+ * Emitted whenever a guild member's presence changes, or they change one of their details.
+ * @event Client#presenceUpdate
+ * @param {GuildMember} oldMember The member before the presence update
+ * @param {GuildMember} newMember The member after the presence update
+ */
+
+/**
+ * Emitted whenever a user's details (e.g. username) are changed.
+ * @event Client#userUpdate
+ * @param {User} oldUser The user before the update
+ * @param {User} newUser The user after the update
+ */
+
+/**
+ * Emitted whenever a member becomes available in a large guild
+ * @event Client#guildMemberAvailable
+ * @param {GuildMember} member The member that became available
+ */
+
+module.exports = PresenceUpdateHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/Ready.js b/node_modules/discord.js/src/client/websocket/packets/handlers/Ready.js
new file mode 100644
index 0000000..10bc6b2
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/Ready.js
@@ -0,0 +1,69 @@
+const AbstractHandler = require('./AbstractHandler');
+
+const ClientUser = require('../../../../structures/ClientUser');
+
+class ReadyHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+
+ client.ws.heartbeat();
+
+ const clientUser = new ClientUser(client, data.user);
+ client.user = clientUser;
+ client.readyAt = new Date();
+ client.users.set(clientUser.id, clientUser);
+
+ for (const guild of data.guilds) client.dataManager.newGuild(guild);
+ for (const privateDM of data.private_channels) client.dataManager.newChannel(privateDM);
+
+ for (const relation of data.relationships) {
+ const user = client.dataManager.newUser(relation.user);
+ if (relation.type === 1) {
+ client.user.friends.set(user.id, user);
+ } else if (relation.type === 2) {
+ client.user.blocked.set(user.id, user);
+ }
+ }
+
+ data.presences = data.presences || [];
+ for (const presence of data.presences) {
+ client.dataManager.newUser(presence.user);
+ client._setPresence(presence.user.id, presence);
+ }
+
+ if (data.notes) {
+ for (const user in data.notes) {
+ let note = data.notes[user];
+ if (!note.length) note = null;
+
+ client.user.notes.set(user, note);
+ }
+ }
+
+ if (!client.user.bot && client.options.sync) client.setInterval(client.syncGuilds.bind(client), 30000);
+ client.once('ready', client.syncGuilds.bind(client));
+
+ if (!client.users.has('1')) {
+ client.dataManager.newUser({
+ id: '1',
+ username: 'Clyde',
+ discriminator: '0000',
+ avatar: 'https://discordapp.com/assets/f78426a064bc9dd24847519259bc42af.png',
+ bot: true,
+ status: 'online',
+ game: null,
+ verified: true,
+ });
+ }
+
+ client.setTimeout(() => {
+ if (!client.ws.normalReady) client.ws._emitReady(false);
+ }, 1200 * data.guilds.length);
+
+ this.packetManager.ws.sessionID = data.session_id;
+ this.packetManager.ws.checkIfReady();
+ }
+}
+
+module.exports = ReadyHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/RelationshipAdd.js b/node_modules/discord.js/src/client/websocket/packets/handlers/RelationshipAdd.js
new file mode 100644
index 0000000..122b4c5
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/RelationshipAdd.js
@@ -0,0 +1,19 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class RelationshipAddHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ if (data.type === 1) {
+ client.fetchUser(data.id).then(user => {
+ client.user.friends.set(user.id, user);
+ });
+ } else if (data.type === 2) {
+ client.fetchUser(data.id).then(user => {
+ client.user.blocked.set(user.id, user);
+ });
+ }
+ }
+}
+
+module.exports = RelationshipAddHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/RelationshipRemove.js b/node_modules/discord.js/src/client/websocket/packets/handlers/RelationshipRemove.js
new file mode 100644
index 0000000..b57326a
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/RelationshipRemove.js
@@ -0,0 +1,19 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class RelationshipRemoveHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ if (data.type === 2) {
+ if (client.user.blocked.has(data.id)) {
+ client.user.blocked.delete(data.id);
+ }
+ } else if (data.type === 1) {
+ if (client.user.friends.has(data.id)) {
+ client.user.friends.delete(data.id);
+ }
+ }
+ }
+}
+
+module.exports = RelationshipRemoveHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/TypingStart.js b/node_modules/discord.js/src/client/websocket/packets/handlers/TypingStart.js
new file mode 100644
index 0000000..1a35ca7
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/TypingStart.js
@@ -0,0 +1,68 @@
+const AbstractHandler = require('./AbstractHandler');
+const Constants = require('../../../../util/Constants');
+
+class TypingStartHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ const channel = client.channels.get(data.channel_id);
+ const user = client.users.get(data.user_id);
+ const timestamp = new Date(data.timestamp * 1000);
+
+ if (channel && user) {
+ if (channel.type === 'voice') {
+ client.emit(Constants.Events.WARN, `Discord sent a typing packet to voice channel ${channel.id}`);
+ return;
+ }
+ if (channel._typing.has(user.id)) {
+ const typing = channel._typing.get(user.id);
+ typing.lastTimestamp = timestamp;
+ typing.resetTimeout(tooLate(channel, user));
+ } else {
+ channel._typing.set(user.id, new TypingData(client, timestamp, timestamp, tooLate(channel, user)));
+ client.emit(Constants.Events.TYPING_START, channel, user);
+ }
+ }
+ }
+}
+
+class TypingData {
+ constructor(client, since, lastTimestamp, _timeout) {
+ this.client = client;
+ this.since = since;
+ this.lastTimestamp = lastTimestamp;
+ this._timeout = _timeout;
+ }
+
+ resetTimeout(_timeout) {
+ this.client.clearTimeout(this._timeout);
+ this._timeout = _timeout;
+ }
+
+ get elapsedTime() {
+ return Date.now() - this.since;
+ }
+}
+
+function tooLate(channel, user) {
+ return channel.client.setTimeout(() => {
+ channel.client.emit(Constants.Events.TYPING_STOP, channel, user, channel._typing.get(user.id));
+ channel._typing.delete(user.id);
+ }, 6000);
+}
+
+/**
+ * Emitted whenever a user starts typing in a channel
+ * @event Client#typingStart
+ * @param {Channel} channel The channel the user started typing in
+ * @param {User} user The user that started typing
+ */
+
+/**
+ * Emitted whenever a user stops typing in a channel
+ * @event Client#typingStop
+ * @param {Channel} channel The channel the user stopped typing in
+ * @param {User} user The user that stopped typing
+ */
+
+module.exports = TypingStartHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/UserNoteUpdate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/UserNoteUpdate.js
new file mode 100644
index 0000000..1e4777a
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/UserNoteUpdate.js
@@ -0,0 +1,12 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class UserNoteUpdateHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+
+ client.actions.UserNoteUpdate.handle(data);
+ }
+}
+
+module.exports = UserNoteUpdateHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/UserUpdate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/UserUpdate.js
new file mode 100644
index 0000000..bc34f34
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/UserUpdate.js
@@ -0,0 +1,11 @@
+const AbstractHandler = require('./AbstractHandler');
+
+class UserUpdateHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.actions.UserUpdate.handle(data);
+ }
+}
+
+module.exports = UserUpdateHandler;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/VoiceServerUpdate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/VoiceServerUpdate.js
new file mode 100644
index 0000000..97885d6
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/VoiceServerUpdate.js
@@ -0,0 +1,19 @@
+const AbstractHandler = require('./AbstractHandler');
+
+/*
+{
+ "token": "my_token",
+ "guild_id": "41771983423143937",
+ "endpoint": "smart.loyal.discord.gg"
+}
+*/
+
+class VoiceServerUpdate extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+ client.emit('self.voiceServer', data);
+ }
+}
+
+module.exports = VoiceServerUpdate;
diff --git a/node_modules/discord.js/src/client/websocket/packets/handlers/VoiceStateUpdate.js b/node_modules/discord.js/src/client/websocket/packets/handlers/VoiceStateUpdate.js
new file mode 100644
index 0000000..ddbfbfc
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/packets/handlers/VoiceStateUpdate.js
@@ -0,0 +1,49 @@
+const AbstractHandler = require('./AbstractHandler');
+
+const Constants = require('../../../../util/Constants');
+const cloneObject = require('../../../../util/CloneObject');
+
+class VoiceStateUpdateHandler extends AbstractHandler {
+ handle(packet) {
+ const client = this.packetManager.client;
+ const data = packet.d;
+
+ const guild = client.guilds.get(data.guild_id);
+ if (guild) {
+ const member = guild.members.get(data.user_id);
+ if (member) {
+ const oldVoiceChannelMember = cloneObject(member);
+ if (member.voiceChannel && member.voiceChannel.id !== data.channel_id) {
+ member.voiceChannel.members.delete(oldVoiceChannelMember.id);
+ }
+
+ // if the member left the voice channel, unset their speaking property
+ if (!data.channel_id) member.speaking = null;
+
+ if (member.user.id === client.user.id && data.channel_id) {
+ client.emit('self.voiceStateUpdate', data);
+ }
+
+ const newChannel = client.channels.get(data.channel_id);
+ if (newChannel) newChannel.members.set(member.user.id, member);
+
+ member.serverMute = data.mute;
+ member.serverDeaf = data.deaf;
+ member.selfMute = data.self_mute;
+ member.selfDeaf = data.self_deaf;
+ member.voiceSessionID = data.session_id;
+ member.voiceChannelID = data.channel_id;
+ client.emit(Constants.Events.VOICE_STATE_UPDATE, oldVoiceChannelMember, member);
+ }
+ }
+ }
+}
+
+/**
+ * Emitted whenever a user changes voice state - e.g. joins/leaves a channel, mutes/unmutes.
+ * @event Client#voiceStateUpdate
+ * @param {GuildMember} oldMember The member before the voice state update
+ * @param {GuildMember} newMember The member after the voice state update
+ */
+
+module.exports = VoiceStateUpdateHandler;