* ENiGMA now require Node.js 6.x LTS+

* Bump version to 0.0.4-alpha
* Update package dependencies
* Use modified node-buffers that does not use deprecated Array.get()
* Update lodash dependency to 4.x & convert to new methods/etc.
* Better 'noHistory' support for menu stack
* Fix bug in download queue init
* Misc code cleanup
This commit is contained in:
Bryan Ashby 2017-01-28 12:33:06 -07:00
parent 1fc9fc1c90
commit 12d4c158c4
19 changed files with 277 additions and 277 deletions

View File

@ -226,7 +226,7 @@ function ANSIEscapeParser(options) {
self.lastMciCode = fullMciCode; self.lastMciCode = fullMciCode;
self.graphicRenditionForErase = _.clone(self.graphicRendition, true); self.graphicRenditionForErase = _.clone(self.graphicRendition);
} }

View File

@ -1,17 +1,19 @@
/* jslint node: true */ /* jslint node: true */
'use strict'; 'use strict';
var miscUtil = require('./misc_util.js'); // ENiGMA½
const miscUtil = require('./misc_util.js');
var fs = require('fs'); // deps
var paths = require('path'); const fs = require('fs');
var async = require('async'); const paths = require('path');
var _ = require('lodash'); const async = require('async');
var hjson = require('hjson'); const _ = require('lodash');
var assert = require('assert'); const hjson = require('hjson');
const assert = require('assert');
exports.init = init; exports.init = init;
exports.getDefaultPath = getDefaultPath; exports.getDefaultPath = getDefaultPath;
function hasMessageConferenceAndArea(config) { function hasMessageConferenceAndArea(config) {
assert(_.isObject(config.messageConferences)); // we create one ourself! assert(_.isObject(config.messageConferences)); // we create one ourself!
@ -43,38 +45,45 @@ function init(configPath, cb) {
async.waterfall( async.waterfall(
[ [
function loadUserConfig(callback) { function loadUserConfig(callback) {
if(_.isString(configPath)) { if(!_.isString(configPath)) {
fs.readFile(configPath, { encoding : 'utf8' }, function configData(err, data) { return callback(null, { } );
if(err) {
callback(err);
} else {
try {
var configJson = hjson.parse(data);
callback(null, configJson);
} catch(e) {
callback(e);
}
}
});
} else {
callback(null, { } );
} }
fs.readFile(configPath, { encoding : 'utf8' }, (err, configData) => {
if(err) {
return callback(err);
}
let configJson;
try {
configJson = hjson.parse(configData);
} catch(e) {
return callback(e);
}
return callback(null, configJson);
});
}, },
function mergeWithDefaultConfig(configJson, callback) { function mergeWithDefaultConfig(configJson, callback) {
var mergedConfig = _.merge(getDefaultConfig(), configJson, function mergeCustomizer(conf1, conf2) {
// Arrays should always concat const mergedConfig = _.mergeWith(
if(_.isArray(conf1)) { getDefaultConfig(),
// :TODO: look for collisions & override dupes configJson, (conf1, conf2) => {
return conf1.concat(conf2); // Arrays should always concat
if(_.isArray(conf1)) {
// :TODO: look for collisions & override dupes
return conf1.concat(conf2);
}
} }
}); );
callback(null, mergedConfig); return callback(null, mergedConfig);
}, },
function validate(mergedConfig, callback) { function validate(mergedConfig, callback) {
// //
// Various sections must now exist in config // Various sections must now exist in config
// //
// :TODO: Logic is broken here:
if(hasMessageConferenceAndArea(mergedConfig)) { if(hasMessageConferenceAndArea(mergedConfig)) {
var msgAreasErr = new Error('Please create at least one message conference and area!'); var msgAreasErr = new Error('Please create at least one message conference and area!');
msgAreasErr.code = 'EBADCONFIG'; msgAreasErr.code = 'EBADCONFIG';
@ -92,7 +101,7 @@ function init(configPath, cb) {
} }
function getDefaultPath() { function getDefaultPath() {
var base = miscUtil.resolvePath('~/'); const base = miscUtil.resolvePath('~/');
if(base) { if(base) {
// e.g. /home/users/joeuser/.config/enigma-bbs/config.hjson // e.g. /home/users/joeuser/.config/enigma-bbs/config.hjson
return paths.join(base, '.config', 'enigma-bbs', 'config.hjson'); return paths.join(base, '.config', 'enigma-bbs', 'config.hjson');

View File

@ -8,7 +8,11 @@ module.exports = class DownloadQueue {
this.client = client; this.client = client;
if(!Array.isArray(this.client.user.downloadQueue)) { if(!Array.isArray(this.client.user.downloadQueue)) {
this.loadFromProperty(client); if(this.client.user.properties.dl_queue) {
this.loadFromProperty(this.client.user.properties.dl_queue);
} else {
this.client.user.downloadQueue = [];
}
} }
} }

View File

@ -30,3 +30,10 @@ exports.Errors = {
ExternalProcess : (reason, reasonCode) => new EnigError('External process error', -32005, reason, reasonCode), ExternalProcess : (reason, reasonCode) => new EnigError('External process error', -32005, reason, reasonCode),
MissingConfig : (reason, reasonCode) => new EnigError('Missing configuration', -32006, reason, reasonCode), MissingConfig : (reason, reasonCode) => new EnigError('Missing configuration', -32006, reason, reasonCode),
}; };
exports.ErrorReasons = {
AlreadyThere : 'ALREADYTHERE',
InvalidNextMenu : 'BADNEXT',
NoPreviousMenu : 'NOPREV',
NoConditionMatch : 'NOCONDMATCH',
};

View File

@ -45,7 +45,7 @@ function getAvailableFileAreas(client, options) {
// perform ACS check per conf & omit internal if desired // perform ACS check per conf & omit internal if desired
const allAreas = _.map(Config.fileBase.areas, (areaInfo, areaTag) => Object.assign(areaInfo, { areaTag : areaTag } )); const allAreas = _.map(Config.fileBase.areas, (areaInfo, areaTag) => Object.assign(areaInfo, { areaTag : areaTag } ));
return _.omit(allAreas, areaInfo => { return _.omitBy(allAreas, areaInfo => {
if(!options.includeSystemInternal && isInternalArea(areaInfo.areaTag)) { if(!options.includeSystemInternal && isInternalArea(areaInfo.areaTag)) {
return true; return true;
} }

View File

@ -274,7 +274,7 @@ exports.FullScreenEditorModule = exports.getModule = class FullScreenEditorModul
} }
getFooterName() { getFooterName() {
return 'footer' + _.capitalize(this.footerMode); // e.g. 'footerEditor', 'footerEditorMenu', ... return 'footer' + _.upperFirst(this.footerMode); // e.g. 'footerEditor', 'footerEditorMenu', ...
} }
getFormId(name) { getFormId(name) {
@ -431,9 +431,9 @@ exports.FullScreenEditorModule = exports.getModule = class FullScreenEditorModul
callback(null); callback(null);
}, },
function displayFooterArt(callback) { function displayFooterArt(callback) {
var footerArt = self.menuConfig.config.art[options.footerName]; const footerArt = self.menuConfig.config.art[options.footerName];
theme.displayThemedAsset( or theme.displayThemedAsset(
footerArt, footerArt,
self.client, self.client,
{ font : self.menuConfig.font }, { font : self.menuConfig.font },
@ -723,7 +723,7 @@ exports.FullScreenEditorModule = exports.getModule = class FullScreenEditorModul
if(posView) { if(posView) {
this.client.term.rawWrite(ansi.savePos()); this.client.term.rawWrite(ansi.savePos());
// :TODO: Use new formatting techniques here, e.g. state.cursorPositionRow, cursorPositionCol and cursorPositionFormat // :TODO: Use new formatting techniques here, e.g. state.cursorPositionRow, cursorPositionCol and cursorPositionFormat
posView.setText(_.padLeft(String(pos.row + 1), 2, '0') + ',' + _.padLeft(String(pos.col + 1), 2, '0')); posView.setText(_.padStart(String(pos.row + 1), 2, '0') + ',' + _.padEnd(String(pos.col + 1), 2, '0'));
this.client.term.rawWrite(ansi.restorePos()); this.client.term.rawWrite(ansi.restorePos());
} }
} }

View File

@ -104,7 +104,7 @@ exports.MenuModule = class MenuModule extends PluginModule {
self.client.once('cursor position report', pos => { self.client.once('cursor position report', pos => {
pausePosition = { row : pos[0], col : 1 }; pausePosition = { row : pos[0], col : 1 };
self.client.log.trace('After art position recorded', { position : pausePosition } ); self.client.log.trace('After art position recorded', pausePosition );
return callback(null); return callback(null);
}); });

View File

@ -133,37 +133,34 @@ module.exports = class MenuStack {
currentModuleInfo.savedState = currentModuleInfo.instance.getSaveState(); currentModuleInfo.savedState = currentModuleInfo.instance.getSaveState();
currentModuleInfo.instance.leave(); currentModuleInfo.instance.leave();
if(modInst.menuConfig.options.menuFlags.includes('noHistory')) {
this.pop().instance.leave(); // leave & remove current
}
} }
const noHistory = modInst.menuConfig.options.menuFlags.indexOf('noHistory') > -1; self.push({
name : name,
const stackToLog = _.map(self.stack, stackEntry => stackEntry.name); instance : modInst,
extraArgs : loadOpts.extraArgs,
if(!noHistory) { });
self.push({
name : name,
instance : modInst,
extraArgs : loadOpts.extraArgs,
});
stackToLog.push(name);
} else {
stackToLog.push(`${name} (noHistory)`);
}
// restore previous state if requested // restore previous state if requested
if(options && options.savedState) { if(options && options.savedState) {
modInst.restoreSavedState(options.savedState); modInst.restoreSavedState(options.savedState);
} }
modInst.enter(); const stackEntries = self.stack.map(stackEntry => {
let name = stackEntry.name;
if(stackEntry.instance.menuConfig.options.menuFlags.length > 0) {
name += ` (${stackEntry.instance.menuConfig.options.menuFlags.join(', ')})`;
}
return name;
});
self.client.log.trace( self.client.log.trace( { stack : stackEntries }, 'Updated menu stack' );
{
stack : stackToLog modInst.enter();
},
'Updated menu stack'
);
if(cb) { if(cb) {
cb(null); cb(null);

View File

@ -94,18 +94,20 @@ function loadMenu(options, cb) {
{ moduleName : modData.name, extraArgs : options.extraArgs, config : modData.config, info : modData.mod.modInfo }, { moduleName : modData.name, extraArgs : options.extraArgs, config : modData.config, info : modData.mod.modInfo },
'Creating menu module instance'); 'Creating menu module instance');
let moduleInstance;
try { try {
const moduleInstance = new modData.mod.getModule({ moduleInstance = new modData.mod.getModule({
menuName : options.name, menuName : options.name,
menuConfig : modData.config, menuConfig : modData.config,
extraArgs : options.extraArgs, extraArgs : options.extraArgs,
client : options.client, client : options.client,
lastMenuResult : options.lastMenuResult, lastMenuResult : options.lastMenuResult,
}); });
return callback(null, moduleInstance);
} catch(e) { } catch(e) {
return callback(e); return callback(e);
} }
return callback(null, moduleInstance);
} }
], ],
(err, modInst) => { (err, modInst) => {
@ -127,8 +129,8 @@ function getFormConfigByIDAndMap(menuConfig, formId, mciMap, cb) {
return; return;
} }
var formForId = menuConfig.form[formId]; const formForId = menuConfig.form[formId];
var mciReqKey = _.filter(_.pluck(_.sortBy(mciMap, 'code'), 'code'), function(mci) { const mciReqKey = _.filter(_.map(_.sortBy(mciMap, 'code'), 'code'), (mci) => {
return MCIViewFactory.UserViewCodes.indexOf(mci) > -1; return MCIViewFactory.UserViewCodes.indexOf(mci) > -1;
}).join(''); }).join('');

View File

@ -37,7 +37,7 @@ function getAvailableMessageConferences(client, options) {
options = options || { includeSystemInternal : false }; options = options || { includeSystemInternal : false };
// perform ACS check per conf & omit system_internal if desired // perform ACS check per conf & omit system_internal if desired
return _.omit(Config.messageConferences, (conf, confTag) => { return _.omitBy(Config.messageConferences, (conf, confTag) => {
if(!options.includeSystemInternal && 'system_internal' === confTag) { if(!options.includeSystemInternal && 'system_internal' === confTag) {
return true; return true;
} }
@ -73,7 +73,7 @@ function getAvailableMessageAreasByConfTag(confTag, options) {
return areas; return areas;
} else { } else {
// perform ACS check per area // perform ACS check per area
return _.omit(areas, area => { return _.omitBy(areas, area => {
return !options.client.acs.hasMessageAreaRead(area); return !options.client.acs.hasMessageAreaRead(area);
}); });
} }

View File

@ -86,7 +86,7 @@ function loadModulesForCategory(category, iterator, complete) {
}); });
async.each(jsModules, (file, next) => { async.each(jsModules, (file, next) => {
+ loadModule(paths.basename(file, '.js'), category, (err, mod) => { loadModule(paths.basename(file, '.js'), category, (err, mod) => {
iterator(err, mod); iterator(err, mod);
return next(); return next();
}); });

View File

@ -1,21 +1,20 @@
/* jslint node: true */ /* jslint node: true */
'use strict'; 'use strict';
var Config = require('./config.js').config; const Config = require('./config.js').config;
var art = require('./art.js'); const art = require('./art.js');
var ansi = require('./ansi_term.js'); const ansi = require('./ansi_term.js');
var miscUtil = require('./misc_util.js'); const Log = require('./logger.js').log;
var Log = require('./logger.js').log; const configCache = require('./config_cache.js');
var configCache = require('./config_cache.js'); const getFullConfig = require('./config_util.js').getFullConfig;
var getFullConfig = require('./config_util.js').getFullConfig; const asset = require('./asset.js');
var asset = require('./asset.js'); const ViewController = require('./view_controller.js').ViewController;
var ViewController = require('./view_controller.js').ViewController;
var fs = require('fs'); const fs = require('fs');
var paths = require('path'); const paths = require('path');
var async = require('async'); const async = require('async');
var _ = require('lodash'); const _ = require('lodash');
var assert = require('assert'); const assert = require('assert');
exports.getThemeArt = getThemeArt; exports.getThemeArt = getThemeArt;
exports.getAvailableThemes = getAvailableThemes; exports.getAvailableThemes = getAvailableThemes;
@ -100,10 +99,10 @@ function loadTheme(themeID, cb) {
}); });
} }
var availableThemes = {}; const availableThemes = {};
var IMMUTABLE_MCI_PROPERTIES = [ const IMMUTABLE_MCI_PROPERTIES = [
'maxLength', 'argName', 'submit', 'validate' 'maxLength', 'argName', 'submit', 'validate'
]; ];
function getMergedTheme(menuConfig, promptConfig, theme) { function getMergedTheme(menuConfig, promptConfig, theme) {
@ -119,44 +118,44 @@ function getMergedTheme(menuConfig, promptConfig, theme) {
// //
var mergedTheme = _.cloneDeep(menuConfig); var mergedTheme = _.cloneDeep(menuConfig);
if(_.isObject(promptConfig.prompts)) { if(_.isObject(promptConfig.prompts)) {
mergedTheme.prompts = _.cloneDeep(promptConfig.prompts); mergedTheme.prompts = _.cloneDeep(promptConfig.prompts);
} }
// //
// Add in data we won't be altering directly from the theme // Add in data we won't be altering directly from the theme
// //
mergedTheme.info = theme.info; mergedTheme.info = theme.info;
mergedTheme.helpers = theme.helpers; mergedTheme.helpers = theme.helpers;
// //
// merge customizer to disallow immutable MCI properties // merge customizer to disallow immutable MCI properties
// //
var mciCustomizer = function(objVal, srcVal, key) { var mciCustomizer = function(objVal, srcVal, key) {
return IMMUTABLE_MCI_PROPERTIES.indexOf(key) > -1 ? objVal : srcVal; return IMMUTABLE_MCI_PROPERTIES.indexOf(key) > -1 ? objVal : srcVal;
}; };
function getFormKeys(fromObj) { function getFormKeys(fromObj) {
return _.remove(_.keys(fromObj), function pred(k) { return _.remove(_.keys(fromObj), function pred(k) {
return !isNaN(k); // remove all non-numbers return !isNaN(k); // remove all non-numbers
}); });
} }
function mergeMciProperties(dest, src) { function mergeMciProperties(dest, src) {
Object.keys(src).forEach(function mciEntry(mci) { Object.keys(src).forEach(function mciEntry(mci) {
_.merge(dest[mci], src[mci], mciCustomizer); _.mergeWith(dest[mci], src[mci], mciCustomizer);
}); });
} }
function applyThemeMciBlock(dest, src, formKey) { function applyThemeMciBlock(dest, src, formKey) {
if(_.isObject(src.mci)) { if(_.isObject(src.mci)) {
mergeMciProperties(dest, src.mci); mergeMciProperties(dest, src.mci);
} else { } else {
if(_.has(src, [ formKey, 'mci' ])) { if(_.has(src, [ formKey, 'mci' ])) {
mergeMciProperties(dest, src[formKey].mci); mergeMciProperties(dest, src[formKey].mci);
} }
} }
} }
// //
// menu.hjson can have a couple different structures: // menu.hjson can have a couple different structures:
@ -180,103 +179,103 @@ function getMergedTheme(menuConfig, promptConfig, theme) {
// * If theme.hjson provides form ID's, use them. Otherwise, we'll apply directly assuming // * If theme.hjson provides form ID's, use them. Otherwise, we'll apply directly assuming
// there is a generic 'mci' block. // there is a generic 'mci' block.
// //
function applyToForm(form, menuTheme, formKey) { function applyToForm(form, menuTheme, formKey) {
if(_.isObject(form.mci)) { if(_.isObject(form.mci)) {
// non-explicit: no MCI code(s) key assumed since we found 'mci' directly under form ID // non-explicit: no MCI code(s) key assumed since we found 'mci' directly under form ID
applyThemeMciBlock(form.mci, menuTheme, formKey); applyThemeMciBlock(form.mci, menuTheme, formKey);
} else { } else {
var menuMciCodeKeys = _.remove(_.keys(form), function pred(k) { var menuMciCodeKeys = _.remove(_.keys(form), function pred(k) {
return k === k.toUpperCase(); // remove anything not uppercase return k === k.toUpperCase(); // remove anything not uppercase
}); });
menuMciCodeKeys.forEach(function mciKeyEntry(mciKey) { menuMciCodeKeys.forEach(function mciKeyEntry(mciKey) {
var applyFrom; var applyFrom;
if(_.has(menuTheme, [ mciKey, 'mci' ])) { if(_.has(menuTheme, [ mciKey, 'mci' ])) {
applyFrom = menuTheme[mciKey]; applyFrom = menuTheme[mciKey];
} else { } else {
applyFrom = menuTheme; applyFrom = menuTheme;
} }
applyThemeMciBlock(form[mciKey].mci, applyFrom); applyThemeMciBlock(form[mciKey].mci, applyFrom);
}); });
} }
} }
[ 'menus', 'prompts' ].forEach(function areaEntry(sectionName) { [ 'menus', 'prompts' ].forEach(function areaEntry(sectionName) {
_.keys(mergedTheme[sectionName]).forEach(function menuEntry(menuName) { _.keys(mergedTheme[sectionName]).forEach(function menuEntry(menuName) {
var createdFormSection = false; var createdFormSection = false;
var mergedThemeMenu = mergedTheme[sectionName][menuName]; var mergedThemeMenu = mergedTheme[sectionName][menuName];
if(_.has(theme, [ 'customization', sectionName, menuName ])) { if(_.has(theme, [ 'customization', sectionName, menuName ])) {
var menuTheme = theme.customization[sectionName][menuName]; var menuTheme = theme.customization[sectionName][menuName];
// config block is direct assign/overwrite // config block is direct assign/overwrite
// :TODO: should probably be _.merge() // :TODO: should probably be _.merge()
if(menuTheme.config) { if(menuTheme.config) {
mergedThemeMenu.config = _.assign(mergedThemeMenu.config || {}, menuTheme.config); mergedThemeMenu.config = _.assign(mergedThemeMenu.config || {}, menuTheme.config);
} }
if('menus' === sectionName) { if('menus' === sectionName) {
if(_.isObject(mergedThemeMenu.form)) { if(_.isObject(mergedThemeMenu.form)) {
getFormKeys(mergedThemeMenu.form).forEach(function formKeyEntry(formKey) { getFormKeys(mergedThemeMenu.form).forEach(function formKeyEntry(formKey) {
applyToForm(mergedThemeMenu.form[formKey], menuTheme, formKey); applyToForm(mergedThemeMenu.form[formKey], menuTheme, formKey);
}); });
} else { } else {
if(_.isObject(menuTheme.mci)) { if(_.isObject(menuTheme.mci)) {
// //
// Not specified at menu level means we apply anything from the // Not specified at menu level means we apply anything from the
// theme to form.0.mci{} // theme to form.0.mci{}
// //
mergedThemeMenu.form = { 0 : { mci : { } } }; mergedThemeMenu.form = { 0 : { mci : { } } };
mergeMciProperties(mergedThemeMenu.form[0], menuTheme); mergeMciProperties(mergedThemeMenu.form[0], menuTheme);
createdFormSection = true; createdFormSection = true;
} }
} }
} else if('prompts' === sectionName) { } else if('prompts' === sectionName) {
// no 'form' or form keys for prompts -- direct to mci // no 'form' or form keys for prompts -- direct to mci
applyToForm(mergedThemeMenu, menuTheme); applyToForm(mergedThemeMenu, menuTheme);
} }
} }
// //
// Finished merging for this menu/prompt // Finished merging for this menu/prompt
// //
// If the following conditions are true, set runtime.autoNext to true: // If the following conditions are true, set runtime.autoNext to true:
// * This is a menu // * This is a menu
// * There is/was no explicit 'form' section // * There is/was no explicit 'form' section
// * There is no 'prompt' specified // * There is no 'prompt' specified
// //
if('menus' === sectionName && !_.isString(mergedThemeMenu.prompt) && if('menus' === sectionName && !_.isString(mergedThemeMenu.prompt) &&
(createdFormSection || !_.isObject(mergedThemeMenu.form))) (createdFormSection || !_.isObject(mergedThemeMenu.form)))
{ {
mergedThemeMenu.runtime = _.merge(mergedThemeMenu.runtime || {}, { autoNext : true } ); mergedThemeMenu.runtime = _.merge(mergedThemeMenu.runtime || {}, { autoNext : true } );
} }
}); });
}); });
return mergedTheme; return mergedTheme;
} }
function initAvailableThemes(cb) { function initAvailableThemes(cb) {
var menuConfig; var menuConfig;
var promptConfig; var promptConfig;
async.waterfall( async.waterfall(
[ [
function loadMenuConfig(callback) { function loadMenuConfig(callback) {
getFullConfig(Config.general.menuFile, function gotConfig(err, mc) { getFullConfig(Config.general.menuFile, function gotConfig(err, mc) {
menuConfig = mc; menuConfig = mc;
callback(err); callback(err);
}); });
}, },
function loadPromptConfig(callback) { function loadPromptConfig(callback) {
getFullConfig(Config.general.promptFile, function gotConfig(err, pc) { getFullConfig(Config.general.promptFile, function gotConfig(err, pc) {
promptConfig = pc; promptConfig = pc;
callback(err); callback(err);
}); });
}, },
function getDir(callback) { function getDir(callback) {
fs.readdir(Config.paths.themes, function dirRead(err, files) { fs.readdir(Config.paths.themes, function dirRead(err, files) {
callback(err, files); callback(err, files);
@ -294,7 +293,7 @@ function initAvailableThemes(cb) {
filtered.forEach(function themeEntry(themeId) { filtered.forEach(function themeEntry(themeId) {
loadTheme(themeId, function themeLoaded(err, theme, themePath) { loadTheme(themeId, function themeLoaded(err, theme, themePath) {
if(!err) { if(!err) {
availableThemes[themeId] = getMergedTheme(menuConfig, promptConfig, theme); availableThemes[themeId] = getMergedTheme(menuConfig, promptConfig, theme);
configCache.on('recached', function recached(path) { configCache.on('recached', function recached(path) {
if(themePath === path) { if(themePath === path) {
@ -339,17 +338,17 @@ function getRandomTheme() {
} }
function setClientTheme(client, themeId) { function setClientTheme(client, themeId) {
var desc; var desc;
try { try {
client.currentTheme = getAvailableThemes()[themeId]; client.currentTheme = getAvailableThemes()[themeId];
desc = 'Set client theme'; desc = 'Set client theme';
} catch(e) { } catch(e) {
client.currentTheme = getAvailableThemes()[Config.defaults.theme]; client.currentTheme = getAvailableThemes()[Config.defaults.theme];
desc = 'Failed setting theme by supplied ID; Using default'; desc = 'Failed setting theme by supplied ID; Using default';
} }
client.log.debug( { themeId : themeId, info : client.currentTheme.info }, desc); client.log.debug( { themeId : themeId, info : client.currentTheme.info }, desc);
} }
function getThemeArt(options, cb) { function getThemeArt(options, cb) {

View File

@ -338,7 +338,7 @@ User.prototype.removeProperty = function(propName, cb) {
return cb(err); return cb(err);
} }
} }
) );
}; };
User.prototype.persistProperties = function(properties, cb) { User.prototype.persistProperties = function(properties, cb) {
@ -474,7 +474,7 @@ function generatePasswordDerivedKeySalt(cb) {
function generatePasswordDerivedKey(password, salt, cb) { function generatePasswordDerivedKey(password, salt, cb) {
password = new Buffer(password).toString('hex'); password = new Buffer(password).toString('hex');
crypto.pbkdf2(password, salt, User.PBKDF2.iterations, User.PBKDF2.keyLen, function onDerivedKey(err, dk) { crypto.pbkdf2(password, salt, User.PBKDF2.iterations, User.PBKDF2.keyLen, 'sha1', function onDerivedKey(err, dk) {
if(err) { if(err) {
cb(err); cb(err);
} else { } else {

View File

@ -73,8 +73,9 @@ function ViewController(options) {
self.switchFocus(actionForKey.viewId); self.switchFocus(actionForKey.viewId);
self.submitForm(key); self.submitForm(key);
} else if(_.isString(actionForKey.action)) { } else if(_.isString(actionForKey.action)) {
const formData = self.getFocusedView() ? self.getFormData() : { };
self.handleActionWrapper( self.handleActionWrapper(
{ ch : ch, key : key }, // formData Object.assign( { ch : ch, key : key }, formData ), // formData + key info
actionForKey); // actionBlock actionForKey); // actionBlock
} }
} else { } else {
@ -115,6 +116,7 @@ function ViewController(options) {
self.emit('submit', this.getFormData(key)); self.emit('submit', this.getFormData(key));
}; };
// :TODO: replace this in favor of overriding toJSON() for various things such that logging will *never* output them
this.getLogFriendlyFormData = function(formData) { this.getLogFriendlyFormData = function(formData) {
// :TODO: these fields should be part of menu.json sensitiveMembers[] // :TODO: these fields should be part of menu.json sensitiveMembers[]
var safeFormData = _.cloneDeep(formData); var safeFormData = _.cloneDeep(formData);
@ -585,7 +587,7 @@ ViewController.prototype.loadFromPromptConfig = function(options, cb) {
for(var c = 0; c < menuSubmit.length; ++c) { for(var c = 0; c < menuSubmit.length; ++c) {
var actionBlock = menuSubmit[c]; var actionBlock = menuSubmit[c];
if(_.isEqual(formData.value, actionBlock.value, self.actionBlockValueComparator)) { if(_.isEqualWith(formData.value, actionBlock.value, self.actionBlockValueComparator)) {
self.handleActionWrapper(formData, actionBlock); self.handleActionWrapper(formData, actionBlock);
break; // there an only be one... break; // there an only be one...
} }
@ -713,7 +715,7 @@ ViewController.prototype.loadFromMenuConfig = function(options, cb) {
for(var c = 0; c < confForFormId.length; ++c) { for(var c = 0; c < confForFormId.length; ++c) {
var actionBlock = confForFormId[c]; var actionBlock = confForFormId[c];
if(_.isEqual(formData.value, actionBlock.value, self.actionBlockValueComparator)) { if(_.isEqualWith(formData.value, actionBlock.value, self.actionBlockValueComparator)) {
self.handleActionWrapper(formData, actionBlock); self.handleActionWrapper(formData, actionBlock);
break; // there an only be one... break; // there an only be one...
} }
@ -827,38 +829,6 @@ ViewController.prototype.getFormData = function(key) {
this.client.log.error( { error : e.message }, 'Exception caught gathering form data' ); this.client.log.error( { error : e.message }, 'Exception caught gathering form data' );
} }
}); });
/*
var viewData;
var view;
for(var id in this.views) {
try {
view = this.views[id];
viewData = view.getData();
if(!_.isUndefined(viewData)) {
if(_.isString(view.submitArgName)) {
formData.value[view.submitArgName] = viewData;
} else {
formData.value[id] = viewData;
}
}
} catch(e) {
this.client.log.error(e); // :TODO: Log better ;)
}
}*/
return formData; return formData;
}; };
/*
ViewController.prototype.formatMenuArgs = function(args) {
var self = this;
return _.mapValues(args, function val(value) {
if('string' === typeof value) {
return self.formatMCIString(value);
}
return value;
});
};
*/

View File

@ -509,7 +509,7 @@ exports.getModule = class FileAreaList extends MenuModule {
displayDetailsSection(sectionName, clearArea, cb) { displayDetailsSection(sectionName, clearArea, cb) {
const self = this; const self = this;
const name = `details${_.capitalize(sectionName)}`; const name = `details${_.upperFirst(sectionName)}`;
async.series( async.series(
[ [

View File

@ -61,12 +61,20 @@ exports.getModule = class FileBaseDownloadQueueManager extends MenuModule {
viewItemInfo : (formData, extraArgs, cb) => { viewItemInfo : (formData, extraArgs, cb) => {
}, },
removeItem : (formData, extraArgs, cb) => { removeItem : (formData, extraArgs, cb) => {
const selectedItem = formData.value.queueItem; const selectedItem = this.dlQueue.items[formData.value.queueItem];
this.dlQueue.removeItems(selectedItem); if(!selectedItem) {
return cb(null);
}
this.dlQueue.removeItems(selectedItem.fileId);
// :TODO: broken: does not redraw menu properly - needs fixed!
return this.updateDownloadQueueView(cb); return this.updateDownloadQueueView(cb);
}, },
clearQueue : (formData, extraArgs, cb) => { clearQueue : (formData, extraArgs, cb) => {
this.dlQueue.clear(); this.dlQueue.clear();
// :TODO: broken: does not redraw menu properly - needs fixed!
return this.updateDownloadQueueView(cb); return this.updateDownloadQueueView(cb);
} }
}; };

View File

@ -32,7 +32,8 @@ exports.getModule = class AreaViewFSEModule extends FullScreenEditorModule {
const self = this; const self = this;
this.menuMethods = { // assign *additional* menuMethods
Object.assign(this.menuMethods, {
nextMessage : (formData, extraArgs, cb) => { nextMessage : (formData, extraArgs, cb) => {
if(self.messageIndex + 1 < self.messageList.length) { if(self.messageIndex + 1 < self.messageList.length) {
self.messageIndex++; self.messageIndex++;
@ -85,7 +86,7 @@ exports.getModule = class AreaViewFSEModule extends FullScreenEditorModule {
self.client.log(extraArgs, 'Missing extraArgs.menu'); self.client.log(extraArgs, 'Missing extraArgs.menu');
return cb(null); return cb(null);
} }
}; });
} }

View File

@ -56,7 +56,7 @@ exports.getModule = class WhosOnlineModule extends MenuModule {
onlineListView.setItems(_.map(onlineList, oe => { onlineListView.setItems(_.map(onlineList, oe => {
if(oe.authenticated) { if(oe.authenticated) {
oe.timeOn = _.capitalize(oe.timeOn.humanize()); oe.timeOn = _.upperFirst(oe.timeOn.humanize());
} else { } else {
[ 'realName', 'location', 'affils', 'timeOn' ].forEach(m => { [ 'realName', 'location', 'affils', 'timeOn' ].forEach(m => {
oe[m] = otherUnknown; oe[m] = otherUnknown;

View File

@ -1,6 +1,6 @@
{ {
"name": "enigma-bbs", "name": "enigma-bbs",
"version": "0.0.3-alpha", "version": "0.0.4-alpha",
"description": "ENiGMA½ Bulletin Board System", "description": "ENiGMA½ Bulletin Board System",
"author": "Bryan Ashby <bryan@l33t.codes>", "author": "Bryan Ashby <bryan@l33t.codes>",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
@ -18,29 +18,32 @@
"retro" "retro"
], ],
"dependencies": { "dependencies": {
"async": "^1.5.1", "async": "^2.1.4",
"binary": "0.3.x", "binary": "0.3.x",
"buffers": "0.1.x", "buffers": "NuSkooler/node-buffers",
"bunyan": "^1.7.1", "bunyan": "^1.7.1",
"farmhash": "^1.2.1", "farmhash": "^1.2.1",
"fs-extra": "0.26.x", "fs-extra": "^2.0.0",
"gaze": "^0.5.2", "gaze": "^1.1.2",
"hjson": "1.7.x", "hashids": "^1.1.1",
"hjson": "^2.4.1",
"iconv-lite": "^0.4.13", "iconv-lite": "^0.4.13",
"inquirer": "^1.1.0", "inquirer": "^3.0.1",
"later": "1.2.0", "later": "1.2.0",
"lodash": "^3.10.1", "lodash": "^4.17.4",
"mime-types": "^2.1.12",
"minimist": "1.2.x", "minimist": "1.2.x",
"moment": "^2.11.0", "moment": "^2.11.0",
"node-uuid": "^1.4.7", "node-uuid": "^1.4.7",
"ptyw.js": "NuSkooler/ptyw.js", "ptyw.js": "NuSkooler/ptyw.js",
"sqlite3": "^3.1.1", "sqlite3": "^3.1.1",
"ssh2": "^0.5.1", "ssh2": "^0.5.1",
"temp": "^0.8.3", "temp": "^0.8.3"
"hashids" : "^1.1.1", },
"mime-types" : "^2.1.12" "devDependencies": {
"lodash-migrate": "^0.3.16"
}, },
"engines": { "engines": {
"node": ">=4.2.0" "node": ">=6.9.2"
} }
} }