* FSE quote format is now configurable and random if there are 2:n available
* Remove old 3rd party string-format & replace with string_format.js version * Some fix some bugs with string_format.js padding, width, and number format
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
'use strict';
|
||||
|
||||
// ENiGMA½
|
||||
const Config = require('./config.js').config;
|
||||
const Config = require('./config.js').config;
|
||||
const stringFormat = require('./string_format.js');
|
||||
|
||||
// base/modules
|
||||
const fs = require('fs');
|
||||
@@ -124,7 +125,7 @@ module.exports = class ArchiveUtil {
|
||||
|
||||
let args = _.clone(archiver.compressArgs); // don't muck with orig
|
||||
for(let i = 0; i < args.length; ++i) {
|
||||
args[i] = args[i].format({
|
||||
args[i] = stringFormat(args[i], {
|
||||
archivePath : archivePath,
|
||||
fileList : files.join(' '),
|
||||
});
|
||||
@@ -144,7 +145,7 @@ module.exports = class ArchiveUtil {
|
||||
|
||||
let args = _.clone(archiver.decompressArgs); // don't muck with orig
|
||||
for(let i = 0; i < args.length; ++i) {
|
||||
args[i] = args[i].format({
|
||||
args[i] = stringFormat(args[i], {
|
||||
archivePath : archivePath,
|
||||
extractPath : extractPath,
|
||||
});
|
||||
|
||||
21
core/bbs.js
21
core/bbs.js
@@ -128,10 +128,10 @@ function initialize(cb) {
|
||||
if(err) {
|
||||
console.error('Could not create path: ' + conf.config.paths[pathKey] + ': ' + err.toString());
|
||||
}
|
||||
next(err);
|
||||
return next(err);
|
||||
});
|
||||
}, function dirCreationComplete(err) {
|
||||
callback(err);
|
||||
return callback(err);
|
||||
});
|
||||
},
|
||||
function basicInit(callback) {
|
||||
@@ -142,22 +142,19 @@ function initialize(cb) {
|
||||
|
||||
process.on('SIGINT', shutdownSystem);
|
||||
|
||||
// Init some extensions
|
||||
require('string-format').extend(String.prototype, require('./string_util.js').stringFormatExtensions);
|
||||
|
||||
callback(null);
|
||||
return callback(null);
|
||||
},
|
||||
function initDatabases(callback) {
|
||||
database.initializeDatabases(callback);
|
||||
return database.initializeDatabases(callback);
|
||||
},
|
||||
function initStatLog(callback) {
|
||||
require('./stat_log.js').init(callback);
|
||||
return require('./stat_log.js').init(callback);
|
||||
},
|
||||
function initThemes(callback) {
|
||||
// Have to pull in here so it's after Config init
|
||||
require('./theme.js').initAvailableThemes(function onThemesInit(err, themeCount) {
|
||||
logger.log.info({ themeCount : themeCount }, 'Themes initialized');
|
||||
callback(err);
|
||||
return callback(err);
|
||||
});
|
||||
},
|
||||
function loadSysOpInformation(callback) {
|
||||
@@ -204,10 +201,10 @@ function initialize(cb) {
|
||||
);
|
||||
},
|
||||
function initMCI(callback) {
|
||||
require('./predefined_mci.js').init(callback);
|
||||
return require('./predefined_mci.js').init(callback);
|
||||
},
|
||||
function readyMessageNetworkSupport(callback) {
|
||||
require('./msg_network.js').startup(callback);
|
||||
return require('./msg_network.js').startup(callback);
|
||||
},
|
||||
function readyEventScheduler(callback) {
|
||||
const EventSchedulerModule = require('./event_scheduler.js').EventSchedulerModule;
|
||||
@@ -218,7 +215,7 @@ function initialize(cb) {
|
||||
}
|
||||
],
|
||||
function onComplete(err) {
|
||||
cb(err);
|
||||
return cb(err);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/* jslint node: true */
|
||||
'use strict';
|
||||
|
||||
|
||||
const stringFormat = require('./string_format.js');
|
||||
|
||||
const events = require('events');
|
||||
const _ = require('lodash');
|
||||
const pty = require('ptyw.js');
|
||||
@@ -100,7 +103,7 @@ Door.prototype.run = function() {
|
||||
let args = _.clone(self.exeInfo.args); // we need a copy so the original is not modified
|
||||
|
||||
for(let i = 0; i < args.length; ++i) {
|
||||
args[i] = self.exeInfo.args[i].format({
|
||||
args[i] = stringFormat(self.exeInfo.args[i], {
|
||||
dropFile : self.exeInfo.dropFile,
|
||||
node : self.exeInfo.node.toString(),
|
||||
srvPort : sockServer ? sockServer.address().port.toString() : '-1',
|
||||
|
||||
43
core/fse.js
43
core/fse.js
@@ -2,17 +2,16 @@
|
||||
'use strict';
|
||||
|
||||
// ENiGMA½
|
||||
const MenuModule = require('../core/menu_module.js').MenuModule;
|
||||
const ViewController = require('../core/view_controller.js').ViewController;
|
||||
const ansi = require('../core/ansi_term.js');
|
||||
const theme = require('../core/theme.js');
|
||||
const Message = require('../core/message.js');
|
||||
const getMessageAreaByTag = require('../core/message_area.js').getMessageAreaByTag;
|
||||
const updateMessageAreaLastReadId = require('../core/message_area.js').updateMessageAreaLastReadId;
|
||||
const getUserIdAndName = require('../core/user.js').getUserIdAndName;
|
||||
const cleanControlCodes = require('../core/string_util.js').cleanControlCodes;
|
||||
const MenuModule = require('./menu_module.js').MenuModule;
|
||||
const ViewController = require('./view_controller.js').ViewController;
|
||||
const ansi = require('./ansi_term.js');
|
||||
const theme = require('./theme.js');
|
||||
const Message = require('./message.js');
|
||||
const updateMessageAreaLastReadId = require('./message_area.js').updateMessageAreaLastReadId;
|
||||
const getUserIdAndName = require('./user.js').getUserIdAndName;
|
||||
const cleanControlCodes = require('./string_util.js').cleanControlCodes;
|
||||
const StatLog = require('./stat_log.js');
|
||||
|
||||
const stringFormat = require('./string_format.js');
|
||||
|
||||
// deps
|
||||
const async = require('async');
|
||||
@@ -851,6 +850,21 @@ function FullScreenEditorModule(options) {
|
||||
});
|
||||
};
|
||||
|
||||
this.getQuoteByHeader = function() {
|
||||
let quoteFormat = this.menuConfig.config.quoteFormats;
|
||||
if(Array.isArray(quoteFormat)) {
|
||||
quoteFormat = quoteFormat[ Math.floor(Math.random() * quoteFormat.length) ];
|
||||
} else if(!_.isString(quoteFormat)) {
|
||||
quoteFormat = 'On {dateTime} {userName} said...';
|
||||
}
|
||||
|
||||
const dtFormat = this.menuConfig.config.quoteDateTimeFormat || self.client.currentTheme.helpers.getDateTimeFormat();
|
||||
return stringFormat(quoteFormat, {
|
||||
dateTime : moment(self.replyToMessage.modTimestamp).format(dtFormat),
|
||||
userName : self.replyToMessage.fromUserName,
|
||||
});
|
||||
};
|
||||
|
||||
this.menuMethods = {
|
||||
//
|
||||
// Validation stuff
|
||||
@@ -917,14 +931,7 @@ function FullScreenEditorModule(options) {
|
||||
|
||||
if(self.newQuoteBlock) {
|
||||
self.newQuoteBlock = false;
|
||||
|
||||
// :TODO: Make date/time format avail as FSE config -- also the line itself!
|
||||
var dtFormat = self.client.currentTheme.helpers.getDateTimeFormat();
|
||||
quoteMsgView.addText(
|
||||
'On {0} {1} said...'.format(
|
||||
moment(self.replyToMessage.modTimestamp).format(dtFormat),
|
||||
self.replyToMessage.fromUserName)
|
||||
);
|
||||
quoteMsgView.addText(self.getQuoteByHeader());
|
||||
}
|
||||
|
||||
var quoteText = self.viewControllers.quoteBuilder.getView(3).getItem(formData.value.quote);
|
||||
|
||||
@@ -66,7 +66,7 @@ var SPECIAL_KEY_MAP_DEFAULT = {
|
||||
'line feed' : [ 'return' ],
|
||||
exit : [ 'esc' ],
|
||||
backspace : [ 'backspace' ],
|
||||
'delete' : [ 'del' ],
|
||||
delete : [ 'del' ],
|
||||
tab : [ 'tab' ],
|
||||
up : [ 'up arrow' ],
|
||||
down : [ 'down arrow' ],
|
||||
@@ -802,7 +802,6 @@ function MultiLineEditTextView(options) {
|
||||
self.emitEditPosition();
|
||||
};
|
||||
|
||||
//this.keyPressClearLine = function() {
|
||||
this.keyPressDeleteLine = function() {
|
||||
if(self.textLines.length > 0) {
|
||||
self.removeCharactersFromText(
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
// ENiGMA½
|
||||
const msgArea = require('./message_area.js');
|
||||
const MenuModule = require('./menu_module.js').MenuModule;
|
||||
const ViewController = require('../core/view_controller.js').ViewController;
|
||||
const ViewController = require('./view_controller.js').ViewController;
|
||||
const stringFormat = require('./string_format.js');
|
||||
|
||||
// deps
|
||||
const _ = require('lodash');
|
||||
@@ -120,16 +121,7 @@ function NewScanModule(options) {
|
||||
// :TODO: it would be nice to cache this - must be done by conf!
|
||||
const sortedAreas = msgArea.getSortedAvailMessageAreasByConfTag(conf.confTag, { client : self.client } );
|
||||
const currentArea = sortedAreas[self.currentScanAux.area];
|
||||
|
||||
function getFormatObj() {
|
||||
return {
|
||||
confName : conf.conf.name,
|
||||
confDesc : conf.conf.desc,
|
||||
areaName : currentArea.area.name,
|
||||
areaDesc : currentArea.area.desc
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Scan and update index until we find something. If results are found,
|
||||
// we'll goto the list module & show them.
|
||||
@@ -147,7 +139,12 @@ function NewScanModule(options) {
|
||||
}
|
||||
},
|
||||
function updateStatusScanStarted(callback) {
|
||||
self.updateScanStatus(self.scanStartFmt.format(getFormatObj()));
|
||||
self.updateScanStatus(stringFormat(self.scanStartFmt, {
|
||||
confName : conf.conf.name,
|
||||
confDesc : conf.conf.desc,
|
||||
areaName : currentArea.area.name,
|
||||
areaDesc : currentArea.area.desc
|
||||
}));
|
||||
return callback(null);
|
||||
},
|
||||
function getNewMessagesCountInArea(callback) {
|
||||
|
||||
@@ -9,6 +9,7 @@ var ServerModule = require('../server_module.js').ServerModule;
|
||||
var userLogin = require('../user_login.js').userLogin;
|
||||
var enigVersion = require('../../package.json').version;
|
||||
var theme = require('../theme.js');
|
||||
const stringFormat = require('../string_format.js');
|
||||
|
||||
var ssh2 = require('ssh2');
|
||||
var fs = require('fs');
|
||||
@@ -105,12 +106,12 @@ function SSHClient(clientConn) {
|
||||
theme.getThemeArt(artOpts, function gotArt(err, artInfo) {
|
||||
if(err) {
|
||||
interactivePrompt.prompt = 'Access denied\n' + ctx.username + '\'s password: ';
|
||||
} else {
|
||||
var newUserNameList = '"' + (Config.users.newUserNames || []).join(', ') + '"';
|
||||
interactivePrompt.prompt =
|
||||
'Access denied\n' +
|
||||
artInfo.data.format( { newUserNames : newUserNameList } ) +
|
||||
'\n' + ctx.username + '\'s password: ';
|
||||
} else {
|
||||
const newUserNameList = _.has(Config, 'users.newUserNames') && Config.users.newUserNames.length > 0 ?
|
||||
Config.users.newUserNames.map(newName => '"' + newName + '"').join(', ') :
|
||||
'(No new user names enabled!)';
|
||||
|
||||
interactivePrompt.prompt = `Access denied\n${stringFormat(artInfo.data, { newUserNames : newUserNameList })}\n${ctx.username}'s password'`;
|
||||
}
|
||||
return ctx.prompt(interactivePrompt, retryPrompt);
|
||||
});
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
/* 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;
|
||||
const EnigError = require('./enig_error.js').EnigError;
|
||||
const pad = require('./string_util.js').pad;
|
||||
const stylizeString = require('./string_util.js').stylizeString;
|
||||
const renderStringLength = require('./string_util.js').renderStringLength;
|
||||
const renderSubstr = require('./string_util.js').renderSubstr;
|
||||
|
||||
// deps
|
||||
const _ = require('lodash');
|
||||
@@ -124,7 +126,7 @@ function getPadAlign(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
|
||||
const precision = Number(tokens.precision || renderStringLength(value) + 1);
|
||||
|
||||
if('' !== tokens.type && 's' !== tokens.type) {
|
||||
throw new ValueError(`Unknown format code "${tokens.type}" for String object`);
|
||||
@@ -146,7 +148,7 @@ function formatString(value, tokens) {
|
||||
throw new ValueError('"=" alignment not allowed in string format specifier');
|
||||
}
|
||||
|
||||
return pad(value.slice(0, precision), parseInt(tokens.width), fill, getPadAlign(align));
|
||||
return pad(renderSubstr(value, 0, precision), Number(tokens.width), fill, getPadAlign(align));
|
||||
}
|
||||
|
||||
const FormatNumRegExp = {
|
||||
@@ -167,7 +169,10 @@ function formatNumberHelper(n, precision, type) {
|
||||
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 'g' :
|
||||
// we don't want useless trailing zeros. parseFloat -> back to string fixes this for us
|
||||
return parseFloat(n.toPrecision(precision || 1)).toString();
|
||||
|
||||
case '%' : return formatNumberHelper(n * 100, precision, 'f') + '%';
|
||||
case '' : return formatNumberHelper(n, precision, 'd');
|
||||
|
||||
@@ -276,7 +281,7 @@ const REGEXP_BASIC_FORMAT = /{([^.!:}]+(?:\.[^.!:}]+)*)(?:\!([^:}]+))?(?:\:([^}]
|
||||
|
||||
function getValue(obj, path) {
|
||||
const value = _.get(obj, path);
|
||||
if(value) {
|
||||
if(!_.isUndefined(value)) {
|
||||
return _.isFunction(value) ? value() : value;
|
||||
}
|
||||
|
||||
@@ -286,9 +291,16 @@ function getValue(obj, path) {
|
||||
module.exports = function format(fmt, obj) {
|
||||
|
||||
const re = REGEXP_BASIC_FORMAT;
|
||||
|
||||
let match;
|
||||
let pos;
|
||||
let out = '';
|
||||
let objPath ;
|
||||
let transformer;
|
||||
let formatSpec;
|
||||
let value;
|
||||
let tokens;
|
||||
|
||||
do {
|
||||
pos = re.lastIndex;
|
||||
match = re.exec(fmt);
|
||||
@@ -298,16 +310,16 @@ module.exports = function format(fmt, obj) {
|
||||
out += fmt.slice(pos, match.index);
|
||||
}
|
||||
|
||||
const objPath = match[1];
|
||||
const transformer = match[2];
|
||||
const formatSpec = match[3];
|
||||
objPath = match[1];
|
||||
transformer = match[2];
|
||||
formatSpec = match[3];
|
||||
|
||||
let value = getValue(obj, objPath);
|
||||
value = getValue(obj, objPath);
|
||||
if(transformer) {
|
||||
value = transformValue(transformer, value);
|
||||
}
|
||||
|
||||
const tokens = tokenizeFormatSpec(formatSpec || '');
|
||||
tokens = tokenizeFormatSpec(formatSpec || '');
|
||||
|
||||
if(!isNaN(parseInt(value))) {
|
||||
out += formatNumber(value, tokens);
|
||||
@@ -323,5 +335,5 @@ module.exports = function format(fmt, obj) {
|
||||
out += fmt.slice(pos);
|
||||
}
|
||||
|
||||
return out;
|
||||
return out;
|
||||
};
|
||||
|
||||
@@ -195,45 +195,6 @@ function stringFromNullTermBuffer(buf, encoding) {
|
||||
return iconv.decode(buf.slice(0, nullPos), encoding || 'utf-8');
|
||||
}
|
||||
|
||||
//
|
||||
// Extend String.format's object syntax with some modifiers
|
||||
// e.g.: '{username!styleL33t}'.format( { username : 'Leet User' } ) -> "L33t U53r"
|
||||
//
|
||||
var stringFormatExtensions = {
|
||||
styleUpper : function(s) {
|
||||
return stylizeString(s, 'upper');
|
||||
},
|
||||
styleLower : function(s) {
|
||||
return stylizeString(s, 'lower');
|
||||
},
|
||||
styleTitle : function(s) {
|
||||
return stylizeString(s, 'title');
|
||||
},
|
||||
styleFirstLower : function(s) {
|
||||
return stylizeString(s, 'first lower');
|
||||
},
|
||||
styleSmallVowels : function(s) {
|
||||
return stylizeString(s, 'small vowels');
|
||||
},
|
||||
styleBigVowels : function(s) {
|
||||
return stylizeString(s, 'big vowels');
|
||||
},
|
||||
styleSmallI : function(s) {
|
||||
return stylizeString(s, 'small i');
|
||||
},
|
||||
styleMixed : function(s) {
|
||||
return stylizeString(s, 'mixed');
|
||||
},
|
||||
styleL33t : function(s) {
|
||||
return stylizeString(s, 'l33t');
|
||||
}
|
||||
|
||||
// :TODO: Add padding/etc. modifiers.
|
||||
};
|
||||
|
||||
exports.stringFormatExtensions = stringFormatExtensions;
|
||||
|
||||
|
||||
// :TODO: Add other codes from ansi_escape_parser
|
||||
const ANSI_REGEXP = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
|
||||
const PIPE_REGEXP = /\|[A-Z\d]{2}/g;
|
||||
@@ -244,7 +205,7 @@ const ANSI_OR_PIPE_REGEXP = new RegExp(ANSI_REGEXP.source + '|' + PIPE_REGEXP.so
|
||||
//
|
||||
function renderSubstr(str, start, length) {
|
||||
start = start || 0;
|
||||
length = length || str.length - start;
|
||||
length = Math.max(0, (length || str.length - start) - 1);
|
||||
|
||||
const re = ANSI_REGEXP;
|
||||
let pos;
|
||||
|
||||
@@ -240,14 +240,6 @@ TextView.prototype.setText = function(text) {
|
||||
};
|
||||
*/
|
||||
|
||||
TextView.prototype.setFormatObject = function(obj) {
|
||||
if(!_.isObject(obj) || !this.text) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setText(this.text.format(obj));
|
||||
};
|
||||
|
||||
TextView.prototype.clearText = function() {
|
||||
this.setText('');
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@ exports.userLogin = userLogin;
|
||||
function userLogin(client, username, password, cb) {
|
||||
client.user.authenticate(username, password, function authenticated(err) {
|
||||
if(err) {
|
||||
client.log.info( { username : username }, 'Failed login attempt: %s', err);
|
||||
client.log.info( { username : username, error : err.message }, 'Failed login attempt');
|
||||
|
||||
// :TODO: if username exists, record failed login attempt to properties
|
||||
// :TODO: check Config max failed logon attempts/etc. - set err.maxAttempts = true
|
||||
|
||||
@@ -6,6 +6,7 @@ var MCIViewFactory = require('./mci_view_factory.js').MCIViewFactory;
|
||||
var menuUtil = require('./menu_util.js');
|
||||
var asset = require('./asset.js');
|
||||
var ansi = require('./ansi_term.js');
|
||||
const Log = require('./logger.js');
|
||||
|
||||
// deps
|
||||
var events = require('events');
|
||||
@@ -328,7 +329,14 @@ function ViewController(options) {
|
||||
}
|
||||
}
|
||||
|
||||
self.client.log.trace( { formValue : formValue, actionValue : actionValue }, 'Action match');
|
||||
self.client.log.trace(
|
||||
{
|
||||
formValue : formValue,
|
||||
actionValue : actionValue
|
||||
},
|
||||
'Action match'
|
||||
);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user