Merge remote-tracking branch 'upstream/master'

This commit is contained in:
David Stephens 2016-08-28 00:05:46 +01:00
commit 0b8916194e
15 changed files with 559 additions and 98 deletions

View File

@ -11,6 +11,7 @@ const logger = require('./logger.js');
const database = require('./database.js'); const database = require('./database.js');
const clientConns = require('./client_connections.js'); const clientConns = require('./client_connections.js');
// deps
const async = require('async'); const async = require('async');
const util = require('util'); const util = require('util');
const _ = require('lodash'); const _ = require('lodash');

View File

@ -1,28 +1,37 @@
/* jslint node: true */ /* jslint node: true */
'use strict'; 'use strict';
var logger = require('./logger.js'); // ENiGMA½
const logger = require('./logger.js');
var _ = require('lodash'); // deps
var moment = require('moment'); const _ = require('lodash');
const moment = require('moment');
exports.getActiveConnections = getActiveConnections; exports.getActiveConnections = getActiveConnections;
exports.getActiveNodeList = getActiveNodeList; exports.getActiveNodeList = getActiveNodeList;
exports.addNewClient = addNewClient; exports.addNewClient = addNewClient;
exports.removeClient = removeClient; exports.removeClient = removeClient;
var clientConnections = []; const clientConnections = [];
exports.clientConnections = clientConnections; exports.clientConnections = clientConnections;
function getActiveConnections() { function getActiveConnections() { return clientConnections; }
return clientConnections;
} function getActiveNodeList(authUsersOnly) {
if(!_.isBoolean(authUsersOnly)) {
authUsersOnly = true;
}
function getActiveNodeList() {
const now = moment(); const now = moment();
const activeConnections = getActiveConnections().filter(ac => {
return ((authUsersOnly && ac.user.isAuthenticated()) || !authUsersOnly);
});
return _.map(getActiveConnections(), ac => { return _.map(activeConnections, ac => {
let entry = { const entry = {
node : ac.node, node : ac.node,
authenticated : ac.user.isAuthenticated(), authenticated : ac.user.isAuthenticated(),
userId : ac.user.userId, userId : ac.user.userId,
@ -46,13 +55,13 @@ function getActiveNodeList() {
} }
function addNewClient(client, clientSock) { function addNewClient(client, clientSock) {
var id = client.session.id = clientConnections.push(client) - 1; const id = client.session.id = clientConnections.push(client) - 1;
// Create a client specific logger // Create a client specific logger
// Note that this will be updated @ login with additional information // Note that this will be updated @ login with additional information
client.log = logger.log.child( { clientId : id } ); client.log = logger.log.child( { clientId : id } );
var connInfo = { const connInfo = {
ip : clientSock.remoteAddress, ip : clientSock.remoteAddress,
serverName : client.session.serverName, serverName : client.session.serverName,
isSecure : client.session.isSecure, isSecure : client.session.isSecure,
@ -71,7 +80,7 @@ function addNewClient(client, clientSock) {
function removeClient(client) { function removeClient(client) {
client.end(); client.end();
var i = clientConnections.indexOf(client); const i = clientConnections.indexOf(client);
if(i > -1) { if(i > -1) {
clientConnections.splice(i, 1); clientConnections.splice(i, 1);
@ -84,15 +93,3 @@ function removeClient(client) {
); );
} }
} }
/* :TODO: make a public API elsewhere
function getActiveClientInformation() {
var info = {};
clientConnections.forEach(function connEntry(cc) {
});
return info;
}
*/

View File

@ -122,10 +122,10 @@ function prepareTerminal(term) {
function displayBanner(term) { function displayBanner(term) {
// note: intentional formatting: // note: intentional formatting:
term.pipeWrite(` term.pipeWrite(`
|06Connected to |02EN|10i|02GMA|10½ |06BBS version |12|VN |06Connected to |02EN|10i|02GMA|10½ |06BBS version |12|VN
|06Copyright (c) 2014-2016 Bryan Ashby |14- |12http://l33t.codes/ |06Copyright (c) 2014-2016 Bryan Ashby |14- |12http://l33t.codes/
|06Updates & source |14- |12https://github.com/NuSkooler/enigma-bbs/ |06Updates & source |14- |12https://github.com/NuSkooler/enigma-bbs/
|00` |00`
); );
} }

19
core/enig_error.js Normal file
View File

@ -0,0 +1,19 @@
/* jslint node: true */
'use strict';
class EnigError extends Error {
constructor(message) {
super(message);
this.name = this.constructor.name;
this.message = message;
if(typeof Error.captureStackTrace === 'function') {
Error.captureStackTrace(this, this.constructor);
} else {
this.stack = (new Error(message)).stack;
}
}
}
exports.EnigError = EnigError;

18
core/enigma_assert.js Normal file
View File

@ -0,0 +1,18 @@
/* jslint node: true */
'use strict';
// ENiGMA½
const Config = require('./config.js').config;
const Log = require('./logger.js').log;
// deps
const assert = require('assert');
module.exports = function(condition, message) {
if(Config.debug.assertsEnabled) {
assert.apply(this, arguments);
} else if(!(condition)) {
const stack = new Error().stack;
Log.error( { condition : condition, stack : stack }, message || 'Assertion failed' );
}
};

327
core/string_format.js Normal file
View File

@ -0,0 +1,327 @@
/* jslint node: true */
'use strict';
const EnigError = require('./enig_error.js').EnigError;
const pad = require('./string_util.js').pad;
const stylizeString = require('./string_util.js').stylizeString;
// deps
const _ = require('lodash');
/*
String formatting HEAVILY inspired by David Chambers string-format library
and the mini-language branch specifically which was gratiously released
under the DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE.
We need some extra functionality. Namely, support for RA style pipe codes
and ANSI escape sequences.
*/
class ValueError extends EnigError { }
class KeyError extends EnigError { }
const SpecRegExp = {
FillAlign : /^(.)?([<>=^])/,
Sign : /^[ +-]/,
Width : /^\d*/,
Precision : /^\d+/,
};
function tokenizeFormatSpec(spec) {
const tokens = {
fill : '',
align : '',
sign : '',
'#' : false,
'0' : false,
width : '',
',' : false,
precision : '',
type : '',
};
let index = 0;
let match;
function incIndexByMatch() {
index += match[0].length;
}
match = SpecRegExp.FillAlign.exec(spec);
if(match) {
if(match[1]) {
tokens.fill = match[1];
}
tokens.align = match[2];
incIndexByMatch();
}
match = SpecRegExp.Sign.exec(spec.slice(index));
if(match) {
tokens.sign = match[0];
incIndexByMatch();
}
if('#' === spec.charAt(index)) {
tokens['#'] = true;
++index;
}
if('0' === spec.charAt(index)) {
tokens['0'] = true;
++index;
}
match = SpecRegExp.Width.exec(spec.slice(index));
tokens.width = match[0];
incIndexByMatch();
if(',' === spec.charAt(index)) {
tokens[','] = true;
++index;
}
if('.' === spec.charAt(index)) {
++index;
match = SpecRegExp.Precision.exec(spec.slice(index));
if(!match) {
throw new ValueError('Format specifier missing precision');
}
tokens.precision = match[0];
incIndexByMatch();
}
if(index < spec.length) {
tokens.type = spec.charAt(index);
++index;
}
if(index < spec.length) {
throw new ValueError('Invalid conversion specification');
}
if(tokens[','] && 's' === tokens.type) {
throw new ValueError(`Cannot specify ',' with 's'`); // eslint-disable-line quotes
}
return tokens;
}
function quote(s) {
return `"${s.replace(/"/g, '\\"')}"`;
}
function getPadAlign(align) {
return {
'<' : 'right',
'>' : 'left',
'^' : 'center',
}[align] || '<';
}
function formatString(value, tokens) {
const fill = tokens.fill || (tokens['0'] ? '0' : ' ');
const align = tokens.align || (tokens['0'] ? '=' : '<');
const precision = Number(tokens.precision || value.length); // :TODO: consider pipe/ANSI length
if('' !== tokens.type && 's' !== tokens.type) {
throw new ValueError(`Unknown format code "${tokens.type}" for String object`);
}
if(tokens[',']) {
throw new ValueError(`Cannot specify ',' with 's'`); // eslint-disable-line quotes
}
if(tokens.sign) {
throw new ValueError('Sign not allowed in string format specifier');
}
if(tokens['#']) {
throw new ValueError('Alternate form (#) not allowed in string format specifier');
}
if('=' === align) {
throw new ValueError('"=" alignment not allowed in string format specifier');
}
return pad(value.slice(0, precision), parseInt(tokens.width), fill, getPadAlign(align));
}
const FormatNumRegExp = {
UpperType : /[A-Z]/,
ExponentRep : /e[+-](?=\d$)/,
};
function formatNumberHelper(n, precision, type) {
if(FormatNumRegExp.UpperType.test(type)) {
return formatNumberHelper(n, precision, type.toLowerCase()).toUpperCase();
}
switch(type) {
case 'c' : return String.fromCharCode(n);
case 'd' : return n.toString(10);
case 'b' : return n.toString(2);
case 'o' : return n.toString(8);
case 'x' : return n.toString(16);
case 'e' : return n.toExponential(precision).replace(FormatNumRegExp.ExponentRep, '$&0');
case 'f' : return n.toFixed(precision);
case 'g' : return n.toPrecision(precision || 1);
case '%' : return formatNumberHelper(n * 100, precision, 'f') + '%';
case '' : return formatNumberHelper(n, precision, 'd');
default :
throw new ValueError(`Unknown format code "${type}" for object of type 'float'`);
}
}
function formatNumber(value, tokens) {
const fill = tokens.fill || (tokens['0'] ? '0' : ' ');
const align = tokens.align || (tokens['0'] ? '=' : '>');
const width = Number(tokens.width);
const type = tokens.type || (tokens.precision ? 'g' : '');
if( [ 'c', 'd', 'b', 'o', 'x', 'X' ].indexOf(type) > -1) {
if(0 !== value % 1) {
throw new ValueError(`Cannot format non-integer with format specifier "${type}"`);
}
if('' !== tokens.sign && 'c' !== type) {
throw new ValueError(`Sign not allowed with integer format specifier 'c'`); // eslint-disable-line quotes
}
if(tokens[','] && 'd' !== type) {
throw new ValueError(`Cannot specify ',' with '${type}'`);
}
if('' !== tokens.precision) {
throw new ValueError('Precision not allowed in integer format specifier');
}
} else if( [ 'e', 'E', 'f', 'F', 'g', 'G', '%' ].indexOf(type) > - 1) {
if(tokens['#']) {
throw new ValueError('Alternate form (#) not allowed in float format specifier');
}
}
const s = formatNumberHelper(Math.abs(value), Number(tokens.precision || 6), type);
const sign = value < 0 || 1 / value < 0 ?
'-' :
'-' === tokens.sign ? '' : tokens.sign;
const prefix = tokens['#'] && ( [ 'b', 'o', 'x', 'X' ].indexOf(type) > -1 ) ? '0' + type : '';
if(tokens[',']) {
const match = /^(\d*)(.*)$/.exec(s);
const separated = match[1].replace(/.(?=(...)+$)/g, '$&,') + match[2];
if('=' !== align) {
return pad(sign + separated, width, fill, getPadAlign(align));
}
if('0' === fill) {
const shortfall = Math.max(0, width - sign.length - separated.length);
const digits = /^\d*/.exec(separated)[0].length;
let padding = '';
// :TODO: do this differntly...
for(let n = 0; n < shortfall; n++) {
padding = ((digits + n) % 4 === 3 ? ',' : '0') + padding;
}
return sign + (/^,/.test(padding) ? '0' : '') + padding + separated;
}
return sign + pad(separated, width - sign.length, fill, getPadAlign('>'));
}
if(0 === width) {
return sign + prefix + s;
}
if('=' === align) {
return sign + prefix + pad(s, width - sign.length - prefix.length, fill, getPadAlign('>'));
}
return pad(sign + prefix + s, width, fill, getPadAlign(align));
}
const transformers = {
// String standard
toUpperCase : String.prototype.toUpperCase,
toLowerCase : String.prototype.toLowerCase,
// some super l33b BBS styles!!
styleUpper : (s) => stylizeString(s, 'upper'),
styleLower : (s) => stylizeString(s, 'lower'),
styleTitle : (s) => stylizeString(s, 'title'),
styleFirstLower : (s) => stylizeString(s, 'first lower'),
styleSmallVowels : (s) => stylizeString(s, 'small vowels'),
styleBigVowels : (s) => stylizeString(s, 'big vowels'),
styleSmallI : (s) => stylizeString(s, 'small i'),
styleMixed : (s) => stylizeString(s, 'mixed'),
styleL33t : (s) => stylizeString(s, 'l33t'),
};
function transformValue(transformerName, value) {
if(transformerName in transformers) {
const transformer = transformers[transformerName];
value = transformer.apply(value, [ value ] );
}
return value;
}
// :TODO: Use explicit set of chars for paths & function/transforms such that } is allowed as fill/etc.
const REGEXP_BASIC_FORMAT = /{([^.!:}]+(?:\.[^.!:}]+)*)(?:\!([^:}]+))?(?:\:([^}]+))?}/g;
function getValue(obj, path) {
const value = _.get(obj, path);
if(value) {
return _.isFunction(value) ? value() : value;
}
throw new KeyError(quote(path));
}
module.exports = function format(fmt, obj) {
const re = REGEXP_BASIC_FORMAT;
let match;
let pos;
let out = '';
do {
pos = re.lastIndex;
match = re.exec(fmt);
if(match) {
if(match.index > pos) {
out += fmt.slice(pos, match.index);
}
const objPath = match[1];
const transformer = match[2];
const formatSpec = match[3];
let value = getValue(obj, objPath);
if(transformer) {
value = transformValue(transformer, value);
}
const tokens = tokenizeFormatSpec(formatSpec || '');
if(!isNaN(parseInt(value))) {
out += formatNumber(value, tokens);
} else {
out += formatString(value, tokens);
}
}
} while(0 !== re.lastIndex);
// remainder
if(pos < fmt.length) {
out += fmt.slice(pos);
}
return out;
};

View File

@ -1,18 +1,19 @@
/* jslint node: true */ /* jslint node: true */
'use strict'; 'use strict';
var events = require('events'); // ENiGMA½
var util = require('util'); const events = require('events');
var assert = require('assert'); const util = require('util');
var ansi = require('./ansi_term.js'); const ansi = require('./ansi_term.js');
var colorCodes = require('./color_codes.js'); const colorCodes = require('./color_codes.js');
const enigAssert = require('./enigma_assert.js');
var _ = require('lodash'); // deps
const _ = require('lodash');
exports.View = View; exports.View = View;
exports.VIEW_SPECIAL_KEY_MAP_DEFAULT = VIEW_SPECIAL_KEY_MAP_DEFAULT;
var VIEW_SPECIAL_KEY_MAP_DEFAULT = { const VIEW_SPECIAL_KEY_MAP_DEFAULT = {
accept : [ 'return' ], accept : [ 'return' ],
exit : [ 'esc' ], exit : [ 'esc' ],
backspace : [ 'backspace', 'del' ], backspace : [ 'backspace', 'del' ],
@ -27,11 +28,13 @@ var VIEW_SPECIAL_KEY_MAP_DEFAULT = {
clearLine : [ 'ctrl + y' ], clearLine : [ 'ctrl + y' ],
}; };
exports.VIEW_SPECIAL_KEY_MAP_DEFAULT = VIEW_SPECIAL_KEY_MAP_DEFAULT;
function View(options) { function View(options) {
events.EventEmitter.call(this); events.EventEmitter.call(this);
assert(_.isObject(options)); enigAssert(_.isObject(options));
assert(_.isObject(options.client)); enigAssert(_.isObject(options.client));
var self = this; var self = this;
@ -131,7 +134,7 @@ View.prototype.setPosition = function(pos) {
this.position.col = parseInt(arguments[1], 10); this.position.col = parseInt(arguments[1], 10);
} }
// santaize // sanatize
this.position.row = Math.max(this.position.row, 1); this.position.row = Math.max(this.position.row, 1);
this.position.col = Math.max(this.position.col, 1); this.position.col = Math.max(this.position.col, 1);
this.position.row = Math.min(this.position.row, this.client.term.termHeight); this.position.row = Math.min(this.position.row, this.client.term.termHeight);
@ -139,25 +142,23 @@ View.prototype.setPosition = function(pos) {
}; };
View.prototype.setDimension = function(dimens) { View.prototype.setDimension = function(dimens) {
assert(_.isObject(dimens) && _.isNumber(dimens.height) && _.isNumber(dimens.width)); enigAssert(_.isObject(dimens) && _.isNumber(dimens.height) && _.isNumber(dimens.width));
this.dimens = dimens; this.dimens = dimens;
this.autoScale = { height : false, width : false }; this.autoScale = { height : false, width : false };
}; };
View.prototype.setHeight = function(height) { View.prototype.setHeight = function(height) {
height = parseInt(height, 10); height = parseInt(height) || 1;
assert(_.isNumber(height)); height = Math.min(height, this.client.term.termHeight);
// :TODO: assert height is within this.client.term.termHeight
this.dimens.height = height; this.dimens.height = height;
this.autoScale.height = false; this.autoScale.height = false;
}; };
View.prototype.setWidth = function(width) { View.prototype.setWidth = function(width) {
width = parseInt(width); width = parseInt(width) || 1;
assert(_.isNumber(width)); width = Math.min(width, this.client.term.termWidth);
// :TODO: assert width is appropriate for this.client.term.termWidth
this.dimens.width = width; this.dimens.width = width;
this.autoScale.width = false; this.autoScale.width = false;
@ -168,7 +169,7 @@ View.prototype.getSGR = function() {
}; };
View.prototype.getStyleSGR = function(n) { View.prototype.getStyleSGR = function(n) {
assert(_.isNumber(n)); n = parseInt(n) || 0;
return this['styleSGR' + n]; return this['styleSGR' + n];
}; };
@ -241,21 +242,22 @@ View.prototype.redraw = function() {
}; };
View.prototype.setFocus = function(focused) { View.prototype.setFocus = function(focused) {
assert(this.acceptsFocus, 'View does not accept focus'); enigAssert(this.acceptsFocus, 'View does not accept focus');
this.hasFocus = focused; this.hasFocus = focused;
this.restoreCursor(); this.restoreCursor();
}; };
View.prototype.onKeyPress = function(ch, key) { View.prototype.onKeyPress = function(ch, key) {
if(false === this.hasFocus) { enigAssert(this.hasFocus, 'View does not have focus');
console.log('doh!'); // :TODO: fix me -- assert here? enigAssert(this.acceptsInput, 'View does not accept input');
if(!this.hasFocus || !this.acceptsInput) {
return;
} }
assert(this.hasFocus, 'View does not have focus');
assert(this.acceptsInput, 'View does not accept input');
if(key) { if(key) {
assert(this.specialKeyMap, 'No special key map defined'); enigAssert(this.specialKeyMap, 'No special key map defined');
if(this.isKeyMapped('accept', key.name)) { if(this.isKeyMapped('accept', key.name)) {
this.emit('action', 'accept', key); this.emit('action', 'accept', key);
@ -265,7 +267,7 @@ View.prototype.onKeyPress = function(ch, key) {
} }
if(ch) { if(ch) {
assert(1 === ch.length); enigAssert(1 === ch.length);
} }
this.emit('key press', ch, key); this.emit('key press', ch, key);

View File

@ -745,6 +745,10 @@
value: { command: "O" } value: { command: "O" }
action: @menu:mainMenuOnelinerz action: @menu:mainMenuOnelinerz
} }
{
value: { command: "R" }
action: @menu:mainMenuRumorz
}
{ {
value: { command: "CHAT"} value: { command: "CHAT"}
action: @menu:ercClient action: @menu:ercClient
@ -1108,6 +1112,92 @@
} }
} }
mainMenuRumorz: {
desc: Rumorz
module: rumorz
options: {
cls: true
}
config: {
art: {
entries: RUMORS
add: RUMORADD
}
}
form: {
0: {
mci: {
VM1: {
focus: false
height: 10
}
TM2: {
argName: addOrExit
items: [ "yeah!", "nah" ]
"hotKeys" : { "Y" : 0, "N" : 1, "Q" : 1 }
submit: true
focus: true
}
}
submit: {
*: [
{
value: { addOrExit: 0 }
action: @method:viewAddScreen
}
{
value: { addOrExit: null }
action: @systemMethod:nextMenu
}
]
}
actionKeys: [
{
keys: [ "escape" ]
action: @systemMethod:nextMenu
}
]
},
1: {
mci: {
ET1: {
focus: true
maxLength: 70
argName: rumor
}
TL2: {
width: 60
}
TM3: {
argName: addOrCancel
items: [ "add", "cancel" ]
"hotKeys" : { "A" : 0, "C" : 1, "Q" : 1 }
submit: true
}
}
submit: {
*: [
{
value: { addOrCancel: 0 }
action: @method:addEntry
}
{
value: { addOrCancel: 1 }
action: @method:cancelAdd
}
]
}
actionKeys: [
{
keys: [ "escape" ]
action: @method:cancelAdd
}
]
}
}
}
ercClient: { ercClient: {
art: erc art: erc
module: erc_client module: erc_client

View File

@ -7,6 +7,7 @@ const getModDatabasePath = require('../core/database.js').getModDatabasePath;
const ViewController = require('../core/view_controller.js').ViewController; const ViewController = require('../core/view_controller.js').ViewController;
const theme = require('../core/theme.js'); const theme = require('../core/theme.js');
const ansi = require('../core/ansi_term.js'); const ansi = require('../core/ansi_term.js');
const stringFormat = require('../core/string_format.js');
// deps // deps
const sqlite3 = require('sqlite3'); const sqlite3 = require('sqlite3');
@ -145,7 +146,7 @@ function OnelinerzModule(options) {
const tsFormat = config.timestampFormat || 'ddd h:mma'; const tsFormat = config.timestampFormat || 'ddd h:mma';
entriesView.setItems(entries.map( e => { entriesView.setItems(entries.map( e => {
return listFormat.format( { return stringFormat(listFormat, {
userId : e.user_id, userId : e.user_id,
username : e.user_name, username : e.user_name,
oneliner : e.oneliner, oneliner : e.oneliner,

Binary file not shown.

Binary file not shown.

View File

@ -271,6 +271,31 @@
} }
} }
mainMenuRumorz: {
config: {
listFormat: "|00|11 {rumor}"
focusListFormat: "|00|15> |14{rumor}"
}
0: {
mci: {
VM1: { height: 14 }
TM2: {
focusTextStyle: upper
items: [ "yes", "no" ]
}
}
}
1: {
mci: {
ET1: { width: 60 }
TL2: { width: 60 }
TM3: {
focusTextStyle: upper
}
}
}
}
bbsList: { bbsList: {
0: { 0: {
mci: { mci: {

View File

@ -1,14 +1,14 @@
/* jslint node: true */ /* jslint node: true */
'use strict'; 'use strict';
var MenuModule = require('../core/menu_module.js').MenuModule; // ENiGMA½
var ViewController = require('../core/view_controller.js').ViewController; const MenuModule = require('../core/menu_module.js').MenuModule;
var getActiveNodeList = require('../core/client_connections.js').getActiveNodeList; const ViewController = require('../core/view_controller.js').ViewController;
const getActiveNodeList = require('../core/client_connections.js').getActiveNodeList;
var moment = require('moment'); // deps
var async = require('async'); const async = require('async');
var assert = require('assert'); const _ = require('lodash');
var _ = require('lodash');
exports.moduleInfo = { exports.moduleInfo = {
name : 'Who\'s Online', name : 'Who\'s Online',
@ -17,26 +17,9 @@ exports.moduleInfo = {
packageName : 'codes.l33t.enigma.whosonline' packageName : 'codes.l33t.enigma.whosonline'
}; };
/*
node
userName
userId
action
note
affils
timeOnSec
location
realName
serverName (Telnet, SSH, ...)
default
{node} - {username} - {action} - {timeOnSec}
*/
exports.getModule = WhosOnlineModule; exports.getModule = WhosOnlineModule;
var MciCodeIds = { const MciCodeIds = {
OnlineList : 1, OnlineList : 1,
}; };
@ -47,30 +30,29 @@ function WhosOnlineModule(options) {
require('util').inherits(WhosOnlineModule, MenuModule); require('util').inherits(WhosOnlineModule, MenuModule);
WhosOnlineModule.prototype.mciReady = function(mciData, cb) { WhosOnlineModule.prototype.mciReady = function(mciData, cb) {
var self = this; const self = this;
var vc = self.viewControllers.allViews = new ViewController( { client : self.client } ); const vc = self.viewControllers.allViews = new ViewController( { client : self.client } );
async.series( async.series(
[ [
function callParentMciReady(callback) { function callParentMciReady(callback) {
WhosOnlineModule.super_.prototype.mciReady.call(self, mciData, callback); return WhosOnlineModule.super_.prototype.mciReady.call(self, mciData, callback);
}, },
function loadFromConfig(callback) { function loadFromConfig(callback) {
var loadOpts = { const loadOpts = {
callingMenu : self, callingMenu : self,
mciMap : mciData.menu, mciMap : mciData.menu,
noInput : true, noInput : true,
}; };
vc.loadFromMenuConfig(loadOpts, callback); return vc.loadFromMenuConfig(loadOpts, callback);
}, },
function populateList(callback) { function populateList(callback) {
var onlineListView = vc.getView(MciCodeIds.OnlineList); const onlineListView = vc.getView(MciCodeIds.OnlineList);
const listFormat = self.menuConfig.config.listFormat || '{node} - {userName} - {action} - {timeOn}';
const listFormat = self.menuConfig.config.listFormat || '{node} - {userName} - {action} - {timeOn}'; const nonAuthUser = self.menuConfig.config.nonAuthUser || 'Logging In';
const nonAuthUser = self.menuConfig.config.nonAuthUser || 'Logging In'; const otherUnknown = self.menuConfig.config.otherUnknown || 'N/A';
const otherUnknown = self.menuConfig.config.otherUnknown || 'N/A'; const onlineList = getActiveNodeList(self.menuConfig.config.authUsersOnly).slice(0, onlineListView.height);
const onlineList = getActiveNodeList().slice(0, onlineListView.height);
onlineListView.setItems(_.map(onlineList, oe => { onlineListView.setItems(_.map(onlineList, oe => {
if(oe.authenticated) { if(oe.authenticated) {
@ -85,16 +67,16 @@ WhosOnlineModule.prototype.mciReady = function(mciData, cb) {
})); }));
onlineListView.focusItems = onlineListView.items; onlineListView.focusItems = onlineListView.items;
onlineListView.redraw(); onlineListView.redraw();
callback(null);
return callback(null);
} }
], ],
function complete(err) { function complete(err) {
if(err) { if(err) {
self.client.log.error( { error : err.toString() }, 'Error loading who\'s online'); self.client.log.error( { error : err.message }, 'Error loading who\'s online');
} }
cb(err); return cb(err);
} }
); );
}; };

View File

@ -12,7 +12,6 @@ const resolvePath = require('./core/misc_util.js').resolvePath;
// deps // deps
const _ = require('lodash'); const _ = require('lodash');
const async = require('async'); const async = require('async');
const assert = require('assert');
const inq = require('inquirer'); const inq = require('inquirer');
const mkdirsSync = require('fs-extra').mkdirsSync; const mkdirsSync = require('fs-extra').mkdirsSync;
const fs = require('fs'); const fs = require('fs');