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) {