diff --git a/lib/Client/Client.js b/lib/Client/Client.js index c052e203a..ed5405ee9 100644 --- a/lib/Client/Client.js +++ b/lib/Client/Client.js @@ -18,7 +18,8 @@ var Client = (function (_EventEmitter) { function Client(options) { _classCallCheck(this, Client); - _EventEmitter.call(this, options); + _EventEmitter.call(this); + this.options = options || {}; this.internal = new InternalClient(this); } diff --git a/lib/Client/InternalClient.js b/lib/Client/InternalClient.js index 0d7795d6a..0a9d8db1d 100644 --- a/lib/Client/InternalClient.js +++ b/lib/Client/InternalClient.js @@ -4,9 +4,21 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons var EventEmitter = require("events"); var request = require("superagent"); +var WebSocket = require("ws"); var ConnectionState = require("./ConnectionState.js"); + var Constants = require("../Constants.js"), - Endpoints = Constants.Endpoints; + Endpoints = Constants.Endpoints, + PacketType = Constants.PacketType; + +var Cache = require("../Util/Cache.js"); + +var User = require("../Structures/User.js"), + Channel = require("../Structures/Channel.js"), + TextChannel = require("../Structures/TextChannel.js"), + VoiceChannel = require("../Structures/VoiceChannel.js"), + PMChannel = require("../Structures/PMChannel.js"), + Server = require("../Structures/Server.js"); var zlib; @@ -21,6 +33,12 @@ var InternalClient = (function () { if (this.client.options.compress) { zlib = require("zlib"); } + + // creates 4 caches with discriminators based on ID + this.users = new Cache(); + this.channels = new Cache(); + this.servers = new Cache(); + this.private_channels = new Cache(); } InternalClient.prototype.login = function login(email, password) { @@ -76,6 +94,7 @@ var InternalClient = (function () { InternalClient.prototype.createWS = function createWS(url) { var self = this; + var client = self.client; if (this.websocket) return false; @@ -103,12 +122,13 @@ var InternalClient = (function () { this.websocket.onclose = function () { self.websocket = null; self.state = ConnectionState.DISCONNECTED; - self.client.emit("disconnected"); + client.emit("disconnected"); }; this.websocket.onmessage = function (e) { if (e.type === "Binary") { + if (!zlib) zlib = require("zlib"); e.data = zlib.inflateSync(e.data).toString(); } @@ -117,12 +137,27 @@ var InternalClient = (function () { packet = JSON.parse(e.data); data = packet.d; } catch (e) { - self.client.emit("error", e); + client.emit("error", e); + return; } - self.emit("raw", packet); + client.emit("raw", packet); - switch (packet.t) {} + switch (packet.t) { + + case PacketType.READY: + + self.users.add(new User(data.user, client)); + + data.guilds.forEach(function (server) { + self.servers.add(new Server(server, client)); + }); + + console.log(self.servers); + + break; + + } }; }; diff --git a/lib/Constants.js b/lib/Constants.js index 6f990e7a7..1543911d5 100644 --- a/lib/Constants.js +++ b/lib/Constants.js @@ -2,7 +2,6 @@ var API = "https://discordapp.com/api"; var Endpoints = { - // general endpoints LOGIN: API + "/auth/login", LOGOUT: API + "/auth/logout", @@ -11,6 +10,9 @@ var Endpoints = { USER_CHANNELS: function USER_CHANNELS(userID) { return API + "/users/" + userID + "/channels"; }, + AVATAR: function AVATAR(userID, avatar) { + return API + "/users/" + userID + "/avatars/" + avatar + ".jpg"; + }, // servers SERVERS: API + "/guilds", @@ -62,8 +64,12 @@ var Endpoints = { CHANNEL_PERMISSIONS: function CHANNEL_PERMISSIONS(channelID) { return Endpoints.CHANNEL(channelID) + "/permissions"; } +}; +var PacketType = { + READY: "READY" }; exports.API_ENDPOINT = API; -exports.Endpoints = Endpoints; \ No newline at end of file +exports.Endpoints = Endpoints; +exports.PacketType = PacketType; \ No newline at end of file diff --git a/lib/Structures/Channel.js b/lib/Structures/Channel.js new file mode 100644 index 000000000..64086a57f --- /dev/null +++ b/lib/Structures/Channel.js @@ -0,0 +1,24 @@ +"use strict"; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var Equality = require("../Util/Equality.js"); + +var Channel = (function (_Equality) { + _inherits(Channel, _Equality); + + function Channel(data, client) { + _classCallCheck(this, Channel); + + _Equality.call(this); + this.type = data.type || "text"; + this.id = data.id; + this.client = client; + } + + return Channel; +})(Equality); + +module.exports = Channel; \ No newline at end of file diff --git a/lib/Structures/Member.js b/lib/Structures/Member.js new file mode 100644 index 000000000..656f03921 --- /dev/null +++ b/lib/Structures/Member.js @@ -0,0 +1,31 @@ +"use strict"; + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var User = require("./User.js"); + +var Member = (function (_User) { + _inherits(Member, _User); + + function Member(data, client, server) { + _classCallCheck(this, Member); + + _User.call(this, data, client); + this.serverID = server; + } + + _createClass(Member, [{ + key: "server", + get: function get() { + return this.client.internal.servers.get("id", this.serverID); + } + }]); + + return Member; +})(User); + +module.exports = Member; \ No newline at end of file diff --git a/lib/Structures/PMChannel.js b/lib/Structures/PMChannel.js new file mode 100644 index 000000000..337a3cc79 --- /dev/null +++ b/lib/Structures/PMChannel.js @@ -0,0 +1,22 @@ +"use strict"; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var Channel = require("./Channel.js"); +var Equality = require("../Util/Equality.js"); + +var PMChannel = (function (_Channel) { + _inherits(PMChannel, _Channel); + + function PMChannel(data, client) { + _classCallCheck(this, PMChannel); + + _Channel.call(this, data, client); + } + + return PMChannel; +})(Channel); + +module.exports = PMChannel; \ No newline at end of file diff --git a/lib/Structures/Server.js b/lib/Structures/Server.js new file mode 100644 index 000000000..e4dabccd4 --- /dev/null +++ b/lib/Structures/Server.js @@ -0,0 +1,91 @@ +"use strict"; + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var Equality = require("../Util/Equality.js"); +var Endpoints = require("../Constants.js").Endpoints; +var Cache = require("../Util/Cache.js"); +var User = require("./User.js"); +var Member = require("./Member.js"); +var TextChannel = require("./TextChannel.js"); +var VoiceChannel = require("./VoiceChannel.js"); + +var Server = (function (_Equality) { + _inherits(Server, _Equality); + + function Server(data, client) { + var _this = this; + + _classCallCheck(this, Server); + + _Equality.call(this); + + var self = this; + this.client = client; + + this.region = data.region; + this.ownerID = data.owner_id; + this.name = data.name; + this.id = data.id; + this.members = new Cache(); + this.channels = new Cache(); + this.roles = new Cache(); + this.icon = data.icon; + this.afkTimeout = data.afkTimeout; + this.afkChannelID = data.afk_channel_id; + + data.members.forEach(function (dataUser) { + var user = client.internal.users.add(new User(dataUser, client)); + _this.members.add(new Member(dataUser, client, self)); + }); + + data.channels.forEach(function (dataChannel) { + + if (dataChannel.type === "text") { + var channel = client.internal.channels.add(new TextChannel(dataChannel, client)); + _this.channels.add(channel); + } else { + var channel = client.internal.channels.add(new VoiceChannel(dataChannel, client)); + _this.channels.add(channel); + } + }); + } + + Server.prototype.toString = function toString() { + return this.name; + }; + + _createClass(Server, [{ + key: "iconURL", + get: function get() { + if (!this.icon) { + return null; + } else { + return Endpoints.SERVER_ICON(this.id, this.icon); + } + } + }, { + key: "afkChannel", + get: function get() { + return this.channels.get("id", this.afkChannelID); + } + }, { + key: "defaultChannel", + get: function get() { + return this.channels.get("id", this.id); + } + }, { + key: "owner", + get: function get() { + return this.members.get("id", this.ownerID); + } + }]); + + return Server; +})(Equality); + +module.exports = Server; \ No newline at end of file diff --git a/lib/Structures/TextChannel.js b/lib/Structures/TextChannel.js new file mode 100644 index 000000000..7616fe915 --- /dev/null +++ b/lib/Structures/TextChannel.js @@ -0,0 +1,23 @@ +"use strict"; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var Channel = require("./Channel.js"); +var Cache = require("../Util/Cache.js"); + +var TextChannel = (function (_Channel) { + _inherits(TextChannel, _Channel); + + function TextChannel(data, client) { + _classCallCheck(this, TextChannel); + + _Channel.call(this, data, client); + this.messages = new Cache("id", client.options.maximumMessages); + } + + return TextChannel; +})(Channel); + +module.exports = TextChannel; \ No newline at end of file diff --git a/lib/Structures/User.js b/lib/Structures/User.js new file mode 100644 index 000000000..5137a21b8 --- /dev/null +++ b/lib/Structures/User.js @@ -0,0 +1,50 @@ +"use strict"; + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var Equality = require("../Util/Equality.js"); +var Endpoints = require("../Constants.js").Endpoints; + +var User = (function (_Equality) { + _inherits(User, _Equality); + + function User(data, client) { + _classCallCheck(this, User); + + _Equality.call(this); + this.client = client; + this.username = data.username; + this.discriminator = data.discriminator; + this.id = data.id; + this.avatar = data.avatar; + this.status = data.status || "offline"; + this.gameID = data.game_id || null; + } + + User.prototype.mention = function mention() { + return "<@" + this.id + ">"; + }; + + User.prototype.toString = function toString() { + return this.mention(); + }; + + _createClass(User, [{ + key: "avatarURL", + get: function get() { + if (!this.avatar) { + return null; + } else { + return Endpoints.AVATAR(this.id, this.avatar); + } + } + }]); + + return User; +})(Equality); + +module.exports = User; \ No newline at end of file diff --git a/lib/Structures/VoiceChannel.js b/lib/Structures/VoiceChannel.js new file mode 100644 index 000000000..a60b3fdf0 --- /dev/null +++ b/lib/Structures/VoiceChannel.js @@ -0,0 +1,21 @@ +"use strict"; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var Channel = require("./Channel.js"); + +var VoiceChannel = (function (_Channel) { + _inherits(VoiceChannel, _Channel); + + function VoiceChannel(data, client) { + _classCallCheck(this, VoiceChannel); + + _Channel.call(this, data, client); + } + + return VoiceChannel; +})(Channel); + +module.exports = VoiceChannel; \ No newline at end of file diff --git a/lib/Util/Cache.js b/lib/Util/Cache.js new file mode 100644 index 000000000..2d428335b --- /dev/null +++ b/lib/Util/Cache.js @@ -0,0 +1,74 @@ +"use strict"; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var Cache = (function (_Array) { + _inherits(Cache, _Array); + + function Cache(discrim, limit) { + _classCallCheck(this, Cache); + + _Array.call(this); + this.discrim = discrim || "id"; + } + + Cache.prototype.get = function get(key, value) { + var found = null; + this.forEach(function (val, index, array) { + if (val.hasOwnProperty(key) && val[key] == value) { + found = val; + return; + } + }); + return found; + }; + + Cache.prototype.getAll = function getAll(key, value) { + var found = []; + this.forEach(function (val, index, array) { + if (val.hasOwnProperty(key) && val[key] == value) { + found.push(val); + return; + } + }); + return found; + }; + + Cache.prototype.add = function add(data) { + var exit = false; + for (var _iterator = this, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var item = _ref; + + if (item[this.discrim] === data[this.discrim]) { + exit = item; + break; + } + } + if (exit) { + return exit; + } else { + if (this.limit && this.length >= this.limit) { + this.splice(0, 1); + } + this.push(data); + return data; + } + }; + + return Cache; +})(Array); + +module.exports = Cache; \ No newline at end of file diff --git a/lib/Util/Equality.js b/lib/Util/Equality.js new file mode 100644 index 000000000..e568eb9aa --- /dev/null +++ b/lib/Util/Equality.js @@ -0,0 +1,40 @@ +/* + The Equality Class is just used to show + that a Class has an ID that can be used to + check for equality. + + Never use == or === when comparing + objects in discord.js, they will be different + instances sometimes. + + Instead, use objectThatExtendsEquality.equals() +*/ +"use strict"; + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Equality = (function () { + function Equality() { + _classCallCheck(this, Equality); + } + + Equality.prototype.equals = function equals(object) { + if (object && object[this.eqDiscriminator] == this[this.eqDiscriminator]) { + return true; + } + return false; + }; + + _createClass(Equality, [{ + key: "eqDiscriminator", + get: function get() { + return "id"; + } + }]); + + return Equality; +})(); + +module.exports = Equality; \ No newline at end of file diff --git a/lib/index.js b/lib/index.js index 1f9a98cc4..ac6609b7a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -5,6 +5,6 @@ module.exports = { }; var a = new module.exports.Client(); -a.login("email", "password")["catch"](function (e) { +a.login(process.env["discordEmail"], process.env["discordPass"])["catch"](function (e) { return console.log(e); }); \ No newline at end of file diff --git a/src/Client/Client.js b/src/Client/Client.js index ae3580d7a..056d1a2a8 100644 --- a/src/Client/Client.js +++ b/src/Client/Client.js @@ -9,7 +9,8 @@ class Client extends EventEmitter{ client. */ constructor(options){ - super(options); + super(); + this.options = options || {}; this.internal = new InternalClient(this); } diff --git a/src/Client/InternalClient.js b/src/Client/InternalClient.js index ab24211e0..2c5a9121f 100644 --- a/src/Client/InternalClient.js +++ b/src/Client/InternalClient.js @@ -2,9 +2,21 @@ var EventEmitter = require("events"); var request = require("superagent"); +var WebSocket = require("ws"); var ConnectionState = require("./ConnectionState.js"); + var Constants = require("../Constants.js"), - Endpoints = Constants.Endpoints; + Endpoints = Constants.Endpoints, + PacketType = Constants.PacketType; + +var Cache = require("../Util/Cache.js"); + +var User = require("../Structures/User.js"), + Channel = require("../Structures/Channel.js"), + TextChannel = require("../Structures/TextChannel.js"), + VoiceChannel = require("../Structures/VoiceChannel.js"), + PMChannel = require("../Structures/PMChannel.js"), + Server = require("../Structures/Server.js"); var zlib; @@ -17,6 +29,12 @@ class InternalClient { if (this.client.options.compress) { zlib = require("zlib"); } + + // creates 4 caches with discriminators based on ID + this.users = new Cache(); + this.channels = new Cache(); + this.servers = new Cache(); + this.private_channels = new Cache(); } login(email, password) { @@ -85,6 +103,7 @@ class InternalClient { createWS(url) { var self = this; + var client = self.client; if (this.websocket) return false; @@ -113,12 +132,13 @@ class InternalClient { this.websocket.onclose = () => { self.websocket = null; self.state = ConnectionState.DISCONNECTED; - self.client.emit("disconnected"); + client.emit("disconnected"); } this.websocket.onmessage = (e) => { if (e.type === "Binary") { + if(!zlib) zlib = require("zlib"); e.data = zlib.inflateSync(e.data).toString(); } @@ -127,17 +147,28 @@ class InternalClient { packet = JSON.parse(e.data); data = packet.d; } catch (e) { - self.client.emit("error", e); + client.emit("error", e); + return; } - - self.emit("raw", packet); - - switch(packet.t){ - - } - - } + client.emit("raw", packet); + + switch (packet.t) { + + case PacketType.READY: + + self.users.add(new User(data.user, client)); + + data.guilds.forEach((server) => { + self.servers.add(new Server(server, client)); + }); + + console.log(self.servers); + + break; + + } + } } } diff --git a/src/Constants.js b/src/Constants.js index 676c3ea25..9c414600b 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -1,12 +1,12 @@ var API = "https://discordapp.com/api"; var Endpoints = { - // general endpoints LOGIN: `${API}/auth/login`, LOGOUT: `${API}/auth/logout`, ME: `${API}/users/@me`, GATEWAY: `${API}/gateway`, USER_CHANNELS: (userID) => `${API}/users/${userID}/channels`, + AVATAR : (userID, avatar) => `${API}/users/${userID}/avatars/${avatar}.jpg`, // servers SERVERS: `${API}/guilds`, @@ -28,8 +28,12 @@ var Endpoints = { CHANNEL_INVITES: (channelID) => `${Endpoints.CHANNEL(channelID) }/invites`, CHANNEL_TYPING: (channelID) => `${Endpoints.CHANNEL(channelID) }/typing`, CHANNEL_PERMISSIONS: (channelID) => `${Endpoints.CHANNEL(channelID) }/permissions`, +}; +var PacketType = { + READY : "READY" } exports.API_ENDPOINT = API; -exports.Endpoints = Endpoints; \ No newline at end of file +exports.Endpoints = Endpoints; +exports.PacketType = PacketType; \ No newline at end of file diff --git a/src/Structures/Channel.js b/src/Structures/Channel.js new file mode 100644 index 000000000..a91ed3f45 --- /dev/null +++ b/src/Structures/Channel.js @@ -0,0 +1,16 @@ +"use strict"; + +var Equality = require("../Util/Equality.js"); + +class Channel extends Equality{ + + constructor(data, client){ + super(); + this.type = data.type || "text"; + this.id = data.id; + this.client = client; + } + +} + +module.exports = Channel; \ No newline at end of file diff --git a/src/Structures/Member.js b/src/Structures/Member.js new file mode 100644 index 000000000..8e015ba4a --- /dev/null +++ b/src/Structures/Member.js @@ -0,0 +1,16 @@ +"use strict"; + +var User = require("./User.js"); + +class Member extends User{ + constructor(data, client, server){ + super(data, client); + this.serverID = server; + } + + get server(){ + return this.client.internal.servers.get("id", this.serverID); + } +} + +module.exports = Member; \ No newline at end of file diff --git a/src/Structures/PMChannel.js b/src/Structures/PMChannel.js new file mode 100644 index 000000000..4ed9fef5e --- /dev/null +++ b/src/Structures/PMChannel.js @@ -0,0 +1,12 @@ +"use strict"; + +var Channel = require("./Channel.js"); +var Equality = require("../Util/Equality.js"); + +class PMChannel extends Channel{ + constructor(data, client){ + super(data, client); + } +} + +module.exports = PMChannel; \ No newline at end of file diff --git a/src/Structures/Server.js b/src/Structures/Server.js new file mode 100644 index 000000000..84eb5ba14 --- /dev/null +++ b/src/Structures/Server.js @@ -0,0 +1,74 @@ +"use strict"; + +var Equality = require("../Util/Equality.js"); +var Endpoints = require("../Constants.js").Endpoints; +var Cache = require("../Util/Cache.js"); +var User = require("./User.js"); +var Member = require("./Member.js"); +var TextChannel = require("./TextChannel.js"); +var VoiceChannel = require("./VoiceChannel.js"); + +class Server extends Equality { + constructor(data, client) { + + super(); + + var self = this; + this.client = client; + + this.region = data.region; + this.ownerID = data.owner_id; + this.name = data.name; + this.id = data.id; + this.members = new Cache(); + this.channels = new Cache(); + this.roles = new Cache(); + this.icon = data.icon; + this.afkTimeout = data.afkTimeout; + this.afkChannelID = data.afk_channel_id; + + data.members.forEach( (dataUser) => { + var user = client.internal.users.add(new User(dataUser, client)); + this.members.add( new Member(dataUser, client, self) ); + } ); + + data.channels.forEach( (dataChannel) => { + + if(dataChannel.type === "text"){ + var channel = client.internal.channels.add(new TextChannel(dataChannel, client)); + this.channels.add(channel); + }else{ + var channel = client.internal.channels.add(new VoiceChannel(dataChannel, client)); + this.channels.add(channel); + } + + } ); + } + + get iconURL() { + if (!this.icon) { + return null; + } else { + return Endpoints.SERVER_ICON(this.id, this.icon); + } + } + + get afkChannel() { + return this.channels.get("id", this.afkChannelID); + } + + get defaultChannel() { + return this.channels.get("id", this.id); + } + + get owner() { + return this.members.get("id", this.ownerID); + } + + toString() { + return this.name; + } + +} + +module.exports = Server; \ No newline at end of file diff --git a/src/Structures/TextChannel.js b/src/Structures/TextChannel.js new file mode 100644 index 000000000..df3881be4 --- /dev/null +++ b/src/Structures/TextChannel.js @@ -0,0 +1,15 @@ +"use strict"; + +var Channel = require("./Channel.js"); +var Cache = require("../Util/Cache.js"); + +class TextChannel extends Channel{ + constructor(data, client){ + + super(data, client); + this.messages = new Cache("id", client.options.maximumMessages); + + } +} + +module.exports = TextChannel; \ No newline at end of file diff --git a/src/Structures/User.js b/src/Structures/User.js new file mode 100644 index 000000000..a0b31abef --- /dev/null +++ b/src/Structures/User.js @@ -0,0 +1,35 @@ +"use strict"; + +var Equality = require("../Util/Equality.js"); +var Endpoints = require("../Constants.js").Endpoints; + +class User extends Equality{ + constructor(data, client){ + super(); + this.client = client; + this.username = data.username; + this.discriminator = data.discriminator; + this.id = data.id; + this.avatar = data.avatar; + this.status = data.status || "offline"; + this.gameID = data.game_id || null; + } + + get avatarURL(){ + if(!this.avatar){ + return null; + }else{ + return Endpoints.AVATAR(this.id, this.avatar); + } + } + + mention(){ + return `<@${this.id}>`; + } + + toString(){ + return this.mention(); + } +} + +module.exports = User; \ No newline at end of file diff --git a/src/Structures/VoiceChannel.js b/src/Structures/VoiceChannel.js new file mode 100644 index 000000000..9c2e12c43 --- /dev/null +++ b/src/Structures/VoiceChannel.js @@ -0,0 +1,11 @@ +"use strict"; + +var Channel = require("./Channel.js"); + +class VoiceChannel extends Channel{ + constructor(data, client){ + super(data, client); + } +} + +module.exports = VoiceChannel; \ No newline at end of file diff --git a/src/Util/Cache.js b/src/Util/Cache.js new file mode 100644 index 000000000..b8e91011e --- /dev/null +++ b/src/Util/Cache.js @@ -0,0 +1,51 @@ +"use strict"; + +class Cache extends Array{ + constructor(discrim, limit){ + super(); + this.discrim = discrim || "id"; + } + + get(key, value){ + var found = null; + this.forEach( (val, index, array) => { + if(val.hasOwnProperty(key) && val[key] == value){ + found = val; + return; + } + } ); + return found; + } + + getAll(key, value){ + var found = []; + this.forEach( (val, index, array) => { + if(val.hasOwnProperty(key) && val[key] == value){ + found.push(val); + return; + } + } ); + return found; + } + + add(data){ + var exit = false; + for(var item of this){ + if(item[this.discrim] === data[this.discrim]){ + exit = item; + break; + } + } + if(exit){ + return exit; + }else{ + if(this.limit && this.length >= this.limit){ + this.splice(0, 1); + } + this.push(data); + return data; + } + } +} + +module.exports = Cache; \ No newline at end of file diff --git a/src/Util/Equality.js b/src/Util/Equality.js new file mode 100644 index 000000000..241be1265 --- /dev/null +++ b/src/Util/Equality.js @@ -0,0 +1,29 @@ +/* + The Equality Class is just used to show + that a Class has an ID that can be used to + check for equality. + + Never use == or === when comparing + objects in discord.js, they will be different + instances sometimes. + + Instead, use objectThatExtendsEquality.equals() +*/ +class Equality{ + constructor(){ + + } + + get eqDiscriminator(){ + return "id"; + } + + equals(object){ + if(object && object[this.eqDiscriminator] == this[this.eqDiscriminator]){ + return true; + } + return false; + } +} + +module.exports = Equality; \ No newline at end of file diff --git a/src/index.js b/src/index.js index fc8d34170..53f306764 100644 --- a/src/index.js +++ b/src/index.js @@ -3,4 +3,4 @@ module.exports = { } var a = new module.exports.Client(); -a.login("email", "password").catch((e)=>console.log(e)); \ No newline at end of file +a.login(process.env["discordEmail"], process.env["discordPass"]).catch((e)=>console.log(e)); \ No newline at end of file