From 8c7c20862c6f5194490bc41e8ffeef82f6e76053 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Wed, 7 Feb 2018 20:26:29 -0700 Subject: [PATCH] * Implement some missing placeholder ACS checks * Add some new ACS checks * Add documentation on new ACS --- core/acs_parser.js | 97 ++++++++++++++++++++++++++++----------- docs/configuration/acs.md | 11 ++++- misc/acs_parser.pegjs | 97 ++++++++++++++++++++++++++++----------- 3 files changed, 150 insertions(+), 55 deletions(-) diff --git a/core/acs_parser.js b/core/acs_parser.js index 36b9372a..3025f654 100644 --- a/core/acs_parser.js +++ b/core/acs_parser.js @@ -844,11 +844,10 @@ function peg$parse(input, options) { } - var client = options.client; - var user = options.client.user; + const client = options.client; + const user = options.client.user; - var _ = require('lodash'); - var assert = require('assert'); + const moment = require('moment'); function checkAccess(acsCode, value) { try { @@ -860,41 +859,85 @@ function peg$parse(input, options) { return !isNaN(value) && user.getAge() >= value; }, AS : function accountStatus() { - if(!_.isArray(value)) { + if(!Array.isArray(value)) { value = [ value ]; } const userAccountStatus = parseInt(user.properties.account_status, 10); - value = value.map(n => parseInt(n, 10)); // ensure we have integers - return value.indexOf(userAccountStatus) > -1; + return value.map(n => parseInt(n, 10)).includes(userAccountStatus); }, EC : function isEncoding() { + const encoding = client.term.outputEncoding.toLowerCase(); switch(value) { - case 0 : return 'cp437' === client.term.outputEncoding.toLowerCase(); - case 1 : return 'utf-8' === client.term.outputEncoding.toLowerCase(); + case 0 : return 'cp437' === encoding; + case 1 : return 'utf-8' === encoding; default : return false; } }, GM : function isOneOfGroups() { - if(!_.isArray(value)) { + if(!Array.isArray(value)) { return false; } - return _.findIndex(value, function cmp(groupName) { - return user.isGroupMember(groupName); - }) > - 1; + return value.some(groupName => user.isGroupMember(groupName)); }, NN : function isNode() { - return client.node === value; + if(!Array.isArray(value)) { + value = [ value ]; + } + return value.map(n => parseInt(n, 10)).includes(client.node); }, NP : function numberOfPosts() { - const postCount = parseInt(user.properties.post_count, 10); + const postCount = parseInt(user.properties.post_count, 10) || 0; return !isNaN(value) && postCount >= value; }, NC : function numberOfCalls() { const loginCount = parseInt(user.properties.login_count, 10); return !isNaN(value) && loginCount >= value; }, + AA : function accountAge() { + const accountCreated = moment(user.properties.account_created); + const now = moment(); + const daysOld = accountCreated.diff(moment(), 'days'); + return !isNaN(value) && + accountCreated.isValid() && + now.isAfter(accountCreated) && + daysOld >= value; + }, + BU : function bytesUploaded() { + const bytesUp = parseInt(user.properties.ul_total_bytes, 10) || 0; + return !isNaN(value) && bytesUp >= value; + }, + UP : function uploads() { + const uls = parseInt(user.properties.ul_total_count, 10) || 0; + return !isNaN(value) && uls >= value; + }, + BD : function bytesDownloaded() { + const bytesDown = parseInt(user.properties.dl_total_bytes, 10) || 0; + return !isNaN(value) && bytesDown >= value; + }, + DL : function downloads() { + const dls = parseInt(user.properties.dl_total_count, 10) || 0; + return !isNaN(value) && dls >= value; + }, + NR : function uploadDownloadRatioGreaterThan() { + const ulCount = parseInt(user.properties.ul_total_count, 10) || 0; + const dlCount = parseInt(user.properties.dl_total_count, 10) || 0; + const ratio = ~~((ulCount / dlCount) * 100); + return !isNaN(value) && ratio >= value; + }, + KR : function uploadDownloadByteRatioGreaterThan() { + const ulBytes = parseInt(user.properties.ul_total_bytes, 10) || 0; + const dlBytes = parseInt(user.properties.dl_total_bytes, 10) || 0; + const ratio = ~~((ulBytes / dlBytes) * 100); + return !isNaN(value) && ratio >= value; + }, + PC : function postCallRatio() { + const postCount = parseInt(user.properties.post_count, 10) || 0; + const loginCount = parseInt(user.properties.login_count, 10); + const ratio = ~~((postCount / loginCount) * 100); + return !isNaN(value) && ratio >= value; + }, SC : function isSecureConnection() { return client.session.isSecure; }, @@ -906,41 +949,41 @@ function peg$parse(input, options) { return !isNaN(value) && client.term.termHeight >= value; }, TM : function isOneOfThemes() { - if(!_.isArray(value)) { + if(!Array.isArray(value)) { return false; } - return value.indexOf(client.currentTheme.name) > -1; + return value.includes(client.currentTheme.name); }, TT : function isOneOfTermTypes() { - if(!_.isArray(value)) { + if(!Array.isArray(value)) { return false; } - return value.indexOf(client.term.termType) > -1; + return value.includes(client.term.termType); }, TW : function termWidth() { return !isNaN(value) && client.term.termWidth >= value; }, ID : function isUserId(value) { - if(!_.isArray(value)) { + if(!Array.isArray(value)) { value = [ value ]; } - value = value.map(n => parseInt(n, 10)); // ensure we have integers - return value.indexOf(user.userId) > -1; + return value.map(n => parseInt(n, 10)).includes(user.userId); }, WD : function isOneOfDayOfWeek() { - if(!_.isArray(value)) { + if(!Array.isArray(value)) { value = [ value ]; } - value = value.map(n => parseInt(n, 10)); // ensure we have integers - return value.indexOf(new Date().getDay()) > -1; + return value.map(n => parseInt(n, 10)).includes(new Date().getDay()); }, MM : function isMinutesPastMidnight() { - // :TODO: return true if value is >= minutes past midnight sys time - return false; + const now = moment(); + const midnight = now.clone().startOf('day') + const minutesPastMidnight = now.diff(midnight, 'minutes'); + return !isNaN(value) && minutesPastMidnight >= value; } }[acsCode](value); } catch (e) { diff --git a/docs/configuration/acs.md b/docs/configuration/acs.md index 827050c4..3b7acbc0 100644 --- a/docs/configuration/acs.md +++ b/docs/configuration/acs.md @@ -16,7 +16,7 @@ The following are ACS codes available as of this writing: | ASstatus, AS[_status_,...] | User's account status is _group_ or one of [_group_,...] | | ECencoding | Terminal encoding is set to _encoding_ where `0` is `CP437` and `1` is `UTF-8` | | GM[_group_,...] | User belongs to one of [_group_,...] | -| NNnode | Current node is _node_ | +| NNnode, NN[_node_,...] | Current node is _node_ or one of [_node_,...] | | NPposts | User's number of message posts is >= _posts_ | | NCcalls | User's number of calls is >= _calls_ | | SC | Connection is considered secure (SSL, secure WebSockets, etc.) | @@ -26,6 +26,15 @@ The following are ACS codes available as of this writing: | TT[_termType_,...] | User's current terminal type is one of [_termType_,...] (`ANSI-BBS`, `utf8`, `xterm`, etc.) | | IDid, ID[_id_,...] | User's ID is _id_ or oen of [_id_,...] | | WDweekDay, WD[_weekDay_,...] | Current day of week is _weekDay_ or one of [_weekDay_,...] where `0` is Sunday, `1` is Monday, and so on. | +| AAdays | Account is >= _days_ old | +| BUbytes | User has uploaded >= _bytes_ | +| UPuploads | User has uploaded >= _uploads_ files | +| BDbytes | User has downloaded >= _bytes_ | +| DLdownloads | User has downloaded >= _downloads_ files | +| NRratio | User has upload/download count ratio >= _ratio_ | +| KRratio | User has a upload/download byte ratio >= _ratio_ | +| PCratio | User has a post/call ratio >= _ratio_ | +| MMminutes | It is currently >= _minutes_ past midnight (system time) \* Many more ACS codes are planned for the near future. diff --git a/misc/acs_parser.pegjs b/misc/acs_parser.pegjs index b381ccef..4c9bc37b 100644 --- a/misc/acs_parser.pegjs +++ b/misc/acs_parser.pegjs @@ -1,10 +1,9 @@ { - var client = options.client; - var user = options.client.user; + const client = options.client; + const user = options.client.user; - var _ = require('lodash'); - var assert = require('assert'); + const moment = require('moment'); function checkAccess(acsCode, value) { try { @@ -16,41 +15,85 @@ return !isNaN(value) && user.getAge() >= value; }, AS : function accountStatus() { - if(!_.isArray(value)) { + if(!Array.isArray(value)) { value = [ value ]; } const userAccountStatus = parseInt(user.properties.account_status, 10); - value = value.map(n => parseInt(n, 10)); // ensure we have integers - return value.indexOf(userAccountStatus) > -1; + return value.map(n => parseInt(n, 10)).includes(userAccountStatus); }, EC : function isEncoding() { + const encoding = client.term.outputEncoding.toLowerCase(); switch(value) { - case 0 : return 'cp437' === client.term.outputEncoding.toLowerCase(); - case 1 : return 'utf-8' === client.term.outputEncoding.toLowerCase(); + case 0 : return 'cp437' === encoding; + case 1 : return 'utf-8' === encoding; default : return false; } }, GM : function isOneOfGroups() { - if(!_.isArray(value)) { + if(!Array.isArray(value)) { return false; } - return _.findIndex(value, function cmp(groupName) { - return user.isGroupMember(groupName); - }) > - 1; + return value.some(groupName => user.isGroupMember(groupName)); }, NN : function isNode() { - return client.node === value; + if(!Array.isArray(value)) { + value = [ value ]; + } + return value.map(n => parseInt(n, 10)).includes(client.node); }, NP : function numberOfPosts() { - const postCount = parseInt(user.properties.post_count, 10); + const postCount = parseInt(user.properties.post_count, 10) || 0; return !isNaN(value) && postCount >= value; }, NC : function numberOfCalls() { const loginCount = parseInt(user.properties.login_count, 10); return !isNaN(value) && loginCount >= value; }, + AA : function accountAge() { + const accountCreated = moment(user.properties.account_created); + const now = moment(); + const daysOld = accountCreated.diff(moment(), 'days'); + return !isNaN(value) && + accountCreated.isValid() && + now.isAfter(accountCreated) && + daysOld >= value; + }, + BU : function bytesUploaded() { + const bytesUp = parseInt(user.properties.ul_total_bytes, 10) || 0; + return !isNaN(value) && bytesUp >= value; + }, + UP : function uploads() { + const uls = parseInt(user.properties.ul_total_count, 10) || 0; + return !isNaN(value) && uls >= value; + }, + BD : function bytesDownloaded() { + const bytesDown = parseInt(user.properties.dl_total_bytes, 10) || 0; + return !isNaN(value) && bytesDown >= value; + }, + DL : function downloads() { + const dls = parseInt(user.properties.dl_total_count, 10) || 0; + return !isNaN(value) && dls >= value; + }, + NR : function uploadDownloadRatioGreaterThan() { + const ulCount = parseInt(user.properties.ul_total_count, 10) || 0; + const dlCount = parseInt(user.properties.dl_total_count, 10) || 0; + const ratio = ~~((ulCount / dlCount) * 100); + return !isNaN(value) && ratio >= value; + }, + KR : function uploadDownloadByteRatioGreaterThan() { + const ulBytes = parseInt(user.properties.ul_total_bytes, 10) || 0; + const dlBytes = parseInt(user.properties.dl_total_bytes, 10) || 0; + const ratio = ~~((ulBytes / dlBytes) * 100); + return !isNaN(value) && ratio >= value; + }, + PC : function postCallRatio() { + const postCount = parseInt(user.properties.post_count, 10) || 0; + const loginCount = parseInt(user.properties.login_count, 10); + const ratio = ~~((postCount / loginCount) * 100); + return !isNaN(value) && ratio >= value; + }, SC : function isSecureConnection() { return client.session.isSecure; }, @@ -62,41 +105,41 @@ return !isNaN(value) && client.term.termHeight >= value; }, TM : function isOneOfThemes() { - if(!_.isArray(value)) { + if(!Array.isArray(value)) { return false; } - return value.indexOf(client.currentTheme.name) > -1; + return value.includes(client.currentTheme.name); }, TT : function isOneOfTermTypes() { - if(!_.isArray(value)) { + if(!Array.isArray(value)) { return false; } - return value.indexOf(client.term.termType) > -1; + return value.includes(client.term.termType); }, TW : function termWidth() { return !isNaN(value) && client.term.termWidth >= value; }, ID : function isUserId(value) { - if(!_.isArray(value)) { + if(!Array.isArray(value)) { value = [ value ]; } - value = value.map(n => parseInt(n, 10)); // ensure we have integers - return value.indexOf(user.userId) > -1; + return value.map(n => parseInt(n, 10)).includes(user.userId); }, WD : function isOneOfDayOfWeek() { - if(!_.isArray(value)) { + if(!Array.isArray(value)) { value = [ value ]; } - value = value.map(n => parseInt(n, 10)); // ensure we have integers - return value.indexOf(new Date().getDay()) > -1; + return value.map(n => parseInt(n, 10)).includes(new Date().getDay()); }, MM : function isMinutesPastMidnight() { - // :TODO: return true if value is >= minutes past midnight sys time - return false; + const now = moment(); + const midnight = now.clone().startOf('day') + const minutesPastMidnight = now.diff(midnight, 'minutes'); + return !isNaN(value) && minutesPastMidnight >= value; } }[acsCode](value); } catch (e) {