From 9956e43c8e0f2424eb6d19ee03b6fb83e6d00f42 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sat, 16 Apr 2016 22:58:49 +0100
Subject: [PATCH 001/324] initial
---
.gitignore | 38 ++++
.jscsrc | 10 +
LICENSE | 201 ++++++++++++++++++
README.md | 6 +
package.json | 56 +++++
src/client/Client.js | 34 +++
src/client/ClientManager.js | 34 +++
src/client/rest/RESTManager.js | 53 +++++
src/client/rest/RESTMethods.js | 37 ++++
src/client/rest/UserAgentManager.js | 24 +++
src/client/websocket/WebSocketManager.js | 79 +++++++
.../packets/WebSocketPacketManager.js | 44 ++++
.../packets/handlers/AbstractHandler.js | 14 ++
.../packets/handlers/ChannelCreate.js | 28 +++
.../packets/handlers/ChannelDelete.js | 31 +++
.../packets/handlers/ChannelUpdate.js | 33 +++
.../websocket/packets/handlers/GuildBanAdd.js | 33 +++
.../packets/handlers/GuildBanRemove.js | 33 +++
.../websocket/packets/handlers/GuildCreate.js | 38 ++++
.../websocket/packets/handlers/GuildDelete.js | 41 ++++
.../packets/handlers/GuildMemberAdd.js | 32 +++
.../packets/handlers/GuildMemberRemove.js | 33 +++
.../packets/handlers/GuildMemberUpdate.js | 33 +++
.../websocket/packets/handlers/GuildUpdate.js | 32 +++
.../websocket/packets/handlers/Ready.js | 36 ++++
src/index.js | 15 ++
src/structures/Channel.js | 16 ++
src/structures/ClientUser.js | 17 ++
src/structures/DMChannel.js | 17 ++
src/structures/Guild.js | 91 ++++++++
src/structures/Message.js | 9 +
src/structures/ServerChannel.js | 22 ++
src/structures/TextChannel.js | 13 ++
src/structures/User.js | 20 ++
src/structures/VoiceChannel.js | 16 ++
src/structures/datastore/AbstractDataStore.js | 43 ++++
src/structures/datastore/ClientDataStore.js | 111 ++++++++++
src/structures/datastore/GuildDataStore.js | 16 ++
.../datastore/TextChannelDataStore.js | 12 ++
src/util/CloneObject.js | 7 +
src/util/Constants.js | 118 ++++++++++
src/util/MergeDefault.js | 19 ++
test/random.js | 39 ++++
43 files changed, 1634 insertions(+)
create mode 100644 .gitignore
create mode 100644 .jscsrc
create mode 100644 LICENSE
create mode 100644 README.md
create mode 100644 package.json
create mode 100644 src/client/Client.js
create mode 100644 src/client/ClientManager.js
create mode 100644 src/client/rest/RESTManager.js
create mode 100644 src/client/rest/RESTMethods.js
create mode 100644 src/client/rest/UserAgentManager.js
create mode 100644 src/client/websocket/WebSocketManager.js
create mode 100644 src/client/websocket/packets/WebSocketPacketManager.js
create mode 100644 src/client/websocket/packets/handlers/AbstractHandler.js
create mode 100644 src/client/websocket/packets/handlers/ChannelCreate.js
create mode 100644 src/client/websocket/packets/handlers/ChannelDelete.js
create mode 100644 src/client/websocket/packets/handlers/ChannelUpdate.js
create mode 100644 src/client/websocket/packets/handlers/GuildBanAdd.js
create mode 100644 src/client/websocket/packets/handlers/GuildBanRemove.js
create mode 100644 src/client/websocket/packets/handlers/GuildCreate.js
create mode 100644 src/client/websocket/packets/handlers/GuildDelete.js
create mode 100644 src/client/websocket/packets/handlers/GuildMemberAdd.js
create mode 100644 src/client/websocket/packets/handlers/GuildMemberRemove.js
create mode 100644 src/client/websocket/packets/handlers/GuildMemberUpdate.js
create mode 100644 src/client/websocket/packets/handlers/GuildUpdate.js
create mode 100644 src/client/websocket/packets/handlers/Ready.js
create mode 100644 src/index.js
create mode 100644 src/structures/Channel.js
create mode 100644 src/structures/ClientUser.js
create mode 100644 src/structures/DMChannel.js
create mode 100644 src/structures/Guild.js
create mode 100644 src/structures/Message.js
create mode 100644 src/structures/ServerChannel.js
create mode 100644 src/structures/TextChannel.js
create mode 100644 src/structures/User.js
create mode 100644 src/structures/VoiceChannel.js
create mode 100644 src/structures/datastore/AbstractDataStore.js
create mode 100644 src/structures/datastore/ClientDataStore.js
create mode 100644 src/structures/datastore/GuildDataStore.js
create mode 100644 src/structures/datastore/TextChannelDataStore.js
create mode 100644 src/util/CloneObject.js
create mode 100644 src/util/Constants.js
create mode 100644 src/util/MergeDefault.js
create mode 100644 test/random.js
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..d1ca39f79
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+# Created by https://www.gitignore.io
+
+.tmp/
+.vscode/
+
+### Node ###
+# Logs
+logs
+*.log
+
+test/auth.json
+
+# Runtime data
+pids
+*.pid
+*.seed
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directory
+# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
+node_modules
+test/auth.json
+examples/auth.json
+docs/_build
\ No newline at end of file
diff --git a/.jscsrc b/.jscsrc
new file mode 100644
index 000000000..d636656da
--- /dev/null
+++ b/.jscsrc
@@ -0,0 +1,10 @@
+{
+ "preset": "airbnb",
+ "validateIndentation": "\t",
+ "maximumLineLength": 140,
+ "maxErrors": 5000,
+ "disallowMultipleVarDecl": false,
+ "disallowSpacesInsideObjectBrackets": false,
+ "disallowMixedSpacesAndTabs": false,
+ "excludeFiles": []
+}
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 000000000..8dada3eda
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
new file mode 100644
index 000000000..2514699cb
--- /dev/null
+++ b/README.md
@@ -0,0 +1,6 @@
+
+
+
+
+
REWRITE
+
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 000000000..08a7c794e
--- /dev/null
+++ b/package.json
@@ -0,0 +1,56 @@
+{
+ "name": "discord.js",
+ "version": "7.0.0",
+ "description": "A way to interface with the Discord API",
+ "main": "./src/index",
+ "scripts": {
+ "test": "jscs src && node test/random"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/hydrabolt/discord.js.git"
+ },
+ "keywords": [
+ "discord",
+ "api",
+ "bot",
+ "client",
+ "node",
+ "discordapp"
+ ],
+ "author": "Amish Shah ",
+ "license": "Apache-2.0",
+ "bugs": {
+ "url": "https://github.com/hydrabolt/discord.js/issues"
+ },
+ "homepage": "https://github.com/hydrabolt/discord.js#readme",
+ "dependencies": {
+ "babel-plugin-transform-runtime": "^6.6.0",
+ "object.entries": "^1.0.3",
+ "object.values": "^1.0.3",
+ "superagent": "^1.5.0",
+ "unpipe": "^1.0.0",
+ "ws": "^0.8.1"
+ },
+ "devDependencies": {
+ "babel-preset-es2015": "^6.6.0",
+ "babel-preset-stage-3": "^6.5.0",
+ "grunt": "^0.4.5",
+ "grunt-babel": "^6.0.0",
+ "grunt-browserify": "^4.0.1",
+ "grunt-contrib-uglify": "^0.11.0",
+ "grunt-jscs": "^2.8.0",
+ "jscs": "^2.11.0",
+ "load-grunt-tasks": "^3.3.0"
+ },
+ "optionalDependencies": {
+ "node-opus": "^0.1.11"
+ },
+ "engines": {
+ "node": ">=0.12.7"
+ },
+ "browser": {
+ "./src/Util/TokenCacher.js": "./src/Util/TokenCacher-shim.js",
+ "./lib/Util/TokenCacher.js": "./lib/Util/TokenCacher-shim.js"
+ }
+}
diff --git a/src/client/Client.js b/src/client/Client.js
new file mode 100644
index 000000000..634cc790f
--- /dev/null
+++ b/src/client/Client.js
@@ -0,0 +1,34 @@
+'use strict';
+
+const EventEmitter = require('events').EventEmitter;
+const MergeDefault = require('../util/MergeDefault');
+const Constants = require('../util/Constants');
+const RESTManager = require('./rest/RestManager');
+const ClientDataStore = require('../structures/DataStore/ClientDataStore');
+const ClientManager = require('./ClientManager');
+const WebSocketManager = require('./websocket/WebSocketManager');
+
+class Client extends EventEmitter{
+
+ constructor(options) {
+ super();
+ this.options = MergeDefault(Constants.DefaultOptions, options);
+ this.rest = new RESTManager(this);
+ this.store = new ClientDataStore(this);
+ this.manager = new ClientManager(this);
+ this.ws = new WebSocketManager(this);
+ }
+
+ login(email, password) {
+ if (password) {
+ // login with email and password
+ return this.rest.methods.LoginEmailPassword(email, password);
+ } else {
+ // login with token
+ return this.rest.methods.LoginToken(email);
+ }
+ }
+
+}
+
+module.exports = Client;
diff --git a/src/client/ClientManager.js b/src/client/ClientManager.js
new file mode 100644
index 000000000..00ffc5c69
--- /dev/null
+++ b/src/client/ClientManager.js
@@ -0,0 +1,34 @@
+'use strict';
+
+const Constants = require('../util/Constants');
+
+class ClientManager {
+
+ constructor(client) {
+ this.client = client;
+ this.heartbeatInterval = null;
+ }
+
+ connectToWebSocket(token, resolve, reject) {
+ this.client.store.token = token;
+ this.client.rest.methods.GetGateway()
+ .then(gateway => {
+ this.client.ws.connect(gateway);
+ this.client.once(Constants.Events.READY, () => resolve(token));
+ })
+ .catch(reject);
+
+ setTimeout(() => reject(Constants.Errors.TOOK_TOO_LONG), 1000 * 15);
+ }
+
+ setupKeepAlive(time) {
+ this.heartbeatInterval = setInterval(() => {
+ this.client.ws.send({
+ op: Constants.OPCodes.HEARTBEAT,
+ d: Date.now(),
+ });
+ }, time);
+ }
+}
+
+module.exports = ClientManager;
diff --git a/src/client/rest/RESTManager.js b/src/client/rest/RESTManager.js
new file mode 100644
index 000000000..5cda94ccd
--- /dev/null
+++ b/src/client/rest/RESTManager.js
@@ -0,0 +1,53 @@
+'use strict';
+
+const request = require('superagent');
+const Constants = require('../../util/Constants');
+const UserAgentManager = require('./UserAgentManager');
+const RESTMethods = require('./RESTMethods');
+
+class RESTManager{
+
+ constructor(client) {
+ this.client = client;
+ this.queue = [];
+ this.userAgentManager = new UserAgentManager(this);
+ this.methods = new RESTMethods(this);
+ }
+
+ makeRequest(method, url, auth, data, file) {
+ /*
+ file is {file, name}
+ */
+ let apiRequest = request[method](url);
+
+ if (auth) {
+ if (this.client.store.token) {
+ apiRequest.set('authorization', this.client.store.token);
+ } else {
+ throw Constants.Errors.NO_TOKEN;
+ }
+ }
+
+ if (data) {
+ apiRequest.send(data);
+ }
+
+ if (file) {
+ apiRequest.attach('file', file.file, file.name);
+ }
+
+ apiRequest.set('User-Agent', this.userAgentManager.userAgent);
+
+ return new Promise((resolve, reject) => {
+ apiRequest.end((err, res) => {
+ if (err) {
+ reject(err);
+ } else {
+ resolve(res ? res.body || {} : {});
+ }
+ });
+ });
+ }
+};
+
+module.exports = RESTManager;
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
new file mode 100644
index 000000000..228f6f7da
--- /dev/null
+++ b/src/client/rest/RESTMethods.js
@@ -0,0 +1,37 @@
+'use strict';
+
+const Constants = require('../../util/Constants');
+
+class RESTMethods{
+ constructor(restManager) {
+ this.rest = restManager;
+ }
+
+ LoginEmailPassword(email, password) {
+ return new Promise((resolve, reject) => {
+
+ this.rest.makeRequest('post', Constants.Endpoints.LOGIN, false, { email, password })
+ .then(data => {
+ this.rest.client.manager.connectToWebSocket(data.token, resolve, reject);
+ })
+ .catch(reject);
+
+ });
+ }
+
+ LoginToken(token) {
+ return new Promise((resolve, reject) => {
+ this.rest.client.manager.connectToWebSocket(token, resolve, reject);
+ });
+ }
+
+ GetGateway() {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('get', Constants.Endpoints.GATEWAY, true)
+ .then(res => resolve(res.url))
+ .catch(reject);
+ });
+ }
+}
+
+module.exports = RESTMethods;
diff --git a/src/client/rest/UserAgentManager.js b/src/client/rest/UserAgentManager.js
new file mode 100644
index 000000000..9fb075fca
--- /dev/null
+++ b/src/client/rest/UserAgentManager.js
@@ -0,0 +1,24 @@
+'use strict';
+
+const Constants = require('../../util/Constants');
+
+class UserAgentManager{
+ constructor(restManager) {
+ this.restManager = restManager;
+ this._userAgent = {
+ url: 'https://github.com/hydrabolt/discord.js',
+ version: Constants.Package.version,
+ };
+ }
+
+ set(info) {
+ this._userAgent.url = info.url || 'https://github.com/hydrabolt/discord.js';
+ this._userAgent.version = info.version || Constants.Package.version;
+ }
+
+ get userAgent() {
+ return `DiscordBot (${this._userAgent.url}, ${this._userAgent.version})`;
+ }
+}
+
+module.exports = UserAgentManager;
diff --git a/src/client/websocket/WebSocketManager.js b/src/client/websocket/WebSocketManager.js
new file mode 100644
index 000000000..ae9b8c550
--- /dev/null
+++ b/src/client/websocket/WebSocketManager.js
@@ -0,0 +1,79 @@
+'use strict';
+
+const WebSocket = require('ws');
+const Constants = require('../../util/Constants');
+const zlib = require('zlib');
+const PacketManager = require('./packets/WebSocketPacketManager');
+
+class WebSocketManager {
+
+ constructor(client) {
+ this.client = client;
+ this.ws = null;
+ this.packetManager = new PacketManager(this);
+ this.emittedReady = false;
+ }
+
+ connect(gateway) {
+ gateway += `/?v=${this.client.options.protocol_version}`;
+ this.ws = new WebSocket(gateway);
+ this.ws.onopen = () => this.EventOpen();
+ this.ws.onclose = () => this.EventClose();
+ this.ws.onmessage = (e) => this.EventMessage(e);
+ this.ws.onerror = (e) => this.EventError(e);
+ }
+
+ send(data) {
+ this.ws.send(JSON.stringify(data));
+ }
+
+ EventOpen() {
+ let payload = this.client.options.ws;
+ payload.token = this.client.store.token;
+
+ this.send({
+ op: Constants.OPCodes.IDENTIFY,
+ d: payload,
+ });
+ }
+
+ EventClose() {
+
+ }
+
+ EventMessage(event) {
+ let packet;
+ try {
+ if (event.binary) {
+ event.data = zlib.inflateSync(event.data).toString();
+ }
+
+ packet = JSON.parse(event.data);
+ } catch (e) {
+ return this.EventError(Constants.Errors.BAD_WS_MESSAGE);
+ }
+
+ this.packetManager.handle(packet);
+ }
+
+ EventError(e) {
+
+ }
+
+ checkIfReady() {
+ if (!this.emittedReady) {
+ let unavailableCount = 0;
+
+ for (let guildID in this.client.store.data.guilds) {
+ unavailableCount += this.client.store.data.guilds[guildID].available ? 0 : 1;
+ }
+
+ if (unavailableCount === 0) {
+ this.client.emit(Constants.Events.READY);
+ this.emittedReady = true;
+ }
+ }
+ }
+}
+
+module.exports = WebSocketManager;
diff --git a/src/client/websocket/packets/WebSocketPacketManager.js b/src/client/websocket/packets/WebSocketPacketManager.js
new file mode 100644
index 000000000..cb114bad6
--- /dev/null
+++ b/src/client/websocket/packets/WebSocketPacketManager.js
@@ -0,0 +1,44 @@
+'use strict';
+
+const Constants = require('../../../util/Constants');
+
+class WebSocketPacketManager {
+
+ constructor(websocketManager) {
+ this.ws = websocketManager;
+ this.handlers = {};
+
+ this.register(Constants.WSEvents.READY, 'Ready');
+ this.register(Constants.WSEvents.GUILD_CREATE, 'GuildCreate');
+ this.register(Constants.WSEvents.GUILD_DELETE, 'GuildDelete');
+ this.register(Constants.WSEvents.GUILD_UPDATE, 'GuildUpdate');
+ this.register(Constants.WSEvents.GUILD_BAN_ADD, 'GuildBanAdd');
+ this.register(Constants.WSEvents.GUILD_BAN_REMOVE, 'GuildBanRemove');
+ this.register(Constants.WSEvents.GUILD_MEMBER_ADD, 'GuildMemberAdd');
+ this.register(Constants.WSEvents.GUILD_MEMBER_REMOVE, 'GuildMemberRemove');
+ this.register(Constants.WSEvents.GUILD_MEMBER_UPDATE, 'GuildMemberUpdate');
+ this.register(Constants.WSEvents.CHANNEL_CREATE, 'ChannelCreate');
+ this.register(Constants.WSEvents.CHANNEL_DELETE, 'ChannelDelete');
+ this.register(Constants.WSEvents.CHANNEL_UPDATE, 'ChannelUpdate');
+ }
+
+ get client() {
+ return this.ws.client;
+ }
+
+ register(event, handle) {
+ let Handler = require(`./handlers/${handle}`);
+ this.handlers[event] = new Handler(this);
+ }
+
+ handle(packet) {
+ if (this.handlers[packet.t]) {
+ return this.handlers[packet.t].handle(packet);
+ }
+
+ return false;
+ }
+
+}
+
+module.exports = WebSocketPacketManager;
diff --git a/src/client/websocket/packets/handlers/AbstractHandler.js b/src/client/websocket/packets/handlers/AbstractHandler.js
new file mode 100644
index 000000000..9ab096dd6
--- /dev/null
+++ b/src/client/websocket/packets/handlers/AbstractHandler.js
@@ -0,0 +1,14 @@
+'use strict';
+
+class AbstractHandler {
+
+ constructor(packetManager) {
+ this.packetManager = packetManager;
+ }
+
+ handle(packet) {
+
+ }
+}
+
+module.exports = AbstractHandler;
diff --git a/src/client/websocket/packets/handlers/ChannelCreate.js b/src/client/websocket/packets/handlers/ChannelCreate.js
new file mode 100644
index 000000000..d938be358
--- /dev/null
+++ b/src/client/websocket/packets/handlers/ChannelCreate.js
@@ -0,0 +1,28 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+
+const ClientUser = Structure('ClientUser');
+const Guild = Structure('Guild');
+const DMChannel = Structure('DMChannel');
+
+const Constants = require('../../../../util/Constants');
+
+class ChannelCreateHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let channel = client.store.NewChannel(data);
+
+ }
+
+};
+
+module.exports = ChannelCreateHandler;
diff --git a/src/client/websocket/packets/handlers/ChannelDelete.js b/src/client/websocket/packets/handlers/ChannelDelete.js
new file mode 100644
index 000000000..e94d052a0
--- /dev/null
+++ b/src/client/websocket/packets/handlers/ChannelDelete.js
@@ -0,0 +1,31 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+
+const ClientUser = Structure('ClientUser');
+const Guild = Structure('Guild');
+const ServerChannel = Structure('ServerChannel');
+
+const Constants = require('../../../../util/Constants');
+
+class ChannelDeleteHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let channel = client.store.get('channels', data.id);
+
+ if (channel) {
+ client.store.KillChannel(channel);
+ }
+ }
+
+};
+
+module.exports = ChannelDeleteHandler;
diff --git a/src/client/websocket/packets/handlers/ChannelUpdate.js b/src/client/websocket/packets/handlers/ChannelUpdate.js
new file mode 100644
index 000000000..d44a15855
--- /dev/null
+++ b/src/client/websocket/packets/handlers/ChannelUpdate.js
@@ -0,0 +1,33 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+
+const ClientUser = Structure('ClientUser');
+const Guild = Structure('Guild');
+const ServerChannel = Structure('ServerChannel');
+
+const Constants = require('../../../../util/Constants');
+const CloneObject = require('../../../../util/CloneObject');
+
+class ChannelUpdateHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let channel = client.store.get('channels', data.id);
+
+ if (channel) {
+ client.store.UpdateChannel(channel, data);
+ }
+
+ }
+
+};
+
+module.exports = ChannelUpdateHandler;
diff --git a/src/client/websocket/packets/handlers/GuildBanAdd.js b/src/client/websocket/packets/handlers/GuildBanAdd.js
new file mode 100644
index 000000000..7294b2fca
--- /dev/null
+++ b/src/client/websocket/packets/handlers/GuildBanAdd.js
@@ -0,0 +1,33 @@
+'use strict';
+
+// ##untested handler##
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+
+const ClientUser = Structure('ClientUser');
+const Guild = Structure('Guild');
+
+const Constants = require('../../../../util/Constants');
+
+class GuildBanAddHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let guild = client.store.get('guilds', data.guild_id);
+ let user = client.store.get('users', data.user.id);
+
+ if (guild && user) {
+ client.emit(Constants.Events.GUILD_BAN_ADD, guild, user);
+ }
+ }
+
+};
+
+module.exports = GuildBanAddHandler;
diff --git a/src/client/websocket/packets/handlers/GuildBanRemove.js b/src/client/websocket/packets/handlers/GuildBanRemove.js
new file mode 100644
index 000000000..ec792f1bf
--- /dev/null
+++ b/src/client/websocket/packets/handlers/GuildBanRemove.js
@@ -0,0 +1,33 @@
+'use strict';
+
+// ##untested handler##
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+
+const ClientUser = Structure('ClientUser');
+const Guild = Structure('Guild');
+
+const Constants = require('../../../../util/Constants');
+
+class GuildBanRemoveHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let guild = client.store.get('guilds', data.guild_id);
+ let user = client.store.get('users', data.user.id);
+
+ if (guild && user) {
+ client.emit(Constants.Events.GUILD_BAN_REMOVE, guild, user);
+ }
+ }
+
+};
+
+module.exports = GuildBanRemoveHandler;
diff --git a/src/client/websocket/packets/handlers/GuildCreate.js b/src/client/websocket/packets/handlers/GuildCreate.js
new file mode 100644
index 000000000..96777a79d
--- /dev/null
+++ b/src/client/websocket/packets/handlers/GuildCreate.js
@@ -0,0 +1,38 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+
+const ClientUser = Structure('ClientUser');
+const Guild = Structure('Guild');
+
+const Constants = require('../../../../util/Constants');
+
+class GuildCreateHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let guild = client.store.get('guilds', 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.store.NewGuild(data);
+ }
+
+ }
+
+};
+
+module.exports = GuildCreateHandler;
diff --git a/src/client/websocket/packets/handlers/GuildDelete.js b/src/client/websocket/packets/handlers/GuildDelete.js
new file mode 100644
index 000000000..550628ac0
--- /dev/null
+++ b/src/client/websocket/packets/handlers/GuildDelete.js
@@ -0,0 +1,41 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+
+const ClientUser = Structure('ClientUser');
+const Guild = Structure('Guild');
+
+const Constants = require('../../../../util/Constants');
+
+class GuildDeleteHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let guild = client.store.get('guilds', data.id);
+
+ if (guild) {
+ if (guild.available && data.unavailable) {
+ // guild is unavailable
+ guild.available = false;
+ client.emit(Constants.Events.GUILD_UNAVAILABLE, guild);
+ } else {
+ // delete guild
+ client.store.KillGuild(guild);
+ }
+ } else {
+ // it's not there! :(
+ client.emit('warn', 'guild deleted but not cached in first place. missed packet?');
+ }
+
+ }
+
+};
+
+module.exports = GuildDeleteHandler;
diff --git a/src/client/websocket/packets/handlers/GuildMemberAdd.js b/src/client/websocket/packets/handlers/GuildMemberAdd.js
new file mode 100644
index 000000000..23a475f96
--- /dev/null
+++ b/src/client/websocket/packets/handlers/GuildMemberAdd.js
@@ -0,0 +1,32 @@
+'use strict';
+
+// ##untested handler##
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+
+const ClientUser = Structure('ClientUser');
+const Guild = Structure('Guild');
+
+const Constants = require('../../../../util/Constants');
+
+class GuildMemberAddHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let guild = client.store.get('guilds', data.guild_id);
+
+ if (guild) {
+ guild._addMember(data);
+ }
+ }
+
+};
+
+module.exports = GuildMemberAddHandler;
diff --git a/src/client/websocket/packets/handlers/GuildMemberRemove.js b/src/client/websocket/packets/handlers/GuildMemberRemove.js
new file mode 100644
index 000000000..53a20fa2a
--- /dev/null
+++ b/src/client/websocket/packets/handlers/GuildMemberRemove.js
@@ -0,0 +1,33 @@
+'use strict';
+
+// ##untested handler##
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+
+const ClientUser = Structure('ClientUser');
+const Guild = Structure('Guild');
+
+const Constants = require('../../../../util/Constants');
+
+class GuildMemberRemoveHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let guild = client.store.get('guilds', data.guild_id);
+ let user = client.store.get('users', data.user.id);
+
+ if (guild && user) {
+ guild._removeMember(user);
+ }
+ }
+
+};
+
+module.exports = GuildMemberRemoveHandler;
diff --git a/src/client/websocket/packets/handlers/GuildMemberUpdate.js b/src/client/websocket/packets/handlers/GuildMemberUpdate.js
new file mode 100644
index 000000000..e54daaa8f
--- /dev/null
+++ b/src/client/websocket/packets/handlers/GuildMemberUpdate.js
@@ -0,0 +1,33 @@
+'use strict';
+
+// ##untested handler##
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+
+const ClientUser = Structure('ClientUser');
+const Guild = Structure('Guild');
+
+const Constants = require('../../../../util/Constants');
+
+class GuildMemberUpdateHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let guild = client.store.get('guilds', data.guild_id);
+ let user = client.store.get('users', data.user.id);
+
+ if (guild) {
+ guild._updateMember(user, data);
+ }
+ }
+
+};
+
+module.exports = GuildMemberUpdateHandler;
diff --git a/src/client/websocket/packets/handlers/GuildUpdate.js b/src/client/websocket/packets/handlers/GuildUpdate.js
new file mode 100644
index 000000000..e74effbfc
--- /dev/null
+++ b/src/client/websocket/packets/handlers/GuildUpdate.js
@@ -0,0 +1,32 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+
+const ClientUser = Structure('ClientUser');
+const Guild = Structure('Guild');
+
+const Constants = require('../../../../util/Constants');
+const CloneObject = require('../../../../util/CloneObject');
+
+class GuildUpdateHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let guild = client.store.get('guilds', data.id);
+
+ if (guild) {
+ client.store.UpdateGuild(guild, data);
+ }
+
+ }
+
+};
+
+module.exports = GuildUpdateHandler;
diff --git a/src/client/websocket/packets/handlers/Ready.js b/src/client/websocket/packets/handlers/Ready.js
new file mode 100644
index 000000000..cd512a5e8
--- /dev/null
+++ b/src/client/websocket/packets/handlers/Ready.js
@@ -0,0 +1,36 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+
+const ClientUser = Structure('ClientUser');
+const Guild = Structure('Guild');
+const DMChannel = Structure('DMChannel');
+
+class ReadyHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ client.manager.setupKeepAlive(data.heartbeat_interval);
+
+ client.store.user = client.store.add('users', new ClientUser(client, data.user));
+
+ for (let guild of data.guilds) {
+ client.store.NewGuild(guild);
+ }
+
+ for (let privateDM of data.private_channels) {
+ client.store.NewChannel(privateDM);
+ }
+
+ }
+
+};
+
+module.exports = ReadyHandler;
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 000000000..1c2103a4c
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,15 @@
+'use strict';
+
+const entries = require('object.entries');
+const values = require('object.values');
+const Client = require('./client/Client');
+
+if (!Object.entries) {
+ entries.shim();
+}
+
+if (!Object.values) {
+ values.shim();
+}
+
+exports.Client = Client;
diff --git a/src/structures/Channel.js b/src/structures/Channel.js
new file mode 100644
index 000000000..ae9950c33
--- /dev/null
+++ b/src/structures/Channel.js
@@ -0,0 +1,16 @@
+'use strict';
+
+class Channel {
+ constructor(client, data) {
+ this.client = client;
+ if (data) {
+ this.setup(data);
+ }
+ }
+
+ setup(data) {
+ this.id = data.id;
+ }
+}
+
+module.exports = Channel;
diff --git a/src/structures/ClientUser.js b/src/structures/ClientUser.js
new file mode 100644
index 000000000..19b84d5b8
--- /dev/null
+++ b/src/structures/ClientUser.js
@@ -0,0 +1,17 @@
+'use strict';
+
+const User = require('./User');
+
+class ClientUser extends User {
+ constructor(client, data) {
+ super(client, data);
+ }
+
+ setup(data) {
+ super.setup(data);
+ this.verified = data.verified;
+ this.email = data.email;
+ }
+}
+
+module.exports = ClientUser;
diff --git a/src/structures/DMChannel.js b/src/structures/DMChannel.js
new file mode 100644
index 000000000..0db181e96
--- /dev/null
+++ b/src/structures/DMChannel.js
@@ -0,0 +1,17 @@
+'use strict';
+
+const Channel = require('./Channel');
+const User = require('./User');
+
+class DMChannel extends Channel{
+ constructor(client, data) {
+ super(client, data);
+ }
+
+ setup(data) {
+ this.recipient = this.client.store.add('users', new User(this.client, data.recipient));
+ this.lastMessageID = data.last_message_id;
+ }
+}
+
+module.exports = DMChannel;
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
new file mode 100644
index 000000000..f230ad86b
--- /dev/null
+++ b/src/structures/Guild.js
@@ -0,0 +1,91 @@
+'use strict';
+
+const User = require('./User');
+const GuildDataStore = require('./datastore/GuildDataStore');
+const TextChannel = require('./TextChannel');
+const VoiceChannel = require('./VoiceChannel');
+const Constants = require('../Util/Constants');
+
+class Guild {
+ constructor(client, data) {
+ this.client = client;
+ this.store = new GuildDataStore();
+
+ if (!data) {
+ return;
+ }
+
+ if (data.unavailable) {
+ this.available = false;
+ this.id = data.id;
+ } else {
+ this.available = true;
+ this.setup(data);
+ }
+ }
+
+ _addMember(guildUser) {
+ let user = this.client.store.NewUser(guildUser.user);
+ this.store.memberData[user.id] = {
+ deaf: guildUser.deaf,
+ mute: guildUser.mute,
+ joinDate: new Date(guildUser.joined_at),
+ roles: guildUser.roles,
+ };
+ if (this.client.ws.emittedReady) {
+ this.client.emit(Constants.Events.GUILD_MEMBER_ADD, this, user);
+ }
+ }
+
+ _updateMember(currentUser, newData) {
+ let oldRoles = this.store.memberData[currentUser.id].roles;
+ this.store.currentUser[currentUser.id].roles = newData.roles;
+ if (this.client.ws.emittedReady) {
+ this.client.emit(Constants.Events.GUILD_MEMBER_ROLES_UPDATE, this, oldRoles, this.store.memberData[currentUser.id].roles);
+ }
+ }
+
+ _removeMember(guildUser) {
+ this.store.remove('members', guildUser);
+ if (this.client.ws.emittedReady) {
+ this.client.emit(Constants.Events.GUILD_MEMBER_REMOVE, this, guildUser);
+ }
+ }
+
+ setup(data) {
+ this.id = data.id;
+ this.available = !data.unavailable;
+ this.splash = data.splash;
+ this.region = data.region;
+ this.ownerID = data.owner_id;
+ this.name = data.name;
+ this.memberCount = data.member_count;
+ this.large = data.large;
+ this.joinDate = new Date(data.joined_at);
+ this.icon = data.icon;
+ this.features = data.features;
+ this.emojis = data.emojis;
+ this.afkTimeout = data.afk_timeout;
+ this.afkChannelID = data.afk_channel_id;
+ this.embedEnabled = data.embed_enabled;
+ this.embedChannelID = data.embed_channel_id;
+ this.verificationLevel = data.verification_level;
+ this.features = data.features || [];
+
+ if (data.members) {
+ this.store.clear('members');
+ for (let guildUser of data.members) {
+ this._addMember(guildUser);
+ }
+ }
+
+ if (data.channels) {
+ this.store.clear('channels');
+ for (let channel of data.channels) {
+ this.client.store.NewChannel(channel, this);
+ }
+ }
+ }
+}
+
+module.exports = Guild;
diff --git a/src/structures/Message.js b/src/structures/Message.js
new file mode 100644
index 000000000..30d7fc4ac
--- /dev/null
+++ b/src/structures/Message.js
@@ -0,0 +1,9 @@
+'use strict';
+
+class Message {
+ constructor() {
+
+ }
+}
+
+module.exports = Message;
diff --git a/src/structures/ServerChannel.js b/src/structures/ServerChannel.js
new file mode 100644
index 000000000..32294b0ab
--- /dev/null
+++ b/src/structures/ServerChannel.js
@@ -0,0 +1,22 @@
+'use strict';
+
+const Channel = require('./Channel');
+
+class ServerChannel extends Channel{
+ constructor(guild, data) {
+ super(guild.client, data);
+ this.guild = guild;
+ }
+
+ setup(data) {
+ super.setup(data);
+ this.type = data.type;
+ this.topic = data.topic;
+ this.position = data.position;
+ this.permissionOverwrites = data.permission_overwrites;
+ this.name = data.name;
+ this.lastMessageID = data.last_message_id;
+ }
+}
+
+module.exports = ServerChannel;
diff --git a/src/structures/TextChannel.js b/src/structures/TextChannel.js
new file mode 100644
index 000000000..e8b2b6acc
--- /dev/null
+++ b/src/structures/TextChannel.js
@@ -0,0 +1,13 @@
+'use strict';
+
+const ServerChannel = require('./ServerChannel');
+const TextChannelDataStore = require('./datastore/TextChannelDataStore');
+
+class TextChannel extends ServerChannel {
+ constructor(guild, data) {
+ super(guild, data);
+ this.store = new TextChannelDataStore();
+ }
+}
+
+module.exports = TextChannel;
diff --git a/src/structures/User.js b/src/structures/User.js
new file mode 100644
index 000000000..50487077f
--- /dev/null
+++ b/src/structures/User.js
@@ -0,0 +1,20 @@
+'use strict';
+
+class User {
+ constructor(client, data) {
+ this.client = client;
+ if (data) {
+ this.setup(data);
+ }
+ }
+
+ setup(data) {
+ this.username = data.username;
+ this.id = data.id;
+ this.discriminator = data.discriminator;
+ this.avatar = data.avatar;
+ this.bot = Boolean(data.bot);
+ }
+}
+
+module.exports = User;
diff --git a/src/structures/VoiceChannel.js b/src/structures/VoiceChannel.js
new file mode 100644
index 000000000..7a69e2b19
--- /dev/null
+++ b/src/structures/VoiceChannel.js
@@ -0,0 +1,16 @@
+'use strict';
+
+const ServerChannel = require('./ServerChannel');
+
+class VoiceChannel extends ServerChannel {
+ constructor(guild, data) {
+ super(guild, data);
+ }
+
+ setup(data) {
+ super.setup(data);
+ this.bitrate = data.bitrate;
+ }
+}
+
+module.exports = VoiceChannel;
diff --git a/src/structures/datastore/AbstractDataStore.js b/src/structures/datastore/AbstractDataStore.js
new file mode 100644
index 000000000..24bfec497
--- /dev/null
+++ b/src/structures/datastore/AbstractDataStore.js
@@ -0,0 +1,43 @@
+'use strict';
+
+class AbstractDataStore{
+ constructor() {
+ this.data = {};
+ }
+
+ register(name) {
+ this.data[name] = {};
+ }
+
+ add(location, object) {
+ if (this.data[location][object.id]) {
+ return this.data[location][object.id];
+ } else {
+ return this.data[location][object.id] = object;
+ }
+ }
+
+ clear(location) {
+ this.data[location] = {};
+ }
+
+ remove(location, object) {
+ let id = (typeof object === 'string' || object instanceof String) ? object : object.id;
+ if (this.data[location][id]) {
+ delete this.data[location][id];
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ get(location, value) {
+ return this.data[location][value];
+ }
+
+ getAsArray(location) {
+ return Object.values(this.data[location]);
+ }
+}
+
+module.exports = AbstractDataStore;
diff --git a/src/structures/datastore/ClientDataStore.js b/src/structures/datastore/ClientDataStore.js
new file mode 100644
index 000000000..6b9a89488
--- /dev/null
+++ b/src/structures/datastore/ClientDataStore.js
@@ -0,0 +1,111 @@
+'use strict';
+
+const AbstractDataStore = require('./AbstractDataStore');
+const Constants = require('../../util/Constants');
+const CloneObject = require('../../util/CloneObject');
+const Guild = require('../Guild');
+const User = require('../User');
+const DMChannel = require('../DMChannel');
+const TextChannel = require('../TextChannel');
+const VoiceChannel = require('../VoiceChannel');
+const ServerChannel = require('../ServerChannel');
+
+class ClientDataStore extends AbstractDataStore{
+ constructor(client) {
+ super();
+
+ this.client = client;
+ this.token = null;
+ this.session = null;
+ this.user = null;
+
+ this.register('users');
+ this.register('guilds');
+ this.register('channels');
+ }
+
+ get pastReady() {
+ return this.client.ws.emittedReady;
+ }
+
+ NewGuild(data) {
+ let already = this.get('guilds', data.id);
+ let guild = this.add('guilds', new Guild(this.client, data));
+ if (this.pastReady && !already) {
+ this.client.emit(Constants.Events.GUILD_CREATE, guild);
+ }
+
+ return guild;
+ }
+
+ NewUser(data) {
+ return this.add('users', new User(this.client, data));
+ }
+
+ NewChannel(data, guild) {
+ let already = this.get('channels', data.id);
+ let channel;
+ if (data.is_private) {
+ channel = new DMChannel(this.client, data);
+ }else {
+ guild = guild || this.get('guilds', data.guild_id);
+ if (guild) {
+ if (data.type === 'text') {
+ channel = new TextChannel(guild, data);
+ guild.store.add('channels', channel);
+ }else if (data.type === 'voice') {
+ channel = new VoiceChannel(guild, data);
+ guild.store.add('channels', channel);
+ }
+ }
+ }
+
+ if (channel) {
+ if (this.pastReady && !already) {
+ this.client.emit(Constants.Events.CHANNEL_CREATE, channel);
+ }
+
+ return this.add('channels', channel);
+ }
+ }
+
+ KillGuild(guild) {
+ let already = this.get('guilds', guilds.id);
+ this.remove('guilds', guild);
+ if (already && this.pastReady) {
+ this.client.emit(Constants.Events.GUILD_DELETE, guild);
+ }
+ }
+
+ KillUser(user) {
+ this.remove('users', user);
+ }
+
+ KillChannel(channel) {
+ let already = this.get('channels', channel.id);
+ this.remove('channels', channel);
+ if (channel instanceof ServerChannel) {
+ channel.guild.store.remove('channels', channel);
+ }
+
+ if (already && this.pastReady) {
+ this.client.emit(Constants.Events.CHANNEL_DELETE, channel);
+ }
+ }
+
+ UpdateGuild(currentGuild, newData) {
+ let oldGuild = CloneObject(currentGuild);
+ currentGuild.setup(newData);
+ if (this.pastReady) {
+ this.client.emit(Constants.Events.GUILD_UPDATE, oldGuild, currentGuild);
+ }
+ }
+
+ UpdateChannel(currentChannel, newData) {
+ let oldChannel = CloneObject(currentChannel);
+ currentChannel.setup(newData);
+ this.client.emit(Constants.Events.CHANNEL_UPDATE, oldChannel, currentChannel);
+ }
+}
+
+module.exports = ClientDataStore;
diff --git a/src/structures/datastore/GuildDataStore.js b/src/structures/datastore/GuildDataStore.js
new file mode 100644
index 000000000..fc541b33a
--- /dev/null
+++ b/src/structures/datastore/GuildDataStore.js
@@ -0,0 +1,16 @@
+'use strict';
+
+const AbstractDataStore = require('./AbstractDataStore');
+
+class GuildDataStore extends AbstractDataStore{
+ constructor() {
+ super();
+
+ this.memberData = {};
+
+ this.register('members');
+ this.register('channels');
+ }
+}
+
+module.exports = GuildDataStore;
diff --git a/src/structures/datastore/TextChannelDataStore.js b/src/structures/datastore/TextChannelDataStore.js
new file mode 100644
index 000000000..08316431b
--- /dev/null
+++ b/src/structures/datastore/TextChannelDataStore.js
@@ -0,0 +1,12 @@
+'use strict';
+
+const AbstractDataStore = require('./AbstractDataStore');
+
+class TextChannelDataStore extends AbstractDataStore{
+ constructor() {
+ super();
+ this.register('messages');
+ }
+}
+
+module.exports = TextChannelDataStore;
diff --git a/src/util/CloneObject.js b/src/util/CloneObject.js
new file mode 100644
index 000000000..158f9d189
--- /dev/null
+++ b/src/util/CloneObject.js
@@ -0,0 +1,7 @@
+'use strict';
+module.exports = function CloneObject(obj) {
+ var cloned = Object.create(obj);
+ Object.assign(cloned, obj);
+
+ return cloned;
+};
diff --git a/src/util/Constants.js b/src/util/Constants.js
new file mode 100644
index 000000000..5adc1636c
--- /dev/null
+++ b/src/util/Constants.js
@@ -0,0 +1,118 @@
+const DefaultOptions = exports.DefaultOptions = {
+ ws: {
+ large_threshold: 250,
+ compress: true,
+ properties: {
+ $os: process ? process.platform : 'discord.js',
+ $browser: 'discord.js',
+ $device: 'discord.js',
+ $referrer: '',
+ $referring_domain: '',
+ },
+ },
+ protocol_version: 4,
+};
+
+const Package = exports.Package = require('../../package.json');
+
+const Errors = exports.Errors = {
+ NO_TOKEN: new Error('request to use token, but token was unavailable to the client'),
+ NO_BOT_ACCOUNT: new Error('you should ideally be using a bot account!'),
+ BAD_WS_MESSAGE: new Error('a bad message was received from the websocket - bad compression or not json'),
+ TOOK_TOO_LONG: new Error('something took too long to do'),
+};
+
+const API = 'https://discordapp.com/api';
+
+const Endpoints = exports.Endpoints = {
+ // general endpoints
+ LOGIN: `${API}/auth/login`,
+ LOGOUT: `${API}/auth/logout`,
+ ME: `${API}/users/@me`,
+ ME_GUILD: (guildID) => `${Endpoints.ME}/guilds/${guildID}`,
+ GATEWAY: `${API}/gateway`,
+ USER_CHANNELS: (userID) => `${API}/users/${userID}/channels`,
+ AVATAR: (userID, avatar) => `${API}/users/${userID}/avatars/${avatar}.jpg`,
+ INVITE: (id) => `${API}/invite/${id}`,
+
+ // guilds
+ GUILDS: `${API}/guilds`,
+ GUILD: (guildID) => `${Endpoints.GUILDS}/${guildID}`,
+ GUILD_ICON: (guildID, hash) => `${Endpoints.GUILD(guildID)}/icons/${hash}.jpg`,
+ GUILD_PRUNE: (guildID) => `${Endpoints.GUILD(guildID)}/prune`,
+ GUILD_EMBED: (guildID) => `${Endpoints.GUILD(guildID)}/embed`,
+ GUILD_INVITES: (guildID) => `${Endpoints.GUILD(guildID)}/invites`,
+ GUILD_ROLES: (guildID) => `${Endpoints.GUILD(guildID)}/roles`,
+ GUILD_BANS: (guildID) => `${Endpoints.GUILD(guildID)}/bans`,
+ GUILD_INTEGRATIONS: (guildID) => `${Endpoints.GUILD(guildID)}/integrations`,
+ GUILD_MEMBERS: (guildID) => `${Endpoints.GUILD(guildID)}/members`,
+ GUILD_CHANNELS: (guildID) => `${Endpoints.GUILD(guildID)}/channels`,
+
+ // channels
+ CHANNELS: `${API}/channels`,
+ CHANNEL: (channelID) => `${Endpoints.CHANNELS}/${channelID}`,
+ CHANNEL_MESSAGES: (channelID) => `${Endpoints.CHANNEL(channelID)}/messages`,
+ CHANNEL_INVITES: (channelID) => `${Endpoints.CHANNEL(channelID)}/invites`,
+ CHANNEL_TYPING: (channelID) => `${Endpoints.CHANNEL(channelID)}/typing`,
+ CHANNEL_PERMISSIONS: (channelID) => `${Endpoints.CHANNEL(channelID)}/permissions`,
+ CHANNEL_MESSAGE: (channelID, messageID) => `${Endpoints.CHANNEL_MESSAGES(channelID)}/${messageID}`,
+};
+
+const OPCodes = exports.OPCodes = {
+ DISPATCH: 0,
+ HEARTBEAT: 1,
+ IDENTIFY: 2,
+ STATUS_UPDATE: 3,
+ VOICE_STATE_UPDATE: 4,
+ VOICE_GUILD_PING: 5,
+ RESUME: 6,
+ RECONNECT: 7,
+ REQUEST_GUILD_MEMBERS: 8,
+ INVALID_SESSION: 9,
+};
+
+const Events = exports.Events = {
+ READY: 'ready',
+ GUILD_CREATE: 'guildCreate',
+ GUILD_DELETE: 'guildDelete',
+ GUILD_UNAVAILABLE: 'guildUnavailable',
+ GUILD_AVAILABLE: 'guildAvailable',
+ GUILD_UPDATE: 'guildUpdate',
+ GUILD_BAN_ADD: 'guildBanAdd',
+ GUILD_BAN_REMOVE: 'guildBanRemove',
+ GUILD_MEMBER_ADD: 'guildMemberAdd',
+ GUILD_MEMBER_REMOVE: 'guildMemberRemove',
+ GUILD_MEMBER_ROLES_UPDATE: 'guildMemberRolesUpdate',
+ CHANNEL_CREATE: 'channelCreate',
+ CHANNEL_DELETE: 'channelDelete',
+ CHANNEL_UPDATE: 'channelUpdate',
+ WARN: 'warn',
+};
+
+const WSEvents = exports.WSEvents = {
+ CHANNEL_CREATE: 'CHANNEL_CREATE',
+ CHANNEL_DELETE: 'CHANNEL_DELETE',
+ CHANNEL_UPDATE: 'CHANNEL_UPDATE',
+ MESSAGE_CREATE: 'MESSAGE_CREATE',
+ MESSAGE_DELETE: 'MESSAGE_DELETE',
+ MESSAGE_UPDATE: 'MESSAGE_UPDATE',
+ PRESENCE_UPDATE: 'PRESENCE_UPDATE',
+ READY: 'READY',
+ GUILD_BAN_ADD: 'GUILD_BAN_ADD',
+ GUILD_BAN_REMOVE: 'GUILD_BAN_REMOVE',
+ GUILD_CREATE: 'GUILD_CREATE',
+ GUILD_DELETE: 'GUILD_DELETE',
+ GUILD_MEMBER_ADD: 'GUILD_MEMBER_ADD',
+ GUILD_MEMBER_REMOVE: 'GUILD_MEMBER_REMOVE',
+ GUILD_MEMBER_UPDATE: 'GUILD_MEMBER_UPDATE',
+ GUILD_MEMBERS_CHUNK: 'GUILD_MEMBERS_CHUNK',
+ GUILD_ROLE_CREATE: 'GUILD_ROLE_CREATE',
+ GUILD_ROLE_DELETE: 'GUILD_ROLE_DELETE',
+ GUILD_ROLE_UPDATE: 'GUILD_ROLE_UPDATE',
+ GUILD_UPDATE: 'GUILD_UPDATE',
+ TYPING: 'TYPING_START',
+ USER_UPDATE: 'USER_UPDATE',
+ VOICE_STATE_UPDATE: 'VOICE_STATE_UPDATE',
+ FRIEND_ADD: 'RELATIONSHIP_ADD',
+ FRIEND_REMOVE: 'RELATIONSHIP_REMOVE',
+};
diff --git a/src/util/MergeDefault.js b/src/util/MergeDefault.js
new file mode 100644
index 000000000..3da11d278
--- /dev/null
+++ b/src/util/MergeDefault.js
@@ -0,0 +1,19 @@
+'use strict';
+
+module.exports = function merge(def, given) {
+ if (!given) {
+ return def;
+ }
+
+ given = given || {};
+
+ for (var key in def) {
+ if (!given.hasOwnProperty(key)) {
+ given[key] = def[key];
+ } else if (given[key] === Object(given[key])) {
+ given[key] = merge(def[key], given[key]);
+ }
+ }
+
+ return given;
+};
diff --git a/test/random.js b/test/random.js
new file mode 100644
index 000000000..300bc25e9
--- /dev/null
+++ b/test/random.js
@@ -0,0 +1,39 @@
+'use strict';
+
+const Discord = require('../');
+
+let client = new Discord.Client();
+
+client.login(require('./auth.json').token).then(token => console.log('ready!')).catch(console.log);
+
+client.on('ready', () => {
+});
+
+client.on('guildCreate', (guild) => {
+ console.log(guild);
+});
+client.on('guildDelete', (guild) => {
+ console.log(guild);
+});
+client.on('guildUpdate', (old, guild) => {
+ console.log(old.name, guild.name);
+});
+client.on('channelCreate', channel => {
+ console.log(channel);
+});
+client.on('channelDelete', channel => {
+ console.log(channel);
+});
+
+client.on('channelUpdate', (old, chan) => {
+ console.log('chan update', old.name, chan.name);
+});
+
+client.on('guildMemberAdd', (guild, user) => {
+ console.log('new guild member', user.username, 'in', guild.name);
+});
+
+client.on('guildMemberRemove', (guild, user) => {
+ console.log('dead guild member', user.username, 'in', guild.name);
+});
+
From ccffe09bca04ff88a1d7ff07d88d64b87d8aa0a6 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sat, 16 Apr 2016 23:01:58 +0100
Subject: [PATCH 002/324] remove unused shim object.entries
---
package.json | 1 -
src/index.js | 5 -----
2 files changed, 6 deletions(-)
diff --git a/package.json b/package.json
index 08a7c794e..b3e6705e3 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,6 @@
"homepage": "https://github.com/hydrabolt/discord.js#readme",
"dependencies": {
"babel-plugin-transform-runtime": "^6.6.0",
- "object.entries": "^1.0.3",
"object.values": "^1.0.3",
"superagent": "^1.5.0",
"unpipe": "^1.0.0",
diff --git a/src/index.js b/src/index.js
index 1c2103a4c..6dc2c55cb 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,13 +1,8 @@
'use strict';
-const entries = require('object.entries');
const values = require('object.values');
const Client = require('./client/Client');
-if (!Object.entries) {
- entries.shim();
-}
-
if (!Object.values) {
values.shim();
}
From 30f5e2943a9d496dbe739e125cd4b99cda6ede6c Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sat, 16 Apr 2016 23:24:52 +0100
Subject: [PATCH 003/324] Create Member class, stop storing member data
separately and merge into one class with a User
---
.../packets/handlers/GuildMemberRemove.js | 8 ++--
.../packets/handlers/GuildMemberUpdate.js | 6 ++-
src/structures/Guild.js | 26 +++++-------
src/structures/Member.js | 42 +++++++++++++++++++
src/structures/datastore/GuildDataStore.js | 2 -
5 files changed, 62 insertions(+), 22 deletions(-)
create mode 100644 src/structures/Member.js
diff --git a/src/client/websocket/packets/handlers/GuildMemberRemove.js b/src/client/websocket/packets/handlers/GuildMemberRemove.js
index 53a20fa2a..a46556c38 100644
--- a/src/client/websocket/packets/handlers/GuildMemberRemove.js
+++ b/src/client/websocket/packets/handlers/GuildMemberRemove.js
@@ -21,10 +21,12 @@ class GuildMemberRemoveHandler extends AbstractHandler {
let client = this.packetManager.client;
let guild = client.store.get('guilds', data.guild_id);
- let user = client.store.get('users', data.user.id);
- if (guild && user) {
- guild._removeMember(user);
+ if (guild) {
+ let member = guild.store.get('members', data.user.id);
+ if (member) {
+ guild._removeMember(member);
+ }
}
}
diff --git a/src/client/websocket/packets/handlers/GuildMemberUpdate.js b/src/client/websocket/packets/handlers/GuildMemberUpdate.js
index e54daaa8f..20455a216 100644
--- a/src/client/websocket/packets/handlers/GuildMemberUpdate.js
+++ b/src/client/websocket/packets/handlers/GuildMemberUpdate.js
@@ -21,10 +21,12 @@ class GuildMemberUpdateHandler extends AbstractHandler {
let client = this.packetManager.client;
let guild = client.store.get('guilds', data.guild_id);
- let user = client.store.get('users', data.user.id);
if (guild) {
- guild._updateMember(user, data);
+ let member = guild.store.get('members', data.user.id);
+ if (member) {
+ guild._updateMember(member, data);
+ }
}
}
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index f230ad86b..f61b3c259 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -1,6 +1,7 @@
'use strict';
const User = require('./User');
+const Member = require('./Member');
const GuildDataStore = require('./datastore/GuildDataStore');
const TextChannel = require('./TextChannel');
const VoiceChannel = require('./VoiceChannel');
@@ -25,30 +26,25 @@ class Guild {
}
_addMember(guildUser) {
- let user = this.client.store.NewUser(guildUser.user);
- this.store.memberData[user.id] = {
- deaf: guildUser.deaf,
- mute: guildUser.mute,
- joinDate: new Date(guildUser.joined_at),
- roles: guildUser.roles,
- };
+ guildUser.user = this.client.store.NewUser(guildUser.user);
+ let member = this.store.add('members', new Member(this, guildUser));
if (this.client.ws.emittedReady) {
- this.client.emit(Constants.Events.GUILD_MEMBER_ADD, this, user);
+ this.client.emit(Constants.Events.GUILD_MEMBER_ADD, this, member);
}
}
- _updateMember(currentUser, newData) {
- let oldRoles = this.store.memberData[currentUser.id].roles;
- this.store.currentUser[currentUser.id].roles = newData.roles;
+ _updateMember(member, data) {
+ let oldRoles = member.roles;
+ member.roles = data.roles;
if (this.client.ws.emittedReady) {
- this.client.emit(Constants.Events.GUILD_MEMBER_ROLES_UPDATE, this, oldRoles, this.store.memberData[currentUser.id].roles);
+ this.client.emit(Constants.Events.GUILD_MEMBER_ROLES_UPDATE, this, oldRoles, member.roles);
}
}
- _removeMember(guildUser) {
- this.store.remove('members', guildUser);
+ _removeMember(guildMember) {
+ this.store.remove('members', guildMember);
if (this.client.ws.emittedReady) {
- this.client.emit(Constants.Events.GUILD_MEMBER_REMOVE, this, guildUser);
+ this.client.emit(Constants.Events.GUILD_MEMBER_REMOVE, this, guildMember);
}
}
diff --git a/src/structures/Member.js b/src/structures/Member.js
new file mode 100644
index 000000000..2a39e5481
--- /dev/null
+++ b/src/structures/Member.js
@@ -0,0 +1,42 @@
+'use strict';
+
+class Member {
+ constructor(guild, data) {
+ this.client = guild.client;
+ this.guild = guild;
+ this._user = {};
+ if (data) {
+ this.setup(data);
+ }
+ }
+
+ setup(data) {
+ this._user = data.user;
+ this.deaf = data.deaf;
+ this.mute = data.mute;
+ this.joinDate = new Date(data.joined_at);
+ this.roles = data.roles;
+ }
+
+ get username() {
+ return this._user.username;
+ }
+
+ get id() {
+ return this._user.id;
+ }
+
+ get discriminator() {
+ return this._user.discriminator;
+ }
+
+ get avatar() {
+ return this._user.avatar;
+ }
+
+ get bot() {
+ return this._user.bot;
+ }
+}
+
+module.exports = Member;
diff --git a/src/structures/datastore/GuildDataStore.js b/src/structures/datastore/GuildDataStore.js
index fc541b33a..68f8fa5d7 100644
--- a/src/structures/datastore/GuildDataStore.js
+++ b/src/structures/datastore/GuildDataStore.js
@@ -6,8 +6,6 @@ class GuildDataStore extends AbstractDataStore{
constructor() {
super();
- this.memberData = {};
-
this.register('members');
this.register('channels');
}
From 4de1f4ce991a142851c2888e4cead6fb5af2c0c2 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sun, 17 Apr 2016 15:03:23 +0100
Subject: [PATCH 004/324] Created Role class and permission evaluation within
Roles
---
src/structures/Guild.js | 12 ++++-
src/structures/{Member.js => GuildMember.js} | 4 +-
src/structures/Role.js | 52 ++++++++++++++++++++
src/util/Constants.js | 28 +++++++++++
4 files changed, 92 insertions(+), 4 deletions(-)
rename src/structures/{Member.js => GuildMember.js} (91%)
create mode 100644 src/structures/Role.js
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index f61b3c259..920dc64f7 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -1,11 +1,12 @@
'use strict';
const User = require('./User');
-const Member = require('./Member');
+const GuildMember = require('./GuildMember');
const GuildDataStore = require('./datastore/GuildDataStore');
const TextChannel = require('./TextChannel');
const VoiceChannel = require('./VoiceChannel');
const Constants = require('../Util/Constants');
+const Role = require('./Role');
class Guild {
constructor(client, data) {
@@ -27,7 +28,7 @@ class Guild {
_addMember(guildUser) {
guildUser.user = this.client.store.NewUser(guildUser.user);
- let member = this.store.add('members', new Member(this, guildUser));
+ let member = this.store.add('members', new GuildMember(this, guildUser));
if (this.client.ws.emittedReady) {
this.client.emit(Constants.Events.GUILD_MEMBER_ADD, this, member);
}
@@ -81,6 +82,13 @@ class Guild {
this.client.store.NewChannel(channel, this);
}
}
+
+ if (data.roles) {
+ this.store.clear('roles');
+ for (let role of data.roles) {
+ this.store.add('roles', new Role(this, role));
+ }
+ };
}
}
diff --git a/src/structures/Member.js b/src/structures/GuildMember.js
similarity index 91%
rename from src/structures/Member.js
rename to src/structures/GuildMember.js
index 2a39e5481..1f6c10187 100644
--- a/src/structures/Member.js
+++ b/src/structures/GuildMember.js
@@ -1,6 +1,6 @@
'use strict';
-class Member {
+class GuildMember {
constructor(guild, data) {
this.client = guild.client;
this.guild = guild;
@@ -39,4 +39,4 @@ class Member {
}
}
-module.exports = Member;
+module.exports = GuildMember;
diff --git a/src/structures/Role.js b/src/structures/Role.js
new file mode 100644
index 000000000..30dc865a3
--- /dev/null
+++ b/src/structures/Role.js
@@ -0,0 +1,52 @@
+'use strict';
+
+const Constants = require('../Util/Constants');
+
+class Role {
+ constructor(guild, data) {
+ this.guild = guild;
+ this.client = guild.client;
+ if (data) {
+ this.setup(data);
+ }
+ }
+
+ setup(data) {
+ this.id = data.id;
+ this.name = data.name;
+ this.color = data.color;
+ this.hoist = data.hoist;
+ this.position = data.position;
+ this.permissions = data.permissions;
+ this.managed = data.managed;
+ }
+
+ serialize() {
+ let serializedPermissions = {};
+ for (let permissionName in Constants.PermissionFlags) {
+ serializedPermissions[permissionName] = this.hasPermission(permissionName);
+ }
+
+ return serializedPermissions;
+ }
+
+ hasPermission(permission, explicit) {
+ if (permission instanceof String || typeof permission === 'string') {
+ permission = Constants.PermissionFlags[permission];
+ }
+
+ if (!permission) {
+ throw Constants.Errors.NOT_A_PERMISSION;
+ }
+
+ if (!explicit) {
+ if ((this.permissions & Constants.PermissionFlags.MANAGE_ROLES) > 0) {
+ return true;
+ }
+ }
+
+ return ((this.permissions & permission) > 0);
+ }
+}
+
+module.exports = Role;
diff --git a/src/util/Constants.js b/src/util/Constants.js
index 5adc1636c..674ce7287 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -20,6 +20,7 @@ const Errors = exports.Errors = {
NO_BOT_ACCOUNT: new Error('you should ideally be using a bot account!'),
BAD_WS_MESSAGE: new Error('a bad message was received from the websocket - bad compression or not json'),
TOOK_TOO_LONG: new Error('something took too long to do'),
+ NOT_A_PERMISSION: new Error('that is not a valid permission number'),
};
const API = 'https://discordapp.com/api';
@@ -116,3 +117,30 @@ const WSEvents = exports.WSEvents = {
FRIEND_ADD: 'RELATIONSHIP_ADD',
FRIEND_REMOVE: 'RELATIONSHIP_REMOVE',
};
+
+const PermissionFlags = exports.PermissionFlags = {
+ CREATE_INSTANT_INVITE: 1 << 0,
+ KICK_MEMBERS: 1 << 1,
+ BAN_MEMBERS: 1 << 2,
+ MANAGE_ROLES: 1 << 3,
+ MANAGE_CHANNELS: 1 << 4,
+ MANAGE_GUILD: 1 << 5,
+
+ READ_MESSAGES: 1 << 10,
+ SEND_MESSAGES: 1 << 11,
+ SEND_TTS_MESSAGES: 1 << 12,
+ MANAGE_MESSAGES: 1 << 13,
+ EMBED_LINKS: 1 << 14,
+ ATTACH_FILES: 1 << 15,
+ READ_MESSAGE_HISTORY: 1 << 16,
+ MENTION_EVERYONE: 1 << 17,
+
+ CONNECT: 1 << 20,
+ SPEAK: 1 << 21,
+ MUTE_MEMBERS: 1 << 22,
+ DEAFEN_MEMBERS: 1 << 23,
+ MOVE_MEMBERS: 1 << 24,
+ USE_VAD: 1 << 25,
+};
+
+const DEFAULT_PERMISSIONS = exports.DEFAULT_PERMISSIONS = 36953089;
From bbf7be7dfae013c4aff59519e6cb978568cad772 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sun, 17 Apr 2016 15:17:18 +0100
Subject: [PATCH 005/324] Tracking of GUILD_ROLE_CREATE/UPDATE/DELETE events
---
.../packets/WebSocketPacketManager.js | 3 ++
.../packets/handlers/GuildRoleCreate.js | 36 +++++++++++++++++++
.../packets/handlers/GuildRoleDelete.js | 34 ++++++++++++++++++
.../packets/handlers/GuildRoleUpdate.js | 36 +++++++++++++++++++
src/util/Constants.js | 3 ++
test/random.js | 11 ++++++
6 files changed, 123 insertions(+)
create mode 100644 src/client/websocket/packets/handlers/GuildRoleCreate.js
create mode 100644 src/client/websocket/packets/handlers/GuildRoleDelete.js
create mode 100644 src/client/websocket/packets/handlers/GuildRoleUpdate.js
diff --git a/src/client/websocket/packets/WebSocketPacketManager.js b/src/client/websocket/packets/WebSocketPacketManager.js
index cb114bad6..2cf3c2149 100644
--- a/src/client/websocket/packets/WebSocketPacketManager.js
+++ b/src/client/websocket/packets/WebSocketPacketManager.js
@@ -17,6 +17,9 @@ class WebSocketPacketManager {
this.register(Constants.WSEvents.GUILD_MEMBER_ADD, 'GuildMemberAdd');
this.register(Constants.WSEvents.GUILD_MEMBER_REMOVE, 'GuildMemberRemove');
this.register(Constants.WSEvents.GUILD_MEMBER_UPDATE, 'GuildMemberUpdate');
+ this.register(Constants.WSEvents.GUILD_ROLE_CREATE, 'GuildRoleCreate');
+ this.register(Constants.WSEvents.GUILD_ROLE_DELETE, 'GuildRoleDelete');
+ this.register(Constants.WSEvents.GUILD_ROLE_UPDATE, 'GuildRoleUpdate');
this.register(Constants.WSEvents.CHANNEL_CREATE, 'ChannelCreate');
this.register(Constants.WSEvents.CHANNEL_DELETE, 'ChannelDelete');
this.register(Constants.WSEvents.CHANNEL_UPDATE, 'ChannelUpdate');
diff --git a/src/client/websocket/packets/handlers/GuildRoleCreate.js b/src/client/websocket/packets/handlers/GuildRoleCreate.js
new file mode 100644
index 000000000..8f8666089
--- /dev/null
+++ b/src/client/websocket/packets/handlers/GuildRoleCreate.js
@@ -0,0 +1,36 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+const Constants = require('../../../../util/Constants');
+
+const Role = Structure('Role');
+const Guild = Structure('Guild');
+
+class GuildRoleCreateHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let guild = client.store.get('guilds', data.guild_id);
+
+ if (guild) {
+ let already = guild.store.get('roles', data.role.id);
+ let role = new Role(guild, data.role);
+ guild.store.add('roles', role);
+
+ if (!already) {
+ client.emit(Constants.Events.GUILD_ROLE_CREATE, guild, role);
+ }
+ }
+
+ }
+
+};
+
+module.exports = GuildRoleCreateHandler;
diff --git a/src/client/websocket/packets/handlers/GuildRoleDelete.js b/src/client/websocket/packets/handlers/GuildRoleDelete.js
new file mode 100644
index 000000000..002d2321e
--- /dev/null
+++ b/src/client/websocket/packets/handlers/GuildRoleDelete.js
@@ -0,0 +1,34 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+const Constants = require('../../../../util/Constants');
+
+const Role = Structure('Role');
+const Guild = Structure('Guild');
+
+class GuildRoleDeleteHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let guild = client.store.get('guilds', data.guild_id);
+
+ if (guild) {
+ let exists = guild.store.get('roles', data.role_id);
+ if (exists) {
+ guild.store.remove('roles', data.role_id);
+ client.emit(Constants.Events.GUILD_ROLE_DELETE, guild, exists);
+ }
+ }
+
+ }
+
+};
+
+module.exports = GuildRoleDeleteHandler;
diff --git a/src/client/websocket/packets/handlers/GuildRoleUpdate.js b/src/client/websocket/packets/handlers/GuildRoleUpdate.js
new file mode 100644
index 000000000..72799a0ea
--- /dev/null
+++ b/src/client/websocket/packets/handlers/GuildRoleUpdate.js
@@ -0,0 +1,36 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+const Constants = require('../../../../util/Constants');
+const CloneObject = require('../../../../util/CloneObject');
+
+const Role = Structure('Role');
+const Guild = Structure('Guild');
+
+class GuildRoleUpdateHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let guild = client.store.get('guilds', data.guild_id);
+
+ if (guild) {
+ let existingRole = guild.store.get('roles', data.role.id);
+ if (existingRole) {
+ let oldRole = CloneObject(existingRole);
+ existingRole.setup(data.role);
+ client.emit(Constants.Events.GUILD_ROLE_UPDATE, guild, oldRole, existingRole);
+ }
+ }
+
+ }
+
+};
+
+module.exports = GuildRoleUpdateHandler;
diff --git a/src/util/Constants.js b/src/util/Constants.js
index 674ce7287..ccd415687 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -84,6 +84,9 @@ const Events = exports.Events = {
GUILD_MEMBER_ADD: 'guildMemberAdd',
GUILD_MEMBER_REMOVE: 'guildMemberRemove',
GUILD_MEMBER_ROLES_UPDATE: 'guildMemberRolesUpdate',
+ GUILD_ROLE_CREATE: 'guildRoleCreate',
+ GUILD_ROLE_DELETE: 'guildRoleDelete',
+ GUILD_ROLE_UPDATE: 'guildRoleUpdate',
CHANNEL_CREATE: 'channelCreate',
CHANNEL_DELETE: 'channelDelete',
CHANNEL_UPDATE: 'channelUpdate',
diff --git a/test/random.js b/test/random.js
index 300bc25e9..5a35bd7a3 100644
--- a/test/random.js
+++ b/test/random.js
@@ -37,3 +37,14 @@ client.on('guildMemberRemove', (guild, user) => {
console.log('dead guild member', user.username, 'in', guild.name);
});
+client.on('guildRoleCreate', (guild, role) => {
+ console.log('new role', role.name, 'in', guild.name);
+});
+
+client.on('guildRoleDelete', (guild, role) => {
+ console.log('dead role', role.name, 'in', guild.name);
+});
+
+client.on('guildRoleUpdate', (guild, old, newRole) => {
+ console.log('updated role', old.name, 'to', newRole.name, 'in', guild.name);
+});
From 71a4cd6a93d5a058c99feb1e2d61d031c2a4c705 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sun, 17 Apr 2016 15:43:12 +0100
Subject: [PATCH 006/324] Added full Role tracking
---
src/structures/Guild.js | 3 ++-
src/structures/GuildMember.js | 33 +++++++++++++++------------------
test/random.js | 4 ++--
3 files changed, 19 insertions(+), 21 deletions(-)
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index 920dc64f7..2fb6627a2 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -36,7 +36,8 @@ class Guild {
_updateMember(member, data) {
let oldRoles = member.roles;
- member.roles = data.roles;
+
+ member._roles = data.roles;
if (this.client.ws.emittedReady) {
this.client.emit(Constants.Events.GUILD_MEMBER_ROLES_UPDATE, this, oldRoles, member.roles);
}
diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js
index 1f6c10187..560787840 100644
--- a/src/structures/GuildMember.js
+++ b/src/structures/GuildMember.js
@@ -4,38 +4,35 @@ class GuildMember {
constructor(guild, data) {
this.client = guild.client;
this.guild = guild;
- this._user = {};
+ this.user = {};
+ this._roles = [];
if (data) {
this.setup(data);
}
}
setup(data) {
- this._user = data.user;
+ this.user = data.user;
this.deaf = data.deaf;
this.mute = data.mute;
this.joinDate = new Date(data.joined_at);
- this.roles = data.roles;
+ this._roles = data.roles;
}
- get username() {
- return this._user.username;
+ get roles() {
+ let list = [];
+ for (let roleID of this._roles) {
+ let role = this.guild.store.get('roles', roleID);
+ if (role) {
+ list.push(role);
+ }
+ }
+
+ return list;
}
get id() {
- return this._user.id;
- }
-
- get discriminator() {
- return this._user.discriminator;
- }
-
- get avatar() {
- return this._user.avatar;
- }
-
- get bot() {
- return this._user.bot;
+ return this.user.id;
}
}
diff --git a/test/random.js b/test/random.js
index 5a35bd7a3..0adff7a8e 100644
--- a/test/random.js
+++ b/test/random.js
@@ -30,11 +30,11 @@ client.on('channelUpdate', (old, chan) => {
});
client.on('guildMemberAdd', (guild, user) => {
- console.log('new guild member', user.username, 'in', guild.name);
+ console.log('new guild member', user.user.username, 'in', guild.name);
});
client.on('guildMemberRemove', (guild, user) => {
- console.log('dead guild member', user.username, 'in', guild.name);
+ console.log('dead guild member', user.user.username, 'in', guild.name);
});
client.on('guildRoleCreate', (guild, role) => {
From abc3f9e2fa8d3e1c788186857bdbffbbdeca4e89 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sun, 17 Apr 2016 18:20:57 +0100
Subject: [PATCH 007/324] Presence tracking
---
src/client/websocket/WebSocketManager.js | 1 +
.../packets/WebSocketPacketManager.js | 23 ++++++
.../websocket/packets/handlers/GuildDelete.js | 1 +
.../packets/handlers/PresenceUpdate.js | 77 +++++++++++++++++++
src/structures/Guild.js | 24 +++++-
src/structures/User.js | 2 +
src/util/Constants.js | 2 +
test/random.js | 4 +
8 files changed, 130 insertions(+), 4 deletions(-)
create mode 100644 src/client/websocket/packets/handlers/PresenceUpdate.js
diff --git a/src/client/websocket/WebSocketManager.js b/src/client/websocket/WebSocketManager.js
index ae9b8c550..41c7ea407 100644
--- a/src/client/websocket/WebSocketManager.js
+++ b/src/client/websocket/WebSocketManager.js
@@ -71,6 +71,7 @@ class WebSocketManager {
if (unavailableCount === 0) {
this.client.emit(Constants.Events.READY);
this.emittedReady = true;
+ this.packetManager.handleQueue();
}
}
}
diff --git a/src/client/websocket/packets/WebSocketPacketManager.js b/src/client/websocket/packets/WebSocketPacketManager.js
index 2cf3c2149..a64a7bac7 100644
--- a/src/client/websocket/packets/WebSocketPacketManager.js
+++ b/src/client/websocket/packets/WebSocketPacketManager.js
@@ -2,11 +2,18 @@
const Constants = require('../../../util/Constants');
+const BeforeReadyWhitelist = [
+ Constants.WSEvents.READY,
+ Constants.WSEvents.GUILD_CREATE,
+ Constants.WSEvents.GUILD_DELETE,
+];
+
class WebSocketPacketManager {
constructor(websocketManager) {
this.ws = websocketManager;
this.handlers = {};
+ this.queue = [];
this.register(Constants.WSEvents.READY, 'Ready');
this.register(Constants.WSEvents.GUILD_CREATE, 'GuildCreate');
@@ -23,6 +30,7 @@ class WebSocketPacketManager {
this.register(Constants.WSEvents.CHANNEL_CREATE, 'ChannelCreate');
this.register(Constants.WSEvents.CHANNEL_DELETE, 'ChannelDelete');
this.register(Constants.WSEvents.CHANNEL_UPDATE, 'ChannelUpdate');
+ this.register(Constants.WSEvents.PRESENCE_UPDATE, 'PresenceUpdate');
}
get client() {
@@ -34,7 +42,22 @@ class WebSocketPacketManager {
this.handlers[event] = new Handler(this);
}
+ handleQueue() {
+ for (let packetIndex in this.queue) {
+ this.handle(this.queue[packetIndex]);
+ this.queue.splice(packetIndex, 1);
+ }
+ }
+
handle(packet) {
+
+ if (!this.ws.emittedReady) {
+ if (BeforeReadyWhitelist.indexOf(packet.t) === -1) {
+ this.queue.push(packet);
+ return;
+ }
+ }
+
if (this.handlers[packet.t]) {
return this.handlers[packet.t].handle(packet);
}
diff --git a/src/client/websocket/packets/handlers/GuildDelete.js b/src/client/websocket/packets/handlers/GuildDelete.js
index 550628ac0..350c27b1c 100644
--- a/src/client/websocket/packets/handlers/GuildDelete.js
+++ b/src/client/websocket/packets/handlers/GuildDelete.js
@@ -28,6 +28,7 @@ class GuildDeleteHandler extends AbstractHandler {
} else {
// delete guild
client.store.KillGuild(guild);
+ this.packetManager.ws.checkIfReady();
}
} else {
// it's not there! :(
diff --git a/src/client/websocket/packets/handlers/PresenceUpdate.js b/src/client/websocket/packets/handlers/PresenceUpdate.js
new file mode 100644
index 000000000..c472a413c
--- /dev/null
+++ b/src/client/websocket/packets/handlers/PresenceUpdate.js
@@ -0,0 +1,77 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+const Constants = require('../../../../util/Constants');
+const CloneObject = require('../../../../util/CloneObject');
+
+const Role = Structure('User');
+
+class PresenceUpdateHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+ let user = client.store.get('users', data.user.id);
+ let guild = client.store.get('guilds', data.guild_id);
+
+ function makeUser(user) {
+ return client.store.NewUser(user);
+ }
+
+ // step 1
+ if (!user) {
+ if (data.user.username) {
+ user = makeUser(data.user);
+ }else {
+ return;
+ }
+ }
+
+ if (guild) {
+ let memberInGuild = guild.store.get('members', user.id);
+ if (!memberInGuild) {
+ let member = guild._addMember({
+ user,
+ roles: data.roles,
+ deaf: false,
+ mute: false,
+ }, true);
+ client.emit(Constants.Events.GUILD_MEMBER_AVAILABLE, guild, member);
+ }
+ }
+
+ data.user.username = data.user.username || user.username;
+ data.user.id = data.user.id || user.id;
+ data.user.discriminator = data.user.discriminator || user.discriminator;
+ data.user.avatar = data.user.avatar || user.avatar;
+ data.user.status = data.status || user.status;
+ data.user.game = data.game;
+
+ let same = (
+ data.user.username === user.username &&
+ data.user.id === user.id &&
+ data.user.discriminator === user.discriminator &&
+ data.user.avatar === user.avatar &&
+ data.user.status === user.status &&
+ !(
+ (data.user.game && !user.game) ||
+ (!data.user.game && user.game) ||
+ (data.user.game && user.game && data.user.game.name !== user.game.name)
+ )
+ );
+
+ if (!same) {
+ let oldUser = CloneObject(user);
+ user.setup(data.user);
+ client.emit(Constants.Events.PRESENCE_UPDATE, oldUser, user);
+ }
+ }
+
+};
+
+module.exports = PresenceUpdateHandler;
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index 2fb6627a2..94b5d82b0 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -26,12 +26,18 @@ class Guild {
}
}
- _addMember(guildUser) {
- guildUser.user = this.client.store.NewUser(guildUser.user);
+ _addMember(guildUser, noEvent) {
+ if (!(guildUser.user instanceof User)) {
+ guildUser.user = this.client.store.NewUser(guildUser.user);
+ }
+
+ guildUser.joined_at = guildUser.joined_at || 0;
let member = this.store.add('members', new GuildMember(this, guildUser));
- if (this.client.ws.emittedReady) {
+ if (this.client.ws.emittedReady && !noEvent) {
this.client.emit(Constants.Events.GUILD_MEMBER_ADD, this, member);
}
+
+ return member;
}
_updateMember(member, data) {
@@ -89,7 +95,17 @@ class Guild {
for (let role of data.roles) {
this.store.add('roles', new Role(this, role));
}
- };
+ }
+
+ if (data.presences) {
+ for (let presence of data.presences) {
+ let user = this.client.store.get('users', presence.user.id);
+ if (user) {
+ user.status = presence.status;
+ user.game = presence.game;
+ }
+ }
+ }
}
}
diff --git a/src/structures/User.js b/src/structures/User.js
index 50487077f..dcab3f561 100644
--- a/src/structures/User.js
+++ b/src/structures/User.js
@@ -14,6 +14,8 @@ class User {
this.discriminator = data.discriminator;
this.avatar = data.avatar;
this.bot = Boolean(data.bot);
+ this.status = data.status || 'offline';
+ this.game = data.game;
}
}
diff --git a/src/util/Constants.js b/src/util/Constants.js
index ccd415687..3f2a8d64c 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -87,9 +87,11 @@ const Events = exports.Events = {
GUILD_ROLE_CREATE: 'guildRoleCreate',
GUILD_ROLE_DELETE: 'guildRoleDelete',
GUILD_ROLE_UPDATE: 'guildRoleUpdate',
+ GUILD_MEMBER_AVAILABLE: 'guildMemberAvailable',
CHANNEL_CREATE: 'channelCreate',
CHANNEL_DELETE: 'channelDelete',
CHANNEL_UPDATE: 'channelUpdate',
+ PRESENCE_UPDATE: 'presenceUpdate',
WARN: 'warn',
};
diff --git a/test/random.js b/test/random.js
index 0adff7a8e..569b40b55 100644
--- a/test/random.js
+++ b/test/random.js
@@ -48,3 +48,7 @@ client.on('guildRoleDelete', (guild, role) => {
client.on('guildRoleUpdate', (guild, old, newRole) => {
console.log('updated role', old.name, 'to', newRole.name, 'in', guild.name);
});
+
+client.on('presenceUpdate', (oldUser, newUser) => {
+ console.log('presence from', oldUser.username, 'to', newUser.username);
+});
From 685d7b622c604cb9ea5409d9bee4e2be86dae81d Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sun, 17 Apr 2016 18:37:15 +0100
Subject: [PATCH 008/324] Fix READY bug when logging in with email/password,
add UserUpdate packet handler
---
.../packets/WebSocketPacketManager.js | 5 ++-
.../websocket/packets/handlers/Ready.js | 3 +-
.../websocket/packets/handlers/UserUpdate.js | 42 +++++++++++++++++++
src/util/Constants.js | 1 +
test/random.js | 2 +-
5 files changed, 50 insertions(+), 3 deletions(-)
create mode 100644 src/client/websocket/packets/handlers/UserUpdate.js
diff --git a/src/client/websocket/packets/WebSocketPacketManager.js b/src/client/websocket/packets/WebSocketPacketManager.js
index a64a7bac7..bb9ef601e 100644
--- a/src/client/websocket/packets/WebSocketPacketManager.js
+++ b/src/client/websocket/packets/WebSocketPacketManager.js
@@ -8,6 +8,8 @@ const BeforeReadyWhitelist = [
Constants.WSEvents.GUILD_DELETE,
];
+var amount = 0;
+
class WebSocketPacketManager {
constructor(websocketManager) {
@@ -31,6 +33,7 @@ class WebSocketPacketManager {
this.register(Constants.WSEvents.CHANNEL_DELETE, 'ChannelDelete');
this.register(Constants.WSEvents.CHANNEL_UPDATE, 'ChannelUpdate');
this.register(Constants.WSEvents.PRESENCE_UPDATE, 'PresenceUpdate');
+ this.register(Constants.WSEvents.USER_UPDATE, 'UserUpdate');
}
get client() {
@@ -50,7 +53,7 @@ class WebSocketPacketManager {
}
handle(packet) {
-
+ amount++;
if (!this.ws.emittedReady) {
if (BeforeReadyWhitelist.indexOf(packet.t) === -1) {
this.queue.push(packet);
diff --git a/src/client/websocket/packets/handlers/Ready.js b/src/client/websocket/packets/handlers/Ready.js
index cd512a5e8..b5bd514f3 100644
--- a/src/client/websocket/packets/handlers/Ready.js
+++ b/src/client/websocket/packets/handlers/Ready.js
@@ -16,7 +16,6 @@ class ReadyHandler extends AbstractHandler {
handle(packet) {
let data = packet.d;
let client = this.packetManager.client;
-
client.manager.setupKeepAlive(data.heartbeat_interval);
client.store.user = client.store.add('users', new ClientUser(client, data.user));
@@ -29,6 +28,8 @@ class ReadyHandler extends AbstractHandler {
client.store.NewChannel(privateDM);
}
+ this.packetManager.ws.checkIfReady();
+
}
};
diff --git a/src/client/websocket/packets/handlers/UserUpdate.js b/src/client/websocket/packets/handlers/UserUpdate.js
new file mode 100644
index 000000000..d8bc1f7cc
--- /dev/null
+++ b/src/client/websocket/packets/handlers/UserUpdate.js
@@ -0,0 +1,42 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+const CloneObject = name => require(`../../../../util/CloneObject`);
+
+const ClientUser = Structure('ClientUser');
+const Guild = Structure('Guild');
+const DMChannel = Structure('DMChannel');
+
+class UserUpdateHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let user = client.store.user;
+
+ if (!user) {
+ return;
+ }
+
+ let oldUser = CloneObject(user);
+
+ user.username = data.username || user.username;
+ user.id = data.id || user.id;
+ user.avatar = data.avatar || user.avatar;
+ user.discriminator = data.discriminator || user.discriminator;
+ user.email = data.email || user.email;
+ user.verified = data.verified || user.verified;
+
+ client.emit(Constants.Events.USER_UPDATE, oldUser, user);
+
+ }
+
+};
+
+module.exports = UserUpdateHandler;
diff --git a/src/util/Constants.js b/src/util/Constants.js
index 3f2a8d64c..81511b072 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -92,6 +92,7 @@ const Events = exports.Events = {
CHANNEL_DELETE: 'channelDelete',
CHANNEL_UPDATE: 'channelUpdate',
PRESENCE_UPDATE: 'presenceUpdate',
+ USER_UPDATE: 'userUpdate',
WARN: 'warn',
};
diff --git a/test/random.js b/test/random.js
index 569b40b55..fd54e734b 100644
--- a/test/random.js
+++ b/test/random.js
@@ -50,5 +50,5 @@ client.on('guildRoleUpdate', (guild, old, newRole) => {
});
client.on('presenceUpdate', (oldUser, newUser) => {
- console.log('presence from', oldUser.username, 'to', newUser.username);
+ // console.log('presence from', oldUser.username, 'to', newUser.username);
});
From d1d13f5c85d89d3c3507a25887673d7655410543 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sun, 17 Apr 2016 19:12:29 +0100
Subject: [PATCH 009/324] Added VoiceStateUpdate handler and DataStore for
VoiceChannels. Also added toString methods to Guilds, DMChannels,
ServerChannels and Users.
---
.../packets/WebSocketPacketManager.js | 1 +
.../packets/handlers/VoiceStateUpdate.js | 43 +++++++++++++++++++
src/structures/DMChannel.js | 4 ++
src/structures/Guild.js | 18 ++++++++
src/structures/GuildMember.js | 20 ++++++++-
src/structures/ServerChannel.js | 4 ++
src/structures/User.js | 4 ++
src/structures/VoiceChannel.js | 2 +
.../datastore/VoiceChannelDataStore.js | 12 ++++++
src/util/Constants.js | 1 +
test/random.js | 4 ++
11 files changed, 111 insertions(+), 2 deletions(-)
create mode 100644 src/client/websocket/packets/handlers/VoiceStateUpdate.js
create mode 100644 src/structures/datastore/VoiceChannelDataStore.js
diff --git a/src/client/websocket/packets/WebSocketPacketManager.js b/src/client/websocket/packets/WebSocketPacketManager.js
index bb9ef601e..e23eabf8b 100644
--- a/src/client/websocket/packets/WebSocketPacketManager.js
+++ b/src/client/websocket/packets/WebSocketPacketManager.js
@@ -34,6 +34,7 @@ class WebSocketPacketManager {
this.register(Constants.WSEvents.CHANNEL_UPDATE, 'ChannelUpdate');
this.register(Constants.WSEvents.PRESENCE_UPDATE, 'PresenceUpdate');
this.register(Constants.WSEvents.USER_UPDATE, 'UserUpdate');
+ this.register(Constants.WSEvents.VOICE_STATE_UPDATE, 'VoiceStateUpdate');
}
get client() {
diff --git a/src/client/websocket/packets/handlers/VoiceStateUpdate.js b/src/client/websocket/packets/handlers/VoiceStateUpdate.js
new file mode 100644
index 000000000..3838b7007
--- /dev/null
+++ b/src/client/websocket/packets/handlers/VoiceStateUpdate.js
@@ -0,0 +1,43 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+const Constants = require('../../../../util/Constants');
+const CloneObject = require('../../../../util/CloneObject');
+
+const Role = Structure('User');
+
+class VoiceStateUpdateHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+ let guild = client.store.get('guilds', data.guild_id);
+
+ if (guild) {
+ let member = guild.store.get('members', data.user_id);
+ let channel = guild.store.get('channels', data.channel_id);
+ if (member) {
+ let oldVoiceChannelMember = CloneObject(member);
+ if (member.voiceChannel && member.voiceChannel.id !== data.channel_id) {
+ member.voiceChannel.store.remove('members', oldVoiceChannelMember);
+ }
+
+ 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);
+ }
+ }
+ }
+
+};
+
+module.exports = VoiceStateUpdateHandler;
diff --git a/src/structures/DMChannel.js b/src/structures/DMChannel.js
index 0db181e96..7333ac8e7 100644
--- a/src/structures/DMChannel.js
+++ b/src/structures/DMChannel.js
@@ -12,6 +12,10 @@ class DMChannel extends Channel{
this.recipient = this.client.store.add('users', new User(this.client, data.recipient));
this.lastMessageID = data.last_message_id;
}
+
+ toString() {
+ return this.recipient.toString();
+ }
}
module.exports = DMChannel;
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index 94b5d82b0..f6fb90a00 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -56,6 +56,10 @@ class Guild {
}
}
+ toString() {
+ return this.name;
+ }
+
setup(data) {
this.id = data.id;
this.available = !data.unavailable;
@@ -106,6 +110,20 @@ class Guild {
}
}
}
+
+ if (data.voice_states) {
+ for (let voiceState of data.voice_states) {
+ let member = this.store.get('members', 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;
+ }
+ }
+ }
}
}
diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js
index 560787840..e8b531db0 100644
--- a/src/structures/GuildMember.js
+++ b/src/structures/GuildMember.js
@@ -13,8 +13,12 @@ class GuildMember {
setup(data) {
this.user = data.user;
- this.deaf = data.deaf;
- this.mute = data.mute;
+ this.serverDeaf = data.deaf;
+ this.serverMute = data.mute;
+ this.selfMute = data.self_mute;
+ this.selfDeaf = data.self_deaf;
+ this.voiceSessionID = data.session_id;
+ this.voiceChannelID = data.channel_id;
this.joinDate = new Date(data.joined_at);
this._roles = data.roles;
}
@@ -31,6 +35,18 @@ class GuildMember {
return list;
}
+ get mute() {
+ return this.selfMute || this.serverMute;
+ }
+
+ get deaf() {
+ return this.selfDeaf || this.serverDeaf;
+ }
+
+ get voiceChannel() {
+ return this.guild.store.get('channels', this.voiceChannelID);
+ }
+
get id() {
return this.user.id;
}
diff --git a/src/structures/ServerChannel.js b/src/structures/ServerChannel.js
index 32294b0ab..58053250a 100644
--- a/src/structures/ServerChannel.js
+++ b/src/structures/ServerChannel.js
@@ -17,6 +17,10 @@ class ServerChannel extends Channel{
this.name = data.name;
this.lastMessageID = data.last_message_id;
}
+
+ toString() {
+ return this.name;
+ }
}
module.exports = ServerChannel;
diff --git a/src/structures/User.js b/src/structures/User.js
index dcab3f561..6cae4518b 100644
--- a/src/structures/User.js
+++ b/src/structures/User.js
@@ -17,6 +17,10 @@ class User {
this.status = data.status || 'offline';
this.game = data.game;
}
+
+ toString() {
+ return `<@${this.id}>`;
+ }
}
module.exports = User;
diff --git a/src/structures/VoiceChannel.js b/src/structures/VoiceChannel.js
index 7a69e2b19..fb54df361 100644
--- a/src/structures/VoiceChannel.js
+++ b/src/structures/VoiceChannel.js
@@ -1,10 +1,12 @@
'use strict';
const ServerChannel = require('./ServerChannel');
+const VoiceChannelDataStore = require('./datastore/VoiceChannelDataStore');
class VoiceChannel extends ServerChannel {
constructor(guild, data) {
super(guild, data);
+ this.store = new VoiceChannelDataStore();
}
setup(data) {
diff --git a/src/structures/datastore/VoiceChannelDataStore.js b/src/structures/datastore/VoiceChannelDataStore.js
new file mode 100644
index 000000000..88b9da7bb
--- /dev/null
+++ b/src/structures/datastore/VoiceChannelDataStore.js
@@ -0,0 +1,12 @@
+'use strict';
+
+const AbstractDataStore = require('./AbstractDataStore');
+
+class VoiceChannelDataStore extends AbstractDataStore{
+ constructor() {
+ super();
+ this.register('members');
+ }
+}
+
+module.exports = VoiceChannelDataStore;
diff --git a/src/util/Constants.js b/src/util/Constants.js
index 81511b072..86fe01556 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -93,6 +93,7 @@ const Events = exports.Events = {
CHANNEL_UPDATE: 'channelUpdate',
PRESENCE_UPDATE: 'presenceUpdate',
USER_UPDATE: 'userUpdate',
+ VOICE_STATE_UPDATE: 'voiceStateUpdate',
WARN: 'warn',
};
diff --git a/test/random.js b/test/random.js
index fd54e734b..ec4003d72 100644
--- a/test/random.js
+++ b/test/random.js
@@ -52,3 +52,7 @@ client.on('guildRoleUpdate', (guild, old, newRole) => {
client.on('presenceUpdate', (oldUser, newUser) => {
// console.log('presence from', oldUser.username, 'to', newUser.username);
});
+
+client.on('voiceStateUpdate', (oldMember, newMember) => {
+ console.log('voiceState', oldMember.user.username, oldMember.voiceChannel + '', newMember.voiceChannel + '');
+});
From ce2cf382b3d755f8a145ed6d4751321a6bd5a648 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Mon, 18 Apr 2016 16:39:57 +0100
Subject: [PATCH 010/324] TypingStart handler
---
.../packets/WebSocketPacketManager.js | 1 +
.../websocket/packets/handlers/TypingStart.js | 62 +++++++++++++++++++
src/structures/Channel.js | 2 +
src/util/Constants.js | 4 +-
test/random.js | 10 +++
5 files changed, 78 insertions(+), 1 deletion(-)
create mode 100644 src/client/websocket/packets/handlers/TypingStart.js
diff --git a/src/client/websocket/packets/WebSocketPacketManager.js b/src/client/websocket/packets/WebSocketPacketManager.js
index e23eabf8b..48c2dd3fa 100644
--- a/src/client/websocket/packets/WebSocketPacketManager.js
+++ b/src/client/websocket/packets/WebSocketPacketManager.js
@@ -35,6 +35,7 @@ class WebSocketPacketManager {
this.register(Constants.WSEvents.PRESENCE_UPDATE, 'PresenceUpdate');
this.register(Constants.WSEvents.USER_UPDATE, 'UserUpdate');
this.register(Constants.WSEvents.VOICE_STATE_UPDATE, 'VoiceStateUpdate');
+ this.register(Constants.WSEvents.TYPING_START, 'TypingStart');
}
get client() {
diff --git a/src/client/websocket/packets/handlers/TypingStart.js b/src/client/websocket/packets/handlers/TypingStart.js
new file mode 100644
index 000000000..5fdbf598f
--- /dev/null
+++ b/src/client/websocket/packets/handlers/TypingStart.js
@@ -0,0 +1,62 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+const Constants = require('../../../../util/Constants');
+const CloneObject = require('../../../../util/CloneObject');
+
+const Role = Structure('User');
+
+class TypingData {
+ constructor(since, lastTimestamp, _timeout) {
+ this.since = since;
+ this.lastTimestamp = lastTimestamp;
+ this._timeout = _timeout;
+ }
+
+ resetTimeout(_timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = _timeout;
+ }
+
+ get elapsedTime() {
+ return Date.now() - this.since;
+ }
+}
+
+class TypingStartHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+ let channel = client.store.get('channels', data.channel_id);
+ let user = client.store.get('users', data.user_id);
+ let timestamp = new Date(data.timestamp * 1000);
+
+ if (channel && user) {
+ if (channel.typingMap[user.id]) {
+ // already typing, renew
+ let mapping = channel.typingMap[user.id];
+ mapping.lastTimestamp = timestamp;
+ mapping.resetTimeout(tooLate());
+ } else {
+ channel.typingMap[user.id] = new TypingData(timestamp, timestamp, tooLate());
+ client.emit(Constants.Events.TYPING_START, channel, user);
+ }
+ }
+
+ function tooLate() {
+ return setTimeout(() => {
+ client.emit(Constants.Events.TYPING_STOP, channel, user, channel.typingMap[user.id]);
+ delete channel.typingMap[user.id];
+ }, 6000);
+ }
+ }
+
+};
+
+module.exports = TypingStartHandler;
diff --git a/src/structures/Channel.js b/src/structures/Channel.js
index ae9950c33..245a17a09 100644
--- a/src/structures/Channel.js
+++ b/src/structures/Channel.js
@@ -3,6 +3,8 @@
class Channel {
constructor(client, data) {
this.client = client;
+ this.typingMap = {};
+ this.typingTimeouts = [];
if (data) {
this.setup(data);
}
diff --git a/src/util/Constants.js b/src/util/Constants.js
index 86fe01556..1449147fe 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -94,6 +94,8 @@ const Events = exports.Events = {
PRESENCE_UPDATE: 'presenceUpdate',
USER_UPDATE: 'userUpdate',
VOICE_STATE_UPDATE: 'voiceStateUpdate',
+ TYPING_START: 'typingStart',
+ TYPING_STOP: 'typingStop',
WARN: 'warn',
};
@@ -118,7 +120,7 @@ const WSEvents = exports.WSEvents = {
GUILD_ROLE_DELETE: 'GUILD_ROLE_DELETE',
GUILD_ROLE_UPDATE: 'GUILD_ROLE_UPDATE',
GUILD_UPDATE: 'GUILD_UPDATE',
- TYPING: 'TYPING_START',
+ TYPING_START: 'TYPING_START',
USER_UPDATE: 'USER_UPDATE',
VOICE_STATE_UPDATE: 'VOICE_STATE_UPDATE',
FRIEND_ADD: 'RELATIONSHIP_ADD',
diff --git a/test/random.js b/test/random.js
index ec4003d72..d47034116 100644
--- a/test/random.js
+++ b/test/random.js
@@ -56,3 +56,13 @@ client.on('presenceUpdate', (oldUser, newUser) => {
client.on('voiceStateUpdate', (oldMember, newMember) => {
console.log('voiceState', oldMember.user.username, oldMember.voiceChannel + '', newMember.voiceChannel + '');
});
+
+client.on('typingStart', (channel, user) => {
+ if (user.username === 'hydrabolt')
+ console.log(user.username, 'started typing in', channel.name);
+});
+
+client.on('typingStop', (channel, user, data) => {
+ if (user.username === 'hydrabolt')
+ console.log(user.username, 'stopped typing in', channel.name, 'after', data.elapsedTime + 'ms');
+});
From c36cc3b551fcec1eb96615f833971dcd842d1d7b Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Mon, 18 Apr 2016 16:54:14 +0100
Subject: [PATCH 011/324] Added GuildMembersChunk handler; untested
---
.../packets/WebSocketPacketManager.js | 1 +
.../packets/handlers/GuildMembersChunk.js | 33 +++++++++++++++++++
.../websocket/packets/handlers/TypingStart.js | 2 --
src/util/Constants.js | 1 +
4 files changed, 35 insertions(+), 2 deletions(-)
create mode 100644 src/client/websocket/packets/handlers/GuildMembersChunk.js
diff --git a/src/client/websocket/packets/WebSocketPacketManager.js b/src/client/websocket/packets/WebSocketPacketManager.js
index 48c2dd3fa..43d6b1249 100644
--- a/src/client/websocket/packets/WebSocketPacketManager.js
+++ b/src/client/websocket/packets/WebSocketPacketManager.js
@@ -29,6 +29,7 @@ class WebSocketPacketManager {
this.register(Constants.WSEvents.GUILD_ROLE_CREATE, 'GuildRoleCreate');
this.register(Constants.WSEvents.GUILD_ROLE_DELETE, 'GuildRoleDelete');
this.register(Constants.WSEvents.GUILD_ROLE_UPDATE, 'GuildRoleUpdate');
+ this.register(Constants.WSEvents.GUILD_MEMBERS_CHUNK, 'GuildMembersChunk');
this.register(Constants.WSEvents.CHANNEL_CREATE, 'ChannelCreate');
this.register(Constants.WSEvents.CHANNEL_DELETE, 'ChannelDelete');
this.register(Constants.WSEvents.CHANNEL_UPDATE, 'ChannelUpdate');
diff --git a/src/client/websocket/packets/handlers/GuildMembersChunk.js b/src/client/websocket/packets/handlers/GuildMembersChunk.js
new file mode 100644
index 000000000..3cd2ba516
--- /dev/null
+++ b/src/client/websocket/packets/handlers/GuildMembersChunk.js
@@ -0,0 +1,33 @@
+'use strict';
+
+// ##untested##
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+const Constants = require('../../../../util/Constants');
+const CloneObject = require('../../../../util/CloneObject');
+
+class GuildMembersChunkHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+ let guild = client.store.get('guilds', data.guild_id);
+
+ let members = [];
+ if (guild) {
+ for (let member of guild.members) {
+ members.push(guild._addMember(member, true));
+ }
+ }
+
+ client.emit(Constants.Events.GUILD_MEMBERS_CHUNK, guild, members);
+ }
+
+};
+
+module.exports = GuildMembersChunkHandler;
diff --git a/src/client/websocket/packets/handlers/TypingStart.js b/src/client/websocket/packets/handlers/TypingStart.js
index 5fdbf598f..c64ff705a 100644
--- a/src/client/websocket/packets/handlers/TypingStart.js
+++ b/src/client/websocket/packets/handlers/TypingStart.js
@@ -5,8 +5,6 @@ const Structure = name => require(`../../../../structures/${name}`);
const Constants = require('../../../../util/Constants');
const CloneObject = require('../../../../util/CloneObject');
-const Role = Structure('User');
-
class TypingData {
constructor(since, lastTimestamp, _timeout) {
this.since = since;
diff --git a/src/util/Constants.js b/src/util/Constants.js
index 1449147fe..74666d589 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -97,6 +97,7 @@ const Events = exports.Events = {
TYPING_START: 'typingStart',
TYPING_STOP: 'typingStop',
WARN: 'warn',
+ GUILD_MEMBERS_CHUNK: 'guildMembersChunk',
};
const WSEvents = exports.WSEvents = {
From 7f4751e7c4369c6ad1cc571cdf30527ee571c01e Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Mon, 18 Apr 2016 17:23:37 +0100
Subject: [PATCH 012/324] add PermissionOverwrites class in preparation for
permission evaluation
---
src/structures/Channel.js | 6 +++++-
src/structures/PermissionOverwrites.js | 19 +++++++++++++++++++
src/structures/ServerChannel.js | 12 +++++++++---
test/random.js | 4 ++--
4 files changed, 35 insertions(+), 6 deletions(-)
create mode 100644 src/structures/PermissionOverwrites.js
diff --git a/src/structures/Channel.js b/src/structures/Channel.js
index 245a17a09..8dc22316f 100644
--- a/src/structures/Channel.js
+++ b/src/structures/Channel.js
@@ -1,10 +1,14 @@
'use strict';
class Channel {
- constructor(client, data) {
+ constructor(client, data, guild) {
this.client = client;
this.typingMap = {};
this.typingTimeouts = [];
+ if (guild) {
+ this.guild = guild;
+ }
+
if (data) {
this.setup(data);
}
diff --git a/src/structures/PermissionOverwrites.js b/src/structures/PermissionOverwrites.js
new file mode 100644
index 000000000..717c94d46
--- /dev/null
+++ b/src/structures/PermissionOverwrites.js
@@ -0,0 +1,19 @@
+'use strict';
+
+class PermissionOverwrites {
+ constructor(serverChannel, data) {
+ this.channel = serverChannel;
+ if (data) {
+ this.setup(data);
+ }
+ }
+
+ setup(data) {
+ this.type = data.type;
+ this.id = data.id;
+ this.denyData = data.deny;
+ this.allowData = data.allow;
+ }
+}
+
+module.exports = PermissionOverwrites;
diff --git a/src/structures/ServerChannel.js b/src/structures/ServerChannel.js
index 58053250a..9be3bd58a 100644
--- a/src/structures/ServerChannel.js
+++ b/src/structures/ServerChannel.js
@@ -1,11 +1,11 @@
'use strict';
const Channel = require('./Channel');
+const PermissionOverwrites = require('./PermissionOverwrites');
class ServerChannel extends Channel{
constructor(guild, data) {
- super(guild.client, data);
- this.guild = guild;
+ super(guild.client, data, guild);
}
setup(data) {
@@ -13,9 +13,15 @@ class ServerChannel extends Channel{
this.type = data.type;
this.topic = data.topic;
this.position = data.position;
- this.permissionOverwrites = data.permission_overwrites;
this.name = data.name;
this.lastMessageID = data.last_message_id;
+
+ if (data.permission_overwrites) {
+ this.permissionOverwrites = [];
+ for (let overwrite of data.permission_overwrites) {
+ this.permissionOverwrites.push(new PermissionOverwrites(this, overwrite));
+ }
+ }
}
toString() {
diff --git a/test/random.js b/test/random.js
index d47034116..22a216aa4 100644
--- a/test/random.js
+++ b/test/random.js
@@ -57,12 +57,12 @@ client.on('voiceStateUpdate', (oldMember, newMember) => {
console.log('voiceState', oldMember.user.username, oldMember.voiceChannel + '', newMember.voiceChannel + '');
});
-client.on('typingStart', (channel, user) => {
+client.on('typingStart.', (channel, user) => {
if (user.username === 'hydrabolt')
console.log(user.username, 'started typing in', channel.name);
});
-client.on('typingStop', (channel, user, data) => {
+client.on('typingStop.', (channel, user, data) => {
if (user.username === 'hydrabolt')
console.log(user.username, 'stopped typing in', channel.name, 'after', data.elapsedTime + 'ms');
});
From c947e172d65424fa10d02988cea1826a7d07540f Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Mon, 18 Apr 2016 17:55:21 +0100
Subject: [PATCH 013/324] Add MessageCreate handler, set up Message class and
add ability to Cache messages
---
.../packets/WebSocketPacketManager.js | 1 +
.../packets/handlers/MessageCreate.js | 31 +++++++++++++++++++
src/structures/DMChannel.js | 16 ++++++++++
src/structures/Message.js | 25 ++++++++++++++-
src/structures/TextChannel.js | 15 +++++++++
src/util/Constants.js | 2 ++
test/random.js | 4 +++
7 files changed, 93 insertions(+), 1 deletion(-)
create mode 100644 src/client/websocket/packets/handlers/MessageCreate.js
diff --git a/src/client/websocket/packets/WebSocketPacketManager.js b/src/client/websocket/packets/WebSocketPacketManager.js
index 43d6b1249..d3c2d0ca6 100644
--- a/src/client/websocket/packets/WebSocketPacketManager.js
+++ b/src/client/websocket/packets/WebSocketPacketManager.js
@@ -37,6 +37,7 @@ class WebSocketPacketManager {
this.register(Constants.WSEvents.USER_UPDATE, 'UserUpdate');
this.register(Constants.WSEvents.VOICE_STATE_UPDATE, 'VoiceStateUpdate');
this.register(Constants.WSEvents.TYPING_START, 'TypingStart');
+ this.register(Constants.WSEvents.MESSAGE_CREATE, 'MessageCreate');
}
get client() {
diff --git a/src/client/websocket/packets/handlers/MessageCreate.js b/src/client/websocket/packets/handlers/MessageCreate.js
new file mode 100644
index 000000000..f6e2cf35e
--- /dev/null
+++ b/src/client/websocket/packets/handlers/MessageCreate.js
@@ -0,0 +1,31 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+const Constants = require('../../../../util/Constants');
+
+const Message = Structure('Message');
+const Guild = Structure('Guild');
+
+class MessageCreateHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+ let channel = client.store.get('channels', data.channel_id);
+
+ if (channel) {
+ let message = new Message(channel, data);
+ channel._cacheMessage(message);
+ client.emit(Constants.Events.MESSAGE_CREATE, message);
+ }
+
+ }
+
+};
+
+module.exports = MessageCreateHandler;
diff --git a/src/structures/DMChannel.js b/src/structures/DMChannel.js
index 7333ac8e7..b1bdd92c7 100644
--- a/src/structures/DMChannel.js
+++ b/src/structures/DMChannel.js
@@ -2,10 +2,26 @@
const Channel = require('./Channel');
const User = require('./User');
+const TextChannelDataStore = require('./datastore/TextChannelDataStore');
class DMChannel extends Channel{
constructor(client, data) {
super(client, data);
+ this.store = new TextChannelDataStore();
+ }
+
+ _cacheMessage(message) {
+ let maxSize = this.client.options.max_message_cache;
+ if (maxSize === 0) {
+ // saves on performance
+ return;
+ }
+
+ let storeKeys = Object.keys(this.store);
+ if (storeKeys.length >= maxSize) {
+ this.store.remove(storeKeys[0]);
+ this.store.add('messages', message);
+ }
}
setup(data) {
diff --git a/src/structures/Message.js b/src/structures/Message.js
index 30d7fc4ac..1da8cf9bc 100644
--- a/src/structures/Message.js
+++ b/src/structures/Message.js
@@ -1,8 +1,31 @@
'use strict';
class Message {
- constructor() {
+ constructor(serverChannel, data) {
+ this.channel = serverChannel;
+ this.guild = serverChannel.guild;
+ if (data) {
+ this.setup(data);
+ }
+ }
+ setup(data) {
+ this.author = this.guild.client.store.get('users', data.author.id);
+ this.content = data.content;
+ this.timestamp = new Date(data.timestamp);
+ this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp) : null;
+ this.tts = data.tts;
+ this.mentionEveryone = data.mention_everyone;
+ this.nonce = data.nonce;
+ this.embeds = data.embeds;
+ this.attachments = data.attachments;
+ this.mentions = [];
+ for (let mention of data.mentions) {
+ let user = this.guild.client.store.get('users', mention.id);
+ if (user) {
+ this.mentions.push(user);
+ }
+ }
}
}
diff --git a/src/structures/TextChannel.js b/src/structures/TextChannel.js
index e8b2b6acc..c9ae55f06 100644
--- a/src/structures/TextChannel.js
+++ b/src/structures/TextChannel.js
@@ -4,10 +4,25 @@ const ServerChannel = require('./ServerChannel');
const TextChannelDataStore = require('./datastore/TextChannelDataStore');
class TextChannel extends ServerChannel {
+
constructor(guild, data) {
super(guild, data);
this.store = new TextChannelDataStore();
}
+
+ _cacheMessage(message) {
+ let maxSize = this.client.options.max_message_cache;
+ if (maxSize === 0) {
+ // saves on performance
+ return;
+ }
+
+ let storeKeys = Object.keys(this.store);
+ if (storeKeys.length >= maxSize) {
+ this.store.remove(storeKeys[0]);
+ this.store.add('messages', message);
+ }
+ }
}
module.exports = TextChannel;
diff --git a/src/util/Constants.js b/src/util/Constants.js
index 74666d589..abbf2c6a2 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -11,6 +11,7 @@ const DefaultOptions = exports.DefaultOptions = {
},
},
protocol_version: 4,
+ max_message_cache: 20,
};
const Package = exports.Package = require('../../package.json');
@@ -98,6 +99,7 @@ const Events = exports.Events = {
TYPING_STOP: 'typingStop',
WARN: 'warn',
GUILD_MEMBERS_CHUNK: 'guildMembersChunk',
+ MESSAGE_CREATE: 'message',
};
const WSEvents = exports.WSEvents = {
diff --git a/test/random.js b/test/random.js
index 22a216aa4..f8df05a74 100644
--- a/test/random.js
+++ b/test/random.js
@@ -66,3 +66,7 @@ client.on('typingStop.', (channel, user, data) => {
if (user.username === 'hydrabolt')
console.log(user.username, 'stopped typing in', channel.name, 'after', data.elapsedTime + 'ms');
});
+
+client.on('message', message => {
+ console.log(message.author.username, 'said', message.content, 'in', message.channel.name);
+});
From d437fd31cf64400284dec5b8b44fc42de0979c82 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Mon, 18 Apr 2016 18:06:31 +0100
Subject: [PATCH 014/324] MessageDelete handling
---
.../packets/WebSocketPacketManager.js | 1 +
.../packets/handlers/MessageDelete.js | 32 +++++++++++++++++++
src/structures/DMChannel.js | 3 +-
src/structures/Message.js | 1 +
src/structures/TextChannel.js | 3 +-
src/util/Constants.js | 1 +
test/random.js | 5 +++
7 files changed, 44 insertions(+), 2 deletions(-)
create mode 100644 src/client/websocket/packets/handlers/MessageDelete.js
diff --git a/src/client/websocket/packets/WebSocketPacketManager.js b/src/client/websocket/packets/WebSocketPacketManager.js
index d3c2d0ca6..1cfeb9362 100644
--- a/src/client/websocket/packets/WebSocketPacketManager.js
+++ b/src/client/websocket/packets/WebSocketPacketManager.js
@@ -38,6 +38,7 @@ class WebSocketPacketManager {
this.register(Constants.WSEvents.VOICE_STATE_UPDATE, 'VoiceStateUpdate');
this.register(Constants.WSEvents.TYPING_START, 'TypingStart');
this.register(Constants.WSEvents.MESSAGE_CREATE, 'MessageCreate');
+ this.register(Constants.WSEvents.MESSAGE_DELETE, 'MessageDelete');
}
get client() {
diff --git a/src/client/websocket/packets/handlers/MessageDelete.js b/src/client/websocket/packets/handlers/MessageDelete.js
new file mode 100644
index 000000000..43944fcbc
--- /dev/null
+++ b/src/client/websocket/packets/handlers/MessageDelete.js
@@ -0,0 +1,32 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+const Constants = require('../../../../util/Constants');
+
+const Message = Structure('Message');
+const Guild = Structure('Guild');
+
+class MessageDeleteHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+ let channel = client.store.get('channels', data.channel_id);
+ if (channel) {
+ let message = channel.store.get('messages', data.id);
+ if (message) {
+ channel.store.remove('messages', message.id);
+ client.emit(Constants.Events.MESSAGE_DELETE, message);
+ }
+ }
+
+ }
+
+};
+
+module.exports = MessageDeleteHandler;
diff --git a/src/structures/DMChannel.js b/src/structures/DMChannel.js
index b1bdd92c7..f755c3b87 100644
--- a/src/structures/DMChannel.js
+++ b/src/structures/DMChannel.js
@@ -20,8 +20,9 @@ class DMChannel extends Channel{
let storeKeys = Object.keys(this.store);
if (storeKeys.length >= maxSize) {
this.store.remove(storeKeys[0]);
- this.store.add('messages', message);
}
+
+ this.store.add('messages', message);
}
setup(data) {
diff --git a/src/structures/Message.js b/src/structures/Message.js
index 1da8cf9bc..8f600f929 100644
--- a/src/structures/Message.js
+++ b/src/structures/Message.js
@@ -20,6 +20,7 @@ class Message {
this.embeds = data.embeds;
this.attachments = data.attachments;
this.mentions = [];
+ this.id = data.id;
for (let mention of data.mentions) {
let user = this.guild.client.store.get('users', mention.id);
if (user) {
diff --git a/src/structures/TextChannel.js b/src/structures/TextChannel.js
index c9ae55f06..eac0f45f6 100644
--- a/src/structures/TextChannel.js
+++ b/src/structures/TextChannel.js
@@ -20,8 +20,9 @@ class TextChannel extends ServerChannel {
let storeKeys = Object.keys(this.store);
if (storeKeys.length >= maxSize) {
this.store.remove(storeKeys[0]);
- this.store.add('messages', message);
}
+
+ this.store.add('messages', message);
}
}
diff --git a/src/util/Constants.js b/src/util/Constants.js
index abbf2c6a2..ad5713e18 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -100,6 +100,7 @@ const Events = exports.Events = {
WARN: 'warn',
GUILD_MEMBERS_CHUNK: 'guildMembersChunk',
MESSAGE_CREATE: 'message',
+ MESSAGE_DELETE: 'messageDelete',
};
const WSEvents = exports.WSEvents = {
diff --git a/test/random.js b/test/random.js
index f8df05a74..54fde3c24 100644
--- a/test/random.js
+++ b/test/random.js
@@ -68,5 +68,10 @@ client.on('typingStop.', (channel, user, data) => {
});
client.on('message', message => {
+ if (message.author.username === 'hydrabolt')
console.log(message.author.username, 'said', message.content, 'in', message.channel.name);
});
+
+client.on('messageDelete', message => {
+ console.log('Message deleted by', message.author.username);
+});
From 00327a577690cdbcc7e4a8d591cf3d8559a88d93 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Mon, 18 Apr 2016 18:12:57 +0100
Subject: [PATCH 015/324] Add MessageUpdate handling
---
.../packets/WebSocketPacketManager.js | 1 +
.../packets/handlers/MessageUpdate.js | 35 +++++++++++++++++++
src/structures/Message.js | 32 +++++++++++++++++
src/util/Constants.js | 3 +-
test/random.js | 5 +++
5 files changed, 75 insertions(+), 1 deletion(-)
create mode 100644 src/client/websocket/packets/handlers/MessageUpdate.js
diff --git a/src/client/websocket/packets/WebSocketPacketManager.js b/src/client/websocket/packets/WebSocketPacketManager.js
index 1cfeb9362..8e0341757 100644
--- a/src/client/websocket/packets/WebSocketPacketManager.js
+++ b/src/client/websocket/packets/WebSocketPacketManager.js
@@ -39,6 +39,7 @@ class WebSocketPacketManager {
this.register(Constants.WSEvents.TYPING_START, 'TypingStart');
this.register(Constants.WSEvents.MESSAGE_CREATE, 'MessageCreate');
this.register(Constants.WSEvents.MESSAGE_DELETE, 'MessageDelete');
+ this.register(Constants.WSEvents.MESSAGE_UPDATE, 'MessageUpdate');
}
get client() {
diff --git a/src/client/websocket/packets/handlers/MessageUpdate.js b/src/client/websocket/packets/handlers/MessageUpdate.js
new file mode 100644
index 000000000..e6daf2bbc
--- /dev/null
+++ b/src/client/websocket/packets/handlers/MessageUpdate.js
@@ -0,0 +1,35 @@
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+const Constants = require('../../../../util/Constants');
+const CloneObject = require('../../../../util/CloneObject');
+
+const Message = Structure('Message');
+const Guild = Structure('Guild');
+
+class MessageUpdateHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+ let channel = client.store.get('channels', data.channel_id);
+
+ if (channel) {
+ let message = channel.store.get('messages', data.id);
+ if (message) {
+ let oldMessage = CloneObject(message);
+ message.patch(data);
+ client.emit(Constants.Events.MESSAGE_UPDATE, oldMessage, message);
+ }
+ }
+
+ }
+
+};
+
+module.exports = MessageUpdateHandler;
diff --git a/src/structures/Message.js b/src/structures/Message.js
index 8f600f929..025547e32 100644
--- a/src/structures/Message.js
+++ b/src/structures/Message.js
@@ -28,6 +28,38 @@ class Message {
}
}
}
+
+ patch(data) {
+ if (data.author)
+ this.author = this.guild.client.store.get('users', data.author.id);
+ if (data.content)
+ this.content = data.content;
+ if (data.timestamp)
+ this.timestamp = new Date(data.timestamp);
+ if (data.edited_timestamp)
+ this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp) : null;
+ if (data.tts)
+ this.tts = data.tts;
+ if (data.mention_everyone)
+ this.mentionEveryone = data.mention_everyone;
+ if (data.nonce)
+ this.nonce = data.nonce;
+ if (data.embeds)
+ this.embeds = data.embeds;
+ if (data.attachments)
+ this.attachments = data.attachments;
+ if (data.mentions) {
+ for (let mention of data.mentions) {
+ let user = this.guild.client.store.get('users', mention.id);
+ if (user) {
+ this.mentions.push(user);
+ }
+ }
+ }
+
+ if (data.id)
+ this.id = data.id;
+ }
}
module.exports = Message;
diff --git a/src/util/Constants.js b/src/util/Constants.js
index ad5713e18..2b1705e0a 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -11,7 +11,7 @@ const DefaultOptions = exports.DefaultOptions = {
},
},
protocol_version: 4,
- max_message_cache: 20,
+ max_message_cache: 200,
};
const Package = exports.Package = require('../../package.json');
@@ -101,6 +101,7 @@ const Events = exports.Events = {
GUILD_MEMBERS_CHUNK: 'guildMembersChunk',
MESSAGE_CREATE: 'message',
MESSAGE_DELETE: 'messageDelete',
+ MESSAGE_UPDATE: 'messageUpdate',
};
const WSEvents = exports.WSEvents = {
diff --git a/test/random.js b/test/random.js
index 54fde3c24..f55fcecac 100644
--- a/test/random.js
+++ b/test/random.js
@@ -75,3 +75,8 @@ client.on('message', message => {
client.on('messageDelete', message => {
console.log('Message deleted by', message.author.username);
});
+
+client.on('messageUpdate', (old, message) => {
+ if (message.author.username === 'hydrabolt')
+ console.log('Message updated from', old.content, 'to', message.content);
+});
From da42b422f04be62521845cacb028aa84ec0f50f2 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Mon, 18 Apr 2016 19:31:36 +0100
Subject: [PATCH 016/324] Added Permission evaluation for channels and
EvaluatedPermissions class.
---
src/client/Client.js | 2 +
src/client/ClientDataResolver.js | 59 +++++++++++++++++++++++++
src/structures/EvaluatedPermissions.js | 39 +++++++++++++++++
src/structures/Guild.js | 19 +++++++-
src/structures/GuildMember.js | 6 +++
src/structures/ServerChannel.js | 60 +++++++++++++++++++++++++-
src/util/Constants.js | 10 +++++
test/random.js | 7 +++
8 files changed, 200 insertions(+), 2 deletions(-)
create mode 100644 src/client/ClientDataResolver.js
create mode 100644 src/structures/EvaluatedPermissions.js
diff --git a/src/client/Client.js b/src/client/Client.js
index 634cc790f..9a5fe5b64 100644
--- a/src/client/Client.js
+++ b/src/client/Client.js
@@ -6,6 +6,7 @@ const Constants = require('../util/Constants');
const RESTManager = require('./rest/RestManager');
const ClientDataStore = require('../structures/DataStore/ClientDataStore');
const ClientManager = require('./ClientManager');
+const ClientDataResolver = require('./ClientDataResolver');
const WebSocketManager = require('./websocket/WebSocketManager');
class Client extends EventEmitter{
@@ -17,6 +18,7 @@ class Client extends EventEmitter{
this.store = new ClientDataStore(this);
this.manager = new ClientManager(this);
this.ws = new WebSocketManager(this);
+ this.resolver = new ClientDataResolver(this);
}
login(email, password) {
diff --git a/src/client/ClientDataResolver.js b/src/client/ClientDataResolver.js
new file mode 100644
index 000000000..47ee3f9fc
--- /dev/null
+++ b/src/client/ClientDataResolver.js
@@ -0,0 +1,59 @@
+'use strict';
+
+const Structure = name => require(`../structures/${name}`);
+
+const User = Structure('User');
+const Message = Structure('Message');
+const Guild = Structure('Guild');
+const ServerChannel = Structure('ServerChannel');
+const TextChannel = Structure('TextChannel');
+const VoiceChannel = Structure('VoiceChannel');
+const GuildMember = Structure('GuildMember');
+
+function $string(obj) {
+ return (typeof obj === 'string' || obj instanceof String);
+}
+
+class ClientDataResolver {
+
+ constructor(client) {
+ this.client = client;
+ }
+
+ ResolveUser(user) {
+ if (user instanceof User) {
+ return user;
+ }else if ($string(user)) {
+ return this.client.store.get('users', user);
+ }else if (user instanceof Message) {
+ return user.author;
+ }else if (user instanceof Guild) {
+ return user.owner;
+ }
+
+ return null;
+ }
+
+ ResolveGuild(guild) {
+ if (guild instanceof Guild) {
+ return guild;
+ }
+ }
+
+ ResolveGuildMember(guild, user) {
+ if (user instanceof GuildMember) {
+ return user;
+ }
+
+ guild = this.ResolveGuild(guild);
+ user = this.ResolveUser(user);
+
+ if (!guild || !user) {
+ return null;
+ }
+
+ return guild.store.get('members', user.id);
+ }
+}
+
+module.exports = ClientDataResolver;
diff --git a/src/structures/EvaluatedPermissions.js b/src/structures/EvaluatedPermissions.js
new file mode 100644
index 000000000..96d0a4c9d
--- /dev/null
+++ b/src/structures/EvaluatedPermissions.js
@@ -0,0 +1,39 @@
+'use strict';
+
+const Constants = require('../Util/Constants');
+
+class EvaluatedPermissions {
+ constructor(member, permissions) {
+ this.member = member;
+ this.permissions = permissions;
+ }
+
+ serialize() {
+ let serializedPermissions = {};
+ for (let permissionName in Constants.PermissionFlags) {
+ serializedPermissions[permissionName] = this.hasPermission(permissionName);
+ }
+
+ return serializedPermissions;
+ }
+
+ hasPermission(permission, explicit) {
+ if (permission instanceof String || typeof permission === 'string') {
+ permission = Constants.PermissionFlags[permission];
+ }
+
+ if (!permission) {
+ throw Constants.Errors.NOT_A_PERMISSION;
+ }
+
+ if (!explicit) {
+ if ((this.permissions & Constants.PermissionFlags.MANAGE_ROLES) > 0) {
+ return true;
+ }
+ }
+
+ return ((this.permissions & permission) > 0);
+ }
+}
+
+module.exports = EvaluatedPermissions;
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index f6fb90a00..462edee38 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -60,12 +60,15 @@ class Guild {
return this.name;
}
+ member(user) {
+ return this.client.resolver.ResolveGuildMember(this, user);
+ }
+
setup(data) {
this.id = data.id;
this.available = !data.unavailable;
this.splash = data.splash;
this.region = data.region;
- this.ownerID = data.owner_id;
this.name = data.name;
this.memberCount = data.member_count;
this.large = data.large;
@@ -87,6 +90,8 @@ class Guild {
}
}
+ this.owner = this.store.get('members', data.owner_id);
+
if (data.channels) {
this.store.clear('channels');
for (let channel of data.channels) {
@@ -125,6 +130,18 @@ class Guild {
}
}
}
+
+ get channels() { return this.store.getAsArray('channels'); }
+
+ get $channels() { return this.store.data.channels; }
+
+ get roles() { return this.store.getAsArray('roles'); }
+
+ get $roles() { return this.store.data.roles; }
+
+ get members() { return this.store.getAsArray('members'); }
+
+ get $members() { return this.store.data.members; }
}
module.exports = Guild;
diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js
index e8b531db0..265f0afe6 100644
--- a/src/structures/GuildMember.js
+++ b/src/structures/GuildMember.js
@@ -25,6 +25,12 @@ class GuildMember {
get roles() {
let list = [];
+ let everyoneRole = this.guild.store.get('roles', this.guild.id);
+
+ if (everyoneRole) {
+ list.push(everyoneRole);
+ }
+
for (let roleID of this._roles) {
let role = this.guild.store.get('roles', roleID);
if (role) {
diff --git a/src/structures/ServerChannel.js b/src/structures/ServerChannel.js
index 9be3bd58a..ebd7ea8b6 100644
--- a/src/structures/ServerChannel.js
+++ b/src/structures/ServerChannel.js
@@ -2,6 +2,8 @@
const Channel = require('./Channel');
const PermissionOverwrites = require('./PermissionOverwrites');
+const EvaluatedPermissions = require('./EvaluatedPermissions');
+const Constants = require('../util/Constants');
class ServerChannel extends Channel{
constructor(guild, data) {
@@ -15,7 +17,7 @@ class ServerChannel extends Channel{
this.position = data.position;
this.name = data.name;
this.lastMessageID = data.last_message_id;
-
+ this.ow = data.permission_overwrites;
if (data.permission_overwrites) {
this.permissionOverwrites = [];
for (let overwrite of data.permission_overwrites) {
@@ -24,6 +26,62 @@ class ServerChannel extends Channel{
}
}
+ permissionsFor(member) {
+ member = this.client.resolver.ResolveGuildMember(this.guild, member);
+ if (member) {
+ if (this.guild.owner.id === member.id) {
+ return new EvaluatedPermissions(member, Constants.ALL_PERMISSIONS);
+ }
+
+ let roles = member.roles;
+ let permissions = 0;
+ let overwrites = this.overwritesFor(member, true);
+
+ for (let role of roles) {
+ permissions |= role.permissions;
+ }
+
+ for (let overwrite of overwrites.role.concat(overwrites.member)) {
+ permissions = permissions & ~overwrite.denyData;
+ permissions = permissions | overwrite.allowData;
+ }
+
+ if (!!(permissions & (Constants.PermissionFlags.MANAGE_ROLES))) {
+ permissions = Constants.ALL_PERMISSIONS;
+ }
+
+ return new EvaluatedPermissions(member, permissions);
+ }
+ }
+
+ overwritesFor(member, verified) {
+ // for speed
+ if (!verified)
+ member = this.client.resolver.ResolveGuildMember(this.guild, member);
+ if (member) {
+ let found = [];
+ let memberRoles = member._roles;
+
+ let roleOverwrites = [];
+ let memberOverwrites = [];
+
+ for (let overwrite of this.permissionOverwrites) {
+ if (overwrite.id === member.id) {
+ memberOverwrites.push(overwrite);
+ } else if (memberRoles.indexOf(overwrite.id) > -1) {
+ roleOverwrites.push(overwrite);
+ }
+ }
+
+ return {
+ role: roleOverwrites,
+ member: memberOverwrites,
+ };
+ }
+
+ return [];
+ }
+
toString() {
return this.name;
}
diff --git a/src/util/Constants.js b/src/util/Constants.js
index 2b1705e0a..802b1714c 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -1,3 +1,5 @@
+'use strict';
+
const DefaultOptions = exports.DefaultOptions = {
ws: {
large_threshold: 250,
@@ -157,4 +159,12 @@ const PermissionFlags = exports.PermissionFlags = {
USE_VAD: 1 << 25,
};
+let _ALL_PERMISSIONS = 0;
+
+for (let key in PermissionFlags) {
+ _ALL_PERMISSIONS |= PermissionFlags[key];
+}
+
+const ALL_PERMISSIONS = exports.ALL_PERMISSIONS = _ALL_PERMISSIONS;
+
const DEFAULT_PERMISSIONS = exports.DEFAULT_PERMISSIONS = 36953089;
diff --git a/test/random.js b/test/random.js
index f55fcecac..64575e0c5 100644
--- a/test/random.js
+++ b/test/random.js
@@ -80,3 +80,10 @@ client.on('messageUpdate', (old, message) => {
if (message.author.username === 'hydrabolt')
console.log('Message updated from', old.content, 'to', message.content);
});
+
+client.on('message', message => {
+ if (message.content === '?perms?') {
+ console.log(message.author.username, 'asked for perms in', message.channel.name, ':');
+ console.log(message.channel.permissionsFor(message.author).serialize());
+ }
+});
From acc9c9bf123ac2c4afd42e5d18ea4612600141b5 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Tue, 19 Apr 2016 20:24:23 +0100
Subject: [PATCH 017/324]
src/client/websocket/packets/WebSocketPacketManager.js
src/structures/datastore/WebSocketManagerDataStore.js Added "rough"
reconnection attempting The following however still needs to be done: 1) stop
trying after a certain amount of time 2) increasing timeout between each
timeout 3) re-evaluate the current method of how reconnecting is handled
internally
---
src/client/websocket/WebSocketManager.js | 45 +++++++++++++++++--
.../packets/WebSocketPacketManager.js | 28 ++++++++++--
.../websocket/packets/handlers/Ready.js | 2 +
.../datastore/WebSocketManagerDataStore.js | 14 ++++++
test/random.js | 3 +-
5 files changed, 85 insertions(+), 7 deletions(-)
create mode 100644 src/structures/datastore/WebSocketManagerDataStore.js
diff --git a/src/client/websocket/WebSocketManager.js b/src/client/websocket/WebSocketManager.js
index 41c7ea407..83324576b 100644
--- a/src/client/websocket/WebSocketManager.js
+++ b/src/client/websocket/WebSocketManager.js
@@ -4,6 +4,7 @@ const WebSocket = require('ws');
const Constants = require('../../util/Constants');
const zlib = require('zlib');
const PacketManager = require('./packets/WebSocketPacketManager');
+const WebSocketManagerDataStore = require('../../structures/datastore/WebSocketManagerDataStore');
class WebSocketManager {
@@ -12,9 +13,12 @@ class WebSocketManager {
this.ws = null;
this.packetManager = new PacketManager(this);
this.emittedReady = false;
+ this.store = new WebSocketManagerDataStore();
+ this.reconnecting = false;
}
connect(gateway) {
+ this.store.gateway = gateway;
gateway += `/?v=${this.client.options.protocol_version}`;
this.ws = new WebSocket(gateway);
this.ws.onopen = () => this.EventOpen();
@@ -24,10 +28,34 @@ class WebSocketManager {
}
send(data) {
- this.ws.send(JSON.stringify(data));
+ if (this.ws.readyState === WebSocket.OPEN) {
+ this.ws.send(JSON.stringify(data));
+ }
}
EventOpen() {
+ if (this.reconnecting) {
+ this._sendResume();
+ } else {
+ this._sendNewIdentify();
+ }
+ }
+
+ _sendResume() {
+ let payload = {
+ token: this.client.store.token,
+ session_id: this.store.sessionID,
+ seq: this.store.sequence,
+ };
+
+ this.send({
+ op: Constants.OPCodes.RESUME,
+ d: payload,
+ });
+ }
+
+ _sendNewIdentify() {
+ this.reconnecting = false;
let payload = this.client.options.ws;
payload.token = this.client.store.token;
@@ -38,7 +66,9 @@ class WebSocketManager {
}
EventClose() {
-
+ if (!this.reconnecting) {
+ this.tryReconnect();
+ }
}
EventMessage(event) {
@@ -57,7 +87,7 @@ class WebSocketManager {
}
EventError(e) {
-
+ this.tryReconnect();
}
checkIfReady() {
@@ -75,6 +105,15 @@ class WebSocketManager {
}
}
}
+
+ tryReconnect() {
+ this.reconnecting = true;
+ this.ws.close();
+ this.packetManager.handleQueue();
+ this.client.emit(Constants.Events.RECONNECTING);
+ this.emittedReady = false;
+ this.connect(this.store.gateway);
+ }
}
module.exports = WebSocketManager;
diff --git a/src/client/websocket/packets/WebSocketPacketManager.js b/src/client/websocket/packets/WebSocketPacketManager.js
index 8e0341757..2f01da2a7 100644
--- a/src/client/websocket/packets/WebSocketPacketManager.js
+++ b/src/client/websocket/packets/WebSocketPacketManager.js
@@ -8,8 +8,6 @@ const BeforeReadyWhitelist = [
Constants.WSEvents.GUILD_DELETE,
];
-var amount = 0;
-
class WebSocketPacketManager {
constructor(websocketManager) {
@@ -58,8 +56,32 @@ class WebSocketPacketManager {
}
}
+ setSequence(s) {
+ if (s && s > this.ws.store.sequence) {
+ this.ws.store.sequence = s;
+ }
+ }
+
handle(packet) {
- amount++;
+
+ if (packet.op === Constants.OPCodes.RECONNECT) {
+ this.setSequence(packet.s);
+ this.ws.tryReconnect();
+ return;
+ }
+
+ if (packet.op === Constants.OPCodes.INVALID_SESSION) {
+ this.ws._sendNewIdentify();
+ return;
+ }
+
+ if (this.ws.reconnecting) {
+ this.ws.reconnecting = false;
+ this.ws.checkIfReady();
+ }
+
+ this.setSequence(packet.s);
+
if (!this.ws.emittedReady) {
if (BeforeReadyWhitelist.indexOf(packet.t) === -1) {
this.queue.push(packet);
diff --git a/src/client/websocket/packets/handlers/Ready.js b/src/client/websocket/packets/handlers/Ready.js
index b5bd514f3..ffd4cd0cb 100644
--- a/src/client/websocket/packets/handlers/Ready.js
+++ b/src/client/websocket/packets/handlers/Ready.js
@@ -28,6 +28,8 @@ class ReadyHandler extends AbstractHandler {
client.store.NewChannel(privateDM);
}
+ this.packetManager.ws.store.sessionID = data.session_id;
+
this.packetManager.ws.checkIfReady();
}
diff --git a/src/structures/datastore/WebSocketManagerDataStore.js b/src/structures/datastore/WebSocketManagerDataStore.js
new file mode 100644
index 000000000..a63d41369
--- /dev/null
+++ b/src/structures/datastore/WebSocketManagerDataStore.js
@@ -0,0 +1,14 @@
+'use strict';
+
+const AbstractDataStore = require('./AbstractDataStore');
+
+class WebSocketManagerDataStore extends AbstractDataStore{
+ constructor() {
+ super();
+ this.sessionID = null;
+ this.sequence = -1;
+ this.gateway = null;
+ }
+}
+
+module.exports = WebSocketManagerDataStore;
diff --git a/test/random.js b/test/random.js
index 64575e0c5..8e4b8e315 100644
--- a/test/random.js
+++ b/test/random.js
@@ -4,9 +4,10 @@ const Discord = require('../');
let client = new Discord.Client();
-client.login(require('./auth.json').token).then(token => console.log('ready!')).catch(console.log);
+client.login(require('./auth.json').token).then(token => console.log('logged in with token ' + token)).catch(console.log);
client.on('ready', () => {
+ console.log('ready!');
});
client.on('guildCreate', (guild) => {
From b8283a8f299af40daed8ff4c6d1fb1541fad8ac7 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Wed, 20 Apr 2016 17:45:20 +0100
Subject: [PATCH 018/324]
src/client/websocket/packets/WebSocketPacketManager.js Unify ready and
reconnecting properties into a single status property and future-proof
Message class The state of the WebSocketManager is now represented by a
single status property, removing emittedReady and reconnecting as
representations of state. Message class will now also cache users it isn't
aware of that appear in mentions and authors.
---
src/client/websocket/WebSocketManager.js | 11 +++++------
.../websocket/packets/WebSocketPacketManager.js | 2 +-
src/structures/Guild.js | 6 +++---
src/structures/Message.js | 8 +++++++-
src/structures/datastore/ClientDataStore.js | 2 +-
src/util/Constants.js | 7 +++++++
6 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/src/client/websocket/WebSocketManager.js b/src/client/websocket/WebSocketManager.js
index 83324576b..a3d7f08ca 100644
--- a/src/client/websocket/WebSocketManager.js
+++ b/src/client/websocket/WebSocketManager.js
@@ -12,12 +12,12 @@ class WebSocketManager {
this.client = client;
this.ws = null;
this.packetManager = new PacketManager(this);
- this.emittedReady = false;
this.store = new WebSocketManagerDataStore();
- this.reconnecting = false;
+ this.status = Constants.Status.IDLE;
}
connect(gateway) {
+ this.status = Constants.Status.CONNECTING;
this.store.gateway = gateway;
gateway += `/?v=${this.client.options.protocol_version}`;
this.ws = new WebSocket(gateway);
@@ -91,7 +91,7 @@ class WebSocketManager {
}
checkIfReady() {
- if (!this.emittedReady) {
+ if (this.status !== Constants.Status.READY) {
let unavailableCount = 0;
for (let guildID in this.client.store.data.guilds) {
@@ -99,19 +99,18 @@ class WebSocketManager {
}
if (unavailableCount === 0) {
+ this.status = Constants.Status.READY;
this.client.emit(Constants.Events.READY);
- this.emittedReady = true;
this.packetManager.handleQueue();
}
}
}
tryReconnect() {
- this.reconnecting = true;
+ this.status = Constants.Status.RECONNECTING;
this.ws.close();
this.packetManager.handleQueue();
this.client.emit(Constants.Events.RECONNECTING);
- this.emittedReady = false;
this.connect(this.store.gateway);
}
}
diff --git a/src/client/websocket/packets/WebSocketPacketManager.js b/src/client/websocket/packets/WebSocketPacketManager.js
index 2f01da2a7..b4e123033 100644
--- a/src/client/websocket/packets/WebSocketPacketManager.js
+++ b/src/client/websocket/packets/WebSocketPacketManager.js
@@ -82,7 +82,7 @@ class WebSocketPacketManager {
this.setSequence(packet.s);
- if (!this.ws.emittedReady) {
+ if (this.ws.status !== Constants.Status.READY) {
if (BeforeReadyWhitelist.indexOf(packet.t) === -1) {
this.queue.push(packet);
return;
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index 462edee38..766cc6955 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -33,7 +33,7 @@ class Guild {
guildUser.joined_at = guildUser.joined_at || 0;
let member = this.store.add('members', new GuildMember(this, guildUser));
- if (this.client.ws.emittedReady && !noEvent) {
+ if (this.client.ws.status === Constants.Status.READY && !noEvent) {
this.client.emit(Constants.Events.GUILD_MEMBER_ADD, this, member);
}
@@ -44,14 +44,14 @@ class Guild {
let oldRoles = member.roles;
member._roles = data.roles;
- if (this.client.ws.emittedReady) {
+ if (this.client.ws.status === Constants.Status.READY) {
this.client.emit(Constants.Events.GUILD_MEMBER_ROLES_UPDATE, this, oldRoles, member.roles);
}
}
_removeMember(guildMember) {
this.store.remove('members', guildMember);
- if (this.client.ws.emittedReady) {
+ if (this.client.ws.status === Constants.Status.READY) {
this.client.emit(Constants.Events.GUILD_MEMBER_REMOVE, this, guildMember);
}
}
diff --git a/src/structures/Message.js b/src/structures/Message.js
index 025547e32..b0262e04a 100644
--- a/src/structures/Message.js
+++ b/src/structures/Message.js
@@ -10,7 +10,7 @@ class Message {
}
setup(data) {
- this.author = this.guild.client.store.get('users', data.author.id);
+ this.author = this.guild.client.store.NewUser(data.author);
this.content = data.content;
this.timestamp = new Date(data.timestamp);
this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp) : null;
@@ -25,6 +25,9 @@ class Message {
let user = this.guild.client.store.get('users', mention.id);
if (user) {
this.mentions.push(user);
+ } else {
+ user = this.guild.client.store.NewUser(mention);
+ this.mentions.push(user);
}
}
}
@@ -53,6 +56,9 @@ class Message {
let user = this.guild.client.store.get('users', mention.id);
if (user) {
this.mentions.push(user);
+ } else {
+ user = this.guild.client.store.NewUser(mention);
+ this.mentions.push(user);
}
}
}
diff --git a/src/structures/datastore/ClientDataStore.js b/src/structures/datastore/ClientDataStore.js
index 6b9a89488..8cae0c97e 100644
--- a/src/structures/datastore/ClientDataStore.js
+++ b/src/structures/datastore/ClientDataStore.js
@@ -25,7 +25,7 @@ class ClientDataStore extends AbstractDataStore{
}
get pastReady() {
- return this.client.ws.emittedReady;
+ return this.client.ws.status === Constants.Status.READY;
}
NewGuild(data) {
diff --git a/src/util/Constants.js b/src/util/Constants.js
index 802b1714c..43ad1819c 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -16,6 +16,13 @@ const DefaultOptions = exports.DefaultOptions = {
max_message_cache: 200,
};
+const Status = exports.Status = {
+ READY: 0,
+ CONNECTING: 1,
+ RECONNECTING: 2,
+ IDLE: 3,
+};
+
const Package = exports.Package = require('../../package.json');
const Errors = exports.Errors = {
From f3e1760538887b4bb7c2c275961978b905eccb37 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Thu, 21 Apr 2016 17:42:52 +0100
Subject: [PATCH 019/324] add channel.sendMessage and channel.sendTTSMessage
---
src/client/rest/RESTMethods.js | 18 +++++++++++++++
.../packets/handlers/MessageCreate.js | 2 +-
src/structures/DMChannel.js | 4 ++++
src/structures/Message.js | 23 +++++++++++--------
src/structures/TextChannel.js | 3 +++
src/structures/interface/TextBasedChannel.js | 20 ++++++++++++++++
test/random.js | 2 +-
7 files changed, 61 insertions(+), 11 deletions(-)
create mode 100644 src/structures/interface/TextBasedChannel.js
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index 228f6f7da..2f2c27f87 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -1,6 +1,9 @@
'use strict';
const Constants = require('../../util/Constants');
+const Structure = name => require('../../structures/' + name);
+
+const Message = Structure('Message');
class RESTMethods{
constructor(restManager) {
@@ -32,6 +35,21 @@ class RESTMethods{
.catch(reject);
});
}
+
+ SendMessage(channel, content, tts, nonce) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('post', Constants.Endpoints.CHANNEL_MESSAGES(channel.id), true, {
+ content, tts, nonce,
+ })
+ .then(data => {
+ let message = new Message(channel, data, this.rest.client);
+ channel._cacheMessage(message);
+ resolve(message);
+ this.rest.client.emit(Constants.Events.MESSAGE_CREATE, message);
+ })
+ .catch(reject);
+ });
+ }
}
module.exports = RESTMethods;
diff --git a/src/client/websocket/packets/handlers/MessageCreate.js b/src/client/websocket/packets/handlers/MessageCreate.js
index f6e2cf35e..d701d0a97 100644
--- a/src/client/websocket/packets/handlers/MessageCreate.js
+++ b/src/client/websocket/packets/handlers/MessageCreate.js
@@ -19,7 +19,7 @@ class MessageCreateHandler extends AbstractHandler {
let channel = client.store.get('channels', data.channel_id);
if (channel) {
- let message = new Message(channel, data);
+ let message = new Message(channel, data, client);
channel._cacheMessage(message);
client.emit(Constants.Events.MESSAGE_CREATE, message);
}
diff --git a/src/structures/DMChannel.js b/src/structures/DMChannel.js
index f755c3b87..f0b7523b2 100644
--- a/src/structures/DMChannel.js
+++ b/src/structures/DMChannel.js
@@ -1,6 +1,7 @@
'use strict';
const Channel = require('./Channel');
+const TextBasedChannel = require('./interface/TextBasedChannel');
const User = require('./User');
const TextChannelDataStore = require('./datastore/TextChannelDataStore');
@@ -26,6 +27,7 @@ class DMChannel extends Channel{
}
setup(data) {
+ super.setup(data);
this.recipient = this.client.store.add('users', new User(this.client, data.recipient));
this.lastMessageID = data.last_message_id;
}
@@ -35,4 +37,6 @@ class DMChannel extends Channel{
}
}
+TextBasedChannel.applyToClass(DMChannel);
+
module.exports = DMChannel;
diff --git a/src/structures/Message.js b/src/structures/Message.js
index b0262e04a..b5a0b3e12 100644
--- a/src/structures/Message.js
+++ b/src/structures/Message.js
@@ -1,16 +1,21 @@
'use strict';
class Message {
- constructor(serverChannel, data) {
- this.channel = serverChannel;
- this.guild = serverChannel.guild;
+ constructor(channel, data, client) {
+ this.channel = channel;
+
+ if (channel.guild) {
+ this.guild = channel.guild;
+ }
+
+ this.client = client;
if (data) {
this.setup(data);
}
}
setup(data) {
- this.author = this.guild.client.store.NewUser(data.author);
+ this.author = this.client.store.NewUser(data.author);
this.content = data.content;
this.timestamp = new Date(data.timestamp);
this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp) : null;
@@ -22,11 +27,11 @@ class Message {
this.mentions = [];
this.id = data.id;
for (let mention of data.mentions) {
- let user = this.guild.client.store.get('users', mention.id);
+ let user = this.client.store.get('users', mention.id);
if (user) {
this.mentions.push(user);
} else {
- user = this.guild.client.store.NewUser(mention);
+ user = this.client.store.NewUser(mention);
this.mentions.push(user);
}
}
@@ -34,7 +39,7 @@ class Message {
patch(data) {
if (data.author)
- this.author = this.guild.client.store.get('users', data.author.id);
+ this.author = this.client.store.get('users', data.author.id);
if (data.content)
this.content = data.content;
if (data.timestamp)
@@ -53,11 +58,11 @@ class Message {
this.attachments = data.attachments;
if (data.mentions) {
for (let mention of data.mentions) {
- let user = this.guild.client.store.get('users', mention.id);
+ let user = this.client.store.get('users', mention.id);
if (user) {
this.mentions.push(user);
} else {
- user = this.guild.client.store.NewUser(mention);
+ user = this.client.store.NewUser(mention);
this.mentions.push(user);
}
}
diff --git a/src/structures/TextChannel.js b/src/structures/TextChannel.js
index eac0f45f6..a93c831be 100644
--- a/src/structures/TextChannel.js
+++ b/src/structures/TextChannel.js
@@ -2,6 +2,7 @@
const ServerChannel = require('./ServerChannel');
const TextChannelDataStore = require('./datastore/TextChannelDataStore');
+const TextBasedChannel = require('./interface/TextBasedChannel');
class TextChannel extends ServerChannel {
@@ -26,4 +27,6 @@ class TextChannel extends ServerChannel {
}
}
+TextBasedChannel.applyToClass(TextChannel);
+
module.exports = TextChannel;
diff --git a/src/structures/interface/TextBasedChannel.js b/src/structures/interface/TextBasedChannel.js
new file mode 100644
index 000000000..0656d03f7
--- /dev/null
+++ b/src/structures/interface/TextBasedChannel.js
@@ -0,0 +1,20 @@
+'use strict';
+
+function sendMessage(content, options) {
+ options = options || {};
+ return this.client.rest.methods.SendMessage(this, content, options.tts);
+}
+
+function sendTTSMessage(content, options) {
+ options = options || {};
+ return this.client.rest.methods.SendMessage(this, content, true);
+}
+
+exports.applyToClass = structure => {
+ if (structure.name !== 'TextChannel' && structure.name !== 'DMChannel') {
+ throw new Error(structure + ' cannot implement TextBasedChannel');
+ }
+
+ structure.prototype.sendMessage = sendMessage;
+
+};
diff --git a/test/random.js b/test/random.js
index 8e4b8e315..87633f281 100644
--- a/test/random.js
+++ b/test/random.js
@@ -70,7 +70,7 @@ client.on('typingStop.', (channel, user, data) => {
client.on('message', message => {
if (message.author.username === 'hydrabolt')
- console.log(message.author.username, 'said', message.content, 'in', message.channel.name);
+ message.channel.sendMessage('hydrabolt said: ' + message.content).then(console.log).catch(console.log);
});
client.on('messageDelete', message => {
From 03caddb4b5e0d01035da53470e288215274f0018 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Thu, 21 Apr 2016 18:24:08 +0100
Subject: [PATCH 020/324] Add Rate Limiting, see
hammerandchisel/discord-api-docs#20
---
src/client/rest/RESTManager.js | 55 +++++++++++++++++++++++++++++++++-
test/random.js | 2 +-
2 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/src/client/rest/RESTManager.js b/src/client/rest/RESTManager.js
index 5cda94ccd..926a4de82 100644
--- a/src/client/rest/RESTManager.js
+++ b/src/client/rest/RESTManager.js
@@ -12,14 +12,57 @@ class RESTManager{
this.queue = [];
this.userAgentManager = new UserAgentManager(this);
this.methods = new RESTMethods(this);
+ this.rateLimitedEndpoints = {};
}
- makeRequest(method, url, auth, data, file) {
+ addRequestToQueue(method, url, auth, data, file, resolve, reject) {
+ let endpoint = url.replace(/\/[0-9]+/g, '/:id');
+
+ let rateLimitedEndpoint = this.rateLimitedEndpoints[endpoint];
+
+ rateLimitedEndpoint.queue = rateLimitedEndpoint.queue || [];
+
+ rateLimitedEndpoint.queue.push({
+ method, url, auth, data, file, resolve, reject,
+ });
+ }
+
+ processQueue(endpoint) {
+ let rateLimitedEndpoint = this.rateLimitedEndpoints[endpoint];
+
+ // prevent multiple queue processes
+ if (!rateLimitedEndpoint.timeout) {
+ return;
+ }
+
+ // lock the queue
+ clearTimeout(rateLimitedEndpoint.timeout);
+ rateLimitedEndpoint.timeout = null;
+
+ for (let item of rateLimitedEndpoint.queue) {
+ this.makeRequest(item.method, item.url, item.auth, item.data, item.file)
+ .then(item.resolve)
+ .catch(item.reject);
+ }
+
+ rateLimitedEndpoint.queue = [];
+ }
+
+ makeRequest(method, url, auth, data, file, fromQueue) {
/*
file is {file, name}
*/
let apiRequest = request[method](url);
+ let endpoint = url.replace(/\/[0-9]+/g, '/:id');
+
+ if (this.rateLimitedEndpoints[endpoint] && this.rateLimitedEndpoints[endpoint].timeout) {
+ console.log('adding to queue');
+ return new Promise((resolve, reject) => {
+ this.addRequestToQueue(method, url, auth, data, file, resolve, reject);
+ });
+ }
+
if (auth) {
if (this.client.store.token) {
apiRequest.set('authorization', this.client.store.token);
@@ -41,6 +84,16 @@ class RESTManager{
return new Promise((resolve, reject) => {
apiRequest.end((err, res) => {
if (err) {
+ let retry = res.headers['retry-after'] || res.headers['Retry-After'];
+ if (retry) {
+ this.rateLimitedEndpoints[endpoint] = {};
+ this.addRequestToQueue(method, url, auth, data, file, resolve, reject);
+ this.rateLimitedEndpoints[endpoint].timeout = setTimeout(() => {
+ this.processQueue(endpoint);
+ }, retry);
+ return;
+ }
+
reject(err);
} else {
resolve(res ? res.body || {} : {});
diff --git a/test/random.js b/test/random.js
index 87633f281..8bc302fdd 100644
--- a/test/random.js
+++ b/test/random.js
@@ -70,7 +70,7 @@ client.on('typingStop.', (channel, user, data) => {
client.on('message', message => {
if (message.author.username === 'hydrabolt')
- message.channel.sendMessage('hydrabolt said: ' + message.content).then(console.log).catch(console.log);
+ message.channel.sendMessage('hydrabolt said: ' + message.content).then(m => console.log(m.content)).catch(console.log);
});
client.on('messageDelete', message => {
From a2841f285c37311279c2ffcdb6cc86d67a59967d Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Thu, 21 Apr 2016 18:40:26 +0100
Subject: [PATCH 021/324] Add TODO list
---
TODO.md | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
create mode 100644 TODO.md
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 000000000..d3020a8bd
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,33 @@
+# To-do list:
+- [x] sending messages
+- [x] sending tts messages
+- [ ] sending files
+- [ ] updating user details
+- [ ] deleting messages
+- [ ] updating messages
+- [ ] leaving guilds
+- [ ] deleting guilds
+- [ ] _joining guilds_
+- [ ] creating channels
+- [ ] updating channels
+- [ ] deleting channels
+- [ ] making roles
+- [ ] deleting roles
+- [ ] updating roles
+- [ ] logging out
+- [ ] modifying channel overwrites
+- [ ] fetching guild members
+- [ ] getting channel logs
+- [ ] getting bans
+- [ ] banning members
+- [ ] unbanning members
+- [ ] kicking members
+- [ ] moving voice channel members
+- [ ] muting/deafening voice channel members
+- [ ] voice support
+- [ ] adding members to roles
+- [ ] creating invites
+- [ ] updating invites
+- [ ] deleting invites
+- [ ] getting invites
+- [ ] typing simulation
\ No newline at end of file
From c42e303b7b455c107f0965ad2fe00b9ca4c6349c Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Thu, 21 Apr 2016 18:50:46 +0100
Subject: [PATCH 022/324] Add Message Deletion via message.delete()
---
TODO.md | 2 +-
src/client/rest/RESTMethods.js | 10 ++++++++++
src/structures/Message.js | 4 ++++
test/random.js | 7 +++++--
4 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/TODO.md b/TODO.md
index d3020a8bd..090d3ebe0 100644
--- a/TODO.md
+++ b/TODO.md
@@ -3,7 +3,7 @@
- [x] sending tts messages
- [ ] sending files
- [ ] updating user details
-- [ ] deleting messages
+- [x] deleting messages
- [ ] updating messages
- [ ] leaving guilds
- [ ] deleting guilds
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index 2f2c27f87..e1066893d 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -50,6 +50,16 @@ class RESTMethods{
.catch(reject);
});
}
+
+ DeleteMessage(channel, message) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.CHANNEL_MESSAGE(channel.id, message.id), true)
+ .then(() => {
+ resolve(message);
+ })
+ .catch(reject);
+ });
+ }
}
module.exports = RESTMethods;
diff --git a/src/structures/Message.js b/src/structures/Message.js
index b5a0b3e12..6e501ede2 100644
--- a/src/structures/Message.js
+++ b/src/structures/Message.js
@@ -71,6 +71,10 @@ class Message {
if (data.id)
this.id = data.id;
}
+
+ delete() {
+ return this.client.rest.methods.DeleteMessage(this.channel, this);
+ }
}
module.exports = Message;
diff --git a/test/random.js b/test/random.js
index 8bc302fdd..52e1f57d4 100644
--- a/test/random.js
+++ b/test/random.js
@@ -69,8 +69,11 @@ client.on('typingStop.', (channel, user, data) => {
});
client.on('message', message => {
- if (message.author.username === 'hydrabolt')
- message.channel.sendMessage('hydrabolt said: ' + message.content).then(m => console.log(m.content)).catch(console.log);
+ if (message.author.username === 'hydrabolt') {
+ message.channel.sendMessage('test').then(msg => {
+ msg.delete();
+ });
+ }
});
client.on('messageDelete', message => {
From 1676a5e73f9ceb427b40429106572931f166d412 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sun, 24 Apr 2016 16:30:58 +0100
Subject: [PATCH 023/324] Bridged WebSocket Events and REST Requests. Now REST
Requests will respond exactly like WS Events to data
---
src/client/Client.js | 2 +
src/client/actions/Action.js | 27 ++++++++++++
src/client/actions/ActionsManager.js | 19 +++++++++
src/client/actions/MessageCreate.js | 31 ++++++++++++++
src/client/actions/MessageDelete.js | 42 +++++++++++++++++++
src/client/rest/RESTManager.js | 1 -
src/client/rest/RESTMethods.js | 12 +++---
.../packets/handlers/MessageCreate.js | 10 ++---
.../packets/handlers/MessageDelete.js | 13 +++---
src/structures/TextChannel.js | 2 +-
src/util/Constants.js | 1 +
test/random.js | 2 +-
12 files changed, 139 insertions(+), 23 deletions(-)
create mode 100644 src/client/actions/Action.js
create mode 100644 src/client/actions/ActionsManager.js
create mode 100644 src/client/actions/MessageCreate.js
create mode 100644 src/client/actions/MessageDelete.js
diff --git a/src/client/Client.js b/src/client/Client.js
index 9a5fe5b64..d48f6c2a8 100644
--- a/src/client/Client.js
+++ b/src/client/Client.js
@@ -8,6 +8,7 @@ const ClientDataStore = require('../structures/DataStore/ClientDataStore');
const ClientManager = require('./ClientManager');
const ClientDataResolver = require('./ClientDataResolver');
const WebSocketManager = require('./websocket/WebSocketManager');
+const ActionsManager = require('./actions/ActionsManager');
class Client extends EventEmitter{
@@ -19,6 +20,7 @@ class Client extends EventEmitter{
this.manager = new ClientManager(this);
this.ws = new WebSocketManager(this);
this.resolver = new ClientDataResolver(this);
+ this.actions = new ActionsManager(this);
}
login(email, password) {
diff --git a/src/client/actions/Action.js b/src/client/actions/Action.js
new file mode 100644
index 000000000..795022b6d
--- /dev/null
+++ b/src/client/actions/Action.js
@@ -0,0 +1,27 @@
+'use strict';
+
+/*
+
+ABOUT ACTIONS
+
+Actions are similar to WebSocket Packet Handlers, but since introducing
+the REST API methods, in order to prevent rewriting code to handle data,
+"actions" have been introduced. They're basically what Packet Handlers
+used to be but they're strictly for manipulating data and making sure
+that WebSocket events don't clash with REST methods.
+
+ */
+
+class GenericAction {
+
+ constructor(client) {
+ this.client = client;
+ }
+
+ handle(data) {
+
+ }
+
+};
+
+module.exports = GenericAction;
diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js
new file mode 100644
index 000000000..aef572bc4
--- /dev/null
+++ b/src/client/actions/ActionsManager.js
@@ -0,0 +1,19 @@
+'use strict';
+
+const requireAction = name => require(`./${name}`);
+
+class ActionsManager {
+ constructor(client) {
+ this.client = client;
+
+ this.register('MessageCreate');
+ this.register('MessageDelete');
+ }
+
+ register(name) {
+ let Action = requireAction(name);
+ this[name] = new Action(this.client);
+ }
+}
+
+module.exports = ActionsManager;
diff --git a/src/client/actions/MessageCreate.js b/src/client/actions/MessageCreate.js
new file mode 100644
index 000000000..55bae8b4e
--- /dev/null
+++ b/src/client/actions/MessageCreate.js
@@ -0,0 +1,31 @@
+'use strict';
+
+const Action = require('./Action');
+const Constants = require('../../util/Constants');
+const Message = require('../../structures/Message');
+
+class MessageCreateAction extends Action {
+
+ constructor(client) {
+ super(client);
+ }
+
+ handle(data) {
+
+ let client = this.client;
+ let channel = client.store.get('channels', data.channel_id);
+
+ if (channel) {
+ let message = channel._cacheMessage(new Message(channel, data, client));
+ return {
+ m: message,
+ };
+ }
+
+ return {
+ m: null,
+ };
+ }
+};
+
+module.exports = MessageCreateAction;
diff --git a/src/client/actions/MessageDelete.js b/src/client/actions/MessageDelete.js
new file mode 100644
index 000000000..9f82f0a15
--- /dev/null
+++ b/src/client/actions/MessageDelete.js
@@ -0,0 +1,42 @@
+'use strict';
+
+const Action = require('./Action');
+const Constants = require('../../util/Constants');
+const Message = require('../../structures/Message');
+
+class MessageDeleteAction extends Action {
+
+ constructor(client) {
+ super(client);
+ this.timeouts = [];
+ }
+
+ handle(data) {
+ let client = this.client;
+ let channel = client.store.get('channels', data.channel_id);
+ if (channel) {
+ let message = channel.store.get('messages', data.id);
+ if (message && !message._deleted) {
+ message._deleted = true;
+ this.scheduleForDeletion(channel, message.id);
+ }
+
+ return {
+ m: message,
+ };
+ }
+
+ return {
+ m: null,
+ };
+ }
+
+ scheduleForDeletion(channel, id) {
+ this.timeouts.push(
+ setTimeout(() => channel.store.remove('messages', id),
+ this.client.options.rest_ws_bridge_timeout)
+ );
+ }
+};
+
+module.exports = MessageDeleteAction;
diff --git a/src/client/rest/RESTManager.js b/src/client/rest/RESTManager.js
index 926a4de82..60c021a47 100644
--- a/src/client/rest/RESTManager.js
+++ b/src/client/rest/RESTManager.js
@@ -57,7 +57,6 @@ class RESTManager{
let endpoint = url.replace(/\/[0-9]+/g, '/:id');
if (this.rateLimitedEndpoints[endpoint] && this.rateLimitedEndpoints[endpoint].timeout) {
- console.log('adding to queue');
return new Promise((resolve, reject) => {
this.addRequestToQueue(method, url, auth, data, file, resolve, reject);
});
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index e1066893d..6f8c1e6ea 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -42,10 +42,7 @@ class RESTMethods{
content, tts, nonce,
})
.then(data => {
- let message = new Message(channel, data, this.rest.client);
- channel._cacheMessage(message);
- resolve(message);
- this.rest.client.emit(Constants.Events.MESSAGE_CREATE, message);
+ resolve(this.rest.client.actions.MessageCreate.handle(data).m);
})
.catch(reject);
});
@@ -54,8 +51,11 @@ class RESTMethods{
DeleteMessage(channel, message) {
return new Promise((resolve, reject) => {
this.rest.makeRequest('del', Constants.Endpoints.CHANNEL_MESSAGE(channel.id, message.id), true)
- .then(() => {
- resolve(message);
+ .then(data => {
+ resolve(this.rest.client.actions.MessageDelete.handle({
+ id: message.id,
+ channel_id: message.channel.id,
+ }).m);
})
.catch(reject);
});
diff --git a/src/client/websocket/packets/handlers/MessageCreate.js b/src/client/websocket/packets/handlers/MessageCreate.js
index d701d0a97..76241e37e 100644
--- a/src/client/websocket/packets/handlers/MessageCreate.js
+++ b/src/client/websocket/packets/handlers/MessageCreate.js
@@ -16,14 +16,12 @@ class MessageCreateHandler extends AbstractHandler {
handle(packet) {
let data = packet.d;
let client = this.packetManager.client;
- let channel = client.store.get('channels', data.channel_id);
- if (channel) {
- let message = new Message(channel, data, client);
- channel._cacheMessage(message);
- client.emit(Constants.Events.MESSAGE_CREATE, message);
+ let response = client.actions.MessageCreate.handle(data);
+
+ if (response.m) {
+ client.emit(Constants.Events.MESSAGE_CREATE, response.m);
}
-
}
};
diff --git a/src/client/websocket/packets/handlers/MessageDelete.js b/src/client/websocket/packets/handlers/MessageDelete.js
index 43944fcbc..c3457f920 100644
--- a/src/client/websocket/packets/handlers/MessageDelete.js
+++ b/src/client/websocket/packets/handlers/MessageDelete.js
@@ -16,15 +16,12 @@ class MessageDeleteHandler extends AbstractHandler {
handle(packet) {
let data = packet.d;
let client = this.packetManager.client;
- let channel = client.store.get('channels', data.channel_id);
- if (channel) {
- let message = channel.store.get('messages', data.id);
- if (message) {
- channel.store.remove('messages', message.id);
- client.emit(Constants.Events.MESSAGE_DELETE, message);
- }
- }
+ let response = client.actions.MessageDelete.handle(data);
+
+ if (response.m) {
+ client.emit(Constants.Events.MESSAGE_DELETE, response.m);
+ }
}
};
diff --git a/src/structures/TextChannel.js b/src/structures/TextChannel.js
index a93c831be..73986118c 100644
--- a/src/structures/TextChannel.js
+++ b/src/structures/TextChannel.js
@@ -23,7 +23,7 @@ class TextChannel extends ServerChannel {
this.store.remove(storeKeys[0]);
}
- this.store.add('messages', message);
+ return this.store.add('messages', message);
}
}
diff --git a/src/util/Constants.js b/src/util/Constants.js
index 43ad1819c..54df21ad5 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -14,6 +14,7 @@ const DefaultOptions = exports.DefaultOptions = {
},
protocol_version: 4,
max_message_cache: 200,
+ rest_ws_bridge_timeout: 5000,
};
const Status = exports.Status = {
diff --git a/test/random.js b/test/random.js
index 52e1f57d4..f38301d9b 100644
--- a/test/random.js
+++ b/test/random.js
@@ -71,7 +71,7 @@ client.on('typingStop.', (channel, user, data) => {
client.on('message', message => {
if (message.author.username === 'hydrabolt') {
message.channel.sendMessage('test').then(msg => {
- msg.delete();
+ msg.delete().catch(console.log);
});
}
});
From 618d8bb95786cbbbd19bbdab327bebb46f3d490f Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sun, 24 Apr 2016 16:41:23 +0100
Subject: [PATCH 024/324] Simplified client.rest.methods.DeleteMessage, now
only takes a message instead of a channel and a message.
---
src/client/rest/RESTMethods.js | 4 ++--
src/structures/Message.js | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index 6f8c1e6ea..9d2093fa9 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -48,9 +48,9 @@ class RESTMethods{
});
}
- DeleteMessage(channel, message) {
+ DeleteMessage(message) {
return new Promise((resolve, reject) => {
- this.rest.makeRequest('del', Constants.Endpoints.CHANNEL_MESSAGE(channel.id, message.id), true)
+ this.rest.makeRequest('del', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true)
.then(data => {
resolve(this.rest.client.actions.MessageDelete.handle({
id: message.id,
diff --git a/src/structures/Message.js b/src/structures/Message.js
index 6e501ede2..826ef049e 100644
--- a/src/structures/Message.js
+++ b/src/structures/Message.js
@@ -73,7 +73,7 @@ class Message {
}
delete() {
- return this.client.rest.methods.DeleteMessage(this.channel, this);
+ return this.client.rest.methods.DeleteMessage(this);
}
}
From e9d7dfaee317065ca3e92c63b7902b3e724f9982 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sun, 24 Apr 2016 17:30:58 +0100
Subject: [PATCH 025/324] Added message.edit(content)
---
TODO.md | 2 +-
src/client/actions/ActionsManager.js | 1 +
src/client/actions/MessageUpdate.js | 38 +++++++++++++++++++
src/client/rest/RESTMethods.js | 12 ++++++
.../packets/handlers/MessageUpdate.js | 12 ++----
src/structures/Message.js | 31 +++++++++++++++
test/random.js | 2 +-
7 files changed, 88 insertions(+), 10 deletions(-)
create mode 100644 src/client/actions/MessageUpdate.js
diff --git a/TODO.md b/TODO.md
index 090d3ebe0..e11806d5d 100644
--- a/TODO.md
+++ b/TODO.md
@@ -4,7 +4,7 @@
- [ ] sending files
- [ ] updating user details
- [x] deleting messages
-- [ ] updating messages
+- [x] updating messages
- [ ] leaving guilds
- [ ] deleting guilds
- [ ] _joining guilds_
diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js
index aef572bc4..0bfc0cc47 100644
--- a/src/client/actions/ActionsManager.js
+++ b/src/client/actions/ActionsManager.js
@@ -8,6 +8,7 @@ class ActionsManager {
this.register('MessageCreate');
this.register('MessageDelete');
+ this.register('MessageUpdate');
}
register(name) {
diff --git a/src/client/actions/MessageUpdate.js b/src/client/actions/MessageUpdate.js
new file mode 100644
index 000000000..13b414fe4
--- /dev/null
+++ b/src/client/actions/MessageUpdate.js
@@ -0,0 +1,38 @@
+'use strict';
+
+const Action = require('./Action');
+const Constants = require('../../util/Constants');
+const CloneObject = require('../../util/CloneObject');
+const Message = require('../../structures/Message');
+
+class MessageUpdateAction extends Action {
+
+ constructor(client) {
+ super(client);
+ }
+
+ handle(data) {
+
+ let client = this.client;
+ let channel = client.store.get('channels', data.channel_id);
+
+ if (channel) {
+ let message = channel.store.get('messages', data.id);
+ if (message && !message.equals(data, true)) {
+ let oldMessage = CloneObject(message);
+ message.patch(data);
+ return {
+ old: oldMessage,
+ updated: message,
+ };
+ }
+ }
+
+ return {
+ old: null,
+ updated: null,
+ };
+ }
+};
+
+module.exports = MessageUpdateAction;
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index 9d2093fa9..827861073 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -60,6 +60,18 @@ class RESTMethods{
.catch(reject);
});
}
+
+ UpdateMessage(message, content) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true, {
+ content,
+ })
+ .then(data => {
+ resolve(this.rest.client.actions.MessageUpdate.handle(data).updated);
+ })
+ .catch(reject);
+ });
+ }
}
module.exports = RESTMethods;
diff --git a/src/client/websocket/packets/handlers/MessageUpdate.js b/src/client/websocket/packets/handlers/MessageUpdate.js
index e6daf2bbc..cf3232249 100644
--- a/src/client/websocket/packets/handlers/MessageUpdate.js
+++ b/src/client/websocket/packets/handlers/MessageUpdate.js
@@ -17,15 +17,11 @@ class MessageUpdateHandler extends AbstractHandler {
handle(packet) {
let data = packet.d;
let client = this.packetManager.client;
- let channel = client.store.get('channels', data.channel_id);
- if (channel) {
- let message = channel.store.get('messages', data.id);
- if (message) {
- let oldMessage = CloneObject(message);
- message.patch(data);
- client.emit(Constants.Events.MESSAGE_UPDATE, oldMessage, message);
- }
+ let response = client.actions.MessageUpdate.handle(data);
+
+ if (response.old) {
+ client.emit(Constants.Events.MESSAGE_UPDATE, response.old, response.updated);
}
}
diff --git a/src/structures/Message.js b/src/structures/Message.js
index 826ef049e..d5118ca70 100644
--- a/src/structures/Message.js
+++ b/src/structures/Message.js
@@ -72,9 +72,40 @@ class Message {
this.id = data.id;
}
+ equals(message, rawData) {
+
+ let embedUpdate = !message.author && !message.attachments;
+
+ if (embedUpdate) {
+ let base = this.id === message.id &&
+ this.embeds.length === message.embeds.length;
+ return base;
+ } else {
+ let base = 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 (base && rawData) {
+ base = this.mentionEveryone === message.mentionEveryone &&
+ this.timestamp.getTime() === new Date(data.timestamp).getTime() &&
+ this.editedTimestamp === new Date(data.edited_timestamp).getTime();
+ }
+
+ return base;
+ }
+ }
+
delete() {
return this.client.rest.methods.DeleteMessage(this);
}
+
+ edit(content) {
+ return this.client.rest.methods.UpdateMessage(this, content);
+ }
}
module.exports = Message;
diff --git a/test/random.js b/test/random.js
index f38301d9b..915185a7e 100644
--- a/test/random.js
+++ b/test/random.js
@@ -71,7 +71,7 @@ client.on('typingStop.', (channel, user, data) => {
client.on('message', message => {
if (message.author.username === 'hydrabolt') {
message.channel.sendMessage('test').then(msg => {
- msg.delete().catch(console.log);
+ msg.edit('woah!');
});
}
});
From 2d3116d505b0e6ee6ed958eff29704de07e81005 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Tue, 26 Apr 2016 17:44:42 +0100
Subject: [PATCH 026/324] Added guild.createChannel(name, type)
---
src/client/actions/ActionsManager.js | 1 +
src/client/actions/ChannelCreate.js | 23 +++++++++++++++++++
src/client/rest/RESTMethods.js | 13 +++++++++++
.../packets/handlers/ChannelCreate.js | 6 ++++-
src/structures/Guild.js | 4 ++++
test/random.js | 10 ++++----
6 files changed, 52 insertions(+), 5 deletions(-)
create mode 100644 src/client/actions/ChannelCreate.js
diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js
index 0bfc0cc47..d43e82163 100644
--- a/src/client/actions/ActionsManager.js
+++ b/src/client/actions/ActionsManager.js
@@ -9,6 +9,7 @@ class ActionsManager {
this.register('MessageCreate');
this.register('MessageDelete');
this.register('MessageUpdate');
+ this.register('ChannelCreate');
}
register(name) {
diff --git a/src/client/actions/ChannelCreate.js b/src/client/actions/ChannelCreate.js
new file mode 100644
index 000000000..53c1d4325
--- /dev/null
+++ b/src/client/actions/ChannelCreate.js
@@ -0,0 +1,23 @@
+'use strict';
+
+const Action = require('./Action');
+const Constants = require('../../util/Constants');
+const Message = require('../../structures/Message');
+
+class ChannelCreateAction extends Action {
+
+ constructor(client) {
+ super(client);
+ }
+
+ handle(data) {
+ let client = this.client;
+ let channel = client.store.NewChannel(data);
+
+ return {
+ channel,
+ };
+ }
+};
+
+module.exports = ChannelCreateAction;
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index 827861073..8bbb6e579 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -72,6 +72,19 @@ class RESTMethods{
.catch(reject);
});
}
+
+ CreateChannel(guild, channelName, channelType) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('post', Constants.Endpoints.GUILD_CHANNELS(guild.id), true, {
+ name: channelName,
+ type: channelType,
+ })
+ .then(data => {
+ resolve(this.rest.client.actions.ChannelCreate.handle(data).channel);
+ })
+ .catch(reject);
+ });
+ }
}
module.exports = RESTMethods;
diff --git a/src/client/websocket/packets/handlers/ChannelCreate.js b/src/client/websocket/packets/handlers/ChannelCreate.js
index d938be358..100b02785 100644
--- a/src/client/websocket/packets/handlers/ChannelCreate.js
+++ b/src/client/websocket/packets/handlers/ChannelCreate.js
@@ -19,7 +19,11 @@ class ChannelCreateHandler extends AbstractHandler {
let data = packet.d;
let client = this.packetManager.client;
- let channel = client.store.NewChannel(data);
+ let response = client.actions.ChannelCreate.handle(data);
+
+ if (response.channel) {
+ client.emit(Constants.Events.CHANNEL_CREATE, response.channel);
+ }
}
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index 766cc6955..566f3be0b 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -131,6 +131,10 @@ class Guild {
}
}
+ createChannel(name, type) {
+ return this.client.rest.methods.CreateChannel(this, name, type);
+ }
+
get channels() { return this.store.getAsArray('channels'); }
get $channels() { return this.store.data.channels; }
diff --git a/test/random.js b/test/random.js
index 915185a7e..8d6d8a859 100644
--- a/test/random.js
+++ b/test/random.js
@@ -20,7 +20,7 @@ client.on('guildUpdate', (old, guild) => {
console.log(old.name, guild.name);
});
client.on('channelCreate', channel => {
- console.log(channel);
+ // console.log(channel);
});
client.on('channelDelete', channel => {
console.log(channel);
@@ -70,9 +70,11 @@ client.on('typingStop.', (channel, user, data) => {
client.on('message', message => {
if (message.author.username === 'hydrabolt') {
- message.channel.sendMessage('test').then(msg => {
- msg.edit('woah!');
- });
+ if (message.content === 'makechann') {
+ if (message.channel.guild) {
+ message.channel.guild.createChannel('hi', 'text').then(console.log);
+ }
+ }
}
});
From b436fac5c45fda59d4755f447f7bed9b980ae11a Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Tue, 26 Apr 2016 17:46:34 +0100
Subject: [PATCH 027/324] Fix presence update bug (#297)
---
src/client/websocket/packets/handlers/PresenceUpdate.js | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/client/websocket/packets/handlers/PresenceUpdate.js b/src/client/websocket/packets/handlers/PresenceUpdate.js
index c472a413c..889017bce 100644
--- a/src/client/websocket/packets/handlers/PresenceUpdate.js
+++ b/src/client/websocket/packets/handlers/PresenceUpdate.js
@@ -48,7 +48,9 @@ class PresenceUpdateHandler extends AbstractHandler {
data.user.username = data.user.username || user.username;
data.user.id = data.user.id || user.id;
data.user.discriminator = data.user.discriminator || user.discriminator;
- data.user.avatar = data.user.avatar || user.avatar;
+
+ // comment out avatar patching as it causes bugs (see #297)
+ // data.user.avatar = data.user.avatar || user.avatar;
data.user.status = data.status || user.status;
data.user.game = data.game;
From 2341c8363839aefd49798f95c0dffcb18ad33fa7 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Wed, 27 Apr 2016 16:25:57 +0100
Subject: [PATCH 028/324] Added channel.delete()
---
src/client/actions/ActionsManager.js | 1 +
src/client/actions/ChannelDelete.js | 27 +++++++++++++++++++
src/client/rest/RESTMethods.js | 11 ++++++++
.../packets/handlers/ChannelDelete.js | 6 ++---
src/structures/Channel.js | 4 +++
src/structures/datastore/ClientDataStore.js | 4 ---
test/random.js | 6 ++++-
7 files changed, 51 insertions(+), 8 deletions(-)
create mode 100644 src/client/actions/ChannelDelete.js
diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js
index d43e82163..eaad74eb0 100644
--- a/src/client/actions/ActionsManager.js
+++ b/src/client/actions/ActionsManager.js
@@ -10,6 +10,7 @@ class ActionsManager {
this.register('MessageDelete');
this.register('MessageUpdate');
this.register('ChannelCreate');
+ this.register('ChannelDelete');
}
register(name) {
diff --git a/src/client/actions/ChannelDelete.js b/src/client/actions/ChannelDelete.js
new file mode 100644
index 000000000..2c07e0019
--- /dev/null
+++ b/src/client/actions/ChannelDelete.js
@@ -0,0 +1,27 @@
+'use strict';
+
+const Action = require('./Action');
+const Constants = require('../../util/Constants');
+const Message = require('../../structures/Message');
+
+class ChannelDeleteAction extends Action {
+
+ constructor(client) {
+ super(client);
+ }
+
+ handle(data) {
+ let client = this.client;
+ let channel = client.store.get('channels', data.id);
+
+ if (channel) {
+ client.store.KillChannel(channel);
+ }
+
+ return {
+ channel,
+ };
+ }
+};
+
+module.exports = ChannelDeleteAction;
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index 8bbb6e579..20e3094bb 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -85,6 +85,17 @@ class RESTMethods{
.catch(reject);
});
}
+
+ DeleteChannel(channel) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.CHANNEL(channel.id), true)
+ .then(data => {
+ data.id = channel.id;
+ resolve(this.rest.client.actions.ChannelDelete.handle(data).channel);
+ })
+ .catch(reject);
+ });
+ }
}
module.exports = RESTMethods;
diff --git a/src/client/websocket/packets/handlers/ChannelDelete.js b/src/client/websocket/packets/handlers/ChannelDelete.js
index e94d052a0..8a171dc43 100644
--- a/src/client/websocket/packets/handlers/ChannelDelete.js
+++ b/src/client/websocket/packets/handlers/ChannelDelete.js
@@ -19,10 +19,10 @@ class ChannelDeleteHandler extends AbstractHandler {
let data = packet.d;
let client = this.packetManager.client;
- let channel = client.store.get('channels', data.id);
+ let response = client.actions.ChannelCreate.handle(data);
- if (channel) {
- client.store.KillChannel(channel);
+ if (response.channel) {
+ client.emit(Constants.Events.CHANNEL_DELETE, response.channel);
}
}
diff --git a/src/structures/Channel.js b/src/structures/Channel.js
index 8dc22316f..d6c3a9822 100644
--- a/src/structures/Channel.js
+++ b/src/structures/Channel.js
@@ -17,6 +17,10 @@ class Channel {
setup(data) {
this.id = data.id;
}
+
+ delete() {
+ return this.client.rest.methods.DeleteChannel(this);
+ }
}
module.exports = Channel;
diff --git a/src/structures/datastore/ClientDataStore.js b/src/structures/datastore/ClientDataStore.js
index 8cae0c97e..d74681891 100644
--- a/src/structures/datastore/ClientDataStore.js
+++ b/src/structures/datastore/ClientDataStore.js
@@ -87,10 +87,6 @@ class ClientDataStore extends AbstractDataStore{
if (channel instanceof ServerChannel) {
channel.guild.store.remove('channels', channel);
}
-
- if (already && this.pastReady) {
- this.client.emit(Constants.Events.CHANNEL_DELETE, channel);
- }
}
UpdateGuild(currentGuild, newData) {
diff --git a/test/random.js b/test/random.js
index 8d6d8a859..b8778a521 100644
--- a/test/random.js
+++ b/test/random.js
@@ -23,7 +23,7 @@ client.on('channelCreate', channel => {
// console.log(channel);
});
client.on('channelDelete', channel => {
- console.log(channel);
+ console.log('channDel', channel);
});
client.on('channelUpdate', (old, chan) => {
@@ -75,6 +75,10 @@ client.on('message', message => {
message.channel.guild.createChannel('hi', 'text').then(console.log);
}
}
+
+ if (message.content === 'delchann') {
+ message.channel.delete();
+ }
}
});
From 90cf78775970a74aa76febf0bc97caaa29e0082b Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sat, 30 Apr 2016 18:22:09 +0100
Subject: [PATCH 029/324] I think I got ChannelUpdate working??
---
src/client/actions/ActionsManager.js | 1 +
src/client/actions/ChannelUpdate.js | 39 ++++++++++++
src/client/actions/MessageUpdate.js | 6 ++
src/client/rest/RESTMethods.js | 15 +++++
.../packets/handlers/ChannelUpdate.js | 7 +--
.../packets/handlers/MessageUpdate.js | 4 --
src/structures/ServerChannel.js | 61 ++++++++++++++++++-
src/structures/datastore/ClientDataStore.js | 1 -
test/random.js | 8 +++
9 files changed, 130 insertions(+), 12 deletions(-)
create mode 100644 src/client/actions/ChannelUpdate.js
diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js
index eaad74eb0..8e4032eed 100644
--- a/src/client/actions/ActionsManager.js
+++ b/src/client/actions/ActionsManager.js
@@ -11,6 +11,7 @@ class ActionsManager {
this.register('MessageUpdate');
this.register('ChannelCreate');
this.register('ChannelDelete');
+ this.register('ChannelUpdate');
}
register(name) {
diff --git a/src/client/actions/ChannelUpdate.js b/src/client/actions/ChannelUpdate.js
new file mode 100644
index 000000000..78d02245e
--- /dev/null
+++ b/src/client/actions/ChannelUpdate.js
@@ -0,0 +1,39 @@
+'use strict';
+
+const Action = require('./Action');
+const Constants = require('../../util/Constants');
+const CloneObject = require('../../util/CloneObject');
+const Message = require('../../structures/Message');
+
+class ChannelUpdateAction extends Action {
+
+ constructor(client) {
+ super(client);
+ }
+
+ handle(data) {
+
+ let client = this.client;
+ let channel = client.store.get('channels', data.id);
+
+ if (channel) {
+ let oldChannel = CloneObject(channel);
+ channel.setup(data);
+ if (!oldChannel.equals(data)) {
+ client.emit(Constants.Events.CHANNEL_UPDATE, oldChannel, channel);
+ }
+
+ return {
+ old: oldChannel,
+ updated: channel,
+ };
+ }
+
+ return {
+ old: null,
+ updated: null,
+ };
+ }
+};
+
+module.exports = ChannelUpdateAction;
diff --git a/src/client/actions/MessageUpdate.js b/src/client/actions/MessageUpdate.js
index 13b414fe4..67c1d79f6 100644
--- a/src/client/actions/MessageUpdate.js
+++ b/src/client/actions/MessageUpdate.js
@@ -25,7 +25,13 @@ class MessageUpdateAction extends Action {
old: oldMessage,
updated: message,
};
+ client.emit(Constants.Events.MESSAGE_UPDATE, oldMessage, message);
}
+
+ return {
+ old: message,
+ updated: message,
+ };
}
return {
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index 20e3094bb..7311aa55a 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -96,6 +96,21 @@ class RESTMethods{
.catch(reject);
});
}
+
+ UpdateChannel(channel, data) {
+ return new Promise((resolve, reject) => {
+ data.name = (data.name || channel.name).trim();
+ data.topic = data.topic || channel.topic;
+ data.position = data.position || channel.position;
+ data.bitrate = data.bitrate || channel.bitrate;
+
+ this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL(channel.id), true, data)
+ .then(data => {
+ resolve(this.rest.client.actions.ChannelUpdate.handle(data).updated);
+ })
+ .catch(reject);
+ });
+ }
}
module.exports = RESTMethods;
diff --git a/src/client/websocket/packets/handlers/ChannelUpdate.js b/src/client/websocket/packets/handlers/ChannelUpdate.js
index d44a15855..699cfd432 100644
--- a/src/client/websocket/packets/handlers/ChannelUpdate.js
+++ b/src/client/websocket/packets/handlers/ChannelUpdate.js
@@ -20,12 +20,7 @@ class ChannelUpdateHandler extends AbstractHandler {
let data = packet.d;
let client = this.packetManager.client;
- let channel = client.store.get('channels', data.id);
-
- if (channel) {
- client.store.UpdateChannel(channel, data);
- }
-
+ client.actions.ChannelUpdate.handle(data);
}
};
diff --git a/src/client/websocket/packets/handlers/MessageUpdate.js b/src/client/websocket/packets/handlers/MessageUpdate.js
index cf3232249..69ac2aa3a 100644
--- a/src/client/websocket/packets/handlers/MessageUpdate.js
+++ b/src/client/websocket/packets/handlers/MessageUpdate.js
@@ -20,10 +20,6 @@ class MessageUpdateHandler extends AbstractHandler {
let response = client.actions.MessageUpdate.handle(data);
- if (response.old) {
- client.emit(Constants.Events.MESSAGE_UPDATE, response.old, response.updated);
- }
-
}
};
diff --git a/src/structures/ServerChannel.js b/src/structures/ServerChannel.js
index ebd7ea8b6..d5133a4a6 100644
--- a/src/structures/ServerChannel.js
+++ b/src/structures/ServerChannel.js
@@ -5,6 +5,19 @@ const PermissionOverwrites = require('./PermissionOverwrites');
const EvaluatedPermissions = require('./EvaluatedPermissions');
const Constants = require('../util/Constants');
+function arraysEqual(a, b) {
+ if (a === b) return true;
+
+ for (let itemInd in a) {
+ let ind = b.indexOf(item);
+ if (ind) {
+ b.splice(ind, 1);
+ }
+ }
+
+ return b.length === 0;
+}
+
class ServerChannel extends Channel{
constructor(guild, data) {
super(guild.client, data, guild);
@@ -18,14 +31,40 @@ class ServerChannel extends Channel{
this.name = data.name;
this.lastMessageID = data.last_message_id;
this.ow = data.permission_overwrites;
+ this.permissionOverwrites = [];
if (data.permission_overwrites) {
- this.permissionOverwrites = [];
for (let overwrite of data.permission_overwrites) {
this.permissionOverwrites.push(new PermissionOverwrites(this, overwrite));
}
}
}
+ equals(other) {
+ let base = (
+ this.type === other.type &&
+ this.topic === other.topic &&
+ this.position === other.position &&
+ this.name === other.name &&
+ this.id === other.id
+ );
+
+ if (base) {
+ if (other.permission_overwrites && other.permission_overwrites.length === this.permissionOverwrites.length) {
+ let thisIDSet = this.permissionOverwrites.map(overwrite => overwrite.id);
+ let otherIDSet = other.permission_overwrites.map(overwrite => overwrite.id);
+ if (arraysEqual(thisIDSet, otherIDSet)) {
+ base = true;
+ } else {
+ base = false;
+ }
+ } else {
+ base = false;
+ }
+ }
+
+ return base;
+ }
+
permissionsFor(member) {
member = this.client.resolver.ResolveGuildMember(this.guild, member);
if (member) {
@@ -82,6 +121,26 @@ class ServerChannel extends Channel{
return [];
}
+ edit(data) {
+ return this.client.rest.methods.UpdateChannel(this, data);
+ }
+
+ setName(name) {
+ return this.client.rest.methods.UpdateChannel(this, { name, });
+ }
+
+ setPosition(position) {
+ return this.rest.client.rest.methods.UpdateChannel(this, { position, });
+ }
+
+ setTopic(topic) {
+ return this.rest.client.rest.methods.UpdateChannel(this, { topic, });
+ }
+
+ setBitrate() {
+ return this.rest.client.rest.methods.UpdateChannel(this, { bitrate, });
+ }
+
toString() {
return this.name;
}
diff --git a/src/structures/datastore/ClientDataStore.js b/src/structures/datastore/ClientDataStore.js
index d74681891..15f359d6a 100644
--- a/src/structures/datastore/ClientDataStore.js
+++ b/src/structures/datastore/ClientDataStore.js
@@ -100,7 +100,6 @@ class ClientDataStore extends AbstractDataStore{
UpdateChannel(currentChannel, newData) {
let oldChannel = CloneObject(currentChannel);
currentChannel.setup(newData);
- this.client.emit(Constants.Events.CHANNEL_UPDATE, oldChannel, currentChannel);
}
}
diff --git a/test/random.js b/test/random.js
index b8778a521..03c244535 100644
--- a/test/random.js
+++ b/test/random.js
@@ -79,9 +79,17 @@ client.on('message', message => {
if (message.content === 'delchann') {
message.channel.delete();
}
+
+ if (message.content.startsWith('setname')) {
+ message.channel.setName(message.content.substr(8)).then(chanLoop).catch(console.log);
+ }
}
});
+function chanLoop(channel) {
+ channel.setName(channel.name + 'a').then(chanLoop).catch(console.log);
+}
+
client.on('messageDelete', message => {
console.log('Message deleted by', message.author.username);
});
From 3a0426482e0e7043906c633eb9896bdafa9ccc1e Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sat, 30 Apr 2016 18:27:34 +0100
Subject: [PATCH 030/324] update TODO list
---
TODO.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/TODO.md b/TODO.md
index e11806d5d..19bac313b 100644
--- a/TODO.md
+++ b/TODO.md
@@ -8,9 +8,9 @@
- [ ] leaving guilds
- [ ] deleting guilds
- [ ] _joining guilds_
-- [ ] creating channels
-- [ ] updating channels
-- [ ] deleting channels
+- [x] creating channels
+- [x] updating channels
+- [x] deleting channels
- [ ] making roles
- [ ] deleting roles
- [ ] updating roles
From f95c588d875c4b5fab0ed9831383205941c32aca Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sun, 1 May 2016 14:51:46 +0100
Subject: [PATCH 031/324] Added Guild Deletion
---
TODO.md | 4 +-
src/client/actions/ActionsManager.js | 1 +
src/client/actions/ChannelDelete.js | 17 ++++++
src/client/actions/GuildDelete.js | 54 +++++++++++++++++++
src/client/actions/MessageDelete.js | 19 +++++--
src/client/rest/RESTMethods.js | 21 ++++++++
.../packets/handlers/ChannelDelete.js | 2 +-
.../websocket/packets/handlers/GuildDelete.js | 17 ++----
src/structures/Guild.js | 8 +++
src/structures/ServerChannel.js | 1 +
src/structures/datastore/ClientDataStore.js | 1 -
test/random.js | 10 ++--
12 files changed, 129 insertions(+), 26 deletions(-)
create mode 100644 src/client/actions/GuildDelete.js
diff --git a/TODO.md b/TODO.md
index 19bac313b..0f2f60e58 100644
--- a/TODO.md
+++ b/TODO.md
@@ -5,8 +5,8 @@
- [ ] updating user details
- [x] deleting messages
- [x] updating messages
-- [ ] leaving guilds
-- [ ] deleting guilds
+- [x] leaving guilds
+- [x] deleting guilds
- [ ] _joining guilds_
- [x] creating channels
- [x] updating channels
diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js
index 8e4032eed..ed711b5fa 100644
--- a/src/client/actions/ActionsManager.js
+++ b/src/client/actions/ActionsManager.js
@@ -12,6 +12,7 @@ class ActionsManager {
this.register('ChannelCreate');
this.register('ChannelDelete');
this.register('ChannelUpdate');
+ this.register('GuildDelete');
}
register(name) {
diff --git a/src/client/actions/ChannelDelete.js b/src/client/actions/ChannelDelete.js
index 2c07e0019..4f021d0ed 100644
--- a/src/client/actions/ChannelDelete.js
+++ b/src/client/actions/ChannelDelete.js
@@ -8,6 +8,8 @@ class ChannelDeleteAction extends Action {
constructor(client) {
super(client);
+ this.timeouts = [];
+ this.deleted = {};
}
handle(data) {
@@ -15,13 +17,28 @@ class ChannelDeleteAction extends Action {
let channel = client.store.get('channels', data.id);
if (channel) {
+
client.store.KillChannel(channel);
+ this.deleted[channel.id] = channel;
+ this.scheduleForDeletion(channel.id);
+
+ } else if (this.deleted[data.id]) {
+
+ channel = this.deleted[data.id];
+
}
return {
channel,
};
}
+
+ scheduleForDeletion(id) {
+ this.timeouts.push(
+ setTimeout(() => delete this.deleted[id],
+ this.client.options.rest_ws_bridge_timeout)
+ );
+ }
};
module.exports = ChannelDeleteAction;
diff --git a/src/client/actions/GuildDelete.js b/src/client/actions/GuildDelete.js
new file mode 100644
index 000000000..271cb7b52
--- /dev/null
+++ b/src/client/actions/GuildDelete.js
@@ -0,0 +1,54 @@
+'use strict';
+
+const Action = require('./Action');
+const Constants = require('../../util/Constants');
+const Message = require('../../structures/Message');
+
+class GuildDeleteAction extends Action {
+
+ constructor(client) {
+ super(client);
+ this.deleted = {};
+ this.timeouts = [];
+ }
+
+ handle(data) {
+
+ let client = this.client;
+ let guild = client.store.get('guilds', data.id);
+
+ if (guild) {
+ if (guild.available && data.unavailable) {
+ // guild is unavailable
+ guild.available = false;
+ client.emit(Constants.Events.GUILD_UNAVAILABLE, guild);
+
+ // stops the GuildDelete packet thinking a guild was actually deleted,
+ // handles emitting of event itself
+ return {
+ guild: null,
+ };
+ } else {
+ // delete guild
+ client.store.remove('guilds', guild);
+ this.deleted[guild.id] = guild;
+ this.scheduleForDeletion(guild.id);
+ }
+ } else if (this.deleted[data.id]) {
+ guild = this.deleted[data.id];
+ }
+
+ return {
+ guild,
+ };
+ }
+
+ scheduleForDeletion(id) {
+ this.timeouts.push(
+ setTimeout(() => delete this.deleted[id],
+ this.client.options.rest_ws_bridge_timeout)
+ );
+ }
+};
+
+module.exports = GuildDeleteAction;
diff --git a/src/client/actions/MessageDelete.js b/src/client/actions/MessageDelete.js
index 9f82f0a15..a8a2f8e04 100644
--- a/src/client/actions/MessageDelete.js
+++ b/src/client/actions/MessageDelete.js
@@ -9,6 +9,7 @@ class MessageDeleteAction extends Action {
constructor(client) {
super(client);
this.timeouts = [];
+ this.deleted = {};
}
handle(data) {
@@ -16,9 +17,17 @@ class MessageDeleteAction extends Action {
let channel = client.store.get('channels', data.channel_id);
if (channel) {
let message = channel.store.get('messages', data.id);
- if (message && !message._deleted) {
- message._deleted = true;
- this.scheduleForDeletion(channel, message.id);
+
+ if (message) {
+
+ channel.store.remove('messages', message.id);
+ this.deleted[channel.id + message.id] = message;
+ this.scheduleForDeletion(channel.id, message.id);
+
+ } else if (this.deleted[channel.id + data.id]) {
+
+ message = this.deleted[channel.id + data.id];
+
}
return {
@@ -31,9 +40,9 @@ class MessageDeleteAction extends Action {
};
}
- scheduleForDeletion(channel, id) {
+ scheduleForDeletion(channelID, messageID) {
this.timeouts.push(
- setTimeout(() => channel.store.remove('messages', id),
+ setTimeout(() => delete this.deleted[channelID + messageID],
this.client.options.rest_ws_bridge_timeout)
);
}
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index 7311aa55a..d175dcf67 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -111,6 +111,27 @@ class RESTMethods{
.catch(reject);
});
}
+
+ LeaveGuild(guild) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.ME_GUILD(guild.id), true)
+ .then(() => {
+ resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild);
+ })
+ .catch(reject);
+ });
+ }
+
+ // untested but probably will work
+ DeleteGuild(guild) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.GUILD(guild.id), true)
+ .then(() => {
+ resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild);
+ })
+ .catch(reject);
+ });
+ }
}
module.exports = RESTMethods;
diff --git a/src/client/websocket/packets/handlers/ChannelDelete.js b/src/client/websocket/packets/handlers/ChannelDelete.js
index 8a171dc43..82a6eed6f 100644
--- a/src/client/websocket/packets/handlers/ChannelDelete.js
+++ b/src/client/websocket/packets/handlers/ChannelDelete.js
@@ -19,7 +19,7 @@ class ChannelDeleteHandler extends AbstractHandler {
let data = packet.d;
let client = this.packetManager.client;
- let response = client.actions.ChannelCreate.handle(data);
+ let response = client.actions.ChannelDelete.handle(data);
if (response.channel) {
client.emit(Constants.Events.CHANNEL_DELETE, response.channel);
diff --git a/src/client/websocket/packets/handlers/GuildDelete.js b/src/client/websocket/packets/handlers/GuildDelete.js
index 350c27b1c..05319a5cb 100644
--- a/src/client/websocket/packets/handlers/GuildDelete.js
+++ b/src/client/websocket/packets/handlers/GuildDelete.js
@@ -18,21 +18,10 @@ class GuildDeleteHandler extends AbstractHandler {
let data = packet.d;
let client = this.packetManager.client;
- let guild = client.store.get('guilds', data.id);
+ let response = client.actions.GuildDelete.handle(data);
- if (guild) {
- if (guild.available && data.unavailable) {
- // guild is unavailable
- guild.available = false;
- client.emit(Constants.Events.GUILD_UNAVAILABLE, guild);
- } else {
- // delete guild
- client.store.KillGuild(guild);
- this.packetManager.ws.checkIfReady();
- }
- } else {
- // it's not there! :(
- client.emit('warn', 'guild deleted but not cached in first place. missed packet?');
+ if (response.guild) {
+ client.emit(Constants.Events.GUILD_DELETE, response.guild);
}
}
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index 566f3be0b..add9d37ed 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -135,6 +135,14 @@ class Guild {
return this.client.rest.methods.CreateChannel(this, name, type);
}
+ leave() {
+ return this.client.rest.methods.LeaveGuild(this);
+ }
+
+ delete() {
+ return this.client.rest.methods.DeleteGuild(this);
+ }
+
get channels() { return this.store.getAsArray('channels'); }
get $channels() { return this.store.data.channels; }
diff --git a/src/structures/ServerChannel.js b/src/structures/ServerChannel.js
index d5133a4a6..f15f1b613 100644
--- a/src/structures/ServerChannel.js
+++ b/src/structures/ServerChannel.js
@@ -9,6 +9,7 @@ function arraysEqual(a, b) {
if (a === b) return true;
for (let itemInd in a) {
+ let item = a[itemInd];
let ind = b.indexOf(item);
if (ind) {
b.splice(ind, 1);
diff --git a/src/structures/datastore/ClientDataStore.js b/src/structures/datastore/ClientDataStore.js
index 15f359d6a..cdcbdc2e3 100644
--- a/src/structures/datastore/ClientDataStore.js
+++ b/src/structures/datastore/ClientDataStore.js
@@ -82,7 +82,6 @@ class ClientDataStore extends AbstractDataStore{
}
KillChannel(channel) {
- let already = this.get('channels', channel.id);
this.remove('channels', channel);
if (channel instanceof ServerChannel) {
channel.guild.store.remove('channels', channel);
diff --git a/test/random.js b/test/random.js
index 03c244535..9f4b6879d 100644
--- a/test/random.js
+++ b/test/random.js
@@ -14,7 +14,7 @@ client.on('guildCreate', (guild) => {
console.log(guild);
});
client.on('guildDelete', (guild) => {
- console.log(guild);
+ console.log('guilddel', guild.name);
});
client.on('guildUpdate', (old, guild) => {
console.log(old.name, guild.name);
@@ -23,7 +23,7 @@ client.on('channelCreate', channel => {
// console.log(channel);
});
client.on('channelDelete', channel => {
- console.log('channDel', channel);
+ console.log('channDel', channel.name);
});
client.on('channelUpdate', (old, chan) => {
@@ -77,12 +77,16 @@ client.on('message', message => {
}
if (message.content === 'delchann') {
- message.channel.delete();
+ message.channel.delete().then(chan => console.log('selfDelChann', chan.name));
}
if (message.content.startsWith('setname')) {
message.channel.setName(message.content.substr(8)).then(chanLoop).catch(console.log);
}
+
+ if (message.content === 'leave') {
+ message.guild.leave().then(guild => console.log('left guild', guild.name)).catch(console.log);
+ }
}
});
From ebfc2169d54dc7722b6fdaed0c8843160fae0abf Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sun, 1 May 2016 21:12:42 +0100
Subject: [PATCH 032/324] Added ClientUser modification support
---
src/client/Client.js | 4 ++
src/client/ClientDataResolver.js | 7 +++
src/client/actions/ActionsManager.js | 1 +
src/client/actions/UserUpdate.js | 44 +++++++++++++++++++
src/client/rest/RESTMethods.js | 22 +++++++++-
.../websocket/packets/handlers/UserUpdate.js | 18 +-------
src/structures/ClientUser.js | 20 +++++++++
src/structures/User.js | 26 ++++++++++-
src/structures/datastore/ClientDataStore.js | 2 +
test/random.js | 18 ++++++++
10 files changed, 143 insertions(+), 19 deletions(-)
create mode 100644 src/client/actions/UserUpdate.js
diff --git a/src/client/Client.js b/src/client/Client.js
index d48f6c2a8..b51ac03e6 100644
--- a/src/client/Client.js
+++ b/src/client/Client.js
@@ -33,6 +33,10 @@ class Client extends EventEmitter{
}
}
+ get user() {
+ return this.store.user;
+ }
+
}
module.exports = Client;
diff --git a/src/client/ClientDataResolver.js b/src/client/ClientDataResolver.js
index 47ee3f9fc..8f8cd6d22 100644
--- a/src/client/ClientDataResolver.js
+++ b/src/client/ClientDataResolver.js
@@ -54,6 +54,13 @@ class ClientDataResolver {
return guild.store.get('members', user.id);
}
+
+ ResolveBase64(data) {
+ if (data instanceof Buffer) {
+ return 'data:image/jpg;base64,' + data.toString('base64');
+ }
+ return data;
+ }
}
module.exports = ClientDataResolver;
diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js
index ed711b5fa..9b1ed9256 100644
--- a/src/client/actions/ActionsManager.js
+++ b/src/client/actions/ActionsManager.js
@@ -13,6 +13,7 @@ class ActionsManager {
this.register('ChannelDelete');
this.register('ChannelUpdate');
this.register('GuildDelete');
+ this.register('UserUpdate');
}
register(name) {
diff --git a/src/client/actions/UserUpdate.js b/src/client/actions/UserUpdate.js
new file mode 100644
index 000000000..ec3a42cb6
--- /dev/null
+++ b/src/client/actions/UserUpdate.js
@@ -0,0 +1,44 @@
+'use strict';
+
+const Action = require('./Action');
+const Constants = require('../../util/Constants');
+const CloneObject = require('../../util/CloneObject');
+const Message = require('../../structures/Message');
+
+class UserUpdateAction extends Action {
+
+ constructor(client) {
+ super(client);
+ }
+
+ handle(data) {
+
+ let client = this.client;
+
+ if (client.store.user) {
+ if (client.store.user.equals(data)) {
+ return {
+ old: client.store.user,
+ updated: client.store.user,
+ };
+ }
+
+ let oldUser = CloneObject(client.store.user);
+ client.store.user.setup(data);
+
+ client.emit(Constants.Events.USER_UPDATE, oldUser, client.store.user);
+
+ return {
+ old: oldUser,
+ updated: client.store.user,
+ };
+ }
+
+ return {
+ old: null,
+ updated: null,
+ };
+ }
+};
+
+module.exports = UserUpdateAction;
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index d175dcf67..2a3a54176 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -12,7 +12,8 @@ class RESTMethods{
LoginEmailPassword(email, password) {
return new Promise((resolve, reject) => {
-
+ this.rest.client.store.email = email;
+ this.rest.client.store.password = password;
this.rest.makeRequest('post', Constants.Endpoints.LOGIN, false, { email, password })
.then(data => {
this.rest.client.manager.connectToWebSocket(data.token, resolve, reject);
@@ -132,6 +133,25 @@ class RESTMethods{
.catch(reject);
});
}
+
+ UpdateCurrentUser(_data) {
+ return new Promise((resolve, reject) => {
+ let user = this.rest.client.store.user;
+ let data = {};
+
+ data.username = _data.username || user.username;
+ data.avatar = this.rest.client.resolver.ResolveBase64(_data.avatar) || user.avatar;
+ if (!user.bot) {
+ data.password = this.rest.client.store.password;
+ data.email = _data.email || this.rest.client.store.email;
+ data.new_password = _data.newPassword;
+ }
+
+ this.rest.makeRequest('patch', Constants.Endpoints.ME, true, data)
+ .then(data => resolve(this.rest.client.actions.UserUpdate.handle(data).updated))
+ .catch(reject);
+ });
+ }
}
module.exports = RESTMethods;
diff --git a/src/client/websocket/packets/handlers/UserUpdate.js b/src/client/websocket/packets/handlers/UserUpdate.js
index d8bc1f7cc..8cefe8fcd 100644
--- a/src/client/websocket/packets/handlers/UserUpdate.js
+++ b/src/client/websocket/packets/handlers/UserUpdate.js
@@ -3,6 +3,7 @@
const AbstractHandler = require('./AbstractHandler');
const Structure = name => require(`../../../../structures/${name}`);
const CloneObject = name => require(`../../../../util/CloneObject`);
+const Constants = require(`../../../../util/Constants`);
const ClientUser = Structure('ClientUser');
const Guild = Structure('Guild');
@@ -18,22 +19,7 @@ class UserUpdateHandler extends AbstractHandler {
let data = packet.d;
let client = this.packetManager.client;
- let user = client.store.user;
-
- if (!user) {
- return;
- }
-
- let oldUser = CloneObject(user);
-
- user.username = data.username || user.username;
- user.id = data.id || user.id;
- user.avatar = data.avatar || user.avatar;
- user.discriminator = data.discriminator || user.discriminator;
- user.email = data.email || user.email;
- user.verified = data.verified || user.verified;
-
- client.emit(Constants.Events.USER_UPDATE, oldUser, user);
+ let response = client.actions.UserUpdate.handle(data);
}
diff --git a/src/structures/ClientUser.js b/src/structures/ClientUser.js
index 19b84d5b8..923c571dd 100644
--- a/src/structures/ClientUser.js
+++ b/src/structures/ClientUser.js
@@ -12,6 +12,26 @@ class ClientUser extends User {
this.verified = data.verified;
this.email = data.email;
}
+
+ setUsername(username) {
+ return this.client.rest.methods.UpdateCurrentUser({ username, });
+ }
+
+ setEmail(email) {
+ return this.client.rest.methods.UpdateCurrentUser({ email, });
+ }
+
+ setPassword(password) {
+ return this.client.rest.methods.UpdateCurrentUser({ password, });
+ }
+
+ setAvatar(avatar) {
+ return this.client.rest.methods.UpdateCurrentUser({ avatar, });
+ }
+
+ edit(data) {
+ return this.client.rest.methods.UpdateCurrentUser(data);
+ }
}
module.exports = ClientUser;
diff --git a/src/structures/User.js b/src/structures/User.js
index 6cae4518b..4d48aed5a 100644
--- a/src/structures/User.js
+++ b/src/structures/User.js
@@ -14,13 +14,35 @@ class User {
this.discriminator = data.discriminator;
this.avatar = data.avatar;
this.bot = Boolean(data.bot);
- this.status = data.status || 'offline';
- this.game = data.game;
+ this.status = data.status || this.status || 'offline';
+ this.game = data.game || this.game;
}
toString() {
return `<@${this.id}>`;
}
+
+ equals(user) {
+ let base = (
+ this.username === user.username &&
+ this.id === user.id &&
+ this.discriminator === user.discriminator &&
+ this.avatar === user.avatar &&
+ this.bot === Boolean(user.bot)
+ );
+
+ if (base) {
+ if (user.status) {
+ base = this.status === user.status;
+ }
+
+ if (user.game) {
+ base = this.game === user.game;
+ }
+ }
+
+ return base;
+ }
}
module.exports = User;
diff --git a/src/structures/datastore/ClientDataStore.js b/src/structures/datastore/ClientDataStore.js
index cdcbdc2e3..a7b39c19d 100644
--- a/src/structures/datastore/ClientDataStore.js
+++ b/src/structures/datastore/ClientDataStore.js
@@ -18,6 +18,8 @@ class ClientDataStore extends AbstractDataStore{
this.token = null;
this.session = null;
this.user = null;
+ this.email = null;
+ this.password = null;
this.register('users');
this.register('guilds');
diff --git a/test/random.js b/test/random.js
index 9f4b6879d..194fe13da 100644
--- a/test/random.js
+++ b/test/random.js
@@ -1,6 +1,7 @@
'use strict';
const Discord = require('../');
+const request = require('superagent');
let client = new Discord.Client();
@@ -84,12 +85,29 @@ client.on('message', message => {
message.channel.setName(message.content.substr(8)).then(chanLoop).catch(console.log);
}
+ if (message.content.startsWith('botname')) {
+ client.user.setUsername(message.content.substr(8)).then(nameLoop).catch(console.log);
+ }
+
+ if (message.content.startsWith('botavatar')) {
+ request
+ .get('url')
+ .end((err, res) => {
+ client.user.setAvatar(res.body).catch(console.log)
+ .then(user => message.channel.sendMessage('Done!'));
+ });
+ }
+
if (message.content === 'leave') {
message.guild.leave().then(guild => console.log('left guild', guild.name)).catch(console.log);
}
}
});
+function nameLoop(user) {
+ user.setUsername(user.username + 'a').then(nameLoop).catch(console.log);
+}
+
function chanLoop(channel) {
channel.setName(channel.name + 'a').then(chanLoop).catch(console.log);
}
From a0418a2551e1df8dba3b84921a707b54efe1cf18 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sun, 1 May 2016 21:14:23 +0100
Subject: [PATCH 033/324] update TODO list whoops
---
TODO.md | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/TODO.md b/TODO.md
index 0f2f60e58..14fbd65ca 100644
--- a/TODO.md
+++ b/TODO.md
@@ -2,7 +2,7 @@
- [x] sending messages
- [x] sending tts messages
- [ ] sending files
-- [ ] updating user details
+- [x] updating user details
- [x] deleting messages
- [x] updating messages
- [x] leaving guilds
@@ -30,4 +30,5 @@
- [ ] updating invites
- [ ] deleting invites
- [ ] getting invites
-- [ ] typing simulation
\ No newline at end of file
+- [ ] typing simulation
+- [ ] guild modification
\ No newline at end of file
From 82ac3d1c444701b10a6f18852b4c12a621a3dcae Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Mon, 2 May 2016 13:07:55 +0100
Subject: [PATCH 034/324] Remove TODO list, now tracked by issue #313
---
TODO.md | 34 ----------------------------------
1 file changed, 34 deletions(-)
delete mode 100644 TODO.md
diff --git a/TODO.md b/TODO.md
deleted file mode 100644
index 14fbd65ca..000000000
--- a/TODO.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# To-do list:
-- [x] sending messages
-- [x] sending tts messages
-- [ ] sending files
-- [x] updating user details
-- [x] deleting messages
-- [x] updating messages
-- [x] leaving guilds
-- [x] deleting guilds
-- [ ] _joining guilds_
-- [x] creating channels
-- [x] updating channels
-- [x] deleting channels
-- [ ] making roles
-- [ ] deleting roles
-- [ ] updating roles
-- [ ] logging out
-- [ ] modifying channel overwrites
-- [ ] fetching guild members
-- [ ] getting channel logs
-- [ ] getting bans
-- [ ] banning members
-- [ ] unbanning members
-- [ ] kicking members
-- [ ] moving voice channel members
-- [ ] muting/deafening voice channel members
-- [ ] voice support
-- [ ] adding members to roles
-- [ ] creating invites
-- [ ] updating invites
-- [ ] deleting invites
-- [ ] getting invites
-- [ ] typing simulation
-- [ ] guild modification
\ No newline at end of file
From ab1737524821d2ad4a2176a7184ffbe1d68ae404 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Tue, 3 May 2016 16:42:38 +0100
Subject: [PATCH 035/324] Added GuildUpdate handling, and setting guilds
details
---
src/client/ClientDataResolver.js | 24 ++++++
src/client/actions/ActionsManager.js | 1 +
src/client/actions/GuildUpdate.js | 42 ++++++++++
src/client/rest/RESTMethods.js | 47 +++++++++++
.../websocket/packets/handlers/GuildUpdate.js | 6 +-
src/structures/Guild.js | 82 ++++++++++++++++++-
src/structures/ServerChannel.js | 3 +-
test/random.js | 21 ++++-
8 files changed, 215 insertions(+), 11 deletions(-)
create mode 100644 src/client/actions/GuildUpdate.js
diff --git a/src/client/ClientDataResolver.js b/src/client/ClientDataResolver.js
index 8f8cd6d22..fc65010cf 100644
--- a/src/client/ClientDataResolver.js
+++ b/src/client/ClientDataResolver.js
@@ -5,6 +5,7 @@ const Structure = name => require(`../structures/${name}`);
const User = Structure('User');
const Message = Structure('Message');
const Guild = Structure('Guild');
+const Channel = Structure('Channel');
const ServerChannel = Structure('ServerChannel');
const TextChannel = Structure('TextChannel');
const VoiceChannel = Structure('VoiceChannel');
@@ -59,8 +60,31 @@ class ClientDataResolver {
if (data instanceof Buffer) {
return 'data:image/jpg;base64,' + data.toString('base64');
}
+
return data;
}
+
+ ResolveChannel(channel) {
+ if (channel instanceof Channel) {
+ return channel;
+ }
+
+ if ($string(channel)) {
+ return this.client.store.get('channels', channel);
+ }
+ }
+
+ ResolveString(data) {
+ if (data instanceof String) {
+ return data;
+ }
+
+ if (data instanceof Array) {
+ return data.join('\n');
+ }
+
+ return String(data);
+ }
}
module.exports = ClientDataResolver;
diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js
index 9b1ed9256..41d5be9de 100644
--- a/src/client/actions/ActionsManager.js
+++ b/src/client/actions/ActionsManager.js
@@ -13,6 +13,7 @@ class ActionsManager {
this.register('ChannelDelete');
this.register('ChannelUpdate');
this.register('GuildDelete');
+ this.register('GuildUpdate');
this.register('UserUpdate');
}
diff --git a/src/client/actions/GuildUpdate.js b/src/client/actions/GuildUpdate.js
new file mode 100644
index 000000000..96ab7565e
--- /dev/null
+++ b/src/client/actions/GuildUpdate.js
@@ -0,0 +1,42 @@
+'use strict';
+
+const Action = require('./Action');
+const Constants = require('../../util/Constants');
+const CloneObject = require('../../util/CloneObject');
+const Message = require('../../structures/Message');
+
+class GuildUpdateAction extends Action {
+
+ constructor(client) {
+ super(client);
+ this.deleted = {};
+ this.timeouts = [];
+ }
+
+ handle(data) {
+
+ let client = this.client;
+ let guild = client.store.get('guilds', data.id);
+
+ if (guild) {
+ let oldGuild = CloneObject(guild);
+ guild.setup(data);
+
+ if (!oldGuild.equals(data)) {
+ client.emit(Constants.Events.GUILD_UPDATE, oldGuild, guild);
+ }
+
+ return {
+ old: oldGuild,
+ updated: guild,
+ };
+ }
+
+ return {
+ old: null,
+ updated: null,
+ };
+ }
+};
+
+module.exports = GuildUpdateAction;
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index 2a3a54176..810b3df58 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -152,6 +152,53 @@ class RESTMethods{
.catch(reject);
});
}
+
+ UpdateGuild(guild, _data) {
+ return new Promise((resolve, reject) => {
+ /*
+ can contain:
+ name, region, verificationLevel, afkChannel, afkTimeout, icon, owner, splash
+ */
+
+ let data = {};
+
+ if (_data.name) {
+ data.name = _data.name;
+ }
+
+ if (_data.region) {
+ data.region = _data.region;
+ }
+
+ if (_data.verificationLevel) {
+ data.verification_level = Number(_data.verificationLevel);
+ }
+
+ if (_data.afkChannel) {
+ data.afk_channel_id = this.rest.client.resolver.ResolveChannel(_data.afkChannel).id;
+ }
+
+ if (_data.afkTimeout) {
+ data.afk_timeout = Number(_data.afkTimeout);
+ }
+
+ if (_data.icon) {
+ data.icon = this.rest.client.resolver.ResolveBase64(_data.icon);
+ }
+
+ if (_data.owner) {
+ data.owner_id = this.rest.client.resolver.ResolveUser(_data.owner).id;
+ }
+
+ if (_data.splash) {
+ data.splash = this.rest.client.resolver.ResolveBase64(_data.splash);
+ }
+
+ this.rest.makeRequest('patch', Constants.Endpoints.GUILD(guild.id), true, data)
+ .then(data => resolve(this.rest.client.actions.GuildUpdate.handle(data).updated))
+ .catch(reject);
+ });
+ }
}
module.exports = RESTMethods;
diff --git a/src/client/websocket/packets/handlers/GuildUpdate.js b/src/client/websocket/packets/handlers/GuildUpdate.js
index e74effbfc..7a44eaabc 100644
--- a/src/client/websocket/packets/handlers/GuildUpdate.js
+++ b/src/client/websocket/packets/handlers/GuildUpdate.js
@@ -19,11 +19,7 @@ class GuildUpdateHandler extends AbstractHandler {
let data = packet.d;
let client = this.packetManager.client;
- let guild = client.store.get('guilds', data.id);
-
- if (guild) {
- client.store.UpdateGuild(guild, data);
- }
+ let response = client.actions.GuildUpdate.handle(data);
}
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index add9d37ed..1d5e71a6d 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -8,6 +8,21 @@ const VoiceChannel = require('./VoiceChannel');
const Constants = require('../Util/Constants');
const Role = require('./Role');
+function arraysEqual(a, b) {
+ if (a === b) return true;
+ if (a.length !== b.length) return false;
+
+ for (let itemInd in a) {
+ let item = a[itemInd];
+ let ind = b.indexOf(item);
+ if (ind) {
+ b.splice(ind, 1);
+ }
+ }
+
+ return b.length === 0;
+}
+
class Guild {
constructor(client, data) {
this.client = client;
@@ -64,6 +79,34 @@ class Guild {
return this.client.resolver.ResolveGuildMember(this, user);
}
+ equals(data) {
+ let base =
+ this.id === data.id &&
+ this.available === !data.unavailable &&
+ this.splash === data.splash &&
+ this.region === data.region &&
+ this.name === data.name &&
+ this.memberCount === data.member_count &&
+ this.large === data.large &&
+ this.icon === data.icon &&
+ arraysEqual(this.features, data.features) &&
+ this.owner.id === data.owner_id &&
+ this.verificationLevel === data.verification_level &&
+ this.embedEnabled === data.embed_enabled;
+
+ if (base) {
+ if (this.embedChannel) {
+ if (this.embedChannel.id !== data.embed_channel_id) {
+ base = false;
+ }
+ } else if (data.embed_channel_id) {
+ base = false;
+ }
+ }
+
+ return base;
+ }
+
setup(data) {
this.id = data.id;
this.available = !data.unavailable;
@@ -79,7 +122,6 @@ class Guild {
this.afkTimeout = data.afk_timeout;
this.afkChannelID = data.afk_channel_id;
this.embedEnabled = data.embed_enabled;
- this.embedChannelID = data.embed_channel_id;
this.verificationLevel = data.verification_level;
this.features = data.features || [];
@@ -99,6 +141,8 @@ class Guild {
}
}
+ this.embedChannel = this.store.get('channels', data.embed_channel_id);
+
if (data.roles) {
this.store.clear('roles');
for (let role of data.roles) {
@@ -143,6 +187,42 @@ class Guild {
return this.client.rest.methods.DeleteGuild(this);
}
+ edit(data) {
+ return this.client.rest.methods.UpdateGuild(this, data);
+ }
+
+ setName(name) {
+ return this.edit({ name, });
+ }
+
+ setRegion(region) {
+ return this.edit({ region, });
+ }
+
+ setVerificationLevel(verificationLevel) {
+ return this.edit({ verificationLevel, });
+ }
+
+ setAFKChannel(afkchannel) {
+ return this.edit({ afkChannel, });
+ }
+
+ setAFKTimeout(afkTimeout) {
+ return this.edit({ afkTimeout, });
+ }
+
+ setIcon(icon) {
+ return this.edit({ icon, });
+ }
+
+ setOwner(owner) {
+ return this.edit({ owner, });
+ }
+
+ setSplash(splash) {
+ return this.edit({ splash, });
+ }
+
get channels() { return this.store.getAsArray('channels'); }
get $channels() { return this.store.data.channels; }
diff --git a/src/structures/ServerChannel.js b/src/structures/ServerChannel.js
index f15f1b613..3ff271477 100644
--- a/src/structures/ServerChannel.js
+++ b/src/structures/ServerChannel.js
@@ -7,6 +7,7 @@ const Constants = require('../util/Constants');
function arraysEqual(a, b) {
if (a === b) return true;
+ if (a.length !== b.length) return false;
for (let itemInd in a) {
let item = a[itemInd];
@@ -50,7 +51,7 @@ class ServerChannel extends Channel{
);
if (base) {
- if (other.permission_overwrites && other.permission_overwrites.length === this.permissionOverwrites.length) {
+ if (other.permission_overwrites) {
let thisIDSet = this.permissionOverwrites.map(overwrite => overwrite.id);
let otherIDSet = other.permission_overwrites.map(overwrite => overwrite.id);
if (arraysEqual(thisIDSet, otherIDSet)) {
diff --git a/test/random.js b/test/random.js
index 194fe13da..656986c42 100644
--- a/test/random.js
+++ b/test/random.js
@@ -18,7 +18,7 @@ client.on('guildDelete', (guild) => {
console.log('guilddel', guild.name);
});
client.on('guildUpdate', (old, guild) => {
- console.log(old.name, guild.name);
+ console.log('guildupdate', old.name, guild.name);
});
client.on('channelCreate', channel => {
// console.log(channel);
@@ -82,11 +82,11 @@ client.on('message', message => {
}
if (message.content.startsWith('setname')) {
- message.channel.setName(message.content.substr(8)).then(chanLoop).catch(console.log);
+ message.channel.setName(message.content.substr(8));
}
if (message.content.startsWith('botname')) {
- client.user.setUsername(message.content.substr(8)).then(nameLoop).catch(console.log);
+ client.user.setUsername(message.content.substr(8));
}
if (message.content.startsWith('botavatar')) {
@@ -98,14 +98,27 @@ client.on('message', message => {
});
}
+ if (message.content.startsWith('gn')) {
+ message.guild.setName(message.content.substr(3))
+ .then(guild => console.log('guild updated to', guild.name))
+ .catch(console.log);
+ }
+
if (message.content === 'leave') {
message.guild.leave().then(guild => console.log('left guild', guild.name)).catch(console.log);
}
+
+ if (message.content === 'stats') {
+ let m = '';
+ m += `I am aware of ${message.guild.channels.length} channels\n`;
+ m += `I am aware of ${message.guild.members.length} members`;
+ message.channel.sendMessage(m);
+ }
}
});
function nameLoop(user) {
- user.setUsername(user.username + 'a').then(nameLoop).catch(console.log);
+ // user.setUsername(user.username + 'a').then(nameLoop).catch(console.log);
}
function chanLoop(channel) {
From bc443df11dde22f20c0628d7409279e0cc4bc027 Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Tue, 3 May 2016 17:50:33 +0100
Subject: [PATCH 036/324] Added DM support, DM Creation and DM Deletion
---
src/client/rest/RESTMethods.js | 57 +++++++++++++++++---
src/structures/GuildMember.js | 8 +++
src/structures/User.js | 8 +++
src/structures/interface/TextBasedChannel.js | 5 --
test/random.js | 11 +++-
5 files changed, 75 insertions(+), 14 deletions(-)
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index 810b3df58..70a4da882 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -2,7 +2,8 @@
const Constants = require('../../util/Constants');
const Structure = name => require('../../structures/' + name);
-
+const User = Structure('User');
+const GuildMember = Structure('GuildMember');
const Message = Structure('Message');
class RESTMethods{
@@ -39,13 +40,24 @@ class RESTMethods{
SendMessage(channel, content, tts, nonce) {
return new Promise((resolve, reject) => {
- this.rest.makeRequest('post', Constants.Endpoints.CHANNEL_MESSAGES(channel.id), true, {
- content, tts, nonce,
- })
- .then(data => {
- resolve(this.rest.client.actions.MessageCreate.handle(data).m);
- })
- .catch(reject);
+
+ if (channel instanceof User || channel instanceof GuildMember) {
+ this.CreateDM(channel).then(chan => {
+ channel = chan;
+ req();
+ })
+ .catch(reject);
+ }
+
+ var _this = this;
+
+ function req() {
+ _this.rest.makeRequest('post', Constants.Endpoints.CHANNEL_MESSAGES(channel.id), true, {
+ content, tts, nonce,
+ })
+ .then(data => resolve(_this.rest.client.actions.MessageCreate.handle(data).m))
+ .catch(reject);
+ }
});
}
@@ -87,8 +99,37 @@ class RESTMethods{
});
}
+ GetExistingDM(recipient) {
+ let dmChannel = this.rest.client.store.getAsArray('channels')
+ .filter(channel => channel.recipient)
+ .filter(channel => channel.recipient.id === recipient.id);
+
+ return dmChannel[0];
+ }
+
+ CreateDM(recipient) {
+ return new Promise((resolve, reject) => {
+
+ let dmChannel = this.GetExistingDM(recipient);
+
+ if (dmChannel) {
+ return resolve(dmChannel);
+ }
+
+ this.rest.makeRequest('post', Constants.Endpoints.USER_CHANNELS(this.rest.client.store.user.id), true, {
+ recipient_id: recipient.id,
+ })
+ .then(data => resolve(this.rest.client.actions.ChannelCreate.handle(data).channel))
+ .catch(reject);
+ });
+ }
+
DeleteChannel(channel) {
return new Promise((resolve, reject) => {
+ if (channel instanceof User || channel instanceof GuildMember) {
+ channel = this.GetExistingDM(channel);
+ }
+
this.rest.makeRequest('del', Constants.Endpoints.CHANNEL(channel.id), true)
.then(data => {
data.id = channel.id;
diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js
index 265f0afe6..bacc3a314 100644
--- a/src/structures/GuildMember.js
+++ b/src/structures/GuildMember.js
@@ -1,5 +1,7 @@
'use strict';
+const TextBasedChannel = require('./interface/TextBasedChannel');
+
class GuildMember {
constructor(guild, data) {
this.client = guild.client;
@@ -56,6 +58,12 @@ class GuildMember {
get id() {
return this.user.id;
}
+
+ deleteDM() {
+ return this.client.rest.methods.DeleteChannel(this);
+ }
}
+TextBasedChannel.applyToClass(GuildMember);
+
module.exports = GuildMember;
diff --git a/src/structures/User.js b/src/structures/User.js
index 4d48aed5a..e635f4937 100644
--- a/src/structures/User.js
+++ b/src/structures/User.js
@@ -1,5 +1,7 @@
'use strict';
+const TextBasedChannel = require('./interface/TextBasedChannel');
+
class User {
constructor(client, data) {
this.client = client;
@@ -22,6 +24,10 @@ class User {
return `<@${this.id}>`;
}
+ deleteDM() {
+ return this.client.rest.methods.DeleteChannel(this);
+ }
+
equals(user) {
let base = (
this.username === user.username &&
@@ -45,4 +51,6 @@ class User {
}
}
+TextBasedChannel.applyToClass(User);
+
module.exports = User;
diff --git a/src/structures/interface/TextBasedChannel.js b/src/structures/interface/TextBasedChannel.js
index 0656d03f7..a76a855a5 100644
--- a/src/structures/interface/TextBasedChannel.js
+++ b/src/structures/interface/TextBasedChannel.js
@@ -11,10 +11,5 @@ function sendTTSMessage(content, options) {
}
exports.applyToClass = structure => {
- if (structure.name !== 'TextChannel' && structure.name !== 'DMChannel') {
- throw new Error(structure + ' cannot implement TextBasedChannel');
- }
-
structure.prototype.sendMessage = sendMessage;
-
};
diff --git a/test/random.js b/test/random.js
index 656986c42..6041df9ae 100644
--- a/test/random.js
+++ b/test/random.js
@@ -70,7 +70,7 @@ client.on('typingStop.', (channel, user, data) => {
});
client.on('message', message => {
- if (message.author.username === 'hydrabolt') {
+ if (true) {
if (message.content === 'makechann') {
if (message.channel.guild) {
message.channel.guild.createChannel('hi', 'text').then(console.log);
@@ -114,6 +114,15 @@ client.on('message', message => {
m += `I am aware of ${message.guild.members.length} members`;
message.channel.sendMessage(m);
}
+
+ if (message.content === 'messageme!') {
+ message.author.sendMessage('oh, hi there!').catch(e => console.log(e.stack));
+ }
+
+ if (message.content === 'don\'t dm me') {
+ message.author.deleteDM();
+ }
+
}
});
From fb49ad7d9310703392b0d00c279e1080645f6b0a Mon Sep 17 00:00:00 2001
From: hydrabolt
Date: Sat, 7 May 2016 15:33:00 +0100
Subject: [PATCH 037/324] Fix Message Sending and Support New Features. The
library now supports all the game streaming and URL stuff and is fixed for
roles #328
src/client/websocket/packets/handlers/PresenceUpdate.js
---
src/client/rest/RESTMethods.js | 6 ++++--
src/client/websocket/packets/handlers/PresenceUpdate.js | 6 +-----
src/structures/EvaluatedPermissions.js | 2 +-
src/structures/Role.js | 2 +-
src/util/Constants.js | 6 +++++-
test/random.js | 5 +++++
6 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index 70a4da882..54254689a 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -41,16 +41,18 @@ class RESTMethods{
SendMessage(channel, content, tts, nonce) {
return new Promise((resolve, reject) => {
+ var _this = this;
+
if (channel instanceof User || channel instanceof GuildMember) {
this.CreateDM(channel).then(chan => {
channel = chan;
req();
})
.catch(reject);
+ } else {
+ req();
}
- var _this = this;
-
function req() {
_this.rest.makeRequest('post', Constants.Endpoints.CHANNEL_MESSAGES(channel.id), true, {
content, tts, nonce,
diff --git a/src/client/websocket/packets/handlers/PresenceUpdate.js b/src/client/websocket/packets/handlers/PresenceUpdate.js
index 889017bce..e3c5e4f1a 100644
--- a/src/client/websocket/packets/handlers/PresenceUpdate.js
+++ b/src/client/websocket/packets/handlers/PresenceUpdate.js
@@ -60,11 +60,7 @@ class PresenceUpdateHandler extends AbstractHandler {
data.user.discriminator === user.discriminator &&
data.user.avatar === user.avatar &&
data.user.status === user.status &&
- !(
- (data.user.game && !user.game) ||
- (!data.user.game && user.game) ||
- (data.user.game && user.game && data.user.game.name !== user.game.name)
- )
+ JSON.stringify(data.user.game) === JSON.stringify(user.game)
);
if (!same) {
diff --git a/src/structures/EvaluatedPermissions.js b/src/structures/EvaluatedPermissions.js
index 96d0a4c9d..30ef07844 100644
--- a/src/structures/EvaluatedPermissions.js
+++ b/src/structures/EvaluatedPermissions.js
@@ -27,7 +27,7 @@ class EvaluatedPermissions {
}
if (!explicit) {
- if ((this.permissions & Constants.PermissionFlags.MANAGE_ROLES) > 0) {
+ if ((this.permissions & Constants.PermissionFlags.ADMINISTRATOR) > 0) {
return true;
}
}
diff --git a/src/structures/Role.js b/src/structures/Role.js
index 30dc865a3..5d8a7dfa8 100644
--- a/src/structures/Role.js
+++ b/src/structures/Role.js
@@ -40,7 +40,7 @@ class Role {
}
if (!explicit) {
- if ((this.permissions & Constants.PermissionFlags.MANAGE_ROLES) > 0) {
+ if ((this.permissions & Constants.PermissionFlags.ADMINISTRATOR) > 0) {
return true;
}
}
diff --git a/src/util/Constants.js b/src/util/Constants.js
index 54df21ad5..33ceeca14 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -146,7 +146,7 @@ const PermissionFlags = exports.PermissionFlags = {
CREATE_INSTANT_INVITE: 1 << 0,
KICK_MEMBERS: 1 << 1,
BAN_MEMBERS: 1 << 2,
- MANAGE_ROLES: 1 << 3,
+ ADMINISTRATOR: 1 << 3,
MANAGE_CHANNELS: 1 << 4,
MANAGE_GUILD: 1 << 5,
@@ -165,6 +165,10 @@ const PermissionFlags = exports.PermissionFlags = {
DEAFEN_MEMBERS: 1 << 23,
MOVE_MEMBERS: 1 << 24,
USE_VAD: 1 << 25,
+
+ CHANGE_NICKNAME: 1 << 26,
+ MANAGE_NICKNAMES: 1 << 27,
+ MANAGE_ROLES_OR_PERMISSIONS: 1 << 28,
};
let _ALL_PERMISSIONS = 0;
diff --git a/test/random.js b/test/random.js
index 6041df9ae..aeb7147d2 100644
--- a/test/random.js
+++ b/test/random.js
@@ -77,6 +77,11 @@ client.on('message', message => {
}
}
+ if (message.content === 'myperms?') {
+ message.channel.sendMessage('Your permissions are:\n' +
+ JSON.stringify(message.channel.permissionsFor(message.author).serialize(), null, 4));
+ }
+
if (message.content === 'delchann') {
message.channel.delete().then(chan => console.log('selfDelChann', chan.name));
}
From bbf0b0683a9ac1a8f509bf91a8c4e380dfb1d380 Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sat, 2 Jul 2016 17:50:44 +0100
Subject: [PATCH 038/324] Added guild.kick(member) and member.kick()
---
.gitignore | 74 +--
src/client/actions/ActionsManager.js | 53 +-
src/client/actions/ChannelDelete.js | 88 +--
src/client/actions/GuildMemberRemove.js | 50 ++
src/client/rest/RESTMethods.js | 507 +++++++++---------
.../packets/handlers/ChannelUpdate.js | 56 +-
.../packets/handlers/GuildMemberRemove.js | 9 +-
src/structures/Guild.js | 7 +-
src/structures/GuildMember.js | 4 +
src/util/Constants.js | 1 +
test/random.js | 7 +
11 files changed, 465 insertions(+), 391 deletions(-)
create mode 100644 src/client/actions/GuildMemberRemove.js
diff --git a/.gitignore b/.gitignore
index d1ca39f79..9167b884f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,38 +1,38 @@
-# Created by https://www.gitignore.io
-
-.tmp/
-.vscode/
-
-### Node ###
-# Logs
-logs
-*.log
-
-test/auth.json
-
-# Runtime data
-pids
-*.pid
-*.seed
-
-# Directory for instrumented libs generated by jscoverage/JSCover
-lib-cov
-
-# Coverage directory used by tools like istanbul
-coverage
-
-# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
-.grunt
-
-# node-waf configuration
-.lock-wscript
-
-# Compiled binary addons (http://nodejs.org/api/addons.html)
-build/Release
-
-# Dependency directory
-# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
-node_modules
-test/auth.json
-examples/auth.json
+# Created by https://www.gitignore.io
+
+.tmp/
+.vscode/
+
+### Node ###
+# Logs
+logs
+*.log
+
+test/auth.json
+
+# Runtime data
+pids
+*.pid
+*.seed
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directory
+# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
+node_modules
+test/auth.json
+examples/auth.json
docs/_build
\ No newline at end of file
diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js
index 41d5be9de..051cde9be 100644
--- a/src/client/actions/ActionsManager.js
+++ b/src/client/actions/ActionsManager.js
@@ -1,26 +1,27 @@
-'use strict';
-
-const requireAction = name => require(`./${name}`);
-
-class ActionsManager {
- constructor(client) {
- this.client = client;
-
- this.register('MessageCreate');
- this.register('MessageDelete');
- this.register('MessageUpdate');
- this.register('ChannelCreate');
- this.register('ChannelDelete');
- this.register('ChannelUpdate');
- this.register('GuildDelete');
- this.register('GuildUpdate');
- this.register('UserUpdate');
- }
-
- register(name) {
- let Action = requireAction(name);
- this[name] = new Action(this.client);
- }
-}
-
-module.exports = ActionsManager;
+'use strict';
+
+const requireAction = name => require(`./${name}`);
+
+class ActionsManager {
+ constructor(client) {
+ this.client = client;
+
+ this.register('MessageCreate');
+ this.register('MessageDelete');
+ this.register('MessageUpdate');
+ this.register('ChannelCreate');
+ this.register('ChannelDelete');
+ this.register('ChannelUpdate');
+ this.register('GuildDelete');
+ this.register('GuildUpdate');
+ this.register('GuildMemberRemove');
+ this.register('UserUpdate');
+ }
+
+ register(name) {
+ let Action = requireAction(name);
+ this[name] = new Action(this.client);
+ }
+}
+
+module.exports = ActionsManager;
diff --git a/src/client/actions/ChannelDelete.js b/src/client/actions/ChannelDelete.js
index 4f021d0ed..36b6d0231 100644
--- a/src/client/actions/ChannelDelete.js
+++ b/src/client/actions/ChannelDelete.js
@@ -1,44 +1,44 @@
-'use strict';
-
-const Action = require('./Action');
-const Constants = require('../../util/Constants');
-const Message = require('../../structures/Message');
-
-class ChannelDeleteAction extends Action {
-
- constructor(client) {
- super(client);
- this.timeouts = [];
- this.deleted = {};
- }
-
- handle(data) {
- let client = this.client;
- let channel = client.store.get('channels', data.id);
-
- if (channel) {
-
- client.store.KillChannel(channel);
- this.deleted[channel.id] = channel;
- this.scheduleForDeletion(channel.id);
-
- } else if (this.deleted[data.id]) {
-
- channel = this.deleted[data.id];
-
- }
-
- return {
- channel,
- };
- }
-
- scheduleForDeletion(id) {
- this.timeouts.push(
- setTimeout(() => delete this.deleted[id],
- this.client.options.rest_ws_bridge_timeout)
- );
- }
-};
-
-module.exports = ChannelDeleteAction;
+'use strict';
+
+const Action = require('./Action');
+const Constants = require('../../util/Constants');
+const Message = require('../../structures/Message');
+
+class ChannelDeleteAction extends Action {
+
+ constructor(client) {
+ super(client);
+ this.timeouts = [];
+ this.deleted = {};
+ }
+
+ handle(data) {
+ let client = this.client;
+ let channel = client.store.get('channels', data.id);
+
+ if (channel) {
+
+ client.store.KillChannel(channel);
+ this.deleted[channel.id] = channel;
+ this.scheduleForDeletion(channel.id);
+
+ } else if (this.deleted[data.id]) {
+
+ channel = this.deleted[data.id];
+
+ }
+
+ return {
+ channel,
+ };
+ }
+
+ scheduleForDeletion(id) {
+ this.timeouts.push(
+ setTimeout(() => delete this.deleted[id],
+ this.client.options.rest_ws_bridge_timeout)
+ );
+ }
+};
+
+module.exports = ChannelDeleteAction;
diff --git a/src/client/actions/GuildMemberRemove.js b/src/client/actions/GuildMemberRemove.js
new file mode 100644
index 000000000..d9ddf62c7
--- /dev/null
+++ b/src/client/actions/GuildMemberRemove.js
@@ -0,0 +1,50 @@
+'use strict';
+
+const Action = require('./Action');
+const Constants = require('../../util/Constants');
+const Message = require('../../structures/Message');
+
+class GuildMemberRemoveAction extends Action {
+
+ constructor(client) {
+ super(client);
+ this.timeouts = [];
+ this.deleted = {};
+ }
+
+ handle(data) {
+ let client = this.client;
+ let guild = client.store.get('guilds', data.guild_id);
+ if (guild) {
+ let member = guild.store.get('members', data.user.id);
+ if (member) {
+ guild._removeMember(member);
+ this.deleted[guild.id + data.user.id] = member;
+ this.scheduleForDeletion(guild.id, data.user.id);
+ }
+
+ if (!member) {
+ member = this.deleted[guild.id + data.user.id];
+ }
+
+ return {
+ g: guild,
+ m: member,
+ };
+ }
+
+ return {
+ g: guild,
+ m: null,
+ };
+ }
+
+ scheduleForDeletion(guildID, userID) {
+ this.timeouts.push(
+ setTimeout(() => delete this.deleted[guildID + userID],
+ this.client.options.rest_ws_bridge_timeout)
+ );
+ }
+};
+
+module.exports = GuildMemberRemoveAction;
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index 54254689a..ea812ebd2 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -1,247 +1,260 @@
-'use strict';
-
-const Constants = require('../../util/Constants');
-const Structure = name => require('../../structures/' + name);
-const User = Structure('User');
-const GuildMember = Structure('GuildMember');
-const Message = Structure('Message');
-
-class RESTMethods{
- constructor(restManager) {
- this.rest = restManager;
- }
-
- LoginEmailPassword(email, password) {
- return new Promise((resolve, reject) => {
- this.rest.client.store.email = email;
- this.rest.client.store.password = password;
- this.rest.makeRequest('post', Constants.Endpoints.LOGIN, false, { email, password })
- .then(data => {
- this.rest.client.manager.connectToWebSocket(data.token, resolve, reject);
- })
- .catch(reject);
-
- });
- }
-
- LoginToken(token) {
- return new Promise((resolve, reject) => {
- this.rest.client.manager.connectToWebSocket(token, resolve, reject);
- });
- }
-
- GetGateway() {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('get', Constants.Endpoints.GATEWAY, true)
- .then(res => resolve(res.url))
- .catch(reject);
- });
- }
-
- SendMessage(channel, content, tts, nonce) {
- return new Promise((resolve, reject) => {
-
- var _this = this;
-
- if (channel instanceof User || channel instanceof GuildMember) {
- this.CreateDM(channel).then(chan => {
- channel = chan;
- req();
- })
- .catch(reject);
- } else {
- req();
- }
-
- function req() {
- _this.rest.makeRequest('post', Constants.Endpoints.CHANNEL_MESSAGES(channel.id), true, {
- content, tts, nonce,
- })
- .then(data => resolve(_this.rest.client.actions.MessageCreate.handle(data).m))
- .catch(reject);
- }
- });
- }
-
- DeleteMessage(message) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('del', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true)
- .then(data => {
- resolve(this.rest.client.actions.MessageDelete.handle({
- id: message.id,
- channel_id: message.channel.id,
- }).m);
- })
- .catch(reject);
- });
- }
-
- UpdateMessage(message, content) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true, {
- content,
- })
- .then(data => {
- resolve(this.rest.client.actions.MessageUpdate.handle(data).updated);
- })
- .catch(reject);
- });
- }
-
- CreateChannel(guild, channelName, channelType) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('post', Constants.Endpoints.GUILD_CHANNELS(guild.id), true, {
- name: channelName,
- type: channelType,
- })
- .then(data => {
- resolve(this.rest.client.actions.ChannelCreate.handle(data).channel);
- })
- .catch(reject);
- });
- }
-
- GetExistingDM(recipient) {
- let dmChannel = this.rest.client.store.getAsArray('channels')
- .filter(channel => channel.recipient)
- .filter(channel => channel.recipient.id === recipient.id);
-
- return dmChannel[0];
- }
-
- CreateDM(recipient) {
- return new Promise((resolve, reject) => {
-
- let dmChannel = this.GetExistingDM(recipient);
-
- if (dmChannel) {
- return resolve(dmChannel);
- }
-
- this.rest.makeRequest('post', Constants.Endpoints.USER_CHANNELS(this.rest.client.store.user.id), true, {
- recipient_id: recipient.id,
- })
- .then(data => resolve(this.rest.client.actions.ChannelCreate.handle(data).channel))
- .catch(reject);
- });
- }
-
- DeleteChannel(channel) {
- return new Promise((resolve, reject) => {
- if (channel instanceof User || channel instanceof GuildMember) {
- channel = this.GetExistingDM(channel);
- }
-
- this.rest.makeRequest('del', Constants.Endpoints.CHANNEL(channel.id), true)
- .then(data => {
- data.id = channel.id;
- resolve(this.rest.client.actions.ChannelDelete.handle(data).channel);
- })
- .catch(reject);
- });
- }
-
- UpdateChannel(channel, data) {
- return new Promise((resolve, reject) => {
- data.name = (data.name || channel.name).trim();
- data.topic = data.topic || channel.topic;
- data.position = data.position || channel.position;
- data.bitrate = data.bitrate || channel.bitrate;
-
- this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL(channel.id), true, data)
- .then(data => {
- resolve(this.rest.client.actions.ChannelUpdate.handle(data).updated);
- })
- .catch(reject);
- });
- }
-
- LeaveGuild(guild) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('del', Constants.Endpoints.ME_GUILD(guild.id), true)
- .then(() => {
- resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild);
- })
- .catch(reject);
- });
- }
-
- // untested but probably will work
- DeleteGuild(guild) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('del', Constants.Endpoints.GUILD(guild.id), true)
- .then(() => {
- resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild);
- })
- .catch(reject);
- });
- }
-
- UpdateCurrentUser(_data) {
- return new Promise((resolve, reject) => {
- let user = this.rest.client.store.user;
- let data = {};
-
- data.username = _data.username || user.username;
- data.avatar = this.rest.client.resolver.ResolveBase64(_data.avatar) || user.avatar;
- if (!user.bot) {
- data.password = this.rest.client.store.password;
- data.email = _data.email || this.rest.client.store.email;
- data.new_password = _data.newPassword;
- }
-
- this.rest.makeRequest('patch', Constants.Endpoints.ME, true, data)
- .then(data => resolve(this.rest.client.actions.UserUpdate.handle(data).updated))
- .catch(reject);
- });
- }
-
- UpdateGuild(guild, _data) {
- return new Promise((resolve, reject) => {
- /*
- can contain:
- name, region, verificationLevel, afkChannel, afkTimeout, icon, owner, splash
- */
-
- let data = {};
-
- if (_data.name) {
- data.name = _data.name;
- }
-
- if (_data.region) {
- data.region = _data.region;
- }
-
- if (_data.verificationLevel) {
- data.verification_level = Number(_data.verificationLevel);
- }
-
- if (_data.afkChannel) {
- data.afk_channel_id = this.rest.client.resolver.ResolveChannel(_data.afkChannel).id;
- }
-
- if (_data.afkTimeout) {
- data.afk_timeout = Number(_data.afkTimeout);
- }
-
- if (_data.icon) {
- data.icon = this.rest.client.resolver.ResolveBase64(_data.icon);
- }
-
- if (_data.owner) {
- data.owner_id = this.rest.client.resolver.ResolveUser(_data.owner).id;
- }
-
- if (_data.splash) {
- data.splash = this.rest.client.resolver.ResolveBase64(_data.splash);
- }
-
- this.rest.makeRequest('patch', Constants.Endpoints.GUILD(guild.id), true, data)
- .then(data => resolve(this.rest.client.actions.GuildUpdate.handle(data).updated))
- .catch(reject);
- });
- }
-}
-
-module.exports = RESTMethods;
+'use strict';
+
+const Constants = require('../../util/Constants');
+const Structure = name => require('../../structures/' + name);
+const User = Structure('User');
+const GuildMember = Structure('GuildMember');
+const Message = Structure('Message');
+
+class RESTMethods{
+ constructor(restManager) {
+ this.rest = restManager;
+ }
+
+ LoginEmailPassword(email, password) {
+ return new Promise((resolve, reject) => {
+ this.rest.client.store.email = email;
+ this.rest.client.store.password = password;
+ this.rest.makeRequest('post', Constants.Endpoints.LOGIN, false, { email, password })
+ .then(data => {
+ this.rest.client.manager.connectToWebSocket(data.token, resolve, reject);
+ })
+ .catch(reject);
+
+ });
+ }
+
+ LoginToken(token) {
+ return new Promise((resolve, reject) => {
+ this.rest.client.manager.connectToWebSocket(token, resolve, reject);
+ });
+ }
+
+ GetGateway() {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('get', Constants.Endpoints.GATEWAY, true)
+ .then(res => resolve(res.url))
+ .catch(reject);
+ });
+ }
+
+ SendMessage(channel, content, tts, nonce) {
+ return new Promise((resolve, reject) => {
+
+ var _this = this;
+
+ if (channel instanceof User || channel instanceof GuildMember) {
+ this.CreateDM(channel).then(chan => {
+ channel = chan;
+ req();
+ })
+ .catch(reject);
+ } else {
+ req();
+ }
+
+ function req() {
+ _this.rest.makeRequest('post', Constants.Endpoints.CHANNEL_MESSAGES(channel.id), true, {
+ content, tts, nonce,
+ })
+ .then(data => resolve(_this.rest.client.actions.MessageCreate.handle(data).m))
+ .catch(reject);
+ }
+ });
+ }
+
+ DeleteMessage(message) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true)
+ .then(data => {
+ resolve(this.rest.client.actions.MessageDelete.handle({
+ id: message.id,
+ channel_id: message.channel.id,
+ }).m);
+ })
+ .catch(reject);
+ });
+ }
+
+ UpdateMessage(message, content) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true, {
+ content,
+ })
+ .then(data => {
+ resolve(this.rest.client.actions.MessageUpdate.handle(data).updated);
+ })
+ .catch(reject);
+ });
+ }
+
+ CreateChannel(guild, channelName, channelType) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('post', Constants.Endpoints.GUILD_CHANNELS(guild.id), true, {
+ name: channelName,
+ type: channelType,
+ })
+ .then(data => {
+ resolve(this.rest.client.actions.ChannelCreate.handle(data).channel);
+ })
+ .catch(reject);
+ });
+ }
+
+ GetExistingDM(recipient) {
+ let dmChannel = this.rest.client.store.getAsArray('channels')
+ .filter(channel => channel.recipient)
+ .filter(channel => channel.recipient.id === recipient.id);
+
+ return dmChannel[0];
+ }
+
+ CreateDM(recipient) {
+ return new Promise((resolve, reject) => {
+
+ let dmChannel = this.GetExistingDM(recipient);
+
+ if (dmChannel) {
+ return resolve(dmChannel);
+ }
+
+ this.rest.makeRequest('post', Constants.Endpoints.USER_CHANNELS(this.rest.client.store.user.id), true, {
+ recipient_id: recipient.id,
+ })
+ .then(data => resolve(this.rest.client.actions.ChannelCreate.handle(data).channel))
+ .catch(reject);
+ });
+ }
+
+ DeleteChannel(channel) {
+ return new Promise((resolve, reject) => {
+ if (channel instanceof User || channel instanceof GuildMember) {
+ channel = this.GetExistingDM(channel);
+ }
+
+ this.rest.makeRequest('del', Constants.Endpoints.CHANNEL(channel.id), true)
+ .then(data => {
+ data.id = channel.id;
+ resolve(this.rest.client.actions.ChannelDelete.handle(data).channel);
+ })
+ .catch(reject);
+ });
+ }
+
+ UpdateChannel(channel, data) {
+ return new Promise((resolve, reject) => {
+ data.name = (data.name || channel.name).trim();
+ data.topic = data.topic || channel.topic;
+ data.position = data.position || channel.position;
+ data.bitrate = data.bitrate || channel.bitrate;
+
+ this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL(channel.id), true, data)
+ .then(data => {
+ resolve(this.rest.client.actions.ChannelUpdate.handle(data).updated);
+ })
+ .catch(reject);
+ });
+ }
+
+ LeaveGuild(guild) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.ME_GUILD(guild.id), true)
+ .then(() => {
+ resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild);
+ })
+ .catch(reject);
+ });
+ }
+
+ // untested but probably will work
+ DeleteGuild(guild) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.GUILD(guild.id), true)
+ .then(() => {
+ resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild);
+ })
+ .catch(reject);
+ });
+ }
+
+ UpdateCurrentUser(_data) {
+ return new Promise((resolve, reject) => {
+ let user = this.rest.client.store.user;
+ let data = {};
+
+ data.username = _data.username || user.username;
+ data.avatar = this.rest.client.resolver.ResolveBase64(_data.avatar) || user.avatar;
+ if (!user.bot) {
+ data.password = this.rest.client.store.password;
+ data.email = _data.email || this.rest.client.store.email;
+ data.new_password = _data.newPassword;
+ }
+
+ this.rest.makeRequest('patch', Constants.Endpoints.ME, true, data)
+ .then(data => resolve(this.rest.client.actions.UserUpdate.handle(data).updated))
+ .catch(reject);
+ });
+ }
+
+ UpdateGuild(guild, _data) {
+ return new Promise((resolve, reject) => {
+ /*
+ can contain:
+ name, region, verificationLevel, afkChannel, afkTimeout, icon, owner, splash
+ */
+
+ let data = {};
+
+ if (_data.name) {
+ data.name = _data.name;
+ }
+
+ if (_data.region) {
+ data.region = _data.region;
+ }
+
+ if (_data.verificationLevel) {
+ data.verification_level = Number(_data.verificationLevel);
+ }
+
+ if (_data.afkChannel) {
+ data.afk_channel_id = this.rest.client.resolver.ResolveChannel(_data.afkChannel).id;
+ }
+
+ if (_data.afkTimeout) {
+ data.afk_timeout = Number(_data.afkTimeout);
+ }
+
+ if (_data.icon) {
+ data.icon = this.rest.client.resolver.ResolveBase64(_data.icon);
+ }
+
+ if (_data.owner) {
+ data.owner_id = this.rest.client.resolver.ResolveUser(_data.owner).id;
+ }
+
+ if (_data.splash) {
+ data.splash = this.rest.client.resolver.ResolveBase64(_data.splash);
+ }
+
+ this.rest.makeRequest('patch', Constants.Endpoints.GUILD(guild.id), true, data)
+ .then(data => resolve(this.rest.client.actions.GuildUpdate.handle(data).updated))
+ .catch(reject);
+ });
+ }
+
+ KickGuildMember(guild, member) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.GUILD_MEMBER(guild.id, member.id), true)
+ .then(() => {
+ resolve(this.rest.client.actions.GuildMemberRemove.handle({
+ guild_id : guild.id,
+ user : member.user,
+ }).m);
+ })
+ .catch(reject);
+ });
+ }
+}
+
+module.exports = RESTMethods;
diff --git a/src/client/websocket/packets/handlers/ChannelUpdate.js b/src/client/websocket/packets/handlers/ChannelUpdate.js
index 699cfd432..41491a103 100644
--- a/src/client/websocket/packets/handlers/ChannelUpdate.js
+++ b/src/client/websocket/packets/handlers/ChannelUpdate.js
@@ -1,28 +1,28 @@
-'use strict';
-
-const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-
-const ClientUser = Structure('ClientUser');
-const Guild = Structure('Guild');
-const ServerChannel = Structure('ServerChannel');
-
-const Constants = require('../../../../util/Constants');
-const CloneObject = require('../../../../util/CloneObject');
-
-class ChannelUpdateHandler extends AbstractHandler {
-
- constructor(packetManager) {
- super(packetManager);
- }
-
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
-
- client.actions.ChannelUpdate.handle(data);
- }
-
-};
-
-module.exports = ChannelUpdateHandler;
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+
+const ClientUser = Structure('ClientUser');
+const Guild = Structure('Guild');
+const ServerChannel = Structure('ServerChannel');
+
+const Constants = require('../../../../util/Constants');
+const CloneObject = require('../../../../util/CloneObject');
+
+class ChannelUpdateHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ client.actions.ChannelUpdate.handle(data);
+ }
+
+};
+
+module.exports = ChannelUpdateHandler;
diff --git a/src/client/websocket/packets/handlers/GuildMemberRemove.js b/src/client/websocket/packets/handlers/GuildMemberRemove.js
index a46556c38..185cb768c 100644
--- a/src/client/websocket/packets/handlers/GuildMemberRemove.js
+++ b/src/client/websocket/packets/handlers/GuildMemberRemove.js
@@ -20,13 +20,10 @@ class GuildMemberRemoveHandler extends AbstractHandler {
let data = packet.d;
let client = this.packetManager.client;
- let guild = client.store.get('guilds', data.guild_id);
+ let response = client.actions.GuildMemberRemove.handle(data);
- if (guild) {
- let member = guild.store.get('members', data.user.id);
- if (member) {
- guild._removeMember(member);
- }
+ if (response.m) {
+ client.emit(Constants.Events.GUILD_MEMBER_REMOVE, response.g, response.m);
}
}
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index 1d5e71a6d..a4607e03f 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -66,15 +66,16 @@ class Guild {
_removeMember(guildMember) {
this.store.remove('members', guildMember);
- if (this.client.ws.status === Constants.Status.READY) {
- this.client.emit(Constants.Events.GUILD_MEMBER_REMOVE, this, guildMember);
- }
}
toString() {
return this.name;
}
+ kick(member) {
+ return this.member(member).kick();
+ }
+
member(user) {
return this.client.resolver.ResolveGuildMember(this, user);
}
diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js
index bacc3a314..d35cc163d 100644
--- a/src/structures/GuildMember.js
+++ b/src/structures/GuildMember.js
@@ -62,6 +62,10 @@ class GuildMember {
deleteDM() {
return this.client.rest.methods.DeleteChannel(this);
}
+
+ kick() {
+ return this.client.rest.methods.KickGuildMember(this.guild, this);
+ }
}
TextBasedChannel.applyToClass(GuildMember);
diff --git a/src/util/Constants.js b/src/util/Constants.js
index 33ceeca14..e03fdf105 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -58,6 +58,7 @@ const Endpoints = exports.Endpoints = {
GUILD_BANS: (guildID) => `${Endpoints.GUILD(guildID)}/bans`,
GUILD_INTEGRATIONS: (guildID) => `${Endpoints.GUILD(guildID)}/integrations`,
GUILD_MEMBERS: (guildID) => `${Endpoints.GUILD(guildID)}/members`,
+ GUILD_MEMBER: (guildID, memberID) => `${Endpoints.GUILD_MEMBERS(guildID)}/${memberID}`,
GUILD_CHANNELS: (guildID) => `${Endpoints.GUILD(guildID)}/channels`,
// channels
diff --git a/test/random.js b/test/random.js
index aeb7147d2..dfe96f699 100644
--- a/test/random.js
+++ b/test/random.js
@@ -128,6 +128,13 @@ client.on('message', message => {
message.author.deleteDM();
}
+ if (message.content.startsWith('kick')) {
+ message.guild.member(message.mentions[0]).kick().then(member => {
+ console.log(member);
+ message.channel.sendMessage('Kicked!' + member.user.username);
+ }).catch(console.log);
+ }
+
}
});
From 849b8df2dad8ccc5196130418e010df200f76f3f Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sat, 2 Jul 2016 21:28:49 +0100
Subject: [PATCH 039/324] Added guild.createRole()
---
README.md | 10 +-
package.json | 110 ++--
src/client/actions/ActionsManager.js | 1 +
src/client/actions/GuildRoleCreate.js | 38 ++
src/client/rest/RESTMethods.js | 533 +++++++++---------
.../packets/handlers/GuildRoleCreate.js | 13 +-
src/structures/Guild.js | 4 +
test/random.js | 5 +
8 files changed, 382 insertions(+), 332 deletions(-)
create mode 100644 src/client/actions/GuildRoleCreate.js
diff --git a/README.md b/README.md
index 2514699cb..5e05bbbea 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-
-
-
-
-
REWRITE
+
+
+
+
+
REWRITE
\ No newline at end of file
diff --git a/package.json b/package.json
index b3e6705e3..36d8e745e 100644
--- a/package.json
+++ b/package.json
@@ -1,55 +1,55 @@
-{
- "name": "discord.js",
- "version": "7.0.0",
- "description": "A way to interface with the Discord API",
- "main": "./src/index",
- "scripts": {
- "test": "jscs src && node test/random"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/hydrabolt/discord.js.git"
- },
- "keywords": [
- "discord",
- "api",
- "bot",
- "client",
- "node",
- "discordapp"
- ],
- "author": "Amish Shah ",
- "license": "Apache-2.0",
- "bugs": {
- "url": "https://github.com/hydrabolt/discord.js/issues"
- },
- "homepage": "https://github.com/hydrabolt/discord.js#readme",
- "dependencies": {
- "babel-plugin-transform-runtime": "^6.6.0",
- "object.values": "^1.0.3",
- "superagent": "^1.5.0",
- "unpipe": "^1.0.0",
- "ws": "^0.8.1"
- },
- "devDependencies": {
- "babel-preset-es2015": "^6.6.0",
- "babel-preset-stage-3": "^6.5.0",
- "grunt": "^0.4.5",
- "grunt-babel": "^6.0.0",
- "grunt-browserify": "^4.0.1",
- "grunt-contrib-uglify": "^0.11.0",
- "grunt-jscs": "^2.8.0",
- "jscs": "^2.11.0",
- "load-grunt-tasks": "^3.3.0"
- },
- "optionalDependencies": {
- "node-opus": "^0.1.11"
- },
- "engines": {
- "node": ">=0.12.7"
- },
- "browser": {
- "./src/Util/TokenCacher.js": "./src/Util/TokenCacher-shim.js",
- "./lib/Util/TokenCacher.js": "./lib/Util/TokenCacher-shim.js"
- }
-}
+{
+ "name": "discord.js",
+ "version": "7.0.0",
+ "description": "A way to interface with the Discord API",
+ "main": "./src/index",
+ "scripts": {
+ "test": "jscs src && node test/random"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/hydrabolt/discord.js.git"
+ },
+ "keywords": [
+ "discord",
+ "api",
+ "bot",
+ "client",
+ "node",
+ "discordapp"
+ ],
+ "author": "Amish Shah ",
+ "license": "Apache-2.0",
+ "bugs": {
+ "url": "https://github.com/hydrabolt/discord.js/issues"
+ },
+ "homepage": "https://github.com/hydrabolt/discord.js#readme",
+ "dependencies": {
+ "babel-plugin-transform-runtime": "^6.6.0",
+ "object.values": "^1.0.3",
+ "superagent": "^1.5.0",
+ "unpipe": "^1.0.0",
+ "ws": "^0.8.1"
+ },
+ "devDependencies": {
+ "babel-preset-es2015": "^6.6.0",
+ "babel-preset-stage-3": "^6.5.0",
+ "grunt": "^0.4.5",
+ "grunt-babel": "^6.0.0",
+ "grunt-browserify": "^4.0.1",
+ "grunt-contrib-uglify": "^0.11.0",
+ "grunt-jscs": "^2.8.0",
+ "jscs": "^2.11.0",
+ "load-grunt-tasks": "^3.3.0"
+ },
+ "optionalDependencies": {
+ "node-opus": "^0.1.11"
+ },
+ "engines": {
+ "node": ">=0.12.7"
+ },
+ "browser": {
+ "./src/Util/TokenCacher.js": "./src/Util/TokenCacher-shim.js",
+ "./lib/Util/TokenCacher.js": "./lib/Util/TokenCacher-shim.js"
+ }
+}
diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js
index 051cde9be..51d4fdebc 100644
--- a/src/client/actions/ActionsManager.js
+++ b/src/client/actions/ActionsManager.js
@@ -15,6 +15,7 @@ class ActionsManager {
this.register('GuildDelete');
this.register('GuildUpdate');
this.register('GuildMemberRemove');
+ this.register('GuildRoleCreate');
this.register('UserUpdate');
}
diff --git a/src/client/actions/GuildRoleCreate.js b/src/client/actions/GuildRoleCreate.js
new file mode 100644
index 000000000..0a929d351
--- /dev/null
+++ b/src/client/actions/GuildRoleCreate.js
@@ -0,0 +1,38 @@
+'use strict';
+
+const Action = require('./Action');
+const Constants = require('../../util/Constants');
+const Role = require('../../structures/Role');
+
+class GuildRoleCreate extends Action {
+
+ constructor(client) {
+ super(client);
+ }
+
+ handle(data) {
+
+ let client = this.client;
+ let guild = client.store.get('guilds', data.guild_id);
+
+ if (guild) {
+ let already = guild.store.get('roles', data.role.id);
+ let role = new Role(guild, data.role);
+ guild.store.add('roles', role);
+
+ if (!already) {
+ client.emit(Constants.Events.GUILD_ROLE_CREATE, guild, role);
+ }
+
+ return {
+ role,
+ };
+ }
+
+ return {
+ role: null,
+ };
+ }
+};
+
+module.exports = GuildRoleCreate;
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index ea812ebd2..e8f05cde3 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -1,260 +1,273 @@
-'use strict';
-
-const Constants = require('../../util/Constants');
-const Structure = name => require('../../structures/' + name);
-const User = Structure('User');
-const GuildMember = Structure('GuildMember');
-const Message = Structure('Message');
-
-class RESTMethods{
- constructor(restManager) {
- this.rest = restManager;
- }
-
- LoginEmailPassword(email, password) {
- return new Promise((resolve, reject) => {
- this.rest.client.store.email = email;
- this.rest.client.store.password = password;
- this.rest.makeRequest('post', Constants.Endpoints.LOGIN, false, { email, password })
- .then(data => {
- this.rest.client.manager.connectToWebSocket(data.token, resolve, reject);
- })
- .catch(reject);
-
- });
- }
-
- LoginToken(token) {
- return new Promise((resolve, reject) => {
- this.rest.client.manager.connectToWebSocket(token, resolve, reject);
- });
- }
-
- GetGateway() {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('get', Constants.Endpoints.GATEWAY, true)
- .then(res => resolve(res.url))
- .catch(reject);
- });
- }
-
- SendMessage(channel, content, tts, nonce) {
- return new Promise((resolve, reject) => {
-
- var _this = this;
-
- if (channel instanceof User || channel instanceof GuildMember) {
- this.CreateDM(channel).then(chan => {
- channel = chan;
- req();
- })
- .catch(reject);
- } else {
- req();
- }
-
- function req() {
- _this.rest.makeRequest('post', Constants.Endpoints.CHANNEL_MESSAGES(channel.id), true, {
- content, tts, nonce,
- })
- .then(data => resolve(_this.rest.client.actions.MessageCreate.handle(data).m))
- .catch(reject);
- }
- });
- }
-
- DeleteMessage(message) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('del', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true)
- .then(data => {
- resolve(this.rest.client.actions.MessageDelete.handle({
- id: message.id,
- channel_id: message.channel.id,
- }).m);
- })
- .catch(reject);
- });
- }
-
- UpdateMessage(message, content) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true, {
- content,
- })
- .then(data => {
- resolve(this.rest.client.actions.MessageUpdate.handle(data).updated);
- })
- .catch(reject);
- });
- }
-
- CreateChannel(guild, channelName, channelType) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('post', Constants.Endpoints.GUILD_CHANNELS(guild.id), true, {
- name: channelName,
- type: channelType,
- })
- .then(data => {
- resolve(this.rest.client.actions.ChannelCreate.handle(data).channel);
- })
- .catch(reject);
- });
- }
-
- GetExistingDM(recipient) {
- let dmChannel = this.rest.client.store.getAsArray('channels')
- .filter(channel => channel.recipient)
- .filter(channel => channel.recipient.id === recipient.id);
-
- return dmChannel[0];
- }
-
- CreateDM(recipient) {
- return new Promise((resolve, reject) => {
-
- let dmChannel = this.GetExistingDM(recipient);
-
- if (dmChannel) {
- return resolve(dmChannel);
- }
-
- this.rest.makeRequest('post', Constants.Endpoints.USER_CHANNELS(this.rest.client.store.user.id), true, {
- recipient_id: recipient.id,
- })
- .then(data => resolve(this.rest.client.actions.ChannelCreate.handle(data).channel))
- .catch(reject);
- });
- }
-
- DeleteChannel(channel) {
- return new Promise((resolve, reject) => {
- if (channel instanceof User || channel instanceof GuildMember) {
- channel = this.GetExistingDM(channel);
- }
-
- this.rest.makeRequest('del', Constants.Endpoints.CHANNEL(channel.id), true)
- .then(data => {
- data.id = channel.id;
- resolve(this.rest.client.actions.ChannelDelete.handle(data).channel);
- })
- .catch(reject);
- });
- }
-
- UpdateChannel(channel, data) {
- return new Promise((resolve, reject) => {
- data.name = (data.name || channel.name).trim();
- data.topic = data.topic || channel.topic;
- data.position = data.position || channel.position;
- data.bitrate = data.bitrate || channel.bitrate;
-
- this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL(channel.id), true, data)
- .then(data => {
- resolve(this.rest.client.actions.ChannelUpdate.handle(data).updated);
- })
- .catch(reject);
- });
- }
-
- LeaveGuild(guild) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('del', Constants.Endpoints.ME_GUILD(guild.id), true)
- .then(() => {
- resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild);
- })
- .catch(reject);
- });
- }
-
- // untested but probably will work
- DeleteGuild(guild) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('del', Constants.Endpoints.GUILD(guild.id), true)
- .then(() => {
- resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild);
- })
- .catch(reject);
- });
- }
-
- UpdateCurrentUser(_data) {
- return new Promise((resolve, reject) => {
- let user = this.rest.client.store.user;
- let data = {};
-
- data.username = _data.username || user.username;
- data.avatar = this.rest.client.resolver.ResolveBase64(_data.avatar) || user.avatar;
- if (!user.bot) {
- data.password = this.rest.client.store.password;
- data.email = _data.email || this.rest.client.store.email;
- data.new_password = _data.newPassword;
- }
-
- this.rest.makeRequest('patch', Constants.Endpoints.ME, true, data)
- .then(data => resolve(this.rest.client.actions.UserUpdate.handle(data).updated))
- .catch(reject);
- });
- }
-
- UpdateGuild(guild, _data) {
- return new Promise((resolve, reject) => {
- /*
- can contain:
- name, region, verificationLevel, afkChannel, afkTimeout, icon, owner, splash
- */
-
- let data = {};
-
- if (_data.name) {
- data.name = _data.name;
- }
-
- if (_data.region) {
- data.region = _data.region;
- }
-
- if (_data.verificationLevel) {
- data.verification_level = Number(_data.verificationLevel);
- }
-
- if (_data.afkChannel) {
- data.afk_channel_id = this.rest.client.resolver.ResolveChannel(_data.afkChannel).id;
- }
-
- if (_data.afkTimeout) {
- data.afk_timeout = Number(_data.afkTimeout);
- }
-
- if (_data.icon) {
- data.icon = this.rest.client.resolver.ResolveBase64(_data.icon);
- }
-
- if (_data.owner) {
- data.owner_id = this.rest.client.resolver.ResolveUser(_data.owner).id;
- }
-
- if (_data.splash) {
- data.splash = this.rest.client.resolver.ResolveBase64(_data.splash);
- }
-
- this.rest.makeRequest('patch', Constants.Endpoints.GUILD(guild.id), true, data)
- .then(data => resolve(this.rest.client.actions.GuildUpdate.handle(data).updated))
- .catch(reject);
- });
- }
-
- KickGuildMember(guild, member) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('del', Constants.Endpoints.GUILD_MEMBER(guild.id, member.id), true)
- .then(() => {
- resolve(this.rest.client.actions.GuildMemberRemove.handle({
- guild_id : guild.id,
- user : member.user,
- }).m);
- })
- .catch(reject);
- });
- }
-}
-
-module.exports = RESTMethods;
+'use strict';
+
+const Constants = require('../../util/Constants');
+const Structure = name => require('../../structures/' + name);
+const User = Structure('User');
+const GuildMember = Structure('GuildMember');
+const Message = Structure('Message');
+
+class RESTMethods{
+ constructor(restManager) {
+ this.rest = restManager;
+ }
+
+ LoginEmailPassword(email, password) {
+ return new Promise((resolve, reject) => {
+ this.rest.client.store.email = email;
+ this.rest.client.store.password = password;
+ this.rest.makeRequest('post', Constants.Endpoints.LOGIN, false, { email, password })
+ .then(data => {
+ this.rest.client.manager.connectToWebSocket(data.token, resolve, reject);
+ })
+ .catch(reject);
+
+ });
+ }
+
+ LoginToken(token) {
+ return new Promise((resolve, reject) => {
+ this.rest.client.manager.connectToWebSocket(token, resolve, reject);
+ });
+ }
+
+ GetGateway() {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('get', Constants.Endpoints.GATEWAY, true)
+ .then(res => resolve(res.url))
+ .catch(reject);
+ });
+ }
+
+ SendMessage(channel, content, tts, nonce) {
+ return new Promise((resolve, reject) => {
+
+ var _this = this;
+
+ if (channel instanceof User || channel instanceof GuildMember) {
+ this.CreateDM(channel).then(chan => {
+ channel = chan;
+ req();
+ })
+ .catch(reject);
+ } else {
+ req();
+ }
+
+ function req() {
+ _this.rest.makeRequest('post', Constants.Endpoints.CHANNEL_MESSAGES(channel.id), true, {
+ content, tts, nonce,
+ })
+ .then(data => resolve(_this.rest.client.actions.MessageCreate.handle(data).m))
+ .catch(reject);
+ }
+ });
+ }
+
+ DeleteMessage(message) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true)
+ .then(data => {
+ resolve(this.rest.client.actions.MessageDelete.handle({
+ id: message.id,
+ channel_id: message.channel.id,
+ }).m);
+ })
+ .catch(reject);
+ });
+ }
+
+ UpdateMessage(message, content) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true, {
+ content,
+ })
+ .then(data => {
+ resolve(this.rest.client.actions.MessageUpdate.handle(data).updated);
+ })
+ .catch(reject);
+ });
+ }
+
+ CreateChannel(guild, channelName, channelType) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('post', Constants.Endpoints.GUILD_CHANNELS(guild.id), true, {
+ name: channelName,
+ type: channelType,
+ })
+ .then(data => {
+ resolve(this.rest.client.actions.ChannelCreate.handle(data).channel);
+ })
+ .catch(reject);
+ });
+ }
+
+ GetExistingDM(recipient) {
+ let dmChannel = this.rest.client.store.getAsArray('channels')
+ .filter(channel => channel.recipient)
+ .filter(channel => channel.recipient.id === recipient.id);
+
+ return dmChannel[0];
+ }
+
+ CreateDM(recipient) {
+ return new Promise((resolve, reject) => {
+
+ let dmChannel = this.GetExistingDM(recipient);
+
+ if (dmChannel) {
+ return resolve(dmChannel);
+ }
+
+ this.rest.makeRequest('post', Constants.Endpoints.USER_CHANNELS(this.rest.client.store.user.id), true, {
+ recipient_id: recipient.id,
+ })
+ .then(data => resolve(this.rest.client.actions.ChannelCreate.handle(data).channel))
+ .catch(reject);
+ });
+ }
+
+ DeleteChannel(channel) {
+ return new Promise((resolve, reject) => {
+ if (channel instanceof User || channel instanceof GuildMember) {
+ channel = this.GetExistingDM(channel);
+ }
+
+ this.rest.makeRequest('del', Constants.Endpoints.CHANNEL(channel.id), true)
+ .then(data => {
+ data.id = channel.id;
+ resolve(this.rest.client.actions.ChannelDelete.handle(data).channel);
+ })
+ .catch(reject);
+ });
+ }
+
+ UpdateChannel(channel, data) {
+ return new Promise((resolve, reject) => {
+ data.name = (data.name || channel.name).trim();
+ data.topic = data.topic || channel.topic;
+ data.position = data.position || channel.position;
+ data.bitrate = data.bitrate || channel.bitrate;
+
+ this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL(channel.id), true, data)
+ .then(data => {
+ resolve(this.rest.client.actions.ChannelUpdate.handle(data).updated);
+ })
+ .catch(reject);
+ });
+ }
+
+ LeaveGuild(guild) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.ME_GUILD(guild.id), true)
+ .then(() => {
+ resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild);
+ })
+ .catch(reject);
+ });
+ }
+
+ // untested but probably will work
+ DeleteGuild(guild) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.GUILD(guild.id), true)
+ .then(() => {
+ resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild);
+ })
+ .catch(reject);
+ });
+ }
+
+ UpdateCurrentUser(_data) {
+ return new Promise((resolve, reject) => {
+ let user = this.rest.client.store.user;
+ let data = {};
+
+ data.username = _data.username || user.username;
+ data.avatar = this.rest.client.resolver.ResolveBase64(_data.avatar) || user.avatar;
+ if (!user.bot) {
+ data.password = this.rest.client.store.password;
+ data.email = _data.email || this.rest.client.store.email;
+ data.new_password = _data.newPassword;
+ }
+
+ this.rest.makeRequest('patch', Constants.Endpoints.ME, true, data)
+ .then(data => resolve(this.rest.client.actions.UserUpdate.handle(data).updated))
+ .catch(reject);
+ });
+ }
+
+ UpdateGuild(guild, _data) {
+ return new Promise((resolve, reject) => {
+ /*
+ can contain:
+ name, region, verificationLevel, afkChannel, afkTimeout, icon, owner, splash
+ */
+
+ let data = {};
+
+ if (_data.name) {
+ data.name = _data.name;
+ }
+
+ if (_data.region) {
+ data.region = _data.region;
+ }
+
+ if (_data.verificationLevel) {
+ data.verification_level = Number(_data.verificationLevel);
+ }
+
+ if (_data.afkChannel) {
+ data.afk_channel_id = this.rest.client.resolver.ResolveChannel(_data.afkChannel).id;
+ }
+
+ if (_data.afkTimeout) {
+ data.afk_timeout = Number(_data.afkTimeout);
+ }
+
+ if (_data.icon) {
+ data.icon = this.rest.client.resolver.ResolveBase64(_data.icon);
+ }
+
+ if (_data.owner) {
+ data.owner_id = this.rest.client.resolver.ResolveUser(_data.owner).id;
+ }
+
+ if (_data.splash) {
+ data.splash = this.rest.client.resolver.ResolveBase64(_data.splash);
+ }
+
+ this.rest.makeRequest('patch', Constants.Endpoints.GUILD(guild.id), true, data)
+ .then(data => resolve(this.rest.client.actions.GuildUpdate.handle(data).updated))
+ .catch(reject);
+ });
+ }
+
+ KickGuildMember(guild, member) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.GUILD_MEMBER(guild.id, member.id), true)
+ .then(() => {
+ resolve(this.rest.client.actions.GuildMemberRemove.handle({
+ guild_id : guild.id,
+ user : member.user,
+ }).m);
+ })
+ .catch(reject);
+ });
+ }
+
+ CreateGuildRole(guild) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('post', Constants.Endpoints.GUILD_ROLES(guild.id), true)
+ .then(role => {
+ resolve(this.rest.client.actions.GuildRoleCreate.handle({
+ guild_id : guild.id,
+ role,
+ }).role);
+ })
+ .catch(reject);
+ });
+ }
+}
+
+module.exports = RESTMethods;
diff --git a/src/client/websocket/packets/handlers/GuildRoleCreate.js b/src/client/websocket/packets/handlers/GuildRoleCreate.js
index 8f8666089..c2ffdbb43 100644
--- a/src/client/websocket/packets/handlers/GuildRoleCreate.js
+++ b/src/client/websocket/packets/handlers/GuildRoleCreate.js
@@ -17,18 +17,7 @@ class GuildRoleCreateHandler extends AbstractHandler {
let data = packet.d;
let client = this.packetManager.client;
- let guild = client.store.get('guilds', data.guild_id);
-
- if (guild) {
- let already = guild.store.get('roles', data.role.id);
- let role = new Role(guild, data.role);
- guild.store.add('roles', role);
-
- if (!already) {
- client.emit(Constants.Events.GUILD_ROLE_CREATE, guild, role);
- }
- }
-
+ let response = client.actions.GuildRoleCreate.handle(data);
}
};
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index a4607e03f..b5bd9f5b3 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -180,6 +180,10 @@ class Guild {
return this.client.rest.methods.CreateChannel(this, name, type);
}
+ createRole() {
+ return this.client.rest.methods.CreateGuildRole(this);
+ }
+
leave() {
return this.client.rest.methods.LeaveGuild(this);
}
diff --git a/test/random.js b/test/random.js
index dfe96f699..d61ea9653 100644
--- a/test/random.js
+++ b/test/random.js
@@ -135,6 +135,11 @@ client.on('message', message => {
}).catch(console.log);
}
+ if (message.content === 'makerole') {
+ message.guild.createRole().then(role => {
+ message.channel.sendMessage(`Made role ${role.name}`);
+ }).catch(console.log);
+ }
}
});
From 3cd91a19aae83082e9b3db0572ef16ce7ed8c067 Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sun, 3 Jul 2016 13:04:39 +0100
Subject: [PATCH 040/324] Added role.delete()
---
src/client/Client.js | 84 +++++++++----------
src/client/actions/ActionsManager.js | 1 +
src/client/actions/GuildMemberRemove.js | 1 +
src/client/actions/GuildRoleDelete.js | 50 +++++++++++
src/client/rest/RESTMethods.js | 19 ++++-
.../packets/handlers/GuildMemberRemove.js | 4 -
.../packets/handlers/GuildRoleDelete.js | 59 ++++++-------
src/structures/Role.js | 4 +
src/util/Constants.js | 1 +
test/random.js | 1 +
10 files changed, 141 insertions(+), 83 deletions(-)
create mode 100644 src/client/actions/GuildRoleDelete.js
diff --git a/src/client/Client.js b/src/client/Client.js
index b51ac03e6..bd3ba133f 100644
--- a/src/client/Client.js
+++ b/src/client/Client.js
@@ -1,42 +1,42 @@
-'use strict';
-
-const EventEmitter = require('events').EventEmitter;
-const MergeDefault = require('../util/MergeDefault');
-const Constants = require('../util/Constants');
-const RESTManager = require('./rest/RestManager');
-const ClientDataStore = require('../structures/DataStore/ClientDataStore');
-const ClientManager = require('./ClientManager');
-const ClientDataResolver = require('./ClientDataResolver');
-const WebSocketManager = require('./websocket/WebSocketManager');
-const ActionsManager = require('./actions/ActionsManager');
-
-class Client extends EventEmitter{
-
- constructor(options) {
- super();
- this.options = MergeDefault(Constants.DefaultOptions, options);
- this.rest = new RESTManager(this);
- this.store = new ClientDataStore(this);
- this.manager = new ClientManager(this);
- this.ws = new WebSocketManager(this);
- this.resolver = new ClientDataResolver(this);
- this.actions = new ActionsManager(this);
- }
-
- login(email, password) {
- if (password) {
- // login with email and password
- return this.rest.methods.LoginEmailPassword(email, password);
- } else {
- // login with token
- return this.rest.methods.LoginToken(email);
- }
- }
-
- get user() {
- return this.store.user;
- }
-
-}
-
-module.exports = Client;
+'use strict';
+
+const EventEmitter = require('events').EventEmitter;
+const MergeDefault = require('../util/MergeDefault');
+const Constants = require('../util/Constants');
+const RESTManager = require('./rest/RestManager');
+const ClientDataStore = require('../structures/DataStore/ClientDataStore');
+const ClientManager = require('./ClientManager');
+const ClientDataResolver = require('./ClientDataResolver');
+const WebSocketManager = require('./websocket/WebSocketManager');
+const ActionsManager = require('./actions/ActionsManager');
+
+class Client extends EventEmitter{
+
+ constructor(options) {
+ super();
+ this.options = MergeDefault(Constants.DefaultOptions, options);
+ this.rest = new RESTManager(this);
+ this.store = new ClientDataStore(this);
+ this.manager = new ClientManager(this);
+ this.ws = new WebSocketManager(this);
+ this.resolver = new ClientDataResolver(this);
+ this.actions = new ActionsManager(this);
+ }
+
+ login(email, password) {
+ if (password) {
+ // login with email and password
+ return this.rest.methods.LoginEmailPassword(email, password);
+ } else {
+ // login with token
+ return this.rest.methods.LoginToken(email);
+ }
+ }
+
+ get user() {
+ return this.store.user;
+ }
+
+}
+
+module.exports = Client;
diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js
index 51d4fdebc..e275963b9 100644
--- a/src/client/actions/ActionsManager.js
+++ b/src/client/actions/ActionsManager.js
@@ -16,6 +16,7 @@ class ActionsManager {
this.register('GuildUpdate');
this.register('GuildMemberRemove');
this.register('GuildRoleCreate');
+ this.register('GuildRoleDelete');
this.register('UserUpdate');
}
diff --git a/src/client/actions/GuildMemberRemove.js b/src/client/actions/GuildMemberRemove.js
index d9ddf62c7..7ef912467 100644
--- a/src/client/actions/GuildMemberRemove.js
+++ b/src/client/actions/GuildMemberRemove.js
@@ -20,6 +20,7 @@ class GuildMemberRemoveAction extends Action {
if (member) {
guild._removeMember(member);
this.deleted[guild.id + data.user.id] = member;
+ client.emit(Constants.Events.GUILD_MEMBER_REMOVE, guild, member);
this.scheduleForDeletion(guild.id, data.user.id);
}
diff --git a/src/client/actions/GuildRoleDelete.js b/src/client/actions/GuildRoleDelete.js
new file mode 100644
index 000000000..687305b30
--- /dev/null
+++ b/src/client/actions/GuildRoleDelete.js
@@ -0,0 +1,50 @@
+'use strict';
+
+const Action = require('./Action');
+const Constants = require('../../util/Constants');
+const Message = require('../../structures/Message');
+
+class GuildRoleDeleteAction extends Action {
+
+ constructor(client) {
+ super(client);
+ this.timeouts = [];
+ this.deleted = {};
+ }
+
+ handle(data) {
+ let client = this.client;
+ let guild = client.store.get('guilds', data.guild_id);
+
+ if (guild) {
+ let exists = guild.store.get('roles', data.role_id);
+ if (exists) {
+ guild.store.remove('roles', data.role_id);
+ this.deleted[guild.id + data.role_id] = exists;
+ this.scheduleForDeletion(guild.id, data.role_id);
+ client.emit(Constants.Events.GUILD_ROLE_DELETE, guild, exists);
+ }
+
+ if (!exists) {
+ exists = this.deleted[guild.id + data.role_id];
+ }
+
+ return {
+ role: exists,
+ };
+ }
+
+ return {
+ role: null,
+ };
+ }
+
+ scheduleForDeletion(guildID, roleID) {
+ this.timeouts.push(
+ setTimeout(() => delete this.deleted[guildID + roleID],
+ this.client.options.rest_ws_bridge_timeout)
+ );
+ }
+};
+
+module.exports = GuildRoleDeleteAction;
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index e8f05cde3..43eaeb9d6 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -248,8 +248,8 @@ class RESTMethods{
this.rest.makeRequest('del', Constants.Endpoints.GUILD_MEMBER(guild.id, member.id), true)
.then(() => {
resolve(this.rest.client.actions.GuildMemberRemove.handle({
- guild_id : guild.id,
- user : member.user,
+ guild_id: guild.id,
+ user: member.user,
}).m);
})
.catch(reject);
@@ -261,13 +261,26 @@ class RESTMethods{
this.rest.makeRequest('post', Constants.Endpoints.GUILD_ROLES(guild.id), true)
.then(role => {
resolve(this.rest.client.actions.GuildRoleCreate.handle({
- guild_id : guild.id,
+ guild_id: guild.id,
role,
}).role);
})
.catch(reject);
});
}
+
+ DeleteGuildRole(role) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.GUILD_ROLE(role.guild.id, role.id), true)
+ .then(() => {
+ resolve(this.rest.client.actions.GuildRoleDelete.handle({
+ guild_id: role.guild.id,
+ role_id: role.id,
+ }).role);
+ })
+ .catch(reject);
+ });
+ }
}
module.exports = RESTMethods;
diff --git a/src/client/websocket/packets/handlers/GuildMemberRemove.js b/src/client/websocket/packets/handlers/GuildMemberRemove.js
index 185cb768c..cf61c816b 100644
--- a/src/client/websocket/packets/handlers/GuildMemberRemove.js
+++ b/src/client/websocket/packets/handlers/GuildMemberRemove.js
@@ -21,10 +21,6 @@ class GuildMemberRemoveHandler extends AbstractHandler {
let client = this.packetManager.client;
let response = client.actions.GuildMemberRemove.handle(data);
-
- if (response.m) {
- client.emit(Constants.Events.GUILD_MEMBER_REMOVE, response.g, response.m);
- }
}
};
diff --git a/src/client/websocket/packets/handlers/GuildRoleDelete.js b/src/client/websocket/packets/handlers/GuildRoleDelete.js
index 002d2321e..2214a7982 100644
--- a/src/client/websocket/packets/handlers/GuildRoleDelete.js
+++ b/src/client/websocket/packets/handlers/GuildRoleDelete.js
@@ -1,34 +1,25 @@
-'use strict';
-
-const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-const Constants = require('../../../../util/Constants');
-
-const Role = Structure('Role');
-const Guild = Structure('Guild');
-
-class GuildRoleDeleteHandler extends AbstractHandler {
-
- constructor(packetManager) {
- super(packetManager);
- }
-
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
-
- let guild = client.store.get('guilds', data.guild_id);
-
- if (guild) {
- let exists = guild.store.get('roles', data.role_id);
- if (exists) {
- guild.store.remove('roles', data.role_id);
- client.emit(Constants.Events.GUILD_ROLE_DELETE, guild, exists);
- }
- }
-
- }
-
-};
-
-module.exports = GuildRoleDeleteHandler;
+'use strict';
+
+const AbstractHandler = require('./AbstractHandler');
+const Structure = name => require(`../../../../structures/${name}`);
+const Constants = require('../../../../util/Constants');
+
+const Role = Structure('Role');
+const Guild = Structure('Guild');
+
+class GuildRoleDeleteHandler extends AbstractHandler {
+
+ constructor(packetManager) {
+ super(packetManager);
+ }
+
+ handle(packet) {
+ let data = packet.d;
+ let client = this.packetManager.client;
+
+ let response = client.actions.GuildRoleDelete.handle(data);
+ }
+
+};
+
+module.exports = GuildRoleDeleteHandler;
diff --git a/src/structures/Role.js b/src/structures/Role.js
index 5d8a7dfa8..864f4ccf6 100644
--- a/src/structures/Role.js
+++ b/src/structures/Role.js
@@ -21,6 +21,10 @@ class Role {
this.managed = data.managed;
}
+ delete() {
+ return this.client.rest.methods.DeleteGuildRole(this);
+ }
+
serialize() {
let serializedPermissions = {};
for (let permissionName in Constants.PermissionFlags) {
diff --git a/src/util/Constants.js b/src/util/Constants.js
index e03fdf105..daf082231 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -55,6 +55,7 @@ const Endpoints = exports.Endpoints = {
GUILD_EMBED: (guildID) => `${Endpoints.GUILD(guildID)}/embed`,
GUILD_INVITES: (guildID) => `${Endpoints.GUILD(guildID)}/invites`,
GUILD_ROLES: (guildID) => `${Endpoints.GUILD(guildID)}/roles`,
+ GUILD_ROLE: (guildID, roleID) => `${Endpoints.GUILD_ROLES(guildID)}/${roleID}`,
GUILD_BANS: (guildID) => `${Endpoints.GUILD(guildID)}/bans`,
GUILD_INTEGRATIONS: (guildID) => `${Endpoints.GUILD(guildID)}/integrations`,
GUILD_MEMBERS: (guildID) => `${Endpoints.GUILD(guildID)}/members`,
diff --git a/test/random.js b/test/random.js
index d61ea9653..f84b2865e 100644
--- a/test/random.js
+++ b/test/random.js
@@ -41,6 +41,7 @@ client.on('guildMemberRemove', (guild, user) => {
client.on('guildRoleCreate', (guild, role) => {
console.log('new role', role.name, 'in', guild.name);
+ role.delete().then(role => console.log("deleted " + role.name)).catch(console.log);
});
client.on('guildRoleDelete', (guild, role) => {
From 0d53afe3cec95bd4f4df51d186b860468d349cd6 Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sun, 3 Jul 2016 16:27:04 +0100
Subject: [PATCH 041/324] Added ability to edit a role
---
src/client/actions/ActionsManager.js | 1 +
src/client/actions/GuildRoleUpdate.js | 44 +++++++++++++++++++
src/client/rest/RESTMethods.js | 43 ++++++++++++++++++
.../packets/handlers/GuildRoleUpdate.js | 12 +----
src/structures/Role.js | 36 +++++++++++++++
test/random.js | 7 ++-
6 files changed, 131 insertions(+), 12 deletions(-)
create mode 100644 src/client/actions/GuildRoleUpdate.js
diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js
index e275963b9..850c052d1 100644
--- a/src/client/actions/ActionsManager.js
+++ b/src/client/actions/ActionsManager.js
@@ -17,6 +17,7 @@ class ActionsManager {
this.register('GuildMemberRemove');
this.register('GuildRoleCreate');
this.register('GuildRoleDelete');
+ this.register('GuildRoleUpdate');
this.register('UserUpdate');
}
diff --git a/src/client/actions/GuildRoleUpdate.js b/src/client/actions/GuildRoleUpdate.js
new file mode 100644
index 000000000..61b269240
--- /dev/null
+++ b/src/client/actions/GuildRoleUpdate.js
@@ -0,0 +1,44 @@
+'use strict';
+
+const Action = require('./Action');
+const Constants = require('../../util/Constants');
+const CloneObject = require('../../util/CloneObject');
+const Message = require('../../structures/Message');
+
+class GuildRoleUpdateAction extends Action {
+
+ constructor(client) {
+ super(client);
+ }
+
+ handle(data) {
+
+ let client = this.client;
+ let guild = client.store.get('guilds', data.guild_id);
+
+ let roleData = data.role;
+
+ if (guild) {
+ let oldRole;
+ let existingRole = guild.store.get('roles', roleData.id);
+ // exists and not the same
+ if (existingRole && !existingRole.equals(roleData)) {
+ oldRole = CloneObject(existingRole);
+ existingRole.setup(data.role);
+ client.emit(Constants.Events.GUILD_ROLE_UPDATE, guild, oldRole, existingRole);
+ }
+
+ return {
+ old: oldRole,
+ updated: existingRole,
+ };
+ }
+
+ return {
+ old: null,
+ updated: null,
+ };
+ }
+};
+
+module.exports = GuildRoleUpdateAction;
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index 43eaeb9d6..5ddf95198 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -281,6 +281,49 @@ class RESTMethods{
.catch(reject);
});
}
+
+ UpdateGuildRole(role, _data) {
+ return new Promise((resolve, reject) => {
+ /*
+ can contain:
+ name, position, permissions, color, hoist
+ */
+
+ let data = {};
+
+ data.name = _data.name || role.name;
+ data.position = _data.position || role.position;
+ data.color = _data.color || role.color;
+
+ if (typeof _data.hoist !== 'undefined') {
+ data.hoist = _data.hoist;
+ } else {
+ data.hoist = role.hoist;
+ }
+
+ if (_data.permissions) {
+ let perms = 0;
+ for (let perm of _data.permissions) {
+ if (perm instanceof String || typeof perm === 'string') {
+ perm = Constants.PermissionFlags[perm];
+ }
+ perms |= perm;
+ }
+ data.permissions = perms;
+ } else {
+ data.permissions = role.permissions;
+ }
+ console.log(data);
+ this.rest.makeRequest('patch', Constants.Endpoints.GUILD_ROLE(role.guild.id, role.id), true, data)
+ .then(_role => {
+ resolve(this.rest.client.actions.GuildRoleUpdate.handle({
+ role: _role,
+ guild_id: role.guild.id,
+ }).updated);
+ })
+ .catch(reject);
+ });
+ }
}
module.exports = RESTMethods;
diff --git a/src/client/websocket/packets/handlers/GuildRoleUpdate.js b/src/client/websocket/packets/handlers/GuildRoleUpdate.js
index 72799a0ea..98005bc02 100644
--- a/src/client/websocket/packets/handlers/GuildRoleUpdate.js
+++ b/src/client/websocket/packets/handlers/GuildRoleUpdate.js
@@ -18,17 +18,7 @@ class GuildRoleUpdateHandler extends AbstractHandler {
let data = packet.d;
let client = this.packetManager.client;
- let guild = client.store.get('guilds', data.guild_id);
-
- if (guild) {
- let existingRole = guild.store.get('roles', data.role.id);
- if (existingRole) {
- let oldRole = CloneObject(existingRole);
- existingRole.setup(data.role);
- client.emit(Constants.Events.GUILD_ROLE_UPDATE, guild, oldRole, existingRole);
- }
- }
-
+ let response = client.actions.GuildRoleUpdate.handle(data);
}
};
diff --git a/src/structures/Role.js b/src/structures/Role.js
index 864f4ccf6..f163ff98e 100644
--- a/src/structures/Role.js
+++ b/src/structures/Role.js
@@ -11,6 +11,18 @@ class Role {
}
}
+ equals(role) {
+ return (
+ 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
+ );
+ }
+
setup(data) {
this.id = data.id;
this.name = data.name;
@@ -25,6 +37,30 @@ class Role {
return this.client.rest.methods.DeleteGuildRole(this);
}
+ edit(data) {
+ return this.client.rest.methods.UpdateGuildRole(this, data);
+ }
+
+ setName(name) {
+ return this.client.rest.methods.UpdateGuildRole(this, {name,});
+ }
+
+ setColor(color) {
+ return this.client.rest.methods.UpdateGuildRole(this, {color,});
+ }
+
+ setHoist(hoist) {
+ return this.client.rest.methods.UpdateGuildRole(this, {hoist,});
+ }
+
+ setPosition(position) {
+ return this.client.rest.methods.UpdateGuildRole(this, {position,});
+ }
+
+ setPermissions(permissions) {
+ return this.client.rest.methods.UpdateGuildRole(this, {permissions,});
+ }
+
serialize() {
let serializedPermissions = {};
for (let permissionName in Constants.PermissionFlags) {
diff --git a/test/random.js b/test/random.js
index f84b2865e..a1de4025f 100644
--- a/test/random.js
+++ b/test/random.js
@@ -41,7 +41,12 @@ client.on('guildMemberRemove', (guild, user) => {
client.on('guildRoleCreate', (guild, role) => {
console.log('new role', role.name, 'in', guild.name);
- role.delete().then(role => console.log("deleted " + role.name)).catch(console.log);
+ role.edit({
+ permissions: ['DEAFEN_MEMBERS'],
+ name: 'deafen'
+ }).then(role2 => {
+ console.log('role replace from ' + role.name + ' to ' + role2.name);
+ }).catch(console.log)
});
client.on('guildRoleDelete', (guild, role) => {
From 53d767ec040b0bcf68f59b8fe9e1e42ea60d6b9f Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sat, 13 Aug 2016 12:25:01 +0100
Subject: [PATCH 042/324] some doc stuff idk
---
src/client/Client.js | 22 ++++++++++++++++++++++
src/structures/User.js | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 57 insertions(+)
diff --git a/src/client/Client.js b/src/client/Client.js
index bd3ba133f..b47fba0c7 100644
--- a/src/client/Client.js
+++ b/src/client/Client.js
@@ -10,6 +10,13 @@ const ClientDataResolver = require('./ClientDataResolver');
const WebSocketManager = require('./websocket/WebSocketManager');
const ActionsManager = require('./actions/ActionsManager');
+/**
+ * Creates a new Discord Client
+ * ```js
+ * const Discord = require("discord.js");
+ * const client = new Discord.Client();
+ * ```
+ */
class Client extends EventEmitter{
constructor(options) {
@@ -23,6 +30,17 @@ class Client extends EventEmitter{
this.actions = new ActionsManager(this);
}
+ /**
+ * Logs the client in. If successful, resolves with the account's token.
+ * @param {string} emailOrToken The email or token used for the account. If it is an email, a password _must_ be
+ * provided.
+ * @param {string} [password] The password for the account, only needed if an email was provided.
+ * @return {Promise}
+ * @example
+ * client.login("token");
+ * // or
+ * client.login("email", "password");
+ */
login(email, password) {
if (password) {
// login with email and password
@@ -33,6 +51,10 @@ class Client extends EventEmitter{
}
}
+ /**
+ * The User of the logged in Client, only available after `READY` has been fired.
+ * @return {ClientUser} [description]
+ */
get user() {
return this.store.user;
}
diff --git a/src/structures/User.js b/src/structures/User.js
index e635f4937..2563fccb2 100644
--- a/src/structures/User.js
+++ b/src/structures/User.js
@@ -2,6 +2,9 @@
const TextBasedChannel = require('./interface/TextBasedChannel');
+/**
+ * Represents a User on Discord.
+ */
class User {
constructor(client, data) {
this.client = client;
@@ -11,11 +14,39 @@ class User {
}
setup(data) {
+ /**
+ * The username of the User
+ * @type {String}
+ */
this.username = data.username;
+ /**
+ * The ID of the User
+ * @type {String}
+ */
this.id = data.id;
+ /**
+ * 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:
+ *
+ * * **`online`** - user is online
+ * * **`offline`** - user is offline
+ * * **`idle`** - user is AFK
+ * @type {String}
+ */
this.status = data.status || this.status || 'offline';
this.game = data.game || this.game;
}
@@ -24,6 +55,10 @@ class User {
return `<@${this.id}>`;
}
+ /**
+ * Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.
+ * @return {Promise}
+ */
deleteDM() {
return this.client.rest.methods.DeleteChannel(this);
}
From b8db4c4f4b6c7353a72d059c0ba5a2a136e7bc9a Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sat, 13 Aug 2016 14:44:49 +0100
Subject: [PATCH 043/324] ESLint stuff...
---
.eslintrc.js | 16 +
package.json | 115 ++--
src/client/Client.js | 125 ++--
src/client/ClientDataResolver.js | 132 ++---
src/client/ClientManager.js | 46 +-
src/client/actions/Action.js | 16 +-
src/client/actions/ActionsManager.js | 58 +-
src/client/actions/ChannelCreate.js | 24 +-
src/client/actions/ChannelDelete.js | 80 ++-
src/client/actions/ChannelUpdate.js | 50 +-
src/client/actions/GuildDelete.js | 79 ++-
src/client/actions/GuildMemberRemove.js | 75 ++-
src/client/actions/GuildRoleCreate.js | 45 +-
src/client/actions/GuildRoleDelete.js | 71 ++-
src/client/actions/GuildRoleUpdate.js | 58 +-
src/client/actions/GuildUpdate.js | 56 +-
src/client/actions/MessageCreate.js | 36 +-
src/client/actions/MessageDelete.js | 72 +--
src/client/actions/MessageUpdate.js | 60 +-
src/client/actions/UserUpdate.js | 56 +-
src/client/rest/RESTManager.js | 163 ++---
src/client/rest/RESTMethods.js | 559 +++++++++---------
src/client/rest/UserAgentManager.js | 32 +-
src/client/websocket/WebSocketManager.js | 180 +++---
.../packets/WebSocketPacketManager.js | 153 +++--
.../packets/handlers/AbstractHandler.js | 14 +-
.../packets/handlers/ChannelCreate.js | 30 +-
.../packets/handlers/ChannelDelete.js | 29 +-
.../packets/handlers/ChannelUpdate.js | 42 +-
.../websocket/packets/handlers/GuildBanAdd.js | 31 +-
.../packets/handlers/GuildBanRemove.js | 30 +-
.../websocket/packets/handlers/GuildCreate.js | 45 +-
.../websocket/packets/handlers/GuildDelete.js | 30 +-
.../packets/handlers/GuildMemberAdd.js | 30 +-
.../packets/handlers/GuildMemberRemove.js | 24 +-
.../packets/handlers/GuildMemberUpdate.js | 36 +-
.../packets/handlers/GuildMembersChunk.js | 34 +-
.../packets/handlers/GuildRoleCreate.js | 23 +-
.../packets/handlers/GuildRoleDelete.js | 39 +-
.../packets/handlers/GuildRoleUpdate.js | 24 +-
.../websocket/packets/handlers/GuildUpdate.js | 26 +-
.../packets/handlers/MessageCreate.js | 28 +-
.../packets/handlers/MessageDelete.js | 28 +-
.../packets/handlers/MessageUpdate.js | 25 +-
.../packets/handlers/PresenceUpdate.js | 111 ++--
.../websocket/packets/handlers/Ready.js | 43 +-
.../websocket/packets/handlers/TypingStart.js | 82 ++-
.../websocket/packets/handlers/UserUpdate.js | 26 +-
.../packets/handlers/VoiceStateUpdate.js | 57 +-
src/index.js | 4 +-
src/structures/Channel.js | 36 +-
src/structures/ClientUser.js | 46 +-
src/structures/DMChannel.js | 52 +-
src/structures/EvaluatedPermissions.js | 54 +-
src/structures/Guild.js | 374 ++++++------
src/structures/GuildMember.js | 106 ++--
src/structures/Message.js | 198 ++++---
src/structures/PermissionOverwrites.js | 26 +-
src/structures/Role.js | 142 +++--
src/structures/ServerChannel.js | 232 ++++----
src/structures/TextChannel.js | 34 +-
src/structures/User.js | 144 +++--
src/structures/VoiceChannel.js | 18 +-
src/structures/datastore/AbstractDataStore.js | 65 +-
src/structures/datastore/ClientDataStore.js | 161 +++--
src/structures/datastore/GuildDataStore.js | 14 +-
.../datastore/TextChannelDataStore.js | 12 +-
.../datastore/VoiceChannelDataStore.js | 12 +-
.../datastore/WebSocketManagerDataStore.js | 16 +-
src/structures/interface/TextBasedChannel.js | 15 +-
src/util/CloneObject.js | 9 +-
src/util/Constants.js | 304 +++++-----
src/util/MergeDefault.js | 26 +-
test/random.js | 186 +++---
74 files changed, 2574 insertions(+), 2956 deletions(-)
create mode 100644 .eslintrc.js
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 000000000..2ea4a252b
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,16 @@
+module.exports = {
+ "extends": "airbnb",
+ "plugins": [
+ "react",
+ "jsx-a11y",
+ "import"
+ ],
+ "rules" : {
+ "max-len": [2, 120, 2],
+ "no-underscore-dangle": 0,
+ "global-require": 0,
+ "guard-for-in": 0,
+ "no-restricted-syntax": 0,
+ "no-param-reassign": 0,
+ }
+};
\ No newline at end of file
diff --git a/package.json b/package.json
index 36d8e745e..09f090512 100644
--- a/package.json
+++ b/package.json
@@ -1,55 +1,60 @@
-{
- "name": "discord.js",
- "version": "7.0.0",
- "description": "A way to interface with the Discord API",
- "main": "./src/index",
- "scripts": {
- "test": "jscs src && node test/random"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/hydrabolt/discord.js.git"
- },
- "keywords": [
- "discord",
- "api",
- "bot",
- "client",
- "node",
- "discordapp"
- ],
- "author": "Amish Shah ",
- "license": "Apache-2.0",
- "bugs": {
- "url": "https://github.com/hydrabolt/discord.js/issues"
- },
- "homepage": "https://github.com/hydrabolt/discord.js#readme",
- "dependencies": {
- "babel-plugin-transform-runtime": "^6.6.0",
- "object.values": "^1.0.3",
- "superagent": "^1.5.0",
- "unpipe": "^1.0.0",
- "ws": "^0.8.1"
- },
- "devDependencies": {
- "babel-preset-es2015": "^6.6.0",
- "babel-preset-stage-3": "^6.5.0",
- "grunt": "^0.4.5",
- "grunt-babel": "^6.0.0",
- "grunt-browserify": "^4.0.1",
- "grunt-contrib-uglify": "^0.11.0",
- "grunt-jscs": "^2.8.0",
- "jscs": "^2.11.0",
- "load-grunt-tasks": "^3.3.0"
- },
- "optionalDependencies": {
- "node-opus": "^0.1.11"
- },
- "engines": {
- "node": ">=0.12.7"
- },
- "browser": {
- "./src/Util/TokenCacher.js": "./src/Util/TokenCacher-shim.js",
- "./lib/Util/TokenCacher.js": "./lib/Util/TokenCacher-shim.js"
- }
-}
+{
+ "name": "discord.js",
+ "version": "7.0.0",
+ "description": "A way to interface with the Discord API",
+ "main": "./src/index",
+ "scripts": {
+ "test": "node test/random"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/hydrabolt/discord.js.git"
+ },
+ "keywords": [
+ "discord",
+ "api",
+ "bot",
+ "client",
+ "node",
+ "discordapp"
+ ],
+ "author": "Amish Shah ",
+ "license": "Apache-2.0",
+ "bugs": {
+ "url": "https://github.com/hydrabolt/discord.js/issues"
+ },
+ "homepage": "https://github.com/hydrabolt/discord.js#readme",
+ "dependencies": {
+ "babel-plugin-transform-runtime": "^6.6.0",
+ "object.values": "^1.0.3",
+ "superagent": "^1.5.0",
+ "unpipe": "^1.0.0",
+ "ws": "^0.8.1"
+ },
+ "devDependencies": {
+ "babel-preset-es2015": "^6.6.0",
+ "babel-preset-stage-3": "^6.5.0",
+ "eslint": "^3.3.0",
+ "eslint-config-airbnb": "^10.0.1",
+ "eslint-plugin-import": "^1.13.0",
+ "eslint-plugin-jsx-a11y": "^2.1.0",
+ "eslint-plugin-react": "^6.0.0",
+ "grunt": "^0.4.5",
+ "grunt-babel": "^6.0.0",
+ "grunt-browserify": "^4.0.1",
+ "grunt-contrib-uglify": "^0.11.0",
+ "grunt-jscs": "^2.8.0",
+ "jscs": "^2.11.0",
+ "load-grunt-tasks": "^3.3.0"
+ },
+ "optionalDependencies": {
+ "node-opus": "^0.1.11"
+ },
+ "engines": {
+ "node": ">=0.12.7"
+ },
+ "browser": {
+ "./src/Util/TokenCacher.js": "./src/Util/TokenCacher-shim.js",
+ "./lib/Util/TokenCacher.js": "./lib/Util/TokenCacher-shim.js"
+ }
+}
diff --git a/src/client/Client.js b/src/client/Client.js
index b47fba0c7..52ed353a2 100644
--- a/src/client/Client.js
+++ b/src/client/Client.js
@@ -1,64 +1,61 @@
-'use strict';
-
-const EventEmitter = require('events').EventEmitter;
-const MergeDefault = require('../util/MergeDefault');
-const Constants = require('../util/Constants');
-const RESTManager = require('./rest/RestManager');
-const ClientDataStore = require('../structures/DataStore/ClientDataStore');
-const ClientManager = require('./ClientManager');
-const ClientDataResolver = require('./ClientDataResolver');
-const WebSocketManager = require('./websocket/WebSocketManager');
-const ActionsManager = require('./actions/ActionsManager');
-
-/**
- * Creates a new Discord Client
- * ```js
- * const Discord = require("discord.js");
- * const client = new Discord.Client();
- * ```
- */
-class Client extends EventEmitter{
-
- constructor(options) {
- super();
- this.options = MergeDefault(Constants.DefaultOptions, options);
- this.rest = new RESTManager(this);
- this.store = new ClientDataStore(this);
- this.manager = new ClientManager(this);
- this.ws = new WebSocketManager(this);
- this.resolver = new ClientDataResolver(this);
- this.actions = new ActionsManager(this);
- }
-
- /**
- * Logs the client in. If successful, resolves with the account's token.
- * @param {string} emailOrToken The email or token used for the account. If it is an email, a password _must_ be
- * provided.
- * @param {string} [password] The password for the account, only needed if an email was provided.
- * @return {Promise}
- * @example
- * client.login("token");
- * // or
- * client.login("email", "password");
- */
- login(email, password) {
- if (password) {
- // login with email and password
- return this.rest.methods.LoginEmailPassword(email, password);
- } else {
- // login with token
- return this.rest.methods.LoginToken(email);
- }
- }
-
- /**
- * The User of the logged in Client, only available after `READY` has been fired.
- * @return {ClientUser} [description]
- */
- get user() {
- return this.store.user;
- }
-
-}
-
-module.exports = Client;
+const EventEmitter = require('events').EventEmitter;
+const mergeDefault = require('../util/MergeDefault');
+const Constants = require('../util/Constants');
+const RESTManager = require('./rest/RESTManager');
+const ClientDataStore = require('../structures/datastore/ClientDataStore');
+const ClientManager = require('./ClientManager');
+const ClientDataResolver = require('./ClientDataResolver');
+const WebSocketManager = require('./websocket/WebSocketManager');
+const ActionsManager = require('./actions/ActionsManager');
+
+/**
+ * Creates a new Discord Client
+ * ```js
+ * const Discord = require("discord.js");
+ * const client = new Discord.Client();
+ * ```
+ */
+class Client extends EventEmitter {
+
+ constructor(options) {
+ super();
+ this.options = mergeDefault(Constants.DefaultOptions, options);
+ this.rest = new RESTManager(this);
+ this.store = new ClientDataStore(this);
+ this.manager = new ClientManager(this);
+ this.ws = new WebSocketManager(this);
+ this.resolver = new ClientDataResolver(this);
+ this.actions = new ActionsManager(this);
+ }
+
+ /**
+ * Logs the client in. If successful, resolves with the account's token.
+ * @param {string} emailOrToken The email or token used for the account. If it is an email, a password _must_ be
+ * provided.
+ * @param {string} [password] The password for the account, only needed if an email was provided.
+ * @return {Promise}
+ * @example
+ * client.login("token");
+ * // or
+ * client.login("email", "password");
+ */
+ login(email, password) {
+ if (password) {
+ // login with email and password
+ return this.rest.methods.loginEmailPassword(email, password);
+ }
+ // login with token
+ return this.rest.methods.loginToken(email);
+ }
+
+ /**
+ * The User of the logged in Client, only available after `READY` has been fired.
+ * @return {ClientUser} [description]
+ */
+ get user() {
+ return this.store.user;
+ }
+
+}
+
+module.exports = Client;
diff --git a/src/client/ClientDataResolver.js b/src/client/ClientDataResolver.js
index fc65010cf..e7003f468 100644
--- a/src/client/ClientDataResolver.js
+++ b/src/client/ClientDataResolver.js
@@ -1,90 +1,90 @@
-'use strict';
+const getStructure = name => require(`../structures/${name}`);
-const Structure = name => require(`../structures/${name}`);
-
-const User = Structure('User');
-const Message = Structure('Message');
-const Guild = Structure('Guild');
-const Channel = Structure('Channel');
-const ServerChannel = Structure('ServerChannel');
-const TextChannel = Structure('TextChannel');
-const VoiceChannel = Structure('VoiceChannel');
-const GuildMember = Structure('GuildMember');
+const User = getStructure('User');
+const Message = getStructure('Message');
+const Guild = getStructure('Guild');
+const Channel = getStructure('Channel');
+const GuildMember = getStructure('GuildMember');
function $string(obj) {
- return (typeof obj === 'string' || obj instanceof String);
+ return (typeof obj === 'string' || obj instanceof String);
}
class ClientDataResolver {
- constructor(client) {
- this.client = client;
- }
+ constructor(client) {
+ this.client = client;
+ }
- ResolveUser(user) {
- if (user instanceof User) {
- return user;
- }else if ($string(user)) {
- return this.client.store.get('users', user);
- }else if (user instanceof Message) {
- return user.author;
- }else if (user instanceof Guild) {
- return user.owner;
- }
+ resolveUser(user) {
+ if (user instanceof User) {
+ return user;
+ } else if ($string(user)) {
+ return this.client.store.get('users', user);
+ } else if (user instanceof Message) {
+ return user.author;
+ } else if (user instanceof Guild) {
+ return user.owner;
+ }
- return null;
- }
+ return null;
+ }
- ResolveGuild(guild) {
- if (guild instanceof Guild) {
- return guild;
- }
- }
+ resolveGuild(guild) {
+ if (guild instanceof Guild) {
+ return guild;
+ }
+ return null;
+ }
- ResolveGuildMember(guild, user) {
- if (user instanceof GuildMember) {
- return user;
- }
+ resolveGuildMember($guild, $user) {
+ let guild = $guild;
+ let user = $user;
+ if (user instanceof GuildMember) {
+ return user;
+ }
- guild = this.ResolveGuild(guild);
- user = this.ResolveUser(user);
+ guild = this.resolveGuild(guild);
+ user = this.resolveUser(user);
- if (!guild || !user) {
- return null;
- }
+ if (!guild || !user) {
+ return null;
+ }
- return guild.store.get('members', user.id);
- }
+ return guild.store.get('members', user.id);
+ }
- ResolveBase64(data) {
- if (data instanceof Buffer) {
- return 'data:image/jpg;base64,' + data.toString('base64');
- }
+ resolveBase64(data) {
+ if (data instanceof Buffer) {
+ return `data:image/jpg;base64,${data.toString('base64')}`;
+ }
- return data;
- }
+ return data;
+ }
- ResolveChannel(channel) {
- if (channel instanceof Channel) {
- return channel;
- }
+ resolveChannel(channel) {
+ if (channel instanceof Channel) {
+ return channel;
+ }
- if ($string(channel)) {
- return this.client.store.get('channels', channel);
- }
- }
+ if ($string(channel)) {
+ return this.client.store.get('channels', channel);
+ }
- ResolveString(data) {
- if (data instanceof String) {
- return data;
- }
+ return null;
+ }
- if (data instanceof Array) {
- return data.join('\n');
- }
+ resolveString(data) {
+ if (data instanceof String) {
+ return data;
+ }
- return String(data);
- }
+ if (data instanceof Array) {
+ return data.join('\n');
+ }
+
+ return String(data);
+ }
}
module.exports = ClientDataResolver;
diff --git a/src/client/ClientManager.js b/src/client/ClientManager.js
index 00ffc5c69..175e905ad 100644
--- a/src/client/ClientManager.js
+++ b/src/client/ClientManager.js
@@ -1,34 +1,32 @@
-'use strict';
-
const Constants = require('../util/Constants');
class ClientManager {
- constructor(client) {
- this.client = client;
- this.heartbeatInterval = null;
- }
+ constructor(client) {
+ this.client = client;
+ this.heartbeatInterval = null;
+ }
- connectToWebSocket(token, resolve, reject) {
- this.client.store.token = token;
- this.client.rest.methods.GetGateway()
- .then(gateway => {
- this.client.ws.connect(gateway);
- this.client.once(Constants.Events.READY, () => resolve(token));
- })
- .catch(reject);
+ connectToWebSocket(token, resolve, reject) {
+ this.client.store.token = token;
+ this.client.rest.methods.getGateway()
+ .then(gateway => {
+ this.client.ws.connect(gateway);
+ this.client.once(Constants.Events.READY, () => resolve(token));
+ })
+ .catch(reject);
- setTimeout(() => reject(Constants.Errors.TOOK_TOO_LONG), 1000 * 15);
- }
+ setTimeout(() => reject(Constants.Errors.TOOK_TOO_LONG), 1000 * 15);
+ }
- setupKeepAlive(time) {
- this.heartbeatInterval = setInterval(() => {
- this.client.ws.send({
- op: Constants.OPCodes.HEARTBEAT,
- d: Date.now(),
- });
- }, time);
- }
+ setupKeepAlive(time) {
+ this.heartbeatInterval = setInterval(() => {
+ this.client.ws.send({
+ op: Constants.OPCodes.HEARTBEAT,
+ d: Date.now(),
+ });
+ }, time);
+ }
}
module.exports = ClientManager;
diff --git a/src/client/actions/Action.js b/src/client/actions/Action.js
index 795022b6d..a92fe45fc 100644
--- a/src/client/actions/Action.js
+++ b/src/client/actions/Action.js
@@ -1,5 +1,3 @@
-'use strict';
-
/*
ABOUT ACTIONS
@@ -14,14 +12,14 @@ that WebSocket events don't clash with REST methods.
class GenericAction {
- constructor(client) {
- this.client = client;
- }
+ constructor(client) {
+ this.client = client;
+ }
- handle(data) {
+ handle(data) {
+ return data;
+ }
- }
-
-};
+}
module.exports = GenericAction;
diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js
index 850c052d1..68112c7d5 100644
--- a/src/client/actions/ActionsManager.js
+++ b/src/client/actions/ActionsManager.js
@@ -1,30 +1,28 @@
-'use strict';
-
-const requireAction = name => require(`./${name}`);
-
-class ActionsManager {
- constructor(client) {
- this.client = client;
-
- this.register('MessageCreate');
- this.register('MessageDelete');
- this.register('MessageUpdate');
- this.register('ChannelCreate');
- this.register('ChannelDelete');
- this.register('ChannelUpdate');
- this.register('GuildDelete');
- this.register('GuildUpdate');
- this.register('GuildMemberRemove');
- this.register('GuildRoleCreate');
- this.register('GuildRoleDelete');
- this.register('GuildRoleUpdate');
- this.register('UserUpdate');
- }
-
- register(name) {
- let Action = requireAction(name);
- this[name] = new Action(this.client);
- }
-}
-
-module.exports = ActionsManager;
+const requireAction = name => require(`./${name}`);
+
+class ActionsManager {
+ constructor(client) {
+ this.client = client;
+
+ this.register('MessageCreate');
+ this.register('MessageDelete');
+ this.register('MessageUpdate');
+ this.register('ChannelCreate');
+ this.register('ChannelDelete');
+ this.register('ChannelUpdate');
+ this.register('GuildDelete');
+ this.register('GuildUpdate');
+ this.register('GuildMemberRemove');
+ this.register('GuildRoleCreate');
+ this.register('GuildRoleDelete');
+ this.register('GuildRoleUpdate');
+ this.register('UserUpdate');
+ }
+
+ register(name) {
+ const Action = requireAction(name);
+ this[name] = new Action(this.client);
+ }
+}
+
+module.exports = ActionsManager;
diff --git a/src/client/actions/ChannelCreate.js b/src/client/actions/ChannelCreate.js
index 53c1d4325..09cbec54f 100644
--- a/src/client/actions/ChannelCreate.js
+++ b/src/client/actions/ChannelCreate.js
@@ -1,23 +1,15 @@
-'use strict';
-
const Action = require('./Action');
-const Constants = require('../../util/Constants');
-const Message = require('../../structures/Message');
class ChannelCreateAction extends Action {
- constructor(client) {
- super(client);
- }
+ handle(data) {
+ const client = this.client;
+ const channel = client.store.newChannel(data);
- handle(data) {
- let client = this.client;
- let channel = client.store.NewChannel(data);
-
- return {
- channel,
- };
- }
-};
+ return {
+ channel,
+ };
+ }
+}
module.exports = ChannelCreateAction;
diff --git a/src/client/actions/ChannelDelete.js b/src/client/actions/ChannelDelete.js
index 36b6d0231..5ecd5c03d 100644
--- a/src/client/actions/ChannelDelete.js
+++ b/src/client/actions/ChannelDelete.js
@@ -1,44 +1,36 @@
-'use strict';
-
-const Action = require('./Action');
-const Constants = require('../../util/Constants');
-const Message = require('../../structures/Message');
-
-class ChannelDeleteAction extends Action {
-
- constructor(client) {
- super(client);
- this.timeouts = [];
- this.deleted = {};
- }
-
- handle(data) {
- let client = this.client;
- let channel = client.store.get('channels', data.id);
-
- if (channel) {
-
- client.store.KillChannel(channel);
- this.deleted[channel.id] = channel;
- this.scheduleForDeletion(channel.id);
-
- } else if (this.deleted[data.id]) {
-
- channel = this.deleted[data.id];
-
- }
-
- return {
- channel,
- };
- }
-
- scheduleForDeletion(id) {
- this.timeouts.push(
- setTimeout(() => delete this.deleted[id],
- this.client.options.rest_ws_bridge_timeout)
- );
- }
-};
-
-module.exports = ChannelDeleteAction;
+const Action = require('./Action');
+
+class ChannelDeleteAction extends Action {
+
+ constructor(client) {
+ super(client);
+ this.timeouts = [];
+ this.deleted = {};
+ }
+
+ handle(data) {
+ const client = this.client;
+ let channel = client.store.get('channels', data.id);
+
+ if (channel) {
+ client.store.killChannel(channel);
+ this.deleted[channel.id] = channel;
+ this.scheduleForDeletion(channel.id);
+ } else if (this.deleted[data.id]) {
+ channel = this.deleted[data.id];
+ }
+
+ return {
+ channel,
+ };
+ }
+
+ scheduleForDeletion(id) {
+ this.timeouts.push(
+ setTimeout(() => delete this.deleted[id],
+ this.client.options.rest_ws_bridge_timeout)
+ );
+ }
+}
+
+module.exports = ChannelDeleteAction;
diff --git a/src/client/actions/ChannelUpdate.js b/src/client/actions/ChannelUpdate.js
index 78d02245e..f7a855b6b 100644
--- a/src/client/actions/ChannelUpdate.js
+++ b/src/client/actions/ChannelUpdate.js
@@ -1,39 +1,31 @@
-'use strict';
-
const Action = require('./Action');
const Constants = require('../../util/Constants');
-const CloneObject = require('../../util/CloneObject');
-const Message = require('../../structures/Message');
+const cloneObject = require('../../util/CloneObject');
class ChannelUpdateAction extends Action {
- constructor(client) {
- super(client);
- }
+ handle(data) {
+ const client = this.client;
+ const channel = client.store.get('channels', data.id);
- handle(data) {
+ if (channel) {
+ const oldChannel = cloneObject(channel);
+ channel.setup(data);
+ if (!oldChannel.equals(data)) {
+ client.emit(Constants.Events.CHANNEL_UPDATE, oldChannel, channel);
+ }
- let client = this.client;
- let channel = client.store.get('channels', data.id);
+ return {
+ old: oldChannel,
+ updated: channel,
+ };
+ }
- if (channel) {
- let oldChannel = CloneObject(channel);
- channel.setup(data);
- if (!oldChannel.equals(data)) {
- client.emit(Constants.Events.CHANNEL_UPDATE, oldChannel, channel);
- }
-
- return {
- old: oldChannel,
- updated: channel,
- };
- }
-
- return {
- old: null,
- updated: null,
- };
- }
-};
+ return {
+ old: null,
+ updated: null,
+ };
+ }
+}
module.exports = ChannelUpdateAction;
diff --git a/src/client/actions/GuildDelete.js b/src/client/actions/GuildDelete.js
index 271cb7b52..0e040dc4a 100644
--- a/src/client/actions/GuildDelete.js
+++ b/src/client/actions/GuildDelete.js
@@ -1,54 +1,49 @@
-'use strict';
-
const Action = require('./Action');
const Constants = require('../../util/Constants');
-const Message = require('../../structures/Message');
class GuildDeleteAction extends Action {
- constructor(client) {
- super(client);
- this.deleted = {};
- this.timeouts = [];
- }
+ constructor(client) {
+ super(client);
+ this.deleted = {};
+ this.timeouts = [];
+ }
- handle(data) {
+ handle(data) {
+ const client = this.client;
+ let guild = client.store.get('guilds', data.id);
- let client = this.client;
- let guild = client.store.get('guilds', data.id);
+ if (guild) {
+ if (guild.available && data.unavailable) {
+ // guild is unavailable
+ guild.available = false;
+ client.emit(Constants.Events.GUILD_UNAVAILABLE, guild);
- if (guild) {
- if (guild.available && data.unavailable) {
- // guild is unavailable
- guild.available = false;
- client.emit(Constants.Events.GUILD_UNAVAILABLE, guild);
+ // stops the GuildDelete packet thinking a guild was actually deleted,
+ // handles emitting of event itself
+ return {
+ guild: null,
+ };
+ }
+ // delete guild
+ client.store.remove('guilds', guild);
+ this.deleted[guild.id] = guild;
+ this.scheduleForDeletion(guild.id);
+ } else if (this.deleted[data.id]) {
+ guild = this.deleted[data.id];
+ }
- // stops the GuildDelete packet thinking a guild was actually deleted,
- // handles emitting of event itself
- return {
- guild: null,
- };
- } else {
- // delete guild
- client.store.remove('guilds', guild);
- this.deleted[guild.id] = guild;
- this.scheduleForDeletion(guild.id);
- }
- } else if (this.deleted[data.id]) {
- guild = this.deleted[data.id];
- }
+ return {
+ guild,
+ };
+ }
- return {
- guild,
- };
- }
-
- scheduleForDeletion(id) {
- this.timeouts.push(
- setTimeout(() => delete this.deleted[id],
- this.client.options.rest_ws_bridge_timeout)
- );
- }
-};
+ scheduleForDeletion(id) {
+ this.timeouts.push(
+ setTimeout(() => delete this.deleted[id],
+ this.client.options.rest_ws_bridge_timeout)
+ );
+ }
+}
module.exports = GuildDeleteAction;
diff --git a/src/client/actions/GuildMemberRemove.js b/src/client/actions/GuildMemberRemove.js
index 7ef912467..f5e965463 100644
--- a/src/client/actions/GuildMemberRemove.js
+++ b/src/client/actions/GuildMemberRemove.js
@@ -1,51 +1,48 @@
-'use strict';
-
const Action = require('./Action');
const Constants = require('../../util/Constants');
-const Message = require('../../structures/Message');
class GuildMemberRemoveAction extends Action {
- constructor(client) {
- super(client);
- this.timeouts = [];
- this.deleted = {};
- }
+ constructor(client) {
+ super(client);
+ this.timeouts = [];
+ this.deleted = {};
+ }
- handle(data) {
- let client = this.client;
- let guild = client.store.get('guilds', data.guild_id);
- if (guild) {
- let member = guild.store.get('members', data.user.id);
- if (member) {
- guild._removeMember(member);
- this.deleted[guild.id + data.user.id] = member;
- client.emit(Constants.Events.GUILD_MEMBER_REMOVE, guild, member);
- this.scheduleForDeletion(guild.id, data.user.id);
- }
+ handle(data) {
+ const client = this.client;
+ const guild = client.store.get('guilds', data.guild_id);
+ if (guild) {
+ let member = guild.store.get('members', data.user.id);
+ if (member) {
+ guild._removeMember(member);
+ this.deleted[guild.id + data.user.id] = member;
+ client.emit(Constants.Events.GUILD_MEMBER_REMOVE, guild, member);
+ this.scheduleForDeletion(guild.id, data.user.id);
+ }
- if (!member) {
- member = this.deleted[guild.id + data.user.id];
- }
+ if (!member) {
+ member = this.deleted[guild.id + data.user.id];
+ }
- return {
- g: guild,
- m: member,
- };
- }
+ return {
+ g: guild,
+ m: member,
+ };
+ }
- return {
- g: guild,
- m: null,
- };
- }
+ return {
+ g: guild,
+ m: null,
+ };
+ }
- scheduleForDeletion(guildID, userID) {
- this.timeouts.push(
- setTimeout(() => delete this.deleted[guildID + userID],
- this.client.options.rest_ws_bridge_timeout)
- );
- }
-};
+ scheduleForDeletion(guildID, userID) {
+ this.timeouts.push(
+ setTimeout(() => delete this.deleted[guildID + userID],
+ this.client.options.rest_ws_bridge_timeout)
+ );
+ }
+}
module.exports = GuildMemberRemoveAction;
diff --git a/src/client/actions/GuildRoleCreate.js b/src/client/actions/GuildRoleCreate.js
index 0a929d351..601e24266 100644
--- a/src/client/actions/GuildRoleCreate.js
+++ b/src/client/actions/GuildRoleCreate.js
@@ -1,38 +1,31 @@
-'use strict';
-
const Action = require('./Action');
const Constants = require('../../util/Constants');
const Role = require('../../structures/Role');
class GuildRoleCreate extends Action {
- constructor(client) {
- super(client);
- }
+ handle(data) {
+ const client = this.client;
+ const guild = client.store.get('guilds', data.guild_id);
- handle(data) {
+ if (guild) {
+ const already = guild.store.get('roles', data.role.id);
+ const role = new Role(guild, data.role);
+ guild.store.add('roles', role);
- let client = this.client;
- let guild = client.store.get('guilds', data.guild_id);
+ if (!already) {
+ client.emit(Constants.Events.GUILD_ROLE_CREATE, guild, role);
+ }
- if (guild) {
- let already = guild.store.get('roles', data.role.id);
- let role = new Role(guild, data.role);
- guild.store.add('roles', role);
+ return {
+ role,
+ };
+ }
- if (!already) {
- client.emit(Constants.Events.GUILD_ROLE_CREATE, guild, role);
- }
-
- return {
- role,
- };
- }
-
- return {
- role: null,
- };
- }
-};
+ return {
+ role: null,
+ };
+ }
+}
module.exports = GuildRoleCreate;
diff --git a/src/client/actions/GuildRoleDelete.js b/src/client/actions/GuildRoleDelete.js
index 687305b30..e27f81639 100644
--- a/src/client/actions/GuildRoleDelete.js
+++ b/src/client/actions/GuildRoleDelete.js
@@ -1,50 +1,47 @@
-'use strict';
-
const Action = require('./Action');
const Constants = require('../../util/Constants');
-const Message = require('../../structures/Message');
class GuildRoleDeleteAction extends Action {
- constructor(client) {
- super(client);
- this.timeouts = [];
- this.deleted = {};
- }
+ constructor(client) {
+ super(client);
+ this.timeouts = [];
+ this.deleted = {};
+ }
- handle(data) {
- let client = this.client;
- let guild = client.store.get('guilds', data.guild_id);
+ handle(data) {
+ const client = this.client;
+ const guild = client.store.get('guilds', data.guild_id);
- if (guild) {
- let exists = guild.store.get('roles', data.role_id);
- if (exists) {
- guild.store.remove('roles', data.role_id);
- this.deleted[guild.id + data.role_id] = exists;
- this.scheduleForDeletion(guild.id, data.role_id);
- client.emit(Constants.Events.GUILD_ROLE_DELETE, guild, exists);
- }
+ if (guild) {
+ let exists = guild.store.get('roles', data.role_id);
+ if (exists) {
+ guild.store.remove('roles', data.role_id);
+ this.deleted[guild.id + data.role_id] = exists;
+ this.scheduleForDeletion(guild.id, data.role_id);
+ client.emit(Constants.Events.GUILD_ROLE_DELETE, guild, exists);
+ }
- if (!exists) {
- exists = this.deleted[guild.id + data.role_id];
- }
+ if (!exists) {
+ exists = this.deleted[guild.id + data.role_id];
+ }
- return {
- role: exists,
- };
- }
+ return {
+ role: exists,
+ };
+ }
- return {
- role: null,
- };
- }
+ return {
+ role: null,
+ };
+ }
- scheduleForDeletion(guildID, roleID) {
- this.timeouts.push(
- setTimeout(() => delete this.deleted[guildID + roleID],
- this.client.options.rest_ws_bridge_timeout)
- );
- }
-};
+ scheduleForDeletion(guildID, roleID) {
+ this.timeouts.push(
+ setTimeout(() => delete this.deleted[guildID + roleID],
+ this.client.options.rest_ws_bridge_timeout)
+ );
+ }
+}
module.exports = GuildRoleDeleteAction;
diff --git a/src/client/actions/GuildRoleUpdate.js b/src/client/actions/GuildRoleUpdate.js
index 61b269240..14a896724 100644
--- a/src/client/actions/GuildRoleUpdate.js
+++ b/src/client/actions/GuildRoleUpdate.js
@@ -1,44 +1,36 @@
-'use strict';
-
const Action = require('./Action');
const Constants = require('../../util/Constants');
-const CloneObject = require('../../util/CloneObject');
-const Message = require('../../structures/Message');
+const cloneObject = require('../../util/CloneObject');
class GuildRoleUpdateAction extends Action {
- constructor(client) {
- super(client);
- }
+ handle(data) {
+ const client = this.client;
+ const guild = client.store.get('guilds', data.guild_id);
- handle(data) {
+ const roleData = data.role;
- let client = this.client;
- let guild = client.store.get('guilds', data.guild_id);
+ if (guild) {
+ let oldRole;
+ const existingRole = guild.store.get('roles', roleData.id);
+ // exists and not the same
+ if (existingRole && !existingRole.equals(roleData)) {
+ oldRole = cloneObject(existingRole);
+ existingRole.setup(data.role);
+ client.emit(Constants.Events.GUILD_ROLE_UPDATE, guild, oldRole, existingRole);
+ }
- let roleData = data.role;
+ return {
+ old: oldRole,
+ updated: existingRole,
+ };
+ }
- if (guild) {
- let oldRole;
- let existingRole = guild.store.get('roles', roleData.id);
- // exists and not the same
- if (existingRole && !existingRole.equals(roleData)) {
- oldRole = CloneObject(existingRole);
- existingRole.setup(data.role);
- client.emit(Constants.Events.GUILD_ROLE_UPDATE, guild, oldRole, existingRole);
- }
-
- return {
- old: oldRole,
- updated: existingRole,
- };
- }
-
- return {
- old: null,
- updated: null,
- };
- }
-};
+ return {
+ old: null,
+ updated: null,
+ };
+ }
+}
module.exports = GuildRoleUpdateAction;
diff --git a/src/client/actions/GuildUpdate.js b/src/client/actions/GuildUpdate.js
index 96ab7565e..a7a2775de 100644
--- a/src/client/actions/GuildUpdate.js
+++ b/src/client/actions/GuildUpdate.js
@@ -1,42 +1,38 @@
-'use strict';
-
const Action = require('./Action');
const Constants = require('../../util/Constants');
-const CloneObject = require('../../util/CloneObject');
-const Message = require('../../structures/Message');
+const cloneObject = require('../../util/CloneObject');
class GuildUpdateAction extends Action {
- constructor(client) {
- super(client);
- this.deleted = {};
- this.timeouts = [];
- }
+ constructor(client) {
+ super(client);
+ this.deleted = {};
+ this.timeouts = [];
+ }
- handle(data) {
+ handle(data) {
+ const client = this.client;
+ const guild = client.store.get('guilds', data.id);
- let client = this.client;
- let guild = client.store.get('guilds', data.id);
+ if (guild) {
+ const oldGuild = cloneObject(guild);
+ guild.setup(data);
- if (guild) {
- let oldGuild = CloneObject(guild);
- guild.setup(data);
+ if (!oldGuild.equals(data)) {
+ client.emit(Constants.Events.GUILD_UPDATE, oldGuild, guild);
+ }
- if (!oldGuild.equals(data)) {
- client.emit(Constants.Events.GUILD_UPDATE, oldGuild, guild);
- }
+ return {
+ old: oldGuild,
+ updated: guild,
+ };
+ }
- return {
- old: oldGuild,
- updated: guild,
- };
- }
-
- return {
- old: null,
- updated: null,
- };
- }
-};
+ return {
+ old: null,
+ updated: null,
+ };
+ }
+}
module.exports = GuildUpdateAction;
diff --git a/src/client/actions/MessageCreate.js b/src/client/actions/MessageCreate.js
index 55bae8b4e..75f5e25f0 100644
--- a/src/client/actions/MessageCreate.js
+++ b/src/client/actions/MessageCreate.js
@@ -1,31 +1,23 @@
-'use strict';
-
const Action = require('./Action');
-const Constants = require('../../util/Constants');
const Message = require('../../structures/Message');
class MessageCreateAction extends Action {
- constructor(client) {
- super(client);
- }
+ handle(data) {
+ const client = this.client;
+ const channel = client.store.get('channels', data.channel_id);
- handle(data) {
+ if (channel) {
+ const message = channel._cacheMessage(new Message(channel, data, client));
+ return {
+ m: message,
+ };
+ }
- let client = this.client;
- let channel = client.store.get('channels', data.channel_id);
-
- if (channel) {
- let message = channel._cacheMessage(new Message(channel, data, client));
- return {
- m: message,
- };
- }
-
- return {
- m: null,
- };
- }
-};
+ return {
+ m: null,
+ };
+ }
+}
module.exports = MessageCreateAction;
diff --git a/src/client/actions/MessageDelete.js b/src/client/actions/MessageDelete.js
index a8a2f8e04..bbd9e00e3 100644
--- a/src/client/actions/MessageDelete.js
+++ b/src/client/actions/MessageDelete.js
@@ -1,51 +1,43 @@
-'use strict';
-
const Action = require('./Action');
-const Constants = require('../../util/Constants');
-const Message = require('../../structures/Message');
class MessageDeleteAction extends Action {
- constructor(client) {
- super(client);
- this.timeouts = [];
- this.deleted = {};
- }
+ constructor(client) {
+ super(client);
+ this.timeouts = [];
+ this.deleted = {};
+ }
- handle(data) {
- let client = this.client;
- let channel = client.store.get('channels', data.channel_id);
- if (channel) {
- let message = channel.store.get('messages', data.id);
+ handle(data) {
+ const client = this.client;
+ const channel = client.store.get('channels', data.channel_id);
+ if (channel) {
+ let message = channel.store.get('messages', data.id);
- if (message) {
+ if (message) {
+ channel.store.remove('messages', message.id);
+ this.deleted[channel.id + message.id] = message;
+ this.scheduleForDeletion(channel.id, message.id);
+ } else if (this.deleted[channel.id + data.id]) {
+ message = this.deleted[channel.id + data.id];
+ }
- channel.store.remove('messages', message.id);
- this.deleted[channel.id + message.id] = message;
- this.scheduleForDeletion(channel.id, message.id);
+ return {
+ m: message,
+ };
+ }
- } else if (this.deleted[channel.id + data.id]) {
+ return {
+ m: null,
+ };
+ }
- message = this.deleted[channel.id + data.id];
-
- }
-
- return {
- m: message,
- };
- }
-
- return {
- m: null,
- };
- }
-
- scheduleForDeletion(channelID, messageID) {
- this.timeouts.push(
- setTimeout(() => delete this.deleted[channelID + messageID],
- this.client.options.rest_ws_bridge_timeout)
- );
- }
-};
+ scheduleForDeletion(channelID, messageID) {
+ this.timeouts.push(
+ setTimeout(() => delete this.deleted[channelID + messageID],
+ this.client.options.rest_ws_bridge_timeout)
+ );
+ }
+}
module.exports = MessageDeleteAction;
diff --git a/src/client/actions/MessageUpdate.js b/src/client/actions/MessageUpdate.js
index 67c1d79f6..3d5854ba9 100644
--- a/src/client/actions/MessageUpdate.js
+++ b/src/client/actions/MessageUpdate.js
@@ -1,44 +1,36 @@
-'use strict';
-
const Action = require('./Action');
const Constants = require('../../util/Constants');
-const CloneObject = require('../../util/CloneObject');
-const Message = require('../../structures/Message');
+const cloneObject = require('../../util/CloneObject');
class MessageUpdateAction extends Action {
- constructor(client) {
- super(client);
- }
+ handle(data) {
+ const client = this.client;
+ const channel = client.store.get('channels', data.channel_id);
- handle(data) {
+ if (channel) {
+ const message = channel.store.get('messages', data.id);
+ if (message && !message.equals(data, true)) {
+ const oldMessage = cloneObject(message);
+ message.patch(data);
+ client.emit(Constants.Events.MESSAGE_UPDATE, oldMessage, message);
+ return {
+ old: oldMessage,
+ updated: message,
+ };
+ }
- let client = this.client;
- let channel = client.store.get('channels', data.channel_id);
+ return {
+ old: message,
+ updated: message,
+ };
+ }
- if (channel) {
- let message = channel.store.get('messages', data.id);
- if (message && !message.equals(data, true)) {
- let oldMessage = CloneObject(message);
- message.patch(data);
- return {
- old: oldMessage,
- updated: message,
- };
- client.emit(Constants.Events.MESSAGE_UPDATE, oldMessage, message);
- }
-
- return {
- old: message,
- updated: message,
- };
- }
-
- return {
- old: null,
- updated: null,
- };
- }
-};
+ return {
+ old: null,
+ updated: null,
+ };
+ }
+}
module.exports = MessageUpdateAction;
diff --git a/src/client/actions/UserUpdate.js b/src/client/actions/UserUpdate.js
index ec3a42cb6..7c10a9297 100644
--- a/src/client/actions/UserUpdate.js
+++ b/src/client/actions/UserUpdate.js
@@ -1,44 +1,36 @@
-'use strict';
-
const Action = require('./Action');
const Constants = require('../../util/Constants');
-const CloneObject = require('../../util/CloneObject');
-const Message = require('../../structures/Message');
+const cloneObject = require('../../util/CloneObject');
class UserUpdateAction extends Action {
- constructor(client) {
- super(client);
- }
+ handle(data) {
+ const client = this.client;
- handle(data) {
+ if (client.store.user) {
+ if (client.store.user.equals(data)) {
+ return {
+ old: client.store.user,
+ updated: client.store.user,
+ };
+ }
- let client = this.client;
+ const oldUser = cloneObject(client.store.user);
+ client.store.user.setup(data);
- if (client.store.user) {
- if (client.store.user.equals(data)) {
- return {
- old: client.store.user,
- updated: client.store.user,
- };
- }
+ client.emit(Constants.Events.USER_UPDATE, oldUser, client.store.user);
- let oldUser = CloneObject(client.store.user);
- client.store.user.setup(data);
+ return {
+ old: oldUser,
+ updated: client.store.user,
+ };
+ }
- client.emit(Constants.Events.USER_UPDATE, oldUser, client.store.user);
-
- return {
- old: oldUser,
- updated: client.store.user,
- };
- }
-
- return {
- old: null,
- updated: null,
- };
- }
-};
+ return {
+ old: null,
+ updated: null,
+ };
+ }
+}
module.exports = UserUpdateAction;
diff --git a/src/client/rest/RESTManager.js b/src/client/rest/RESTManager.js
index 60c021a47..768367219 100644
--- a/src/client/rest/RESTManager.js
+++ b/src/client/rest/RESTManager.js
@@ -1,105 +1,110 @@
-'use strict';
-
const request = require('superagent');
const Constants = require('../../util/Constants');
const UserAgentManager = require('./UserAgentManager');
const RESTMethods = require('./RESTMethods');
-class RESTManager{
+class RESTManager {
- constructor(client) {
- this.client = client;
- this.queue = [];
- this.userAgentManager = new UserAgentManager(this);
- this.methods = new RESTMethods(this);
- this.rateLimitedEndpoints = {};
- }
+ constructor(client) {
+ this.client = client;
+ this.queue = [];
+ this.userAgentManager = new UserAgentManager(this);
+ this.methods = new RESTMethods(this);
+ this.rateLimitedEndpoints = {};
+ }
- addRequestToQueue(method, url, auth, data, file, resolve, reject) {
- let endpoint = url.replace(/\/[0-9]+/g, '/:id');
+ addRequestToQueue(method, url, auth, data, file, resolve, reject) {
+ const endpoint = url.replace(/\/[0-9]+/g, '/:id');
- let rateLimitedEndpoint = this.rateLimitedEndpoints[endpoint];
+ const rateLimitedEndpoint = this.rateLimitedEndpoints[endpoint];
- rateLimitedEndpoint.queue = rateLimitedEndpoint.queue || [];
+ rateLimitedEndpoint.queue = rateLimitedEndpoint.queue || [];
- rateLimitedEndpoint.queue.push({
- method, url, auth, data, file, resolve, reject,
- });
- }
+ rateLimitedEndpoint.queue.push({
+ method,
+ url,
+ auth,
+ data,
+ file,
+ resolve,
+ reject,
+ });
+ }
- processQueue(endpoint) {
- let rateLimitedEndpoint = this.rateLimitedEndpoints[endpoint];
+ processQueue(endpoint) {
+ const rateLimitedEndpoint = this.rateLimitedEndpoints[endpoint];
- // prevent multiple queue processes
- if (!rateLimitedEndpoint.timeout) {
- return;
- }
+ // prevent multiple queue processes
+ if (!rateLimitedEndpoint.timeout) {
+ return;
+ }
- // lock the queue
- clearTimeout(rateLimitedEndpoint.timeout);
- rateLimitedEndpoint.timeout = null;
+ // lock the queue
+ clearTimeout(rateLimitedEndpoint.timeout);
+ rateLimitedEndpoint.timeout = null;
- for (let item of rateLimitedEndpoint.queue) {
- this.makeRequest(item.method, item.url, item.auth, item.data, item.file)
- .then(item.resolve)
- .catch(item.reject);
- }
+ for (const item of rateLimitedEndpoint.queue) {
+ this.makeRequest(item.method, item.url, item.auth, item.data, item.file)
+ .then(item.resolve)
+ .catch(item.reject);
+ }
- rateLimitedEndpoint.queue = [];
- }
+ rateLimitedEndpoint.queue = [];
+ }
- makeRequest(method, url, auth, data, file, fromQueue) {
- /*
- file is {file, name}
- */
- let apiRequest = request[method](url);
+ makeRequest(method, url, auth, data, file) {
+ /*
+ file is {file, name}
+ */
+ console.log(url);
+ const apiRequest = request[method](url);
- let endpoint = url.replace(/\/[0-9]+/g, '/:id');
+ const endpoint = url.replace(/\/[0-9]+/g, '/:id');
- if (this.rateLimitedEndpoints[endpoint] && this.rateLimitedEndpoints[endpoint].timeout) {
- return new Promise((resolve, reject) => {
- this.addRequestToQueue(method, url, auth, data, file, resolve, reject);
- });
- }
+ if (this.rateLimitedEndpoints[endpoint] && this.rateLimitedEndpoints[endpoint].timeout) {
+ return new Promise((resolve, reject) => {
+ this.addRequestToQueue(method, url, auth, data, file, resolve, reject);
+ });
+ }
- if (auth) {
- if (this.client.store.token) {
- apiRequest.set('authorization', this.client.store.token);
- } else {
- throw Constants.Errors.NO_TOKEN;
- }
- }
+ if (auth) {
+ if (this.client.store.token) {
+ apiRequest.set('authorization', this.client.store.token);
+ } else {
+ throw Constants.Errors.NO_TOKEN;
+ }
+ }
- if (data) {
- apiRequest.send(data);
- }
+ if (data) {
+ apiRequest.send(data);
+ }
- if (file) {
- apiRequest.attach('file', file.file, file.name);
- }
+ if (file) {
+ apiRequest.attach('file', file.file, file.name);
+ }
- apiRequest.set('User-Agent', this.userAgentManager.userAgent);
+ apiRequest.set('User-Agent', this.userAgentManager.userAgent);
- return new Promise((resolve, reject) => {
- apiRequest.end((err, res) => {
- if (err) {
- let retry = res.headers['retry-after'] || res.headers['Retry-After'];
- if (retry) {
- this.rateLimitedEndpoints[endpoint] = {};
- this.addRequestToQueue(method, url, auth, data, file, resolve, reject);
- this.rateLimitedEndpoints[endpoint].timeout = setTimeout(() => {
- this.processQueue(endpoint);
- }, retry);
- return;
- }
+ return new Promise((resolve, reject) => {
+ apiRequest.end((err, res) => {
+ if (err) {
+ const retry = res.headers['retry-after'] || res.headers['Retry-After'];
+ if (retry) {
+ this.rateLimitedEndpoints[endpoint] = {};
+ this.addRequestToQueue(method, url, auth, data, file, resolve, reject);
+ this.rateLimitedEndpoints[endpoint].timeout = setTimeout(() => {
+ this.processQueue(endpoint);
+ }, retry);
+ return;
+ }
- reject(err);
- } else {
- resolve(res ? res.body || {} : {});
- }
- });
- });
- }
-};
+ reject(err);
+ } else {
+ resolve(res ? res.body || {} : {});
+ }
+ });
+ });
+ }
+}
module.exports = RESTManager;
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index 5ddf95198..9eff9d3d1 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -1,329 +1,328 @@
-'use strict';
-
const Constants = require('../../util/Constants');
-const Structure = name => require('../../structures/' + name);
-const User = Structure('User');
-const GuildMember = Structure('GuildMember');
-const Message = Structure('Message');
-class RESTMethods{
- constructor(restManager) {
- this.rest = restManager;
- }
+const getStructure = name => require(`../../structures/${name}`);
+const User = getStructure('User');
+const GuildMember = getStructure('GuildMember');
- LoginEmailPassword(email, password) {
- return new Promise((resolve, reject) => {
- this.rest.client.store.email = email;
- this.rest.client.store.password = password;
- this.rest.makeRequest('post', Constants.Endpoints.LOGIN, false, { email, password })
- .then(data => {
- this.rest.client.manager.connectToWebSocket(data.token, resolve, reject);
- })
- .catch(reject);
+class RESTMethods {
+ constructor(restManager) {
+ this.rest = restManager;
+ }
- });
- }
+ loginEmailPassword(email, password) {
+ return new Promise((resolve, reject) => {
+ this.rest.client.store.email = email;
+ this.rest.client.store.password = password;
+ this.rest.makeRequest('post', Constants.Endpoints.login, false, { email, password })
+ .then(data => {
+ this.rest.client.manager.connectToWebSocket(data.token, resolve, reject);
+ })
+ .catch(reject);
+ });
+ }
- LoginToken(token) {
- return new Promise((resolve, reject) => {
- this.rest.client.manager.connectToWebSocket(token, resolve, reject);
- });
- }
+ loginToken(token) {
+ return new Promise((resolve, reject) => {
+ this.rest.client.manager.connectToWebSocket(token, resolve, reject);
+ });
+ }
- GetGateway() {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('get', Constants.Endpoints.GATEWAY, true)
- .then(res => resolve(res.url))
- .catch(reject);
- });
- }
+ getGateway() {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('get', Constants.Endpoints.gateway, true)
+ .then(res => resolve(res.url))
+ .catch(reject);
+ });
+ }
- SendMessage(channel, content, tts, nonce) {
- return new Promise((resolve, reject) => {
+ sendMessage($channel, content, tts, nonce) {
+ return new Promise((resolve, reject) => {
+ const $this = this;
+ let channel = $channel;
- var _this = this;
+ function req() {
+ $this.rest.makeRequest('post', Constants.Endpoints.channelMessages(channel.id), true, {
+ content, tts, nonce,
+ })
+ .then(data => resolve($this.rest.client.actions.MessageCreate.handle(data).m))
+ .catch(reject);
+ }
- if (channel instanceof User || channel instanceof GuildMember) {
- this.CreateDM(channel).then(chan => {
- channel = chan;
- req();
- })
- .catch(reject);
- } else {
- req();
- }
+ if (channel instanceof User || channel instanceof GuildMember) {
+ this.createDM(channel).then(chan => {
+ channel = chan;
+ req();
+ })
+ .catch(reject);
+ } else {
+ req();
+ }
+ });
+ }
- function req() {
- _this.rest.makeRequest('post', Constants.Endpoints.CHANNEL_MESSAGES(channel.id), true, {
- content, tts, nonce,
- })
- .then(data => resolve(_this.rest.client.actions.MessageCreate.handle(data).m))
- .catch(reject);
- }
- });
- }
+ deleteMessage(message) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.channelMessage(message.channel.id, message.id), true)
+ .then(() => {
+ resolve(this.rest.client.actions.MessageDelete.handle({
+ id: message.id,
+ channel_id: message.channel.id,
+ }).m);
+ })
+ .catch(reject);
+ });
+ }
- DeleteMessage(message) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('del', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true)
- .then(data => {
- resolve(this.rest.client.actions.MessageDelete.handle({
- id: message.id,
- channel_id: message.channel.id,
- }).m);
- })
- .catch(reject);
- });
- }
+ updateMessage(message, content) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('patch', Constants.Endpoints.channelMessage(message.channel.id, message.id), true, {
+ content,
+ })
+ .then(data => {
+ resolve(this.rest.client.actions.MessageUpdate.handle(data).updated);
+ })
+ .catch(reject);
+ });
+ }
- UpdateMessage(message, content) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id), true, {
- content,
- })
- .then(data => {
- resolve(this.rest.client.actions.MessageUpdate.handle(data).updated);
- })
- .catch(reject);
- });
- }
+ createChannel(guild, channelName, channelType) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('post', Constants.Endpoints.guildChannels(guild.id), true, {
+ name: channelName,
+ type: channelType,
+ })
+ .then(data => {
+ resolve(this.rest.client.actions.ChannelCreate.handle(data).channel);
+ })
+ .catch(reject);
+ });
+ }
- CreateChannel(guild, channelName, channelType) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('post', Constants.Endpoints.GUILD_CHANNELS(guild.id), true, {
- name: channelName,
- type: channelType,
- })
- .then(data => {
- resolve(this.rest.client.actions.ChannelCreate.handle(data).channel);
- })
- .catch(reject);
- });
- }
+ getExistingDM(recipient) {
+ const dmChannel = this.rest.client.store.getAsArray('channels')
+ .filter(channel => channel.recipient)
+ .filter(channel => channel.recipient.id === recipient.id);
- GetExistingDM(recipient) {
- let dmChannel = this.rest.client.store.getAsArray('channels')
- .filter(channel => channel.recipient)
- .filter(channel => channel.recipient.id === recipient.id);
+ return dmChannel[0];
+ }
- return dmChannel[0];
- }
+ createDM(recipient) {
+ return new Promise((resolve, reject) => {
+ const dmChannel = this.getExistingDM(recipient);
- CreateDM(recipient) {
- return new Promise((resolve, reject) => {
+ if (dmChannel) {
+ return resolve(dmChannel);
+ }
- let dmChannel = this.GetExistingDM(recipient);
+ return this.rest.makeRequest('post', Constants.Endpoints.userChannels(this.rest.client.store.user.id), true, {
+ recipient_id: recipient.id,
+ })
+ .then(data => resolve(this.rest.client.actions.ChannelCreate.handle(data).channel))
+ .catch(reject);
+ });
+ }
- if (dmChannel) {
- return resolve(dmChannel);
- }
+ deleteChannel($channel) {
+ let channel = $channel;
+ return new Promise((resolve, reject) => {
+ if (channel instanceof User || channel instanceof GuildMember) {
+ channel = this.getExistingDM(channel);
+ }
- this.rest.makeRequest('post', Constants.Endpoints.USER_CHANNELS(this.rest.client.store.user.id), true, {
- recipient_id: recipient.id,
- })
- .then(data => resolve(this.rest.client.actions.ChannelCreate.handle(data).channel))
- .catch(reject);
- });
- }
+ this.rest.makeRequest('del', Constants.Endpoints.channel(channel.id), true)
+ .then($data => {
+ const data = $data;
+ data.id = channel.id;
+ resolve(this.rest.client.actions.ChannelDelete.handle(data).channel);
+ })
+ .catch(reject);
+ });
+ }
- DeleteChannel(channel) {
- return new Promise((resolve, reject) => {
- if (channel instanceof User || channel instanceof GuildMember) {
- channel = this.GetExistingDM(channel);
- }
+ updateChannel(channel, $data) {
+ const data = $data;
+ return new Promise((resolve, reject) => {
+ data.name = (data.name || channel.name).trim();
+ data.topic = data.topic || channel.topic;
+ data.position = data.position || channel.position;
+ data.bitrate = data.bitrate || channel.bitrate;
- this.rest.makeRequest('del', Constants.Endpoints.CHANNEL(channel.id), true)
- .then(data => {
- data.id = channel.id;
- resolve(this.rest.client.actions.ChannelDelete.handle(data).channel);
- })
- .catch(reject);
- });
- }
+ this.rest.makeRequest('patch', Constants.Endpoints.channel(channel.id), true, data)
+ .then(newData => {
+ resolve(this.rest.client.actions.ChannelUpdate.handle(newData).updated);
+ })
+ .catch(reject);
+ });
+ }
- UpdateChannel(channel, data) {
- return new Promise((resolve, reject) => {
- data.name = (data.name || channel.name).trim();
- data.topic = data.topic || channel.topic;
- data.position = data.position || channel.position;
- data.bitrate = data.bitrate || channel.bitrate;
+ leaveGuild(guild) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.meGuild(guild.id), true)
+ .then(() => {
+ resolve(this.rest.client.actions.GuildDelete.handle({ id: guild.id }).guild);
+ })
+ .catch(reject);
+ });
+ }
- this.rest.makeRequest('patch', Constants.Endpoints.CHANNEL(channel.id), true, data)
- .then(data => {
- resolve(this.rest.client.actions.ChannelUpdate.handle(data).updated);
- })
- .catch(reject);
- });
- }
+ // untested but probably will work
+ deleteGuild(guild) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.guild(guild.id), true)
+ .then(() => {
+ resolve(this.rest.client.actions.GuildDelete.handle({ id: guild.id }).guild);
+ })
+ .catch(reject);
+ });
+ }
- LeaveGuild(guild) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('del', Constants.Endpoints.ME_GUILD(guild.id), true)
- .then(() => {
- resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild);
- })
- .catch(reject);
- });
- }
+ updateCurrentUser(_data) {
+ return new Promise((resolve, reject) => {
+ const user = this.rest.client.store.user;
+ const data = {};
- // untested but probably will work
- DeleteGuild(guild) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('del', Constants.Endpoints.GUILD(guild.id), true)
- .then(() => {
- resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild);
- })
- .catch(reject);
- });
- }
+ data.username = _data.username || user.username;
+ data.avatar = this.rest.client.resolver.resolveBase64(_data.avatar) || user.avatar;
+ if (!user.bot) {
+ data.password = this.rest.client.store.password;
+ data.email = _data.email || this.rest.client.store.email;
+ data.new_password = _data.newPassword;
+ }
- UpdateCurrentUser(_data) {
- return new Promise((resolve, reject) => {
- let user = this.rest.client.store.user;
- let data = {};
+ this.rest.makeRequest('patch', Constants.Endpoints.me, true, data)
+ .then(newData => resolve(this.rest.client.actions.UserUpdate.handle(newData).updated))
+ .catch(reject);
+ });
+ }
- data.username = _data.username || user.username;
- data.avatar = this.rest.client.resolver.ResolveBase64(_data.avatar) || user.avatar;
- if (!user.bot) {
- data.password = this.rest.client.store.password;
- data.email = _data.email || this.rest.client.store.email;
- data.new_password = _data.newPassword;
- }
+ updateGuild(guild, _data) {
+ return new Promise((resolve, reject) => {
+ /*
+ can contain:
+ name, region, verificationLevel, afkChannel, afkTimeout, icon, owner, splash
+ */
- this.rest.makeRequest('patch', Constants.Endpoints.ME, true, data)
- .then(data => resolve(this.rest.client.actions.UserUpdate.handle(data).updated))
- .catch(reject);
- });
- }
+ const data = {};
- UpdateGuild(guild, _data) {
- return new Promise((resolve, reject) => {
- /*
- can contain:
- name, region, verificationLevel, afkChannel, afkTimeout, icon, owner, splash
- */
+ if (_data.name) {
+ data.name = _data.name;
+ }
- let data = {};
+ if (_data.region) {
+ data.region = _data.region;
+ }
- if (_data.name) {
- data.name = _data.name;
- }
+ if (_data.verificationLevel) {
+ data.verification_level = Number(_data.verificationLevel);
+ }
- if (_data.region) {
- data.region = _data.region;
- }
+ if (_data.afkChannel) {
+ data.afk_channel_id = this.rest.client.resolver.resolveChannel(_data.afkChannel).id;
+ }
- if (_data.verificationLevel) {
- data.verification_level = Number(_data.verificationLevel);
- }
+ if (_data.afkTimeout) {
+ data.afk_timeout = Number(_data.afkTimeout);
+ }
- if (_data.afkChannel) {
- data.afk_channel_id = this.rest.client.resolver.ResolveChannel(_data.afkChannel).id;
- }
+ if (_data.icon) {
+ data.icon = this.rest.client.resolver.resolveBase64(_data.icon);
+ }
- if (_data.afkTimeout) {
- data.afk_timeout = Number(_data.afkTimeout);
- }
+ if (_data.owner) {
+ data.owner_id = this.rest.client.resolver.resolveUser(_data.owner).id;
+ }
- if (_data.icon) {
- data.icon = this.rest.client.resolver.ResolveBase64(_data.icon);
- }
+ if (_data.splash) {
+ data.splash = this.rest.client.resolver.resolveBase64(_data.splash);
+ }
- if (_data.owner) {
- data.owner_id = this.rest.client.resolver.ResolveUser(_data.owner).id;
- }
+ this.rest.makeRequest('patch', Constants.Endpoints.guild(guild.id), true, data)
+ .then(newData => resolve(this.rest.client.actions.GuildUpdate.handle(newData).updated))
+ .catch(reject);
+ });
+ }
- if (_data.splash) {
- data.splash = this.rest.client.resolver.ResolveBase64(_data.splash);
- }
+ kickGuildMember(guild, member) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.guildMember(guild.id, member.id), true)
+ .then(() => {
+ resolve(this.rest.client.actions.GuildMemberRemove.handle({
+ guild_id: guild.id,
+ user: member.user,
+ }).m);
+ })
+ .catch(reject);
+ });
+ }
- this.rest.makeRequest('patch', Constants.Endpoints.GUILD(guild.id), true, data)
- .then(data => resolve(this.rest.client.actions.GuildUpdate.handle(data).updated))
- .catch(reject);
- });
- }
+ createGuildRole(guild) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('post', Constants.Endpoints.guildRoles(guild.id), true)
+ .then(role => {
+ resolve(this.rest.client.actions.GuildRoleCreate.handle({
+ guild_id: guild.id,
+ role,
+ }).role);
+ })
+ .catch(reject);
+ });
+ }
- KickGuildMember(guild, member) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('del', Constants.Endpoints.GUILD_MEMBER(guild.id, member.id), true)
- .then(() => {
- resolve(this.rest.client.actions.GuildMemberRemove.handle({
- guild_id: guild.id,
- user: member.user,
- }).m);
- })
- .catch(reject);
- });
- }
+ deleteGuildRole(role) {
+ return new Promise((resolve, reject) => {
+ this.rest.makeRequest('del', Constants.Endpoints.guildRole(role.guild.id, role.id), true)
+ .then(() => {
+ resolve(this.rest.client.actions.GuildRoleDelete.handle({
+ guild_id: role.guild.id,
+ role_id: role.id,
+ }).role);
+ })
+ .catch(reject);
+ });
+ }
- CreateGuildRole(guild) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('post', Constants.Endpoints.GUILD_ROLES(guild.id), true)
- .then(role => {
- resolve(this.rest.client.actions.GuildRoleCreate.handle({
- guild_id: guild.id,
- role,
- }).role);
- })
- .catch(reject);
- });
- }
+ updateGuildRole(role, _data) {
+ return new Promise((resolve, reject) => {
+ /*
+ can contain:
+ name, position, permissions, color, hoist
+ */
- DeleteGuildRole(role) {
- return new Promise((resolve, reject) => {
- this.rest.makeRequest('del', Constants.Endpoints.GUILD_ROLE(role.guild.id, role.id), true)
- .then(() => {
- resolve(this.rest.client.actions.GuildRoleDelete.handle({
- guild_id: role.guild.id,
- role_id: role.id,
- }).role);
- })
- .catch(reject);
- });
- }
+ const data = {};
- UpdateGuildRole(role, _data) {
- return new Promise((resolve, reject) => {
- /*
- can contain:
- name, position, permissions, color, hoist
- */
+ data.name = _data.name || role.name;
+ data.position = _data.position || role.position;
+ data.color = _data.color || role.color;
- let data = {};
+ if (typeof _data.hoist !== 'undefined') {
+ data.hoist = _data.hoist;
+ } else {
+ data.hoist = role.hoist;
+ }
- data.name = _data.name || role.name;
- data.position = _data.position || role.position;
- data.color = _data.color || role.color;
+ if (_data.permissions) {
+ let perms = 0;
+ for (let perm of _data.permissions) {
+ if (perm instanceof String || typeof perm === 'string') {
+ perm = Constants.PermissionFlags[perm];
+ }
+ perms |= perm;
+ }
+ data.permissions = perms;
+ } else {
+ data.permissions = role.permissions;
+ }
- if (typeof _data.hoist !== 'undefined') {
- data.hoist = _data.hoist;
- } else {
- data.hoist = role.hoist;
- }
-
- if (_data.permissions) {
- let perms = 0;
- for (let perm of _data.permissions) {
- if (perm instanceof String || typeof perm === 'string') {
- perm = Constants.PermissionFlags[perm];
- }
- perms |= perm;
- }
- data.permissions = perms;
- } else {
- data.permissions = role.permissions;
- }
- console.log(data);
- this.rest.makeRequest('patch', Constants.Endpoints.GUILD_ROLE(role.guild.id, role.id), true, data)
- .then(_role => {
- resolve(this.rest.client.actions.GuildRoleUpdate.handle({
- role: _role,
- guild_id: role.guild.id,
- }).updated);
- })
- .catch(reject);
- });
- }
+ this.rest.makeRequest('patch', Constants.Endpoints.guildRole(role.guild.id, role.id), true, data)
+ .then(_role => {
+ resolve(this.rest.client.actions.GuildRoleUpdate.handle({
+ role: _role,
+ guild_id: role.guild.id,
+ }).updated);
+ })
+ .catch(reject);
+ });
+ }
}
module.exports = RESTMethods;
diff --git a/src/client/rest/UserAgentManager.js b/src/client/rest/UserAgentManager.js
index 9fb075fca..12393ffd1 100644
--- a/src/client/rest/UserAgentManager.js
+++ b/src/client/rest/UserAgentManager.js
@@ -1,24 +1,22 @@
-'use strict';
-
const Constants = require('../../util/Constants');
-class UserAgentManager{
- constructor(restManager) {
- this.restManager = restManager;
- this._userAgent = {
- url: 'https://github.com/hydrabolt/discord.js',
- version: Constants.Package.version,
- };
- }
+class UserAgentManager {
+ constructor(restManager) {
+ this.restManager = restManager;
+ this._userAgent = {
+ url: 'https://github.com/hydrabolt/discord.js',
+ version: Constants.Package.version,
+ };
+ }
- set(info) {
- this._userAgent.url = info.url || 'https://github.com/hydrabolt/discord.js';
- this._userAgent.version = info.version || Constants.Package.version;
- }
+ set(info) {
+ this._userAgent.url = info.url || 'https://github.com/hydrabolt/discord.js';
+ this._userAgent.version = info.version || Constants.Package.version;
+ }
- get userAgent() {
- return `DiscordBot (${this._userAgent.url}, ${this._userAgent.version})`;
- }
+ get userAgent() {
+ return `DiscordBot (${this._userAgent.url}, ${this._userAgent.version})`;
+ }
}
module.exports = UserAgentManager;
diff --git a/src/client/websocket/WebSocketManager.js b/src/client/websocket/WebSocketManager.js
index a3d7f08ca..0b30d627d 100644
--- a/src/client/websocket/WebSocketManager.js
+++ b/src/client/websocket/WebSocketManager.js
@@ -1,5 +1,3 @@
-'use strict';
-
const WebSocket = require('ws');
const Constants = require('../../util/Constants');
const zlib = require('zlib');
@@ -8,111 +6,111 @@ const WebSocketManagerDataStore = require('../../structures/datastore/WebSocketM
class WebSocketManager {
- constructor(client) {
- this.client = client;
- this.ws = null;
- this.packetManager = new PacketManager(this);
- this.store = new WebSocketManagerDataStore();
- this.status = Constants.Status.IDLE;
- }
+ constructor(client) {
+ this.client = client;
+ this.ws = null;
+ this.packetManager = new PacketManager(this);
+ this.store = new WebSocketManagerDataStore();
+ this.status = Constants.Status.IDLE;
+ }
- connect(gateway) {
- this.status = Constants.Status.CONNECTING;
- this.store.gateway = gateway;
- gateway += `/?v=${this.client.options.protocol_version}`;
- this.ws = new WebSocket(gateway);
- this.ws.onopen = () => this.EventOpen();
- this.ws.onclose = () => this.EventClose();
- this.ws.onmessage = (e) => this.EventMessage(e);
- this.ws.onerror = (e) => this.EventError(e);
- }
+ connect(gateway) {
+ this.status = Constants.Status.CONNECTING;
+ this.store.gateway = `${gateway}/?v=${this.client.options.protocol_version}`;
+ this.ws = new WebSocket(gateway);
+ this.ws.onopen = () => this.eventOpen();
+ this.ws.onclose = () => this.eventClose();
+ this.ws.onmessage = (e) => this.eventMessage(e);
+ this.ws.onerror = (e) => this.eventError(e);
+ }
- send(data) {
- if (this.ws.readyState === WebSocket.OPEN) {
- this.ws.send(JSON.stringify(data));
- }
- }
+ send(data) {
+ if (this.ws.readyState === WebSocket.OPEN) {
+ this.ws.send(JSON.stringify(data));
+ }
+ }
- EventOpen() {
- if (this.reconnecting) {
- this._sendResume();
- } else {
- this._sendNewIdentify();
- }
- }
+ eventOpen() {
+ if (this.reconnecting) {
+ this._sendResume();
+ } else {
+ this._sendNewIdentify();
+ }
+ }
- _sendResume() {
- let payload = {
- token: this.client.store.token,
- session_id: this.store.sessionID,
- seq: this.store.sequence,
- };
+ _sendResume() {
+ const payload = {
+ token: this.client.store.token,
+ session_id: this.store.sessionID,
+ seq: this.store.sequence,
+ };
- this.send({
- op: Constants.OPCodes.RESUME,
- d: payload,
- });
- }
+ this.send({
+ op: Constants.OPCodes.RESUME,
+ d: payload,
+ });
+ }
- _sendNewIdentify() {
- this.reconnecting = false;
- let payload = this.client.options.ws;
- payload.token = this.client.store.token;
+ _sendNewIdentify() {
+ this.reconnecting = false;
+ const payload = this.client.options.ws;
+ payload.token = this.client.store.token;
- this.send({
- op: Constants.OPCodes.IDENTIFY,
- d: payload,
- });
- }
+ this.send({
+ op: Constants.OPCodes.IDENTIFY,
+ d: payload,
+ });
+ }
- EventClose() {
- if (!this.reconnecting) {
- this.tryReconnect();
- }
- }
+ eventClose() {
+ if (!this.reconnecting) {
+ this.tryReconnect();
+ }
+ }
- EventMessage(event) {
- let packet;
- try {
- if (event.binary) {
- event.data = zlib.inflateSync(event.data).toString();
- }
+ eventMessage($event) {
+ let packet;
+ const event = $event;
+ try {
+ if (event.binary) {
+ event.data = zlib.inflateSync(event.data).toString();
+ }
- packet = JSON.parse(event.data);
- } catch (e) {
- return this.EventError(Constants.Errors.BAD_WS_MESSAGE);
- }
+ packet = JSON.parse(event.data);
+ } catch (e) {
+ return this.eventError(Constants.Errors.BAD_WS_MESSAGE);
+ }
- this.packetManager.handle(packet);
- }
+ return this.packetManager.handle(packet);
+ }
- EventError(e) {
- this.tryReconnect();
- }
+ EventError() {
+ this.tryReconnect();
+ }
- checkIfReady() {
- if (this.status !== Constants.Status.READY) {
- let unavailableCount = 0;
+ checkIfReady() {
+ if (this.status !== Constants.Status.READY) {
+ let unavailableCount = 0;
- for (let guildID in this.client.store.data.guilds) {
- unavailableCount += this.client.store.data.guilds[guildID].available ? 0 : 1;
- }
+ for (const guildID in this.client.store.data.guilds) {
+ unavailableCount += this.client.store.data.guilds[guildID].available ? 0 : 1;
+ }
- if (unavailableCount === 0) {
- this.status = Constants.Status.READY;
- this.client.emit(Constants.Events.READY);
- this.packetManager.handleQueue();
- }
- }
- }
+ if (unavailableCount === 0) {
+ this.status = Constants.Status.READY;
+ this.client.emit(Constants.Events.READY);
+ this.packetManager.handleQueue();
+ }
+ }
+ }
- tryReconnect() {
- this.status = Constants.Status.RECONNECTING;
- this.ws.close();
- this.packetManager.handleQueue();
- this.client.emit(Constants.Events.RECONNECTING);
- this.connect(this.store.gateway);
- }
+ tryReconnect() {
+ this.status = Constants.Status.RECONNECTING;
+ this.ws.close();
+ this.packetManager.handleQueue();
+ this.client.emit(Constants.Events.RECONNECTING);
+ this.connect(this.store.gateway);
+ }
}
module.exports = WebSocketManager;
diff --git a/src/client/websocket/packets/WebSocketPacketManager.js b/src/client/websocket/packets/WebSocketPacketManager.js
index b4e123033..dd8615637 100644
--- a/src/client/websocket/packets/WebSocketPacketManager.js
+++ b/src/client/websocket/packets/WebSocketPacketManager.js
@@ -1,100 +1,97 @@
-'use strict';
-
const Constants = require('../../../util/Constants');
const BeforeReadyWhitelist = [
- Constants.WSEvents.READY,
- Constants.WSEvents.GUILD_CREATE,
- Constants.WSEvents.GUILD_DELETE,
+ Constants.WSEvents.READY,
+ Constants.WSEvents.GUILD_CREATE,
+ Constants.WSEvents.GUILD_DELETE,
];
class WebSocketPacketManager {
- constructor(websocketManager) {
- this.ws = websocketManager;
- this.handlers = {};
- this.queue = [];
+ constructor(websocketManager) {
+ this.ws = websocketManager;
+ this.handlers = {};
+ this.queue = [];
- this.register(Constants.WSEvents.READY, 'Ready');
- this.register(Constants.WSEvents.GUILD_CREATE, 'GuildCreate');
- this.register(Constants.WSEvents.GUILD_DELETE, 'GuildDelete');
- this.register(Constants.WSEvents.GUILD_UPDATE, 'GuildUpdate');
- this.register(Constants.WSEvents.GUILD_BAN_ADD, 'GuildBanAdd');
- this.register(Constants.WSEvents.GUILD_BAN_REMOVE, 'GuildBanRemove');
- this.register(Constants.WSEvents.GUILD_MEMBER_ADD, 'GuildMemberAdd');
- this.register(Constants.WSEvents.GUILD_MEMBER_REMOVE, 'GuildMemberRemove');
- this.register(Constants.WSEvents.GUILD_MEMBER_UPDATE, 'GuildMemberUpdate');
- this.register(Constants.WSEvents.GUILD_ROLE_CREATE, 'GuildRoleCreate');
- this.register(Constants.WSEvents.GUILD_ROLE_DELETE, 'GuildRoleDelete');
- this.register(Constants.WSEvents.GUILD_ROLE_UPDATE, 'GuildRoleUpdate');
- this.register(Constants.WSEvents.GUILD_MEMBERS_CHUNK, 'GuildMembersChunk');
- this.register(Constants.WSEvents.CHANNEL_CREATE, 'ChannelCreate');
- this.register(Constants.WSEvents.CHANNEL_DELETE, 'ChannelDelete');
- this.register(Constants.WSEvents.CHANNEL_UPDATE, 'ChannelUpdate');
- this.register(Constants.WSEvents.PRESENCE_UPDATE, 'PresenceUpdate');
- this.register(Constants.WSEvents.USER_UPDATE, 'UserUpdate');
- this.register(Constants.WSEvents.VOICE_STATE_UPDATE, 'VoiceStateUpdate');
- this.register(Constants.WSEvents.TYPING_START, 'TypingStart');
- this.register(Constants.WSEvents.MESSAGE_CREATE, 'MessageCreate');
- this.register(Constants.WSEvents.MESSAGE_DELETE, 'MessageDelete');
- this.register(Constants.WSEvents.MESSAGE_UPDATE, 'MessageUpdate');
- }
+ this.register(Constants.WSEvents.READY, 'Ready');
+ this.register(Constants.WSEvents.GUILD_CREATE, 'GuildCreate');
+ this.register(Constants.WSEvents.GUILD_DELETE, 'GuildDelete');
+ this.register(Constants.WSEvents.GUILD_UPDATE, 'GuildUpdate');
+ this.register(Constants.WSEvents.GUILD_BAN_ADD, 'GuildBanAdd');
+ this.register(Constants.WSEvents.GUILD_BAN_REMOVE, 'GuildBanRemove');
+ this.register(Constants.WSEvents.GUILD_MEMBER_ADD, 'GuildMemberAdd');
+ this.register(Constants.WSEvents.GUILD_MEMBER_REMOVE, 'GuildMemberRemove');
+ this.register(Constants.WSEvents.GUILD_MEMBER_UPDATE, 'GuildMemberUpdate');
+ this.register(Constants.WSEvents.GUILD_ROLE_CREATE, 'GuildRoleCreate');
+ this.register(Constants.WSEvents.GUILD_ROLE_DELETE, 'GuildRoleDelete');
+ this.register(Constants.WSEvents.GUILD_ROLE_UPDATE, 'GuildRoleUpdate');
+ this.register(Constants.WSEvents.GUILD_MEMBERS_CHUNK, 'GuildMembersChunk');
+ this.register(Constants.WSEvents.CHANNEL_CREATE, 'ChannelCreate');
+ this.register(Constants.WSEvents.CHANNEL_DELETE, 'ChannelDelete');
+ this.register(Constants.WSEvents.CHANNEL_UPDATE, 'ChannelUpdate');
+ this.register(Constants.WSEvents.PRESENCE_UPDATE, 'PresenceUpdate');
+ this.register(Constants.WSEvents.USER_UPDATE, 'UserUpdate');
+ this.register(Constants.WSEvents.VOICE_STATE_UPDATE, 'VoiceStateUpdate');
+ this.register(Constants.WSEvents.TYPING_START, 'TypingStart');
+ this.register(Constants.WSEvents.MESSAGE_CREATE, 'MessageCreate');
+ this.register(Constants.WSEvents.MESSAGE_DELETE, 'MessageDelete');
+ this.register(Constants.WSEvents.MESSAGE_UPDATE, 'MessageUpdate');
+ }
- get client() {
- return this.ws.client;
- }
+ get client() {
+ return this.ws.client;
+ }
- register(event, handle) {
- let Handler = require(`./handlers/${handle}`);
- this.handlers[event] = new Handler(this);
- }
+ register(event, handle) {
+ const Handler = require(`./handlers/${handle}`);
+ this.handlers[event] = new Handler(this);
+ }
- handleQueue() {
- for (let packetIndex in this.queue) {
- this.handle(this.queue[packetIndex]);
- this.queue.splice(packetIndex, 1);
- }
- }
+ handleQueue() {
+ this.queue.forEach((element, index) => {
+ this.handle(this.queue[index]);
+ this.queue.splice(index, 1);
+ });
+ }
- setSequence(s) {
- if (s && s > this.ws.store.sequence) {
- this.ws.store.sequence = s;
- }
- }
+ setSequence(s) {
+ if (s && s > this.ws.store.sequence) {
+ this.ws.store.sequence = s;
+ }
+ }
- handle(packet) {
+ handle(packet) {
+ if (packet.op === Constants.OPCodes.RECONNECT) {
+ this.setSequence(packet.s);
+ this.ws.tryReconnect();
+ return false;
+ }
- if (packet.op === Constants.OPCodes.RECONNECT) {
- this.setSequence(packet.s);
- this.ws.tryReconnect();
- return;
- }
+ if (packet.op === Constants.OPCodes.INVALID_SESSION) {
+ this.ws._sendNewIdentify();
+ return false;
+ }
- if (packet.op === Constants.OPCodes.INVALID_SESSION) {
- this.ws._sendNewIdentify();
- return;
- }
+ if (this.ws.reconnecting) {
+ this.ws.reconnecting = false;
+ this.ws.checkIfReady();
+ }
- if (this.ws.reconnecting) {
- this.ws.reconnecting = false;
- this.ws.checkIfReady();
- }
+ this.setSequence(packet.s);
- this.setSequence(packet.s);
+ if (this.ws.status !== Constants.Status.READY) {
+ if (BeforeReadyWhitelist.indexOf(packet.t) === -1) {
+ this.queue.push(packet);
+ return false;
+ }
+ }
- if (this.ws.status !== Constants.Status.READY) {
- if (BeforeReadyWhitelist.indexOf(packet.t) === -1) {
- this.queue.push(packet);
- return;
- }
- }
+ if (this.handlers[packet.t]) {
+ return this.handlers[packet.t].handle(packet);
+ }
- if (this.handlers[packet.t]) {
- return this.handlers[packet.t].handle(packet);
- }
-
- return false;
- }
+ return false;
+ }
}
diff --git a/src/client/websocket/packets/handlers/AbstractHandler.js b/src/client/websocket/packets/handlers/AbstractHandler.js
index 9ab096dd6..ec744c487 100644
--- a/src/client/websocket/packets/handlers/AbstractHandler.js
+++ b/src/client/websocket/packets/handlers/AbstractHandler.js
@@ -1,14 +1,12 @@
-'use strict';
-
class AbstractHandler {
- constructor(packetManager) {
- this.packetManager = packetManager;
- }
+ constructor(packetManager) {
+ this.packetManager = packetManager;
+ }
- handle(packet) {
-
- }
+ handle(packet) {
+ return packet;
+ }
}
module.exports = AbstractHandler;
diff --git a/src/client/websocket/packets/handlers/ChannelCreate.js b/src/client/websocket/packets/handlers/ChannelCreate.js
index 100b02785..bf81ee6ce 100644
--- a/src/client/websocket/packets/handlers/ChannelCreate.js
+++ b/src/client/websocket/packets/handlers/ChannelCreate.js
@@ -1,32 +1,20 @@
-'use strict';
-
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-
-const ClientUser = Structure('ClientUser');
-const Guild = Structure('Guild');
-const DMChannel = Structure('DMChannel');
const Constants = require('../../../../util/Constants');
class ChannelCreateHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ const response = client.actions.ChannelCreate.handle(data);
- let response = client.actions.ChannelCreate.handle(data);
+ if (response.channel) {
+ client.emit(Constants.Events.CHANNEL_CREATE, response.channel);
+ }
+ }
- if (response.channel) {
- client.emit(Constants.Events.CHANNEL_CREATE, response.channel);
- }
-
- }
-
-};
+}
module.exports = ChannelCreateHandler;
diff --git a/src/client/websocket/packets/handlers/ChannelDelete.js b/src/client/websocket/packets/handlers/ChannelDelete.js
index 82a6eed6f..fc47f1858 100644
--- a/src/client/websocket/packets/handlers/ChannelDelete.js
+++ b/src/client/websocket/packets/handlers/ChannelDelete.js
@@ -1,31 +1,20 @@
-'use strict';
-
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-
-const ClientUser = Structure('ClientUser');
-const Guild = Structure('Guild');
-const ServerChannel = Structure('ServerChannel');
const Constants = require('../../../../util/Constants');
class ChannelDeleteHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ const response = client.actions.ChannelDelete.handle(data);
- let response = client.actions.ChannelDelete.handle(data);
+ if (response.channel) {
+ client.emit(Constants.Events.CHANNEL_DELETE, response.channel);
+ }
+ }
- if (response.channel) {
- client.emit(Constants.Events.CHANNEL_DELETE, response.channel);
- }
- }
-
-};
+}
module.exports = ChannelDeleteHandler;
diff --git a/src/client/websocket/packets/handlers/ChannelUpdate.js b/src/client/websocket/packets/handlers/ChannelUpdate.js
index 41491a103..070cdcd24 100644
--- a/src/client/websocket/packets/handlers/ChannelUpdate.js
+++ b/src/client/websocket/packets/handlers/ChannelUpdate.js
@@ -1,28 +1,14 @@
-'use strict';
-
-const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-
-const ClientUser = Structure('ClientUser');
-const Guild = Structure('Guild');
-const ServerChannel = Structure('ServerChannel');
-
-const Constants = require('../../../../util/Constants');
-const CloneObject = require('../../../../util/CloneObject');
-
-class ChannelUpdateHandler extends AbstractHandler {
-
- constructor(packetManager) {
- super(packetManager);
- }
-
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
-
- client.actions.ChannelUpdate.handle(data);
- }
-
-};
-
-module.exports = ChannelUpdateHandler;
+const AbstractHandler = require('./AbstractHandler');
+
+class ChannelUpdateHandler extends AbstractHandler {
+
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
+
+ client.actions.ChannelUpdate.handle(data);
+ }
+
+}
+
+module.exports = ChannelUpdateHandler;
diff --git a/src/client/websocket/packets/handlers/GuildBanAdd.js b/src/client/websocket/packets/handlers/GuildBanAdd.js
index 7294b2fca..11b336961 100644
--- a/src/client/websocket/packets/handlers/GuildBanAdd.js
+++ b/src/client/websocket/packets/handlers/GuildBanAdd.js
@@ -1,33 +1,22 @@
-'use strict';
-
// ##untested handler##
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-
-const ClientUser = Structure('ClientUser');
-const Guild = Structure('Guild');
-
const Constants = require('../../../../util/Constants');
class GuildBanAddHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ const guild = client.store.get('guilds', data.guild_id);
+ const user = client.store.get('users', data.user.id);
- let guild = client.store.get('guilds', data.guild_id);
- let user = client.store.get('users', data.user.id);
+ if (guild && user) {
+ client.emit(Constants.Events.GUILD_BAN_ADD, guild, user);
+ }
+ }
- if (guild && user) {
- client.emit(Constants.Events.GUILD_BAN_ADD, guild, user);
- }
- }
-
-};
+}
module.exports = GuildBanAddHandler;
diff --git a/src/client/websocket/packets/handlers/GuildBanRemove.js b/src/client/websocket/packets/handlers/GuildBanRemove.js
index ec792f1bf..1a41f777a 100644
--- a/src/client/websocket/packets/handlers/GuildBanRemove.js
+++ b/src/client/websocket/packets/handlers/GuildBanRemove.js
@@ -1,33 +1,23 @@
-'use strict';
-
// ##untested handler##
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-
-const ClientUser = Structure('ClientUser');
-const Guild = Structure('Guild');
const Constants = require('../../../../util/Constants');
class GuildBanRemoveHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ const guild = client.store.get('guilds', data.guild_id);
+ const user = client.store.get('users', data.user.id);
- let guild = client.store.get('guilds', data.guild_id);
- let user = client.store.get('users', data.user.id);
+ if (guild && user) {
+ client.emit(Constants.Events.GUILD_BAN_REMOVE, guild, user);
+ }
+ }
- if (guild && user) {
- client.emit(Constants.Events.GUILD_BAN_REMOVE, guild, user);
- }
- }
-
-};
+}
module.exports = GuildBanRemoveHandler;
diff --git a/src/client/websocket/packets/handlers/GuildCreate.js b/src/client/websocket/packets/handlers/GuildCreate.js
index 96777a79d..f39b21302 100644
--- a/src/client/websocket/packets/handlers/GuildCreate.js
+++ b/src/client/websocket/packets/handlers/GuildCreate.js
@@ -1,38 +1,25 @@
-'use strict';
-
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-
-const ClientUser = Structure('ClientUser');
-const Guild = Structure('Guild');
-
-const Constants = require('../../../../util/Constants');
class GuildCreateHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ const guild = client.store.get('guilds', data.id);
- let guild = client.store.get('guilds', 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.store.newGuild(data);
+ }
+ }
- if (guild) {
- if (!guild.available && !data.unavailable) {
- // a newly available guild
- guild.setup(data);
- this.packetManager.ws.checkIfReady();
- }
- } else {
- // a new guild
- client.store.NewGuild(data);
- }
-
- }
-
-};
+}
module.exports = GuildCreateHandler;
diff --git a/src/client/websocket/packets/handlers/GuildDelete.js b/src/client/websocket/packets/handlers/GuildDelete.js
index 05319a5cb..a86dbd2db 100644
--- a/src/client/websocket/packets/handlers/GuildDelete.js
+++ b/src/client/websocket/packets/handlers/GuildDelete.js
@@ -1,31 +1,19 @@
-'use strict';
-
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-
-const ClientUser = Structure('ClientUser');
-const Guild = Structure('Guild');
-
const Constants = require('../../../../util/Constants');
class GuildDeleteHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ const response = client.actions.GuildDelete.handle(data);
- let response = client.actions.GuildDelete.handle(data);
+ if (response.guild) {
+ client.emit(Constants.Events.GUILD_DELETE, response.guild);
+ }
+ }
- if (response.guild) {
- client.emit(Constants.Events.GUILD_DELETE, response.guild);
- }
-
- }
-
-};
+}
module.exports = GuildDeleteHandler;
diff --git a/src/client/websocket/packets/handlers/GuildMemberAdd.js b/src/client/websocket/packets/handlers/GuildMemberAdd.js
index 23a475f96..8f9101fb8 100644
--- a/src/client/websocket/packets/handlers/GuildMemberAdd.js
+++ b/src/client/websocket/packets/handlers/GuildMemberAdd.js
@@ -1,32 +1,20 @@
-'use strict';
-
// ##untested handler##
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-
-const ClientUser = Structure('ClientUser');
-const Guild = Structure('Guild');
-
-const Constants = require('../../../../util/Constants');
class GuildMemberAddHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ const guild = client.store.get('guilds', data.guild_id);
- let guild = client.store.get('guilds', data.guild_id);
+ if (guild) {
+ guild._addMember(data);
+ }
+ }
- if (guild) {
- guild._addMember(data);
- }
- }
-
-};
+}
module.exports = GuildMemberAddHandler;
diff --git a/src/client/websocket/packets/handlers/GuildMemberRemove.js b/src/client/websocket/packets/handlers/GuildMemberRemove.js
index cf61c816b..2f8571e58 100644
--- a/src/client/websocket/packets/handlers/GuildMemberRemove.js
+++ b/src/client/websocket/packets/handlers/GuildMemberRemove.js
@@ -1,28 +1,16 @@
-'use strict';
-
// ##untested handler##
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-
-const ClientUser = Structure('ClientUser');
-const Guild = Structure('Guild');
-
-const Constants = require('../../../../util/Constants');
class GuildMemberRemoveHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ client.actions.GuildMemberRemove.handle(data);
+ }
- let response = client.actions.GuildMemberRemove.handle(data);
- }
-
-};
+}
module.exports = GuildMemberRemoveHandler;
diff --git a/src/client/websocket/packets/handlers/GuildMemberUpdate.js b/src/client/websocket/packets/handlers/GuildMemberUpdate.js
index 20455a216..d5f6f7145 100644
--- a/src/client/websocket/packets/handlers/GuildMemberUpdate.js
+++ b/src/client/websocket/packets/handlers/GuildMemberUpdate.js
@@ -1,35 +1,23 @@
-'use strict';
-
// ##untested handler##
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-
-const ClientUser = Structure('ClientUser');
-const Guild = Structure('Guild');
-
-const Constants = require('../../../../util/Constants');
class GuildMemberUpdateHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ const guild = client.store.get('guilds', data.guild_id);
- let guild = client.store.get('guilds', data.guild_id);
+ if (guild) {
+ const member = guild.store.get('members', data.user.id);
+ if (member) {
+ guild._updateMember(member, data);
+ }
+ }
+ }
- if (guild) {
- let member = guild.store.get('members', data.user.id);
- if (member) {
- guild._updateMember(member, data);
- }
- }
- }
-
-};
+}
module.exports = GuildMemberUpdateHandler;
diff --git a/src/client/websocket/packets/handlers/GuildMembersChunk.js b/src/client/websocket/packets/handlers/GuildMembersChunk.js
index 3cd2ba516..5949580dd 100644
--- a/src/client/websocket/packets/handlers/GuildMembersChunk.js
+++ b/src/client/websocket/packets/handlers/GuildMembersChunk.js
@@ -1,33 +1,25 @@
-'use strict';
-
// ##untested##
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
const Constants = require('../../../../util/Constants');
-const CloneObject = require('../../../../util/CloneObject');
class GuildMembersChunkHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
+ const guild = client.store.get('guilds', data.guild_id);
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
- let guild = client.store.get('guilds', data.guild_id);
+ const members = [];
+ if (guild) {
+ for (const member of guild.members) {
+ members.push(guild._addMember(member, true));
+ }
+ }
- let members = [];
- if (guild) {
- for (let member of guild.members) {
- members.push(guild._addMember(member, true));
- }
- }
+ client.emit(Constants.Events.GUILD_MEMBERS_CHUNK, guild, members);
+ }
- client.emit(Constants.Events.GUILD_MEMBERS_CHUNK, guild, members);
- }
-
-};
+}
module.exports = GuildMembersChunkHandler;
diff --git a/src/client/websocket/packets/handlers/GuildRoleCreate.js b/src/client/websocket/packets/handlers/GuildRoleCreate.js
index c2ffdbb43..6b791bfb3 100644
--- a/src/client/websocket/packets/handlers/GuildRoleCreate.js
+++ b/src/client/websocket/packets/handlers/GuildRoleCreate.js
@@ -1,25 +1,14 @@
-'use strict';
-
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-const Constants = require('../../../../util/Constants');
-
-const Role = Structure('Role');
-const Guild = Structure('Guild');
class GuildRoleCreateHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ client.actions.GuildRoleCreate.handle(data);
+ }
- let response = client.actions.GuildRoleCreate.handle(data);
- }
-
-};
+}
module.exports = GuildRoleCreateHandler;
diff --git a/src/client/websocket/packets/handlers/GuildRoleDelete.js b/src/client/websocket/packets/handlers/GuildRoleDelete.js
index 2214a7982..17135e20a 100644
--- a/src/client/websocket/packets/handlers/GuildRoleDelete.js
+++ b/src/client/websocket/packets/handlers/GuildRoleDelete.js
@@ -1,25 +1,14 @@
-'use strict';
-
-const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-const Constants = require('../../../../util/Constants');
-
-const Role = Structure('Role');
-const Guild = Structure('Guild');
-
-class GuildRoleDeleteHandler extends AbstractHandler {
-
- constructor(packetManager) {
- super(packetManager);
- }
-
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
-
- let response = client.actions.GuildRoleDelete.handle(data);
- }
-
-};
-
-module.exports = GuildRoleDeleteHandler;
+const AbstractHandler = require('./AbstractHandler');
+
+class GuildRoleDeleteHandler extends AbstractHandler {
+
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
+
+ client.actions.GuildRoleDelete.handle(data);
+ }
+
+}
+
+module.exports = GuildRoleDeleteHandler;
diff --git a/src/client/websocket/packets/handlers/GuildRoleUpdate.js b/src/client/websocket/packets/handlers/GuildRoleUpdate.js
index 98005bc02..8fea7271f 100644
--- a/src/client/websocket/packets/handlers/GuildRoleUpdate.js
+++ b/src/client/websocket/packets/handlers/GuildRoleUpdate.js
@@ -1,26 +1,14 @@
-'use strict';
-
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-const Constants = require('../../../../util/Constants');
-const CloneObject = require('../../../../util/CloneObject');
-
-const Role = Structure('Role');
-const Guild = Structure('Guild');
class GuildRoleUpdateHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ client.actions.GuildRoleUpdate.handle(data);
+ }
- let response = client.actions.GuildRoleUpdate.handle(data);
- }
-
-};
+}
module.exports = GuildRoleUpdateHandler;
diff --git a/src/client/websocket/packets/handlers/GuildUpdate.js b/src/client/websocket/packets/handlers/GuildUpdate.js
index 7a44eaabc..b022fb688 100644
--- a/src/client/websocket/packets/handlers/GuildUpdate.js
+++ b/src/client/websocket/packets/handlers/GuildUpdate.js
@@ -1,28 +1,14 @@
-'use strict';
-
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-
-const ClientUser = Structure('ClientUser');
-const Guild = Structure('Guild');
-
-const Constants = require('../../../../util/Constants');
-const CloneObject = require('../../../../util/CloneObject');
class GuildUpdateHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ client.actions.GuildUpdate.handle(data);
+ }
- let response = client.actions.GuildUpdate.handle(data);
-
- }
-
-};
+}
module.exports = GuildUpdateHandler;
diff --git a/src/client/websocket/packets/handlers/MessageCreate.js b/src/client/websocket/packets/handlers/MessageCreate.js
index 76241e37e..fcbd8028c 100644
--- a/src/client/websocket/packets/handlers/MessageCreate.js
+++ b/src/client/websocket/packets/handlers/MessageCreate.js
@@ -1,29 +1,19 @@
-'use strict';
-
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
const Constants = require('../../../../util/Constants');
-const Message = Structure('Message');
-const Guild = Structure('Guild');
-
class MessageCreateHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ const response = client.actions.MessageCreate.handle(data);
- let response = client.actions.MessageCreate.handle(data);
+ if (response.m) {
+ client.emit(Constants.Events.MESSAGE_CREATE, response.m);
+ }
+ }
- if (response.m) {
- client.emit(Constants.Events.MESSAGE_CREATE, response.m);
- }
- }
-
-};
+}
module.exports = MessageCreateHandler;
diff --git a/src/client/websocket/packets/handlers/MessageDelete.js b/src/client/websocket/packets/handlers/MessageDelete.js
index c3457f920..e29b149d4 100644
--- a/src/client/websocket/packets/handlers/MessageDelete.js
+++ b/src/client/websocket/packets/handlers/MessageDelete.js
@@ -1,29 +1,19 @@
-'use strict';
-
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
const Constants = require('../../../../util/Constants');
-const Message = Structure('Message');
-const Guild = Structure('Guild');
-
class MessageDeleteHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ const response = client.actions.MessageDelete.handle(data);
- let response = client.actions.MessageDelete.handle(data);
+ if (response.m) {
+ client.emit(Constants.Events.MESSAGE_DELETE, response.m);
+ }
+ }
- if (response.m) {
- client.emit(Constants.Events.MESSAGE_DELETE, response.m);
- }
- }
-
-};
+}
module.exports = MessageDeleteHandler;
diff --git a/src/client/websocket/packets/handlers/MessageUpdate.js b/src/client/websocket/packets/handlers/MessageUpdate.js
index 69ac2aa3a..56b8992b4 100644
--- a/src/client/websocket/packets/handlers/MessageUpdate.js
+++ b/src/client/websocket/packets/handlers/MessageUpdate.js
@@ -1,27 +1,14 @@
-'use strict';
-
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-const Constants = require('../../../../util/Constants');
-const CloneObject = require('../../../../util/CloneObject');
-
-const Message = Structure('Message');
-const Guild = Structure('Guild');
class MessageUpdateHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ client.actions.MessageUpdate.handle(data);
+ }
- let response = client.actions.MessageUpdate.handle(data);
-
- }
-
-};
+}
module.exports = MessageUpdateHandler;
diff --git a/src/client/websocket/packets/handlers/PresenceUpdate.js b/src/client/websocket/packets/handlers/PresenceUpdate.js
index e3c5e4f1a..51732c726 100644
--- a/src/client/websocket/packets/handlers/PresenceUpdate.js
+++ b/src/client/websocket/packets/handlers/PresenceUpdate.js
@@ -1,75 +1,66 @@
-'use strict';
-
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
const Constants = require('../../../../util/Constants');
-const CloneObject = require('../../../../util/CloneObject');
-
-const Role = Structure('User');
+const cloneObject = require('../../../../util/CloneObject');
class PresenceUpdateHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
+ let user = client.store.get('users', data.user.id);
+ const guild = client.store.get('guilds', data.guild_id);
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
- let user = client.store.get('users', data.user.id);
- let guild = client.store.get('guilds', data.guild_id);
+ function makeUser(newUser) {
+ return client.store.newUser(newUser);
+ }
- function makeUser(user) {
- return client.store.NewUser(user);
- }
+ // step 1
+ if (!user) {
+ if (data.user.username) {
+ user = makeUser(data.user);
+ } else {
+ return;
+ }
+ }
- // step 1
- if (!user) {
- if (data.user.username) {
- user = makeUser(data.user);
- }else {
- return;
- }
- }
+ if (guild) {
+ const memberInGuild = guild.store.get('members', user.id);
+ if (!memberInGuild) {
+ const member = guild._addMember({
+ user,
+ roles: data.roles,
+ deaf: false,
+ mute: false,
+ }, true);
+ client.emit(Constants.Events.GUILD_MEMBER_AVAILABLE, guild, member);
+ }
+ }
- if (guild) {
- let memberInGuild = guild.store.get('members', user.id);
- if (!memberInGuild) {
- let member = guild._addMember({
- user,
- roles: data.roles,
- deaf: false,
- mute: false,
- }, true);
- client.emit(Constants.Events.GUILD_MEMBER_AVAILABLE, guild, member);
- }
- }
+ data.user.username = data.user.username || user.username;
+ data.user.id = data.user.id || user.id;
+ data.user.discriminator = data.user.discriminator || user.discriminator;
- data.user.username = data.user.username || user.username;
- data.user.id = data.user.id || user.id;
- data.user.discriminator = data.user.discriminator || user.discriminator;
+ // comment out avatar patching as it causes bugs (see #297)
+ // data.user.avatar = data.user.avatar || user.avatar;
+ data.user.status = data.status || user.status;
+ data.user.game = data.game;
- // comment out avatar patching as it causes bugs (see #297)
- // data.user.avatar = data.user.avatar || user.avatar;
- data.user.status = data.status || user.status;
- data.user.game = data.game;
+ const same = (
+ data.user.username === user.username &&
+ data.user.id === user.id &&
+ data.user.discriminator === user.discriminator &&
+ data.user.avatar === user.avatar &&
+ data.user.status === user.status &&
+ JSON.stringify(data.user.game) === JSON.stringify(user.game)
+ );
- let same = (
- data.user.username === user.username &&
- data.user.id === user.id &&
- data.user.discriminator === user.discriminator &&
- data.user.avatar === user.avatar &&
- data.user.status === user.status &&
- JSON.stringify(data.user.game) === JSON.stringify(user.game)
- );
+ if (!same) {
+ const oldUser = cloneObject(user);
+ user.setup(data.user);
+ client.emit(Constants.Events.PRESENCE_UPDATE, oldUser, user);
+ }
+ }
- if (!same) {
- let oldUser = CloneObject(user);
- user.setup(data.user);
- client.emit(Constants.Events.PRESENCE_UPDATE, oldUser, user);
- }
- }
-
-};
+}
module.exports = PresenceUpdateHandler;
diff --git a/src/client/websocket/packets/handlers/Ready.js b/src/client/websocket/packets/handlers/Ready.js
index ffd4cd0cb..e37d0a758 100644
--- a/src/client/websocket/packets/handlers/Ready.js
+++ b/src/client/websocket/packets/handlers/Ready.js
@@ -1,39 +1,30 @@
-'use strict';
-
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-const ClientUser = Structure('ClientUser');
-const Guild = Structure('Guild');
-const DMChannel = Structure('DMChannel');
+const getStructure = name => require(`../../../../structures/${name}`);
+const ClientUser = getStructure('ClientUser');
class ReadyHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
+ client.manager.setupKeepAlive(data.heartbeat_interval);
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
- client.manager.setupKeepAlive(data.heartbeat_interval);
+ client.store.user = client.store.add('users', new ClientUser(client, data.user));
- client.store.user = client.store.add('users', new ClientUser(client, data.user));
+ for (const guild of data.guilds) {
+ client.store.newGuild(guild);
+ }
- for (let guild of data.guilds) {
- client.store.NewGuild(guild);
- }
+ for (const privateDM of data.private_channels) {
+ client.store.newChannel(privateDM);
+ }
- for (let privateDM of data.private_channels) {
- client.store.NewChannel(privateDM);
- }
+ this.packetManager.ws.store.sessionID = data.session_id;
- this.packetManager.ws.store.sessionID = data.session_id;
+ this.packetManager.ws.checkIfReady();
+ }
- this.packetManager.ws.checkIfReady();
-
- }
-
-};
+}
module.exports = ReadyHandler;
diff --git a/src/client/websocket/packets/handlers/TypingStart.js b/src/client/websocket/packets/handlers/TypingStart.js
index c64ff705a..421cba9b0 100644
--- a/src/client/websocket/packets/handlers/TypingStart.js
+++ b/src/client/websocket/packets/handlers/TypingStart.js
@@ -1,60 +1,52 @@
-'use strict';
-
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
const Constants = require('../../../../util/Constants');
-const CloneObject = require('../../../../util/CloneObject');
class TypingData {
- constructor(since, lastTimestamp, _timeout) {
- this.since = since;
- this.lastTimestamp = lastTimestamp;
- this._timeout = _timeout;
- }
+ constructor(since, lastTimestamp, _timeout) {
+ this.since = since;
+ this.lastTimestamp = lastTimestamp;
+ this._timeout = _timeout;
+ }
- resetTimeout(_timeout) {
- clearTimeout(this._timeout);
- this._timeout = _timeout;
- }
+ resetTimeout(_timeout) {
+ clearTimeout(this._timeout);
+ this._timeout = _timeout;
+ }
- get elapsedTime() {
- return Date.now() - this.since;
- }
+ get elapsedTime() {
+ return Date.now() - this.since;
+ }
}
class TypingStartHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
+ const channel = client.store.get('channels', data.channel_id);
+ const user = client.store.get('users', data.user_id);
+ const timestamp = new Date(data.timestamp * 1000);
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
- let channel = client.store.get('channels', data.channel_id);
- let user = client.store.get('users', data.user_id);
- let timestamp = new Date(data.timestamp * 1000);
+ function tooLate() {
+ return 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
- let mapping = channel.typingMap[user.id];
- mapping.lastTimestamp = timestamp;
- mapping.resetTimeout(tooLate());
- } else {
- channel.typingMap[user.id] = new TypingData(timestamp, timestamp, tooLate());
- client.emit(Constants.Events.TYPING_START, channel, user);
- }
- }
+ if (channel && user) {
+ if (channel.typingMap[user.id]) {
+ // already typing, renew
+ const mapping = channel.typingMap[user.id];
+ mapping.lastTimestamp = timestamp;
+ mapping.resetTimeout(tooLate());
+ } else {
+ channel.typingMap[user.id] = new TypingData(timestamp, timestamp, tooLate());
+ client.emit(Constants.Events.TYPING_START, channel, user);
+ }
+ }
+ }
- function tooLate() {
- return setTimeout(() => {
- client.emit(Constants.Events.TYPING_STOP, channel, user, channel.typingMap[user.id]);
- delete channel.typingMap[user.id];
- }, 6000);
- }
- }
-
-};
+}
module.exports = TypingStartHandler;
diff --git a/src/client/websocket/packets/handlers/UserUpdate.js b/src/client/websocket/packets/handlers/UserUpdate.js
index 8cefe8fcd..f1d6db65c 100644
--- a/src/client/websocket/packets/handlers/UserUpdate.js
+++ b/src/client/websocket/packets/handlers/UserUpdate.js
@@ -1,28 +1,14 @@
-'use strict';
-
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-const CloneObject = name => require(`../../../../util/CloneObject`);
-const Constants = require(`../../../../util/Constants`);
-
-const ClientUser = Structure('ClientUser');
-const Guild = Structure('Guild');
-const DMChannel = Structure('DMChannel');
class UserUpdateHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
+ client.actions.UserUpdate.handle(data);
+ }
- let response = client.actions.UserUpdate.handle(data);
-
- }
-
-};
+}
module.exports = UserUpdateHandler;
diff --git a/src/client/websocket/packets/handlers/VoiceStateUpdate.js b/src/client/websocket/packets/handlers/VoiceStateUpdate.js
index 3838b7007..de7ac687a 100644
--- a/src/client/websocket/packets/handlers/VoiceStateUpdate.js
+++ b/src/client/websocket/packets/handlers/VoiceStateUpdate.js
@@ -1,43 +1,34 @@
-'use strict';
-
const AbstractHandler = require('./AbstractHandler');
-const Structure = name => require(`../../../../structures/${name}`);
-const Constants = require('../../../../util/Constants');
-const CloneObject = require('../../../../util/CloneObject');
-const Role = Structure('User');
+const Constants = require('../../../../util/Constants');
+const cloneObject = require('../../../../util/CloneObject');
class VoiceStateUpdateHandler extends AbstractHandler {
- constructor(packetManager) {
- super(packetManager);
- }
+ handle(packet) {
+ const data = packet.d;
+ const client = this.packetManager.client;
+ const guild = client.store.get('guilds', data.guild_id);
- handle(packet) {
- let data = packet.d;
- let client = this.packetManager.client;
- let guild = client.store.get('guilds', data.guild_id);
+ if (guild) {
+ const member = guild.store.get('members', data.user_id);
+ if (member) {
+ const oldVoiceChannelMember = cloneObject(member);
+ if (member.voiceChannel && member.voiceChannel.id !== data.channel_id) {
+ member.voiceChannel.store.remove('members', oldVoiceChannelMember);
+ }
- if (guild) {
- let member = guild.store.get('members', data.user_id);
- let channel = guild.store.get('channels', data.channel_id);
- if (member) {
- let oldVoiceChannelMember = CloneObject(member);
- if (member.voiceChannel && member.voiceChannel.id !== data.channel_id) {
- member.voiceChannel.store.remove('members', oldVoiceChannelMember);
- }
+ 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);
+ }
+ }
+ }
- 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);
- }
- }
- }
-
-};
+}
module.exports = VoiceStateUpdateHandler;
diff --git a/src/index.js b/src/index.js
index 6dc2c55cb..e5f018673 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,10 +1,8 @@
-'use strict';
-
const values = require('object.values');
const Client = require('./client/Client');
if (!Object.values) {
- values.shim();
+ values.shim();
}
exports.Client = Client;
diff --git a/src/structures/Channel.js b/src/structures/Channel.js
index d6c3a9822..c9bed1141 100644
--- a/src/structures/Channel.js
+++ b/src/structures/Channel.js
@@ -1,26 +1,24 @@
-'use strict';
-
class Channel {
- constructor(client, data, guild) {
- this.client = client;
- this.typingMap = {};
- this.typingTimeouts = [];
- if (guild) {
- this.guild = guild;
- }
+ constructor(client, data, guild) {
+ this.client = client;
+ this.typingMap = {};
+ this.typingTimeouts = [];
+ if (guild) {
+ this.guild = guild;
+ }
- if (data) {
- this.setup(data);
- }
- }
+ if (data) {
+ this.setup(data);
+ }
+ }
- setup(data) {
- this.id = data.id;
- }
+ setup(data) {
+ this.id = data.id;
+ }
- delete() {
- return this.client.rest.methods.DeleteChannel(this);
- }
+ delete() {
+ return this.client.rest.methods.deleteChannel(this);
+ }
}
module.exports = Channel;
diff --git a/src/structures/ClientUser.js b/src/structures/ClientUser.js
index 923c571dd..412587785 100644
--- a/src/structures/ClientUser.js
+++ b/src/structures/ClientUser.js
@@ -1,37 +1,31 @@
-'use strict';
-
const User = require('./User');
class ClientUser extends User {
- constructor(client, data) {
- super(client, data);
- }
+ setup(data) {
+ super.setup(data);
+ this.verified = data.verified;
+ this.email = data.email;
+ }
- setup(data) {
- super.setup(data);
- this.verified = data.verified;
- this.email = data.email;
- }
+ setUsername(username) {
+ return this.client.rest.methods.updateCurrentUser({ username });
+ }
- setUsername(username) {
- return this.client.rest.methods.UpdateCurrentUser({ username, });
- }
+ setEmail(email) {
+ return this.client.rest.methods.updateCurrentUser({ email });
+ }
- setEmail(email) {
- return this.client.rest.methods.UpdateCurrentUser({ email, });
- }
+ setPassword(password) {
+ return this.client.rest.methods.updateCurrentUser({ password });
+ }
- setPassword(password) {
- return this.client.rest.methods.UpdateCurrentUser({ password, });
- }
+ setAvatar(avatar) {
+ return this.client.rest.methods.updateCurrentUser({ avatar });
+ }
- setAvatar(avatar) {
- return this.client.rest.methods.UpdateCurrentUser({ avatar, });
- }
-
- edit(data) {
- return this.client.rest.methods.UpdateCurrentUser(data);
- }
+ edit(data) {
+ return this.client.rest.methods.updateCurrentUser(data);
+ }
}
module.exports = ClientUser;
diff --git a/src/structures/DMChannel.js b/src/structures/DMChannel.js
index f0b7523b2..53d0be758 100644
--- a/src/structures/DMChannel.js
+++ b/src/structures/DMChannel.js
@@ -1,40 +1,38 @@
-'use strict';
-
const Channel = require('./Channel');
const TextBasedChannel = require('./interface/TextBasedChannel');
const User = require('./User');
const TextChannelDataStore = require('./datastore/TextChannelDataStore');
-class DMChannel extends Channel{
- constructor(client, data) {
- super(client, data);
- this.store = new TextChannelDataStore();
- }
+class DMChannel extends Channel {
+ constructor(client, data) {
+ super(client, data);
+ this.store = new TextChannelDataStore();
+ }
- _cacheMessage(message) {
- let maxSize = this.client.options.max_message_cache;
- if (maxSize === 0) {
- // saves on performance
- return;
- }
+ _cacheMessage(message) {
+ const maxSize = this.client.options.max_message_cache;
+ if (maxSize === 0) {
+ // saves on performance
+ return;
+ }
- let storeKeys = Object.keys(this.store);
- if (storeKeys.length >= maxSize) {
- this.store.remove(storeKeys[0]);
- }
+ const storeKeys = Object.keys(this.store);
+ if (storeKeys.length >= maxSize) {
+ this.store.remove(storeKeys[0]);
+ }
- this.store.add('messages', message);
- }
+ this.store.add('messages', message);
+ }
- setup(data) {
- super.setup(data);
- this.recipient = this.client.store.add('users', new User(this.client, data.recipient));
- this.lastMessageID = data.last_message_id;
- }
+ setup(data) {
+ super.setup(data);
+ this.recipient = this.client.store.add('users', new User(this.client, data.recipient));
+ this.lastMessageID = data.last_message_id;
+ }
- toString() {
- return this.recipient.toString();
- }
+ toString() {
+ return this.recipient.toString();
+ }
}
TextBasedChannel.applyToClass(DMChannel);
diff --git a/src/structures/EvaluatedPermissions.js b/src/structures/EvaluatedPermissions.js
index 30ef07844..32ac3557d 100644
--- a/src/structures/EvaluatedPermissions.js
+++ b/src/structures/EvaluatedPermissions.js
@@ -1,39 +1,37 @@
-'use strict';
-
-const Constants = require('../Util/Constants');
+const Constants = require('../util/Constants');
class EvaluatedPermissions {
- constructor(member, permissions) {
- this.member = member;
- this.permissions = permissions;
- }
+ constructor(member, permissions) {
+ this.member = member;
+ this.permissions = permissions;
+ }
- serialize() {
- let serializedPermissions = {};
- for (let permissionName in Constants.PermissionFlags) {
- serializedPermissions[permissionName] = this.hasPermission(permissionName);
- }
+ serialize() {
+ const serializedPermissions = {};
+ for (const permissionName in Constants.PermissionFlags) {
+ serializedPermissions[permissionName] = this.hasPermission(permissionName);
+ }
- return serializedPermissions;
- }
+ return serializedPermissions;
+ }
- hasPermission(permission, explicit) {
- if (permission instanceof String || typeof permission === 'string') {
- permission = Constants.PermissionFlags[permission];
- }
+ hasPermission(permission, explicit) {
+ if (permission instanceof String || typeof permission === 'string') {
+ permission = Constants.PermissionFlags[permission];
+ }
- if (!permission) {
- throw Constants.Errors.NOT_A_PERMISSION;
- }
+ if (!permission) {
+ throw Constants.Errors.NOT_A_PERMISSION;
+ }
- if (!explicit) {
- if ((this.permissions & Constants.PermissionFlags.ADMINISTRATOR) > 0) {
- return true;
- }
- }
+ if (!explicit) {
+ if ((this.permissions & Constants.PermissionFlags.ADMINISTRATOR) > 0) {
+ return true;
+ }
+ }
- return ((this.permissions & permission) > 0);
- }
+ return ((this.permissions & permission) > 0);
+ }
}
module.exports = EvaluatedPermissions;
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index b5bd9f5b3..596d9bf7a 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -1,244 +1,240 @@
-'use strict';
-
const User = require('./User');
const GuildMember = require('./GuildMember');
const GuildDataStore = require('./datastore/GuildDataStore');
-const TextChannel = require('./TextChannel');
-const VoiceChannel = require('./VoiceChannel');
-const Constants = require('../Util/Constants');
+const Constants = require('../util/Constants');
const Role = require('./Role');
function arraysEqual(a, b) {
- if (a === b) return true;
- if (a.length !== b.length) return false;
+ if (a === b) return true;
+ if (a.length !== b.length) return false;
- for (let itemInd in a) {
- let item = a[itemInd];
- let ind = b.indexOf(item);
- if (ind) {
- b.splice(ind, 1);
- }
- }
+ for (const itemInd in a) {
+ const item = a[itemInd];
+ const ind = b.indexOf(item);
+ if (ind) {
+ b.splice(ind, 1);
+ }
+ }
- return b.length === 0;
+ return b.length === 0;
}
class Guild {
- constructor(client, data) {
- this.client = client;
- this.store = new GuildDataStore();
+ constructor(client, data) {
+ this.client = client;
+ this.store = new GuildDataStore();
- if (!data) {
- return;
- }
+ if (!data) {
+ return;
+ }
- if (data.unavailable) {
- this.available = false;
- this.id = data.id;
- } else {
- this.available = true;
- this.setup(data);
- }
- }
+ if (data.unavailable) {
+ this.available = false;
+ this.id = data.id;
+ } else {
+ this.available = true;
+ this.setup(data);
+ }
+ }
- _addMember(guildUser, noEvent) {
- if (!(guildUser.user instanceof User)) {
- guildUser.user = this.client.store.NewUser(guildUser.user);
- }
+ _addMember(guildUser, noEvent) {
+ if (!(guildUser.user instanceof User)) {
+ guildUser.user = this.client.store.newUser(guildUser.user);
+ }
- guildUser.joined_at = guildUser.joined_at || 0;
- let member = this.store.add('members', new GuildMember(this, guildUser));
- if (this.client.ws.status === Constants.Status.READY && !noEvent) {
- this.client.emit(Constants.Events.GUILD_MEMBER_ADD, this, member);
- }
+ guildUser.joined_at = guildUser.joined_at || 0;
+ const member = this.store.add('members', new GuildMember(this, guildUser));
+ if (this.client.ws.status === Constants.Status.READY && !noEvent) {
+ this.client.emit(Constants.Events.GUILD_MEMBER_ADD, this, member);
+ }
- return member;
- }
+ return member;
+ }
- _updateMember(member, data) {
- let oldRoles = member.roles;
+ _updateMember(member, data) {
+ const oldRoles = member.roles;
- member._roles = data.roles;
- if (this.client.ws.status === Constants.Status.READY) {
- this.client.emit(Constants.Events.GUILD_MEMBER_ROLES_UPDATE, this, oldRoles, member.roles);
- }
- }
+ member._roles = data.roles;
+ if (this.client.ws.status === Constants.Status.READY) {
+ this.client.emit(Constants.Events.GUILD_MEMBER_ROLES_UPDATE, this, oldRoles, member.roles);
+ }
+ }
- _removeMember(guildMember) {
- this.store.remove('members', guildMember);
- }
+ _removeMember(guildMember) {
+ this.store.remove('members', guildMember);
+ }
- toString() {
- return this.name;
- }
+ toString() {
+ return this.name;
+ }
- kick(member) {
- return this.member(member).kick();
- }
+ kick(member) {
+ return this.member(member).kick();
+ }
- member(user) {
- return this.client.resolver.ResolveGuildMember(this, user);
- }
+ member(user) {
+ return this.client.resolver.resolveGuildMember(this, user);
+ }
- equals(data) {
- let base =
- this.id === data.id &&
- this.available === !data.unavailable &&
- this.splash === data.splash &&
- this.region === data.region &&
- this.name === data.name &&
- this.memberCount === data.member_count &&
- this.large === data.large &&
- this.icon === data.icon &&
- arraysEqual(this.features, data.features) &&
- this.owner.id === data.owner_id &&
- this.verificationLevel === data.verification_level &&
- this.embedEnabled === data.embed_enabled;
+ equals(data) {
+ let base =
+ this.id === data.id &&
+ this.available === !data.unavailable &&
+ this.splash === data.splash &&
+ this.region === data.region &&
+ this.name === data.name &&
+ this.memberCount === data.member_count &&
+ this.large === data.large &&
+ this.icon === data.icon &&
+ arraysEqual(this.features, data.features) &&
+ this.owner.id === data.owner_id &&
+ this.verificationLevel === data.verification_level &&
+ this.embedEnabled === data.embed_enabled;
- if (base) {
- if (this.embedChannel) {
- if (this.embedChannel.id !== data.embed_channel_id) {
- base = false;
- }
- } else if (data.embed_channel_id) {
- base = false;
- }
- }
+ if (base) {
+ if (this.embedChannel) {
+ if (this.embedChannel.id !== data.embed_channel_id) {
+ base = false;
+ }
+ } else if (data.embed_channel_id) {
+ base = false;
+ }
+ }
- return base;
- }
+ return base;
+ }
- setup(data) {
- this.id = data.id;
- this.available = !data.unavailable;
- this.splash = data.splash;
- this.region = data.region;
- this.name = data.name;
- this.memberCount = data.member_count;
- this.large = data.large;
- this.joinDate = new Date(data.joined_at);
- this.icon = data.icon;
- this.features = data.features;
- this.emojis = data.emojis;
- this.afkTimeout = data.afk_timeout;
- this.afkChannelID = data.afk_channel_id;
- this.embedEnabled = data.embed_enabled;
- this.verificationLevel = data.verification_level;
- this.features = data.features || [];
+ setup(data) {
+ this.id = data.id;
+ this.available = !data.unavailable;
+ this.splash = data.splash;
+ this.region = data.region;
+ this.name = data.name;
+ this.memberCount = data.member_count;
+ this.large = data.large;
+ this.joinDate = new Date(data.joined_at);
+ this.icon = data.icon;
+ this.features = data.features;
+ this.emojis = data.emojis;
+ this.afkTimeout = data.afk_timeout;
+ this.afkChannelID = data.afk_channel_id;
+ this.embedEnabled = data.embed_enabled;
+ this.verificationLevel = data.verification_level;
+ this.features = data.features || [];
- if (data.members) {
- this.store.clear('members');
- for (let guildUser of data.members) {
- this._addMember(guildUser);
- }
- }
+ if (data.members) {
+ this.store.clear('members');
+ for (const guildUser of data.members) {
+ this._addMember(guildUser);
+ }
+ }
- this.owner = this.store.get('members', data.owner_id);
+ this.owner = this.store.get('members', data.owner_id);
- if (data.channels) {
- this.store.clear('channels');
- for (let channel of data.channels) {
- this.client.store.NewChannel(channel, this);
- }
- }
+ if (data.channels) {
+ this.store.clear('channels');
+ for (const channel of data.channels) {
+ this.client.store.newChannel(channel, this);
+ }
+ }
- this.embedChannel = this.store.get('channels', data.embed_channel_id);
+ this.embedChannel = this.store.get('channels', data.embed_channel_id);
- if (data.roles) {
- this.store.clear('roles');
- for (let role of data.roles) {
- this.store.add('roles', new Role(this, role));
- }
- }
+ if (data.roles) {
+ this.store.clear('roles');
+ for (const role of data.roles) {
+ this.store.add('roles', new Role(this, role));
+ }
+ }
- if (data.presences) {
- for (let presence of data.presences) {
- let user = this.client.store.get('users', presence.user.id);
- if (user) {
- user.status = presence.status;
- user.game = presence.game;
- }
- }
- }
+ if (data.presences) {
+ for (const presence of data.presences) {
+ const user = this.client.store.get('users', presence.user.id);
+ if (user) {
+ user.status = presence.status;
+ user.game = presence.game;
+ }
+ }
+ }
- if (data.voice_states) {
- for (let voiceState of data.voice_states) {
- let member = this.store.get('members', 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;
- }
- }
- }
- }
+ if (data.voice_states) {
+ for (const voiceState of data.voice_states) {
+ const member = this.store.get('members', 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;
+ }
+ }
+ }
+ }
- createChannel(name, type) {
- return this.client.rest.methods.CreateChannel(this, name, type);
- }
+ createChannel(name, type) {
+ return this.client.rest.methods.createChannel(this, name, type);
+ }
- createRole() {
- return this.client.rest.methods.CreateGuildRole(this);
- }
+ createRole() {
+ return this.client.rest.methods.createGuildRole(this);
+ }
- leave() {
- return this.client.rest.methods.LeaveGuild(this);
- }
+ leave() {
+ return this.client.rest.methods.leaveGuild(this);
+ }
- delete() {
- return this.client.rest.methods.DeleteGuild(this);
- }
+ delete() {
+ return this.client.rest.methods.deleteGuild(this);
+ }
- edit(data) {
- return this.client.rest.methods.UpdateGuild(this, data);
- }
+ edit(data) {
+ return this.client.rest.methods.updateGuild(this, data);
+ }
- setName(name) {
- return this.edit({ name, });
- }
+ setName(name) {
+ return this.edit({ name });
+ }
- setRegion(region) {
- return this.edit({ region, });
- }
+ setRegion(region) {
+ return this.edit({ region });
+ }
- setVerificationLevel(verificationLevel) {
- return this.edit({ verificationLevel, });
- }
+ setVerificationLevel(verificationLevel) {
+ return this.edit({ verificationLevel });
+ }
- setAFKChannel(afkchannel) {
- return this.edit({ afkChannel, });
- }
+ setAFKChannel(afkChannel) {
+ return this.edit({ afkChannel });
+ }
- setAFKTimeout(afkTimeout) {
- return this.edit({ afkTimeout, });
- }
+ setAFKTimeout(afkTimeout) {
+ return this.edit({ afkTimeout });
+ }
- setIcon(icon) {
- return this.edit({ icon, });
- }
+ setIcon(icon) {
+ return this.edit({ icon });
+ }
- setOwner(owner) {
- return this.edit({ owner, });
- }
+ setOwner(owner) {
+ return this.edit({ owner });
+ }
- setSplash(splash) {
- return this.edit({ splash, });
- }
+ setSplash(splash) {
+ return this.edit({ splash });
+ }
- get channels() { return this.store.getAsArray('channels'); }
+ get channels() { return this.store.getAsArray('channels'); }
- get $channels() { return this.store.data.channels; }
+ get $channels() { return this.store.data.channels; }
- get roles() { return this.store.getAsArray('roles'); }
+ get roles() { return this.store.getAsArray('roles'); }
- get $roles() { return this.store.data.roles; }
+ get $roles() { return this.store.data.roles; }
- get members() { return this.store.getAsArray('members'); }
+ get members() { return this.store.getAsArray('members'); }
- get $members() { return this.store.data.members; }
+ get $members() { return this.store.data.members; }
}
module.exports = Guild;
diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js
index d35cc163d..6c1b11afc 100644
--- a/src/structures/GuildMember.js
+++ b/src/structures/GuildMember.js
@@ -1,71 +1,69 @@
-'use strict';
-
const TextBasedChannel = require('./interface/TextBasedChannel');
class GuildMember {
- constructor(guild, data) {
- this.client = guild.client;
- this.guild = guild;
- this.user = {};
- this._roles = [];
- if (data) {
- this.setup(data);
- }
- }
+ constructor(guild, data) {
+ this.client = guild.client;
+ this.guild = guild;
+ this.user = {};
+ this._roles = [];
+ if (data) {
+ this.setup(data);
+ }
+ }
- setup(data) {
- this.user = data.user;
- this.serverDeaf = data.deaf;
- this.serverMute = data.mute;
- this.selfMute = data.self_mute;
- this.selfDeaf = data.self_deaf;
- this.voiceSessionID = data.session_id;
- this.voiceChannelID = data.channel_id;
- this.joinDate = new Date(data.joined_at);
- this._roles = data.roles;
- }
+ setup(data) {
+ this.user = data.user;
+ this.serverDeaf = data.deaf;
+ this.serverMute = data.mute;
+ this.selfMute = data.self_mute;
+ this.selfDeaf = data.self_deaf;
+ this.voiceSessionID = data.session_id;
+ this.voiceChannelID = data.channel_id;
+ this.joinDate = new Date(data.joined_at);
+ this._roles = data.roles;
+ }
- get roles() {
- let list = [];
- let everyoneRole = this.guild.store.get('roles', this.guild.id);
+ get roles() {
+ const list = [];
+ const everyoneRole = this.guild.store.get('roles', this.guild.id);
- if (everyoneRole) {
- list.push(everyoneRole);
- }
+ if (everyoneRole) {
+ list.push(everyoneRole);
+ }
- for (let roleID of this._roles) {
- let role = this.guild.store.get('roles', roleID);
- if (role) {
- list.push(role);
- }
- }
+ for (const roleID of this._roles) {
+ const role = this.guild.store.get('roles', roleID);
+ if (role) {
+ list.push(role);
+ }
+ }
- return list;
- }
+ return list;
+ }
- get mute() {
- return this.selfMute || this.serverMute;
- }
+ get mute() {
+ return this.selfMute || this.serverMute;
+ }
- get deaf() {
- return this.selfDeaf || this.serverDeaf;
- }
+ get deaf() {
+ return this.selfDeaf || this.serverDeaf;
+ }
- get voiceChannel() {
- return this.guild.store.get('channels', this.voiceChannelID);
- }
+ get voiceChannel() {
+ return this.guild.store.get('channels', this.voiceChannelID);
+ }
- get id() {
- return this.user.id;
- }
+ get id() {
+ return this.user.id;
+ }
- deleteDM() {
- return this.client.rest.methods.DeleteChannel(this);
- }
+ deleteDM() {
+ return this.client.rest.methods.deleteChannel(this);
+ }
- kick() {
- return this.client.rest.methods.KickGuildMember(this.guild, this);
- }
+ kick() {
+ return this.client.rest.methods.kickGuildMember(this.guild, this);
+ }
}
TextBasedChannel.applyToClass(GuildMember);
diff --git a/src/structures/Message.js b/src/structures/Message.js
index d5118ca70..b565737ce 100644
--- a/src/structures/Message.js
+++ b/src/structures/Message.js
@@ -1,111 +1,117 @@
-'use strict';
-
class Message {
- constructor(channel, data, client) {
- this.channel = channel;
+ constructor(channel, data, client) {
+ this.channel = channel;
- if (channel.guild) {
- this.guild = channel.guild;
- }
+ if (channel.guild) {
+ this.guild = channel.guild;
+ }
- this.client = client;
- if (data) {
- this.setup(data);
- }
- }
+ this.client = client;
+ if (data) {
+ this.setup(data);
+ }
+ }
- setup(data) {
- this.author = this.client.store.NewUser(data.author);
- this.content = data.content;
- this.timestamp = new Date(data.timestamp);
- this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp) : null;
- this.tts = data.tts;
- this.mentionEveryone = data.mention_everyone;
- this.nonce = data.nonce;
- this.embeds = data.embeds;
- this.attachments = data.attachments;
- this.mentions = [];
- this.id = data.id;
- for (let mention of data.mentions) {
- let user = this.client.store.get('users', mention.id);
- if (user) {
- this.mentions.push(user);
- } else {
- user = this.client.store.NewUser(mention);
- this.mentions.push(user);
- }
- }
- }
+ setup(data) {
+ this.author = this.client.store.newUser(data.author);
+ this.content = data.content;
+ this.timestamp = new Date(data.timestamp);
+ this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp) : null;
+ this.tts = data.tts;
+ this.mentionEveryone = data.mention_everyone;
+ this.nonce = data.nonce;
+ this.embeds = data.embeds;
+ this.attachments = data.attachments;
+ this.mentions = [];
+ this.id = data.id;
+ for (const mention of data.mentions) {
+ let user = this.client.store.get('users', mention.id);
+ if (user) {
+ this.mentions.push(user);
+ } else {
+ user = this.client.store.newUser(mention);
+ this.mentions.push(user);
+ }
+ }
+ }
- patch(data) {
- if (data.author)
- this.author = this.client.store.get('users', data.author.id);
- if (data.content)
- this.content = data.content;
- if (data.timestamp)
- this.timestamp = new Date(data.timestamp);
- if (data.edited_timestamp)
- this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp) : null;
- if (data.tts)
- this.tts = data.tts;
- if (data.mention_everyone)
- this.mentionEveryone = data.mention_everyone;
- if (data.nonce)
- this.nonce = data.nonce;
- if (data.embeds)
- this.embeds = data.embeds;
- if (data.attachments)
- this.attachments = data.attachments;
- if (data.mentions) {
- for (let mention of data.mentions) {
- let user = this.client.store.get('users', mention.id);
- if (user) {
- this.mentions.push(user);
- } else {
- user = this.client.store.NewUser(mention);
- this.mentions.push(user);
- }
- }
- }
+ patch(data) {
+ if (data.author) {
+ this.author = this.client.store.get('users', data.author.id);
+ }
+ if (data.content) {
+ this.content = data.content;
+ }
+ if (data.timestamp) {
+ this.timestamp = new Date(data.timestamp);
+ }
+ if (data.edited_timestamp) {
+ this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp) : null;
+ }
+ if (data.tts) {
+ this.tts = data.tts;
+ }
+ if (data.mention_everyone) {
+ this.mentionEveryone = data.mention_everyone;
+ }
+ if (data.nonce) {
+ this.nonce = data.nonce;
+ }
+ if (data.embeds) {
+ this.embeds = data.embeds;
+ }
+ if (data.attachments) {
+ this.attachments = data.attachments;
+ }
+ if (data.mentions) {
+ for (const mention of data.mentions) {
+ let user = this.client.store.get('users', mention.id);
+ if (user) {
+ this.mentions.push(user);
+ } else {
+ user = this.client.store.newUser(mention);
+ this.mentions.push(user);
+ }
+ }
+ }
- if (data.id)
- this.id = data.id;
- }
+ if (data.id) {
+ this.id = data.id;
+ }
+ }
- equals(message, rawData) {
+ equals(message, rawData) {
+ const embedUpdate = !message.author && !message.attachments;
- let embedUpdate = !message.author && !message.attachments;
+ if (embedUpdate) {
+ const base = this.id === message.id &&
+ this.embeds.length === message.embeds.length;
+ return base;
+ }
+ let base = 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 (embedUpdate) {
- let base = this.id === message.id &&
- this.embeds.length === message.embeds.length;
- return base;
- } else {
- let base = 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 (base && rawData) {
+ base = this.mentionEveryone === message.mentionEveryone &&
+ this.timestamp.getTime() === new Date(rawData.timestamp).getTime() &&
+ this.editedTimestamp === new Date(rawData.edited_timestamp).getTime();
+ }
- if (base && rawData) {
- base = this.mentionEveryone === message.mentionEveryone &&
- this.timestamp.getTime() === new Date(data.timestamp).getTime() &&
- this.editedTimestamp === new Date(data.edited_timestamp).getTime();
- }
+ return base;
+ }
- return base;
- }
- }
+ delete() {
+ return this.client.rest.methods.deleteMessage(this);
+ }
- delete() {
- return this.client.rest.methods.DeleteMessage(this);
- }
-
- edit(content) {
- return this.client.rest.methods.UpdateMessage(this, content);
- }
+ edit(content) {
+ return this.client.rest.methods.updateMessage(this, content);
+ }
}
module.exports = Message;
diff --git a/src/structures/PermissionOverwrites.js b/src/structures/PermissionOverwrites.js
index 717c94d46..47177d3fc 100644
--- a/src/structures/PermissionOverwrites.js
+++ b/src/structures/PermissionOverwrites.js
@@ -1,19 +1,17 @@
-'use strict';
-
class PermissionOverwrites {
- constructor(serverChannel, data) {
- this.channel = serverChannel;
- if (data) {
- this.setup(data);
- }
- }
+ constructor(serverChannel, data) {
+ this.channel = serverChannel;
+ if (data) {
+ this.setup(data);
+ }
+ }
- setup(data) {
- this.type = data.type;
- this.id = data.id;
- this.denyData = data.deny;
- this.allowData = data.allow;
- }
+ setup(data) {
+ this.type = data.type;
+ this.id = data.id;
+ this.denyData = data.deny;
+ this.allowData = data.allow;
+ }
}
module.exports = PermissionOverwrites;
diff --git a/src/structures/Role.js b/src/structures/Role.js
index f163ff98e..9d14c9074 100644
--- a/src/structures/Role.js
+++ b/src/structures/Role.js
@@ -1,92 +1,90 @@
-'use strict';
-
-const Constants = require('../Util/Constants');
+const Constants = require('../util/Constants');
class Role {
- constructor(guild, data) {
- this.guild = guild;
- this.client = guild.client;
- if (data) {
- this.setup(data);
- }
- }
+ constructor(guild, data) {
+ this.guild = guild;
+ this.client = guild.client;
+ if (data) {
+ this.setup(data);
+ }
+ }
- equals(role) {
- return (
- 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
- );
- }
+ equals(role) {
+ return (
+ 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
+ );
+ }
- setup(data) {
- this.id = data.id;
- this.name = data.name;
- this.color = data.color;
- this.hoist = data.hoist;
- this.position = data.position;
- this.permissions = data.permissions;
- this.managed = data.managed;
- }
+ setup(data) {
+ this.id = data.id;
+ this.name = data.name;
+ this.color = data.color;
+ this.hoist = data.hoist;
+ this.position = data.position;
+ this.permissions = data.permissions;
+ this.managed = data.managed;
+ }
- delete() {
- return this.client.rest.methods.DeleteGuildRole(this);
- }
+ delete() {
+ return this.client.rest.methods.deleteGuildRole(this);
+ }
- edit(data) {
- return this.client.rest.methods.UpdateGuildRole(this, data);
- }
+ edit(data) {
+ return this.client.rest.methods.updateGuildRole(this, data);
+ }
- setName(name) {
- return this.client.rest.methods.UpdateGuildRole(this, {name,});
- }
+ setName(name) {
+ return this.client.rest.methods.updateGuildRole(this, { name });
+ }
- setColor(color) {
- return this.client.rest.methods.UpdateGuildRole(this, {color,});
- }
+ setColor(color) {
+ return this.client.rest.methods.updateGuildRole(this, { color });
+ }
- setHoist(hoist) {
- return this.client.rest.methods.UpdateGuildRole(this, {hoist,});
- }
+ setHoist(hoist) {
+ return this.client.rest.methods.updateGuildRole(this, { hoist });
+ }
- setPosition(position) {
- return this.client.rest.methods.UpdateGuildRole(this, {position,});
- }
+ setPosition(position) {
+ return this.client.rest.methods.updateGuildRole(this, { position });
+ }
- setPermissions(permissions) {
- return this.client.rest.methods.UpdateGuildRole(this, {permissions,});
- }
+ setPermissions(permissions) {
+ return this.client.rest.methods.updateGuildRole(this, { permissions });
+ }
- serialize() {
- let serializedPermissions = {};
- for (let permissionName in Constants.PermissionFlags) {
- serializedPermissions[permissionName] = this.hasPermission(permissionName);
- }
+ serialize() {
+ const serializedPermissions = {};
+ for (const permissionName in Constants.PermissionFlags) {
+ serializedPermissions[permissionName] = this.hasPermission(permissionName);
+ }
- return serializedPermissions;
- }
+ return serializedPermissions;
+ }
- hasPermission(permission, explicit) {
- if (permission instanceof String || typeof permission === 'string') {
- permission = Constants.PermissionFlags[permission];
- }
+ hasPermission(permission, explicit) {
+ if (permission instanceof String || typeof permission === 'string') {
+ permission = Constants.PermissionFlags[permission];
+ }
- if (!permission) {
- throw Constants.Errors.NOT_A_PERMISSION;
- }
+ if (!permission) {
+ throw Constants.Errors.NOT_A_PERMISSION;
+ }
- if (!explicit) {
- if ((this.permissions & Constants.PermissionFlags.ADMINISTRATOR) > 0) {
- return true;
- }
- }
+ if (!explicit) {
+ if ((this.permissions & Constants.PermissionFlags.ADMINISTRATOR) > 0) {
+ return true;
+ }
+ }
- return ((this.permissions & permission) > 0);
- }
+ return ((this.permissions & permission) > 0);
+ }
}
module.exports = Role;
diff --git a/src/structures/ServerChannel.js b/src/structures/ServerChannel.js
index 3ff271477..2e7ee4f93 100644
--- a/src/structures/ServerChannel.js
+++ b/src/structures/ServerChannel.js
@@ -1,151 +1,149 @@
-'use strict';
-
const Channel = require('./Channel');
const PermissionOverwrites = require('./PermissionOverwrites');
const EvaluatedPermissions = require('./EvaluatedPermissions');
const Constants = require('../util/Constants');
function arraysEqual(a, b) {
- if (a === b) return true;
- if (a.length !== b.length) return false;
+ if (a === b) return true;
+ if (a.length !== b.length) return false;
- for (let itemInd in a) {
- let item = a[itemInd];
- let ind = b.indexOf(item);
- if (ind) {
- b.splice(ind, 1);
- }
- }
+ for (const itemInd in a) {
+ const item = a[itemInd];
+ const ind = b.indexOf(item);
+ if (ind) {
+ b.splice(ind, 1);
+ }
+ }
- return b.length === 0;
+ return b.length === 0;
}
-class ServerChannel extends Channel{
- constructor(guild, data) {
- super(guild.client, data, guild);
- }
+class ServerChannel extends Channel {
+ constructor(guild, data) {
+ super(guild.client, data, guild);
+ }
- setup(data) {
- super.setup(data);
- this.type = data.type;
- this.topic = data.topic;
- this.position = data.position;
- this.name = data.name;
- this.lastMessageID = data.last_message_id;
- this.ow = data.permission_overwrites;
- this.permissionOverwrites = [];
- if (data.permission_overwrites) {
- for (let overwrite of data.permission_overwrites) {
- this.permissionOverwrites.push(new PermissionOverwrites(this, overwrite));
- }
- }
- }
+ setup(data) {
+ super.setup(data);
+ this.type = data.type;
+ this.topic = data.topic;
+ this.position = data.position;
+ this.name = data.name;
+ this.lastMessageID = data.last_message_id;
+ this.ow = data.permission_overwrites;
+ this.permissionOverwrites = [];
+ if (data.permission_overwrites) {
+ for (const overwrite of data.permission_overwrites) {
+ this.permissionOverwrites.push(new PermissionOverwrites(this, overwrite));
+ }
+ }
+ }
- equals(other) {
- let base = (
- this.type === other.type &&
- this.topic === other.topic &&
- this.position === other.position &&
- this.name === other.name &&
- this.id === other.id
- );
+ equals(other) {
+ let base = (
+ this.type === other.type &&
+ this.topic === other.topic &&
+ this.position === other.position &&
+ this.name === other.name &&
+ this.id === other.id
+ );
- if (base) {
- if (other.permission_overwrites) {
- let thisIDSet = this.permissionOverwrites.map(overwrite => overwrite.id);
- let otherIDSet = other.permission_overwrites.map(overwrite => overwrite.id);
- if (arraysEqual(thisIDSet, otherIDSet)) {
- base = true;
- } else {
- base = false;
- }
- } else {
- base = false;
- }
- }
+ if (base) {
+ if (other.permission_overwrites) {
+ const thisIDSet = this.permissionOverwrites.map(overwrite => overwrite.id);
+ const otherIDSet = other.permission_overwrites.map(overwrite => overwrite.id);
+ if (arraysEqual(thisIDSet, otherIDSet)) {
+ base = true;
+ } else {
+ base = false;
+ }
+ } else {
+ base = false;
+ }
+ }
- return base;
- }
+ return base;
+ }
- permissionsFor(member) {
- member = this.client.resolver.ResolveGuildMember(this.guild, member);
- if (member) {
- if (this.guild.owner.id === member.id) {
- return new EvaluatedPermissions(member, Constants.ALL_PERMISSIONS);
- }
+ permissionsFor(member) {
+ member = this.client.resolver.resolveGuildMember(this.guild, member);
+ if (member) {
+ if (this.guild.owner.id === member.id) {
+ return new EvaluatedPermissions(member, Constants.ALL_PERMISSIONS);
+ }
- let roles = member.roles;
- let permissions = 0;
- let overwrites = this.overwritesFor(member, true);
+ const roles = member.roles;
+ let permissions = 0;
+ const overwrites = this.overwritesFor(member, true);
- for (let role of roles) {
- permissions |= role.permissions;
- }
+ for (const role of roles) {
+ permissions |= role.permissions;
+ }
- for (let overwrite of overwrites.role.concat(overwrites.member)) {
- permissions = permissions & ~overwrite.denyData;
- permissions = permissions | overwrite.allowData;
- }
+ for (const overwrite of overwrites.role.concat(overwrites.member)) {
+ permissions &= ~overwrite.denyData;
+ permissions |= overwrite.allowData;
+ }
- if (!!(permissions & (Constants.PermissionFlags.MANAGE_ROLES))) {
- permissions = Constants.ALL_PERMISSIONS;
- }
+ const admin = Boolean(permissions & (Constants.PermissionFlags.MANAGE_ROLES));
+ if (admin) {
+ permissions = Constants.ALL_PERMISSIONS;
+ }
- return new EvaluatedPermissions(member, permissions);
- }
- }
+ return new EvaluatedPermissions(member, permissions);
+ }
+ return null;
+ }
- overwritesFor(member, verified) {
- // for speed
- if (!verified)
- member = this.client.resolver.ResolveGuildMember(this.guild, member);
- if (member) {
- let found = [];
- let memberRoles = member._roles;
+ overwritesFor(member, verified) {
+ // for speed
+ if (!verified) member = this.client.resolver.resolveGuildMember(this.guild, member);
+ if (member) {
+ const memberRoles = member._roles;
- let roleOverwrites = [];
- let memberOverwrites = [];
+ const roleOverwrites = [];
+ const memberOverwrites = [];
- for (let overwrite of this.permissionOverwrites) {
- if (overwrite.id === member.id) {
- memberOverwrites.push(overwrite);
- } else if (memberRoles.indexOf(overwrite.id) > -1) {
- roleOverwrites.push(overwrite);
- }
- }
+ for (const overwrite of this.permissionOverwrites) {
+ if (overwrite.id === member.id) {
+ memberOverwrites.push(overwrite);
+ } else if (memberRoles.indexOf(overwrite.id) > -1) {
+ roleOverwrites.push(overwrite);
+ }
+ }
- return {
- role: roleOverwrites,
- member: memberOverwrites,
- };
- }
+ return {
+ role: roleOverwrites,
+ member: memberOverwrites,
+ };
+ }
- return [];
- }
+ return [];
+ }
- edit(data) {
- return this.client.rest.methods.UpdateChannel(this, data);
- }
+ edit(data) {
+ return this.client.rest.methods.updateChannel(this, data);
+ }
- setName(name) {
- return this.client.rest.methods.UpdateChannel(this, { name, });
- }
+ setName(name) {
+ return this.client.rest.methods.updateChannel(this, { name });
+ }
- setPosition(position) {
- return this.rest.client.rest.methods.UpdateChannel(this, { position, });
- }
+ setPosition(position) {
+ return this.rest.client.rest.methods.updateChannel(this, { position });
+ }
- setTopic(topic) {
- return this.rest.client.rest.methods.UpdateChannel(this, { topic, });
- }
+ setTopic(topic) {
+ return this.rest.client.rest.methods.updateChannel(this, { topic });
+ }
- setBitrate() {
- return this.rest.client.rest.methods.UpdateChannel(this, { bitrate, });
- }
+ setBitrate(bitrate) {
+ return this.rest.client.rest.methods.updateChannel(this, { bitrate });
+ }
- toString() {
- return this.name;
- }
+ toString() {
+ return this.name;
+ }
}
module.exports = ServerChannel;
diff --git a/src/structures/TextChannel.js b/src/structures/TextChannel.js
index 73986118c..c87b27ed4 100644
--- a/src/structures/TextChannel.js
+++ b/src/structures/TextChannel.js
@@ -1,30 +1,28 @@
-'use strict';
-
const ServerChannel = require('./ServerChannel');
const TextChannelDataStore = require('./datastore/TextChannelDataStore');
const TextBasedChannel = require('./interface/TextBasedChannel');
class TextChannel extends ServerChannel {
- constructor(guild, data) {
- super(guild, data);
- this.store = new TextChannelDataStore();
- }
+ constructor(guild, data) {
+ super(guild, data);
+ this.store = new TextChannelDataStore();
+ }
- _cacheMessage(message) {
- let maxSize = this.client.options.max_message_cache;
- if (maxSize === 0) {
- // saves on performance
- return;
- }
+ _cacheMessage(message) {
+ const maxSize = this.client.options.max_message_cache;
+ if (maxSize === 0) {
+ // saves on performance
+ return null;
+ }
- let storeKeys = Object.keys(this.store);
- if (storeKeys.length >= maxSize) {
- this.store.remove(storeKeys[0]);
- }
+ const storeKeys = Object.keys(this.store);
+ if (storeKeys.length >= maxSize) {
+ this.store.remove(storeKeys[0]);
+ }
- return this.store.add('messages', message);
- }
+ return this.store.add('messages', message);
+ }
}
TextBasedChannel.applyToClass(TextChannel);
diff --git a/src/structures/User.js b/src/structures/User.js
index 2563fccb2..823c8597d 100644
--- a/src/structures/User.js
+++ b/src/structures/User.js
@@ -1,89 +1,87 @@
-'use strict';
-
const TextBasedChannel = require('./interface/TextBasedChannel');
/**
* Represents a User on Discord.
*/
class User {
- constructor(client, data) {
- this.client = client;
- if (data) {
- this.setup(data);
- }
- }
+ constructor(client, data) {
+ this.client = client;
+ 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;
- /**
- * 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:
- *
- * * **`online`** - user is online
- * * **`offline`** - user is offline
- * * **`idle`** - user is AFK
- * @type {String}
- */
- this.status = data.status || this.status || 'offline';
- this.game = data.game || this.game;
- }
+ setup(data) {
+ /**
+ * The username of the User
+ * @type {String}
+ */
+ this.username = data.username;
+ /**
+ * The ID of the User
+ * @type {String}
+ */
+ this.id = data.id;
+ /**
+ * 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:
+ *
+ * * **`online`** - user is online
+ * * **`offline`** - user is offline
+ * * **`idle`** - user is AFK
+ * @type {String}
+ */
+ this.status = data.status || this.status || 'offline';
+ this.game = data.game || this.game;
+ }
- toString() {
- return `<@${this.id}>`;
- }
+ toString() {
+ return `<@${this.id}>`;
+ }
- /**
- * Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.
- * @return {Promise}
- */
- deleteDM() {
- return this.client.rest.methods.DeleteChannel(this);
- }
+ /**
+ * Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.
+ * @return {Promise}
+ */
+ deleteDM() {
+ return this.client.rest.methods.deleteChannel(this);
+ }
- equals(user) {
- let base = (
- this.username === user.username &&
- this.id === user.id &&
- this.discriminator === user.discriminator &&
- this.avatar === user.avatar &&
- this.bot === Boolean(user.bot)
- );
+ equals(user) {
+ let base = (
+ this.username === user.username &&
+ this.id === user.id &&
+ this.discriminator === user.discriminator &&
+ this.avatar === user.avatar &&
+ this.bot === Boolean(user.bot)
+ );
- if (base) {
- if (user.status) {
- base = this.status === user.status;
- }
+ if (base) {
+ if (user.status) {
+ base = this.status === user.status;
+ }
- if (user.game) {
- base = this.game === user.game;
- }
- }
+ if (user.game) {
+ base = this.game === user.game;
+ }
+ }
- return base;
- }
+ return base;
+ }
}
TextBasedChannel.applyToClass(User);
diff --git a/src/structures/VoiceChannel.js b/src/structures/VoiceChannel.js
index fb54df361..9c643820d 100644
--- a/src/structures/VoiceChannel.js
+++ b/src/structures/VoiceChannel.js
@@ -1,18 +1,16 @@
-'use strict';
-
const ServerChannel = require('./ServerChannel');
const VoiceChannelDataStore = require('./datastore/VoiceChannelDataStore');
class VoiceChannel extends ServerChannel {
- constructor(guild, data) {
- super(guild, data);
- this.store = new VoiceChannelDataStore();
- }
+ constructor(guild, data) {
+ super(guild, data);
+ this.store = new VoiceChannelDataStore();
+ }
- setup(data) {
- super.setup(data);
- this.bitrate = data.bitrate;
- }
+ setup(data) {
+ super.setup(data);
+ this.bitrate = data.bitrate;
+ }
}
module.exports = VoiceChannel;
diff --git a/src/structures/datastore/AbstractDataStore.js b/src/structures/datastore/AbstractDataStore.js
index 24bfec497..5ec83ecad 100644
--- a/src/structures/datastore/AbstractDataStore.js
+++ b/src/structures/datastore/AbstractDataStore.js
@@ -1,43 +1,40 @@
-'use strict';
+class AbstractDataStore {
+ constructor() {
+ this.data = {};
+ }
-class AbstractDataStore{
- constructor() {
- this.data = {};
- }
+ register(name) {
+ this.data[name] = {};
+ }
- register(name) {
- this.data[name] = {};
- }
+ add(location, object) {
+ if (this.data[location][object.id]) {
+ return this.data[location][object.id];
+ }
+ this.data[location][object.id] = object;
+ return object;
+ }
- add(location, object) {
- if (this.data[location][object.id]) {
- return this.data[location][object.id];
- } else {
- return this.data[location][object.id] = object;
- }
- }
+ clear(location) {
+ this.data[location] = {};
+ }
- clear(location) {
- this.data[location] = {};
- }
+ remove(location, object) {
+ const id = (typeof object === 'string' || object instanceof String) ? object : object.id;
+ if (this.data[location][id]) {
+ delete this.data[location][id];
+ return true;
+ }
+ return false;
+ }
- remove(location, object) {
- let id = (typeof object === 'string' || object instanceof String) ? object : object.id;
- if (this.data[location][id]) {
- delete this.data[location][id];
- return true;
- } else {
- return false;
- }
- }
+ get(location, value) {
+ return this.data[location][value];
+ }
- get(location, value) {
- return this.data[location][value];
- }
-
- getAsArray(location) {
- return Object.values(this.data[location]);
- }
+ getAsArray(location) {
+ return Object.values(this.data[location]);
+ }
}
module.exports = AbstractDataStore;
diff --git a/src/structures/datastore/ClientDataStore.js b/src/structures/datastore/ClientDataStore.js
index a7b39c19d..4d0dd0a87 100644
--- a/src/structures/datastore/ClientDataStore.js
+++ b/src/structures/datastore/ClientDataStore.js
@@ -1,8 +1,6 @@
-'use strict';
-
const AbstractDataStore = require('./AbstractDataStore');
const Constants = require('../../util/Constants');
-const CloneObject = require('../../util/CloneObject');
+const cloneObject = require('../../util/CloneObject');
const Guild = require('../Guild');
const User = require('../User');
const DMChannel = require('../DMChannel');
@@ -10,98 +8,99 @@ const TextChannel = require('../TextChannel');
const VoiceChannel = require('../VoiceChannel');
const ServerChannel = require('../ServerChannel');
-class ClientDataStore extends AbstractDataStore{
- constructor(client) {
- super();
+class ClientDataStore extends AbstractDataStore {
+ constructor(client) {
+ super();
- this.client = client;
- this.token = null;
- this.session = null;
- this.user = null;
- this.email = null;
- this.password = null;
+ this.client = client;
+ this.token = null;
+ this.session = null;
+ this.user = null;
+ this.email = null;
+ this.password = null;
- this.register('users');
- this.register('guilds');
- this.register('channels');
- }
+ this.register('users');
+ this.register('guilds');
+ this.register('channels');
+ }
- get pastReady() {
- return this.client.ws.status === Constants.Status.READY;
- }
+ get pastReady() {
+ return this.client.ws.status === Constants.Status.READY;
+ }
- NewGuild(data) {
- let already = this.get('guilds', data.id);
- let guild = this.add('guilds', new Guild(this.client, data));
- if (this.pastReady && !already) {
- this.client.emit(Constants.Events.GUILD_CREATE, guild);
- }
+ newGuild(data) {
+ const already = this.get('guilds', data.id);
+ const guild = this.add('guilds', new Guild(this.client, data));
+ if (this.pastReady && !already) {
+ this.client.emit(Constants.Events.GUILD_CREATE, guild);
+ }
- return guild;
- }
+ return guild;
+ }
- NewUser(data) {
- return this.add('users', new User(this.client, data));
- }
+ newUser(data) {
+ return this.add('users', new User(this.client, data));
+ }
- NewChannel(data, guild) {
- let already = this.get('channels', data.id);
- let channel;
- if (data.is_private) {
- channel = new DMChannel(this.client, data);
- }else {
- guild = guild || this.get('guilds', data.guild_id);
- if (guild) {
- if (data.type === 'text') {
- channel = new TextChannel(guild, data);
- guild.store.add('channels', channel);
- }else if (data.type === 'voice') {
- channel = new VoiceChannel(guild, data);
- guild.store.add('channels', channel);
- }
- }
- }
+ newChannel(data, $guild) {
+ let guild = $guild;
+ const already = this.get('channels', data.id);
+ let channel;
+ if (data.is_private) {
+ channel = new DMChannel(this.client, data);
+ } else {
+ guild = guild || this.get('guilds', data.guild_id);
+ if (guild) {
+ if (data.type === 'text') {
+ channel = new TextChannel(guild, data);
+ guild.store.add('channels', channel);
+ } else if (data.type === 'voice') {
+ channel = new VoiceChannel(guild, data);
+ guild.store.add('channels', channel);
+ }
+ }
+ }
- if (channel) {
- if (this.pastReady && !already) {
- this.client.emit(Constants.Events.CHANNEL_CREATE, channel);
- }
+ if (channel) {
+ if (this.pastReady && !already) {
+ this.client.emit(Constants.Events.CHANNEL_CREATE, channel);
+ }
- return this.add('channels', channel);
- }
- }
+ return this.add('channels', channel);
+ }
+ return null;
+ }
- KillGuild(guild) {
- let already = this.get('guilds', guilds.id);
- this.remove('guilds', guild);
- if (already && this.pastReady) {
- this.client.emit(Constants.Events.GUILD_DELETE, guild);
- }
- }
+ killGuild(guild) {
+ const already = this.get('guilds', guild.id);
+ this.remove('guilds', guild);
+ if (already && this.pastReady) {
+ this.client.emit(Constants.Events.GUILD_DELETE, guild);
+ }
+ }
- KillUser(user) {
- this.remove('users', user);
- }
+ killUser(user) {
+ this.remove('users', user);
+ }
- KillChannel(channel) {
- this.remove('channels', channel);
- if (channel instanceof ServerChannel) {
- channel.guild.store.remove('channels', channel);
- }
- }
+ killChannel(channel) {
+ this.remove('channels', channel);
+ if (channel instanceof ServerChannel) {
+ channel.guild.store.remove('channels', channel);
+ }
+ }
- UpdateGuild(currentGuild, newData) {
- let oldGuild = CloneObject(currentGuild);
- currentGuild.setup(newData);
- if (this.pastReady) {
- this.client.emit(Constants.Events.GUILD_UPDATE, oldGuild, currentGuild);
- }
- }
+ updateGuild(currentGuild, newData) {
+ const oldGuild = cloneObject(currentGuild);
+ currentGuild.setup(newData);
+ if (this.pastReady) {
+ this.client.emit(Constants.Events.GUILD_UPDATE, oldGuild, currentGuild);
+ }
+ }
- UpdateChannel(currentChannel, newData) {
- let oldChannel = CloneObject(currentChannel);
- currentChannel.setup(newData);
- }
+ updateChannel(currentChannel, newData) {
+ currentChannel.setup(newData);
+ }
}
module.exports = ClientDataStore;
diff --git a/src/structures/datastore/GuildDataStore.js b/src/structures/datastore/GuildDataStore.js
index 68f8fa5d7..bea556765 100644
--- a/src/structures/datastore/GuildDataStore.js
+++ b/src/structures/datastore/GuildDataStore.js
@@ -1,14 +1,12 @@
-'use strict';
-
const AbstractDataStore = require('./AbstractDataStore');
-class GuildDataStore extends AbstractDataStore{
- constructor() {
- super();
+class GuildDataStore extends AbstractDataStore {
+ constructor() {
+ super();
- this.register('members');
- this.register('channels');
- }
+ this.register('members');
+ this.register('channels');
+ }
}
module.exports = GuildDataStore;
diff --git a/src/structures/datastore/TextChannelDataStore.js b/src/structures/datastore/TextChannelDataStore.js
index 08316431b..1cf54a825 100644
--- a/src/structures/datastore/TextChannelDataStore.js
+++ b/src/structures/datastore/TextChannelDataStore.js
@@ -1,12 +1,10 @@
-'use strict';
-
const AbstractDataStore = require('./AbstractDataStore');
-class TextChannelDataStore extends AbstractDataStore{
- constructor() {
- super();
- this.register('messages');
- }
+class TextChannelDataStore extends AbstractDataStore {
+ constructor() {
+ super();
+ this.register('messages');
+ }
}
module.exports = TextChannelDataStore;
diff --git a/src/structures/datastore/VoiceChannelDataStore.js b/src/structures/datastore/VoiceChannelDataStore.js
index 88b9da7bb..9705d5c77 100644
--- a/src/structures/datastore/VoiceChannelDataStore.js
+++ b/src/structures/datastore/VoiceChannelDataStore.js
@@ -1,12 +1,10 @@
-'use strict';
-
const AbstractDataStore = require('./AbstractDataStore');
-class VoiceChannelDataStore extends AbstractDataStore{
- constructor() {
- super();
- this.register('members');
- }
+class VoiceChannelDataStore extends AbstractDataStore {
+ constructor() {
+ super();
+ this.register('members');
+ }
}
module.exports = VoiceChannelDataStore;
diff --git a/src/structures/datastore/WebSocketManagerDataStore.js b/src/structures/datastore/WebSocketManagerDataStore.js
index a63d41369..82f8d94c4 100644
--- a/src/structures/datastore/WebSocketManagerDataStore.js
+++ b/src/structures/datastore/WebSocketManagerDataStore.js
@@ -1,14 +1,12 @@
-'use strict';
-
const AbstractDataStore = require('./AbstractDataStore');
-class WebSocketManagerDataStore extends AbstractDataStore{
- constructor() {
- super();
- this.sessionID = null;
- this.sequence = -1;
- this.gateway = null;
- }
+class WebSocketManagerDataStore extends AbstractDataStore {
+ constructor() {
+ super();
+ this.sessionID = null;
+ this.sequence = -1;
+ this.gateway = null;
+ }
}
module.exports = WebSocketManagerDataStore;
diff --git a/src/structures/interface/TextBasedChannel.js b/src/structures/interface/TextBasedChannel.js
index a76a855a5..1eb44ca90 100644
--- a/src/structures/interface/TextBasedChannel.js
+++ b/src/structures/interface/TextBasedChannel.js
@@ -1,15 +1,12 @@
-'use strict';
-
-function sendMessage(content, options) {
- options = options || {};
- return this.client.rest.methods.SendMessage(this, content, options.tts);
+function sendMessage(content, options = {}) {
+ return this.client.rest.methods.sendMessage(this, content, options.tts);
}
-function sendTTSMessage(content, options) {
- options = options || {};
- return this.client.rest.methods.SendMessage(this, content, true);
+function sendTTSMessage(content) {
+ return this.client.rest.methods.sendMessage(this, content, true);
}
exports.applyToClass = structure => {
- structure.prototype.sendMessage = sendMessage;
+ structure.prototype.sendMessage = sendMessage;
+ structure.prototype.sendTTSMessage = sendTTSMessage;
};
diff --git a/src/util/CloneObject.js b/src/util/CloneObject.js
index 158f9d189..726712fb6 100644
--- a/src/util/CloneObject.js
+++ b/src/util/CloneObject.js
@@ -1,7 +1,6 @@
-'use strict';
-module.exports = function CloneObject(obj) {
- var cloned = Object.create(obj);
- Object.assign(cloned, obj);
+module.exports = function cloneObject(obj) {
+ const cloned = Object.create(obj);
+ Object.assign(cloned, obj);
- return cloned;
+ return cloned;
};
diff --git a/src/util/Constants.js b/src/util/Constants.js
index daf082231..f958c3a7f 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -1,184 +1,182 @@
-'use strict';
-
-const DefaultOptions = exports.DefaultOptions = {
- ws: {
- large_threshold: 250,
- compress: true,
- properties: {
- $os: process ? process.platform : 'discord.js',
- $browser: 'discord.js',
- $device: 'discord.js',
- $referrer: '',
- $referring_domain: '',
- },
- },
- protocol_version: 4,
- max_message_cache: 200,
- rest_ws_bridge_timeout: 5000,
+exports.DefaultOptions = {
+ ws: {
+ large_threshold: 250,
+ compress: true,
+ properties: {
+ $os: process ? process.platform : 'discord.js',
+ $browser: 'discord.js',
+ $device: 'discord.js',
+ $referrer: '',
+ $referring_domain: '',
+ },
+ },
+ protocol_version: 4,
+ max_message_cache: 200,
+ rest_ws_bridge_timeout: 5000,
};
-const Status = exports.Status = {
- READY: 0,
- CONNECTING: 1,
- RECONNECTING: 2,
- IDLE: 3,
+exports.Status = {
+ READY: 0,
+ CONNECTING: 1,
+ RECONNECTING: 2,
+ IDLE: 3,
};
-const Package = exports.Package = require('../../package.json');
+exports.Package = require('../../package.json');
-const Errors = exports.Errors = {
- NO_TOKEN: new Error('request to use token, but token was unavailable to the client'),
- NO_BOT_ACCOUNT: new Error('you should ideally be using a bot account!'),
- BAD_WS_MESSAGE: new Error('a bad message was received from the websocket - bad compression or not json'),
- TOOK_TOO_LONG: new Error('something took too long to do'),
- NOT_A_PERMISSION: new Error('that is not a valid permission number'),
+exports.Errors = {
+ NO_TOKEN: new Error('request to use token, but token was unavailable to the client'),
+ NO_BOT_ACCOUNT: new Error('you should ideally be using a bot account!'),
+ BAD_WS_MESSAGE: new Error('a bad message was received from the websocket - bad compression or not json'),
+ TOOK_TOO_LONG: new Error('something took too long to do'),
+ NOT_A_PERMISSION: new Error('that is not a valid permission number'),
};
const API = 'https://discordapp.com/api';
const Endpoints = exports.Endpoints = {
- // general endpoints
- LOGIN: `${API}/auth/login`,
- LOGOUT: `${API}/auth/logout`,
- ME: `${API}/users/@me`,
- ME_GUILD: (guildID) => `${Endpoints.ME}/guilds/${guildID}`,
- GATEWAY: `${API}/gateway`,
- USER_CHANNELS: (userID) => `${API}/users/${userID}/channels`,
- AVATAR: (userID, avatar) => `${API}/users/${userID}/avatars/${avatar}.jpg`,
- INVITE: (id) => `${API}/invite/${id}`,
+ // general endpoints
+ login: `${API}/auth/login`,
+ logout: `${API}/auth/logout`,
+ me: `${API}/users/@me`,
+ meGuild: (guildID) => `${Endpoints.me}/guilds/${guildID}`,
+ gateway: `${API}/gateway`,
+ userChannels: (userID) => `${API}/users/${userID}/channels`,
+ avatar: (userID, avatar) => `${API}/users/${userID}/avatars/${avatar}.jpg`,
+ invite: (id) => `${API}/invite/${id}`,
- // guilds
- GUILDS: `${API}/guilds`,
- GUILD: (guildID) => `${Endpoints.GUILDS}/${guildID}`,
- GUILD_ICON: (guildID, hash) => `${Endpoints.GUILD(guildID)}/icons/${hash}.jpg`,
- GUILD_PRUNE: (guildID) => `${Endpoints.GUILD(guildID)}/prune`,
- GUILD_EMBED: (guildID) => `${Endpoints.GUILD(guildID)}/embed`,
- GUILD_INVITES: (guildID) => `${Endpoints.GUILD(guildID)}/invites`,
- GUILD_ROLES: (guildID) => `${Endpoints.GUILD(guildID)}/roles`,
- GUILD_ROLE: (guildID, roleID) => `${Endpoints.GUILD_ROLES(guildID)}/${roleID}`,
- GUILD_BANS: (guildID) => `${Endpoints.GUILD(guildID)}/bans`,
- GUILD_INTEGRATIONS: (guildID) => `${Endpoints.GUILD(guildID)}/integrations`,
- GUILD_MEMBERS: (guildID) => `${Endpoints.GUILD(guildID)}/members`,
- GUILD_MEMBER: (guildID, memberID) => `${Endpoints.GUILD_MEMBERS(guildID)}/${memberID}`,
- GUILD_CHANNELS: (guildID) => `${Endpoints.GUILD(guildID)}/channels`,
+ // guilds
+ guilds: `${API}/guilds`,
+ guild: (guildID) => `${Endpoints.guilds}/${guildID}`,
+ guildIcon: (guildID, hash) => `${Endpoints.guild(guildID)}/icons/${hash}.jpg`,
+ guildPrune: (guildID) => `${Endpoints.guild(guildID)}/prune`,
+ guildEmbed: (guildID) => `${Endpoints.guild(guildID)}/embed`,
+ guildInvites: (guildID) => `${Endpoints.guild(guildID)}/invites`,
+ guildRoles: (guildID) => `${Endpoints.guild(guildID)}/roles`,
+ guildRole: (guildID, roleID) => `${Endpoints.guildRoles(guildID)}/${roleID}`,
+ guildBans: (guildID) => `${Endpoints.guild(guildID)}/bans`,
+ guildIntegrations: (guildID) => `${Endpoints.guild(guildID)}/integrations`,
+ guildMembers: (guildID) => `${Endpoints.guild(guildID)}/members`,
+ guildMember: (guildID, memberID) => `${Endpoints.guildMembers(guildID)}/${memberID}`,
+ guildChannels: (guildID) => `${Endpoints.guild(guildID)}/channels`,
- // channels
- CHANNELS: `${API}/channels`,
- CHANNEL: (channelID) => `${Endpoints.CHANNELS}/${channelID}`,
- CHANNEL_MESSAGES: (channelID) => `${Endpoints.CHANNEL(channelID)}/messages`,
- CHANNEL_INVITES: (channelID) => `${Endpoints.CHANNEL(channelID)}/invites`,
- CHANNEL_TYPING: (channelID) => `${Endpoints.CHANNEL(channelID)}/typing`,
- CHANNEL_PERMISSIONS: (channelID) => `${Endpoints.CHANNEL(channelID)}/permissions`,
- CHANNEL_MESSAGE: (channelID, messageID) => `${Endpoints.CHANNEL_MESSAGES(channelID)}/${messageID}`,
+ // channels
+ channels: `${API}/channels`,
+ channel: (channelID) => `${Endpoints.channels}/${channelID}`,
+ channelMessages: (channelID) => `${Endpoints.channel(channelID)}/messages`,
+ channelInvites: (channelID) => `${Endpoints.channel(channelID)}/invites`,
+ channelTyping: (channelID) => `${Endpoints.channel(channelID)}/typing`,
+ channelPermissions: (channelID) => `${Endpoints.channel(channelID)}/permissions`,
+ channelMessage: (channelID, messageID) => `${Endpoints.channelMessage(channelID)}/${messageID}`,
};
-const OPCodes = exports.OPCodes = {
- DISPATCH: 0,
- HEARTBEAT: 1,
- IDENTIFY: 2,
- STATUS_UPDATE: 3,
- VOICE_STATE_UPDATE: 4,
- VOICE_GUILD_PING: 5,
- RESUME: 6,
- RECONNECT: 7,
- REQUEST_GUILD_MEMBERS: 8,
- INVALID_SESSION: 9,
+exports.OPCodes = {
+ DISPATCH: 0,
+ HEARTBEAT: 1,
+ IDENTIFY: 2,
+ STATUS_UPDATE: 3,
+ VOICE_STATE_UPDATE: 4,
+ VOICE_GUILD_PING: 5,
+ RESUME: 6,
+ RECONNECT: 7,
+ REQUEST_GUILD_MEMBERS: 8,
+ INVALID_SESSION: 9,
};
-const Events = exports.Events = {
- READY: 'ready',
- GUILD_CREATE: 'guildCreate',
- GUILD_DELETE: 'guildDelete',
- GUILD_UNAVAILABLE: 'guildUnavailable',
- GUILD_AVAILABLE: 'guildAvailable',
- GUILD_UPDATE: 'guildUpdate',
- GUILD_BAN_ADD: 'guildBanAdd',
- GUILD_BAN_REMOVE: 'guildBanRemove',
- GUILD_MEMBER_ADD: 'guildMemberAdd',
- GUILD_MEMBER_REMOVE: 'guildMemberRemove',
- GUILD_MEMBER_ROLES_UPDATE: 'guildMemberRolesUpdate',
- GUILD_ROLE_CREATE: 'guildRoleCreate',
- GUILD_ROLE_DELETE: 'guildRoleDelete',
- GUILD_ROLE_UPDATE: 'guildRoleUpdate',
- GUILD_MEMBER_AVAILABLE: 'guildMemberAvailable',
- CHANNEL_CREATE: 'channelCreate',
- CHANNEL_DELETE: 'channelDelete',
- CHANNEL_UPDATE: 'channelUpdate',
- PRESENCE_UPDATE: 'presenceUpdate',
- USER_UPDATE: 'userUpdate',
- VOICE_STATE_UPDATE: 'voiceStateUpdate',
- TYPING_START: 'typingStart',
- TYPING_STOP: 'typingStop',
- WARN: 'warn',
- GUILD_MEMBERS_CHUNK: 'guildMembersChunk',
- MESSAGE_CREATE: 'message',
- MESSAGE_DELETE: 'messageDelete',
- MESSAGE_UPDATE: 'messageUpdate',
+exports.Events = {
+ READY: 'ready',
+ GUILD_CREATE: 'guildCreate',
+ GUILD_DELETE: 'guildDelete',
+ GUILD_UNAVAILABLE: 'guildUnavailable',
+ GUILD_AVAILABLE: 'guildAvailable',
+ GUILD_UPDATE: 'guildUpdate',
+ GUILD_BAN_ADD: 'guildBanAdd',
+ GUILD_BAN_REMOVE: 'guildBanRemove',
+ GUILD_MEMBER_ADD: 'guildMemberAdd',
+ GUILD_MEMBER_REMOVE: 'guildMemberRemove',
+ GUILD_MEMBER_ROLES_UPDATE: 'guildMemberRolesUpdate',
+ GUILD_ROLE_CREATE: 'guildRoleCreate',
+ GUILD_ROLE_DELETE: 'guildRoleDelete',
+ GUILD_ROLE_UPDATE: 'guildRoleUpdate',
+ GUILD_MEMBER_AVAILABLE: 'guildMemberAvailable',
+ CHANNEL_CREATE: 'channelCreate',
+ CHANNEL_DELETE: 'channelDelete',
+ CHANNEL_UPDATE: 'channelUpdate',
+ PRESENCE_UPDATE: 'presenceUpdate',
+ USER_UPDATE: 'userUpdate',
+ VOICE_STATE_UPDATE: 'voiceStateUpdate',
+ TYPING_START: 'typingStart',
+ TYPING_STOP: 'typingStop',
+ WARN: 'warn',
+ GUILD_MEMBERS_CHUNK: 'guildMembersChunk',
+ MESSAGE_CREATE: 'message',
+ MESSAGE_DELETE: 'messageDelete',
+ MESSAGE_UPDATE: 'messageUpdate',
};
-const WSEvents = exports.WSEvents = {
- CHANNEL_CREATE: 'CHANNEL_CREATE',
- CHANNEL_DELETE: 'CHANNEL_DELETE',
- CHANNEL_UPDATE: 'CHANNEL_UPDATE',
- MESSAGE_CREATE: 'MESSAGE_CREATE',
- MESSAGE_DELETE: 'MESSAGE_DELETE',
- MESSAGE_UPDATE: 'MESSAGE_UPDATE',
- PRESENCE_UPDATE: 'PRESENCE_UPDATE',
- READY: 'READY',
- GUILD_BAN_ADD: 'GUILD_BAN_ADD',
- GUILD_BAN_REMOVE: 'GUILD_BAN_REMOVE',
- GUILD_CREATE: 'GUILD_CREATE',
- GUILD_DELETE: 'GUILD_DELETE',
- GUILD_MEMBER_ADD: 'GUILD_MEMBER_ADD',
- GUILD_MEMBER_REMOVE: 'GUILD_MEMBER_REMOVE',
- GUILD_MEMBER_UPDATE: 'GUILD_MEMBER_UPDATE',
- GUILD_MEMBERS_CHUNK: 'GUILD_MEMBERS_CHUNK',
- GUILD_ROLE_CREATE: 'GUILD_ROLE_CREATE',
- GUILD_ROLE_DELETE: 'GUILD_ROLE_DELETE',
- GUILD_ROLE_UPDATE: 'GUILD_ROLE_UPDATE',
- GUILD_UPDATE: 'GUILD_UPDATE',
- TYPING_START: 'TYPING_START',
- USER_UPDATE: 'USER_UPDATE',
- VOICE_STATE_UPDATE: 'VOICE_STATE_UPDATE',
- FRIEND_ADD: 'RELATIONSHIP_ADD',
- FRIEND_REMOVE: 'RELATIONSHIP_REMOVE',
+exports.WSEvents = {
+ CHANNEL_CREATE: 'CHANNEL_CREATE',
+ CHANNEL_DELETE: 'CHANNEL_DELETE',
+ CHANNEL_UPDATE: 'CHANNEL_UPDATE',
+ MESSAGE_CREATE: 'MESSAGE_CREATE',
+ MESSAGE_DELETE: 'MESSAGE_DELETE',
+ MESSAGE_UPDATE: 'MESSAGE_UPDATE',
+ PRESENCE_UPDATE: 'PRESENCE_UPDATE',
+ READY: 'READY',
+ GUILD_BAN_ADD: 'GUILD_BAN_ADD',
+ GUILD_BAN_REMOVE: 'GUILD_BAN_REMOVE',
+ GUILD_CREATE: 'GUILD_CREATE',
+ GUILD_DELETE: 'GUILD_DELETE',
+ GUILD_MEMBER_ADD: 'GUILD_MEMBER_ADD',
+ GUILD_MEMBER_REMOVE: 'GUILD_MEMBER_REMOVE',
+ GUILD_MEMBER_UPDATE: 'GUILD_MEMBER_UPDATE',
+ GUILD_MEMBERS_CHUNK: 'GUILD_MEMBERS_CHUNK',
+ GUILD_ROLE_CREATE: 'GUILD_ROLE_CREATE',
+ GUILD_ROLE_DELETE: 'GUILD_ROLE_DELETE',
+ GUILD_ROLE_UPDATE: 'GUILD_ROLE_UPDATE',
+ GUILD_UPDATE: 'GUILD_UPDATE',
+ TYPING_START: 'TYPING_START',
+ USER_UPDATE: 'USER_UPDATE',
+ VOICE_STATE_UPDATE: 'VOICE_STATE_UPDATE',
+ FRIEND_ADD: 'RELATIONSHIP_ADD',
+ FRIEND_REMOVE: 'RELATIONSHIP_REMOVE',
};
const PermissionFlags = exports.PermissionFlags = {
- CREATE_INSTANT_INVITE: 1 << 0,
- KICK_MEMBERS: 1 << 1,
- BAN_MEMBERS: 1 << 2,
- ADMINISTRATOR: 1 << 3,
- MANAGE_CHANNELS: 1 << 4,
- MANAGE_GUILD: 1 << 5,
+ CREATE_INSTANT_INVITE: 1 << 0,
+ KICK_MEMBERS: 1 << 1,
+ BAN_MEMBERS: 1 << 2,
+ ADMINISTRATOR: 1 << 3,
+ MANAGE_CHANNELS: 1 << 4,
+ MANAGE_GUILD: 1 << 5,
- READ_MESSAGES: 1 << 10,
- SEND_MESSAGES: 1 << 11,
- SEND_TTS_MESSAGES: 1 << 12,
- MANAGE_MESSAGES: 1 << 13,
- EMBED_LINKS: 1 << 14,
- ATTACH_FILES: 1 << 15,
- READ_MESSAGE_HISTORY: 1 << 16,
- MENTION_EVERYONE: 1 << 17,
+ READ_MESSAGES: 1 << 10,
+ SEND_MESSAGES: 1 << 11,
+ SEND_TTS_MESSAGES: 1 << 12,
+ MANAGE_MESSAGES: 1 << 13,
+ EMBED_LINKS: 1 << 14,
+ ATTACH_FILES: 1 << 15,
+ READ_MESSAGE_HISTORY: 1 << 16,
+ MENTION_EVERYONE: 1 << 17,
- CONNECT: 1 << 20,
- SPEAK: 1 << 21,
- MUTE_MEMBERS: 1 << 22,
- DEAFEN_MEMBERS: 1 << 23,
- MOVE_MEMBERS: 1 << 24,
- USE_VAD: 1 << 25,
+ CONNECT: 1 << 20,
+ SPEAK: 1 << 21,
+ MUTE_MEMBERS: 1 << 22,
+ DEAFEN_MEMBERS: 1 << 23,
+ MOVE_MEMBERS: 1 << 24,
+ USE_VAD: 1 << 25,
- CHANGE_NICKNAME: 1 << 26,
- MANAGE_NICKNAMES: 1 << 27,
- MANAGE_ROLES_OR_PERMISSIONS: 1 << 28,
+ CHANGE_NICKNAME: 1 << 26,
+ MANAGE_NICKNAMES: 1 << 27,
+ MANAGE_ROLES_OR_PERMISSIONS: 1 << 28,
};
let _ALL_PERMISSIONS = 0;
-for (let key in PermissionFlags) {
- _ALL_PERMISSIONS |= PermissionFlags[key];
+for (const key in PermissionFlags) {
+ _ALL_PERMISSIONS |= PermissionFlags[key];
}
-const ALL_PERMISSIONS = exports.ALL_PERMISSIONS = _ALL_PERMISSIONS;
+exports.ALL_PERMISSIONS = _ALL_PERMISSIONS;
-const DEFAULT_PERMISSIONS = exports.DEFAULT_PERMISSIONS = 36953089;
+exports.DEFAULT_PERMISSIONS = 36953089;
diff --git a/src/util/MergeDefault.js b/src/util/MergeDefault.js
index 3da11d278..d07044cdc 100644
--- a/src/util/MergeDefault.js
+++ b/src/util/MergeDefault.js
@@ -1,19 +1,17 @@
-'use strict';
-
module.exports = function merge(def, given) {
- if (!given) {
- return def;
- }
+ if (!given) {
+ return def;
+ }
- given = given || {};
+ given = given || {};
- for (var key in def) {
- if (!given.hasOwnProperty(key)) {
- given[key] = def[key];
- } else if (given[key] === Object(given[key])) {
- given[key] = merge(def[key], given[key]);
- }
- }
+ for (const key in def) {
+ if (!{}.hasOwnProperty.call(given, key)) {
+ given[key] = def[key];
+ } else if (given[key] === Object(given[key])) {
+ given[key] = merge(def[key], given[key]);
+ }
+ }
- return given;
+ return given;
};
diff --git a/test/random.js b/test/random.js
index a1de4025f..54516b2be 100644
--- a/test/random.js
+++ b/test/random.js
@@ -3,172 +3,172 @@
const Discord = require('../');
const request = require('superagent');
-let client = new Discord.Client();
+const client = new Discord.Client();
client.login(require('./auth.json').token).then(token => console.log('logged in with token ' + token)).catch(console.log);
client.on('ready', () => {
- console.log('ready!');
+ console.log('ready!');
});
client.on('guildCreate', (guild) => {
- console.log(guild);
+ console.log(guild);
});
client.on('guildDelete', (guild) => {
- console.log('guilddel', guild.name);
+ console.log('guilddel', guild.name);
});
client.on('guildUpdate', (old, guild) => {
- console.log('guildupdate', old.name, guild.name);
+ console.log('guildupdate', old.name, guild.name);
});
client.on('channelCreate', channel => {
- // console.log(channel);
+ // console.log(channel);
});
client.on('channelDelete', channel => {
- console.log('channDel', channel.name);
+ console.log('channDel', channel.name);
});
client.on('channelUpdate', (old, chan) => {
- console.log('chan update', old.name, chan.name);
+ console.log('chan update', old.name, chan.name);
});
client.on('guildMemberAdd', (guild, user) => {
- console.log('new guild member', user.user.username, 'in', guild.name);
+ console.log('new guild member', user.user.username, 'in', guild.name);
});
client.on('guildMemberRemove', (guild, user) => {
- console.log('dead guild member', user.user.username, 'in', guild.name);
+ console.log('dead guild member', user.user.username, 'in', guild.name);
});
client.on('guildRoleCreate', (guild, role) => {
- console.log('new role', role.name, 'in', guild.name);
- role.edit({
- permissions: ['DEAFEN_MEMBERS'],
- name: 'deafen'
- }).then(role2 => {
- console.log('role replace from ' + role.name + ' to ' + role2.name);
- }).catch(console.log)
+ console.log('new role', role.name, 'in', guild.name);
+ role.edit({
+ permissions: ['DEAFEN_MEMBERS'],
+ name: 'deafen',
+ }).then(role2 => {
+ console.log('role replace from ' + role.name + ' to ' + role2.name);
+ }).catch(console.log);
});
client.on('guildRoleDelete', (guild, role) => {
- console.log('dead role', role.name, 'in', guild.name);
+ console.log('dead role', role.name, 'in', guild.name);
});
client.on('guildRoleUpdate', (guild, old, newRole) => {
- console.log('updated role', old.name, 'to', newRole.name, 'in', guild.name);
+ console.log('updated role', old.name, 'to', newRole.name, 'in', guild.name);
});
client.on('presenceUpdate', (oldUser, newUser) => {
- // console.log('presence from', oldUser.username, 'to', newUser.username);
+ // console.log('presence from', oldUser.username, 'to', newUser.username);
});
client.on('voiceStateUpdate', (oldMember, newMember) => {
- console.log('voiceState', oldMember.user.username, oldMember.voiceChannel + '', newMember.voiceChannel + '');
+ console.log('voiceState', oldMember.user.username, oldMember.voiceChannel + '', newMember.voiceChannel + '');
});
client.on('typingStart.', (channel, user) => {
- if (user.username === 'hydrabolt')
- console.log(user.username, 'started typing in', channel.name);
+ if (user.username === 'hydrabolt')
+ console.log(user.username, 'started typing in', channel.name);
});
client.on('typingStop.', (channel, user, data) => {
- if (user.username === 'hydrabolt')
- console.log(user.username, 'stopped typing in', channel.name, 'after', data.elapsedTime + 'ms');
+ if (user.username === 'hydrabolt')
+ console.log(user.username, 'stopped typing in', channel.name, 'after', data.elapsedTime + 'ms');
});
client.on('message', message => {
- if (true) {
- if (message.content === 'makechann') {
- if (message.channel.guild) {
- message.channel.guild.createChannel('hi', 'text').then(console.log);
- }
- }
+ if (true) {
+ if (message.content === 'makechann') {
+ if (message.channel.guild) {
+ message.channel.guild.createChannel('hi', 'text').then(console.log);
+ }
+ }
- if (message.content === 'myperms?') {
- message.channel.sendMessage('Your permissions are:\n' +
- JSON.stringify(message.channel.permissionsFor(message.author).serialize(), null, 4));
- }
+ if (message.content === 'myperms?') {
+ message.channel.sendMessage('Your permissions are:\n' +
+ JSON.stringify(message.channel.permissionsFor(message.author).serialize(), null, 4));
+ }
- if (message.content === 'delchann') {
- message.channel.delete().then(chan => console.log('selfDelChann', chan.name));
- }
+ if (message.content === 'delchann') {
+ message.channel.delete().then(chan => console.log('selfDelChann', chan.name));
+ }
- if (message.content.startsWith('setname')) {
- message.channel.setName(message.content.substr(8));
- }
+ if (message.content.startsWith('setname')) {
+ message.channel.setName(message.content.substr(8));
+ }
- if (message.content.startsWith('botname')) {
- client.user.setUsername(message.content.substr(8));
- }
+ if (message.content.startsWith('botname')) {
+ client.user.setUsername(message.content.substr(8));
+ }
- if (message.content.startsWith('botavatar')) {
- request
- .get('url')
- .end((err, res) => {
- client.user.setAvatar(res.body).catch(console.log)
- .then(user => message.channel.sendMessage('Done!'));
- });
- }
+ if (message.content.startsWith('botavatar')) {
+ request
+ .get('url')
+ .end((err, res) => {
+ client.user.setAvatar(res.body).catch(console.log)
+ .then(user => message.channel.sendMessage('Done!'));
+ });
+ }
- if (message.content.startsWith('gn')) {
- message.guild.setName(message.content.substr(3))
- .then(guild => console.log('guild updated to', guild.name))
- .catch(console.log);
- }
+ if (message.content.startsWith('gn')) {
+ message.guild.setName(message.content.substr(3))
+ .then(guild => console.log('guild updated to', guild.name))
+ .catch(console.log);
+ }
- if (message.content === 'leave') {
- message.guild.leave().then(guild => console.log('left guild', guild.name)).catch(console.log);
- }
+ if (message.content === 'leave') {
+ message.guild.leave().then(guild => console.log('left guild', guild.name)).catch(console.log);
+ }
- if (message.content === 'stats') {
- let m = '';
- m += `I am aware of ${message.guild.channels.length} channels\n`;
- m += `I am aware of ${message.guild.members.length} members`;
- message.channel.sendMessage(m);
- }
+ if (message.content === 'stats') {
+ let m = '';
+ m += `I am aware of ${message.guild.channels.length} channels\n`;
+ m += `I am aware of ${message.guild.members.length} members`;
+ message.channel.sendMessage(m);
+ }
- if (message.content === 'messageme!') {
- message.author.sendMessage('oh, hi there!').catch(e => console.log(e.stack));
- }
+ if (message.content === 'messageme!') {
+ message.author.sendMessage('oh, hi there!').catch(e => console.log(e.stack));
+ }
- if (message.content === 'don\'t dm me') {
- message.author.deleteDM();
- }
+ if (message.content === 'don\'t dm me') {
+ message.author.deleteDM();
+ }
- if (message.content.startsWith('kick')) {
- message.guild.member(message.mentions[0]).kick().then(member => {
- console.log(member);
- message.channel.sendMessage('Kicked!' + member.user.username);
- }).catch(console.log);
- }
+ if (message.content.startsWith('kick')) {
+ message.guild.member(message.mentions[0]).kick().then(member => {
+ console.log(member);
+ message.channel.sendMessage('Kicked!' + member.user.username);
+ }).catch(console.log);
+ }
- if (message.content === 'makerole') {
- message.guild.createRole().then(role => {
- message.channel.sendMessage(`Made role ${role.name}`);
- }).catch(console.log);
- }
- }
+ if (message.content === 'makerole') {
+ message.guild.createRole().then(role => {
+ message.channel.sendMessage(`Made role ${role.name}`);
+ }).catch(console.log);
+ }
+ }
});
function nameLoop(user) {
- // user.setUsername(user.username + 'a').then(nameLoop).catch(console.log);
+ // user.setUsername(user.username + 'a').then(nameLoop).catch(console.log);
}
function chanLoop(channel) {
- channel.setName(channel.name + 'a').then(chanLoop).catch(console.log);
+ channel.setName(channel.name + 'a').then(chanLoop).catch(console.log);
}
client.on('messageDelete', message => {
- console.log('Message deleted by', message.author.username);
+ console.log('Message deleted by', message.author.username);
});
client.on('messageUpdate', (old, message) => {
- if (message.author.username === 'hydrabolt')
- console.log('Message updated from', old.content, 'to', message.content);
+ if (message.author.username === 'hydrabolt')
+ console.log('Message updated from', old.content, 'to', message.content);
});
client.on('message', message => {
- if (message.content === '?perms?') {
- console.log(message.author.username, 'asked for perms in', message.channel.name, ':');
- console.log(message.channel.permissionsFor(message.author).serialize());
- }
+ if (message.content === '?perms?') {
+ console.log(message.author.username, 'asked for perms in', message.channel.name, ':');
+ console.log(message.channel.permissionsFor(message.author).serialize());
+ }
});
From f2ccef1ce57584ee737a1f959a8a80bf7fc5d9d1 Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sat, 13 Aug 2016 14:45:22 +0100
Subject: [PATCH 044/324] remove console.log in rest
---
src/client/rest/RESTManager.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/client/rest/RESTManager.js b/src/client/rest/RESTManager.js
index 768367219..9db8403b7 100644
--- a/src/client/rest/RESTManager.js
+++ b/src/client/rest/RESTManager.js
@@ -56,7 +56,6 @@ class RESTManager {
/*
file is {file, name}
*/
- console.log(url);
const apiRequest = request[method](url);
const endpoint = url.replace(/\/[0-9]+/g, '/:id');
From 50af835774f2ee2eac3b3da45278f5aace8a8ebb Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sat, 13 Aug 2016 14:53:04 +0100
Subject: [PATCH 045/324] Move to v6 protocol
---
src/client/websocket/WebSocketManager.js | 1 -
src/util/Constants.js | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/client/websocket/WebSocketManager.js b/src/client/websocket/WebSocketManager.js
index 0b30d627d..4ac300004 100644
--- a/src/client/websocket/WebSocketManager.js
+++ b/src/client/websocket/WebSocketManager.js
@@ -91,7 +91,6 @@ class WebSocketManager {
checkIfReady() {
if (this.status !== Constants.Status.READY) {
let unavailableCount = 0;
-
for (const guildID in this.client.store.data.guilds) {
unavailableCount += this.client.store.data.guilds[guildID].available ? 0 : 1;
}
diff --git a/src/util/Constants.js b/src/util/Constants.js
index f958c3a7f..0625118e1 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -10,7 +10,7 @@ exports.DefaultOptions = {
$referring_domain: '',
},
},
- protocol_version: 4,
+ protocol_version: 6,
max_message_cache: 200,
rest_ws_bridge_timeout: 5000,
};
From c02d7808c1e8b9b65242a3754f6cf58e9c2dd9bd Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sat, 13 Aug 2016 16:01:01 +0100
Subject: [PATCH 046/324] =?UTF-8?q?go=20back=20to=20protocol=205=20because?=
=?UTF-8?q?=20the=20docs=20aren't=20ready=20for=20v6=20=C2=AF\=5F(?=
=?UTF-8?q?=E3=83=84)=5F/=C2=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/util/Constants.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/util/Constants.js b/src/util/Constants.js
index 0625118e1..69780c241 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -10,7 +10,7 @@ exports.DefaultOptions = {
$referring_domain: '',
},
},
- protocol_version: 6,
+ protocol_version: 5,
max_message_cache: 200,
rest_ws_bridge_timeout: 5000,
};
From a2f868051404f42650a000c77cb20f8c55f0d839 Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sat, 13 Aug 2016 16:23:24 +0100
Subject: [PATCH 047/324] Fix protocol versions
---
src/client/rest/RESTMethods.js | 5 ++++-
src/client/websocket/WebSocketManager.js | 9 ++++++---
src/client/websocket/packets/handlers/Ready.js | 1 -
3 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index 9eff9d3d1..abb5390da 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -30,7 +30,10 @@ class RESTMethods {
getGateway() {
return new Promise((resolve, reject) => {
this.rest.makeRequest('get', Constants.Endpoints.gateway, true)
- .then(res => resolve(res.url))
+ .then(res => {
+ this.rest.client.store.gateway = `${res.url}/?encoding=json&v=${this.rest.client.options.protocol_version}`;
+ resolve(this.rest.client.store.gateway);
+ })
.catch(reject);
});
}
diff --git a/src/client/websocket/WebSocketManager.js b/src/client/websocket/WebSocketManager.js
index 4ac300004..08df59b46 100644
--- a/src/client/websocket/WebSocketManager.js
+++ b/src/client/websocket/WebSocketManager.js
@@ -16,7 +16,6 @@ class WebSocketManager {
connect(gateway) {
this.status = Constants.Status.CONNECTING;
- this.store.gateway = `${gateway}/?v=${this.client.options.protocol_version}`;
this.ws = new WebSocket(gateway);
this.ws.onopen = () => this.eventOpen();
this.ws.onclose = () => this.eventClose();
@@ -81,10 +80,14 @@ class WebSocketManager {
return this.eventError(Constants.Errors.BAD_WS_MESSAGE);
}
+ if (packet.op === 10) {
+ this.client.manager.setupKeepAlive(packet.d.heartbeat_interval);
+ }
+
return this.packetManager.handle(packet);
}
- EventError() {
+ eventError() {
this.tryReconnect();
}
@@ -108,7 +111,7 @@ class WebSocketManager {
this.ws.close();
this.packetManager.handleQueue();
this.client.emit(Constants.Events.RECONNECTING);
- this.connect(this.store.gateway);
+ this.connect(this.client.store.gateway);
}
}
diff --git a/src/client/websocket/packets/handlers/Ready.js b/src/client/websocket/packets/handlers/Ready.js
index e37d0a758..f49a8aa63 100644
--- a/src/client/websocket/packets/handlers/Ready.js
+++ b/src/client/websocket/packets/handlers/Ready.js
@@ -8,7 +8,6 @@ class ReadyHandler extends AbstractHandler {
handle(packet) {
const data = packet.d;
const client = this.packetManager.client;
- client.manager.setupKeepAlive(data.heartbeat_interval);
client.store.user = client.store.add('users', new ClientUser(client, data.user));
From 75e3ee86fbbc23910f84594909e4a5c7ba10e88d Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sat, 13 Aug 2016 16:29:19 +0100
Subject: [PATCH 048/324] Add userLimit param to voice channel
---
src/structures/VoiceChannel.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/structures/VoiceChannel.js b/src/structures/VoiceChannel.js
index 9c643820d..4a4f6c253 100644
--- a/src/structures/VoiceChannel.js
+++ b/src/structures/VoiceChannel.js
@@ -10,6 +10,7 @@ class VoiceChannel extends ServerChannel {
setup(data) {
super.setup(data);
this.bitrate = data.bitrate;
+ this.userLimit = data.user_limit;
}
}
From 7ada70f856debf03be3ae30603c868260f649a00 Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sat, 13 Aug 2016 16:41:06 +0100
Subject: [PATCH 049/324] update back to v6 (again) and start work patching the
lib
---
src/structures/datastore/ClientDataStore.js | 6 +++---
src/util/Constants.js | 9 ++++++++-
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/structures/datastore/ClientDataStore.js b/src/structures/datastore/ClientDataStore.js
index 4d0dd0a87..b62e97af5 100644
--- a/src/structures/datastore/ClientDataStore.js
+++ b/src/structures/datastore/ClientDataStore.js
@@ -46,15 +46,15 @@ class ClientDataStore extends AbstractDataStore {
let guild = $guild;
const already = this.get('channels', data.id);
let channel;
- if (data.is_private) {
+ if (data.type === Constants.ChannelTypes.DM) {
channel = new DMChannel(this.client, data);
} else {
guild = guild || this.get('guilds', data.guild_id);
if (guild) {
- if (data.type === 'text') {
+ if (data.type === Constants.ChannelTypes.text) {
channel = new TextChannel(guild, data);
guild.store.add('channels', channel);
- } else if (data.type === 'voice') {
+ } else if (data.type === Constants.ChannelTypes.voice) {
channel = new VoiceChannel(guild, data);
guild.store.add('channels', channel);
}
diff --git a/src/util/Constants.js b/src/util/Constants.js
index 69780c241..bfaf84e57 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -10,7 +10,7 @@ exports.DefaultOptions = {
$referring_domain: '',
},
},
- protocol_version: 5,
+ protocol_version: 6,
max_message_cache: 200,
rest_ws_bridge_timeout: 5000,
};
@@ -22,6 +22,13 @@ exports.Status = {
IDLE: 3,
};
+exports.ChannelTypes = {
+ text: 0,
+ DM: 1,
+ voice: 2,
+ groupDM: 3,
+};
+
exports.Package = require('../../package.json');
exports.Errors = {
From b2950b299735eb42c1911ba930176f09e7bf6d68 Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sat, 13 Aug 2016 16:51:01 +0100
Subject: [PATCH 050/324] Fix DM Channels
---
src/client/rest/RESTMethods.js | 2 +-
src/structures/DMChannel.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js
index abb5390da..fa62fa85f 100644
--- a/src/client/rest/RESTMethods.js
+++ b/src/client/rest/RESTMethods.js
@@ -56,7 +56,7 @@ class RESTMethods {
channel = chan;
req();
})
- .catch(reject);
+ .catch(reject);
} else {
req();
}
diff --git a/src/structures/DMChannel.js b/src/structures/DMChannel.js
index 53d0be758..3714339bd 100644
--- a/src/structures/DMChannel.js
+++ b/src/structures/DMChannel.js
@@ -26,7 +26,7 @@ class DMChannel extends Channel {
setup(data) {
super.setup(data);
- this.recipient = this.client.store.add('users', new User(this.client, data.recipient));
+ this.recipient = this.client.store.add('users', new User(this.client, data.recipients[0]));
this.lastMessageID = data.last_message_id;
}
From 603e231494cd7d93c5dfb867db8c35ba3eca764e Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sat, 13 Aug 2016 17:04:49 +0100
Subject: [PATCH 051/324] Fix implicit permissions in roles
---
src/structures/ServerChannel.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/structures/ServerChannel.js b/src/structures/ServerChannel.js
index 2e7ee4f93..563058220 100644
--- a/src/structures/ServerChannel.js
+++ b/src/structures/ServerChannel.js
@@ -85,7 +85,7 @@ class ServerChannel extends Channel {
permissions |= overwrite.allowData;
}
- const admin = Boolean(permissions & (Constants.PermissionFlags.MANAGE_ROLES));
+ const admin = Boolean(permissions & (Constants.PermissionFlags.ADMINISTRATOR));
if (admin) {
permissions = Constants.ALL_PERMISSIONS;
}
From 0d44a801f20e778ed1566a2cc61674efba50ebbd Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sat, 13 Aug 2016 17:23:23 +0100
Subject: [PATCH 052/324] add support for Bot auth in REST
---
src/client/rest/RESTManager.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/client/rest/RESTManager.js b/src/client/rest/RESTManager.js
index 9db8403b7..2ebc184e8 100644
--- a/src/client/rest/RESTManager.js
+++ b/src/client/rest/RESTManager.js
@@ -67,7 +67,9 @@ class RESTManager {
}
if (auth) {
- if (this.client.store.token) {
+ if (this.client.store.token && this.client.store.user && this.client.store.user.bot) {
+ apiRequest.set('authorization', `Bot ${this.client.store.token}`);
+ } else if (this.client.store.token) {
apiRequest.set('authorization', this.client.store.token);
} else {
throw Constants.Errors.NO_TOKEN;
@@ -99,6 +101,7 @@ class RESTManager {
reject(err);
} else {
+ console.log(res.headers);
resolve(res ? res.body || {} : {});
}
});
From 0224138dc979544df8aae394a0d6fe8c21df932a Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sat, 13 Aug 2016 22:22:24 +0100
Subject: [PATCH 053/324] crappy ratelimiting it doesnt work but its here ok
---
.eslintrc.js | 1 +
src/client/rest/APIRequest.js | 43 ++++++++++++++
src/client/rest/Bucket.js | 62 ++++++++++++++++++++
src/client/rest/RESTManager.js | 101 ++++++---------------------------
src/util/Constants.js | 1 +
test/random.js | 8 +++
6 files changed, 131 insertions(+), 85 deletions(-)
create mode 100644 src/client/rest/APIRequest.js
create mode 100644 src/client/rest/Bucket.js
diff --git a/.eslintrc.js b/.eslintrc.js
index 2ea4a252b..a721fe464 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -12,5 +12,6 @@ module.exports = {
"guard-for-in": 0,
"no-restricted-syntax": 0,
"no-param-reassign": 0,
+ "consistent-return": 0,
}
};
\ No newline at end of file
diff --git a/src/client/rest/APIRequest.js b/src/client/rest/APIRequest.js
new file mode 100644
index 000000000..462e78fdc
--- /dev/null
+++ b/src/client/rest/APIRequest.js
@@ -0,0 +1,43 @@
+const request = require('superagent');
+const Constants = require('../../util/Constants');
+
+class APIRequest {
+ constructor(rest, method, url, auth, data, file) {
+ this.rest = rest;
+ this.method = method;
+ this.url = url;
+ this.auth = auth;
+ this.data = data;
+ this.file = file;
+ }
+
+ getBucketName() {
+ return `${this.method} ${this.url}`;
+ }
+
+ getAuth() {
+ if (this.rest.client.store.token && this.rest.client.store.user && this.rest.client.store.user.bot) {
+ return `Bot ${this.rest.client.store.token}`;
+ } else if (this.rest.client.store.token) {
+ return this.rest.client.store.token;
+ }
+ throw Constants.Errors.NO_TOKEN;
+ }
+
+ gen() {
+ const apiRequest = request[this.method](this.url);
+ if (this.auth) {
+ apiRequest.set('authorization', this.getAuth());
+ }
+ if (this.data) {
+ apiRequest.send(this.data);
+ }
+ if (this.file) {
+ apiRequest.attach('file', this.file.file, this.file.name);
+ }
+ apiRequest.set('User-Agent', this.rest.userAgentManager.userAgent);
+ return apiRequest;
+ }
+}
+
+module.exports = APIRequest;
diff --git a/src/client/rest/Bucket.js b/src/client/rest/Bucket.js
new file mode 100644
index 000000000..b93ca9607
--- /dev/null
+++ b/src/client/rest/Bucket.js
@@ -0,0 +1,62 @@
+class Bucket {
+ constructor(rest, limit, remainingRequests = 1, resetTime) {
+ this.rest = rest;
+ this.limit = limit;
+ this.remainingRequests = remainingRequests;
+ this.resetTime = resetTime;
+ this.locked = false;
+ this.queue = [];
+ this.nextCheck = null;
+ }
+
+ setCheck(time) {
+ clearTimeout(this.nextCheck);
+ console.log('going to iterate in', time, 'remaining:', this.queue.length);
+ this.nextCheck = setTimeout(() => {
+ this.remainingRequests = this.limit - 1;
+ this.locked = false;
+ this.process();
+ }, time);
+ }
+
+ process() {
+ if (this.locked) {
+ return;
+ }
+
+ this.locked = true;
+
+ if (this.queue.length === 0) {
+ return;
+ }
+
+ if (this.remainingRequests === 0) {
+ return;
+ }
+ console.log('bucket is going to iterate', Math.min(this.remainingRequests, this.queue.length), 'items with max', this.limit, 'and remaining', this.remainingRequests);
+ while (Math.min(this.remainingRequests, this.queue.length) > 0) {
+ const item = this.queue.shift();
+ item.request.gen().end((err, res) => {
+ if (res && res.headers) {
+ this.limit = res.headers['x-ratelimit-limit'];
+ this.resetTime = Number(res.headers['x-ratelimit-reset']) * 1000;
+ this.setCheck((Math.max(500, this.resetTime - Date.now())) + 1000);
+ }
+ if (err) {
+ console.log(err.status, this.remainingRequests);
+ item.reject(err);
+ } else {
+ item.resolve(res && res.body ? res.body : {});
+ }
+ });
+ this.remainingRequests--;
+ }
+ }
+
+ add(method) {
+ this.queue.push(method);
+ this.process();
+ }
+}
+
+module.exports = Bucket;
diff --git a/src/client/rest/RESTManager.js b/src/client/rest/RESTManager.js
index 2ebc184e8..d0275ff44 100644
--- a/src/client/rest/RESTManager.js
+++ b/src/client/rest/RESTManager.js
@@ -2,110 +2,41 @@ const request = require('superagent');
const Constants = require('../../util/Constants');
const UserAgentManager = require('./UserAgentManager');
const RESTMethods = require('./RESTMethods');
+const Bucket = require('./Bucket');
+const APIRequest = require('./APIRequest');
class RESTManager {
constructor(client) {
this.client = client;
- this.queue = [];
+ this.buckets = {};
this.userAgentManager = new UserAgentManager(this);
this.methods = new RESTMethods(this);
this.rateLimitedEndpoints = {};
}
- addRequestToQueue(method, url, auth, data, file, resolve, reject) {
- const endpoint = url.replace(/\/[0-9]+/g, '/:id');
-
- const rateLimitedEndpoint = this.rateLimitedEndpoints[endpoint];
-
- rateLimitedEndpoint.queue = rateLimitedEndpoint.queue || [];
-
- rateLimitedEndpoint.queue.push({
- method,
- url,
- auth,
- data,
- file,
- resolve,
- reject,
+ addToBucket(bucket, apiRequest) {
+ return new Promise((resolve, reject) => {
+ bucket.add({
+ request: apiRequest,
+ resolve,
+ reject,
+ });
});
}
- processQueue(endpoint) {
- const rateLimitedEndpoint = this.rateLimitedEndpoints[endpoint];
-
- // prevent multiple queue processes
- if (!rateLimitedEndpoint.timeout) {
- return;
- }
-
- // lock the queue
- clearTimeout(rateLimitedEndpoint.timeout);
- rateLimitedEndpoint.timeout = null;
-
- for (const item of rateLimitedEndpoint.queue) {
- this.makeRequest(item.method, item.url, item.auth, item.data, item.file)
- .then(item.resolve)
- .catch(item.reject);
- }
-
- rateLimitedEndpoint.queue = [];
- }
-
makeRequest(method, url, auth, data, file) {
/*
file is {file, name}
*/
- const apiRequest = request[method](url);
+ const apiRequest = new APIRequest(this, method, url, auth, data, file);
- const endpoint = url.replace(/\/[0-9]+/g, '/:id');
-
- if (this.rateLimitedEndpoints[endpoint] && this.rateLimitedEndpoints[endpoint].timeout) {
- return new Promise((resolve, reject) => {
- this.addRequestToQueue(method, url, auth, data, file, resolve, reject);
- });
+ if (!this.buckets[apiRequest.getBucketName()]) {
+ console.log('new bucket', apiRequest.getBucketName());
+ this.buckets[apiRequest.getBucketName()] = new Bucket(this, 1, 1);
}
-
- if (auth) {
- if (this.client.store.token && this.client.store.user && this.client.store.user.bot) {
- apiRequest.set('authorization', `Bot ${this.client.store.token}`);
- } else if (this.client.store.token) {
- apiRequest.set('authorization', this.client.store.token);
- } else {
- throw Constants.Errors.NO_TOKEN;
- }
- }
-
- if (data) {
- apiRequest.send(data);
- }
-
- if (file) {
- apiRequest.attach('file', file.file, file.name);
- }
-
- apiRequest.set('User-Agent', this.userAgentManager.userAgent);
-
- return new Promise((resolve, reject) => {
- apiRequest.end((err, res) => {
- if (err) {
- const retry = res.headers['retry-after'] || res.headers['Retry-After'];
- if (retry) {
- this.rateLimitedEndpoints[endpoint] = {};
- this.addRequestToQueue(method, url, auth, data, file, resolve, reject);
- this.rateLimitedEndpoints[endpoint].timeout = setTimeout(() => {
- this.processQueue(endpoint);
- }, retry);
- return;
- }
-
- reject(err);
- } else {
- console.log(res.headers);
- resolve(res ? res.body || {} : {});
- }
- });
- });
+
+ return this.addToBucket(this.buckets[apiRequest.getBucketName()], apiRequest);
}
}
diff --git a/src/util/Constants.js b/src/util/Constants.js
index bfaf84e57..ae8ba951c 100644
--- a/src/util/Constants.js
+++ b/src/util/Constants.js
@@ -165,6 +165,7 @@ const PermissionFlags = exports.PermissionFlags = {
ATTACH_FILES: 1 << 15,
READ_MESSAGE_HISTORY: 1 << 16,
MENTION_EVERYONE: 1 << 17,
+ EXTERNAL_EMOJIS: 1 << 18,
CONNECT: 1 << 20,
SPEAK: 1 << 21,
diff --git a/test/random.js b/test/random.js
index 54516b2be..ba89da291 100644
--- a/test/random.js
+++ b/test/random.js
@@ -141,6 +141,14 @@ client.on('message', message => {
}).catch(console.log);
}
+ if (message.content === 'ratelimittest') {
+ let i = 0;
+ while (i < 20) {
+ message.channel.sendMessage(`Testing my rates, item ${i} of 20`);
+ i++;
+ }
+ }
+
if (message.content === 'makerole') {
message.guild.createRole().then(role => {
message.channel.sendMessage(`Made role ${role.name}`);
From 62856ff57a6bf70c2173386e103fd33b9c825703 Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sun, 14 Aug 2016 18:12:59 +0100
Subject: [PATCH 054/324] start work on documentation generator
---
.eslintrc.js | 1 +
docs/custom/getting_started.js | 8 +++++
docs/custom/index.js | 14 +++++++++
docs/docs.json | 1 +
docs/gen/index.js | 53 ++++++++++++++++++++++++++++++++++
package.json | 7 +++--
6 files changed, 82 insertions(+), 2 deletions(-)
create mode 100644 docs/custom/getting_started.js
create mode 100644 docs/custom/index.js
create mode 100644 docs/docs.json
create mode 100644 docs/gen/index.js
diff --git a/.eslintrc.js b/.eslintrc.js
index a721fe464..d4ac453f8 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -13,5 +13,6 @@ module.exports = {
"no-restricted-syntax": 0,
"no-param-reassign": 0,
"consistent-return": 0,
+ "import/no-extraneous-dependencies": 0,
}
};
\ No newline at end of file
diff --git a/docs/custom/getting_started.js b/docs/custom/getting_started.js
new file mode 100644
index 000000000..fcf5e1e0a
--- /dev/null
+++ b/docs/custom/getting_started.js
@@ -0,0 +1,8 @@
+module.exports = {
+ category: 'General',
+ name: 'Getting Started',
+ data:
+`# Welcome!
+discord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.
+`,
+};
diff --git a/docs/custom/index.js b/docs/custom/index.js
new file mode 100644
index 000000000..15fe93bb7
--- /dev/null
+++ b/docs/custom/index.js
@@ -0,0 +1,14 @@
+const files = [
+ require('./getting_started'),
+];
+
+const categories = {};
+for (const file of files) {
+ file.category = file.category.toLowerCase();
+ if (!categories[file.category]) {
+ categories[file.category] = {};
+ }
+ categories[file.category][file.name] = file.data;
+}
+
+module.exports = categories;
diff --git a/docs/docs.json b/docs/docs.json
new file mode 100644
index 000000000..e79ce6b00
--- /dev/null
+++ b/docs/docs.json
@@ -0,0 +1 @@
+{"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":[{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":3},{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"returns":[{"type":{"names":["ClientUser"]},"description":"[description]"}],"meta":{"lineno":55,"filename":"Client.js","path":"src/client"},"order":2},{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":4},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":5},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":6},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":7},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":8},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":9},{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["client.login(\"token\");\n// or\nclient.login(\"email\", \"password\");"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":42,"filename":"Client.js","path":"src/client"},"order":1},{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":60,"filename":"User.js","path":"src/structures"},"order":10}]}
\ No newline at end of file
diff --git a/docs/gen/index.js b/docs/gen/index.js
new file mode 100644
index 000000000..ddd4ef9c7
--- /dev/null
+++ b/docs/gen/index.js
@@ -0,0 +1,53 @@
+let fs;
+/* eslint no-console:0 no-return-assign:0 */
+let parse;
+
+const customDocs = require('../custom/index');
+
+const GEN_VERSION = 1;
+
+try {
+ fs = require('fs-extra');
+ parse = require('jsdoc-parse');
+} catch (e) {
+ console.log('Error loading fs-extra or jsdoc-parse:');
+ console.log(e);
+ process.exit();
+}
+
+console.log('Starting...');
+
+let json = '';
+
+const stream = parse({
+ src: ['./src/*.js', './src/*/*.js'],
+});
+
+const cwd = (`${process.cwd()}\\`).replace(/\\/g, '/');
+
+function cleanPaths() {
+ for (const item of json) {
+ if (item.meta && item.meta.path) {
+ item.meta.path = item.meta.path.replace(/\\/g, '/').replace(cwd, '');
+ }
+ }
+}
+
+function next() {
+ json = JSON.parse(json);
+ cleanPaths();
+ console.log('parsed inline code');
+ json = {
+ custom: customDocs,
+ json,
+ };
+ fs.writeFile('./docs/docs.json', JSON.stringify(json, null, 0), err => {
+ if (err) {
+ throw err;
+ }
+ console.log('done');
+ });
+}
+
+stream.on('data', chunk => json += chunk.toString('utf-8'));
+stream.on('end', () => next());
diff --git a/package.json b/package.json
index 09f090512..64bc6e480 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,8 @@
"description": "A way to interface with the Discord API",
"main": "./src/index",
"scripts": {
- "test": "node test/random"
+ "test": "node test/random",
+ "docs": "node docs/gen/index.js"
},
"repository": {
"type": "git",
@@ -45,7 +46,9 @@
"grunt-contrib-uglify": "^0.11.0",
"grunt-jscs": "^2.8.0",
"jscs": "^2.11.0",
- "load-grunt-tasks": "^3.3.0"
+ "load-grunt-tasks": "^3.3.0",
+ "fs-extra": "^0.30.0",
+ "jsdoc-parse": "^1.2.7"
},
"optionalDependencies": {
"node-opus": "^0.1.11"
From 1ea53c18acef20c0b93d8b0e85a4e66895597645 Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Sun, 14 Aug 2016 18:13:41 +0100
Subject: [PATCH 055/324] fix meta data for docs
---
docs/docs.json | 2 +-
docs/gen/index.js | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/docs/docs.json b/docs/docs.json
index e79ce6b00..e0cb59039 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -1 +1 @@
-{"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":[{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":3},{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"returns":[{"type":{"names":["ClientUser"]},"description":"[description]"}],"meta":{"lineno":55,"filename":"Client.js","path":"src/client"},"order":2},{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":4},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":5},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":6},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":7},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":8},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":9},{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["client.login(\"token\");\n// or\nclient.login(\"email\", \"password\");"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":42,"filename":"Client.js","path":"src/client"},"order":1},{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":60,"filename":"User.js","path":"src/structures"},"order":10}]}
\ No newline at end of file
+{"meta":{"version":1},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":[{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":3},{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"returns":[{"type":{"names":["ClientUser"]},"description":"[description]"}],"meta":{"lineno":55,"filename":"Client.js","path":"src/client"},"order":2},{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":4},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":5},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":6},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":7},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":8},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":9},{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["client.login(\"token\");\n// or\nclient.login(\"email\", \"password\");"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":42,"filename":"Client.js","path":"src/client"},"order":1},{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":60,"filename":"User.js","path":"src/structures"},"order":10}]}
\ No newline at end of file
diff --git a/docs/gen/index.js b/docs/gen/index.js
index ddd4ef9c7..cb688b22e 100644
--- a/docs/gen/index.js
+++ b/docs/gen/index.js
@@ -38,6 +38,9 @@ function next() {
cleanPaths();
console.log('parsed inline code');
json = {
+ meta: {
+ version: GEN_VERSION,
+ },
custom: customDocs,
json,
};
From eba3bd029169fa151e4fbea9caa9b43c882271ef Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Mon, 15 Aug 2016 22:07:01 +0100
Subject: [PATCH 056/324] Update documentation generator
---
docs/docs.json | 2 +-
docs/gen/index.js | 25 ++++++++++++++++++++++++-
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/docs/docs.json b/docs/docs.json
index e0cb59039..a347d8e0b 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -1 +1 @@
-{"meta":{"version":1},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":[{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":3},{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"returns":[{"type":{"names":["ClientUser"]},"description":"[description]"}],"meta":{"lineno":55,"filename":"Client.js","path":"src/client"},"order":2},{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":4},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":5},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":6},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":7},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":8},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":9},{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["client.login(\"token\");\n// or\nclient.login(\"email\", \"password\");"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":42,"filename":"Client.js","path":"src/client"},"order":1},{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":60,"filename":"User.js","path":"src/structures"},"order":10}]}
\ No newline at end of file
+{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["client.login(\"token\");\n// or\nclient.login(\"email\", \"password\");"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":42,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"returns":[{"type":{"names":["ClientUser"]},"description":"[description]"}],"meta":{"lineno":55,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"User":{"meta":{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":3},"functions":[{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":60,"filename":"User.js","path":"src/structures"},"order":10}],"properties":[{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":4},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":5},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":6},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":7},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":8},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":9}],"events":[]}}}}
\ No newline at end of file
diff --git a/docs/gen/index.js b/docs/gen/index.js
index cb688b22e..a12185e5a 100644
--- a/docs/gen/index.js
+++ b/docs/gen/index.js
@@ -4,7 +4,7 @@ let parse;
const customDocs = require('../custom/index');
-const GEN_VERSION = 1;
+const GEN_VERSION = 2;
try {
fs = require('fs-extra');
@@ -33,10 +33,33 @@ function cleanPaths() {
}
}
+function clean() {
+ const cleaned = {
+ classes: {},
+ };
+ for (const item of json) {
+ if (item.kind === 'class') {
+ cleaned.classes[item.longname] = {
+ meta: item,
+ functions: [],
+ properties: [],
+ events: [],
+ };
+ } else if (item.kind === 'member') {
+ cleaned.classes[item.memberof].properties.push(item);
+ } else if (item.kind === 'function' && item.memberof) {
+ cleaned.classes[item.memberof].functions.push(item);
+ }
+ }
+ json = cleaned;
+}
+
function next() {
json = JSON.parse(json);
cleanPaths();
console.log('parsed inline code');
+ console.log(json);
+ clean();
json = {
meta: {
version: GEN_VERSION,
From 4fff20d66e538951e4716be8c67e43297c432cab Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Tue, 16 Aug 2016 23:22:52 +0100
Subject: [PATCH 057/324] update some docs
---
docs/docs.json | 2 +-
src/client/Client.js | 2 +-
src/structures/Message.js | 3 +++
src/structures/TextChannel.js | 3 +++
src/structures/VoiceChannel.js | 3 +++
5 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/docs/docs.json b/docs/docs.json
index a347d8e0b..763d02951 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -1 +1 @@
-{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["client.login(\"token\");\n// or\nclient.login(\"email\", \"password\");"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":42,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"returns":[{"type":{"names":["ClientUser"]},"description":"[description]"}],"meta":{"lineno":55,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"User":{"meta":{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":3},"functions":[{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":60,"filename":"User.js","path":"src/structures"},"order":10}],"properties":[{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":4},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":5},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":6},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":7},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":8},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":9}],"events":[]}}}}
\ No newline at end of file
+{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["client.login(\"token\");\n// or\nclient.login(\"email\", \"password\");"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":42,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"type":{"names":["ClientUser"]},"meta":{"lineno":55,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"Message":{"meta":{"id":"Message","longname":"Message","name":"Message","scope":"global","kind":"class","description":"Represents a Message on Discord","meta":{"lineno":4,"filename":"Message.js","path":"src/structures"},"order":3},"functions":[],"properties":[],"events":[]},"TextChannel":{"meta":{"id":"TextChannel","longname":"TextChannel","name":"TextChannel","scope":"global","kind":"class","description":"Represents a Server Text Channel on Discord.","meta":{"lineno":8,"filename":"TextChannel.js","path":"src/structures"},"order":4},"functions":[],"properties":[],"events":[]},"User":{"meta":{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":5},"functions":[{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":60,"filename":"User.js","path":"src/structures"},"order":12}],"properties":[{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":6},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":7},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":8},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":9},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":10},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":11}],"events":[]},"VoiceChannel":{"meta":{"id":"VoiceChannel","longname":"VoiceChannel","name":"VoiceChannel","scope":"global","kind":"class","description":"Represents a Server Voice Channel on Discord.","meta":{"lineno":7,"filename":"VoiceChannel.js","path":"src/structures"},"order":13},"functions":[],"properties":[],"events":[]}}}}
\ No newline at end of file
diff --git a/src/client/Client.js b/src/client/Client.js
index 52ed353a2..f61596d12 100644
--- a/src/client/Client.js
+++ b/src/client/Client.js
@@ -50,7 +50,7 @@ class Client extends EventEmitter {
/**
* The User of the logged in Client, only available after `READY` has been fired.
- * @return {ClientUser} [description]
+ * @type {ClientUser}
*/
get user() {
return this.store.user;
diff --git a/src/structures/Message.js b/src/structures/Message.js
index b565737ce..c225fe697 100644
--- a/src/structures/Message.js
+++ b/src/structures/Message.js
@@ -1,3 +1,6 @@
+/**
+ * Represents a Message on Discord
+ */
class Message {
constructor(channel, data, client) {
this.channel = channel;
diff --git a/src/structures/TextChannel.js b/src/structures/TextChannel.js
index c87b27ed4..6775e2989 100644
--- a/src/structures/TextChannel.js
+++ b/src/structures/TextChannel.js
@@ -2,6 +2,9 @@ const ServerChannel = require('./ServerChannel');
const TextChannelDataStore = require('./datastore/TextChannelDataStore');
const TextBasedChannel = require('./interface/TextBasedChannel');
+/**
+ * Represents a Server Text Channel on Discord.
+ */
class TextChannel extends ServerChannel {
constructor(guild, data) {
diff --git a/src/structures/VoiceChannel.js b/src/structures/VoiceChannel.js
index 4a4f6c253..8e01ebfc1 100644
--- a/src/structures/VoiceChannel.js
+++ b/src/structures/VoiceChannel.js
@@ -1,6 +1,9 @@
const ServerChannel = require('./ServerChannel');
const VoiceChannelDataStore = require('./datastore/VoiceChannelDataStore');
+/**
+ * Represents a Server Voice Channel on Discord.
+ */
class VoiceChannel extends ServerChannel {
constructor(guild, data) {
super(guild, data);
From 13db0db298576df7c2a9bd804c018e94bf1e09b6 Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Wed, 17 Aug 2016 15:50:27 +0100
Subject: [PATCH 058/324] updated client docs
---
docs/docs.json | 2 +-
src/client/Client.js | 11 ++++++++---
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/docs/docs.json b/docs/docs.json
index 763d02951..1231865bf 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -1 +1 @@
-{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["client.login(\"token\");\n// or\nclient.login(\"email\", \"password\");"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":42,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"type":{"names":["ClientUser"]},"meta":{"lineno":55,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"Message":{"meta":{"id":"Message","longname":"Message","name":"Message","scope":"global","kind":"class","description":"Represents a Message on Discord","meta":{"lineno":4,"filename":"Message.js","path":"src/structures"},"order":3},"functions":[],"properties":[],"events":[]},"TextChannel":{"meta":{"id":"TextChannel","longname":"TextChannel","name":"TextChannel","scope":"global","kind":"class","description":"Represents a Server Text Channel on Discord.","meta":{"lineno":8,"filename":"TextChannel.js","path":"src/structures"},"order":4},"functions":[],"properties":[],"events":[]},"User":{"meta":{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":5},"functions":[{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":60,"filename":"User.js","path":"src/structures"},"order":12}],"properties":[{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":6},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":7},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":8},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":9},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":10},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":11}],"events":[]},"VoiceChannel":{"meta":{"id":"VoiceChannel","longname":"VoiceChannel","name":"VoiceChannel","scope":"global","kind":"class","description":"Represents a Server Voice Channel on Discord.","meta":{"lineno":7,"filename":"VoiceChannel.js","path":"src/structures"},"order":13},"functions":[],"properties":[],"events":[]}}}}
\ No newline at end of file
+{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["// log the client in using a token\nconst token = 'my token';\nclient.login(token);","// log the client in using email and password\nconst email = 'user@email.com';\nconst password = 'supersecret123';\nclient.login(email, password);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":47,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"type":{"names":["ClientUser"]},"meta":{"lineno":60,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"Message":{"meta":{"id":"Message","longname":"Message","name":"Message","scope":"global","kind":"class","description":"Represents a Message on Discord","meta":{"lineno":4,"filename":"Message.js","path":"src/structures"},"order":3},"functions":[],"properties":[],"events":[]},"TextChannel":{"meta":{"id":"TextChannel","longname":"TextChannel","name":"TextChannel","scope":"global","kind":"class","description":"Represents a Server Text Channel on Discord.","meta":{"lineno":8,"filename":"TextChannel.js","path":"src/structures"},"order":4},"functions":[],"properties":[],"events":[]},"User":{"meta":{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":5},"functions":[{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":60,"filename":"User.js","path":"src/structures"},"order":12}],"properties":[{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":6},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":7},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":8},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":9},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":10},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":11}],"events":[]},"VoiceChannel":{"meta":{"id":"VoiceChannel","longname":"VoiceChannel","name":"VoiceChannel","scope":"global","kind":"class","description":"Represents a Server Voice Channel on Discord.","meta":{"lineno":7,"filename":"VoiceChannel.js","path":"src/structures"},"order":13},"functions":[],"properties":[],"events":[]}}}}
\ No newline at end of file
diff --git a/src/client/Client.js b/src/client/Client.js
index f61596d12..111cc1314 100644
--- a/src/client/Client.js
+++ b/src/client/Client.js
@@ -35,9 +35,14 @@ class Client extends EventEmitter {
* @param {string} [password] The password for the account, only needed if an email was provided.
* @return {Promise}
* @example
- * client.login("token");
- * // or
- * client.login("email", "password");
+ * // log the client in using a token
+ * const token = 'my token';
+ * client.login(token);
+ * @example
+ * // log the client in using email and password
+ * const email = 'user@email.com';
+ * const password = 'supersecret123';
+ * client.login(email, password);
*/
login(email, password) {
if (password) {
From e7e6355cfe3ff211907fe7925442f4c952495a4d Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Wed, 17 Aug 2016 16:28:31 +0100
Subject: [PATCH 059/324] work on guild docs
---
docs/docs.json | 2 +-
src/structures/Guild.js | 109 ++++++++++++++++++++++++++++++++++++++++
src/structures/User.js | 10 ++++
3 files changed, 120 insertions(+), 1 deletion(-)
diff --git a/docs/docs.json b/docs/docs.json
index 1231865bf..cf5db4f05 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -1 +1 @@
-{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["// log the client in using a token\nconst token = 'my token';\nclient.login(token);","// log the client in using email and password\nconst email = 'user@email.com';\nconst password = 'supersecret123';\nclient.login(email, password);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":47,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"type":{"names":["ClientUser"]},"meta":{"lineno":60,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"Message":{"meta":{"id":"Message","longname":"Message","name":"Message","scope":"global","kind":"class","description":"Represents a Message on Discord","meta":{"lineno":4,"filename":"Message.js","path":"src/structures"},"order":3},"functions":[],"properties":[],"events":[]},"TextChannel":{"meta":{"id":"TextChannel","longname":"TextChannel","name":"TextChannel","scope":"global","kind":"class","description":"Represents a Server Text Channel on Discord.","meta":{"lineno":8,"filename":"TextChannel.js","path":"src/structures"},"order":4},"functions":[],"properties":[],"events":[]},"User":{"meta":{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":5},"functions":[{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":60,"filename":"User.js","path":"src/structures"},"order":12}],"properties":[{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":6},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":7},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":8},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":9},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":10},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":11}],"events":[]},"VoiceChannel":{"meta":{"id":"VoiceChannel","longname":"VoiceChannel","name":"VoiceChannel","scope":"global","kind":"class","description":"Represents a Server Voice Channel on Discord.","meta":{"lineno":7,"filename":"VoiceChannel.js","path":"src/structures"},"order":13},"functions":[],"properties":[],"events":[]}}}}
\ No newline at end of file
+{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["// log the client in using a token\nconst token = 'my token';\nclient.login(token);","// log the client in using email and password\nconst email = 'user@email.com';\nconst password = 'supersecret123';\nclient.login(email, password);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":47,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"type":{"names":["ClientUser"]},"meta":{"lineno":60,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"Guild":{"meta":{"id":"Guild","longname":"Guild","name":"Guild","scope":"global","kind":"class","meta":{"lineno":22,"filename":"Guild.js","path":"src/structures"},"order":3},"functions":[{"id":"Guild#toString","longname":"Guild#toString","name":"toString","scope":"instance","kind":"function","description":"When concatenated with a String, this automatically concatenates the Guild's name instead of the Guild object.","memberof":"Guild","params":[],"examples":["// logs: Hello from My Guild!\nconsole.log(`Hello from ${guild}!`);","// logs: Hello from My Guild!\nconsole.log(`Hello from ' + guild + '!');"],"returns":[{"type":{"names":["String"]}}],"meta":{"lineno":98,"filename":"Guild.js","path":"src/structures"},"order":9},{"id":"Guild#kick","longname":"Guild#kick","name":"kick","scope":"instance","kind":"function","description":"Tries to kick a member from the guild.","memberof":"Guild","params":[{"type":{"names":["GuildMemberResolvable"]},"description":"the member to kick","name":"member"}],"examples":["// kicks a member from a guild:\nguild.kick(message.author)\n .then(member => console.log(`Kicked ${member}`))\n .catch(error => console.log(error));"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":112,"filename":"Guild.js","path":"src/structures"},"order":10},{"id":"Guild#member","longname":"Guild#member","name":"member","scope":"instance","kind":"function","description":"Returns the GuildMember form of a User object, if the User is present in the guild.","memberof":"Guild","params":[{"type":{"names":["UserResolvable"]},"description":"the user that you want to obtain the GuildMember of.","name":"user"}],"examples":["// get the guild member of a user\nconst member = guild.member(message.author);"],"returns":[{"type":{"names":["GuildMember","null"]}}],"meta":{"lineno":124,"filename":"Guild.js","path":"src/structures"},"order":11}],"properties":[{"id":"Guild#client","longname":"Guild#client","name":"client","scope":"instance","kind":"member","description":"The Client that created the instance of the the Guild.","memberof":"Guild","type":{"names":["Client"]},"meta":{"lineno":32,"filename":"Guild.js","path":"src/structures"},"order":5},{"id":"Guild#store","longname":"Guild#store","name":"store","scope":"instance","kind":"member","description":"The data store of the Guild.","memberof":"Guild","type":{"names":["GuildDataStore"]},"meta":{"lineno":38,"filename":"Guild.js","path":"src/structures"},"order":6},{"id":"Guild#available","longname":"Guild#available","name":"available","scope":"instance","kind":"member","description":"Whether the Guild is available to access. If it is not available, it indicates a server outage.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":49,"filename":"Guild.js","path":"src/structures"},"order":7},{"id":"Guild#id","longname":"Guild#id","name":"id","scope":"instance","kind":"member","description":"The Unique ID of the Guild, useful for comparisons.","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":54,"filename":"Guild.js","path":"src/structures"},"order":8},{"id":"Guild#splash","longname":"Guild#splash","name":"splash","scope":"instance","kind":"member","description":"The hash of the guild splash image, or null if no splash (VIP only)","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":163,"filename":"Guild.js","path":"src/structures"},"order":12},{"id":"Guild#region","longname":"Guild#region","name":"region","scope":"instance","kind":"member","description":"The region the guild is located in","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":168,"filename":"Guild.js","path":"src/structures"},"order":13},{"id":"Guild#name","longname":"Guild#name","name":"name","scope":"instance","kind":"member","description":"The name of the guild","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":173,"filename":"Guild.js","path":"src/structures"},"order":14},{"id":"Guild#memberCount","longname":"Guild#memberCount","name":"memberCount","scope":"instance","kind":"member","description":"The amount of initial members in the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":178,"filename":"Guild.js","path":"src/structures"},"order":15},{"id":"Guild#large","longname":"Guild#large","name":"large","scope":"instance","kind":"member","description":"Whether the guild is \"large\" (has more than 250 members)","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":183,"filename":"Guild.js","path":"src/structures"},"order":16},{"id":"Guild#joinDate","longname":"Guild#joinDate","name":"joinDate","scope":"instance","kind":"member","description":"The date at which the logged-in client joined the guild.","memberof":"Guild","type":{"names":["Date"]},"meta":{"lineno":188,"filename":"Guild.js","path":"src/structures"},"order":17},{"id":"Guild#icon","longname":"Guild#icon","name":"icon","scope":"instance","kind":"member","description":"The hash of the guild icon, or null if there is no icon.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":193,"filename":"Guild.js","path":"src/structures"},"order":18},{"id":"Guild#features","longname":"Guild#features","name":"features","scope":"instance","kind":"member","description":"An array of guild features.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":198,"filename":"Guild.js","path":"src/structures"},"order":19},{"id":"Guild#emojis","longname":"Guild#emojis","name":"emojis","scope":"instance","kind":"member","description":"An array of guild emojis.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":203,"filename":"Guild.js","path":"src/structures"},"order":20},{"id":"Guild#afkTimeout","longname":"Guild#afkTimeout","name":"afkTimeout","scope":"instance","kind":"member","description":"The time in seconds before a user is counted as \"away from keyboard\".","memberof":"Guild","type":{"names":["Number"]},"nullable":true,"meta":{"lineno":208,"filename":"Guild.js","path":"src/structures"},"order":21},{"id":"Guild#afkChannelID","longname":"Guild#afkChannelID","name":"afkChannelID","scope":"instance","kind":"member","description":"The ID of the voice channel where AFK members are moved.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":213,"filename":"Guild.js","path":"src/structures"},"order":22},{"id":"Guild#embedEnabled","longname":"Guild#embedEnabled","name":"embedEnabled","scope":"instance","kind":"member","description":"Whether embedded images are enabled on this guild.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":218,"filename":"Guild.js","path":"src/structures"},"order":23},{"id":"Guild#verificationLevel","longname":"Guild#verificationLevel","name":"verificationLevel","scope":"instance","kind":"member","description":"The verification level of the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":223,"filename":"Guild.js","path":"src/structures"},"order":24},{"id":"Guild#owner","longname":"Guild#owner","name":"owner","scope":"instance","kind":"member","description":"The owner of the guild","memberof":"Guild","type":{"names":["User"]},"meta":{"lineno":237,"filename":"Guild.js","path":"src/structures"},"order":25},{"id":"Guild#embedChannel","longname":"Guild#embedChannel","name":"embedChannel","scope":"instance","kind":"member","description":"The embed channel of the Guild.","memberof":"Guild","type":{"names":["GuildChannel"]},"meta":{"lineno":250,"filename":"Guild.js","path":"src/structures"},"order":26}],"events":[]},"Message":{"meta":{"id":"Message","longname":"Message","name":"Message","scope":"global","kind":"class","description":"Represents a Message on Discord","meta":{"lineno":4,"filename":"Message.js","path":"src/structures"},"order":27},"functions":[],"properties":[],"events":[]},"TextChannel":{"meta":{"id":"TextChannel","longname":"TextChannel","name":"TextChannel","scope":"global","kind":"class","description":"Represents a Server Text Channel on Discord.","meta":{"lineno":8,"filename":"TextChannel.js","path":"src/structures"},"order":28},"functions":[],"properties":[],"events":[]},"User":{"meta":{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":29},"functions":[{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":64,"filename":"User.js","path":"src/structures"},"order":37},{"id":"User#equals","longname":"User#equals","name":"equals","scope":"instance","kind":"function","description":"Checks if the user is equal to another. It compares username, ID, discriminator, status and the game being played.\nIt is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties.","memberof":"User","params":[{"type":{"names":["User"]},"description":"the user to compare","name":"user"}],"returns":[{"description":"Boolean"}],"meta":{"lineno":74,"filename":"User.js","path":"src/structures"},"order":38}],"properties":[{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":30},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":31},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":32},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":33},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":34},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":35},{"id":"User#game","longname":"User#game","name":"game","scope":"instance","kind":"member","description":"The game that the user is playing, `null` if they aren't playing a game.","memberof":"User","type":{"names":["String"]},"meta":{"lineno":53,"filename":"User.js","path":"src/structures"},"order":36}],"events":[]},"VoiceChannel":{"meta":{"id":"VoiceChannel","longname":"VoiceChannel","name":"VoiceChannel","scope":"global","kind":"class","description":"Represents a Server Voice Channel on Discord.","meta":{"lineno":7,"filename":"VoiceChannel.js","path":"src/structures"},"order":39},"functions":[],"properties":[],"events":[]}}}}
\ No newline at end of file
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index 596d9bf7a..8707dc94a 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -19,9 +19,22 @@ function arraysEqual(a, b) {
return b.length === 0;
}
+/**
+ * Represents a Guild (or a Server) on Discord.
+ * @class Guild
+ */
class Guild {
constructor(client, data) {
+ /**
+ * The Client that created the instance of the the Guild.
+ * @type {Client}
+ */
this.client = client;
+
+ /**
+ * The data store of the Guild.
+ * @type {GuildDataStore}
+ */
this.store = new GuildDataStore();
if (!data) {
@@ -29,7 +42,15 @@ class Guild {
}
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}
+ */
this.id = data.id;
} else {
this.available = true;
@@ -64,14 +85,42 @@ class Guild {
this.store.remove('members', guildMember);
}
+ /**
+ * 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;
}
+ /**
+ * Tries to kick a member from the guild.
+ * @param {GuildMemberResolvable} member the member to kick
+ * @returns {Promise}
+ * @example
+ * // kicks a member from a guild:
+ * guild.kick(message.author)
+ * .then(member => console.log(`Kicked ${member}`))
+ * .catch(error => console.log(error));
+ */
kick(member) {
return this.member(member).kick();
}
+ /**
+ * 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|null}
+ * @example
+ * // get the guild member of a user
+ * const member = guild.member(message.author);
+ */
member(user) {
return this.client.resolver.resolveGuildMember(this, user);
}
@@ -107,18 +156,70 @@ class Guild {
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 amount of initial members in the guild.
+ * @type {Number}
+ */
this.memberCount = data.member_count;
+ /**
+ * Whether the guild is "large" (has more than 250 members)
+ * @type {Boolean}
+ */
this.large = data.large;
+ /**
+ * The date at which the logged-in client joined the guild.
+ * @type {Date}
+ */
this.joinDate = new Date(data.joined_at);
+ /**
+ * 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 {Array}
+ */
this.features = data.features;
+ /**
+ * An array of guild emojis.
+ * @type {Array}
+ */
this.emojis = data.emojis;
+ /**
+ * 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 || [];
@@ -129,6 +230,10 @@ class Guild {
}
}
+ /**
+ * The owner of the guild
+ * @type {User}
+ */
this.owner = this.store.get('members', data.owner_id);
if (data.channels) {
@@ -138,6 +243,10 @@ class Guild {
}
}
+ /**
+ * The embed channel of the Guild.
+ * @type {GuildChannel}
+ */
this.embedChannel = this.store.get('channels', data.embed_channel_id);
if (data.roles) {
diff --git a/src/structures/User.js b/src/structures/User.js
index 823c8597d..1d8c4a497 100644
--- a/src/structures/User.js
+++ b/src/structures/User.js
@@ -46,6 +46,10 @@ 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}
+ */
this.game = data.game || this.game;
}
@@ -61,6 +65,12 @@ class User {
return this.client.rest.methods.deleteChannel(this);
}
+ /**
+ * Checks if the user is equal to another. It compares username, ID, discriminator, status and the game being played.
+ * It is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties.
+ * @param {User} user the user to compare
+ * @returns Boolean
+ */
equals(user) {
let base = (
this.username === user.username &&
From e7ef73ffdc4f4cb8a32cf3b0213029b2c5914730 Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Wed, 17 Aug 2016 16:33:53 +0100
Subject: [PATCH 060/324] work on guild docs
---
docs/docs.json | 2 +-
src/structures/Guild.js | 8 +++++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/docs/docs.json b/docs/docs.json
index cf5db4f05..5197521eb 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -1 +1 @@
-{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["// log the client in using a token\nconst token = 'my token';\nclient.login(token);","// log the client in using email and password\nconst email = 'user@email.com';\nconst password = 'supersecret123';\nclient.login(email, password);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":47,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"type":{"names":["ClientUser"]},"meta":{"lineno":60,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"Guild":{"meta":{"id":"Guild","longname":"Guild","name":"Guild","scope":"global","kind":"class","meta":{"lineno":22,"filename":"Guild.js","path":"src/structures"},"order":3},"functions":[{"id":"Guild#toString","longname":"Guild#toString","name":"toString","scope":"instance","kind":"function","description":"When concatenated with a String, this automatically concatenates the Guild's name instead of the Guild object.","memberof":"Guild","params":[],"examples":["// logs: Hello from My Guild!\nconsole.log(`Hello from ${guild}!`);","// logs: Hello from My Guild!\nconsole.log(`Hello from ' + guild + '!');"],"returns":[{"type":{"names":["String"]}}],"meta":{"lineno":98,"filename":"Guild.js","path":"src/structures"},"order":9},{"id":"Guild#kick","longname":"Guild#kick","name":"kick","scope":"instance","kind":"function","description":"Tries to kick a member from the guild.","memberof":"Guild","params":[{"type":{"names":["GuildMemberResolvable"]},"description":"the member to kick","name":"member"}],"examples":["// kicks a member from a guild:\nguild.kick(message.author)\n .then(member => console.log(`Kicked ${member}`))\n .catch(error => console.log(error));"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":112,"filename":"Guild.js","path":"src/structures"},"order":10},{"id":"Guild#member","longname":"Guild#member","name":"member","scope":"instance","kind":"function","description":"Returns the GuildMember form of a User object, if the User is present in the guild.","memberof":"Guild","params":[{"type":{"names":["UserResolvable"]},"description":"the user that you want to obtain the GuildMember of.","name":"user"}],"examples":["// get the guild member of a user\nconst member = guild.member(message.author);"],"returns":[{"type":{"names":["GuildMember","null"]}}],"meta":{"lineno":124,"filename":"Guild.js","path":"src/structures"},"order":11}],"properties":[{"id":"Guild#client","longname":"Guild#client","name":"client","scope":"instance","kind":"member","description":"The Client that created the instance of the the Guild.","memberof":"Guild","type":{"names":["Client"]},"meta":{"lineno":32,"filename":"Guild.js","path":"src/structures"},"order":5},{"id":"Guild#store","longname":"Guild#store","name":"store","scope":"instance","kind":"member","description":"The data store of the Guild.","memberof":"Guild","type":{"names":["GuildDataStore"]},"meta":{"lineno":38,"filename":"Guild.js","path":"src/structures"},"order":6},{"id":"Guild#available","longname":"Guild#available","name":"available","scope":"instance","kind":"member","description":"Whether the Guild is available to access. If it is not available, it indicates a server outage.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":49,"filename":"Guild.js","path":"src/structures"},"order":7},{"id":"Guild#id","longname":"Guild#id","name":"id","scope":"instance","kind":"member","description":"The Unique ID of the Guild, useful for comparisons.","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":54,"filename":"Guild.js","path":"src/structures"},"order":8},{"id":"Guild#splash","longname":"Guild#splash","name":"splash","scope":"instance","kind":"member","description":"The hash of the guild splash image, or null if no splash (VIP only)","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":163,"filename":"Guild.js","path":"src/structures"},"order":12},{"id":"Guild#region","longname":"Guild#region","name":"region","scope":"instance","kind":"member","description":"The region the guild is located in","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":168,"filename":"Guild.js","path":"src/structures"},"order":13},{"id":"Guild#name","longname":"Guild#name","name":"name","scope":"instance","kind":"member","description":"The name of the guild","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":173,"filename":"Guild.js","path":"src/structures"},"order":14},{"id":"Guild#memberCount","longname":"Guild#memberCount","name":"memberCount","scope":"instance","kind":"member","description":"The amount of initial members in the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":178,"filename":"Guild.js","path":"src/structures"},"order":15},{"id":"Guild#large","longname":"Guild#large","name":"large","scope":"instance","kind":"member","description":"Whether the guild is \"large\" (has more than 250 members)","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":183,"filename":"Guild.js","path":"src/structures"},"order":16},{"id":"Guild#joinDate","longname":"Guild#joinDate","name":"joinDate","scope":"instance","kind":"member","description":"The date at which the logged-in client joined the guild.","memberof":"Guild","type":{"names":["Date"]},"meta":{"lineno":188,"filename":"Guild.js","path":"src/structures"},"order":17},{"id":"Guild#icon","longname":"Guild#icon","name":"icon","scope":"instance","kind":"member","description":"The hash of the guild icon, or null if there is no icon.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":193,"filename":"Guild.js","path":"src/structures"},"order":18},{"id":"Guild#features","longname":"Guild#features","name":"features","scope":"instance","kind":"member","description":"An array of guild features.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":198,"filename":"Guild.js","path":"src/structures"},"order":19},{"id":"Guild#emojis","longname":"Guild#emojis","name":"emojis","scope":"instance","kind":"member","description":"An array of guild emojis.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":203,"filename":"Guild.js","path":"src/structures"},"order":20},{"id":"Guild#afkTimeout","longname":"Guild#afkTimeout","name":"afkTimeout","scope":"instance","kind":"member","description":"The time in seconds before a user is counted as \"away from keyboard\".","memberof":"Guild","type":{"names":["Number"]},"nullable":true,"meta":{"lineno":208,"filename":"Guild.js","path":"src/structures"},"order":21},{"id":"Guild#afkChannelID","longname":"Guild#afkChannelID","name":"afkChannelID","scope":"instance","kind":"member","description":"The ID of the voice channel where AFK members are moved.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":213,"filename":"Guild.js","path":"src/structures"},"order":22},{"id":"Guild#embedEnabled","longname":"Guild#embedEnabled","name":"embedEnabled","scope":"instance","kind":"member","description":"Whether embedded images are enabled on this guild.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":218,"filename":"Guild.js","path":"src/structures"},"order":23},{"id":"Guild#verificationLevel","longname":"Guild#verificationLevel","name":"verificationLevel","scope":"instance","kind":"member","description":"The verification level of the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":223,"filename":"Guild.js","path":"src/structures"},"order":24},{"id":"Guild#owner","longname":"Guild#owner","name":"owner","scope":"instance","kind":"member","description":"The owner of the guild","memberof":"Guild","type":{"names":["User"]},"meta":{"lineno":237,"filename":"Guild.js","path":"src/structures"},"order":25},{"id":"Guild#embedChannel","longname":"Guild#embedChannel","name":"embedChannel","scope":"instance","kind":"member","description":"The embed channel of the Guild.","memberof":"Guild","type":{"names":["GuildChannel"]},"meta":{"lineno":250,"filename":"Guild.js","path":"src/structures"},"order":26}],"events":[]},"Message":{"meta":{"id":"Message","longname":"Message","name":"Message","scope":"global","kind":"class","description":"Represents a Message on Discord","meta":{"lineno":4,"filename":"Message.js","path":"src/structures"},"order":27},"functions":[],"properties":[],"events":[]},"TextChannel":{"meta":{"id":"TextChannel","longname":"TextChannel","name":"TextChannel","scope":"global","kind":"class","description":"Represents a Server Text Channel on Discord.","meta":{"lineno":8,"filename":"TextChannel.js","path":"src/structures"},"order":28},"functions":[],"properties":[],"events":[]},"User":{"meta":{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":29},"functions":[{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":64,"filename":"User.js","path":"src/structures"},"order":37},{"id":"User#equals","longname":"User#equals","name":"equals","scope":"instance","kind":"function","description":"Checks if the user is equal to another. It compares username, ID, discriminator, status and the game being played.\nIt is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties.","memberof":"User","params":[{"type":{"names":["User"]},"description":"the user to compare","name":"user"}],"returns":[{"description":"Boolean"}],"meta":{"lineno":74,"filename":"User.js","path":"src/structures"},"order":38}],"properties":[{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":30},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":31},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":32},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":33},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":34},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":35},{"id":"User#game","longname":"User#game","name":"game","scope":"instance","kind":"member","description":"The game that the user is playing, `null` if they aren't playing a game.","memberof":"User","type":{"names":["String"]},"meta":{"lineno":53,"filename":"User.js","path":"src/structures"},"order":36}],"events":[]},"VoiceChannel":{"meta":{"id":"VoiceChannel","longname":"VoiceChannel","name":"VoiceChannel","scope":"global","kind":"class","description":"Represents a Server Voice Channel on Discord.","meta":{"lineno":7,"filename":"VoiceChannel.js","path":"src/structures"},"order":39},"functions":[],"properties":[],"events":[]}}}}
\ No newline at end of file
+{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["// log the client in using a token\nconst token = 'my token';\nclient.login(token);","// log the client in using email and password\nconst email = 'user@email.com';\nconst password = 'supersecret123';\nclient.login(email, password);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":47,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"type":{"names":["ClientUser"]},"meta":{"lineno":60,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"Guild":{"meta":{"id":"Guild","longname":"Guild","name":"Guild","scope":"global","kind":"class","description":"Represents a Guild (or a Server) on Discord.","meta":{"lineno":25,"filename":"Guild.js","path":"src/structures"},"order":3},"functions":[{"id":"Guild#toString","longname":"Guild#toString","name":"toString","scope":"instance","kind":"function","description":"When concatenated with a String, this automatically concatenates the Guild's name instead of the Guild object.","memberof":"Guild","params":[],"examples":["// logs: Hello from My Guild!\nconsole.log(`Hello from ${guild}!`);","// logs: Hello from My Guild!\nconsole.log(`Hello from ' + guild + '!');"],"returns":[{"type":{"names":["String"]}}],"meta":{"lineno":97,"filename":"Guild.js","path":"src/structures"},"order":8},{"id":"Guild#kick","longname":"Guild#kick","name":"kick","scope":"instance","kind":"function","description":"Tries to kick a member from the guild.","memberof":"Guild","params":[{"type":{"names":["GuildMemberResolvable"]},"description":"the member to kick","name":"member"}],"examples":["// kicks a member from a guild:\nguild.kick(message.author)\n .then(member => console.log(`Kicked ${member}`))\n .catch(error => console.log(error));"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":111,"filename":"Guild.js","path":"src/structures"},"order":9},{"id":"Guild#member","longname":"Guild#member","name":"member","scope":"instance","kind":"function","description":"Returns the GuildMember form of a User object, if the User is present in the guild.","memberof":"Guild","params":[{"type":{"names":["UserResolvable"]},"description":"the user that you want to obtain the GuildMember of.","name":"user"}],"examples":["// get the guild member of a user\nconst member = guild.member(message.author);"],"returns":[{"type":{"names":["GuildMember","null"]}}],"meta":{"lineno":123,"filename":"Guild.js","path":"src/structures"},"order":10},{"id":"Guild#equals","longname":"Guild#equals","name":"equals","scope":"instance","kind":"function","description":"Whether this Guild equals another Guild. It compares all properties, so for most operations\nit is advisable to just compare `guild.id === guild2.id` as it is much faster and is often\nwhat most users need.","memberof":"Guild","params":[{"type":{"names":["Guild"]},"description":"the guild to compare","name":"guild"}],"returns":[{"type":{"names":["Boolean"]}}],"meta":{"lineno":134,"filename":"Guild.js","path":"src/structures"},"order":11}],"properties":[{"id":"Guild#client","longname":"Guild#client","name":"client","scope":"instance","kind":"member","description":"The Client that created the instance of the the Guild.","memberof":"Guild","type":{"names":["Client"]},"meta":{"lineno":31,"filename":"Guild.js","path":"src/structures"},"order":4},{"id":"Guild#store","longname":"Guild#store","name":"store","scope":"instance","kind":"member","description":"The data store of the Guild.","memberof":"Guild","type":{"names":["GuildDataStore"]},"meta":{"lineno":37,"filename":"Guild.js","path":"src/structures"},"order":5},{"id":"Guild#available","longname":"Guild#available","name":"available","scope":"instance","kind":"member","description":"Whether the Guild is available to access. If it is not available, it indicates a server outage.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":48,"filename":"Guild.js","path":"src/structures"},"order":6},{"id":"Guild#id","longname":"Guild#id","name":"id","scope":"instance","kind":"member","description":"The Unique ID of the Guild, useful for comparisons.","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":53,"filename":"Guild.js","path":"src/structures"},"order":7},{"id":"Guild#splash","longname":"Guild#splash","name":"splash","scope":"instance","kind":"member","description":"The hash of the guild splash image, or null if no splash (VIP only)","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":169,"filename":"Guild.js","path":"src/structures"},"order":12},{"id":"Guild#region","longname":"Guild#region","name":"region","scope":"instance","kind":"member","description":"The region the guild is located in","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":174,"filename":"Guild.js","path":"src/structures"},"order":13},{"id":"Guild#name","longname":"Guild#name","name":"name","scope":"instance","kind":"member","description":"The name of the guild","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":179,"filename":"Guild.js","path":"src/structures"},"order":14},{"id":"Guild#memberCount","longname":"Guild#memberCount","name":"memberCount","scope":"instance","kind":"member","description":"The amount of initial members in the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":184,"filename":"Guild.js","path":"src/structures"},"order":15},{"id":"Guild#large","longname":"Guild#large","name":"large","scope":"instance","kind":"member","description":"Whether the guild is \"large\" (has more than 250 members)","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":189,"filename":"Guild.js","path":"src/structures"},"order":16},{"id":"Guild#joinDate","longname":"Guild#joinDate","name":"joinDate","scope":"instance","kind":"member","description":"The date at which the logged-in client joined the guild.","memberof":"Guild","type":{"names":["Date"]},"meta":{"lineno":194,"filename":"Guild.js","path":"src/structures"},"order":17},{"id":"Guild#icon","longname":"Guild#icon","name":"icon","scope":"instance","kind":"member","description":"The hash of the guild icon, or null if there is no icon.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":199,"filename":"Guild.js","path":"src/structures"},"order":18},{"id":"Guild#features","longname":"Guild#features","name":"features","scope":"instance","kind":"member","description":"An array of guild features.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":204,"filename":"Guild.js","path":"src/structures"},"order":19},{"id":"Guild#emojis","longname":"Guild#emojis","name":"emojis","scope":"instance","kind":"member","description":"An array of guild emojis.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":209,"filename":"Guild.js","path":"src/structures"},"order":20},{"id":"Guild#afkTimeout","longname":"Guild#afkTimeout","name":"afkTimeout","scope":"instance","kind":"member","description":"The time in seconds before a user is counted as \"away from keyboard\".","memberof":"Guild","type":{"names":["Number"]},"nullable":true,"meta":{"lineno":214,"filename":"Guild.js","path":"src/structures"},"order":21},{"id":"Guild#afkChannelID","longname":"Guild#afkChannelID","name":"afkChannelID","scope":"instance","kind":"member","description":"The ID of the voice channel where AFK members are moved.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":219,"filename":"Guild.js","path":"src/structures"},"order":22},{"id":"Guild#embedEnabled","longname":"Guild#embedEnabled","name":"embedEnabled","scope":"instance","kind":"member","description":"Whether embedded images are enabled on this guild.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":224,"filename":"Guild.js","path":"src/structures"},"order":23},{"id":"Guild#verificationLevel","longname":"Guild#verificationLevel","name":"verificationLevel","scope":"instance","kind":"member","description":"The verification level of the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":229,"filename":"Guild.js","path":"src/structures"},"order":24},{"id":"Guild#owner","longname":"Guild#owner","name":"owner","scope":"instance","kind":"member","description":"The owner of the guild","memberof":"Guild","type":{"names":["User"]},"meta":{"lineno":243,"filename":"Guild.js","path":"src/structures"},"order":25},{"id":"Guild#embedChannel","longname":"Guild#embedChannel","name":"embedChannel","scope":"instance","kind":"member","description":"The embed channel of the Guild.","memberof":"Guild","type":{"names":["GuildChannel"]},"meta":{"lineno":256,"filename":"Guild.js","path":"src/structures"},"order":26}],"events":[]},"Message":{"meta":{"id":"Message","longname":"Message","name":"Message","scope":"global","kind":"class","description":"Represents a Message on Discord","meta":{"lineno":4,"filename":"Message.js","path":"src/structures"},"order":27},"functions":[],"properties":[],"events":[]},"TextChannel":{"meta":{"id":"TextChannel","longname":"TextChannel","name":"TextChannel","scope":"global","kind":"class","description":"Represents a Server Text Channel on Discord.","meta":{"lineno":8,"filename":"TextChannel.js","path":"src/structures"},"order":28},"functions":[],"properties":[],"events":[]},"User":{"meta":{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":29},"functions":[{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":64,"filename":"User.js","path":"src/structures"},"order":37},{"id":"User#equals","longname":"User#equals","name":"equals","scope":"instance","kind":"function","description":"Checks if the user is equal to another. It compares username, ID, discriminator, status and the game being played.\nIt is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties.","memberof":"User","params":[{"type":{"names":["User"]},"description":"the user to compare","name":"user"}],"returns":[{"description":"Boolean"}],"meta":{"lineno":74,"filename":"User.js","path":"src/structures"},"order":38}],"properties":[{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":30},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":31},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":32},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":33},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":34},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":35},{"id":"User#game","longname":"User#game","name":"game","scope":"instance","kind":"member","description":"The game that the user is playing, `null` if they aren't playing a game.","memberof":"User","type":{"names":["String"]},"meta":{"lineno":53,"filename":"User.js","path":"src/structures"},"order":36}],"events":[]},"VoiceChannel":{"meta":{"id":"VoiceChannel","longname":"VoiceChannel","name":"VoiceChannel","scope":"global","kind":"class","description":"Represents a Server Voice Channel on Discord.","meta":{"lineno":7,"filename":"VoiceChannel.js","path":"src/structures"},"order":39},"functions":[],"properties":[],"events":[]}}}}
\ No newline at end of file
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index 8707dc94a..2c2e3a9f3 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -21,7 +21,6 @@ function arraysEqual(a, b) {
/**
* Represents a Guild (or a Server) on Discord.
- * @class Guild
*/
class Guild {
constructor(client, data) {
@@ -125,6 +124,13 @@ class Guild {
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(data) {
let base =
this.id === data.id &&
From 2b7dd39f3eef3a3069cdfc64fe7f04b803310b5a Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Wed, 17 Aug 2016 16:57:22 +0100
Subject: [PATCH 061/324] work on guild docs
---
docs/docs.json | 2 +-
src/structures/Guild.js | 136 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 137 insertions(+), 1 deletion(-)
diff --git a/docs/docs.json b/docs/docs.json
index 5197521eb..d22a69ac8 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -1 +1 @@
-{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["// log the client in using a token\nconst token = 'my token';\nclient.login(token);","// log the client in using email and password\nconst email = 'user@email.com';\nconst password = 'supersecret123';\nclient.login(email, password);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":47,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"type":{"names":["ClientUser"]},"meta":{"lineno":60,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"Guild":{"meta":{"id":"Guild","longname":"Guild","name":"Guild","scope":"global","kind":"class","description":"Represents a Guild (or a Server) on Discord.","meta":{"lineno":25,"filename":"Guild.js","path":"src/structures"},"order":3},"functions":[{"id":"Guild#toString","longname":"Guild#toString","name":"toString","scope":"instance","kind":"function","description":"When concatenated with a String, this automatically concatenates the Guild's name instead of the Guild object.","memberof":"Guild","params":[],"examples":["// logs: Hello from My Guild!\nconsole.log(`Hello from ${guild}!`);","// logs: Hello from My Guild!\nconsole.log(`Hello from ' + guild + '!');"],"returns":[{"type":{"names":["String"]}}],"meta":{"lineno":97,"filename":"Guild.js","path":"src/structures"},"order":8},{"id":"Guild#kick","longname":"Guild#kick","name":"kick","scope":"instance","kind":"function","description":"Tries to kick a member from the guild.","memberof":"Guild","params":[{"type":{"names":["GuildMemberResolvable"]},"description":"the member to kick","name":"member"}],"examples":["// kicks a member from a guild:\nguild.kick(message.author)\n .then(member => console.log(`Kicked ${member}`))\n .catch(error => console.log(error));"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":111,"filename":"Guild.js","path":"src/structures"},"order":9},{"id":"Guild#member","longname":"Guild#member","name":"member","scope":"instance","kind":"function","description":"Returns the GuildMember form of a User object, if the User is present in the guild.","memberof":"Guild","params":[{"type":{"names":["UserResolvable"]},"description":"the user that you want to obtain the GuildMember of.","name":"user"}],"examples":["// get the guild member of a user\nconst member = guild.member(message.author);"],"returns":[{"type":{"names":["GuildMember","null"]}}],"meta":{"lineno":123,"filename":"Guild.js","path":"src/structures"},"order":10},{"id":"Guild#equals","longname":"Guild#equals","name":"equals","scope":"instance","kind":"function","description":"Whether this Guild equals another Guild. It compares all properties, so for most operations\nit is advisable to just compare `guild.id === guild2.id` as it is much faster and is often\nwhat most users need.","memberof":"Guild","params":[{"type":{"names":["Guild"]},"description":"the guild to compare","name":"guild"}],"returns":[{"type":{"names":["Boolean"]}}],"meta":{"lineno":134,"filename":"Guild.js","path":"src/structures"},"order":11}],"properties":[{"id":"Guild#client","longname":"Guild#client","name":"client","scope":"instance","kind":"member","description":"The Client that created the instance of the the Guild.","memberof":"Guild","type":{"names":["Client"]},"meta":{"lineno":31,"filename":"Guild.js","path":"src/structures"},"order":4},{"id":"Guild#store","longname":"Guild#store","name":"store","scope":"instance","kind":"member","description":"The data store of the Guild.","memberof":"Guild","type":{"names":["GuildDataStore"]},"meta":{"lineno":37,"filename":"Guild.js","path":"src/structures"},"order":5},{"id":"Guild#available","longname":"Guild#available","name":"available","scope":"instance","kind":"member","description":"Whether the Guild is available to access. If it is not available, it indicates a server outage.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":48,"filename":"Guild.js","path":"src/structures"},"order":6},{"id":"Guild#id","longname":"Guild#id","name":"id","scope":"instance","kind":"member","description":"The Unique ID of the Guild, useful for comparisons.","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":53,"filename":"Guild.js","path":"src/structures"},"order":7},{"id":"Guild#splash","longname":"Guild#splash","name":"splash","scope":"instance","kind":"member","description":"The hash of the guild splash image, or null if no splash (VIP only)","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":169,"filename":"Guild.js","path":"src/structures"},"order":12},{"id":"Guild#region","longname":"Guild#region","name":"region","scope":"instance","kind":"member","description":"The region the guild is located in","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":174,"filename":"Guild.js","path":"src/structures"},"order":13},{"id":"Guild#name","longname":"Guild#name","name":"name","scope":"instance","kind":"member","description":"The name of the guild","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":179,"filename":"Guild.js","path":"src/structures"},"order":14},{"id":"Guild#memberCount","longname":"Guild#memberCount","name":"memberCount","scope":"instance","kind":"member","description":"The amount of initial members in the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":184,"filename":"Guild.js","path":"src/structures"},"order":15},{"id":"Guild#large","longname":"Guild#large","name":"large","scope":"instance","kind":"member","description":"Whether the guild is \"large\" (has more than 250 members)","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":189,"filename":"Guild.js","path":"src/structures"},"order":16},{"id":"Guild#joinDate","longname":"Guild#joinDate","name":"joinDate","scope":"instance","kind":"member","description":"The date at which the logged-in client joined the guild.","memberof":"Guild","type":{"names":["Date"]},"meta":{"lineno":194,"filename":"Guild.js","path":"src/structures"},"order":17},{"id":"Guild#icon","longname":"Guild#icon","name":"icon","scope":"instance","kind":"member","description":"The hash of the guild icon, or null if there is no icon.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":199,"filename":"Guild.js","path":"src/structures"},"order":18},{"id":"Guild#features","longname":"Guild#features","name":"features","scope":"instance","kind":"member","description":"An array of guild features.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":204,"filename":"Guild.js","path":"src/structures"},"order":19},{"id":"Guild#emojis","longname":"Guild#emojis","name":"emojis","scope":"instance","kind":"member","description":"An array of guild emojis.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":209,"filename":"Guild.js","path":"src/structures"},"order":20},{"id":"Guild#afkTimeout","longname":"Guild#afkTimeout","name":"afkTimeout","scope":"instance","kind":"member","description":"The time in seconds before a user is counted as \"away from keyboard\".","memberof":"Guild","type":{"names":["Number"]},"nullable":true,"meta":{"lineno":214,"filename":"Guild.js","path":"src/structures"},"order":21},{"id":"Guild#afkChannelID","longname":"Guild#afkChannelID","name":"afkChannelID","scope":"instance","kind":"member","description":"The ID of the voice channel where AFK members are moved.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":219,"filename":"Guild.js","path":"src/structures"},"order":22},{"id":"Guild#embedEnabled","longname":"Guild#embedEnabled","name":"embedEnabled","scope":"instance","kind":"member","description":"Whether embedded images are enabled on this guild.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":224,"filename":"Guild.js","path":"src/structures"},"order":23},{"id":"Guild#verificationLevel","longname":"Guild#verificationLevel","name":"verificationLevel","scope":"instance","kind":"member","description":"The verification level of the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":229,"filename":"Guild.js","path":"src/structures"},"order":24},{"id":"Guild#owner","longname":"Guild#owner","name":"owner","scope":"instance","kind":"member","description":"The owner of the guild","memberof":"Guild","type":{"names":["User"]},"meta":{"lineno":243,"filename":"Guild.js","path":"src/structures"},"order":25},{"id":"Guild#embedChannel","longname":"Guild#embedChannel","name":"embedChannel","scope":"instance","kind":"member","description":"The embed channel of the Guild.","memberof":"Guild","type":{"names":["GuildChannel"]},"meta":{"lineno":256,"filename":"Guild.js","path":"src/structures"},"order":26}],"events":[]},"Message":{"meta":{"id":"Message","longname":"Message","name":"Message","scope":"global","kind":"class","description":"Represents a Message on Discord","meta":{"lineno":4,"filename":"Message.js","path":"src/structures"},"order":27},"functions":[],"properties":[],"events":[]},"TextChannel":{"meta":{"id":"TextChannel","longname":"TextChannel","name":"TextChannel","scope":"global","kind":"class","description":"Represents a Server Text Channel on Discord.","meta":{"lineno":8,"filename":"TextChannel.js","path":"src/structures"},"order":28},"functions":[],"properties":[],"events":[]},"User":{"meta":{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":29},"functions":[{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":64,"filename":"User.js","path":"src/structures"},"order":37},{"id":"User#equals","longname":"User#equals","name":"equals","scope":"instance","kind":"function","description":"Checks if the user is equal to another. It compares username, ID, discriminator, status and the game being played.\nIt is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties.","memberof":"User","params":[{"type":{"names":["User"]},"description":"the user to compare","name":"user"}],"returns":[{"description":"Boolean"}],"meta":{"lineno":74,"filename":"User.js","path":"src/structures"},"order":38}],"properties":[{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":30},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":31},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":32},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":33},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":34},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":35},{"id":"User#game","longname":"User#game","name":"game","scope":"instance","kind":"member","description":"The game that the user is playing, `null` if they aren't playing a game.","memberof":"User","type":{"names":["String"]},"meta":{"lineno":53,"filename":"User.js","path":"src/structures"},"order":36}],"events":[]},"VoiceChannel":{"meta":{"id":"VoiceChannel","longname":"VoiceChannel","name":"VoiceChannel","scope":"global","kind":"class","description":"Represents a Server Voice Channel on Discord.","meta":{"lineno":7,"filename":"VoiceChannel.js","path":"src/structures"},"order":39},"functions":[],"properties":[],"events":[]}}}}
\ No newline at end of file
+{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["// log the client in using a token\nconst token = 'my token';\nclient.login(token);","// log the client in using email and password\nconst email = 'user@email.com';\nconst password = 'supersecret123';\nclient.login(email, password);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":47,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"type":{"names":["ClientUser"]},"meta":{"lineno":60,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"Guild":{"meta":{"id":"Guild","longname":"Guild","name":"Guild","scope":"global","kind":"class","description":"Represents a Guild (or a Server) on Discord.","meta":{"lineno":25,"filename":"Guild.js","path":"src/structures"},"order":3},"functions":[{"id":"Guild#toString","longname":"Guild#toString","name":"toString","scope":"instance","kind":"function","description":"When concatenated with a String, this automatically concatenates the Guild's name instead of the Guild object.","memberof":"Guild","params":[],"examples":["// logs: Hello from My Guild!\nconsole.log(`Hello from ${guild}!`);","// logs: Hello from My Guild!\nconsole.log(`Hello from ' + guild + '!');"],"returns":[{"type":{"names":["String"]}}],"meta":{"lineno":97,"filename":"Guild.js","path":"src/structures"},"order":8},{"id":"Guild#kick","longname":"Guild#kick","name":"kick","scope":"instance","kind":"function","description":"Tries to kick a member from the guild.","memberof":"Guild","params":[{"type":{"names":["GuildMemberResolvable"]},"description":"the member to kick","name":"member"}],"examples":["// kicks a member from a guild:\nguild.kick(message.author)\n .then(member => console.log(`Kicked ${member}`))\n .catch(error => console.log(error));"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":111,"filename":"Guild.js","path":"src/structures"},"order":9},{"id":"Guild#member","longname":"Guild#member","name":"member","scope":"instance","kind":"function","description":"Returns the GuildMember form of a User object, if the User is present in the guild.","memberof":"Guild","params":[{"type":{"names":["UserResolvable"]},"description":"the user that you want to obtain the GuildMember of.","name":"user"}],"examples":["// get the guild member of a user\nconst member = guild.member(message.author);"],"returns":[{"type":{"names":["GuildMember","null"]}}],"meta":{"lineno":123,"filename":"Guild.js","path":"src/structures"},"order":10},{"id":"Guild#equals","longname":"Guild#equals","name":"equals","scope":"instance","kind":"function","description":"Whether this Guild equals another Guild. It compares all properties, so for most operations\nit is advisable to just compare `guild.id === guild2.id` as it is much faster and is often\nwhat most users need.","memberof":"Guild","params":[{"type":{"names":["Guild"]},"description":"the guild to compare","name":"guild"}],"returns":[{"type":{"names":["Boolean"]}}],"meta":{"lineno":134,"filename":"Guild.js","path":"src/structures"},"order":11},{"id":"Guild#createChannel","longname":"Guild#createChannel","name":"createChannel","scope":"instance","kind":"function","description":"Creates a new Channel in the Guild.","memberof":"Guild","params":[{"type":{"names":["String"]},"description":"the name of the new channel.","name":"name"},{"type":{"names":["any"]},"description":"the type of the new channel, either `text` or `voice`.","name":"type"}],"examples":["// create a new text channel\nguild.createChannel('new general', 'text')\n .then(channel => console.log(`Created new channel ${channel}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise.<(TextChannel|VoiceChannel), Error>"]}}],"meta":{"lineno":301,"filename":"Guild.js","path":"src/structures"},"order":27},{"id":"Guild#createRole","longname":"Guild#createRole","name":"createRole","scope":"instance","kind":"function","description":"Creates a new role in the guild, as of now this is just a blank role.","memberof":"Guild","params":[],"examples":["// create a new role\nguild.createRole()\n .then(role => console.log(`Created role ${role}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":314,"filename":"Guild.js","path":"src/structures"},"order":28},{"id":"Guild#leave","longname":"Guild#leave","name":"leave","scope":"instance","kind":"function","description":"Causes the Client to leave the guild.","memberof":"Guild","params":[],"examples":["// leave a guild\nguild.leave()\n .then(g => console.log(`Left the guild ${g}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":327,"filename":"Guild.js","path":"src/structures"},"order":29},{"id":"Guild#delete","longname":"Guild#delete","name":"delete","scope":"instance","kind":"function","description":"Causes the Client to delete the guild.","memberof":"Guild","params":[],"examples":["// delete a guild\nguild.delete()\n .then(g => console.log(`Deleted the guild ${g}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":340,"filename":"Guild.js","path":"src/structures"},"order":30},{"id":"Guild#edit","longname":"Guild#edit","name":"edit","scope":"instance","kind":"function","description":"Updates the Guild with new information - e.g. a new name.","memberof":"Guild","params":[{"type":{"names":["GuildEditData"]},"description":"the data to update the guild with.","name":"data"}],"examples":["// set the guild name and region\nguild.edit({\n name: 'Discord Guild',\n region: 'london',\n})\n.then(updated => console.log(`New guild name ${updated.name} in region ${updated.region}`))\n.catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":357,"filename":"Guild.js","path":"src/structures"},"order":31},{"id":"Guild#setName","longname":"Guild#setName","name":"setName","scope":"instance","kind":"function","description":"Edit the name of the Guild.","memberof":"Guild","params":[{"type":{"names":["String"]},"description":"the new name of the Guild.","name":"name"}],"examples":["// edit the guild name\nguild.setName('Discord Guild')\n .then(updated => console.log(`Updated guild name to ${guild.name}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":371,"filename":"Guild.js","path":"src/structures"},"order":32},{"id":"Guild#setRegion","longname":"Guild#setRegion","name":"setRegion","scope":"instance","kind":"function","description":"Edit the region of the Guild.","memberof":"Guild","params":[{"type":{"names":["Region"]},"description":"the new region of the guild.","name":"region"}],"examples":["// edit the guild region\nguild.setRegion('london')\n .then(updated => console.log(`Updated guild region to ${guild.region}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":385,"filename":"Guild.js","path":"src/structures"},"order":33},{"id":"Guild#setVerificationLevel","longname":"Guild#setVerificationLevel","name":"setVerificationLevel","scope":"instance","kind":"function","description":"Edit the verification level of the Guild.","memberof":"Guild","params":[{"type":{"names":["VerificationLevel"]},"description":"the new verification level of the guild.","name":"verificationLevel"}],"examples":["// edit the guild verification level\nguild.setVerificationLevel(1)\n .then(updated => console.log(`Updated guild verification level to ${guild.verificationLevel}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":399,"filename":"Guild.js","path":"src/structures"},"order":34},{"id":"Guild#setAFKChannel","longname":"Guild#setAFKChannel","name":"setAFKChannel","scope":"instance","kind":"function","description":"Edit the AFK channel of the Guild.","memberof":"Guild","params":[{"type":{"names":["GuildChannelResolvable"]},"description":"the new AFK channel.","name":"afkChannel"}],"examples":["// edit the guild AFK channel\nguild.setAFKChannel(channel)\n .then(updated => console.log(`Updated guild AFK channel to ${guild.afkChannel}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":413,"filename":"Guild.js","path":"src/structures"},"order":35},{"id":"Guild#setAFKTimeout","longname":"Guild#setAFKTimeout","name":"setAFKTimeout","scope":"instance","kind":"function","description":"Edit the AFK timeout of the Guild.","memberof":"Guild","params":[{"type":{"names":["Number"]},"description":"the time in seconds that a user must be idle to be considered AFK.","name":"afkTimeout"}],"examples":["// edit the guild AFK channel\nguild.setAFKTimeout(60)\n .then(updated => console.log(`Updated guild AFK timeout to ${guild.afkTimeout}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":427,"filename":"Guild.js","path":"src/structures"},"order":36},{"id":"Guild#setIcon","longname":"Guild#setIcon","name":"setIcon","scope":"instance","kind":"function","description":"Set a new Guild Icon.","memberof":"Guild","params":[{"type":{"names":["Base64Resolvable"]},"description":"the new icon of the guild.","name":"icon"}],"examples":["// edit the guild icon\nguild.setIcon(fs.readFileSync('./icon.png'))\n .then(updated => console.log('Updated the guild icon'))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":441,"filename":"Guild.js","path":"src/structures"},"order":37},{"id":"Guild#setOwner","longname":"Guild#setOwner","name":"setOwner","scope":"instance","kind":"function","description":"Sets a new owner of the Guild.","memberof":"Guild","params":[{"type":{"names":["GuildMemberResolvable"]},"description":"the new owner of the Guild.","name":"owner"}],"examples":["// edit the guild owner\nguild.setOwner(guilds.members[0])\n .then(updated => console.log(`Updated the guild owner to ${updated.owner.username}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":455,"filename":"Guild.js","path":"src/structures"},"order":38},{"id":"Guild#setSplash","longname":"Guild#setSplash","name":"setSplash","scope":"instance","kind":"function","description":"Set a new Guild Splash Logo.","memberof":"Guild","params":[{"type":{"names":["Base64Resolvable"]},"description":"the new splash screen of the guild.","name":"splash"}],"examples":["// edit the guild splash\nguild.setIcon(fs.readFileSync('./splash.png'))\n .then(updated => console.log('Updated the guild splash'))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":469,"filename":"Guild.js","path":"src/structures"},"order":39}],"properties":[{"id":"Guild#client","longname":"Guild#client","name":"client","scope":"instance","kind":"member","description":"The Client that created the instance of the the Guild.","memberof":"Guild","type":{"names":["Client"]},"meta":{"lineno":31,"filename":"Guild.js","path":"src/structures"},"order":4},{"id":"Guild#store","longname":"Guild#store","name":"store","scope":"instance","kind":"member","description":"The data store of the Guild.","memberof":"Guild","type":{"names":["GuildDataStore"]},"meta":{"lineno":37,"filename":"Guild.js","path":"src/structures"},"order":5},{"id":"Guild#available","longname":"Guild#available","name":"available","scope":"instance","kind":"member","description":"Whether the Guild is available to access. If it is not available, it indicates a server outage.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":48,"filename":"Guild.js","path":"src/structures"},"order":6},{"id":"Guild#id","longname":"Guild#id","name":"id","scope":"instance","kind":"member","description":"The Unique ID of the Guild, useful for comparisons.","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":53,"filename":"Guild.js","path":"src/structures"},"order":7},{"id":"Guild#splash","longname":"Guild#splash","name":"splash","scope":"instance","kind":"member","description":"The hash of the guild splash image, or null if no splash (VIP only)","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":169,"filename":"Guild.js","path":"src/structures"},"order":12},{"id":"Guild#region","longname":"Guild#region","name":"region","scope":"instance","kind":"member","description":"The region the guild is located in","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":174,"filename":"Guild.js","path":"src/structures"},"order":13},{"id":"Guild#name","longname":"Guild#name","name":"name","scope":"instance","kind":"member","description":"The name of the guild","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":179,"filename":"Guild.js","path":"src/structures"},"order":14},{"id":"Guild#memberCount","longname":"Guild#memberCount","name":"memberCount","scope":"instance","kind":"member","description":"The amount of initial members in the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":184,"filename":"Guild.js","path":"src/structures"},"order":15},{"id":"Guild#large","longname":"Guild#large","name":"large","scope":"instance","kind":"member","description":"Whether the guild is \"large\" (has more than 250 members)","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":189,"filename":"Guild.js","path":"src/structures"},"order":16},{"id":"Guild#joinDate","longname":"Guild#joinDate","name":"joinDate","scope":"instance","kind":"member","description":"The date at which the logged-in client joined the guild.","memberof":"Guild","type":{"names":["Date"]},"meta":{"lineno":194,"filename":"Guild.js","path":"src/structures"},"order":17},{"id":"Guild#icon","longname":"Guild#icon","name":"icon","scope":"instance","kind":"member","description":"The hash of the guild icon, or null if there is no icon.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":199,"filename":"Guild.js","path":"src/structures"},"order":18},{"id":"Guild#features","longname":"Guild#features","name":"features","scope":"instance","kind":"member","description":"An array of guild features.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":204,"filename":"Guild.js","path":"src/structures"},"order":19},{"id":"Guild#emojis","longname":"Guild#emojis","name":"emojis","scope":"instance","kind":"member","description":"An array of guild emojis.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":209,"filename":"Guild.js","path":"src/structures"},"order":20},{"id":"Guild#afkTimeout","longname":"Guild#afkTimeout","name":"afkTimeout","scope":"instance","kind":"member","description":"The time in seconds before a user is counted as \"away from keyboard\".","memberof":"Guild","type":{"names":["Number"]},"nullable":true,"meta":{"lineno":214,"filename":"Guild.js","path":"src/structures"},"order":21},{"id":"Guild#afkChannelID","longname":"Guild#afkChannelID","name":"afkChannelID","scope":"instance","kind":"member","description":"The ID of the voice channel where AFK members are moved.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":219,"filename":"Guild.js","path":"src/structures"},"order":22},{"id":"Guild#embedEnabled","longname":"Guild#embedEnabled","name":"embedEnabled","scope":"instance","kind":"member","description":"Whether embedded images are enabled on this guild.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":224,"filename":"Guild.js","path":"src/structures"},"order":23},{"id":"Guild#verificationLevel","longname":"Guild#verificationLevel","name":"verificationLevel","scope":"instance","kind":"member","description":"The verification level of the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":229,"filename":"Guild.js","path":"src/structures"},"order":24},{"id":"Guild#owner","longname":"Guild#owner","name":"owner","scope":"instance","kind":"member","description":"The owner of the guild","memberof":"Guild","type":{"names":["User"]},"meta":{"lineno":243,"filename":"Guild.js","path":"src/structures"},"order":25},{"id":"Guild#embedChannel","longname":"Guild#embedChannel","name":"embedChannel","scope":"instance","kind":"member","description":"The embed channel of the Guild.","memberof":"Guild","type":{"names":["GuildChannel"]},"meta":{"lineno":256,"filename":"Guild.js","path":"src/structures"},"order":26},{"id":"Guild#channels","longname":"Guild#channels","name":"channels","scope":"instance","kind":"member","description":"The channels in the guild.","memberof":"Guild","params":[],"type":{"names":["Array."]},"readonly":true,"meta":{"lineno":478,"filename":"Guild.js","path":"src/structures"},"order":40}],"events":[]},"Message":{"meta":{"id":"Message","longname":"Message","name":"Message","scope":"global","kind":"class","description":"Represents a Message on Discord","meta":{"lineno":4,"filename":"Message.js","path":"src/structures"},"order":41},"functions":[],"properties":[],"events":[]},"TextChannel":{"meta":{"id":"TextChannel","longname":"TextChannel","name":"TextChannel","scope":"global","kind":"class","description":"Represents a Server Text Channel on Discord.","meta":{"lineno":8,"filename":"TextChannel.js","path":"src/structures"},"order":42},"functions":[],"properties":[],"events":[]},"User":{"meta":{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":43},"functions":[{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":64,"filename":"User.js","path":"src/structures"},"order":51},{"id":"User#equals","longname":"User#equals","name":"equals","scope":"instance","kind":"function","description":"Checks if the user is equal to another. It compares username, ID, discriminator, status and the game being played.\nIt is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties.","memberof":"User","params":[{"type":{"names":["User"]},"description":"the user to compare","name":"user"}],"returns":[{"description":"Boolean"}],"meta":{"lineno":74,"filename":"User.js","path":"src/structures"},"order":52}],"properties":[{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":44},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":45},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":46},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":47},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":48},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":49},{"id":"User#game","longname":"User#game","name":"game","scope":"instance","kind":"member","description":"The game that the user is playing, `null` if they aren't playing a game.","memberof":"User","type":{"names":["String"]},"meta":{"lineno":53,"filename":"User.js","path":"src/structures"},"order":50}],"events":[]},"VoiceChannel":{"meta":{"id":"VoiceChannel","longname":"VoiceChannel","name":"VoiceChannel","scope":"global","kind":"class","description":"Represents a Server Voice Channel on Discord.","meta":{"lineno":7,"filename":"VoiceChannel.js","path":"src/structures"},"order":53},"functions":[],"properties":[],"events":[]}}}}
\ No newline at end of file
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index 2c2e3a9f3..52a1cc9c8 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -287,58 +287,194 @@ class Guild {
}
}
+ /**
+ * Creates a new Channel in the Guild.
+ * @param {String} name the name of the new channel.
+ * @param {any} type the type of the new channel, either `text` or `voice`.
+ * @returns {Promise}
+ * @example
+ * // create a new text channel
+ * guild.createChannel('new general', 'text')
+ * .then(channel => console.log(`Created new channel ${channel}`))
+ * .catch(console.log);
+ */
createChannel(name, type) {
return this.client.rest.methods.createChannel(this, name, type);
}
+ /**
+ * Creates a new role in the guild, as of now this is just a blank role.
+ * @returns {Promise}
+ * @example
+ * // create a new role
+ * guild.createRole()
+ * .then(role => console.log(`Created role ${role}`))
+ * .catch(console.log);
+ */
createRole() {
return this.client.rest.methods.createGuildRole(this);
}
+ /**
+ * Causes the Client to leave the guild.
+ * @returns {Promise}
+ * @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}
+ * @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);
}
+ /**
+ * Updates the Guild with new information - e.g. a new name.
+ * @param {GuildEditData} data the data to update the guild with.
+ * @returns {Promise}
+ * @example
+ * // set the guild name and region
+ * guild.edit({
+ * name: 'Discord Guild',
+ * region: 'london',
+ * })
+ * .then(updated => console.log(`New guild name ${updated.name} in region ${updated.region}`))
+ * .catch(console.log);
+ */
edit(data) {
return this.client.rest.methods.updateGuild(this, data);
}
+ /**
+ * Edit the name of the Guild.
+ * @param {String} name the new name of the Guild.
+ * @returns {Promise}
+ * @example
+ * // edit the guild name
+ * guild.setName('Discord Guild')
+ * .then(updated => console.log(`Updated guild name to ${guild.name}`))
+ * .catch(console.log);
+ */
setName(name) {
return this.edit({ name });
}
+ /**
+ * Edit the region of the Guild.
+ * @param {Region} region the new region of the guild.
+ * @returns {Promise}
+ * @example
+ * // edit the guild region
+ * guild.setRegion('london')
+ * .then(updated => console.log(`Updated guild region to ${guild.region}`))
+ * .catch(console.log);
+ */
setRegion(region) {
return this.edit({ region });
}
+ /**
+ * Edit the verification level of the Guild.
+ * @param {VerificationLevel} verificationLevel the new verification level of the guild.
+ * @returns {Promise}
+ * @example
+ * // edit the guild verification level
+ * guild.setVerificationLevel(1)
+ * .then(updated => console.log(`Updated guild verification level to ${guild.verificationLevel}`))
+ * .catch(console.log);
+ */
setVerificationLevel(verificationLevel) {
return this.edit({ verificationLevel });
}
+ /**
+ * Edit the AFK channel of the Guild.
+ * @param {GuildChannelResolvable} afkChannel the new AFK channel.
+ * @returns {Promise}
+ * @example
+ * // edit the guild AFK channel
+ * guild.setAFKChannel(channel)
+ * .then(updated => console.log(`Updated guild AFK channel to ${guild.afkChannel}`))
+ * .catch(console.log);
+ */
setAFKChannel(afkChannel) {
return this.edit({ afkChannel });
}
+ /**
+ * Edit the AFK timeout of the Guild.
+ * @param {Number} afkTimeout the time in seconds that a user must be idle to be considered AFK.
+ * @returns {Promise}
+ * @example
+ * // edit the guild AFK channel
+ * guild.setAFKTimeout(60)
+ * .then(updated => console.log(`Updated guild AFK timeout to ${guild.afkTimeout}`))
+ * .catch(console.log);
+ */
setAFKTimeout(afkTimeout) {
return this.edit({ afkTimeout });
}
+ /**
+ * Set a new Guild Icon.
+ * @param {Base64Resolvable} icon the new icon of the guild.
+ * @returns {Promise}
+ * @example
+ * // edit the guild icon
+ * guild.setIcon(fs.readFileSync('./icon.png'))
+ * .then(updated => console.log('Updated the guild icon'))
+ * .catch(console.log);
+ */
setIcon(icon) {
return this.edit({ icon });
}
+ /**
+ * Sets a new owner of the Guild.
+ * @param {GuildMemberResolvable} owner the new owner of the Guild.
+ * @returns {Promise}
+ * @example
+ * // edit the guild owner
+ * guild.setOwner(guilds.members[0])
+ * .then(updated => console.log(`Updated the guild owner to ${updated.owner.username}`))
+ * .catch(console.log);
+ */
setOwner(owner) {
return this.edit({ owner });
}
+ /**
+ * Set a new Guild Splash Logo.
+ * @param {Base64Resolvable} splash the new splash screen of the guild.
+ * @returns {Promise}
+ * @example
+ * // edit the guild splash
+ * guild.setIcon(fs.readFileSync('./splash.png'))
+ * .then(updated => console.log('Updated the guild splash'))
+ * .catch(console.log);
+ */
setSplash(splash) {
return this.edit({ splash });
}
+ /**
+ * The channels in the guild.
+ * @type {Array}
+ * @readonly
+ */
get channels() { return this.store.getAsArray('channels'); }
get $channels() { return this.store.data.channels; }
From 9dc8265a9350b45b0f3c884d3912105d4ddf5326 Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Wed, 17 Aug 2016 17:06:37 +0100
Subject: [PATCH 062/324] work on guild docs
---
docs/docs.json | 2 +-
src/structures/Guild.js | 28 ++++++++++++++++++++++++++++
2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/docs/docs.json b/docs/docs.json
index d22a69ac8..c24d06147 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -1 +1 @@
-{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["// log the client in using a token\nconst token = 'my token';\nclient.login(token);","// log the client in using email and password\nconst email = 'user@email.com';\nconst password = 'supersecret123';\nclient.login(email, password);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":47,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"type":{"names":["ClientUser"]},"meta":{"lineno":60,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"Guild":{"meta":{"id":"Guild","longname":"Guild","name":"Guild","scope":"global","kind":"class","description":"Represents a Guild (or a Server) on Discord.","meta":{"lineno":25,"filename":"Guild.js","path":"src/structures"},"order":3},"functions":[{"id":"Guild#toString","longname":"Guild#toString","name":"toString","scope":"instance","kind":"function","description":"When concatenated with a String, this automatically concatenates the Guild's name instead of the Guild object.","memberof":"Guild","params":[],"examples":["// logs: Hello from My Guild!\nconsole.log(`Hello from ${guild}!`);","// logs: Hello from My Guild!\nconsole.log(`Hello from ' + guild + '!');"],"returns":[{"type":{"names":["String"]}}],"meta":{"lineno":97,"filename":"Guild.js","path":"src/structures"},"order":8},{"id":"Guild#kick","longname":"Guild#kick","name":"kick","scope":"instance","kind":"function","description":"Tries to kick a member from the guild.","memberof":"Guild","params":[{"type":{"names":["GuildMemberResolvable"]},"description":"the member to kick","name":"member"}],"examples":["// kicks a member from a guild:\nguild.kick(message.author)\n .then(member => console.log(`Kicked ${member}`))\n .catch(error => console.log(error));"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":111,"filename":"Guild.js","path":"src/structures"},"order":9},{"id":"Guild#member","longname":"Guild#member","name":"member","scope":"instance","kind":"function","description":"Returns the GuildMember form of a User object, if the User is present in the guild.","memberof":"Guild","params":[{"type":{"names":["UserResolvable"]},"description":"the user that you want to obtain the GuildMember of.","name":"user"}],"examples":["// get the guild member of a user\nconst member = guild.member(message.author);"],"returns":[{"type":{"names":["GuildMember","null"]}}],"meta":{"lineno":123,"filename":"Guild.js","path":"src/structures"},"order":10},{"id":"Guild#equals","longname":"Guild#equals","name":"equals","scope":"instance","kind":"function","description":"Whether this Guild equals another Guild. It compares all properties, so for most operations\nit is advisable to just compare `guild.id === guild2.id` as it is much faster and is often\nwhat most users need.","memberof":"Guild","params":[{"type":{"names":["Guild"]},"description":"the guild to compare","name":"guild"}],"returns":[{"type":{"names":["Boolean"]}}],"meta":{"lineno":134,"filename":"Guild.js","path":"src/structures"},"order":11},{"id":"Guild#createChannel","longname":"Guild#createChannel","name":"createChannel","scope":"instance","kind":"function","description":"Creates a new Channel in the Guild.","memberof":"Guild","params":[{"type":{"names":["String"]},"description":"the name of the new channel.","name":"name"},{"type":{"names":["any"]},"description":"the type of the new channel, either `text` or `voice`.","name":"type"}],"examples":["// create a new text channel\nguild.createChannel('new general', 'text')\n .then(channel => console.log(`Created new channel ${channel}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise.<(TextChannel|VoiceChannel), Error>"]}}],"meta":{"lineno":301,"filename":"Guild.js","path":"src/structures"},"order":27},{"id":"Guild#createRole","longname":"Guild#createRole","name":"createRole","scope":"instance","kind":"function","description":"Creates a new role in the guild, as of now this is just a blank role.","memberof":"Guild","params":[],"examples":["// create a new role\nguild.createRole()\n .then(role => console.log(`Created role ${role}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":314,"filename":"Guild.js","path":"src/structures"},"order":28},{"id":"Guild#leave","longname":"Guild#leave","name":"leave","scope":"instance","kind":"function","description":"Causes the Client to leave the guild.","memberof":"Guild","params":[],"examples":["// leave a guild\nguild.leave()\n .then(g => console.log(`Left the guild ${g}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":327,"filename":"Guild.js","path":"src/structures"},"order":29},{"id":"Guild#delete","longname":"Guild#delete","name":"delete","scope":"instance","kind":"function","description":"Causes the Client to delete the guild.","memberof":"Guild","params":[],"examples":["// delete a guild\nguild.delete()\n .then(g => console.log(`Deleted the guild ${g}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":340,"filename":"Guild.js","path":"src/structures"},"order":30},{"id":"Guild#edit","longname":"Guild#edit","name":"edit","scope":"instance","kind":"function","description":"Updates the Guild with new information - e.g. a new name.","memberof":"Guild","params":[{"type":{"names":["GuildEditData"]},"description":"the data to update the guild with.","name":"data"}],"examples":["// set the guild name and region\nguild.edit({\n name: 'Discord Guild',\n region: 'london',\n})\n.then(updated => console.log(`New guild name ${updated.name} in region ${updated.region}`))\n.catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":357,"filename":"Guild.js","path":"src/structures"},"order":31},{"id":"Guild#setName","longname":"Guild#setName","name":"setName","scope":"instance","kind":"function","description":"Edit the name of the Guild.","memberof":"Guild","params":[{"type":{"names":["String"]},"description":"the new name of the Guild.","name":"name"}],"examples":["// edit the guild name\nguild.setName('Discord Guild')\n .then(updated => console.log(`Updated guild name to ${guild.name}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":371,"filename":"Guild.js","path":"src/structures"},"order":32},{"id":"Guild#setRegion","longname":"Guild#setRegion","name":"setRegion","scope":"instance","kind":"function","description":"Edit the region of the Guild.","memberof":"Guild","params":[{"type":{"names":["Region"]},"description":"the new region of the guild.","name":"region"}],"examples":["// edit the guild region\nguild.setRegion('london')\n .then(updated => console.log(`Updated guild region to ${guild.region}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":385,"filename":"Guild.js","path":"src/structures"},"order":33},{"id":"Guild#setVerificationLevel","longname":"Guild#setVerificationLevel","name":"setVerificationLevel","scope":"instance","kind":"function","description":"Edit the verification level of the Guild.","memberof":"Guild","params":[{"type":{"names":["VerificationLevel"]},"description":"the new verification level of the guild.","name":"verificationLevel"}],"examples":["// edit the guild verification level\nguild.setVerificationLevel(1)\n .then(updated => console.log(`Updated guild verification level to ${guild.verificationLevel}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":399,"filename":"Guild.js","path":"src/structures"},"order":34},{"id":"Guild#setAFKChannel","longname":"Guild#setAFKChannel","name":"setAFKChannel","scope":"instance","kind":"function","description":"Edit the AFK channel of the Guild.","memberof":"Guild","params":[{"type":{"names":["GuildChannelResolvable"]},"description":"the new AFK channel.","name":"afkChannel"}],"examples":["// edit the guild AFK channel\nguild.setAFKChannel(channel)\n .then(updated => console.log(`Updated guild AFK channel to ${guild.afkChannel}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":413,"filename":"Guild.js","path":"src/structures"},"order":35},{"id":"Guild#setAFKTimeout","longname":"Guild#setAFKTimeout","name":"setAFKTimeout","scope":"instance","kind":"function","description":"Edit the AFK timeout of the Guild.","memberof":"Guild","params":[{"type":{"names":["Number"]},"description":"the time in seconds that a user must be idle to be considered AFK.","name":"afkTimeout"}],"examples":["// edit the guild AFK channel\nguild.setAFKTimeout(60)\n .then(updated => console.log(`Updated guild AFK timeout to ${guild.afkTimeout}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":427,"filename":"Guild.js","path":"src/structures"},"order":36},{"id":"Guild#setIcon","longname":"Guild#setIcon","name":"setIcon","scope":"instance","kind":"function","description":"Set a new Guild Icon.","memberof":"Guild","params":[{"type":{"names":["Base64Resolvable"]},"description":"the new icon of the guild.","name":"icon"}],"examples":["// edit the guild icon\nguild.setIcon(fs.readFileSync('./icon.png'))\n .then(updated => console.log('Updated the guild icon'))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":441,"filename":"Guild.js","path":"src/structures"},"order":37},{"id":"Guild#setOwner","longname":"Guild#setOwner","name":"setOwner","scope":"instance","kind":"function","description":"Sets a new owner of the Guild.","memberof":"Guild","params":[{"type":{"names":["GuildMemberResolvable"]},"description":"the new owner of the Guild.","name":"owner"}],"examples":["// edit the guild owner\nguild.setOwner(guilds.members[0])\n .then(updated => console.log(`Updated the guild owner to ${updated.owner.username}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":455,"filename":"Guild.js","path":"src/structures"},"order":38},{"id":"Guild#setSplash","longname":"Guild#setSplash","name":"setSplash","scope":"instance","kind":"function","description":"Set a new Guild Splash Logo.","memberof":"Guild","params":[{"type":{"names":["Base64Resolvable"]},"description":"the new splash screen of the guild.","name":"splash"}],"examples":["// edit the guild splash\nguild.setIcon(fs.readFileSync('./splash.png'))\n .then(updated => console.log('Updated the guild splash'))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":469,"filename":"Guild.js","path":"src/structures"},"order":39}],"properties":[{"id":"Guild#client","longname":"Guild#client","name":"client","scope":"instance","kind":"member","description":"The Client that created the instance of the the Guild.","memberof":"Guild","type":{"names":["Client"]},"meta":{"lineno":31,"filename":"Guild.js","path":"src/structures"},"order":4},{"id":"Guild#store","longname":"Guild#store","name":"store","scope":"instance","kind":"member","description":"The data store of the Guild.","memberof":"Guild","type":{"names":["GuildDataStore"]},"meta":{"lineno":37,"filename":"Guild.js","path":"src/structures"},"order":5},{"id":"Guild#available","longname":"Guild#available","name":"available","scope":"instance","kind":"member","description":"Whether the Guild is available to access. If it is not available, it indicates a server outage.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":48,"filename":"Guild.js","path":"src/structures"},"order":6},{"id":"Guild#id","longname":"Guild#id","name":"id","scope":"instance","kind":"member","description":"The Unique ID of the Guild, useful for comparisons.","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":53,"filename":"Guild.js","path":"src/structures"},"order":7},{"id":"Guild#splash","longname":"Guild#splash","name":"splash","scope":"instance","kind":"member","description":"The hash of the guild splash image, or null if no splash (VIP only)","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":169,"filename":"Guild.js","path":"src/structures"},"order":12},{"id":"Guild#region","longname":"Guild#region","name":"region","scope":"instance","kind":"member","description":"The region the guild is located in","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":174,"filename":"Guild.js","path":"src/structures"},"order":13},{"id":"Guild#name","longname":"Guild#name","name":"name","scope":"instance","kind":"member","description":"The name of the guild","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":179,"filename":"Guild.js","path":"src/structures"},"order":14},{"id":"Guild#memberCount","longname":"Guild#memberCount","name":"memberCount","scope":"instance","kind":"member","description":"The amount of initial members in the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":184,"filename":"Guild.js","path":"src/structures"},"order":15},{"id":"Guild#large","longname":"Guild#large","name":"large","scope":"instance","kind":"member","description":"Whether the guild is \"large\" (has more than 250 members)","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":189,"filename":"Guild.js","path":"src/structures"},"order":16},{"id":"Guild#joinDate","longname":"Guild#joinDate","name":"joinDate","scope":"instance","kind":"member","description":"The date at which the logged-in client joined the guild.","memberof":"Guild","type":{"names":["Date"]},"meta":{"lineno":194,"filename":"Guild.js","path":"src/structures"},"order":17},{"id":"Guild#icon","longname":"Guild#icon","name":"icon","scope":"instance","kind":"member","description":"The hash of the guild icon, or null if there is no icon.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":199,"filename":"Guild.js","path":"src/structures"},"order":18},{"id":"Guild#features","longname":"Guild#features","name":"features","scope":"instance","kind":"member","description":"An array of guild features.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":204,"filename":"Guild.js","path":"src/structures"},"order":19},{"id":"Guild#emojis","longname":"Guild#emojis","name":"emojis","scope":"instance","kind":"member","description":"An array of guild emojis.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":209,"filename":"Guild.js","path":"src/structures"},"order":20},{"id":"Guild#afkTimeout","longname":"Guild#afkTimeout","name":"afkTimeout","scope":"instance","kind":"member","description":"The time in seconds before a user is counted as \"away from keyboard\".","memberof":"Guild","type":{"names":["Number"]},"nullable":true,"meta":{"lineno":214,"filename":"Guild.js","path":"src/structures"},"order":21},{"id":"Guild#afkChannelID","longname":"Guild#afkChannelID","name":"afkChannelID","scope":"instance","kind":"member","description":"The ID of the voice channel where AFK members are moved.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":219,"filename":"Guild.js","path":"src/structures"},"order":22},{"id":"Guild#embedEnabled","longname":"Guild#embedEnabled","name":"embedEnabled","scope":"instance","kind":"member","description":"Whether embedded images are enabled on this guild.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":224,"filename":"Guild.js","path":"src/structures"},"order":23},{"id":"Guild#verificationLevel","longname":"Guild#verificationLevel","name":"verificationLevel","scope":"instance","kind":"member","description":"The verification level of the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":229,"filename":"Guild.js","path":"src/structures"},"order":24},{"id":"Guild#owner","longname":"Guild#owner","name":"owner","scope":"instance","kind":"member","description":"The owner of the guild","memberof":"Guild","type":{"names":["User"]},"meta":{"lineno":243,"filename":"Guild.js","path":"src/structures"},"order":25},{"id":"Guild#embedChannel","longname":"Guild#embedChannel","name":"embedChannel","scope":"instance","kind":"member","description":"The embed channel of the Guild.","memberof":"Guild","type":{"names":["GuildChannel"]},"meta":{"lineno":256,"filename":"Guild.js","path":"src/structures"},"order":26},{"id":"Guild#channels","longname":"Guild#channels","name":"channels","scope":"instance","kind":"member","description":"The channels in the guild.","memberof":"Guild","params":[],"type":{"names":["Array."]},"readonly":true,"meta":{"lineno":478,"filename":"Guild.js","path":"src/structures"},"order":40}],"events":[]},"Message":{"meta":{"id":"Message","longname":"Message","name":"Message","scope":"global","kind":"class","description":"Represents a Message on Discord","meta":{"lineno":4,"filename":"Message.js","path":"src/structures"},"order":41},"functions":[],"properties":[],"events":[]},"TextChannel":{"meta":{"id":"TextChannel","longname":"TextChannel","name":"TextChannel","scope":"global","kind":"class","description":"Represents a Server Text Channel on Discord.","meta":{"lineno":8,"filename":"TextChannel.js","path":"src/structures"},"order":42},"functions":[],"properties":[],"events":[]},"User":{"meta":{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":43},"functions":[{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":64,"filename":"User.js","path":"src/structures"},"order":51},{"id":"User#equals","longname":"User#equals","name":"equals","scope":"instance","kind":"function","description":"Checks if the user is equal to another. It compares username, ID, discriminator, status and the game being played.\nIt is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties.","memberof":"User","params":[{"type":{"names":["User"]},"description":"the user to compare","name":"user"}],"returns":[{"description":"Boolean"}],"meta":{"lineno":74,"filename":"User.js","path":"src/structures"},"order":52}],"properties":[{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":44},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":45},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":46},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":47},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":48},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":49},{"id":"User#game","longname":"User#game","name":"game","scope":"instance","kind":"member","description":"The game that the user is playing, `null` if they aren't playing a game.","memberof":"User","type":{"names":["String"]},"meta":{"lineno":53,"filename":"User.js","path":"src/structures"},"order":50}],"events":[]},"VoiceChannel":{"meta":{"id":"VoiceChannel","longname":"VoiceChannel","name":"VoiceChannel","scope":"global","kind":"class","description":"Represents a Server Voice Channel on Discord.","meta":{"lineno":7,"filename":"VoiceChannel.js","path":"src/structures"},"order":53},"functions":[],"properties":[],"events":[]}}}}
\ No newline at end of file
+{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["// log the client in using a token\nconst token = 'my token';\nclient.login(token);","// log the client in using email and password\nconst email = 'user@email.com';\nconst password = 'supersecret123';\nclient.login(email, password);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":47,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"type":{"names":["ClientUser"]},"meta":{"lineno":60,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"Guild":{"meta":{"id":"Guild","longname":"Guild","name":"Guild","scope":"global","kind":"class","description":"Represents a Guild (or a Server) on Discord.","meta":{"lineno":25,"filename":"Guild.js","path":"src/structures"},"order":3},"functions":[{"id":"Guild#toString","longname":"Guild#toString","name":"toString","scope":"instance","kind":"function","description":"When concatenated with a String, this automatically concatenates the Guild's name instead of the Guild object.","memberof":"Guild","params":[],"examples":["// logs: Hello from My Guild!\nconsole.log(`Hello from ${guild}!`);","// logs: Hello from My Guild!\nconsole.log(`Hello from ' + guild + '!');"],"returns":[{"type":{"names":["String"]}}],"meta":{"lineno":97,"filename":"Guild.js","path":"src/structures"},"order":8},{"id":"Guild#kick","longname":"Guild#kick","name":"kick","scope":"instance","kind":"function","description":"Tries to kick a member from the guild.","memberof":"Guild","params":[{"type":{"names":["GuildMemberResolvable"]},"description":"the member to kick","name":"member"}],"examples":["// kicks a member from a guild:\nguild.kick(message.author)\n .then(member => console.log(`Kicked ${member}`))\n .catch(error => console.log(error));"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":111,"filename":"Guild.js","path":"src/structures"},"order":9},{"id":"Guild#member","longname":"Guild#member","name":"member","scope":"instance","kind":"function","description":"Returns the GuildMember form of a User object, if the User is present in the guild.","memberof":"Guild","params":[{"type":{"names":["UserResolvable"]},"description":"the user that you want to obtain the GuildMember of.","name":"user"}],"examples":["// get the guild member of a user\nconst member = guild.member(message.author);"],"returns":[{"type":{"names":["GuildMember","null"]}}],"meta":{"lineno":123,"filename":"Guild.js","path":"src/structures"},"order":10},{"id":"Guild#equals","longname":"Guild#equals","name":"equals","scope":"instance","kind":"function","description":"Whether this Guild equals another Guild. It compares all properties, so for most operations\nit is advisable to just compare `guild.id === guild2.id` as it is much faster and is often\nwhat most users need.","memberof":"Guild","params":[{"type":{"names":["Guild"]},"description":"the guild to compare","name":"guild"}],"returns":[{"type":{"names":["Boolean"]}}],"meta":{"lineno":134,"filename":"Guild.js","path":"src/structures"},"order":11},{"id":"Guild#createChannel","longname":"Guild#createChannel","name":"createChannel","scope":"instance","kind":"function","description":"Creates a new Channel in the Guild.","memberof":"Guild","params":[{"type":{"names":["String"]},"description":"the name of the new channel.","name":"name"},{"type":{"names":["any"]},"description":"the type of the new channel, either `text` or `voice`.","name":"type"}],"examples":["// create a new text channel\nguild.createChannel('new general', 'text')\n .then(channel => console.log(`Created new channel ${channel}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise.<(TextChannel|VoiceChannel), Error>"]}}],"meta":{"lineno":301,"filename":"Guild.js","path":"src/structures"},"order":27},{"id":"Guild#createRole","longname":"Guild#createRole","name":"createRole","scope":"instance","kind":"function","description":"Creates a new role in the guild, as of now this is just a blank role.","memberof":"Guild","params":[],"examples":["// create a new role\nguild.createRole()\n .then(role => console.log(`Created role ${role}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":314,"filename":"Guild.js","path":"src/structures"},"order":28},{"id":"Guild#leave","longname":"Guild#leave","name":"leave","scope":"instance","kind":"function","description":"Causes the Client to leave the guild.","memberof":"Guild","params":[],"examples":["// leave a guild\nguild.leave()\n .then(g => console.log(`Left the guild ${g}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":327,"filename":"Guild.js","path":"src/structures"},"order":29},{"id":"Guild#delete","longname":"Guild#delete","name":"delete","scope":"instance","kind":"function","description":"Causes the Client to delete the guild.","memberof":"Guild","params":[],"examples":["// delete a guild\nguild.delete()\n .then(g => console.log(`Deleted the guild ${g}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":340,"filename":"Guild.js","path":"src/structures"},"order":30},{"id":"Guild#edit","longname":"Guild#edit","name":"edit","scope":"instance","kind":"function","description":"Updates the Guild with new information - e.g. a new name.","memberof":"Guild","params":[{"type":{"names":["GuildEditData"]},"description":"the data to update the guild with.","name":"data"}],"examples":["// set the guild name and region\nguild.edit({\n name: 'Discord Guild',\n region: 'london',\n})\n.then(updated => console.log(`New guild name ${updated.name} in region ${updated.region}`))\n.catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":357,"filename":"Guild.js","path":"src/structures"},"order":31},{"id":"Guild#setName","longname":"Guild#setName","name":"setName","scope":"instance","kind":"function","description":"Edit the name of the Guild.","memberof":"Guild","params":[{"type":{"names":["String"]},"description":"the new name of the Guild.","name":"name"}],"examples":["// edit the guild name\nguild.setName('Discord Guild')\n .then(updated => console.log(`Updated guild name to ${guild.name}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":371,"filename":"Guild.js","path":"src/structures"},"order":32},{"id":"Guild#setRegion","longname":"Guild#setRegion","name":"setRegion","scope":"instance","kind":"function","description":"Edit the region of the Guild.","memberof":"Guild","params":[{"type":{"names":["Region"]},"description":"the new region of the guild.","name":"region"}],"examples":["// edit the guild region\nguild.setRegion('london')\n .then(updated => console.log(`Updated guild region to ${guild.region}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":385,"filename":"Guild.js","path":"src/structures"},"order":33},{"id":"Guild#setVerificationLevel","longname":"Guild#setVerificationLevel","name":"setVerificationLevel","scope":"instance","kind":"function","description":"Edit the verification level of the Guild.","memberof":"Guild","params":[{"type":{"names":["VerificationLevel"]},"description":"the new verification level of the guild.","name":"verificationLevel"}],"examples":["// edit the guild verification level\nguild.setVerificationLevel(1)\n .then(updated => console.log(`Updated guild verification level to ${guild.verificationLevel}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":399,"filename":"Guild.js","path":"src/structures"},"order":34},{"id":"Guild#setAFKChannel","longname":"Guild#setAFKChannel","name":"setAFKChannel","scope":"instance","kind":"function","description":"Edit the AFK channel of the Guild.","memberof":"Guild","params":[{"type":{"names":["GuildChannelResolvable"]},"description":"the new AFK channel.","name":"afkChannel"}],"examples":["// edit the guild AFK channel\nguild.setAFKChannel(channel)\n .then(updated => console.log(`Updated guild AFK channel to ${guild.afkChannel}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":413,"filename":"Guild.js","path":"src/structures"},"order":35},{"id":"Guild#setAFKTimeout","longname":"Guild#setAFKTimeout","name":"setAFKTimeout","scope":"instance","kind":"function","description":"Edit the AFK timeout of the Guild.","memberof":"Guild","params":[{"type":{"names":["Number"]},"description":"the time in seconds that a user must be idle to be considered AFK.","name":"afkTimeout"}],"examples":["// edit the guild AFK channel\nguild.setAFKTimeout(60)\n .then(updated => console.log(`Updated guild AFK timeout to ${guild.afkTimeout}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":427,"filename":"Guild.js","path":"src/structures"},"order":36},{"id":"Guild#setIcon","longname":"Guild#setIcon","name":"setIcon","scope":"instance","kind":"function","description":"Set a new Guild Icon.","memberof":"Guild","params":[{"type":{"names":["Base64Resolvable"]},"description":"the new icon of the guild.","name":"icon"}],"examples":["// edit the guild icon\nguild.setIcon(fs.readFileSync('./icon.png'))\n .then(updated => console.log('Updated the guild icon'))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":441,"filename":"Guild.js","path":"src/structures"},"order":37},{"id":"Guild#setOwner","longname":"Guild#setOwner","name":"setOwner","scope":"instance","kind":"function","description":"Sets a new owner of the Guild.","memberof":"Guild","params":[{"type":{"names":["GuildMemberResolvable"]},"description":"the new owner of the Guild.","name":"owner"}],"examples":["// edit the guild owner\nguild.setOwner(guilds.members[0])\n .then(updated => console.log(`Updated the guild owner to ${updated.owner.username}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":455,"filename":"Guild.js","path":"src/structures"},"order":38},{"id":"Guild#setSplash","longname":"Guild#setSplash","name":"setSplash","scope":"instance","kind":"function","description":"Set a new Guild Splash Logo.","memberof":"Guild","params":[{"type":{"names":["Base64Resolvable"]},"description":"the new splash screen of the guild.","name":"splash"}],"examples":["// edit the guild splash\nguild.setIcon(fs.readFileSync('./splash.png'))\n .then(updated => console.log('Updated the guild splash'))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":469,"filename":"Guild.js","path":"src/structures"},"order":39}],"properties":[{"id":"Guild#client","longname":"Guild#client","name":"client","scope":"instance","kind":"member","description":"The Client that created the instance of the the Guild.","memberof":"Guild","type":{"names":["Client"]},"meta":{"lineno":31,"filename":"Guild.js","path":"src/structures"},"order":4},{"id":"Guild#store","longname":"Guild#store","name":"store","scope":"instance","kind":"member","description":"The data store of the Guild.","memberof":"Guild","type":{"names":["GuildDataStore"]},"meta":{"lineno":37,"filename":"Guild.js","path":"src/structures"},"order":5},{"id":"Guild#available","longname":"Guild#available","name":"available","scope":"instance","kind":"member","description":"Whether the Guild is available to access. If it is not available, it indicates a server outage.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":48,"filename":"Guild.js","path":"src/structures"},"order":6},{"id":"Guild#id","longname":"Guild#id","name":"id","scope":"instance","kind":"member","description":"The Unique ID of the Guild, useful for comparisons.","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":53,"filename":"Guild.js","path":"src/structures"},"order":7},{"id":"Guild#splash","longname":"Guild#splash","name":"splash","scope":"instance","kind":"member","description":"The hash of the guild splash image, or null if no splash (VIP only)","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":169,"filename":"Guild.js","path":"src/structures"},"order":12},{"id":"Guild#region","longname":"Guild#region","name":"region","scope":"instance","kind":"member","description":"The region the guild is located in","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":174,"filename":"Guild.js","path":"src/structures"},"order":13},{"id":"Guild#name","longname":"Guild#name","name":"name","scope":"instance","kind":"member","description":"The name of the guild","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":179,"filename":"Guild.js","path":"src/structures"},"order":14},{"id":"Guild#memberCount","longname":"Guild#memberCount","name":"memberCount","scope":"instance","kind":"member","description":"The amount of initial members in the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":184,"filename":"Guild.js","path":"src/structures"},"order":15},{"id":"Guild#large","longname":"Guild#large","name":"large","scope":"instance","kind":"member","description":"Whether the guild is \"large\" (has more than 250 members)","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":189,"filename":"Guild.js","path":"src/structures"},"order":16},{"id":"Guild#joinDate","longname":"Guild#joinDate","name":"joinDate","scope":"instance","kind":"member","description":"The date at which the logged-in client joined the guild.","memberof":"Guild","type":{"names":["Date"]},"meta":{"lineno":194,"filename":"Guild.js","path":"src/structures"},"order":17},{"id":"Guild#icon","longname":"Guild#icon","name":"icon","scope":"instance","kind":"member","description":"The hash of the guild icon, or null if there is no icon.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":199,"filename":"Guild.js","path":"src/structures"},"order":18},{"id":"Guild#features","longname":"Guild#features","name":"features","scope":"instance","kind":"member","description":"An array of guild features.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":204,"filename":"Guild.js","path":"src/structures"},"order":19},{"id":"Guild#emojis","longname":"Guild#emojis","name":"emojis","scope":"instance","kind":"member","description":"An array of guild emojis.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":209,"filename":"Guild.js","path":"src/structures"},"order":20},{"id":"Guild#afkTimeout","longname":"Guild#afkTimeout","name":"afkTimeout","scope":"instance","kind":"member","description":"The time in seconds before a user is counted as \"away from keyboard\".","memberof":"Guild","type":{"names":["Number"]},"nullable":true,"meta":{"lineno":214,"filename":"Guild.js","path":"src/structures"},"order":21},{"id":"Guild#afkChannelID","longname":"Guild#afkChannelID","name":"afkChannelID","scope":"instance","kind":"member","description":"The ID of the voice channel where AFK members are moved.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":219,"filename":"Guild.js","path":"src/structures"},"order":22},{"id":"Guild#embedEnabled","longname":"Guild#embedEnabled","name":"embedEnabled","scope":"instance","kind":"member","description":"Whether embedded images are enabled on this guild.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":224,"filename":"Guild.js","path":"src/structures"},"order":23},{"id":"Guild#verificationLevel","longname":"Guild#verificationLevel","name":"verificationLevel","scope":"instance","kind":"member","description":"The verification level of the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":229,"filename":"Guild.js","path":"src/structures"},"order":24},{"id":"Guild#owner","longname":"Guild#owner","name":"owner","scope":"instance","kind":"member","description":"The owner of the guild","memberof":"Guild","type":{"names":["User"]},"meta":{"lineno":243,"filename":"Guild.js","path":"src/structures"},"order":25},{"id":"Guild#embedChannel","longname":"Guild#embedChannel","name":"embedChannel","scope":"instance","kind":"member","description":"The embed channel of the Guild.","memberof":"Guild","type":{"names":["GuildChannel"]},"meta":{"lineno":256,"filename":"Guild.js","path":"src/structures"},"order":26},{"id":"Guild#channels","longname":"Guild#channels","name":"channels","scope":"instance","kind":"member","description":"The channels in the guild.","memberof":"Guild","params":[],"type":{"names":["Array."]},"readonly":true,"meta":{"lineno":478,"filename":"Guild.js","path":"src/structures"},"order":40},{"id":"Guild#$channels","longname":"Guild#$channels","name":"$channels","scope":"instance","kind":"member","description":"A dictionary mapping the IDs of channels in this guild to the channel itself. If you want to find a channel\nin the guild by ID, use `guild.$channels[id]` rather than filtering `guild.channels` as it is much more efficient.","memberof":"Guild","params":[],"type":{"names":["Object."]},"readonly":true,"meta":{"lineno":486,"filename":"Guild.js","path":"src/structures"},"order":41},{"id":"Guild#roles","longname":"Guild#roles","name":"roles","scope":"instance","kind":"member","description":"The roles in the guild.","memberof":"Guild","params":[],"type":{"names":["Array."]},"readonly":true,"meta":{"lineno":493,"filename":"Guild.js","path":"src/structures"},"order":42},{"id":"Guild#$roles","longname":"Guild#$roles","name":"$roles","scope":"instance","kind":"member","description":"A dictionary mapping the IDs of roles in this guild to the role itself. If you want to find a role\nin the guild by ID, use `guild.$roles[id]` rather than filtering `guild.roles` as it is much more efficient.","memberof":"Guild","params":[],"type":{"names":["Object."]},"readonly":true,"meta":{"lineno":501,"filename":"Guild.js","path":"src/structures"},"order":43},{"id":"Guild#members","longname":"Guild#members","name":"members","scope":"instance","kind":"member","description":"The members of the guild.","memberof":"Guild","params":[],"type":{"names":["Array."]},"readonly":true,"meta":{"lineno":508,"filename":"Guild.js","path":"src/structures"},"order":44},{"id":"Guild#$members","longname":"Guild#$members","name":"$members","scope":"instance","kind":"member","description":"A dictionary mapping the IDs of members in this guild to the member object itself. If you want to find a member\nin the guild by ID, use `guild.$members[id]` rather than filtering `guild.members` as it is much more efficient.","memberof":"Guild","params":[],"type":{"names":["Object."]},"readonly":true,"meta":{"lineno":516,"filename":"Guild.js","path":"src/structures"},"order":45}],"events":[]},"Message":{"meta":{"id":"Message","longname":"Message","name":"Message","scope":"global","kind":"class","description":"Represents a Message on Discord","meta":{"lineno":4,"filename":"Message.js","path":"src/structures"},"order":46},"functions":[],"properties":[],"events":[]},"TextChannel":{"meta":{"id":"TextChannel","longname":"TextChannel","name":"TextChannel","scope":"global","kind":"class","description":"Represents a Server Text Channel on Discord.","meta":{"lineno":8,"filename":"TextChannel.js","path":"src/structures"},"order":47},"functions":[],"properties":[],"events":[]},"User":{"meta":{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":48},"functions":[{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":64,"filename":"User.js","path":"src/structures"},"order":56},{"id":"User#equals","longname":"User#equals","name":"equals","scope":"instance","kind":"function","description":"Checks if the user is equal to another. It compares username, ID, discriminator, status and the game being played.\nIt is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties.","memberof":"User","params":[{"type":{"names":["User"]},"description":"the user to compare","name":"user"}],"returns":[{"description":"Boolean"}],"meta":{"lineno":74,"filename":"User.js","path":"src/structures"},"order":57}],"properties":[{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":49},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":50},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":51},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":52},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":53},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":54},{"id":"User#game","longname":"User#game","name":"game","scope":"instance","kind":"member","description":"The game that the user is playing, `null` if they aren't playing a game.","memberof":"User","type":{"names":["String"]},"meta":{"lineno":53,"filename":"User.js","path":"src/structures"},"order":55}],"events":[]},"VoiceChannel":{"meta":{"id":"VoiceChannel","longname":"VoiceChannel","name":"VoiceChannel","scope":"global","kind":"class","description":"Represents a Server Voice Channel on Discord.","meta":{"lineno":7,"filename":"VoiceChannel.js","path":"src/structures"},"order":58},"functions":[],"properties":[],"events":[]}}}}
\ No newline at end of file
diff --git a/src/structures/Guild.js b/src/structures/Guild.js
index 52a1cc9c8..88cae06ae 100644
--- a/src/structures/Guild.js
+++ b/src/structures/Guild.js
@@ -477,14 +477,42 @@ class Guild {
*/
get channels() { return this.store.getAsArray('channels'); }
+ /**
+ * A dictionary mapping the IDs of channels in this guild to the channel itself. If you want to find a channel
+ * in the guild by ID, use `guild.$channels[id]` rather than filtering `guild.channels` as it is much more efficient.
+ * @readonly
+ * @type {Object}
+ */
get $channels() { return this.store.data.channels; }
+ /**
+ * The roles in the guild.
+ * @type {Array}
+ * @readonly
+ */
get roles() { return this.store.getAsArray('roles'); }
+ /**
+ * A dictionary mapping the IDs of roles in this guild to the role itself. If you want to find a role
+ * in the guild by ID, use `guild.$roles[id]` rather than filtering `guild.roles` as it is much more efficient.
+ * @readonly
+ * @type {Object}
+ */
get $roles() { return this.store.data.roles; }
+ /**
+ * The members of the guild.
+ * @type {Array}
+ * @readonly
+ */
get members() { return this.store.getAsArray('members'); }
+ /**
+ * A dictionary mapping the IDs of members in this guild to the member object itself. If you want to find a member
+ * in the guild by ID, use `guild.$members[id]` rather than filtering `guild.members` as it is much more efficient.
+ * @readonly
+ * @type {Object}
+ */
get $members() { return this.store.data.members; }
}
From 614c488f966d29d1a1bb1e86845c1bff656e7ddb Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Wed, 17 Aug 2016 19:15:33 +0100
Subject: [PATCH 063/324] work on docs
---
docs/docs.json | 2 +-
src/structures/Message.js | 82 +++++++++++++++++++++++++++++++++++++++
2 files changed, 83 insertions(+), 1 deletion(-)
diff --git a/docs/docs.json b/docs/docs.json
index c24d06147..db14380bb 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -1 +1 @@
-{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["// log the client in using a token\nconst token = 'my token';\nclient.login(token);","// log the client in using email and password\nconst email = 'user@email.com';\nconst password = 'supersecret123';\nclient.login(email, password);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":47,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"type":{"names":["ClientUser"]},"meta":{"lineno":60,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"Guild":{"meta":{"id":"Guild","longname":"Guild","name":"Guild","scope":"global","kind":"class","description":"Represents a Guild (or a Server) on Discord.","meta":{"lineno":25,"filename":"Guild.js","path":"src/structures"},"order":3},"functions":[{"id":"Guild#toString","longname":"Guild#toString","name":"toString","scope":"instance","kind":"function","description":"When concatenated with a String, this automatically concatenates the Guild's name instead of the Guild object.","memberof":"Guild","params":[],"examples":["// logs: Hello from My Guild!\nconsole.log(`Hello from ${guild}!`);","// logs: Hello from My Guild!\nconsole.log(`Hello from ' + guild + '!');"],"returns":[{"type":{"names":["String"]}}],"meta":{"lineno":97,"filename":"Guild.js","path":"src/structures"},"order":8},{"id":"Guild#kick","longname":"Guild#kick","name":"kick","scope":"instance","kind":"function","description":"Tries to kick a member from the guild.","memberof":"Guild","params":[{"type":{"names":["GuildMemberResolvable"]},"description":"the member to kick","name":"member"}],"examples":["// kicks a member from a guild:\nguild.kick(message.author)\n .then(member => console.log(`Kicked ${member}`))\n .catch(error => console.log(error));"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":111,"filename":"Guild.js","path":"src/structures"},"order":9},{"id":"Guild#member","longname":"Guild#member","name":"member","scope":"instance","kind":"function","description":"Returns the GuildMember form of a User object, if the User is present in the guild.","memberof":"Guild","params":[{"type":{"names":["UserResolvable"]},"description":"the user that you want to obtain the GuildMember of.","name":"user"}],"examples":["// get the guild member of a user\nconst member = guild.member(message.author);"],"returns":[{"type":{"names":["GuildMember","null"]}}],"meta":{"lineno":123,"filename":"Guild.js","path":"src/structures"},"order":10},{"id":"Guild#equals","longname":"Guild#equals","name":"equals","scope":"instance","kind":"function","description":"Whether this Guild equals another Guild. It compares all properties, so for most operations\nit is advisable to just compare `guild.id === guild2.id` as it is much faster and is often\nwhat most users need.","memberof":"Guild","params":[{"type":{"names":["Guild"]},"description":"the guild to compare","name":"guild"}],"returns":[{"type":{"names":["Boolean"]}}],"meta":{"lineno":134,"filename":"Guild.js","path":"src/structures"},"order":11},{"id":"Guild#createChannel","longname":"Guild#createChannel","name":"createChannel","scope":"instance","kind":"function","description":"Creates a new Channel in the Guild.","memberof":"Guild","params":[{"type":{"names":["String"]},"description":"the name of the new channel.","name":"name"},{"type":{"names":["any"]},"description":"the type of the new channel, either `text` or `voice`.","name":"type"}],"examples":["// create a new text channel\nguild.createChannel('new general', 'text')\n .then(channel => console.log(`Created new channel ${channel}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise.<(TextChannel|VoiceChannel), Error>"]}}],"meta":{"lineno":301,"filename":"Guild.js","path":"src/structures"},"order":27},{"id":"Guild#createRole","longname":"Guild#createRole","name":"createRole","scope":"instance","kind":"function","description":"Creates a new role in the guild, as of now this is just a blank role.","memberof":"Guild","params":[],"examples":["// create a new role\nguild.createRole()\n .then(role => console.log(`Created role ${role}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":314,"filename":"Guild.js","path":"src/structures"},"order":28},{"id":"Guild#leave","longname":"Guild#leave","name":"leave","scope":"instance","kind":"function","description":"Causes the Client to leave the guild.","memberof":"Guild","params":[],"examples":["// leave a guild\nguild.leave()\n .then(g => console.log(`Left the guild ${g}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":327,"filename":"Guild.js","path":"src/structures"},"order":29},{"id":"Guild#delete","longname":"Guild#delete","name":"delete","scope":"instance","kind":"function","description":"Causes the Client to delete the guild.","memberof":"Guild","params":[],"examples":["// delete a guild\nguild.delete()\n .then(g => console.log(`Deleted the guild ${g}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":340,"filename":"Guild.js","path":"src/structures"},"order":30},{"id":"Guild#edit","longname":"Guild#edit","name":"edit","scope":"instance","kind":"function","description":"Updates the Guild with new information - e.g. a new name.","memberof":"Guild","params":[{"type":{"names":["GuildEditData"]},"description":"the data to update the guild with.","name":"data"}],"examples":["// set the guild name and region\nguild.edit({\n name: 'Discord Guild',\n region: 'london',\n})\n.then(updated => console.log(`New guild name ${updated.name} in region ${updated.region}`))\n.catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":357,"filename":"Guild.js","path":"src/structures"},"order":31},{"id":"Guild#setName","longname":"Guild#setName","name":"setName","scope":"instance","kind":"function","description":"Edit the name of the Guild.","memberof":"Guild","params":[{"type":{"names":["String"]},"description":"the new name of the Guild.","name":"name"}],"examples":["// edit the guild name\nguild.setName('Discord Guild')\n .then(updated => console.log(`Updated guild name to ${guild.name}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":371,"filename":"Guild.js","path":"src/structures"},"order":32},{"id":"Guild#setRegion","longname":"Guild#setRegion","name":"setRegion","scope":"instance","kind":"function","description":"Edit the region of the Guild.","memberof":"Guild","params":[{"type":{"names":["Region"]},"description":"the new region of the guild.","name":"region"}],"examples":["// edit the guild region\nguild.setRegion('london')\n .then(updated => console.log(`Updated guild region to ${guild.region}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":385,"filename":"Guild.js","path":"src/structures"},"order":33},{"id":"Guild#setVerificationLevel","longname":"Guild#setVerificationLevel","name":"setVerificationLevel","scope":"instance","kind":"function","description":"Edit the verification level of the Guild.","memberof":"Guild","params":[{"type":{"names":["VerificationLevel"]},"description":"the new verification level of the guild.","name":"verificationLevel"}],"examples":["// edit the guild verification level\nguild.setVerificationLevel(1)\n .then(updated => console.log(`Updated guild verification level to ${guild.verificationLevel}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":399,"filename":"Guild.js","path":"src/structures"},"order":34},{"id":"Guild#setAFKChannel","longname":"Guild#setAFKChannel","name":"setAFKChannel","scope":"instance","kind":"function","description":"Edit the AFK channel of the Guild.","memberof":"Guild","params":[{"type":{"names":["GuildChannelResolvable"]},"description":"the new AFK channel.","name":"afkChannel"}],"examples":["// edit the guild AFK channel\nguild.setAFKChannel(channel)\n .then(updated => console.log(`Updated guild AFK channel to ${guild.afkChannel}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":413,"filename":"Guild.js","path":"src/structures"},"order":35},{"id":"Guild#setAFKTimeout","longname":"Guild#setAFKTimeout","name":"setAFKTimeout","scope":"instance","kind":"function","description":"Edit the AFK timeout of the Guild.","memberof":"Guild","params":[{"type":{"names":["Number"]},"description":"the time in seconds that a user must be idle to be considered AFK.","name":"afkTimeout"}],"examples":["// edit the guild AFK channel\nguild.setAFKTimeout(60)\n .then(updated => console.log(`Updated guild AFK timeout to ${guild.afkTimeout}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":427,"filename":"Guild.js","path":"src/structures"},"order":36},{"id":"Guild#setIcon","longname":"Guild#setIcon","name":"setIcon","scope":"instance","kind":"function","description":"Set a new Guild Icon.","memberof":"Guild","params":[{"type":{"names":["Base64Resolvable"]},"description":"the new icon of the guild.","name":"icon"}],"examples":["// edit the guild icon\nguild.setIcon(fs.readFileSync('./icon.png'))\n .then(updated => console.log('Updated the guild icon'))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":441,"filename":"Guild.js","path":"src/structures"},"order":37},{"id":"Guild#setOwner","longname":"Guild#setOwner","name":"setOwner","scope":"instance","kind":"function","description":"Sets a new owner of the Guild.","memberof":"Guild","params":[{"type":{"names":["GuildMemberResolvable"]},"description":"the new owner of the Guild.","name":"owner"}],"examples":["// edit the guild owner\nguild.setOwner(guilds.members[0])\n .then(updated => console.log(`Updated the guild owner to ${updated.owner.username}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":455,"filename":"Guild.js","path":"src/structures"},"order":38},{"id":"Guild#setSplash","longname":"Guild#setSplash","name":"setSplash","scope":"instance","kind":"function","description":"Set a new Guild Splash Logo.","memberof":"Guild","params":[{"type":{"names":["Base64Resolvable"]},"description":"the new splash screen of the guild.","name":"splash"}],"examples":["// edit the guild splash\nguild.setIcon(fs.readFileSync('./splash.png'))\n .then(updated => console.log('Updated the guild splash'))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":469,"filename":"Guild.js","path":"src/structures"},"order":39}],"properties":[{"id":"Guild#client","longname":"Guild#client","name":"client","scope":"instance","kind":"member","description":"The Client that created the instance of the the Guild.","memberof":"Guild","type":{"names":["Client"]},"meta":{"lineno":31,"filename":"Guild.js","path":"src/structures"},"order":4},{"id":"Guild#store","longname":"Guild#store","name":"store","scope":"instance","kind":"member","description":"The data store of the Guild.","memberof":"Guild","type":{"names":["GuildDataStore"]},"meta":{"lineno":37,"filename":"Guild.js","path":"src/structures"},"order":5},{"id":"Guild#available","longname":"Guild#available","name":"available","scope":"instance","kind":"member","description":"Whether the Guild is available to access. If it is not available, it indicates a server outage.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":48,"filename":"Guild.js","path":"src/structures"},"order":6},{"id":"Guild#id","longname":"Guild#id","name":"id","scope":"instance","kind":"member","description":"The Unique ID of the Guild, useful for comparisons.","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":53,"filename":"Guild.js","path":"src/structures"},"order":7},{"id":"Guild#splash","longname":"Guild#splash","name":"splash","scope":"instance","kind":"member","description":"The hash of the guild splash image, or null if no splash (VIP only)","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":169,"filename":"Guild.js","path":"src/structures"},"order":12},{"id":"Guild#region","longname":"Guild#region","name":"region","scope":"instance","kind":"member","description":"The region the guild is located in","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":174,"filename":"Guild.js","path":"src/structures"},"order":13},{"id":"Guild#name","longname":"Guild#name","name":"name","scope":"instance","kind":"member","description":"The name of the guild","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":179,"filename":"Guild.js","path":"src/structures"},"order":14},{"id":"Guild#memberCount","longname":"Guild#memberCount","name":"memberCount","scope":"instance","kind":"member","description":"The amount of initial members in the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":184,"filename":"Guild.js","path":"src/structures"},"order":15},{"id":"Guild#large","longname":"Guild#large","name":"large","scope":"instance","kind":"member","description":"Whether the guild is \"large\" (has more than 250 members)","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":189,"filename":"Guild.js","path":"src/structures"},"order":16},{"id":"Guild#joinDate","longname":"Guild#joinDate","name":"joinDate","scope":"instance","kind":"member","description":"The date at which the logged-in client joined the guild.","memberof":"Guild","type":{"names":["Date"]},"meta":{"lineno":194,"filename":"Guild.js","path":"src/structures"},"order":17},{"id":"Guild#icon","longname":"Guild#icon","name":"icon","scope":"instance","kind":"member","description":"The hash of the guild icon, or null if there is no icon.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":199,"filename":"Guild.js","path":"src/structures"},"order":18},{"id":"Guild#features","longname":"Guild#features","name":"features","scope":"instance","kind":"member","description":"An array of guild features.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":204,"filename":"Guild.js","path":"src/structures"},"order":19},{"id":"Guild#emojis","longname":"Guild#emojis","name":"emojis","scope":"instance","kind":"member","description":"An array of guild emojis.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":209,"filename":"Guild.js","path":"src/structures"},"order":20},{"id":"Guild#afkTimeout","longname":"Guild#afkTimeout","name":"afkTimeout","scope":"instance","kind":"member","description":"The time in seconds before a user is counted as \"away from keyboard\".","memberof":"Guild","type":{"names":["Number"]},"nullable":true,"meta":{"lineno":214,"filename":"Guild.js","path":"src/structures"},"order":21},{"id":"Guild#afkChannelID","longname":"Guild#afkChannelID","name":"afkChannelID","scope":"instance","kind":"member","description":"The ID of the voice channel where AFK members are moved.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":219,"filename":"Guild.js","path":"src/structures"},"order":22},{"id":"Guild#embedEnabled","longname":"Guild#embedEnabled","name":"embedEnabled","scope":"instance","kind":"member","description":"Whether embedded images are enabled on this guild.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":224,"filename":"Guild.js","path":"src/structures"},"order":23},{"id":"Guild#verificationLevel","longname":"Guild#verificationLevel","name":"verificationLevel","scope":"instance","kind":"member","description":"The verification level of the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":229,"filename":"Guild.js","path":"src/structures"},"order":24},{"id":"Guild#owner","longname":"Guild#owner","name":"owner","scope":"instance","kind":"member","description":"The owner of the guild","memberof":"Guild","type":{"names":["User"]},"meta":{"lineno":243,"filename":"Guild.js","path":"src/structures"},"order":25},{"id":"Guild#embedChannel","longname":"Guild#embedChannel","name":"embedChannel","scope":"instance","kind":"member","description":"The embed channel of the Guild.","memberof":"Guild","type":{"names":["GuildChannel"]},"meta":{"lineno":256,"filename":"Guild.js","path":"src/structures"},"order":26},{"id":"Guild#channels","longname":"Guild#channels","name":"channels","scope":"instance","kind":"member","description":"The channels in the guild.","memberof":"Guild","params":[],"type":{"names":["Array."]},"readonly":true,"meta":{"lineno":478,"filename":"Guild.js","path":"src/structures"},"order":40},{"id":"Guild#$channels","longname":"Guild#$channels","name":"$channels","scope":"instance","kind":"member","description":"A dictionary mapping the IDs of channels in this guild to the channel itself. If you want to find a channel\nin the guild by ID, use `guild.$channels[id]` rather than filtering `guild.channels` as it is much more efficient.","memberof":"Guild","params":[],"type":{"names":["Object."]},"readonly":true,"meta":{"lineno":486,"filename":"Guild.js","path":"src/structures"},"order":41},{"id":"Guild#roles","longname":"Guild#roles","name":"roles","scope":"instance","kind":"member","description":"The roles in the guild.","memberof":"Guild","params":[],"type":{"names":["Array."]},"readonly":true,"meta":{"lineno":493,"filename":"Guild.js","path":"src/structures"},"order":42},{"id":"Guild#$roles","longname":"Guild#$roles","name":"$roles","scope":"instance","kind":"member","description":"A dictionary mapping the IDs of roles in this guild to the role itself. If you want to find a role\nin the guild by ID, use `guild.$roles[id]` rather than filtering `guild.roles` as it is much more efficient.","memberof":"Guild","params":[],"type":{"names":["Object."]},"readonly":true,"meta":{"lineno":501,"filename":"Guild.js","path":"src/structures"},"order":43},{"id":"Guild#members","longname":"Guild#members","name":"members","scope":"instance","kind":"member","description":"The members of the guild.","memberof":"Guild","params":[],"type":{"names":["Array."]},"readonly":true,"meta":{"lineno":508,"filename":"Guild.js","path":"src/structures"},"order":44},{"id":"Guild#$members","longname":"Guild#$members","name":"$members","scope":"instance","kind":"member","description":"A dictionary mapping the IDs of members in this guild to the member object itself. If you want to find a member\nin the guild by ID, use `guild.$members[id]` rather than filtering `guild.members` as it is much more efficient.","memberof":"Guild","params":[],"type":{"names":["Object."]},"readonly":true,"meta":{"lineno":516,"filename":"Guild.js","path":"src/structures"},"order":45}],"events":[]},"Message":{"meta":{"id":"Message","longname":"Message","name":"Message","scope":"global","kind":"class","description":"Represents a Message on Discord","meta":{"lineno":4,"filename":"Message.js","path":"src/structures"},"order":46},"functions":[],"properties":[],"events":[]},"TextChannel":{"meta":{"id":"TextChannel","longname":"TextChannel","name":"TextChannel","scope":"global","kind":"class","description":"Represents a Server Text Channel on Discord.","meta":{"lineno":8,"filename":"TextChannel.js","path":"src/structures"},"order":47},"functions":[],"properties":[],"events":[]},"User":{"meta":{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":48},"functions":[{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":64,"filename":"User.js","path":"src/structures"},"order":56},{"id":"User#equals","longname":"User#equals","name":"equals","scope":"instance","kind":"function","description":"Checks if the user is equal to another. It compares username, ID, discriminator, status and the game being played.\nIt is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties.","memberof":"User","params":[{"type":{"names":["User"]},"description":"the user to compare","name":"user"}],"returns":[{"description":"Boolean"}],"meta":{"lineno":74,"filename":"User.js","path":"src/structures"},"order":57}],"properties":[{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":49},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":50},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":51},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":52},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":53},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":54},{"id":"User#game","longname":"User#game","name":"game","scope":"instance","kind":"member","description":"The game that the user is playing, `null` if they aren't playing a game.","memberof":"User","type":{"names":["String"]},"meta":{"lineno":53,"filename":"User.js","path":"src/structures"},"order":55}],"events":[]},"VoiceChannel":{"meta":{"id":"VoiceChannel","longname":"VoiceChannel","name":"VoiceChannel","scope":"global","kind":"class","description":"Represents a Server Voice Channel on Discord.","meta":{"lineno":7,"filename":"VoiceChannel.js","path":"src/structures"},"order":58},"functions":[],"properties":[],"events":[]}}}}
\ No newline at end of file
+{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["// log the client in using a token\nconst token = 'my token';\nclient.login(token);","// log the client in using email and password\nconst email = 'user@email.com';\nconst password = 'supersecret123';\nclient.login(email, password);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":47,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"type":{"names":["ClientUser"]},"meta":{"lineno":60,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"Guild":{"meta":{"id":"Guild","longname":"Guild","name":"Guild","scope":"global","kind":"class","description":"Represents a Guild (or a Server) on Discord.","meta":{"lineno":25,"filename":"Guild.js","path":"src/structures"},"order":3},"functions":[{"id":"Guild#toString","longname":"Guild#toString","name":"toString","scope":"instance","kind":"function","description":"When concatenated with a String, this automatically concatenates the Guild's name instead of the Guild object.","memberof":"Guild","params":[],"examples":["// logs: Hello from My Guild!\nconsole.log(`Hello from ${guild}!`);","// logs: Hello from My Guild!\nconsole.log(`Hello from ' + guild + '!');"],"returns":[{"type":{"names":["String"]}}],"meta":{"lineno":97,"filename":"Guild.js","path":"src/structures"},"order":8},{"id":"Guild#kick","longname":"Guild#kick","name":"kick","scope":"instance","kind":"function","description":"Tries to kick a member from the guild.","memberof":"Guild","params":[{"type":{"names":["GuildMemberResolvable"]},"description":"the member to kick","name":"member"}],"examples":["// kicks a member from a guild:\nguild.kick(message.author)\n .then(member => console.log(`Kicked ${member}`))\n .catch(error => console.log(error));"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":111,"filename":"Guild.js","path":"src/structures"},"order":9},{"id":"Guild#member","longname":"Guild#member","name":"member","scope":"instance","kind":"function","description":"Returns the GuildMember form of a User object, if the User is present in the guild.","memberof":"Guild","params":[{"type":{"names":["UserResolvable"]},"description":"the user that you want to obtain the GuildMember of.","name":"user"}],"examples":["// get the guild member of a user\nconst member = guild.member(message.author);"],"returns":[{"type":{"names":["GuildMember","null"]}}],"meta":{"lineno":123,"filename":"Guild.js","path":"src/structures"},"order":10},{"id":"Guild#equals","longname":"Guild#equals","name":"equals","scope":"instance","kind":"function","description":"Whether this Guild equals another Guild. It compares all properties, so for most operations\nit is advisable to just compare `guild.id === guild2.id` as it is much faster and is often\nwhat most users need.","memberof":"Guild","params":[{"type":{"names":["Guild"]},"description":"the guild to compare","name":"guild"}],"returns":[{"type":{"names":["Boolean"]}}],"meta":{"lineno":134,"filename":"Guild.js","path":"src/structures"},"order":11},{"id":"Guild#createChannel","longname":"Guild#createChannel","name":"createChannel","scope":"instance","kind":"function","description":"Creates a new Channel in the Guild.","memberof":"Guild","params":[{"type":{"names":["String"]},"description":"the name of the new channel.","name":"name"},{"type":{"names":["any"]},"description":"the type of the new channel, either `text` or `voice`.","name":"type"}],"examples":["// create a new text channel\nguild.createChannel('new general', 'text')\n .then(channel => console.log(`Created new channel ${channel}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise.<(TextChannel|VoiceChannel), Error>"]}}],"meta":{"lineno":301,"filename":"Guild.js","path":"src/structures"},"order":27},{"id":"Guild#createRole","longname":"Guild#createRole","name":"createRole","scope":"instance","kind":"function","description":"Creates a new role in the guild, as of now this is just a blank role.","memberof":"Guild","params":[],"examples":["// create a new role\nguild.createRole()\n .then(role => console.log(`Created role ${role}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":314,"filename":"Guild.js","path":"src/structures"},"order":28},{"id":"Guild#leave","longname":"Guild#leave","name":"leave","scope":"instance","kind":"function","description":"Causes the Client to leave the guild.","memberof":"Guild","params":[],"examples":["// leave a guild\nguild.leave()\n .then(g => console.log(`Left the guild ${g}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":327,"filename":"Guild.js","path":"src/structures"},"order":29},{"id":"Guild#delete","longname":"Guild#delete","name":"delete","scope":"instance","kind":"function","description":"Causes the Client to delete the guild.","memberof":"Guild","params":[],"examples":["// delete a guild\nguild.delete()\n .then(g => console.log(`Deleted the guild ${g}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":340,"filename":"Guild.js","path":"src/structures"},"order":30},{"id":"Guild#edit","longname":"Guild#edit","name":"edit","scope":"instance","kind":"function","description":"Updates the Guild with new information - e.g. a new name.","memberof":"Guild","params":[{"type":{"names":["GuildEditData"]},"description":"the data to update the guild with.","name":"data"}],"examples":["// set the guild name and region\nguild.edit({\n name: 'Discord Guild',\n region: 'london',\n})\n.then(updated => console.log(`New guild name ${updated.name} in region ${updated.region}`))\n.catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":357,"filename":"Guild.js","path":"src/structures"},"order":31},{"id":"Guild#setName","longname":"Guild#setName","name":"setName","scope":"instance","kind":"function","description":"Edit the name of the Guild.","memberof":"Guild","params":[{"type":{"names":["String"]},"description":"the new name of the Guild.","name":"name"}],"examples":["// edit the guild name\nguild.setName('Discord Guild')\n .then(updated => console.log(`Updated guild name to ${guild.name}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":371,"filename":"Guild.js","path":"src/structures"},"order":32},{"id":"Guild#setRegion","longname":"Guild#setRegion","name":"setRegion","scope":"instance","kind":"function","description":"Edit the region of the Guild.","memberof":"Guild","params":[{"type":{"names":["Region"]},"description":"the new region of the guild.","name":"region"}],"examples":["// edit the guild region\nguild.setRegion('london')\n .then(updated => console.log(`Updated guild region to ${guild.region}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":385,"filename":"Guild.js","path":"src/structures"},"order":33},{"id":"Guild#setVerificationLevel","longname":"Guild#setVerificationLevel","name":"setVerificationLevel","scope":"instance","kind":"function","description":"Edit the verification level of the Guild.","memberof":"Guild","params":[{"type":{"names":["VerificationLevel"]},"description":"the new verification level of the guild.","name":"verificationLevel"}],"examples":["// edit the guild verification level\nguild.setVerificationLevel(1)\n .then(updated => console.log(`Updated guild verification level to ${guild.verificationLevel}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":399,"filename":"Guild.js","path":"src/structures"},"order":34},{"id":"Guild#setAFKChannel","longname":"Guild#setAFKChannel","name":"setAFKChannel","scope":"instance","kind":"function","description":"Edit the AFK channel of the Guild.","memberof":"Guild","params":[{"type":{"names":["GuildChannelResolvable"]},"description":"the new AFK channel.","name":"afkChannel"}],"examples":["// edit the guild AFK channel\nguild.setAFKChannel(channel)\n .then(updated => console.log(`Updated guild AFK channel to ${guild.afkChannel}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":413,"filename":"Guild.js","path":"src/structures"},"order":35},{"id":"Guild#setAFKTimeout","longname":"Guild#setAFKTimeout","name":"setAFKTimeout","scope":"instance","kind":"function","description":"Edit the AFK timeout of the Guild.","memberof":"Guild","params":[{"type":{"names":["Number"]},"description":"the time in seconds that a user must be idle to be considered AFK.","name":"afkTimeout"}],"examples":["// edit the guild AFK channel\nguild.setAFKTimeout(60)\n .then(updated => console.log(`Updated guild AFK timeout to ${guild.afkTimeout}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":427,"filename":"Guild.js","path":"src/structures"},"order":36},{"id":"Guild#setIcon","longname":"Guild#setIcon","name":"setIcon","scope":"instance","kind":"function","description":"Set a new Guild Icon.","memberof":"Guild","params":[{"type":{"names":["Base64Resolvable"]},"description":"the new icon of the guild.","name":"icon"}],"examples":["// edit the guild icon\nguild.setIcon(fs.readFileSync('./icon.png'))\n .then(updated => console.log('Updated the guild icon'))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":441,"filename":"Guild.js","path":"src/structures"},"order":37},{"id":"Guild#setOwner","longname":"Guild#setOwner","name":"setOwner","scope":"instance","kind":"function","description":"Sets a new owner of the Guild.","memberof":"Guild","params":[{"type":{"names":["GuildMemberResolvable"]},"description":"the new owner of the Guild.","name":"owner"}],"examples":["// edit the guild owner\nguild.setOwner(guilds.members[0])\n .then(updated => console.log(`Updated the guild owner to ${updated.owner.username}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":455,"filename":"Guild.js","path":"src/structures"},"order":38},{"id":"Guild#setSplash","longname":"Guild#setSplash","name":"setSplash","scope":"instance","kind":"function","description":"Set a new Guild Splash Logo.","memberof":"Guild","params":[{"type":{"names":["Base64Resolvable"]},"description":"the new splash screen of the guild.","name":"splash"}],"examples":["// edit the guild splash\nguild.setIcon(fs.readFileSync('./splash.png'))\n .then(updated => console.log('Updated the guild splash'))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":469,"filename":"Guild.js","path":"src/structures"},"order":39}],"properties":[{"id":"Guild#client","longname":"Guild#client","name":"client","scope":"instance","kind":"member","description":"The Client that created the instance of the the Guild.","memberof":"Guild","type":{"names":["Client"]},"meta":{"lineno":31,"filename":"Guild.js","path":"src/structures"},"order":4},{"id":"Guild#store","longname":"Guild#store","name":"store","scope":"instance","kind":"member","description":"The data store of the Guild.","memberof":"Guild","type":{"names":["GuildDataStore"]},"meta":{"lineno":37,"filename":"Guild.js","path":"src/structures"},"order":5},{"id":"Guild#available","longname":"Guild#available","name":"available","scope":"instance","kind":"member","description":"Whether the Guild is available to access. If it is not available, it indicates a server outage.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":48,"filename":"Guild.js","path":"src/structures"},"order":6},{"id":"Guild#id","longname":"Guild#id","name":"id","scope":"instance","kind":"member","description":"The Unique ID of the Guild, useful for comparisons.","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":53,"filename":"Guild.js","path":"src/structures"},"order":7},{"id":"Guild#splash","longname":"Guild#splash","name":"splash","scope":"instance","kind":"member","description":"The hash of the guild splash image, or null if no splash (VIP only)","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":169,"filename":"Guild.js","path":"src/structures"},"order":12},{"id":"Guild#region","longname":"Guild#region","name":"region","scope":"instance","kind":"member","description":"The region the guild is located in","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":174,"filename":"Guild.js","path":"src/structures"},"order":13},{"id":"Guild#name","longname":"Guild#name","name":"name","scope":"instance","kind":"member","description":"The name of the guild","memberof":"Guild","type":{"names":["String"]},"meta":{"lineno":179,"filename":"Guild.js","path":"src/structures"},"order":14},{"id":"Guild#memberCount","longname":"Guild#memberCount","name":"memberCount","scope":"instance","kind":"member","description":"The amount of initial members in the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":184,"filename":"Guild.js","path":"src/structures"},"order":15},{"id":"Guild#large","longname":"Guild#large","name":"large","scope":"instance","kind":"member","description":"Whether the guild is \"large\" (has more than 250 members)","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":189,"filename":"Guild.js","path":"src/structures"},"order":16},{"id":"Guild#joinDate","longname":"Guild#joinDate","name":"joinDate","scope":"instance","kind":"member","description":"The date at which the logged-in client joined the guild.","memberof":"Guild","type":{"names":["Date"]},"meta":{"lineno":194,"filename":"Guild.js","path":"src/structures"},"order":17},{"id":"Guild#icon","longname":"Guild#icon","name":"icon","scope":"instance","kind":"member","description":"The hash of the guild icon, or null if there is no icon.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":199,"filename":"Guild.js","path":"src/structures"},"order":18},{"id":"Guild#features","longname":"Guild#features","name":"features","scope":"instance","kind":"member","description":"An array of guild features.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":204,"filename":"Guild.js","path":"src/structures"},"order":19},{"id":"Guild#emojis","longname":"Guild#emojis","name":"emojis","scope":"instance","kind":"member","description":"An array of guild emojis.","memberof":"Guild","type":{"names":["Array."]},"meta":{"lineno":209,"filename":"Guild.js","path":"src/structures"},"order":20},{"id":"Guild#afkTimeout","longname":"Guild#afkTimeout","name":"afkTimeout","scope":"instance","kind":"member","description":"The time in seconds before a user is counted as \"away from keyboard\".","memberof":"Guild","type":{"names":["Number"]},"nullable":true,"meta":{"lineno":214,"filename":"Guild.js","path":"src/structures"},"order":21},{"id":"Guild#afkChannelID","longname":"Guild#afkChannelID","name":"afkChannelID","scope":"instance","kind":"member","description":"The ID of the voice channel where AFK members are moved.","memberof":"Guild","type":{"names":["String"]},"nullable":true,"meta":{"lineno":219,"filename":"Guild.js","path":"src/structures"},"order":22},{"id":"Guild#embedEnabled","longname":"Guild#embedEnabled","name":"embedEnabled","scope":"instance","kind":"member","description":"Whether embedded images are enabled on this guild.","memberof":"Guild","type":{"names":["Boolean"]},"meta":{"lineno":224,"filename":"Guild.js","path":"src/structures"},"order":23},{"id":"Guild#verificationLevel","longname":"Guild#verificationLevel","name":"verificationLevel","scope":"instance","kind":"member","description":"The verification level of the guild.","memberof":"Guild","type":{"names":["Number"]},"meta":{"lineno":229,"filename":"Guild.js","path":"src/structures"},"order":24},{"id":"Guild#owner","longname":"Guild#owner","name":"owner","scope":"instance","kind":"member","description":"The owner of the guild","memberof":"Guild","type":{"names":["User"]},"meta":{"lineno":243,"filename":"Guild.js","path":"src/structures"},"order":25},{"id":"Guild#embedChannel","longname":"Guild#embedChannel","name":"embedChannel","scope":"instance","kind":"member","description":"The embed channel of the Guild.","memberof":"Guild","type":{"names":["GuildChannel"]},"meta":{"lineno":256,"filename":"Guild.js","path":"src/structures"},"order":26},{"id":"Guild#channels","longname":"Guild#channels","name":"channels","scope":"instance","kind":"member","description":"The channels in the guild.","memberof":"Guild","params":[],"type":{"names":["Array."]},"readonly":true,"meta":{"lineno":478,"filename":"Guild.js","path":"src/structures"},"order":40},{"id":"Guild#$channels","longname":"Guild#$channels","name":"$channels","scope":"instance","kind":"member","description":"A dictionary mapping the IDs of channels in this guild to the channel itself. If you want to find a channel\nin the guild by ID, use `guild.$channels[id]` rather than filtering `guild.channels` as it is much more efficient.","memberof":"Guild","params":[],"type":{"names":["Object."]},"readonly":true,"meta":{"lineno":486,"filename":"Guild.js","path":"src/structures"},"order":41},{"id":"Guild#roles","longname":"Guild#roles","name":"roles","scope":"instance","kind":"member","description":"The roles in the guild.","memberof":"Guild","params":[],"type":{"names":["Array."]},"readonly":true,"meta":{"lineno":493,"filename":"Guild.js","path":"src/structures"},"order":42},{"id":"Guild#$roles","longname":"Guild#$roles","name":"$roles","scope":"instance","kind":"member","description":"A dictionary mapping the IDs of roles in this guild to the role itself. If you want to find a role\nin the guild by ID, use `guild.$roles[id]` rather than filtering `guild.roles` as it is much more efficient.","memberof":"Guild","params":[],"type":{"names":["Object."]},"readonly":true,"meta":{"lineno":501,"filename":"Guild.js","path":"src/structures"},"order":43},{"id":"Guild#members","longname":"Guild#members","name":"members","scope":"instance","kind":"member","description":"The members of the guild.","memberof":"Guild","params":[],"type":{"names":["Array."]},"readonly":true,"meta":{"lineno":508,"filename":"Guild.js","path":"src/structures"},"order":44},{"id":"Guild#$members","longname":"Guild#$members","name":"$members","scope":"instance","kind":"member","description":"A dictionary mapping the IDs of members in this guild to the member object itself. If you want to find a member\nin the guild by ID, use `guild.$members[id]` rather than filtering `guild.members` as it is much more efficient.","memberof":"Guild","params":[],"type":{"names":["Object."]},"readonly":true,"meta":{"lineno":516,"filename":"Guild.js","path":"src/structures"},"order":45}],"events":[]},"Message":{"meta":{"id":"Message","longname":"Message","name":"Message","scope":"global","kind":"class","description":"Represents a Message on Discord","meta":{"lineno":4,"filename":"Message.js","path":"src/structures"},"order":46},"functions":[{"id":"Message#equals","longname":"Message#equals","name":"equals","scope":"instance","kind":"function","description":"Used mainly internally. Whether two messages are identical in properties. If you want to compare messages\nwithout checking all the properties, use `message.id === message2.id`, which is much more efficient. This\nmethod allows you to see if there are differences in content, embeds, attachments, nonce and tts properties.","memberof":"Message","params":[{"type":{"names":["Message"]},"description":"The message to compare it to","name":"message"},{"type":{"names":["Object"]},"description":"Raw data passed through the WebSocket about this message","name":"rawData"}],"returns":[{"type":{"names":["Boolean"]}}],"meta":{"lineno":149,"filename":"Message.js","path":"src/structures"},"order":61},{"id":"Message#delete","longname":"Message#delete","name":"delete","scope":"instance","kind":"function","description":"Deletes the message","memberof":"Message","params":[],"examples":["// delete a message\nmessage.delete()\n .then(msg => console.log(`Deleted message from ${msg.author}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":183,"filename":"Message.js","path":"src/structures"},"order":62},{"id":"Message#edit","longname":"Message#edit","name":"edit","scope":"instance","kind":"function","description":"Edit the content of a message","memberof":"Message","params":[{"type":{"names":["String"]},"description":"the new content of a message","name":"content"}],"examples":["// update the content of a message\nmessage.edit('This is my new content!')\n .then(msg => console.log(`Updated the content of a message from ${msg.author}`))\n .catch(console.log);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":197,"filename":"Message.js","path":"src/structures"},"order":63}],"properties":[{"id":"Message#channel","longname":"Message#channel","name":"channel","scope":"instance","kind":"member","description":"The channel that the message was sent in","memberof":"Message","type":{"names":["Channel"]},"meta":{"lineno":10,"filename":"Message.js","path":"src/structures"},"order":47},{"id":"Message#guild","longname":"Message#guild","name":"guild","scope":"instance","kind":"member","description":"If the message was sent in a guild, this will be the guild the message was sent in","memberof":"Message","type":{"names":["Guild"]},"nullable":true,"meta":{"lineno":17,"filename":"Message.js","path":"src/structures"},"order":48},{"id":"Message#client","longname":"Message#client","name":"client","scope":"instance","kind":"member","description":"The client that instantiated the Object","memberof":"Message","type":{"names":["Client"]},"meta":{"lineno":24,"filename":"Message.js","path":"src/structures"},"order":49},{"id":"Message#author","longname":"Message#author","name":"author","scope":"instance","kind":"member","description":"The author of the message","memberof":"Message","type":{"names":["User"]},"meta":{"lineno":35,"filename":"Message.js","path":"src/structures"},"order":50},{"id":"Message#content","longname":"Message#content","name":"content","scope":"instance","kind":"member","description":"The content of the message","memberof":"Message","type":{"names":["String"]},"meta":{"lineno":40,"filename":"Message.js","path":"src/structures"},"order":51},{"id":"Message#timestamp","longname":"Message#timestamp","name":"timestamp","scope":"instance","kind":"member","description":"When the message was sent","memberof":"Message","type":{"names":["Date"]},"meta":{"lineno":45,"filename":"Message.js","path":"src/structures"},"order":52},{"id":"Message#editedTimestamp","longname":"Message#editedTimestamp","name":"editedTimestamp","scope":"instance","kind":"member","description":"If the message was edited, the timestamp at which it was last edited","memberof":"Message","type":{"names":["Date"]},"nullable":true,"meta":{"lineno":50,"filename":"Message.js","path":"src/structures"},"order":53},{"id":"Message#tts","longname":"Message#tts","name":"tts","scope":"instance","kind":"member","description":"Whether or not the message was Text-To-Speech","memberof":"Message","type":{"names":["Boolean"]},"meta":{"lineno":55,"filename":"Message.js","path":"src/structures"},"order":54},{"id":"Message#mentionEveryone","longname":"Message#mentionEveryone","name":"mentionEveryone","scope":"instance","kind":"member","description":"Whether the message mentioned @everyone or not","memberof":"Message","type":{"names":["Boolean"]},"meta":{"lineno":60,"filename":"Message.js","path":"src/structures"},"order":55},{"id":"Message#nonce","longname":"Message#nonce","name":"nonce","scope":"instance","kind":"member","description":"A random number used for checking message delivery","memberof":"Message","type":{"names":["String"]},"meta":{"lineno":65,"filename":"Message.js","path":"src/structures"},"order":56},{"id":"Message#embeds","longname":"Message#embeds","name":"embeds","scope":"instance","kind":"member","description":"A list of embeds in the message - e.g. YouTube Player","memberof":"Message","type":{"names":["Array."]},"meta":{"lineno":70,"filename":"Message.js","path":"src/structures"},"order":57},{"id":"Message#attachments","longname":"Message#attachments","name":"attachments","scope":"instance","kind":"member","description":"A list of attachments in the message - e.g. Pictures","memberof":"Message","type":{"names":["Array."]},"meta":{"lineno":75,"filename":"Message.js","path":"src/structures"},"order":58},{"id":"Message#mentions","longname":"Message#mentions","name":"mentions","scope":"instance","kind":"member","description":"A list of users mentioned in the message","memberof":"Message","type":{"names":["Array."]},"meta":{"lineno":80,"filename":"Message.js","path":"src/structures"},"order":59},{"id":"Message#id","longname":"Message#id","name":"id","scope":"instance","kind":"member","description":"The ID of the message (unique in the channel it was sent)","memberof":"Message","meta":{"lineno":84,"filename":"Message.js","path":"src/structures"},"order":60}],"events":[]},"TextChannel":{"meta":{"id":"TextChannel","longname":"TextChannel","name":"TextChannel","scope":"global","kind":"class","description":"Represents a Server Text Channel on Discord.","meta":{"lineno":8,"filename":"TextChannel.js","path":"src/structures"},"order":64},"functions":[],"properties":[],"events":[]},"User":{"meta":{"id":"User","longname":"User","name":"User","scope":"global","kind":"class","description":"Represents a User on Discord.","meta":{"lineno":6,"filename":"User.js","path":"src/structures"},"order":65},"functions":[{"id":"User#deleteDM","longname":"User#deleteDM","name":"deleteDM","scope":"instance","kind":"function","description":"Deletes a DM Channel (if one exists) between the Client and the User. Resolves with the Channel if successful.","memberof":"User","params":[],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":64,"filename":"User.js","path":"src/structures"},"order":73},{"id":"User#equals","longname":"User#equals","name":"equals","scope":"instance","kind":"function","description":"Checks if the user is equal to another. It compares username, ID, discriminator, status and the game being played.\nIt is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties.","memberof":"User","params":[{"type":{"names":["User"]},"description":"the user to compare","name":"user"}],"returns":[{"description":"Boolean"}],"meta":{"lineno":74,"filename":"User.js","path":"src/structures"},"order":74}],"properties":[{"id":"User#username","longname":"User#username","name":"username","scope":"instance","kind":"member","description":"The username of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":19,"filename":"User.js","path":"src/structures"},"order":66},{"id":"User#id","longname":"User#id","name":"id","scope":"instance","kind":"member","description":"The ID of the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":24,"filename":"User.js","path":"src/structures"},"order":67},{"id":"User#discriminator","longname":"User#discriminator","name":"discriminator","scope":"instance","kind":"member","description":"A discriminator based on username for the User","memberof":"User","type":{"names":["String"]},"meta":{"lineno":29,"filename":"User.js","path":"src/structures"},"order":68},{"id":"User#avatar","longname":"User#avatar","name":"avatar","scope":"instance","kind":"member","description":"The ID of the user's avatar","memberof":"User","type":{"names":["String"]},"meta":{"lineno":34,"filename":"User.js","path":"src/structures"},"order":69},{"id":"User#bot","longname":"User#bot","name":"bot","scope":"instance","kind":"member","description":"Whether or not the User is a Bot.","memberof":"User","type":{"names":["Boolean"]},"meta":{"lineno":39,"filename":"User.js","path":"src/structures"},"order":70},{"id":"User#status","longname":"User#status","name":"status","scope":"instance","kind":"member","description":"The status of the user:\n\n* **`online`** - user is online\n* **`offline`** - user is offline\n* **`idle`** - user is AFK","memberof":"User","type":{"names":["String"]},"meta":{"lineno":48,"filename":"User.js","path":"src/structures"},"order":71},{"id":"User#game","longname":"User#game","name":"game","scope":"instance","kind":"member","description":"The game that the user is playing, `null` if they aren't playing a game.","memberof":"User","type":{"names":["String"]},"meta":{"lineno":53,"filename":"User.js","path":"src/structures"},"order":72}],"events":[]},"VoiceChannel":{"meta":{"id":"VoiceChannel","longname":"VoiceChannel","name":"VoiceChannel","scope":"global","kind":"class","description":"Represents a Server Voice Channel on Discord.","meta":{"lineno":7,"filename":"VoiceChannel.js","path":"src/structures"},"order":75},"functions":[],"properties":[],"events":[]}}}}
\ No newline at end of file
diff --git a/src/structures/Message.js b/src/structures/Message.js
index c225fe697..132086236 100644
--- a/src/structures/Message.js
+++ b/src/structures/Message.js
@@ -3,12 +3,24 @@
*/
class Message {
constructor(channel, data, client) {
+ /**
+ * The channel that the message was sent in
+ * @type {Channel}
+ */
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 Object
+ * @type {Client}
+ */
this.client = client;
if (data) {
this.setup(data);
@@ -16,16 +28,59 @@ class Message {
}
setup(data) {
+ /**
+ * The author of the message
+ * @type {User}
+ */
this.author = this.client.store.newUser(data.author);
+ /**
+ * The content of the message
+ * @type {String}
+ */
this.content = data.content;
+ /**
+ * When the message was sent
+ * @type {Date}
+ */
this.timestamp = new Date(data.timestamp);
+ /**
+ * If the message was edited, the timestamp at which it was last edited
+ * @type {?Date}
+ */
this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp) : null;
+ /**
+ * Whether or not the message was Text-To-Speech
+ * @type {Boolean}
+ */
this.tts = data.tts;
+ /**
+ * Whether the message mentioned @everyone or not
+ * @type {Boolean}
+ */
this.mentionEveryone = data.mention_everyone;
+ /**
+ * A random number used for checking message delivery
+ * @type {String}
+ */
this.nonce = data.nonce;
+ /**
+ * A list of embeds in the message - e.g. YouTube Player
+ * @type {Array}
+ */
this.embeds = data.embeds;
+ /**
+ * A list of attachments in the message - e.g. Pictures
+ * @type {Array}
+ */
this.attachments = data.attachments;
+ /**
+ * A list of users mentioned in the message
+ * @type {Array}
+ */
this.mentions = [];
+ /**
+ * The ID of the message (unique in the channel it was sent)
+ */
this.id = data.id;
for (const mention of data.mentions) {
let user = this.client.store.get('users', mention.id);
@@ -83,6 +138,14 @@ 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) {
const embedUpdate = !message.author && !message.attachments;
@@ -108,10 +171,29 @@ class Message {
return base;
}
+ /**
+ * Deletes the message
+ * @returns {Promise}
+ * @example
+ * // delete a message
+ * message.delete()
+ * .then(msg => console.log(`Deleted message from ${msg.author}`))
+ * .catch(console.log);
+ */
delete() {
return this.client.rest.methods.deleteMessage(this);
}
+ /**
+ * Edit the content of a message
+ * @param {String} content the new content of a message
+ * @returns {Promise}
+ * @example
+ * // update the content of a message
+ * message.edit('This is my new content!')
+ * .then(msg => console.log(`Updated the content of a message from ${msg.author}`))
+ * .catch(console.log);
+ */
edit(content) {
return this.client.rest.methods.updateMessage(this, content);
}
From 79ea663afeafc753472c8f008033f655cf759ce0 Mon Sep 17 00:00:00 2001
From: Amish Shah
Date: Wed, 17 Aug 2016 19:18:39 +0100
Subject: [PATCH 064/324] Fix guild.createChannel docs
---
docs/docs.json | 2 +-
src/structures/Guild.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/docs.json b/docs/docs.json
index db14380bb..b7c5cfa36 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -1 +1 @@
-{"meta":{"version":2},"custom":{"general":{"Getting Started":"# Welcome!\ndiscord.js is an easy-to-use and intuitive JavaScript library that wraps around the Discord API.\n"}},"json":{"classes":{"Client":{"meta":{"id":"Client","longname":"Client","name":"Client","scope":"global","kind":"class","description":"Creates a new Discord Client\n```js\nconst Discord = require(\"discord.js\");\nconst client = new Discord.Client();\n```","meta":{"lineno":18,"filename":"Client.js","path":"src/client"},"order":0},"functions":[{"id":"Client#login","longname":"Client#login","name":"login","scope":"instance","kind":"function","description":"Logs the client in. If successful, resolves with the account's token.","memberof":"Client","params":[{"type":{"names":["string"]},"description":"The email or token used for the account. If it is an email, a password _must_ be\nprovided.","name":"emailOrToken"},{"type":{"names":["string"]},"optional":true,"description":"The password for the account, only needed if an email was provided.","name":"password"}],"examples":["// log the client in using a token\nconst token = 'my token';\nclient.login(token);","// log the client in using email and password\nconst email = 'user@email.com';\nconst password = 'supersecret123';\nclient.login(email, password);"],"returns":[{"type":{"names":["Promise."]}}],"meta":{"lineno":47,"filename":"Client.js","path":"src/client"},"order":1}],"properties":[{"id":"Client#user","longname":"Client#user","name":"user","scope":"instance","kind":"member","description":"The User of the logged in Client, only available after `READY` has been fired.","memberof":"Client","params":[],"type":{"names":["ClientUser"]},"meta":{"lineno":60,"filename":"Client.js","path":"src/client"},"order":2}],"events":[]},"Guild":{"meta":{"id":"Guild","longname":"Guild","name":"Guild","scope":"global","kind":"class","description":"Represents a Guild (or a Server) on Discord.","meta":{"lineno":25,"filename":"Guild.js","path":"src/structures"},"order":3},"functions":[{"id":"Guild#toString","longname":"Guild#toString","name":"toString","scope":"instance","kind":"function","description":"When concatenated with a String, this automatically concatenates the Guild's name instead of the Guild object.","memberof":"Guild","params":[],"examples":["// logs: Hello from My Guild!\nconsole.log(`Hello from ${guild}!`);","// logs: Hello from My Guild!\nconsole.log(`Hello from ' + guild + '!');"],"returns":[{"type":{"names":["String"]}}],"meta":{"lineno":97,"filename":"Guild.js","path":"src/structures"},"order":8},{"id":"Guild#kick","longname":"Guild#kick","name":"kick","scope":"instance","kind":"function","description":"Tries to kick a member from the guild.","memberof":"Guild","params":[{"type":{"names":["GuildMemberResolvable"]},"description":"the member to kick","name":"member"}],"examples":["// kicks a member from a guild:\nguild.kick(message.author)\n .then(member => console.log(`Kicked ${member}`))\n .catch(error => console.log(error));"],"returns":[{"type":{"names":["Promise.