diff --git a/lib/Client/Client.js b/lib/Client/Client.js new file mode 100644 index 000000000..030b972c5 --- /dev/null +++ b/lib/Client/Client.js @@ -0,0 +1,625 @@ +"use strict"; + +exports.__esModule = true; + +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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +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 _InternalClient = require("./InternalClient"); + +var _InternalClient2 = _interopRequireDefault(_InternalClient); + +var _events = require("events"); + +var _events2 = _interopRequireDefault(_events); + +function errCB(callback) { + return function (error) { + callback(error); + throw error; + }; +} + +var Client = (function (_EventEmitter) { + _inherits(Client, _EventEmitter); + + /* + this class is an interface for the internal + client. + */ + + function Client(options) { + _classCallCheck(this, Client); + + _EventEmitter.call(this); + this.options = options || {}; + this.internal = new _InternalClient2["default"](this); + } + + // def login + + Client.prototype.login = function login(email, password) { + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*err, token*/{} : arguments[2]; + + return this.internal.login(email, password).then(function (token) { + callback(null, token); + return token; + }, errCB(callback)); + }; + + // def logout + + Client.prototype.logout = function logout() { + var callback = arguments.length <= 0 || arguments[0] === undefined ? function () /*err*/{} : arguments[0]; + + return this.internal.logout().then(callback, errCB(callback)); + }; + + // def sendMessage + + Client.prototype.sendMessage = function sendMessage(where, content) { + var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; + var callback = arguments.length <= 3 || arguments[3] === undefined ? function () /*e, m*/{} : arguments[3]; + + if (typeof options === "function") { + // options is the callback + callback = options; + } + + return this.internal.sendMessage(where, content, options).then(function (m) { + callback(null, m); + return m; + }, errCB(callback)); + }; + + // def sendTTSMessage + + Client.prototype.sendTTSMessage = function sendTTSMessage(where, content) { + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*e, m*/{} : arguments[2]; + + return this.sendMessage(where, content, { tts: true }).then(function (m) { + callback(null, m); + return m; + }, errCB(callback)); + }; + + // def reply + + Client.prototype.reply = function reply(where, content) { + var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; + var callback = arguments.length <= 3 || arguments[3] === undefined ? function () /*e, m*/{} : arguments[3]; + + if (typeof options === "function") { + // options is the callback + callback = options; + } + + var msg = this.internal.resolver.resolveMessage(where); + if (msg) { + content = msg.author + ", " + content; + return this.internal.sendMessage(msg, content, options).then(function (m) { + callback(null, m); + return m; + }, errCB(callback)); + } + var err = new Error("Destination not resolvable to a message!"); + callback(err); + return Promise.reject(err); + }; + + // def replyTTS + + Client.prototype.replyTTS = function replyTTS(where, content) { + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /**/{} : arguments[2]; + + return this.reply(where, content, { tts: true }).then(function (m) { + callback(null, m); + return m; + }, errCB(callback)); + }; + + // def deleteMessage + + Client.prototype.deleteMessage = function deleteMessage(msg) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*e*/{} : arguments[2]; + + if (typeof options === "function") { + // options is the callback + callback = options; + } + + return this.internal.deleteMessage(msg, options).then(callback, errCB(callback)); + }; + + //def updateMessage + + Client.prototype.updateMessage = function updateMessage(msg, content) { + var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; + var callback = arguments.length <= 3 || arguments[3] === undefined ? function () /*err, msg*/{} : arguments[3]; + + if (typeof options === "function") { + // options is the callback + callback = options; + } + + return this.internal.updateMessage(msg, content, options).then(function (msg) { + callback(null, msg); + return msg; + }, errCB(callback)); + }; + + // def getChannelLogs + + Client.prototype.getChannelLogs = function getChannelLogs(where) { + var limit = arguments.length <= 1 || arguments[1] === undefined ? 500 : arguments[1]; + var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; + var callback = arguments.length <= 3 || arguments[3] === undefined ? function () /*err, logs*/{} : arguments[3]; + + if (typeof options === "function") { + // options is the callback + callback = options; + } + + return this.internal.getChannelLogs(where, limit, options).then(function (logs) { + callback(null, logs); + return logs; + }, errCB(callback)); + }; + + // def getBans + + Client.prototype.getBans = function getBans(where) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function () /*err, bans*/{} : arguments[1]; + + return this.internal.getBans(where).then(function (bans) { + callback(null, bans); + return bans; + }, errCB(callback)); + }; + + // def sendFile + + Client.prototype.sendFile = function sendFile(where, attachment) { + var name = arguments.length <= 2 || arguments[2] === undefined ? "image.png" : arguments[2]; + var callback = arguments.length <= 3 || arguments[3] === undefined ? function () /*err, m*/{} : arguments[3]; + + return this.internal.sendFile(where, attachment, name).then(function (m) { + callback(null, m); + return m; + }, errCB(callback)); + }; + + // def joinServer + + Client.prototype.joinServer = function joinServer(invite) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function () /*err, srv*/{} : arguments[1]; + + return this.internal.joinServer(invite).then(function (srv) { + callback(null, srv); + return srv; + }, errCB(callback)); + }; + + // def createServer + + Client.prototype.createServer = function createServer(name) { + var region = arguments.length <= 1 || arguments[1] === undefined ? "london" : arguments[1]; + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*err, srv*/{} : arguments[2]; + + return this.internal.createServer(name, region).then(function (srv) { + callback(null, srv); + return srv; + }, errCB(callback)); + }; + + // def leaveServer + + Client.prototype.leaveServer = function leaveServer(server) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function () /*err*/{} : arguments[1]; + + return this.internal.leaveServer(server).then(callback, errCB(callback)); + }; + + // def createChannel + + Client.prototype.createChannel = function createChannel(server, name) { + var type = arguments.length <= 2 || arguments[2] === undefined ? "text" : arguments[2]; + var callback = arguments.length <= 3 || arguments[3] === undefined ? function () /*err, channel*/{} : arguments[3]; + + if (typeof type === "function") { + // options is the callback + callback = type; + } + return this.internal.createChannel(server, name, type).then(function (channel) { + callback(channel); + return channel; + }, errCB(callback)); + }; + + // def deleteChannel + + Client.prototype.deleteChannel = function deleteChannel(channel) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function () /*err*/{} : arguments[1]; + + return this.internal.deleteChannel(channel).then(callback, errCB(callback)); + }; + + //def banMember + + Client.prototype.banMember = function banMember(user, server) { + var length = arguments.length <= 2 || arguments[2] === undefined ? 1 : arguments[2]; + var callback = arguments.length <= 3 || arguments[3] === undefined ? function () /*err*/{} : arguments[3]; + + if (typeof length === "function") { + // length is the callback + callback = length; + } + return this.internal.banMember(user, server, length).then(callback, errCB(callback)); + }; + + //def unbanMember + + Client.prototype.unbanMember = function unbanMember(user, server) { + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*err*/{} : arguments[2]; + + return this.internal.unbanMember(user, server).then(callback, errCB(callback)); + }; + + //def kickMember + + Client.prototype.kickMember = function kickMember(user, server) { + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*err*/{} : arguments[2]; + + return this.internal.kickMember(user, server).then(callback, errCB(callback)); + }; + + //def createRole + + Client.prototype.createRole = function createRole(server) { + var data = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*err, res*/{} : arguments[2]; + + if (typeof data === "function") { + // data is the callback + callback = data; + } + return this.internal.createRole(server, data).then(function (role) { + callback(null, role); + return role; + }, errCB(callback)); + }; + + //def updateRole + + Client.prototype.updateRole = function updateRole(role) { + var data = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*err, res*/{} : arguments[2]; + + if (typeof data === "function") { + // data is the callback + callback = data; + } + return this.internal.updateRole(role, data).then(function (role) { + callback(null, role); + return role; + }, errCB(callback)); + }; + + //def deleteRole + + Client.prototype.deleteRole = function deleteRole(role) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function () /*err*/{} : arguments[1]; + + return this.internal.deleteRole(role).then(callback, errCB(callback)); + }; + + //def addMemberToRole + + Client.prototype.addMemberToRole = function addMemberToRole(member, role) { + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*err*/{} : arguments[2]; + + return this.internal.addMemberToRole(member, role).then(callback, errCB(callback)); + }; + + // def addUserToRole + + Client.prototype.addUserToRole = function addUserToRole(member, role) { + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*err*/{} : arguments[2]; + + return this.addMemberToRole(member, role, callback); + }; + + // def removeMemberFromRole + + Client.prototype.removeMemberFromRole = function removeMemberFromRole(member, role) { + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*err*/{} : arguments[2]; + + return this.internal.removeMemberFromRole(member, role).then(callback, errCB(callback)); + }; + + // def removeUserFromRole + + Client.prototype.removeUserFromRole = function removeUserFromRole(member, role) { + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*err*/{} : arguments[2]; + + return this.removeMemberFromRole(member, role, callback); + }; + + // def createInvite + + Client.prototype.createInvite = function createInvite(chanServ, options) { + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*err, invite*/{} : arguments[2]; + + if (typeof options === "function") { + // length is the callback + callback = options; + } + + return this.internal.createInvite(chanServ, options).then(function (invite) { + callback(null, invite); + }, errCB(callback)); + }; + + // def deleteInvite + + Client.prototype.deleteInvite = function deleteInvite(invite) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function () /*err*/{} : arguments[1]; + + return this.internal.deleteInvite(invite).then(callback, errCB(callback)); + }; + + // def overwritePermissions + + Client.prototype.overwritePermissions = function overwritePermissions(channel, role) { + var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; + var callback = arguments.length <= 3 || arguments[3] === undefined ? function () /*err*/{} : arguments[3]; + + return this.internal.overwritePermissions(channel, role, options).then(callback, errCB(callback)); + }; + + //def setStatus + + Client.prototype.setStatus = function setStatus(idleStatus, gameID) { + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*err*/{} : arguments[2]; + + if (typeof gameID === "function") { + // gameID is the callback + callback = gameID; + } else if (typeof idleStatus === "function") { + // idleStatus is the callback + callback = idleStatus; + } + + return this.internal.setStatus(idleStatus, gameID).then(callback, errCB(callback)); + }; + + //def sendTyping + + Client.prototype.sendTyping = function sendTyping(channel) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function () /*err*/{} : arguments[1]; + + return this.internal.sendTyping(channel).then(callback, errCB(callback)); + }; + + // def setTopic + + Client.prototype.setTopic = function setTopic(channel, topic) { + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*err*/{} : arguments[2]; + + return this.internal.setTopic(channel, topic).then(callback, errCB(callback)); + }; + + //def setChannelName + + Client.prototype.setChannelName = function setChannelName(channel, name) { + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*err*/{} : arguments[2]; + + return this.internal.setChannelName(channel, name).then(callback, errCB(callback)); + }; + + //def setChannelNameAndTopic + + Client.prototype.setChannelNameAndTopic = function setChannelNameAndTopic(channel, name, topic) { + var callback = arguments.length <= 3 || arguments[3] === undefined ? function () /*err*/{} : arguments[3]; + + return this.internal.setChannelNameAndTopic(channel, name, topic).then(callback, errCB(callback)); + }; + + //def updateChannel + + Client.prototype.updateChannel = function updateChannel(channel, data) { + var callback = arguments.length <= 2 || arguments[2] === undefined ? function () /*err*/{} : arguments[2]; + + return this.internal.updateChannel(channel, data).then(callback, errCB(callback)); + }; + + //def startTyping + + Client.prototype.startTyping = function startTyping(channel) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function () /*err*/{} : arguments[1]; + + return this.internal.startTyping(channel).then(callback, errCB(callback)); + }; + + //def stopTyping + + Client.prototype.stopTyping = function stopTyping(channel) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function () /*err*/{} : arguments[1]; + + return this.internal.stopTyping(channel).then(callback, errCB(callback)); + }; + + //def updateDetails + + Client.prototype.updateDetails = function updateDetails(details) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function () /*err*/{} : arguments[1]; + + return this.internal.updateDetails(details).then(callback, errCB(callback)); + }; + + //def setUsername + + Client.prototype.setUsername = function setUsername(name) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function () /*err*/{} : arguments[1]; + + return this.internal.setUsername(name).then(callback, errCB(callback)); + }; + + //def setAvatar + + Client.prototype.setAvatar = function setAvatar(avatar) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function () /*err*/{} : arguments[1]; + + return this.internal.setAvatar(avatar).then(callback, errCB(callback)); + }; + + //def joinVoiceChannel + + Client.prototype.joinVoiceChannel = function joinVoiceChannel(channel) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function () /*err*/{} : arguments[1]; + + return this.internal.joinVoiceChannel(channel).then(function (chan) { + callback(null, chan); + return chan; + }, errCB(callback)); + }; + + // def leaveVoiceChannel + + Client.prototype.leaveVoiceChannel = function leaveVoiceChannel() { + var callback = arguments.length <= 0 || arguments[0] === undefined ? function () /*err*/{} : arguments[0]; + + return this.internal.leaveVoiceChannel().then(callback, errCB(callback)); + }; + + // def awaitResponse + + Client.prototype.awaitResponse = function awaitResponse(msg) { + var toSend = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; + + var _this = this; + + var options = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2]; + var callback = arguments.length <= 3 || arguments[3] === undefined ? function () /*e, newMsg*/{} : arguments[3]; + + var ret; + + if (toSend) { + if (typeof toSend === "function") { + // (msg, callback) + callback = toSend; + } else { + // (msg, toSend, ...) + if (options) { + if (typeof options === "function") { + //(msg, toSend, callback) + callback = options; + ret = this.sendMessage(msg, toSend); + } else { + //(msg, toSend, options, callback) + ret = this.sendMessage(msg, toSend, options); + } + } else { + // (msg, toSend) promise + ret = this.sendMessage(msg, toSend); + } + } + } + + if (!ret) { + ret = Promise.resolve(); + } + // (msg) promise + return ret.then(function () { + return _this.internal.awaitResponse(msg); + }).then(function (newMsg) { + callback(null, newMsg); + return newMsg; + }, errCB(callback)); + }; + + Client.prototype.setStatusIdle = function setStatusIdle() { + var callback = arguments.length <= 0 || arguments[0] === undefined ? function () /*err*/{} : arguments[0]; + + return this.internal.setStatus("idle").then(callback, errCB(callback)); + }; + + Client.prototype.setStatusOnline = function setStatusOnline() { + var callback = arguments.length <= 0 || arguments[0] === undefined ? function () /*err*/{} : arguments[0]; + + return this.internal.setStatus("online").then(callback, errCB(callback)); + }; + + Client.prototype.setStatusActive = function setStatusActive(callback) { + return this.setStatusOnline(callback); + }; + + Client.prototype.setStatusHere = function setStatusHere(callback) { + return this.setStatusOnline(callback); + }; + + Client.prototype.setStatusAvailable = function setStatusAvailable(callback) { + return this.setStatusOnline(callback); + }; + + Client.prototype.setStatusAway = function setStatusAway(callback) { + return this.setStatusIdle(callback); + }; + + Client.prototype.setPlayingGame = function setPlayingGame(game) { + return this.setStatus(null, game); + }; + + _createClass(Client, [{ + key: "users", + get: function get() { + return this.internal.users; + } + }, { + key: "channels", + get: function get() { + return this.internal.channels; + } + }, { + key: "servers", + get: function get() { + return this.internal.servers; + } + }, { + key: "privateChannels", + get: function get() { + return this.internal.private_channels; + } + }, { + key: "voiceConnection", + get: function get() { + return this.internal.voiceConnection; + } + }, { + key: "readyTime", + get: function get() { + return this.internal.readyTime; + } + }, { + key: "uptime", + get: function get() { + return this.internal.uptime; + } + }, { + key: "user", + get: function get() { + return this.internal.user; + } + }]); + + return Client; +})(_events2["default"]); + +exports["default"] = Client; +module.exports = exports["default"]; diff --git a/lib/Client/ConnectionState.js b/lib/Client/ConnectionState.js new file mode 100644 index 000000000..b17e17a5e --- /dev/null +++ b/lib/Client/ConnectionState.js @@ -0,0 +1,11 @@ +"use strict"; + +exports.__esModule = true; +exports["default"] = { + IDLE: 0, + LOGGING_IN: 1, + LOGGED_IN: 2, + READY: 3, + DISCONNECTED: 4 +}; +module.exports = exports["default"]; diff --git a/lib/Client/InternalClient.js b/lib/Client/InternalClient.js new file mode 100644 index 000000000..1a1329c07 --- /dev/null +++ b/lib/Client/InternalClient.js @@ -0,0 +1,1419 @@ +"use strict"; + +exports.__esModule = true; + +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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var _superagent = require("superagent"); + +var _superagent2 = _interopRequireDefault(_superagent); + +var _ws = require("ws"); + +var _ws2 = _interopRequireDefault(_ws); + +var _ConnectionState = require("./ConnectionState"); + +var _ConnectionState2 = _interopRequireDefault(_ConnectionState); + +var _querystring = require("querystring"); + +var _querystring2 = _interopRequireDefault(_querystring); + +var _Constants = require("../Constants"); + +var _UtilCache = require("../Util/Cache"); + +var _UtilCache2 = _interopRequireDefault(_UtilCache); + +var _ResolverResolver = require("./Resolver/Resolver"); + +var _ResolverResolver2 = _interopRequireDefault(_ResolverResolver); + +var _StructuresUser = require("../Structures/User"); + +var _StructuresUser2 = _interopRequireDefault(_StructuresUser); + +var _StructuresChannel = require("../Structures/Channel"); + +var _StructuresChannel2 = _interopRequireDefault(_StructuresChannel); + +var _StructuresTextChannel = require("../Structures/TextChannel"); + +var _StructuresTextChannel2 = _interopRequireDefault(_StructuresTextChannel); + +var _StructuresVoiceChannel = require("../Structures/VoiceChannel"); + +var _StructuresVoiceChannel2 = _interopRequireDefault(_StructuresVoiceChannel); + +var _StructuresPMChannel = require("../Structures/PMChannel"); + +var _StructuresPMChannel2 = _interopRequireDefault(_StructuresPMChannel); + +var _StructuresServer = require("../Structures/Server"); + +var _StructuresServer2 = _interopRequireDefault(_StructuresServer); + +var _StructuresMessage = require("../Structures/Message"); + +var _StructuresMessage2 = _interopRequireDefault(_StructuresMessage); + +var _StructuresRole = require("../Structures/Role"); + +var _StructuresRole2 = _interopRequireDefault(_StructuresRole); + +var _StructuresInvite = require("../Structures/Invite"); + +var _StructuresInvite2 = _interopRequireDefault(_StructuresInvite); + +var _VoiceVoiceConnection = require("../Voice/VoiceConnection"); + +var _VoiceVoiceConnection2 = _interopRequireDefault(_VoiceVoiceConnection); + +var zlib; + +//todo: move this somewhere else +var originalEnd = _superagent2["default"].Request.prototype.end; +_superagent2["default"].Request.prototype.end = function (callback) { + var _this = this; + + return new Promise(function (resolve, reject) { + originalEnd.call(_this, function (err, response) { + if (callback) { + callback(err, response); + } + + if (err) { + return reject(err); + } + resolve(response); + }); + }); +}; + +function waitFor(condition) { + var value = arguments.length <= 1 || arguments[1] === undefined ? condition : arguments[1]; + var interval = arguments.length <= 2 || arguments[2] === undefined ? 20 : arguments[2]; + return (function () { + return new Promise(function (resolve) { + var int = setInterval(function () { + var isDone = condition(); + if (isDone) { + if (condition === value) { + resolve(isDone); + } else { + resolve(value(isDone)); + } + return clearInterval(int); + } + }, interval); + }); + })(); +} + +function delay(ms) { + return new Promise(function (resolve) { + return setTimeout(resolve, ms); + }); +} + +var InternalClient = (function () { + function InternalClient(discordClient) { + _classCallCheck(this, InternalClient); + + this.client = discordClient; + this.state = _ConnectionState2["default"].IDLE; + this.websocket = null; + + if (this.client.options.compress) { + zlib = require("zlib"); + } + + // creates 4 caches with discriminators based on ID + this.users = new _UtilCache2["default"](); + this.channels = new _UtilCache2["default"](); + this.servers = new _UtilCache2["default"](); + this.private_channels = new _UtilCache2["default"](); + this.typingIntervals = []; + this.voiceConnection = null; + this.resolver = new _ResolverResolver2["default"](this); + this.readyTime = null; + + this.messageAwaits = {}; + } + + //def leaveVoiceChannel + + InternalClient.prototype.leaveVoiceChannel = function leaveVoiceChannel() { + if (this.voiceConnection) { + this.voiceConnection.destroy(); + this.voiceConnection = null; + } + return Promise.resolve(); + }; + + //def awaitResponse + + InternalClient.prototype.awaitResponse = function awaitResponse(msg) { + var _this2 = this; + + return new Promise(function (resolve, reject) { + + msg = _this2.resolver.resolveMessage(msg); + + if (!msg) { + reject(new Error("message undefined")); + return; + } + + var awaitID = msg.channel.id + msg.author.id; + + if (!_this2.messageAwaits[awaitID]) { + _this2.messageAwaits[awaitID] = []; + } + + _this2.messageAwaits[awaitID].push(resolve); + }); + }; + + //def joinVoiceChannel + + InternalClient.prototype.joinVoiceChannel = function joinVoiceChannel(chann) { + var _this3 = this; + + var channel = this.resolver.resolveVoiceChannel(chann); + + if (!channel) { + return Promise.reject(new Error("voice channel does not exist")); + } + return this.leaveVoiceChannel().then(function () { + return new Promise(function (resolve, reject) { + var session, + token, + server = channel.server, + endpoint; + + var check = function check(m) { + var data = JSON.parse(m); + if (data.t === "VOICE_STATE_UPDATE") { + session = data.d.session_id; + } else if (data.t === "VOICE_SERVER_UPDATE") { + token = data.d.token; + endpoint = data.d.endpoint; + var chan = _this3.voiceConnection = new _VoiceVoiceConnection2["default"](channel, _this3.client, session, token, server, endpoint); + + chan.on("ready", function () { + return resolve(chan); + }); + chan.on("error", reject); + + _this3.client.emit("debug", "removed temporary voice websocket listeners"); + _this3.websocket.removeListener("message", check); + } + }; + + _this3.websocket.on("message", check); + _this3.sendWS({ + op: 4, + d: { + "guild_id": server.id, + "channel_id": channel.id, + "self_mute": false, + "self_deaf": false + } + }); + }); + }); + }; + + // def createServer + + InternalClient.prototype.createServer = function createServer(name) { + var _this4 = this; + + var region = arguments.length <= 1 || arguments[1] === undefined ? "london" : arguments[1]; + + name = this.resolver.resolveString(name); + + return _superagent2["default"].post(_Constants.Endpoints.SERVERS).set("authorization", this.token).send({ name: name, region: region }).end().then(function (res) { + // valid server, wait until it is cached + return waitFor(function () { + return _this4.servers.get("id", res.body.guild.id); + }); + }); + }; + + //def joinServer + + InternalClient.prototype.joinServer = function joinServer(invite) { + var _this5 = this; + + invite = this.resolver.resolveInviteID(invite); + if (!invite) { + return Promise.reject(new Error("Not a valid invite")); + } + return _superagent2["default"].post(_Constants.Endpoints.INVITE(invite)).set("authorization", this.token).end().then(function (res) { + // valid server, wait until it is received via ws and cached + return waitFor(function () { + return _this5.servers.get("id", res.body.guild.id); + }); + }); + }; + + //def leaveServer + + InternalClient.prototype.leaveServer = function leaveServer(srv) { + var _this6 = this; + + var server = this.resolver.resolveServer(srv); + if (!server) { + return Promise.reject(new Error("server did not resolve")); + } + + return _superagent2["default"].del(_Constants.Endpoints.SERVER(server.id)).set("authorization", this.token).end().then(function () { + // remove channels of server then the server + for (var _iterator = server.channels, _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 chan = _ref; + + _this6.channels.remove(chan); + } + // remove server + _this6.servers.remove(server); + }); + }; + + // def login + + InternalClient.prototype.login = function login(email, password) { + var _this7 = this; + + var client = this.client; + if (this.state !== _ConnectionState2["default"].DISCONNECTED && this.state !== _ConnectionState2["default"].IDLE) { + return Promise.reject(new Error("already logging in/logged in/ready!")); + } + + this.state = _ConnectionState2["default"].LOGGING_IN; + + return _superagent2["default"].post(_Constants.Endpoints.LOGIN).send({ + email: email, + password: password + }).end().then(function (res) { + var token = res.body.token; + _this7.state = _ConnectionState2["default"].LOGGED_IN; + _this7.token = token; + _this7.email = email; + _this7.password = password; + + return _this7.getGateway().then(function (url) { + _this7.createWS(url); + return token; + }); + }, function (error) { + _this7.websocket = null; + throw error; + })["catch"](function (error) { + _this7.state = _ConnectionState2["default"].DISCONNECTED; + client.emit("disconnected"); + throw error; + }); + }; + + // def logout + + InternalClient.prototype.logout = function logout() { + var _this8 = this; + + if (this.state === _ConnectionState2["default"].DISCONNECTED || this.state === _ConnectionState2["default"].IDLE) { + return Promise.reject(new Error("Client is not logged in!")); + } + + return _superagent2["default"].post(_Constants.Endpoints.LOGOUT).set("authorization", this.token).end().then(function () { + if (_this8.websocket) { + _this8.websocket.close(); + _this8.websocket = null; + } + _this8.token = null; + _this8.email = null; + _this8.password = null; + _this8.state = _ConnectionState2["default"].DISCONNECTED; + }); + }; + + // def startPM + + InternalClient.prototype.startPM = function startPM(resUser) { + var _this9 = this; + + var user = this.resolver.resolveUser(resUser); + if (!user) { + return Promise.reject(new Error("Unable to resolve resUser to a User")); + } + // start the PM + return _superagent2["default"].post("" + _Constants.Endpoints.USER_CHANNELS(user.id)).set("authorization", this.token).send({ + recipient_id: user.id + }).end().then(function (res) { + return _this9.private_channels.add(new _StructuresPMChannel2["default"](res.body, _this9.client)); + }); + }; + + // def getGateway + + InternalClient.prototype.getGateway = function getGateway() { + return _superagent2["default"].get(_Constants.Endpoints.GATEWAY).set("authorization", this.token).end().then(function (res) { + return res.body.url; + }); + }; + + // def sendMessage + + InternalClient.prototype.sendMessage = function sendMessage(where, _content) { + var _this10 = this; + + var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; + + return this.resolver.resolveChannel(where).then(function (destination) { + //var destination; + var content = _this10.resolver.resolveString(_content); + var mentions = _this10.resolver.resolveMentions(content); + + return _superagent2["default"].post(_Constants.Endpoints.CHANNEL_MESSAGES(destination.id)).set("authorization", _this10.token).send({ + content: content, + mentions: mentions, + tts: options.tts + }).end().then(function (res) { + return destination.messages.add(new _StructuresMessage2["default"](res.body, destination, _this10.client)); + }); + }); + }; + + // def deleteMessage + + InternalClient.prototype.deleteMessage = function deleteMessage(_message) { + var _this11 = this; + + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var message = this.resolver.resolveMessage(_message); + if (!message) { + return Promise.reject(new Error("Supplied message did not resolve to a message!")); + } + + var chain = options.wait ? delay(options.wait) : Promise.resolve(); + return chain.then(function () { + return _superagent2["default"].del(_Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id)).set("authorization", _this11.token).end(); + }).then(function () { + return message.channel.messages.remove(message); + }); + }; + + // def updateMessage + + InternalClient.prototype.updateMessage = function updateMessage(msg, _content) { + var _this12 = this; + + var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; + + var message = this.resolver.resolveMessage(msg); + + if (!message) { + return Promise.reject(new Error("Supplied message did not resolve to a message!")); + } + + var content = this.resolver.resolveString(_content); + var mentions = this.resolver.resolveMentions(content); + + return _superagent2["default"].patch(_Constants.Endpoints.CHANNEL_MESSAGE(message.channel.id, message.id)).set("authorization", this.token).send({ + content: content, + tts: options.tts, + mentions: mentions + }).end().then(function (res) { + return message.channel.messages.update(message, new _StructuresMessage2["default"](res.body, message.channel, _this12.client)); + }); + }; + + // def sendFile + + InternalClient.prototype.sendFile = function sendFile(where, _file) { + var _this13 = this; + + var name = arguments.length <= 2 || arguments[2] === undefined ? "image.png" : arguments[2]; + + return this.resolver.resolveChannel(where).then(function (channel) { + return _superagent2["default"].post(_Constants.Endpoints.CHANNEL_MESSAGES(channel.id)).set("authorization", _this13.token).attach("file", _this13.resolver.resolveFile(_file), name).end().then(function (res) { + return channel.messages.add(new _StructuresMessage2["default"](res.body, channel, _this13.client)); + }); + }); + }; + + // def getChannelLogs + + InternalClient.prototype.getChannelLogs = function getChannelLogs(_channel) { + var _this14 = this; + + var limit = arguments.length <= 1 || arguments[1] === undefined ? 500 : arguments[1]; + var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; + + return this.resolver.resolveChannel(_channel).then(function (channel) { + var qsObject = { limit: limit }; + if (options.before) { + var res = _this14.resolver.resolveMessage(options.before); + if (res) { + qsObject.before = res; + } + } + if (options.after) { + var res = _this14.resolver.resolveMessage(options.after); + if (res) { + qsObject.after = res; + } + } + + return _superagent2["default"].get(_Constants.Endpoints.CHANNEL_MESSAGES(channel.id) + "?" + _querystring2["default"].stringify(qsObject)).set("authorization", _this14.token).end().then(function (res) { + return res.body.map(function (msg) { + return channel.messages.add(new _StructuresMessage2["default"](msg, channel, _this14.client)); + }); + }); + }); + }; + + // def getBans + + InternalClient.prototype.getBans = function getBans(server) { + var _this15 = this; + + server = this.resolver.resolveServer(server); + + return _superagent2["default"].get("" + _Constants.Endpoints.SERVER_BANS(server.id)).set("authorization", this.token).end().then(function (res) { + res.body.map(function (ban) { + return _this15.users.add(new _StructuresUser2["default"](ban.user, _this15.client)); + }); + }); + }; + + // def createChannel + + InternalClient.prototype.createChannel = function createChannel(server, name) { + var _this16 = this; + + var type = arguments.length <= 2 || arguments[2] === undefined ? "text" : arguments[2]; + + server = this.resolver.resolveServer(server); + + return _superagent2["default"].post(_Constants.Endpoints.SERVER_CHANNELS(server.id)).set("authorization", this.token).send({ + name: name, + type: type + }).end().then(function (res) { + var channel; + if (res.body.type === "text") { + channel = new _StructuresTextChannel2["default"](res.body, _this16.client, server); + } + channel = new _StructuresVoiceChannel2["default"](res.body, _this16.client, server); + return server.channels.add(_this16.channels.add(channel)); + }); + }; + + // def deleteChannel + + InternalClient.prototype.deleteChannel = function deleteChannel(_channel) { + var _this17 = this; + + return this.resolver.resolveChannel(_channel).then(function (channel) { + return _superagent2["default"].del(_Constants.Endpoints.CHANNEL(channel.id)).set("authorization", _this17.token).end().then(function () { + channel.server.channels.remove(channel); + _this17.channels.remove(channel); + }); + }, function (error) { + error.message = "Couldn't resolve to channel - " + error.toString(); + throw error; + }); + }; + + // def banMember + + InternalClient.prototype.banMember = function banMember(user, server) { + var length = arguments.length <= 2 || arguments[2] === undefined ? 1 : arguments[2]; + + user = this.resolver.resolveUser(user); + server = this.resolver.resolveServer(server); + + return _superagent2["default"].put(_Constants.Endpoints.SERVER_BANS(server.id) + "/" + user.id + "?delete-message-days=" + length).set("authorization", this.token).end(); //will expose api result, probably not bad tho + }; + + // def unbanMember + + InternalClient.prototype.unbanMember = function unbanMember(user, server) { + + server = this.resolver.resolveServer(server); + user = this.resolver.resolveUser(user); + + return _superagent2["default"].del(_Constants.Endpoints.SERVER_BANS(server.id) + "/" + user.id).set("authorization", this.token).end(); //will expose api result, probably not bad tho + }; + + // def kickMember + + InternalClient.prototype.kickMember = function kickMember(user, server) { + user = this.resolver.resolveUser(user); + server = this.resolver.resolveServer(server); + + return _superagent2["default"].del(_Constants.Endpoints.SERVER_MEMBERS(server.id) + "/" + user.id).set("authorization", this.token).end(); + }; + + // def createRole + + InternalClient.prototype.createRole = function createRole(server, data) { + var _this18 = this; + + server = this.resolver.resolveServer(server); + + return _superagent2["default"].post(_Constants.Endpoints.SERVER_ROLES(server.id)).set("authorization", this.token).end().then(function (res) { + var role = server.roles.add(new _StructuresRole2["default"](res.body, server, _this18.client)); + + if (data) { + return _this18.updateRole(role, data); + } + return role; + }); + }; + + // def updateRole + + InternalClient.prototype.updateRole = function updateRole(role, data) { + var _this19 = this; + + var server = this.resolver.resolveServer(role.server); + + var newData = { + color: data.color || role.color, + hoist: data.hoist || role.hoist, + name: data.name || role.name, + permissions: role.permissions || 0 + }; + + if (data.permissions) { + newData.permissions = 0; + for (var _iterator2 = data.permissions, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var perm = _ref2; + + if (perm instanceof String || typeof perm === "string") { + newData.permissions |= _Constants.Permissions[perm] || 0; + } else { + newData.permissions |= perm; + } + } + } + + return _superagent2["default"].patch(_Constants.Endpoints.SERVER_ROLES(server.id) + "/" + role.id).set("authorization", this.token).send(newData).end().then(function (res) { + return server.roles.update(role, new _StructuresRole2["default"](res.body, server, _this19.client)); + }); + }; + + // def deleteRole + + InternalClient.prototype.deleteRole = function deleteRole(role) { + return _superagent2["default"].del(_Constants.Endpoints.SERVER_ROLES(role.server.id) + "/" + role.id).set("authorization", this.token).end(); + }; + + //def addMemberToRole + + InternalClient.prototype.addMemberToRole = function addMemberToRole(member, role) { + member = this.resolver.resolveUser(member); + + if (!member || !role) { + return Promise.reject(new Error("member/role not in server")); + } + + if (!role.server.memberMap[member.id]) { + return Promise.reject(new Error("member not in server")); + } + + var roleIDS = role.server.memberMap[member.id].roles.map(function (r) { + return r.id; + }).concat(role.id); + + return _superagent2["default"].patch(_Constants.Endpoints.SERVER_MEMBERS(role.server.id) + "/" + member.id).set("authorization", this.token).send({ + roles: roleIDS + }).end(); + }; + + //def removeMemberFromRole + + InternalClient.prototype.removeMemberFromRole = function removeMemberFromRole(member, role) { + member = this.resolver.resolveUser(member); + + if (!member || !role) { + return Promise.reject(new Error("member/role not in server")); + } + + if (!role.server.memberMap[member.id]) { + return Promise.reject(new Error("member not in server")); + } + + var roleIDS = role.server.memberMap[member.id].roles.map(function (r) { + return r.id; + }); + + for (var item in roleIDS) { + if (roleIDS[item] === role.id) { + roleIDS.splice(item, 1); + //missing break? + } + } + + return _superagent2["default"].patch(_Constants.Endpoints.SERVER_MEMBERS(role.server.id) + "/" + member.id).set("authorization", this.token).send({ + roles: roleIDS + }).end(); + }; + + // def createInvite + + InternalClient.prototype.createInvite = function createInvite(chanServ, options) { + var _this20 = this; + + if (chanServ instanceof _StructuresChannel2["default"]) { + // do something + } else if (chanServ instanceof _StructuresServer2["default"]) { + // do something + } else { + chanServ = this.resolver.resolveServer(chanServ) || this.resolver.resolveChannel(chanServ); + } + + if (!chanServ) { + throw new Error("couldn't resolve where"); + } + + if (!options) { + options = { + validate: null + }; + } else { + options.max_age = options.maxAge || 0; + options.max_uses = options.maxUses || 0; + options.temporary = options.temporary || false; + options.xkcdpass = options.xkcd || false; + } + + var epoint; + if (chanServ instanceof _StructuresChannel2["default"]) { + epoint = _Constants.Endpoints.CHANNEL_INVITES(chanServ.id); + } else { + epoint = _Constants.Endpoints.SERVER_INVITES(chanServ.id); + } + + return _superagent2["default"].post(epoint).set("authorization", this.token).send(options).end().then(function (res) { + return new _StructuresInvite2["default"](res.body, _this20.channels.get("id", res.body.channel.id), _this20.client); + }); + }; + + //def deleteInvite + + InternalClient.prototype.deleteInvite = function deleteInvite(invite) { + + invite = this.resolver.resolveInviteID(invite); + if (!invite) { + throw new Error("Not a valid invite"); + } + return _superagent2["default"].del(_Constants.Endpoints.INVITE(invite)).set("authorization", this.token).end(); + }; + + //def overwritePermissions + + InternalClient.prototype.overwritePermissions = function overwritePermissions(channel, role, updated) { + var _this21 = this; + + return this.resolver.resolveChannel(channel).then(function (channel) { + var user; + if (role instanceof _StructuresUser2["default"]) { + user = role; + } + + var data = {}; + data.allow = 0; + data.deny = 0; + + updated.allow = updated.allow || []; + updated.deny = updated.deny || []; + + if (role instanceof _StructuresRole2["default"]) { + data.id = role.id; + data.type = "role"; + } else if (user) { + data.id = user.id; + data.type = "member"; + } else { + throw new Error("role incorrect"); + } + + for (var perm in updated) { + if (updated[perm]) { + if (perm instanceof String || typeof perm === "string") { + data.allow |= _Constants.Permissions[perm] || 0; + } else { + data.allow |= perm; + } + } else { + if (perm instanceof String || typeof perm === "string") { + data.deny |= _Constants.Permissions[perm] || 0; + } else { + data.deny |= perm; + } + } + } + + return _superagent2["default"].put(_Constants.Endpoints.CHANNEL_PERMISSIONS(channel.id) + "/" + data.id).set("authorization", _this21.token).send(data).end(); + }); + }; + + //def setStatus + + InternalClient.prototype.setStatus = function setStatus(idleStatus, gameID) { + + this.idleStatus = idleStatus || this.idleStatus || null; + if (idleStatus) { + if (idleStatus === "online" || idleStatus === "here" || idleStatus === "available") { + this.idleStatus = null; + } + } + this.gameID = this.resolver.resolveGameID(gameID) || this.gameID || null; + + var packet = { + op: 3, + d: { + idle_since: this.idleStatus, + game_id: this.gameID + } + }; + + if (this.idleStatus === "idle" || this.idleStatus === "away") { + packet.d.idle_since = Date.now(); + } + + this.sendWS(packet); + + return Promise.resolve(); //why? + }; + + //def sendTyping + + InternalClient.prototype.sendTyping = function sendTyping(channel) { + var _this22 = this; + + return this.resolver.resolveChannel(channel).then(function (channel) { + return _superagent2["default"].post(_Constants.Endpoints.CHANNEL(channel.id) + "/typing").set("authorization", _this22.token).end(); + }); + }; + + //def startTyping + + InternalClient.prototype.startTyping = function startTyping(channel) { + var _this23 = this; + + return this.resolver.resolveChannel(channel).then(function (channel) { + + if (_this23.typingIntervals[channel.id]) { + // typing interval already exists, leave it alone + throw new Error("Already typing in that channel"); + } + + _this23.typingIntervals[channel.id] = setInterval(function () { + return _this23.sendTyping(channel)["catch"](function (error) { + return _this23.emit("error", error); + }); + }, 4000); + + return _this23.sendTyping(channel); + }); + }; + + //def stopTyping + + InternalClient.prototype.stopTyping = function stopTyping(channel) { + var _this24 = this; + + return this.resolver.resolveChannel(channel).then(function (channel) { + + if (!_this24.typingIntervals[channel.id]) { + // typing interval doesn't exist + throw new Error("Not typing in that channel"); + } + + clearInterval(_this24.typingIntervals[channel.id]); + _this24.typingIntervals[channel.id] = false; + }); + }; + + //def updateDetails + + InternalClient.prototype.updateDetails = function updateDetails(data) { + return _superagent2["default"].patch(_Constants.Endpoints.ME).set("authorization", this.token).send({ + avatar: this.resolver.resolveToBase64(data.avatar) || this.user.avatar, + email: data.email || this.email, + new_password: data.newPassword || null, + password: data.password || this.password, + username: data.username || this.user.username + }).end(); + }; + + //def setAvatar + + InternalClient.prototype.setAvatar = function setAvatar(avatar) { + return this.updateDetails({ avatar: avatar }); + }; + + //def setUsername + + InternalClient.prototype.setUsername = function setUsername(username) { + return this.updateDetails({ username: username }); + }; + + //def setTopic + + InternalClient.prototype.setTopic = function setTopic(chann) { + var _this25 = this; + + var topic = arguments.length <= 1 || arguments[1] === undefined ? "" : arguments[1]; + + return this.resolver.resolveChannel(chann).then(function (channel) { + return _superagent2["default"].patch(_Constants.Endpoints.CHANNEL(channel.id)).set("authorization", _this25.token).send({ + name: channel.name, + position: channel.position, + topic: topic + }).end().then(function (res) { + return channel.topic = res.body.topic; + }); + }); + }; + + //def setChannelName + + InternalClient.prototype.setChannelName = function setChannelName(chann) { + var _this26 = this; + + var name = arguments.length <= 1 || arguments[1] === undefined ? "discordjs_is_the_best" : arguments[1]; + + return this.resolver.resolveChannel(chann).then(function (channel) { + return _superagent2["default"].patch(_Constants.Endpoints.CHANNEL(channel.id)).set("authorization", _this26.token).send({ + name: name, + position: channel.position, + topic: channel.topic + }).end().then(function (res) { + return channel.name = res.body.name; + }); + }); + }; + + //def setChannelNameAndTopic + + InternalClient.prototype.setChannelNameAndTopic = function setChannelNameAndTopic(chann) { + var _this27 = this; + + var name = arguments.length <= 1 || arguments[1] === undefined ? "discordjs_is_the_best" : arguments[1]; + var topic = arguments.length <= 2 || arguments[2] === undefined ? "" : arguments[2]; + + return this.resolver.resolveChannel(chann).then(function (channel) { + return _superagent2["default"].patch(_Constants.Endpoints.CHANNEL(channel.id)).set("authorization", _this27.token).send({ + name: name, + position: channel.position, + topic: topic + }).end().then(function (res) { + channel.name = res.body.name; + channel.topic = res.body.topic; + }); + }); + }; + + //def updateChannel + + InternalClient.prototype.updateChannel = function updateChannel(chann, data) { + return this.setChannelNameAndTopic(chann, data.name, data.topic); + }; + + //def ack + + InternalClient.prototype.ack = function ack(msg) { + msg = this.resolver.resolveMessage(msg); + + if (!msg) { + Promise.reject(new Error("Message does not exist")); + } + + return _superagent2["default"].post(_Constants.Endpoints.CHANNEL_MESSAGE(msg.channel.id, msg.id) + "/ack").set("authorization", this.token).end(); + }; + + InternalClient.prototype.sendWS = function sendWS(object) { + if (this.websocket) { + this.websocket.send(JSON.stringify(object)); + } + }; + + InternalClient.prototype.createWS = function createWS(url) { + var self = this; + var client = self.client; + + if (this.websocket) { + return false; + } + + this.websocket = new _ws2["default"](url); + + this.websocket.onopen = function () { + + self.sendWS({ + op: 2, + d: { + token: self.token, + v: 3, + compress: self.client.options.compress, + properties: { + "$os": "discord.js", + "$browser": "discord.js", + "$device": "discord.js", + "$referrer": "discord.js", + "$referring_domain": "discord.js" + } + } + }); + }; + + this.websocket.onclose = function () { + self.websocket = null; + self.state = _ConnectionState2["default"].DISCONNECTED; + client.emit("disconnected"); + }; + + this.websocket.onerror = function (e) { + client.emit("error", e); + }; + + this.websocket.onmessage = function (e) { + + if (e.type === "Binary") { + if (!zlib) zlib = require("zlib"); + e.data = zlib.inflateSync(e.data).toString(); + } + + var packet, data; + try { + packet = JSON.parse(e.data); + data = packet.d; + } catch (e) { + client.emit("error", e); + return; + } + + client.emit("raw", packet); + + switch (packet.t) { + + case _Constants.PacketType.READY: + var startTime = Date.now(); + self.user = self.users.add(new _StructuresUser2["default"](data.user, client)); + data.guilds.forEach(function (server) { + self.servers.add(new _StructuresServer2["default"](server, client)); + }); + data.private_channels.forEach(function (pm) { + self.private_channels.add(new _StructuresPMChannel2["default"](pm, client)); + }); + self.state = _ConnectionState2["default"].READY; + + setInterval(function () { + return self.sendWS({ op: 1, d: Date.now() }); + }, data.heartbeat_interval); + + client.emit("ready"); + client.emit("debug", "ready packet took " + (Date.now() - startTime) + "ms to process"); + client.emit("debug", "ready with " + self.servers.length + " servers, " + self.channels.length + " channels and " + self.users.length + " users cached."); + + self.readyTime = Date.now(); + break; + + case _Constants.PacketType.MESSAGE_CREATE: + // format: https://discordapi.readthedocs.org/en/latest/reference/channels/messages.html#message-format + var channel = self.channels.get("id", data.channel_id) || self.private_channels.get("id", data.channel_id); + if (channel) { + var msg = channel.messages.add(new _StructuresMessage2["default"](data, channel, client)); + + if (self.messageAwaits[channel.id + msg.author.id]) { + self.messageAwaits[channel.id + msg.author.id].map(function (fn) { + return fn(msg); + }); + self.messageAwaits[channel.id + msg.author.id] = null; + client.emit("message", msg, true); //2nd param is isAwaitedMessage + } else { + client.emit("message", msg); + } + self.ack(msg); + } else { + client.emit("warn", "message created but channel is not cached"); + } + break; + case _Constants.PacketType.MESSAGE_DELETE: + // format https://discordapi.readthedocs.org/en/latest/reference/channels/messages.html#message-delete + var channel = self.channels.get("id", data.channel_id) || self.private_channels.get("id", data.channel_id); + if (channel) { + // potentially blank + var msg = channel.messages.get("id", data.id); + client.emit("messageDeleted", msg, channel); + if (msg) { + channel.messages.remove(msg); + } + } else { + client.emit("warn", "message was deleted but channel is not cached"); + } + break; + case _Constants.PacketType.MESSAGE_UPDATE: + // format https://discordapi.readthedocs.org/en/latest/reference/channels/messages.html#message-format + var channel = self.channels.get("id", data.channel_id) || self.private_channels.get("id", data.channel_id); + if (channel) { + // potentially blank + var msg = channel.messages.get("id", data.id); + + if (msg) { + // old message exists + data.nonce = data.nonce || msg.nonce; + data.attachments = data.attachments || msg.attachments; + data.tts = data.tts || msg.tts; + data.embeds = data.embeds || msg.embeds; + data.timestamp = data.timestamp || msg.timestamp; + data.mention_everyone = data.mention_everyone || msg.everyoneMentioned; + data.content = data.content || msg.content; + data.mentions = data.mentions || msg.mentions; + data.author = data.author || msg.author; + var nmsg = channel.messages.update(msg, new _StructuresMessage2["default"](data, channel, client)); + client.emit("messageUpdated", nmsg, msg); + } + } else { + client.emit("warn", "message was updated but channel is not cached"); + } + break; + case _Constants.PacketType.SERVER_CREATE: + var server = self.servers.get("id", data.id); + if (!server) { + self.servers.add(new _StructuresServer2["default"](data, client)); + client.emit("serverCreated", server); + } + break; + case _Constants.PacketType.SERVER_DELETE: + var server = self.servers.get("id", data.id); + if (server) { + + for (var _iterator3 = server.channels, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var channel = _ref3; + + self.channels.remove(channel); + } + + self.servers.remove(server); + client.emit("serverDeleted", server); + } else { + client.emit("warn", "server was deleted but it was not in the cache"); + } + break; + case _Constants.PacketType.SERVER_UPDATE: + var server = self.servers.get("id", data.id); + if (server) { + // server exists + data.members = data.members || []; + data.channels = data.channels || []; + var newserver = new _StructuresServer2["default"](data, self); + newserver.members = server.members; + newserver.memberMap = server.memberMap; + newserver.channels = server.channels; + if (newserver.equalsStrict(server)) { + // already the same don't do anything + client.emit("debug", "received server update but server already updated"); + } else { + self.servers.update(server, newserver); + client.emit("serverUpdated", server, newserver); + } + } else if (!server) { + client.emit("warn", "server was updated but it was not in the cache"); + self.servers.add(new _StructuresServer2["default"](data, self)); + client.emit("serverCreated", server); + } + break; + case _Constants.PacketType.CHANNEL_CREATE: + + var channel = self.channels.get("id", data.id); + + if (!channel) { + + var server = self.servers.get("id", data.guild_id); + if (server) { + if (data.is_private) { + client.emit("channelCreated", self.private_channels.add(new _StructuresPMChannel2["default"](data, client))); + } else { + var chan = null; + if (data.type === "text") { + chan = self.channels.add(new _StructuresTextChannel2["default"](data, client, server)); + } else { + chan = self.channels.add(new _StructuresVoiceChannel2["default"](data, client, server)); + } + client.emit("channelCreated", server.channels.add(chan)); + } + } else { + client.emit("warn", "channel created but server does not exist"); + } + } else { + client.emit("warn", "channel created but already in cache"); + } + + break; + case _Constants.PacketType.CHANNEL_DELETE: + var channel = self.channels.get("id", data.id); + if (channel) { + + if (channel.server) // accounts for PMs + channel.server.channels.remove(channel); + + self.channels.remove(channel); + client.emit("channelDeleted", channel); + } else { + client.emit("warn", "channel deleted but already out of cache?"); + } + break; + case _Constants.PacketType.CHANNEL_UPDATE: + var channel = self.channels.get("id", data.id) || self.private_channels.get("id", data.id); + if (channel) { + + if (channel instanceof _StructuresPMChannel2["default"]) { + //PM CHANNEL + client.emit("channelUpdated", channel, self.private_channels.update(channel, new _StructuresPMChannel2["default"](data, client))); + } else { + if (channel.server) { + if (channel.type === "text") { + //TEXT CHANNEL + var chan = new _StructuresTextChannel2["default"](data, client, channel.server); + chan.messages = channel.messages; + channel.server.channels.update(channel, chan); + self.channels.update(channel, chan); + client.emit("channelUpdated", channel, chan); + } else { + //VOICE CHANNEL + var chan = new _StructuresVoiceChannel2["default"](data, client, channel.server); + channel.server.channels.update(channel, chan); + self.channels.update(channel, chan); + client.emit("channelUpdated", channel, chan); + } + } else { + client.emit("warn", "channel updated but server non-existant"); + } + } + } else { + client.emit("warn", "channel updated but not in cache"); + } + break; + case _Constants.PacketType.SERVER_ROLE_CREATE: + var server = self.servers.get("id", data.guild_id); + if (server) { + client.emit("serverRoleCreated", server.roles.add(new _StructuresRole2["default"](data.role, server, client)), server); + } else { + client.emit("warn", "server role made but server not in cache"); + } + break; + case _Constants.PacketType.SERVER_ROLE_DELETE: + var server = self.servers.get("id", data.guild_id); + if (server) { + var role = server.roles.get("id", data.role_id); + if (role) { + server.roles.remove(role); + client.emit("serverRoleDeleted", role); + } else { + client.emit("warn", "server role deleted but role not in cache"); + } + } else { + client.emit("warn", "server role deleted but server not in cache"); + } + break; + case _Constants.PacketType.SERVER_ROLE_UPDATE: + var server = self.servers.get("id", data.guild_id); + if (server) { + var role = server.roles.get("id", data.role.id); + if (role) { + var newRole = new _StructuresRole2["default"](data.role, server, client); + server.roles.update(role, newRole); + client.emit("serverRoleUpdated", role, newRole); + } else { + client.emit("warn", "server role updated but role not in cache"); + } + } else { + client.emit("warn", "server role updated but server not in cache"); + } + break; + case _Constants.PacketType.SERVER_MEMBER_ADD: + var server = self.servers.get("id", data.guild_id); + if (server) { + + server.memberMap[data.user.id] = { + roles: data.roles.map(function (pid) { + return server.roles.get("id", pid); + }), + mute: false, + deaf: false, + joinedAt: Date.parse(data.joined_at) + }; + + client.emit("serverNewMember", server, server.members.add(self.users.add(new _StructuresUser2["default"](data.user, client)))); + } else { + client.emit("warn", "server member added but server doesn't exist in cache"); + } + break; + case _Constants.PacketType.SERVER_MEMBER_REMOVE: + var server = self.servers.get("id", data.guild_id); + if (server) { + var user = self.users.get("id", data.user.id); + if (user) { + server.memberMap[data.user.id] = null; + server.members.remove(user); + client.emit("serverMemberRemoved", server, user); + } else { + client.emit("warn", "server member removed but user doesn't exist in cache"); + } + } else { + client.emit("warn", "server member removed but server doesn't exist in cache"); + } + break; + case _Constants.PacketType.SERVER_MEMBER_UPDATE: + var server = self.servers.get("id", data.guild_id); + if (server) { + var user = self.users.get("id", data.user.id); + if (user) { + server.memberMap[data.user.id].roles = data.roles.map(function (pid) { + return server.roles.get("id", pid); + }); + server.memberMap[data.user.id].mute = data.mute; + server.memberMap[data.user.id].deaf = data.deaf; + client.emit("serverMemberUpdated", server, user); + } else { + client.emit("warn", "server member removed but user doesn't exist in cache"); + } + } else { + client.emit("warn", "server member updated but server doesn't exist in cache"); + } + break; + case _Constants.PacketType.PRESENCE_UPDATE: + + var user = self.users.get("id", data.user.id); + + if (user) { + + data.user.username = data.user.username || user.username; + data.user.id = data.user.id || user.id; + data.user.avatar = data.user.avatar || user.avatar; + data.user.discriminator = data.user.discriminator || user.discriminator; + + var presenceUser = new _StructuresUser2["default"](data.user, client); + + if (presenceUser.equals(user)) { + // a real presence update + client.emit("presence", user, data.status, data.game_id); + user.status = data.status; + user.gameID = data.game_id; + } else { + // a name change or avatar change + client.emit("userUpdated", user, presenceUser); + self.users.update(user, presenceUser); + } + } else { + client.emit("warn", "presence update but user not in cache"); + } + + break; + case _Constants.PacketType.TYPING: + + var user = self.users.get("id", data.user_id); + var channel = self.channels.get("id", data.channel_id) || self.private_channels.get("id", data.channel_id); + + if (user && channel) { + if (user.typing.since) { + user.typing.since = Date.now(); + user.typing.channel = channel; + } else { + user.typing.since = Date.now(); + user.typing.channel = channel; + client.emit("userTypingStarted", user, channel); + } + setTimeout(function () { + if (Date.now() - user.typing.since > 5500) { + // they haven't typed since + user.typing.since = null; + user.typing.channel = null; + client.emit("userTypingStopped", user, channel); + } + }, 6000); + } else { + client.emit("warn", "user typing but user or channel not existant in cache"); + } + break; + case _Constants.PacketType.SERVER_BAN_ADD: + var user = self.users.get("id", data.user.id); + var server = self.servers.get("id", data.guild_id); + + if (user && server) { + client.emit("userBanned", user, server); + } else { + client.emit("warn", "user banned but user/server not in cache."); + } + break; + case _Constants.PacketType.SERVER_BAN_REMOVE: + var user = self.users.get("id", data.user.id); + var server = self.servers.get("id", data.guild_id); + + if (user && server) { + client.emit("userUnbanned", user, server); + } else { + client.emit("warn", "user unbanned but user/server not in cache."); + } + break; + } + }; + }; + + _createClass(InternalClient, [{ + key: "uptime", + get: function get() { + return this.readyTime ? Date.now() - this.readyTime : null; + } + }]); + + return InternalClient; +})(); + +exports["default"] = InternalClient; +module.exports = exports["default"]; diff --git a/lib/Client/Resolver/Resolver.js b/lib/Client/Resolver/Resolver.js new file mode 100644 index 000000000..b05ac0363 --- /dev/null +++ b/lib/Client/Resolver/Resolver.js @@ -0,0 +1,248 @@ +"use strict"; +/* global Buffer */ + +exports.__esModule = true; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var _fs = require("fs"); + +var _fs2 = _interopRequireDefault(_fs); + +var _StructuresUser = require("../../Structures/User"); + +var _StructuresUser2 = _interopRequireDefault(_StructuresUser); + +var _StructuresChannel = require("../../Structures/Channel"); + +var _StructuresChannel2 = _interopRequireDefault(_StructuresChannel); + +var _StructuresTextChannel = require("../../Structures/TextChannel"); + +var _StructuresTextChannel2 = _interopRequireDefault(_StructuresTextChannel); + +var _StructuresVoiceChannel = require("../../Structures/VoiceChannel"); + +var _StructuresVoiceChannel2 = _interopRequireDefault(_StructuresVoiceChannel); + +var _StructuresServerChannel = require("../../Structures/ServerChannel"); + +var _StructuresServerChannel2 = _interopRequireDefault(_StructuresServerChannel); + +var _StructuresPMChannel = require("../../Structures/PMChannel"); + +var _StructuresPMChannel2 = _interopRequireDefault(_StructuresPMChannel); + +var _StructuresServer = require("../../Structures/Server"); + +var _StructuresServer2 = _interopRequireDefault(_StructuresServer); + +var _StructuresMessage = require("../../Structures/Message"); + +var _StructuresMessage2 = _interopRequireDefault(_StructuresMessage); + +var _StructuresInvite = require("../../Structures/Invite"); + +var _StructuresInvite2 = _interopRequireDefault(_StructuresInvite); + +var _refGameMap = require("../../../ref/gameMap"); + +var _refGameMap2 = _interopRequireDefault(_refGameMap); + +var Resolver = (function () { + function Resolver(internal) { + _classCallCheck(this, Resolver); + + this.internal = internal; + } + + Resolver.prototype.resolveGameID = function resolveGameID(resource) { + if (!isNaN(resource) && parseInt(resource) % 1 === 0) { + return resource; + } + if (typeof resource === "string" || resource instanceof String) { + var gameName = resource.toLowerCase(); + var found = _refGameMap2["default"].find(function (game) { + return game.name.toLowerCase() === gameName; + }); + if (found) { + return found.id; + } + } + + return null; + }; + + Resolver.prototype.resolveToBase64 = function resolveToBase64(resource) { + if (resource instanceof Buffer) { + resource = resource.toString("base64"); + resource = "data:image/jpg;base64," + resource; + } + return resource; + }; + + Resolver.prototype.resolveInviteID = function resolveInviteID(resource) { + if (resource instanceof _StructuresInvite2["default"]) { + return resource.id; + } + if (typeof resource === "string" || resource instanceof String) { + if (resource.indexOf("http") === 0) { + var split = resource.split("/"); + return split.pop(); + } + return resource; + } + return null; + }; + + Resolver.prototype.resolveServer = function resolveServer(resource) { + if (resource instanceof _StructuresServer2["default"]) { + return resource; + } + if (resource instanceof _StructuresServerChannel2["default"]) { + return resource.server; + } + if (resource instanceof String || typeof resource === "string") { + return this.internal.servers.get("id", resource); + } + if (resource instanceof _StructuresMessage2["default"]) { + if (resource.channel instanceof _StructuresTextChannel2["default"]) { + return resource.server; + } + } + return null; + }; + + Resolver.prototype.resolveFile = function resolveFile(resource) { + if (typeof resource === "string" || resource instanceof String) { + return _fs2["default"].createReadStream(resource); + } + return resource; + }; + + Resolver.prototype.resolveMentions = function resolveMentions(resource) { + // resource is a string + var _mentions = []; + for (var _iterator = resource.match(/<@[^>]*>/g) || [], _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 mention = _ref; + + _mentions.push(mention.substring(2, mention.length - 1)); + } + return _mentions; + }; + + Resolver.prototype.resolveString = function resolveString(resource) { + + // accepts Array, Channel, Server, User, Message, String and anything + // toString()-able + + var final = resource; + if (resource instanceof Array) { + final = resource.join("\n"); + } + + return final.toString(); + }; + + Resolver.prototype.resolveUser = function resolveUser(resource) { + /* + accepts a Message, Channel, Server, String ID, User, PMChannel + */ + if (resource instanceof _StructuresUser2["default"]) { + return resource; + } + if (resource instanceof _StructuresMessage2["default"]) { + return resource.author; + } + if (resource instanceof _StructuresTextChannel2["default"]) { + var lmsg = resource.lastMessage; + if (lmsg) { + return lmsg.author; + } + } + if (resource instanceof _StructuresServer2["default"]) { + return resource.owner; + } + if (resource instanceof _StructuresPMChannel2["default"]) { + return resource.recipient; + } + if (resource instanceof String || typeof resource === "string") { + return this.client.internal.users.get("id", resource); + } + + return null; + }; + + Resolver.prototype.resolveMessage = function resolveMessage(resource) { + // accepts a Message, PMChannel & TextChannel + + if (resource instanceof _StructuresTextChannel2["default"] || resource instanceof _StructuresPMChannel2["default"]) { + return resource.lastMessage; + } + if (resource instanceof _StructuresMessage2["default"]) { + return resource; + } + + return null; + }; + + Resolver.prototype.resolveVoiceChannel = function resolveVoiceChannel(resource) { + // resolveChannel will also work but this is more apt + if (resource instanceof _StructuresVoiceChannel2["default"]) { + return resource; + } + return null; + }; + + Resolver.prototype.resolveChannel = function resolveChannel(resource) { + /* + accepts a Message, Channel, Server, String ID, User + */ + + if (resource instanceof _StructuresMessage2["default"]) { + return Promise.resolve(resource.channel); + } + if (resource instanceof _StructuresChannel2["default"]) { + return Promise.resolve(resource); + } + if (resource instanceof _StructuresServer2["default"]) { + return Promise.resolve(resource.channels.get("id", resource.id)); + } + if (resource instanceof String || typeof resource === "string") { + return Promise.resolve(this.internal.channels.get("id", resource)); + } + if (resource instanceof _StructuresUser2["default"]) { + // see if a PM exists + var chatFound = this.internal.private_channels.find(function (pmchat) { + return pmchat.recipient.equals(resource); + }); + if (chatFound) { + // a PM already exists! + return Promise.resolve(chatFound); + } + // PM does not exist :\ + return this.internal.startPM(resource); + } + var error = new Error("Could not resolve channel"); + error.resource = resource; + return Promise.reject(error); + }; + + return Resolver; +})(); + +exports["default"] = Resolver; +module.exports = exports["default"]; diff --git a/lib/Constants.js b/lib/Constants.js new file mode 100644 index 000000000..13b465ae1 --- /dev/null +++ b/lib/Constants.js @@ -0,0 +1,130 @@ +"use strict"; + +exports.__esModule = true; +var API = "https://discordapp.com/api"; +exports.API = API; +var Endpoints = { + // general endpoints + LOGIN: API + "/auth/login", + LOGOUT: API + "/auth/logout", + ME: API + "/users/@me", + GATEWAY: API + "/gateway", + USER_CHANNELS: function USER_CHANNELS(userID) { + return API + "/users/" + userID + "/channels"; + }, + AVATAR: function AVATAR(userID, avatar) { + return API + "/users/" + userID + "/avatars/" + avatar + ".jpg"; + }, + INVITE: function INVITE(id) { + return API + "/invite/" + id; + }, + + // servers + SERVERS: API + "/guilds", + SERVER: function SERVER(serverID) { + return Endpoints.SERVERS + "/" + serverID; + }, + SERVER_ICON: function SERVER_ICON(serverID, hash) { + return Endpoints.SERVER(serverID) + "/icons/" + hash + ".jpg"; + }, + SERVER_PRUNE: function SERVER_PRUNE(serverID) { + return Endpoints.SERVER(serverID) + "/prune"; + }, + SERVER_EMBED: function SERVER_EMBED(serverID) { + return Endpoints.SERVER(serverID) + "/embed"; + }, + SERVER_INVITES: function SERVER_INVITES(serverID) { + return Endpoints.SERVER(serverID) + "/invites"; + }, + SERVER_ROLES: function SERVER_ROLES(serverID) { + return Endpoints.SERVER(serverID) + "/roles"; + }, + SERVER_BANS: function SERVER_BANS(serverID) { + return Endpoints.SERVER(serverID) + "/bans"; + }, + SERVER_INTEGRATIONS: function SERVER_INTEGRATIONS(serverID) { + return Endpoints.SERVER(serverID) + "/integrations"; + }, + SERVER_MEMBERS: function SERVER_MEMBERS(serverID) { + return Endpoints.SERVER(serverID) + "/members"; + }, + SERVER_CHANNELS: function SERVER_CHANNELS(serverID) { + return Endpoints.SERVER(serverID) + "/channels"; + }, + + // channels + CHANNELS: API + "/channels", + CHANNEL: function CHANNEL(channelID) { + return Endpoints.CHANNELS + "/" + channelID; + }, + CHANNEL_MESSAGES: function CHANNEL_MESSAGES(channelID) { + return Endpoints.CHANNEL(channelID) + "/messages"; + }, + CHANNEL_INVITES: function CHANNEL_INVITES(channelID) { + return Endpoints.CHANNEL(channelID) + "/invites"; + }, + CHANNEL_TYPING: function CHANNEL_TYPING(channelID) { + return Endpoints.CHANNEL(channelID) + "/typing"; + }, + CHANNEL_PERMISSIONS: function CHANNEL_PERMISSIONS(channelID) { + return Endpoints.CHANNEL(channelID) + "/permissions"; + }, + CHANNEL_MESSAGE: function CHANNEL_MESSAGE(channelID, messageID) { + return Endpoints.CHANNEL_MESSAGES(channelID) + "/" + messageID; + } +}; + +exports.Endpoints = Endpoints; +var Permissions = { + // general + createInstantInvite: 1 << 0, + kickMembers: 1 << 1, + banMembers: 1 << 2, + manageRoles: 1 << 3, + managePermissions: 1 << 3, + manageChannels: 1 << 4, + manageChannel: 1 << 4, + manageServer: 1 << 5, + // text + readMessages: 1 << 10, + sendMessages: 1 << 11, + sendTTSMessages: 1 << 12, + manageMessages: 1 << 13, + embedLinks: 1 << 14, + attachFiles: 1 << 15, + readMessageHistory: 1 << 16, + mentionEveryone: 1 << 17, + // voice + voiceConnect: 1 << 20, + voiceSpeak: 1 << 21, + voiceMuteMembers: 1 << 22, + voiceDeafenMembers: 1 << 23, + voiceMoveMembers: 1 << 24, + voiceUseVAD: 1 << 25 + +}; + +exports.Permissions = Permissions; +var PacketType = { + READY: "READY", + MESSAGE_CREATE: "MESSAGE_CREATE", + MESSAGE_UPDATE: "MESSAGE_UPDATE", + MESSAGE_DELETE: "MESSAGE_DELETE", + SERVER_CREATE: "GUILD_CREATE", + SERVER_DELETE: "GUILD_DELETE", + SERVER_UPDATE: "GUILD_UPDATE", + CHANNEL_CREATE: "CHANNEL_CREATE", + CHANNEL_DELETE: "CHANNEL_DELETE", + CHANNEL_UPDATE: "CHANNEL_UPDATE", + SERVER_ROLE_CREATE: "GUILD_ROLE_CREATE", + SERVER_ROLE_DELETE: "GUILD_ROLE_DELETE", + SERVER_ROLE_UPDATE: "GUILD_ROLE_UPDATE", + SERVER_MEMBER_ADD: "GUILD_MEMBER_ADD", + SERVER_MEMBER_REMOVE: "GUILD_MEMBER_REMOVE", + SERVER_MEMBER_UPDATE: "GUILD_MEMBER_UPDATE", + PRESENCE_UPDATE: "PRESENCE_UPDATE", + TYPING: "TYPING_START", + SERVER_BAN_ADD: "GUILD_BAN_ADD", + SERVER_BAN_REMOVE: "GUILD_BAN_REMOVE" +}; +exports.PacketType = PacketType; diff --git a/lib/Structures/Channel.js b/lib/Structures/Channel.js new file mode 100644 index 000000000..c573a3a10 --- /dev/null +++ b/lib/Structures/Channel.js @@ -0,0 +1,45 @@ +"use strict"; + +exports.__esModule = true; + +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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +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 _UtilEquality = require("../Util/Equality"); + +var _UtilEquality2 = _interopRequireDefault(_UtilEquality); + +var _UtilArgumentRegulariser = require("../Util/ArgumentRegulariser"); + +var Channel = (function (_Equality) { + _inherits(Channel, _Equality); + + function Channel(data, client) { + _classCallCheck(this, Channel); + + _Equality.call(this); + this.id = data.id; + this.client = client; + } + + Channel.prototype["delete"] = function _delete() { + return this.client.deleteChannel.apply(this.client, _UtilArgumentRegulariser.reg(this, arguments)); + }; + + _createClass(Channel, [{ + key: "isPrivate", + get: function get() { + return !!this.server; + } + }]); + + return Channel; +})(_UtilEquality2["default"]); + +exports["default"] = Channel; +module.exports = exports["default"]; diff --git a/lib/Structures/ChannelPermissions.js b/lib/Structures/ChannelPermissions.js new file mode 100644 index 000000000..81773a75e --- /dev/null +++ b/lib/Structures/ChannelPermissions.js @@ -0,0 +1,78 @@ +"use strict"; + +exports.__esModule = true; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var _Constants = require("../Constants"); + +var ChannelPermissions = (function () { + function ChannelPermissions(permissions) { + _classCallCheck(this, ChannelPermissions); + + this.permissions = permissions; + } + + ChannelPermissions.prototype.serialise = function serialise(explicit) { + var _this = this; + + var hp = function hp(perm) { + return _this.hasPermission(perm, explicit); + }; + + return { + // general + createInstantInvite: hp(_Constants.Permissions.createInstantInvite), + kickMembers: hp(_Constants.Permissions.kickMembers), + banMembers: hp(_Constants.Permissions.banMembers), + managePermissions: hp(_Constants.Permissions.managePermissions), + manageChannel: hp(_Constants.Permissions.manageChannel), + manageServer: hp(_Constants.Permissions.manageServer), + // text + readMessages: hp(_Constants.Permissions.readMessages), + sendMessages: hp(_Constants.Permissions.sendMessages), + sendTTSMessages: hp(_Constants.Permissions.sendTTSMessages), + manageMessages: hp(_Constants.Permissions.manageMessages), + embedLinks: hp(_Constants.Permissions.embedLinks), + attachFiles: hp(_Constants.Permissions.attachFiles), + readMessageHistory: hp(_Constants.Permissions.readMessageHistory), + mentionEveryone: hp(_Constants.Permissions.mentionEveryone), + // voice + voiceConnect: hp(_Constants.Permissions.voiceConnect), + voiceSpeak: hp(_Constants.Permissions.voiceSpeak), + voiceMuteMembers: hp(_Constants.Permissions.voiceMuteMembers), + voiceDeafenMembers: hp(_Constants.Permissions.voiceDeafenMembers), + voiceMoveMembers: hp(_Constants.Permissions.voiceMoveMembers), + voiceUseVAD: hp(_Constants.Permissions.voiceUseVAD) + }; + }; + + ChannelPermissions.prototype.serialize = function serialize() { + // ;n; + return this.serialise(); + }; + + ChannelPermissions.prototype.hasPermission = function hasPermission(perm) { + var explicit = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; + + if (perm instanceof String || typeof perm === "string") { + perm = _Constants.Permissions[perm]; + } + if (!perm) { + return false; + } + if (!explicit) { + // implicit permissions allowed + if (!!(this.permissions & _Constants.Permissions.manageRoles)) { + // manageRoles allowed, they have all permissions + return true; + } + } + return !!(this.permissions & perm); + }; + + return ChannelPermissions; +})(); + +exports["default"] = ChannelPermissions; +module.exports = exports["default"]; diff --git a/lib/Structures/Invite.js b/lib/Structures/Invite.js new file mode 100644 index 000000000..27d470b9c --- /dev/null +++ b/lib/Structures/Invite.js @@ -0,0 +1,32 @@ +"use strict"; + +exports.__esModule = true; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Invite = (function () { + function Invite(data, chan, client) { + _classCallCheck(this, Invite); + + this.maxAge = data.max_age; + this.code = data.code; + this.server = chan.server; + this.channel = chan; + this.revoked = data.revoked; + this.createdAt = Date.parse(data.created_at); + this.temporary = data.temporary; + this.uses = data.uses; + this.maxUses = data.uses; + this.inviter = client.internal.users.get("id", data.inviter.id); + this.xkcd = data.xkcdpass; + } + + Invite.prototype.toString = function toString() { + return "https://discord.gg/" + this.code; + }; + + return Invite; +})(); + +exports["default"] = Invite; +module.exports = exports["default"]; diff --git a/lib/Structures/Message.js b/lib/Structures/Message.js new file mode 100644 index 000000000..7e0942514 --- /dev/null +++ b/lib/Structures/Message.js @@ -0,0 +1,101 @@ +"use strict"; + +exports.__esModule = true; + +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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +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 _UtilCache = require("../Util/Cache"); + +var _UtilCache2 = _interopRequireDefault(_UtilCache); + +var _User = require("./User"); + +var _User2 = _interopRequireDefault(_User); + +var _UtilArgumentRegulariser = require("../Util/ArgumentRegulariser"); + +var _UtilEquality = require("../Util/Equality"); + +var _UtilEquality2 = _interopRequireDefault(_UtilEquality); + +var Message = (function (_Equality) { + _inherits(Message, _Equality); + + function Message(data, channel, client) { + var _this = this; + + _classCallCheck(this, Message); + + _Equality.call(this); + this.channel = channel; + this.client = client; + this.nonce = data.nonce; + this.attachments = data.attachments; + this.tts = data.tts; + this.embeds = data.embeds; + this.timestamp = Date.parse(data.timestamp); + this.everyoneMentioned = data.mention_everyone; + this.id = data.id; + + if (data.edited_timestamp) this.editedTimestamp = Date.parse(data.edited_timestamp); + + if (data.author instanceof _User2["default"]) this.author = data.author;else this.author = client.internal.users.add(new _User2["default"](data.author, client)); + + this.content = data.content; + this.mentions = new _UtilCache2["default"](); + + data.mentions.forEach(function (mention) { + // this is .add and not .get because it allows the bot to cache + // users from messages from logs who may have left the server and were + // not previously cached. + if (mention instanceof _User2["default"]) _this.mentions.push(mention);else _this.mentions.add(client.internal.users.add(new _User2["default"](mention, client))); + }); + } + + Message.prototype.isMentioned = function isMentioned(user) { + user = this.client.internal.resolver.resolveUser(user); + if (user) { + return this.mentions.has("id", user.id); + } else { + return false; + } + }; + + Message.prototype.toString = function toString() { + return this.content; + }; + + Message.prototype["delete"] = function _delete() { + return this.client.deleteMessage.apply(this.client, _UtilArgumentRegulariser.reg(this, arguments)); + }; + + Message.prototype.update = function update() { + return this.client.updateMessage.apply(this.client, _UtilArgumentRegulariser.reg(this, arguments)); + }; + + Message.prototype.reply = function reply() { + return this.client.reply.apply(this.client, _UtilArgumentRegulariser.reg(this, arguments)); + }; + + Message.prototype.replyTTS = function replyTTS() { + return this.client.replyTTS.apply(this.client, _UtilArgumentRegulariser.reg(this, arguments)); + }; + + _createClass(Message, [{ + key: "sender", + get: function get() { + return this.author; + } + }]); + + return Message; +})(_UtilEquality2["default"]); + +exports["default"] = Message; +module.exports = exports["default"]; diff --git a/lib/Structures/PMChannel.js b/lib/Structures/PMChannel.js new file mode 100644 index 000000000..61a77e465 --- /dev/null +++ b/lib/Structures/PMChannel.js @@ -0,0 +1,66 @@ +"use strict"; + +exports.__esModule = true; + +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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +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 _Channel2 = require("./Channel"); + +var _Channel3 = _interopRequireDefault(_Channel2); + +var _User = require("./User"); + +var _User2 = _interopRequireDefault(_User); + +var _UtilCache = require("../Util/Cache"); + +var _UtilCache2 = _interopRequireDefault(_UtilCache); + +var _UtilArgumentRegulariser = require("../Util/ArgumentRegulariser"); + +var PMChannel = (function (_Channel) { + _inherits(PMChannel, _Channel); + + function PMChannel(data, client) { + _classCallCheck(this, PMChannel); + + _Channel.call(this, data, client); + + this.type = data.type || "text"; + this.lastMessageId = data.last_message_id; + this.messages = new _UtilCache2["default"]("id", 1000); + this.recipient = this.client.internal.users.add(new _User2["default"](data.recipient, this.client)); + } + + /* warning! may return null */ + + PMChannel.prototype.toString = function toString() { + return this.recipient.toString(); + }; + + PMChannel.prototype.sendMessage = function sendMessage() { + return this.client.sendMessage.apply(this.client, _UtilArgumentRegulariser.reg(this, arguments)); + }; + + PMChannel.prototype.sendTTSMessage = function sendTTSMessage() { + return this.client.sendTTSMessage.apply(this.client, _UtilArgumentRegulariser.reg(this, arguments)); + }; + + _createClass(PMChannel, [{ + key: "lastMessage", + get: function get() { + return this.messages.get("id", this.lastMessageID); + } + }]); + + return PMChannel; +})(_Channel3["default"]); + +exports["default"] = PMChannel; +module.exports = exports["default"]; diff --git a/lib/Structures/PermissionOverwrite.js b/lib/Structures/PermissionOverwrite.js new file mode 100644 index 000000000..6682c168a --- /dev/null +++ b/lib/Structures/PermissionOverwrite.js @@ -0,0 +1,89 @@ +"use strict"; + +exports.__esModule = true; + +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 _Constants = require("../Constants"); + +var PermissionOverwrite = (function () { + function PermissionOverwrite(data) { + _classCallCheck(this, PermissionOverwrite); + + this.id = data.id; + this.type = data.type; // member or role + this.deny = data.deny; + this.allow = data.allow; + } + + // returns an array of allowed permissions + + PermissionOverwrite.prototype.setAllowed = function setAllowed(allowedArray) { + var _this = this; + + allowedArray.forEach(function (permission) { + if (permission instanceof String || typeof permission === "string") { + permission = _Constants.Permissions[permission]; + } + if (permission) { + _this.allow |= 1 << permission; + } + }); + }; + + PermissionOverwrite.prototype.setDenied = function setDenied(deniedArray) { + var _this2 = this; + + deniedArray.forEach(function (permission) { + if (permission instanceof String || typeof permission === "string") { + permission = _Constants.Permissions[permission]; + } + if (permission) { + _this2.deny |= 1 << permission; + } + }); + }; + + _createClass(PermissionOverwrite, [{ + key: "allowed", + get: function get() { + var allowed = []; + for (var permName in _Constants.Permissions) { + if (permName === "manageRoles" || permName === "manageChannels") { + // these permissions do not exist in overwrites. + continue; + } + + if (!!(this.allow & _Constants.Permissions[permName])) { + allowed.push(permName); + } + } + return allowed; + } + + // returns an array of denied permissions + }, { + key: "denied", + get: function get() { + var denied = []; + for (var permName in _Constants.Permissions) { + if (permName === "manageRoles" || permName === "manageChannels") { + // these permissions do not exist in overwrites. + continue; + } + + if (!!(this.deny & _Constants.Permissions[permName])) { + denied.push(permName); + } + } + return denied; + } + }]); + + return PermissionOverwrite; +})(); + +exports["default"] = PermissionOverwrite; +module.exports = exports["default"]; diff --git a/lib/Structures/Role.js b/lib/Structures/Role.js new file mode 100644 index 000000000..1aa4ce25b --- /dev/null +++ b/lib/Structures/Role.js @@ -0,0 +1,142 @@ +"use strict"; +exports.__esModule = true; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var _Constants = require("../Constants"); + +/* + +example data + +{ position: -1, + permissions: 36953089, + name: '@everyone', + managed: false, + id: '110007368451915776', + hoist: false, + color: 0 } +*/ + +var DefaultRole = [_Constants.Permissions.createInstantInvite, _Constants.Permissions.readMessages, _Constants.Permissions.readMessageHistory, _Constants.Permissions.sendMessages, _Constants.Permissions.sendTTSMessages, _Constants.Permissions.embedLinks, _Constants.Permissions.attachFiles, _Constants.Permissions.readMessageHistory, _Constants.Permissions.mentionEveryone, _Constants.Permissions.voiceConnect, _Constants.Permissions.voiceSpeak, _Constants.Permissions.voiceUseVAD].reduce(function (previous, current) { + return previous | current; +}, 0); + +var Role = (function () { + function Role(data, server, client) { + _classCallCheck(this, Role); + + this.position = data.position || -1; + this.permissions = data.permissions || (data.name === "@everyone" ? DefaultRole : 0); + this.name = data.name || "@everyone"; + this.managed = data.managed || false; + this.id = data.id; + this.hoist = data.hoist || false; + this.color = data.color || 0; + this.server = server; + this.client = client; + } + + Role.prototype.serialise = function serialise(explicit) { + var _this = this; + + var hp = function hp(perm) { + return _this.hasPermission(perm, explicit); + }; + + return { + // general + createInstantInvite: hp(_Constants.Permissions.createInstantInvite), + kickMembers: hp(_Constants.Permissions.kickMembers), + banMembers: hp(_Constants.Permissions.banMembers), + manageRoles: hp(_Constants.Permissions.manageRoles), + manageChannels: hp(_Constants.Permissions.manageChannels), + manageServer: hp(_Constants.Permissions.manageServer), + // text + readMessages: hp(_Constants.Permissions.readMessages), + sendMessages: hp(_Constants.Permissions.sendMessages), + sendTTSMessages: hp(_Constants.Permissions.sendTTSMessages), + manageMessages: hp(_Constants.Permissions.manageMessages), + embedLinks: hp(_Constants.Permissions.embedLinks), + attachFiles: hp(_Constants.Permissions.attachFiles), + readMessageHistory: hp(_Constants.Permissions.readMessageHistory), + mentionEveryone: hp(_Constants.Permissions.mentionEveryone), + // voice + voiceConnect: hp(_Constants.Permissions.voiceConnect), + voiceSpeak: hp(_Constants.Permissions.voiceSpeak), + voiceMuteMembers: hp(_Constants.Permissions.voiceMuteMembers), + voiceDeafenMembers: hp(_Constants.Permissions.voiceDeafenMembers), + voiceMoveMembers: hp(_Constants.Permissions.voiceMoveMembers), + voiceUseVAD: hp(_Constants.Permissions.voiceUseVAD) + }; + }; + + Role.prototype.serialize = function serialize() { + // ;n; + return this.serialise(); + }; + + Role.prototype.hasPermission = function hasPermission(perm) { + var explicit = arguments.length <= 1 || arguments[1] === undefined ? false : arguments[1]; + + if (perm instanceof String || typeof perm === "string") { + perm = _Constants.Permissions[perm]; + } + if (!perm) { + return false; + } + if (!explicit) { + // implicit permissions allowed + if (!!(this.permissions & _Constants.Permissions.manageRoles)) { + // manageRoles allowed, they have all permissions + return true; + } + } + // e.g. + // !!(36953089 & Permissions.manageRoles) = not allowed to manage roles + // !!(36953089 & (1 << 21)) = voice speak allowed + + return !!(this.permissions & perm); + }; + + Role.prototype.setPermission = function setPermission(permission, value) { + if (permission instanceof String || typeof permission === "string") { + permission = _Constants.Permissions[permission]; + } + if (permission) { + // valid permission + if (value) { + this.permissions |= permission; + } else { + this.permissions &= ~permission; + } + } + }; + + Role.prototype.setPermissions = function setPermissions(obj) { + var _this2 = this; + + obj.forEach(function (value, permission) { + if (permission instanceof String || typeof permission === "string") { + permission = _Constants.Permissions[permission]; + } + if (permission) { + // valid permission + _this2.setPermission(permission, value); + } + }); + }; + + Role.prototype.colorAsHex = function colorAsHex() { + var val = this.color.toString(); + while (val.length < 6) { + val = "0" + val; + } + return "#" + val; + }; + + return Role; +})(); + +exports["default"] = Role; +module.exports = exports["default"]; diff --git a/lib/Structures/Server.js b/lib/Structures/Server.js new file mode 100644 index 000000000..39eb03ef2 --- /dev/null +++ b/lib/Structures/Server.js @@ -0,0 +1,192 @@ +"use strict"; + +exports.__esModule = true; + +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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +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 _UtilEquality = require("../Util/Equality"); + +var _UtilEquality2 = _interopRequireDefault(_UtilEquality); + +var _Constants = require("../Constants"); + +var _UtilCache = require("../Util/Cache"); + +var _UtilCache2 = _interopRequireDefault(_UtilCache); + +var _User = require("./User"); + +var _User2 = _interopRequireDefault(_User); + +var _TextChannel = require("./TextChannel"); + +var _TextChannel2 = _interopRequireDefault(_TextChannel); + +var _VoiceChannel = require("./VoiceChannel"); + +var _VoiceChannel2 = _interopRequireDefault(_VoiceChannel); + +var _Role = require("./Role"); + +var _Role2 = _interopRequireDefault(_Role); + +var strictKeys = ["region", "ownerID", "name", "id", "icon", "afkTimeout", "afkChannelID"]; + +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 _UtilCache2["default"](); + this.channels = new _UtilCache2["default"](); + this.roles = new _UtilCache2["default"](); + this.icon = data.icon; + this.afkTimeout = data.afkTimeout; + this.afkChannelID = data.afk_channel_id; + this.memberMap = {}; + + var self = this; + + data.roles.forEach(function (dataRole) { + _this.roles.add(new _Role2["default"](dataRole, _this, client)); + }); + + data.members.forEach(function (dataUser) { + _this.memberMap[dataUser.user.id] = { + roles: dataUser.roles.map(function (pid) { + return self.roles.get("id", pid); + }), + mute: dataUser.mute, + deaf: dataUser.deaf, + joinedAt: Date.parse(dataUser.joined_at) + }; + var user = client.internal.users.add(new _User2["default"](dataUser.user, client)); + _this.members.add(user); + }); + + data.channels.forEach(function (dataChannel) { + if (dataChannel.type === "text") { + var channel = client.internal.channels.add(new _TextChannel2["default"](dataChannel, client, _this)); + _this.channels.add(channel); + } else { + var channel = client.internal.channels.add(new _VoiceChannel2["default"](dataChannel, client, _this)); + _this.channels.add(channel); + } + }); + + if (data.presences) { + for (var _iterator = data.presences, _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 presence = _ref; + + var user = client.internal.users.get("id", presence.user.id); + if (user) { + user.status = presence.status; + user.gameID = presence.game_id; + } + } + } + } + + Server.prototype.rolesOfUser = function rolesOfUser(user) { + user = this.client.internal.resolver.resolveUser(user); + if (user) { + return this.memberMap[user.id] ? this.memberMap[user.id].roles : []; + } else { + return null; + } + }; + + Server.prototype.rolesOf = function rolesOf(user) { + return this.rolesOfUser(user); + }; + + Server.prototype.toString = function toString() { + return this.name; + }; + + Server.prototype.equalsStrict = function equalsStrict(obj) { + if (obj instanceof Server) { + for (var _iterator2 = strictKeys, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var key = _ref2; + + if (obj[key] !== this[key]) { + return false; + } + } + } else { + return false; + } + return true; + }; + + _createClass(Server, [{ + key: "iconURL", + get: function get() { + if (!this.icon) { + return null; + } else { + return _Constants.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; +})(_UtilEquality2["default"]); + +exports["default"] = Server; +module.exports = exports["default"]; diff --git a/lib/Structures/ServerChannel.js b/lib/Structures/ServerChannel.js new file mode 100644 index 000000000..57ad3f21f --- /dev/null +++ b/lib/Structures/ServerChannel.js @@ -0,0 +1,134 @@ +"use strict"; + +exports.__esModule = true; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +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 _Channel2 = require("./Channel"); + +var _Channel3 = _interopRequireDefault(_Channel2); + +var _UtilCache = require("../Util/Cache"); + +var _UtilCache2 = _interopRequireDefault(_UtilCache); + +var _PermissionOverwrite = require("./PermissionOverwrite"); + +var _PermissionOverwrite2 = _interopRequireDefault(_PermissionOverwrite); + +var _ChannelPermissions = require("./ChannelPermissions"); + +var _ChannelPermissions2 = _interopRequireDefault(_ChannelPermissions); + +var _UtilArgumentRegulariser = require("../Util/ArgumentRegulariser"); + +var ServerChannel = (function (_Channel) { + _inherits(ServerChannel, _Channel); + + function ServerChannel(data, client, server) { + var _this = this; + + _classCallCheck(this, ServerChannel); + + _Channel.call(this, data, client); + this.name = data.name; + this.type = data.type; + this.position = data.position; + this.permissionOverwrites = new _UtilCache2["default"](); + this.server = server; + data.permission_overwrites.forEach(function (permission) { + _this.permissionOverwrites.add(new _PermissionOverwrite2["default"](permission)); + }); + } + + ServerChannel.prototype.permissionsOf = function permissionsOf(user) { + user = this.client.internal.resolver.resolveUser(user); + if (user) { + if (this.server.owner.equals(user)) { + return new _ChannelPermissions2["default"](4294967295); + } + var everyoneRole = this.server.roles.get("name", "@everyone"); + + var userRoles = [everyoneRole].concat(this.server.rolesOf(user) || []); + var userRolesID = userRoles.map(function (v) { + return v.id; + }); + var roleOverwrites = [], + memberOverwrites = []; + + this.permissionOverwrites.forEach(function (overwrite) { + if (overwrite.type === "member" && overwrite.id === user.id) { + memberOverwrites.push(overwrite); + } else if (overwrite.type === "role" && overwrite.id in userRolesID) { + roleOverwrites.push(overwrite); + } + }); + + var permissions = 0; + + for (var _iterator = userRoles, _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 serverRole = _ref; + + permissions |= serverRole.permissions; + } + + for (var _iterator2 = roleOverwrites.concat(memberOverwrites), _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var overwrite = _ref2; + + permissions = permissions & ~overwrite.deny; + permissions = permissions | overwrite.allow; + } + + return new _ChannelPermissions2["default"](permissions); + } else { + return null; + } + }; + + ServerChannel.prototype.permsOf = function permsOf(user) { + return this.permissionsOf(user); + }; + + ServerChannel.prototype.mention = function mention() { + return "<#" + this.id + ">"; + }; + + ServerChannel.prototype.toString = function toString() { + return this.mention(); + }; + + ServerChannel.prototype.setName = function setName() { + return this.client.setChannelName.apply(this.client, _UtilArgumentRegulariser.reg(this, arguments)); + }; + + return ServerChannel; +})(_Channel3["default"]); + +exports["default"] = ServerChannel; +module.exports = exports["default"]; diff --git a/lib/Structures/TextChannel.js b/lib/Structures/TextChannel.js new file mode 100644 index 000000000..92fa7566f --- /dev/null +++ b/lib/Structures/TextChannel.js @@ -0,0 +1,69 @@ +"use strict"; + +exports.__esModule = true; + +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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +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 _ServerChannel2 = require("./ServerChannel"); + +var _ServerChannel3 = _interopRequireDefault(_ServerChannel2); + +var _UtilCache = require("../Util/Cache"); + +var _UtilCache2 = _interopRequireDefault(_UtilCache); + +var _UtilArgumentRegulariser = require("../Util/ArgumentRegulariser"); + +var TextChannel = (function (_ServerChannel) { + _inherits(TextChannel, _ServerChannel); + + function TextChannel(data, client, server) { + _classCallCheck(this, TextChannel); + + _ServerChannel.call(this, data, client, server); + + this.topic = data.topic; + this.lastMessageID = data.last_message_id; + this.messages = new _UtilCache2["default"]("id", client.options.maximumMessages); + } + + /* warning! may return null */ + + TextChannel.prototype.setTopic = function setTopic() { + return this.client.setTopic.apply(this.client, _UtilArgumentRegulariser.reg(this, arguments)); + }; + + TextChannel.prototype.setNameAndTopic = function setNameAndTopic() { + return this.client.setChannelNameAndTopic.apply(this.client, _UtilArgumentRegulariser.reg(this, arguments)); + }; + + TextChannel.prototype.update = function update() { + return this.client.updateChannel.apply(this.client, _UtilArgumentRegulariser.reg(this, arguments)); + }; + + TextChannel.prototype.sendMessage = function sendMessage() { + return this.client.sendMessage.apply(this.client, _UtilArgumentRegulariser.reg(this, arguments)); + }; + + TextChannel.prototype.sendTTSMessage = function sendTTSMessage() { + return this.client.sendTTSMessage.apply(this.client, _UtilArgumentRegulariser.reg(this, arguments)); + }; + + _createClass(TextChannel, [{ + key: "lastMessage", + get: function get() { + return this.messages.get("id", this.lastMessageID); + } + }]); + + return TextChannel; +})(_ServerChannel3["default"]); + +exports["default"] = TextChannel; +module.exports = exports["default"]; diff --git a/lib/Structures/User.js b/lib/Structures/User.js new file mode 100644 index 000000000..259da1efc --- /dev/null +++ b/lib/Structures/User.js @@ -0,0 +1,70 @@ +"use strict"; + +exports.__esModule = true; + +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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +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 _UtilEquality = require("../Util/Equality"); + +var _UtilEquality2 = _interopRequireDefault(_UtilEquality); + +var _Constants = require("../Constants"); + +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; + this.typing = { + since: null, + channel: null + }; + } + + User.prototype.mention = function mention() { + return "<@" + this.id + ">"; + }; + + User.prototype.toString = function toString() { + return this.mention(); + }; + + User.prototype.equalsStrict = function equalsStrict(obj) { + if (obj instanceof User) return this.id === obj.id && this.username === obj.username && this.discriminator === obj.discriminator && this.avatar === obj.avatar && this.status === obj.status && this.gameID === obj.gameID;else return false; + }; + + User.prototype.equals = function equals(obj) { + if (obj instanceof User) return this.id === obj.id && this.username === obj.username && this.discriminator === obj.discriminator && this.avatar === obj.avatar;else return false; + }; + + _createClass(User, [{ + key: "avatarURL", + get: function get() { + if (!this.avatar) { + return null; + } else { + return _Constants.Endpoints.AVATAR(this.id, this.avatar); + } + } + }]); + + return User; +})(_UtilEquality2["default"]); + +exports["default"] = User; +module.exports = exports["default"]; diff --git a/lib/Structures/VoiceChannel.js b/lib/Structures/VoiceChannel.js new file mode 100644 index 000000000..f73bbfade --- /dev/null +++ b/lib/Structures/VoiceChannel.js @@ -0,0 +1,28 @@ +"use strict"; + +exports.__esModule = true; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +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 _ServerChannel2 = require("./ServerChannel"); + +var _ServerChannel3 = _interopRequireDefault(_ServerChannel2); + +var VoiceChannel = (function (_ServerChannel) { + _inherits(VoiceChannel, _ServerChannel); + + function VoiceChannel(data, client, server) { + _classCallCheck(this, VoiceChannel); + + _ServerChannel.call(this, data, client, server); + } + + return VoiceChannel; +})(_ServerChannel3["default"]); + +exports["default"] = VoiceChannel; +module.exports = exports["default"]; diff --git a/lib/Util/ArgumentRegulariser.js b/lib/Util/ArgumentRegulariser.js new file mode 100644 index 000000000..cee9d5a57 --- /dev/null +++ b/lib/Util/ArgumentRegulariser.js @@ -0,0 +1,8 @@ +"use strict"; + +exports.__esModule = true; +exports.reg = reg; + +function reg(c, a) { + return [c].concat(Array.prototype.slice.call(a)); +} diff --git a/lib/Util/Cache.js b/lib/Util/Cache.js new file mode 100644 index 000000000..61f4ab171 --- /dev/null +++ b/lib/Util/Cache.js @@ -0,0 +1,109 @@ +"use strict"; + +exports.__esModule = true; + +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.has = function has(key, value) { + return !!this.get(key, value); + }; + + Cache.prototype.getAll = function getAll(key, value) { + var found = new Cache(this.discrim); + 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; + } + }; + + Cache.prototype.update = function update(old, data) { + var item = this.get(this.discrim, old[this.discrim]); + if (item) { + var index = this.indexOf(item); + this[index] = data; + return this[index]; + } else { + return false; + } + }; + + Cache.prototype.random = function random() { + return this[Math.floor(Math.random() * this.length)]; + }; + + Cache.prototype.remove = function remove(data) { + var index = this.indexOf(data); + if (~index) { + this.splice(index, 1); + } else { + var item = this.get(this.discrim, data[this.discrim]); + if (item) { + this.splice(this.indexOf(item), 1); + } + } + return false; + }; + + return Cache; +})(Array); + +exports["default"] = Cache; +module.exports = exports["default"]; diff --git a/lib/Util/Equality.js b/lib/Util/Equality.js new file mode 100644 index 000000000..aab165350 --- /dev/null +++ b/lib/Util/Equality.js @@ -0,0 +1,48 @@ +/* + 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"; + +exports.__esModule = true; + +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; + }; + + Equality.prototype.equalsStrict = function equalsStrict(object) { + // override per class type + return; + }; + + _createClass(Equality, [{ + key: "eqDiscriminator", + get: function get() { + return "id"; + } + }]); + + return Equality; +})(); + +exports["default"] = Equality; +module.exports = exports["default"]; diff --git a/lib/Voice/AudioEncoder.js b/lib/Voice/AudioEncoder.js new file mode 100644 index 000000000..4b8489b9b --- /dev/null +++ b/lib/Voice/AudioEncoder.js @@ -0,0 +1,135 @@ +"use strict"; + +exports.__esModule = true; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var _child_process = require("child_process"); + +var _child_process2 = _interopRequireDefault(_child_process); + +var opus; +try { + opus = require("node-opus"); +} catch (e) { + // no opus! +} + +var AudioEncoder = (function () { + function AudioEncoder() { + _classCallCheck(this, AudioEncoder); + + if (opus) { + this.opus = new opus.OpusEncoder(48000, 1); + } + this.choice = false; + } + + AudioEncoder.prototype.opusBuffer = function opusBuffer(buffer) { + + return this.opus.encode(buffer, 1920); + }; + + AudioEncoder.prototype.getCommand = function getCommand(force) { + + if (this.choice && force) return choice; + + var choices = ["avconv", "ffmpeg"]; + + for (var _iterator = choices, _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 choice = _ref; + + var p = _child_process2["default"].spawnSync(choice); + if (!p.error) { + this.choice = choice; + return choice; + } + } + + return "help"; + }; + + AudioEncoder.prototype.encodeStream = function encodeStream(stream) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function (err, buffer) {} : arguments[1]; + + var self = this; + return new Promise(function (resolve, reject) { + var enc = _child_process2["default"].spawn(self.getCommand(), ["-f", "s16le", "-ar", "48000", "-ac", "1", // this can be 2 but there's no point, discord makes it mono on playback, wasted bandwidth. + "-af", "volume=1", "pipe:1", "-i", "-"]); + + stream.pipe(enc.stdin); + + enc.stdout.once("readable", function () { + callback(null, { + proc: enc, + stream: enc.stdout, + instream: stream + }); + resolve({ + proc: enc, + stream: enc.stdout, + instream: stream + }); + }); + + enc.stdout.on("end", function () { + callback("end"); + reject("end"); + }); + + enc.stdout.on("close", function () { + callback("close"); + reject("close"); + }); + }); + }; + + AudioEncoder.prototype.encodeFile = function encodeFile(file) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function (err, buffer) {} : arguments[1]; + + var self = this; + return new Promise(function (resolve, reject) { + var enc = _child_process2["default"].spawn(self.getCommand(), ["-f", "s16le", "-ar", "48000", "-ac", "1", // this can be 2 but there's no point, discord makes it mono on playback, wasted bandwidth. + "-af", "volume=1", "pipe:1", "-i", file]); + + enc.stdout.once("readable", function () { + callback(null, { + proc: enc, + stream: enc.stdout + }); + resolve({ + proc: enc, + stream: enc.stdout + }); + }); + + enc.stdout.on("end", function () { + callback("end"); + reject("end"); + }); + + enc.stdout.on("close", function () { + callback("close"); + reject("close"); + }); + }); + }; + + return AudioEncoder; +})(); + +exports["default"] = AudioEncoder; +module.exports = exports["default"]; diff --git a/lib/Voice/StreamIntent.js b/lib/Voice/StreamIntent.js new file mode 100644 index 000000000..37b981a14 --- /dev/null +++ b/lib/Voice/StreamIntent.js @@ -0,0 +1,28 @@ +"use strict"; +// represents an intent of streaming music +exports.__esModule = true; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +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 _events = require("events"); + +var _events2 = _interopRequireDefault(_events); + +var StreamIntent = (function (_EventEmitter) { + _inherits(StreamIntent, _EventEmitter); + + function StreamIntent() { + _classCallCheck(this, StreamIntent); + + _EventEmitter.call(this); + } + + return StreamIntent; +})(_events2["default"]); + +exports["default"] = StreamIntent; +module.exports = exports["default"]; diff --git a/lib/Voice/VoiceConnection.js b/lib/Voice/VoiceConnection.js new file mode 100644 index 000000000..ac43034ea --- /dev/null +++ b/lib/Voice/VoiceConnection.js @@ -0,0 +1,366 @@ +"use strict"; +/* + Major credit to izy521 who is the creator of + https://github.com/izy521/discord.io, + + without his help voice chat in discord.js would not have + been possible! +*/ + +exports.__esModule = true; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +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 _ws = require("ws"); + +var _ws2 = _interopRequireDefault(_ws); + +var _dns = require("dns"); + +var _dns2 = _interopRequireDefault(_dns); + +var _dgram = require("dgram"); + +var _dgram2 = _interopRequireDefault(_dgram); + +var _AudioEncoder = require("./AudioEncoder"); + +var _AudioEncoder2 = _interopRequireDefault(_AudioEncoder); + +var _VoicePacket = require("./VoicePacket"); + +var _VoicePacket2 = _interopRequireDefault(_VoicePacket); + +var _StreamIntent = require("./StreamIntent"); + +var _StreamIntent2 = _interopRequireDefault(_StreamIntent); + +var _events = require("events"); + +var _events2 = _interopRequireDefault(_events); + +var VoiceConnection = (function (_EventEmitter) { + _inherits(VoiceConnection, _EventEmitter); + + function VoiceConnection(channel, client, session, token, server, endpoint) { + _classCallCheck(this, VoiceConnection); + + _EventEmitter.call(this); + this.id = channel.id; + this.voiceChannel = channel; + this.client = client; + this.session = session; + this.token = token; + this.server = server; + this.endpoint = endpoint.replace(":80", ""); + this.vWS = null; // vWS means voice websocket + this.ready = false; + this.vWSData = {}; + this.encoder = new _AudioEncoder2["default"](); + this.udp = null; + this.playingIntent = null; + this.playing = false; + this.streamTime = 0; + this.streamProc = null; + this.KAI = null; + this.init(); + } + + VoiceConnection.prototype.destroy = function destroy() { + this.stopPlaying(); + if (this.KAI) clearInterval(this.KAI); + this.vWS.close(); + this.udp.close(); + this.client.internal.sendWS({ + op: 4, + d: { + guild_id: null, + channel_id: null, + self_mute: true, + self_deaf: false + } + }); + }; + + VoiceConnection.prototype.stopPlaying = function stopPlaying() { + this.playing = false; + this.playingIntent = null; + if (this.instream) { + //not all streams implement these... + //and even file stream don't seem to implement them properly... + if (this.instream.end) { + this.instream.end(); + } + if (this.instream.destroy) { + this.instream.destroy(); + } + this.instream = null; + } + }; + + VoiceConnection.prototype.playStream = function playStream(stream) { + + var self = this; + + var startTime = Date.now(); + var sequence = 0; + var time = 0; + var count = 0; + + var length = 20; + + if (self.playingIntent) { + self.stopPlaying(); + } + self.playing = true; + var retStream = new _StreamIntent2["default"](); + var onWarning = false; + self.playingIntent = retStream; + + function send() { + + if (!self.playingIntent || !self.playing) { + self.setSpeaking(false); + retStream.emit("end"); + self; + return; + } + try { + + var buffer = stream.read(1920); + + if (!buffer) { + if (onWarning) { + retStream.emit("end"); + self.setSpeaking(false); + return; + } else { + onWarning = true; + setTimeout(send, length * 10); // give chance for some data in 200ms to appear + return; + } + } + + if (buffer.length !== 1920) { + var newBuffer = new Buffer(1920).fill(0); + buffer.copy(newBuffer); + buffer = newBuffer; + } + + count++; + sequence + 10 < 65535 ? sequence += 1 : sequence = 0; + time + 9600 < 4294967295 ? time += 960 : time = 0; + + self.sendBuffer(buffer, sequence, time, function (e) {}); + + var nextTime = startTime + count * length; + + self.streamTime = count * length; + + setTimeout(send, length + (nextTime - Date.now())); + + if (!self.playing) self.setSpeaking(true); + + retStream.emit("time", self.streamTime); + } catch (e) { + retStream.emit("error", e); + } + } + self.setSpeaking(true); + send(); + + return retStream; + }; + + VoiceConnection.prototype.setSpeaking = function setSpeaking(value) { + this.playing = value; + if (this.vWS.readyState === _ws2["default"].OPEN) this.vWS.send(JSON.stringify({ + op: 5, + d: { + speaking: value, + delay: 0 + } + })); + }; + + VoiceConnection.prototype.sendPacket = function sendPacket(packet) { + var callback = arguments.length <= 1 || arguments[1] === undefined ? function (err) {} : arguments[1]; + + var self = this; + self.playing = true; + try { + if (self.vWS.readyState === _ws2["default"].OPEN) self.udp.send(packet, 0, packet.length, self.vWSData.port, self.endpoint, callback); + } catch (e) { + self.playing = false; + callback(e); + return false; + } + }; + + VoiceConnection.prototype.sendBuffer = function sendBuffer(rawbuffer, sequence, timestamp, callback) { + var self = this; + self.playing = true; + try { + if (!self.encoder.opus) { + self.playing = false; + self.emit("error", "No Opus!"); + self.client.emit("debug", "Tried to use node-opus, but opus not available - install it!"); + return; + } + var buffer = self.encoder.opusBuffer(rawbuffer); + var packet = new _VoicePacket2["default"](buffer, sequence, timestamp, self.vWSData.ssrc); + return self.sendPacket(packet, callback); + } catch (e) { + self.playing = false; + self.emit("error", e); + return false; + } + }; + + VoiceConnection.prototype.test = function test() { + this.playFile("C:/users/amish/desktop/audio.mp3").then(function (stream) { + stream.on("time", function (time) { + console.log("Time", time); + }); + }); + }; + + VoiceConnection.prototype.playFile = function playFile(stream) { + var _this = this; + + var callback = arguments.length <= 1 || arguments[1] === undefined ? function (err, str) {} : arguments[1]; + + var self = this; + return new Promise(function (resolve, reject) { + _this.encoder.encodeFile(stream)["catch"](error).then(function (data) { + self.streamProc = data.proc; + var intent = self.playStream(data.stream); + resolve(intent); + callback(null, intent); + }); + function error() { + var e = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0]; + + reject(e); + callback(e); + } + }); + }; + + VoiceConnection.prototype.playRawStream = function playRawStream(stream) { + var _this2 = this; + + var callback = arguments.length <= 1 || arguments[1] === undefined ? function (err, str) {} : arguments[1]; + + var self = this; + return new Promise(function (resolve, reject) { + _this2.encoder.encodeStream(stream)["catch"](error).then(function (data) { + self.streamProc = data.proc; + self.instream = data.instream; + var intent = self.playStream(data.stream); + resolve(intent); + callback(null, intent); + }); + function error() { + var e = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0]; + + reject(e); + callback(e); + } + }); + }; + + VoiceConnection.prototype.init = function init() { + var _this3 = this; + + var self = this; + _dns2["default"].lookup(this.endpoint, function (err, address, family) { + self.endpoint = address; + var vWS = self.vWS = new _ws2["default"]("wss://" + _this3.endpoint, null, { rejectUnauthorized: false }); + var udpClient = self.udp = _dgram2["default"].createSocket("udp4"); + + var firstPacket = true; + + var discordIP = "", + discordPort = ""; + + udpClient.bind({ exclusive: true }); + udpClient.on('message', function (msg, rinfo) { + var buffArr = JSON.parse(JSON.stringify(msg)).data; + if (firstPacket === true) { + for (var i = 4; i < buffArr.indexOf(0, i); i++) { + discordIP += String.fromCharCode(buffArr[i]); + } + discordPort = msg.readUIntLE(msg.length - 2, 2).toString(10); + + var wsDiscPayload = { + "op": 1, + "d": { + "protocol": "udp", + "data": { + "address": discordIP, + "port": Number(discordPort), + "mode": self.vWSData.modes[0] //Plain + } + } + }; + vWS.send(JSON.stringify(wsDiscPayload)); + firstPacket = false; + } + }); + + vWS.on("open", function () { + vWS.send(JSON.stringify({ + op: 0, + d: { + server_id: self.server.id, + user_id: self.client.internal.user.id, + session_id: self.session, + token: self.token + } + })); + }); + + var KAI; + + vWS.on("message", function (msg) { + var data = JSON.parse(msg); + switch (data.op) { + case 2: + self.vWSData = data.d; + + KAI = setInterval(function () { + if (vWS && vWS.readyState === _ws2["default"].OPEN) vWS.send(JSON.stringify({ + op: 3, + d: null + })); + }, data.d.heartbeat_interval); + self.KAI = KAI; + + var udpPacket = new Buffer(70); + udpPacket.writeUIntBE(data.d.ssrc, 0, 4); + udpClient.send(udpPacket, 0, udpPacket.length, data.d.port, self.endpoint, function (err) { + if (err) self.emit("error", err); + }); + break; + case 4: + + self.ready = true; + self.mode = data.d.mode; + self.emit("ready", self); + + break; + } + }); + }); + }; + + return VoiceConnection; +})(_events2["default"]); + +exports["default"] = VoiceConnection; +module.exports = exports["default"]; diff --git a/lib/Voice/VoicePacket.js b/lib/Voice/VoicePacket.js new file mode 100644 index 000000000..445f9d6c4 --- /dev/null +++ b/lib/Voice/VoicePacket.js @@ -0,0 +1,29 @@ +"use strict"; + +exports.__esModule = true; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var VoicePacket = function VoicePacket(data, sequence, time, ssrc) { + _classCallCheck(this, VoicePacket); + + var audioBuffer = data, + returnBuffer = new Buffer(audioBuffer.length + 12); + + returnBuffer.fill(0); + returnBuffer[0] = 0x80; + returnBuffer[1] = 0x78; + + returnBuffer.writeUIntBE(sequence, 2, 2); + returnBuffer.writeUIntBE(time, 4, 4); + returnBuffer.writeUIntBE(ssrc, 8, 4); + + for (var i = 0; i < audioBuffer.length; i++) { + returnBuffer[i + 12] = audioBuffer[i]; + } + + return returnBuffer; +}; + +exports["default"] = VoicePacket; +module.exports = exports["default"]; diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 000000000..f5ef732bc --- /dev/null +++ b/lib/index.js @@ -0,0 +1,79 @@ +"use strict"; + +exports.__esModule = true; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +var _ClientClient = require("./Client/Client"); + +var _ClientClient2 = _interopRequireDefault(_ClientClient); + +var _StructuresChannel = require("./Structures/Channel"); + +var _StructuresChannel2 = _interopRequireDefault(_StructuresChannel); + +var _StructuresChannelPermissions = require("./Structures/ChannelPermissions"); + +var _StructuresChannelPermissions2 = _interopRequireDefault(_StructuresChannelPermissions); + +var _StructuresInvite = require("./Structures/Invite"); + +var _StructuresInvite2 = _interopRequireDefault(_StructuresInvite); + +var _StructuresMessage = require("./Structures/Message"); + +var _StructuresMessage2 = _interopRequireDefault(_StructuresMessage); + +var _StructuresPermissionOverwrite = require("./Structures/PermissionOverwrite"); + +var _StructuresPermissionOverwrite2 = _interopRequireDefault(_StructuresPermissionOverwrite); + +var _StructuresPMChannel = require("./Structures/PMChannel"); + +var _StructuresPMChannel2 = _interopRequireDefault(_StructuresPMChannel); + +var _StructuresRole = require("./Structures/Role"); + +var _StructuresRole2 = _interopRequireDefault(_StructuresRole); + +var _StructuresServer = require("./Structures/Server"); + +var _StructuresServer2 = _interopRequireDefault(_StructuresServer); + +var _StructuresServerChannel = require("./Structures/ServerChannel"); + +var _StructuresServerChannel2 = _interopRequireDefault(_StructuresServerChannel); + +var _StructuresTextChannel = require("./Structures/TextChannel"); + +var _StructuresTextChannel2 = _interopRequireDefault(_StructuresTextChannel); + +var _StructuresUser = require("./Structures/User"); + +var _StructuresUser2 = _interopRequireDefault(_StructuresUser); + +var _StructuresVoiceChannel = require("./Structures/VoiceChannel"); + +var _StructuresVoiceChannel2 = _interopRequireDefault(_StructuresVoiceChannel); + +var _Constants = require("./Constants"); + +var _Constants2 = _interopRequireDefault(_Constants); + +exports["default"] = { + Client: _ClientClient2["default"], + Channel: _StructuresChannel2["default"], + ChannelPermissions: _StructuresChannelPermissions2["default"], + Invite: _StructuresInvite2["default"], + Message: _StructuresMessage2["default"], + PermissionOverwrite: _StructuresPermissionOverwrite2["default"], + PMChannel: _StructuresPMChannel2["default"], + Role: _StructuresRole2["default"], + Server: _StructuresServer2["default"], + ServerChannel: _StructuresServerChannel2["default"], + TextChannel: _StructuresTextChannel2["default"], + User: _StructuresUser2["default"], + VoiceChannel: _StructuresVoiceChannel2["default"], + Constants: _Constants2["default"] +}; +module.exports = exports["default"];