diff --git a/lib/ChannelPermissions.js b/lib/ChannelPermissions.js index e47395fd3..b8109644c 100644 --- a/lib/ChannelPermissions.js +++ b/lib/ChannelPermissions.js @@ -5,20 +5,51 @@ var _createClass = (function () { function defineProperties(target, props) { for function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var ChannelPermissions = (function () { - function ChannelPermissions(data) { + function ChannelPermissions(data, channel) { _classCallCheck(this, ChannelPermissions); + var self = this; + function getBit(x) { - return (this.packed >>> x & 1) === 1; + return (self.packed >>> x & 1) === 1; } this.type = data.type; //either member or role - this.id = data.id; - this.deny = data.deny; + if (this.type === "member") { + this.packed = channel.server.getMember("id", data.id).evalPerms.packed; + } else { + this.packed = channel.server.getRole(data.id).packed; + } + this.packed = this.packed & ~data.deny; + this.packed = this.packed | data.allow; + + this.deny = data.deny; this.allow = data.allow; + + this.createInstantInvite = getBit(0); + //this.banMembers = getBit(1); + //this.kickMembers = getBit(2); + this.managePermissions = getBit(3); + this.manageChannels = getBit(4); + //this.manageServer = getBit(5); + this.readMessages = getBit(10); + this.sendMessages = getBit(11); + this.sendTTSMessages = getBit(12); + this.manageMessages = getBit(13); + this.embedLinks = getBit(14); + this.attachFiles = getBit(15); + this.readMessageHistory = getBit(16); + this.mentionEveryone = getBit(17); + + this.voiceConnect = getBit(20); + this.voiceSpeak = getBit(21); + this.voiceMuteMembers = getBit(22); + this.voiceDeafenMembers = getBit(23); + this.voiceMoveMembers = getBit(24); + this.voiceUseVoiceActivation = getBit(25); } _createClass(ChannelPermissions, [{ diff --git a/lib/EvaluatedPermissions.js b/lib/EvaluatedPermissions.js new file mode 100644 index 000000000..a0795823c --- /dev/null +++ b/lib/EvaluatedPermissions.js @@ -0,0 +1,52 @@ +"use strict"; + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var EvaluatedPermissions = (function () { + function EvaluatedPermissions(data) { + _classCallCheck(this, EvaluatedPermissions); + + var self = this; + + function getBit(x) { + return (self.packed >>> x & 1) === 1; + } + + this.packed = data; + + this.createInstantInvite = getBit(0); + //this.banMembers = getBit(1); + //this.kickMembers = getBit(2); + this.managePermissions = getBit(3); + this.manageChannels = getBit(4); + //this.manageServer = getBit(5); + this.readMessages = getBit(10); + this.sendMessages = getBit(11); + this.sendTTSMessages = getBit(12); + this.manageMessages = getBit(13); + this.embedLinks = getBit(14); + this.attachFiles = getBit(15); + this.readMessageHistory = getBit(16); + this.mentionEveryone = getBit(17); + + this.voiceConnect = getBit(20); + this.voiceSpeak = getBit(21); + this.voiceMuteMembers = getBit(22); + this.voiceDeafenMembers = getBit(23); + this.voiceMoveMembers = getBit(24); + this.voiceUseVoiceActivation = getBit(25); + } + + _createClass(EvaluatedPermissions, [{ + key: "getBit", + value: function getBit(x) { + return (this.packed >>> x & 1) === 1; + } + }]); + + return EvaluatedPermissions; +})(); + +module.exports = EvaluatedPermissions; \ No newline at end of file diff --git a/lib/Member.js b/lib/Member.js index 093d37d5a..a4be7c50b 100644 --- a/lib/Member.js +++ b/lib/Member.js @@ -10,6 +10,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" var User = require("./user.js"); var ServerPermissions = require("./ServerPermissions.js"); +var EvaluatedPermissions = require("./EvaluatedPermissions.js"); var Member = (function (_User) { _inherits(Member, _User); @@ -23,21 +24,25 @@ var Member = (function (_User) { } _createClass(Member, [{ - key: "roles", - get: function get() { + key: "permissionsIn", + value: function permissionsIn(channel) { - var ufRoles = [this.server.getRole(this.server.id)]; + var affectingOverwrites = []; + var affectingMemberOverwrites = []; - console.log(this.rawRoles); var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { - for (var _iterator = this.rawRoles[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var rawRole = _step.value; + for (var _iterator = channel.roles[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var overwrite = _step.value; - ufRoles.push(this.server.getRole(rawRole)); + if (overwrite.id === this.id && overwrite.type === "member") { + affectingMemberOverwrites.push(overwrite); + } else if (this.rawRoles.indexOf(overwrite.id) !== -1) { + affectingOverwrites.push(overwrite); + } } } catch (err) { _didIteratorError = true; @@ -54,25 +59,22 @@ var Member = (function (_User) { } } - return ufRoles; - } - }, { - key: "evalPerms", - get: function get() { + if (affectingOverwrites.length === 0) { + return new EvaluatedPermissions(this.evalPerms.packed); + } - var basePerms = this.roles, - //cache roles as it can be slightly expensive - basePerm = basePerms[0].packed; + var finalPacked = affectingOverwrites[0].packed; var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { - for (var _iterator2 = basePerms[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { - var perm = _step2.value; + for (var _iterator2 = affectingOverwrites[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var overwrite = _step2.value; - basePerm = basePerm | perm.packed; + finalPacked = finalPacked & ~overwrite.deny; + finalPacked = finalPacked | overwrite.allow; } } catch (err) { _didIteratorError2 = true; @@ -89,6 +91,99 @@ var Member = (function (_User) { } } + var _iteratorNormalCompletion3 = true; + var _didIteratorError3 = false; + var _iteratorError3 = undefined; + + try { + for (var _iterator3 = affectingMemberOverwrites[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { + var overwrite = _step3.value; + + finalPacked = finalPacked & ~overwrite.deny; + finalPacked = finalPacked | overwrite.allow; + } + } catch (err) { + _didIteratorError3 = true; + _iteratorError3 = err; + } finally { + try { + if (!_iteratorNormalCompletion3 && _iterator3["return"]) { + _iterator3["return"](); + } + } finally { + if (_didIteratorError3) { + throw _iteratorError3; + } + } + } + + return new EvaluatedPermissions(finalPacked); + } + }, { + key: "roles", + get: function get() { + + var ufRoles = [this.server.getRole(this.server.id)]; + + var _iteratorNormalCompletion4 = true; + var _didIteratorError4 = false; + var _iteratorError4 = undefined; + + try { + for (var _iterator4 = this.rawRoles[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { + var rawRole = _step4.value; + + ufRoles.push(this.server.getRole(rawRole)); + } + } catch (err) { + _didIteratorError4 = true; + _iteratorError4 = err; + } finally { + try { + if (!_iteratorNormalCompletion4 && _iterator4["return"]) { + _iterator4["return"](); + } + } finally { + if (_didIteratorError4) { + throw _iteratorError4; + } + } + } + + return ufRoles; + } + }, { + key: "evalPerms", + get: function get() { + var basePerms = this.roles, + //cache roles as it can be slightly expensive + basePerm = basePerms[0].packed; + + var _iteratorNormalCompletion5 = true; + var _didIteratorError5 = false; + var _iteratorError5 = undefined; + + try { + for (var _iterator5 = basePerms[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { + var perm = _step5.value; + + basePerm = basePerm | perm.packed; + } + } catch (err) { + _didIteratorError5 = true; + _iteratorError5 = err; + } finally { + try { + if (!_iteratorNormalCompletion5 && _iterator5["return"]) { + _iterator5["return"](); + } + } finally { + if (_didIteratorError5) { + throw _iteratorError5; + } + } + } + return new ServerPermissions({ permissions: basePerm }); diff --git a/lib/channel.js b/lib/channel.js index be49484d3..eee332b0d 100644 --- a/lib/channel.js +++ b/lib/channel.js @@ -26,7 +26,7 @@ var Channel = (function () { for (var _iterator = data.permission_overwrites[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var role = _step.value; - this.roles.push(new ChannelPermissions(role)); + this.roles.push(new ChannelPermissions(role, this)); } //this.isPrivate = isPrivate; //not sure about the implementation of this... diff --git a/src/ChannelPermissions.js b/src/ChannelPermissions.js index 13f183867..aa70ed2a2 100644 --- a/src/ChannelPermissions.js +++ b/src/ChannelPermissions.js @@ -1,18 +1,49 @@ class ChannelPermissions{ - constructor(data){ + constructor(data, channel){ + + var self = this; function getBit(x) { - return ((this.packed >>> x) & 1) === 1; + return ((self.packed >>> x) & 1) === 1; } this.type = data.type; //either member or role - this.id = data.id; - this.deny = data.deny; + if(this.type === "member"){ + this.packed = channel.server.getMember("id", data.id).evalPerms.packed; + }else{ + this.packed = channel.server.getRole(data.id).packed; + } + this.packed = this.packed & ~data.deny; + this.packed = this.packed | data.allow; + + this.deny = data.deny; this.allow = data.allow; + this.createInstantInvite = getBit(0); + //this.banMembers = getBit(1); + //this.kickMembers = getBit(2); + this.managePermissions = getBit(3); + this.manageChannels = getBit(4); + //this.manageServer = getBit(5); + this.readMessages = getBit(10); + this.sendMessages = getBit(11); + this.sendTTSMessages = getBit(12); + this.manageMessages = getBit(13); + this.embedLinks = getBit(14); + this.attachFiles = getBit(15); + this.readMessageHistory = getBit(16); + this.mentionEveryone = getBit(17); + + this.voiceConnect = getBit(20); + this.voiceSpeak = getBit(21); + this.voiceMuteMembers = getBit(22); + this.voiceDeafenMembers = getBit(23); + this.voiceMoveMembers = getBit(24); + this.voiceUseVoiceActivation = getBit(25); + } getBit(x) { diff --git a/src/EvaluatedPermissions.js b/src/EvaluatedPermissions.js new file mode 100644 index 000000000..3c21e7870 --- /dev/null +++ b/src/EvaluatedPermissions.js @@ -0,0 +1,41 @@ +class EvaluatedPermissions{ + constructor(data){ + + var self = this; + + function getBit(x) { + return ((self.packed >>> x) & 1) === 1; + } + + this.packed = data; + + this.createInstantInvite = getBit(0); + //this.banMembers = getBit(1); + //this.kickMembers = getBit(2); + this.managePermissions = getBit(3); + this.manageChannels = getBit(4); + //this.manageServer = getBit(5); + this.readMessages = getBit(10); + this.sendMessages = getBit(11); + this.sendTTSMessages = getBit(12); + this.manageMessages = getBit(13); + this.embedLinks = getBit(14); + this.attachFiles = getBit(15); + this.readMessageHistory = getBit(16); + this.mentionEveryone = getBit(17); + + this.voiceConnect = getBit(20); + this.voiceSpeak = getBit(21); + this.voiceMuteMembers = getBit(22); + this.voiceDeafenMembers = getBit(23); + this.voiceMoveMembers = getBit(24); + this.voiceUseVoiceActivation = getBit(25); + + } + + getBit(x) { + return ((this.packed >>> x) & 1) === 1; + } +} + +module.exports = EvaluatedPermissions; \ No newline at end of file diff --git a/src/Member.js b/src/Member.js index 5db412403..969c5cd43 100644 --- a/src/Member.js +++ b/src/Member.js @@ -1,5 +1,6 @@ var User = require("./user.js"); var ServerPermissions = require("./ServerPermissions.js"); +var EvaluatedPermissions = require("./EvaluatedPermissions.js"); class Member extends User{ @@ -12,8 +13,7 @@ class Member extends User{ get roles(){ var ufRoles = [ this.server.getRole(this.server.id) ]; - - console.log(this.rawRoles); + for(var rawRole of this.rawRoles){ ufRoles.push( this.server.getRole(rawRole) ); } @@ -23,7 +23,6 @@ class Member extends User{ } get evalPerms(){ - var basePerms = this.roles, //cache roles as it can be slightly expensive basePerm = basePerms[0].packed; @@ -34,6 +33,38 @@ class Member extends User{ return new ServerPermissions({ permissions : basePerm }); + } + + permissionsIn(channel){ + + var affectingOverwrites = []; + var affectingMemberOverwrites = []; + + for(var overwrite of channel.roles){ + if(overwrite.id === this.id && overwrite.type === "member"){ + affectingMemberOverwrites.push(overwrite); + }else if( this.rawRoles.indexOf(overwrite.id) !== -1 ){ + affectingOverwrites.push(overwrite); + } + } + + if(affectingOverwrites.length === 0){ + return new EvaluatedPermissions(this.evalPerms.packed); + } + + var finalPacked = affectingOverwrites[0].packed; + + for(var overwrite of affectingOverwrites){ + finalPacked = finalPacked & ~overwrite.deny; + finalPacked = finalPacked | overwrite.allow; + } + + for(var overwrite of affectingMemberOverwrites){ + finalPacked = finalPacked & ~overwrite.deny; + finalPacked = finalPacked | overwrite.allow; + } + + return new EvaluatedPermissions(finalPacked); } diff --git a/src/channel.js b/src/channel.js index 64c9f22f0..81d5c5b28 100644 --- a/src/channel.js +++ b/src/channel.js @@ -13,7 +13,7 @@ class Channel { for (var role of data.permission_overwrites) { - this.roles.push( new ChannelPermissions(role) ); + this.roles.push( new ChannelPermissions(role, this) ); } diff --git a/test/bot.1.js b/test/bot.1.js index e216f2e4a..0f429ebe4 100644 --- a/test/bot.1.js +++ b/test/bot.1.js @@ -19,7 +19,7 @@ mybot.on("message", function (message) { // we can go ahead :) - mybot.reply(message, "your evaluated server-wide permissions are " + JSON.stringify(message.sender.evalPerms, null, 4).replace(/true/g, "**true**")); + mybot.reply(message, "your evaluated permissions in this channel are " + JSON.stringify(message.sender.permissionsIn(message.channel), null, 4).replace(/true/g, "**true**")); });