Merge branch 'master' of ssh://numinibsd/git/base/enigma-bbs

This commit is contained in:
Bryan Ashby 2016-01-03 15:51:06 -07:00
commit e9bdf1f68f
4 changed files with 274 additions and 26 deletions

View File

@ -26,6 +26,7 @@ exports.clearScreen = clearScreen;
exports.resetScreen = resetScreen;
exports.normal = normal;
exports.goHome = goHome;
//exports.deleteLine = deleteLine;
exports.disableVT100LineWrapping = disableVT100LineWrapping;
exports.setSyncTERMFont = setSyncTERMFont;
exports.getSyncTERMFontFromAlias = getSyncTERMFontFromAlias;
@ -52,10 +53,52 @@ var CONTROL = {
nextLine : 'E',
prevLine : 'F',
horizAbsolute : 'G',
//
// CSI [ p1 ] J
// Erase in Page / Erase Data
// Defaults: p1 = 0
// Erases from the current screen according to the value of p1
// 0 - Erase from the current position to the end of the screen.
// 1 - Erase from the current position to the start of the screen.
// 2 - Erase entire screen. As a violation of ECMA-048, also moves
// the cursor to position 1/1 as a number of BBS programs assume
// this behaviour.
// Erased characters are set to the current attribute.
//
// Support:
// * SyncTERM: Works as expected
// * NetRunner: Always clears a screen *height* (e.g. 25) regardless of p1
// and screen remainder
//
eraseData : 'J',
eraseLine : 'K',
insertLine : 'L',
//
// CSI [ p1 ] M
// Delete Line(s) / "ANSI" Music
// Defaults: p1 = 1
// Deletes the current line and the p1 - 1 lines after it scrolling the
// first non-deleted line up to the current line and filling the newly
// empty lines at the end of the screen with the current attribute.
// If "ANSI" Music is fully enabled (CSI = 2 M), performs "ANSI" music
// instead.
// See "ANSI" MUSIC section for more details.
//
// Support:
// * SyncTERM: Works as expected
// * NetRunner:
//
// General Notes:
// See also notes in bansi.txt and cterm.txt about the various
// incompatibilities & oddities around this sequence. ANSI-BBS
// states that it *should* work with any value of p1.
//
deleteLine : 'M',
ansiMusic : 'M',
scrollUp : 'S',
scrollDown : 'T',
setScrollRegion : 'r',
@ -385,6 +428,32 @@ function goHome() {
return exports.goto(); // no params = home = 1,1
}
//
// Delete line(s)
// This method acts like ESC[ p1 M but should work
// for all terminals via using eraseLine and movement
//
/*
function deleteLine(count) {
count = count || 1;
console.log(exports.eraseLine)
var seq = exports.eraseLine(2); // 2 = entire line
var i;
for(i = 1; i < count; ++i) {
seq +=
'\n' + // down a line
exports.eraseLine(2); // erase it
}
// now, move back up any we lines we went down
if(count > 1) {
seq += exports.up(count - 1);
}
return seq;
}
*/
//
// See http://www.termsys.demon.co.uk/vtANSI_BBS.htm
//
@ -410,5 +479,5 @@ function setEmulatedBaudRate(rate) {
115200 : 11,
}[rate] || 0;
return 0 === speed ? exports.emulationSpeed() : exports.emulationSpeed(1, speed);
};
}

View File

@ -33,7 +33,7 @@ function Message(options) {
this.viewCount = options.viewCount || 0;
this.meta = {
system : {}, // we'll always have this one
System : {}, // we'll always have this one
};
if(_.isObject(options.meta)) {
@ -125,11 +125,11 @@ Message.FtnPropertyNames = {
// Note: kludges are stored with their names as-is
Message.prototype.setLocalToUserId = function(userId) {
this.meta.system.local_to_user_id = userId;
this.meta.System.local_to_user_id = userId;
};
Message.prototype.setLocalFromUserId = function(userId) {
this.meta.system.local_from_user_id = userId;
this.meta.System.local_from_user_id = userId;
};
Message.prototype.load = function(options, cb) {

View File

@ -5,6 +5,7 @@
var msgArea = require('./message_area.js');
var Message = require('./message.js');
var MenuModule = require('./menu_module.js').MenuModule;
var ViewController = require('../core/view_controller.js').ViewController;
var async = require('async');
@ -21,8 +22,8 @@ exports.getModule = NewScanModule;
* * Update message ID when reading (this should be working!)
* * New scan all areas
* * User configurable new scan: Area selection (avail from messages area)
*
*
* * Add status TL/VM (either/both should update if present)
* *
*/
@ -33,14 +34,36 @@ function NewScanModule(options) {
var self = this;
var config = this.menuConfig.config;
this.currentStep = 'privateMail';
this.currentStep = 'messageAreas';
this.currentScanAux = 0; // Message.WellKnownAreaNames.Private
this.newScanMessageArea = function(areaName, cb) {
this.newScanMessageArea = function(cb) {
var availMsgAreas = msgArea.getAvailableMessageAreas( { includePrivate : true } );
var currentArea = availMsgAreas[self.currentScanAux];
//
// Scan and update index until we find something. If results are found,
// we'll goto the list module & show them.
//
async.waterfall(
[
function checkAndUpdateIndex(callback) {
// Advance to next area if possible
if(availMsgAreas.length >= self.currentScanAux + 1) {
self.currentScanAux += 1;
callback(null);
} else {
callback(new Error('No more areas'));
}
},
function updateStatus(callback) {
// :TODO: Update status text
callback(null);
},
function newScanAreaAndGetMessages(callback) {
msgArea.getNewMessagesInAreaForUser(
self.client.user.userId, areaName, function msgs(err, msgList) {
self.client.user.userId, currentArea.name, function msgs(err, msgList) {
callback(err, msgList);
}
);
@ -49,52 +72,78 @@ function NewScanModule(options) {
if(msgList && msgList.length > 0) {
var nextModuleOpts = {
extraArgs: {
messageAreaName : areaName,
messageAreaName : currentArea.name,
messageList : msgList,
}
};
self.gotoMenu(config.newScanMessageList || 'newScanMessageList', nextModuleOpts);
} else {
callback(null);
self.newScanMessageArea(cb);
}
}
],
function complete(err) {
cb(err);
}
cb
);
};
}
require('util').inherits(NewScanModule, MenuModule);
NewScanModule.prototype.getSaveState = function() {
return {
currentStep : this.currentStep,
currentStep : this.currentStep,
currentScanAux : this.currentScanAux,
};
};
NewScanModule.prototype.restoreSavedState = function(savedState) {
this.currentStep = savedState.currentStep;
this.currentStep = savedState.currentStep;
this.currentScanAux = savedState.currentScanAux;
};
NewScanModule.prototype.mciReady = function(mciData, cb) {
var self = this;
var self = this;
var vc = self.viewControllers.allViews = new ViewController( { client : self.client } );
// :TODO: display scan step/etc.
switch(this.currentStep) {
case 'privateMail' :
self.currentStep = 'finished';
self.newScanMessageArea(Message.WellKnownAreaNames.Private, cb);
break;
default :
cb(null);
}
async.series(
[
function callParentMciReady(callback) {
NewScanModule.super_.prototype.mciReady.call(self, mciData, callback);
},
function loadFromConfig(callback) {
var loadOpts = {
callingMenu : self,
mciMap : mciData.menu,
noInput : true,
};
vc.loadFromMenuConfig(loadOpts, callback);
},
function performCurrentStepScan(callback) {
switch(self.currentStep) {
case 'messageAreas' :
self.newScanMessageArea(function scanComplete(err) {
callback(null); // finished
});
break;
default :
callback(null);
}
}
],
function complete(err) {
if(err) {
self.client.log.error( { error : err.toString() }, 'Error during new scan');
}
cb(err);
}
);
};
/*

130
oputil.js Normal file
View File

@ -0,0 +1,130 @@
/* jslint node: true */
'use strict';
// ENiGMA½
var config = require('./core/config.js');
var db = require('./core/database.js');
var _ = require('lodash');
var async = require('async');
var argv = require('minimist')(process.argv.slice(2));
var ExitCodes = {
SUCCESS : 0,
ERROR : -1,
BAD_COMMAND : -2,
BAD_ARGS : -3,
}
function printUsage(command) {
var usage;
switch(command) {
case '' :
usage =
'usage: oputil.js [--version] [--help]\n' +
' <command> [<args>]' +
'\n' +
'global args:\n' +
' --config PATH : specify config path';
break;
case 'user' :
usage =
'usage: optutil.js user --user USERNAME <args>\n' +
'\n' +
'valid args:\n' +
' --user USERNAME : specify username\n' +
' --password PASS : reset password to PASS';
break;
}
console.error(usage);
}
function initConfig(cb) {
var configPath = argv.config ? argv.config : config.getDefaultPath();
config.init(configPath, cb);
}
function handleUserCommand() {
if(true === argv.help || !_.isString(argv.user) || 0 === argv.user.length) {
process.exitCode = ExitCodes.ERROR;
return printUsage('user');
}
if(_.isString(argv.password)) {
if(0 === argv.password.length) {
process.exitCode = ExitCodes.BAD_ARGS;
return console.error('Invalid password');
}
var user;
async.waterfall(
[
function init(callback) {
initConfig(callback);
},
function initDb(callback) {
db.initializeDatabases(callback);
},
function getUser(callback) {
user = require('./core/user.js');
user.getUserIdAndName(argv.user, function userNameAndId(err, username, userId) {
if(err) {
process.exitCode = ExitCodes.BAD_ARGS;
callback(new Error('Failed to retrieve user'));
} else {
callback(null, userId);
}
});
},
function setNewPass(userId, callback) {
var u = new user.User();
u.userId = userId;
u.setNewAuthCredentials(argv.password, function credsSet(err) {
if(err) {
process.exitCode = ExitCodes.ERROR;
callback(new Error('Failed setting password'));
} else {
callback(null);
}
});
}
],
function complete(err) {
if(err) {
console.error(err.message);
} else {
console.info('Password set');
}
}
);
}
}
function main() {
process.exitCode = ExitCodes.SUCCESS;
if(0 === argv._.length ||
'help' === argv._[0])
{
printUsage('');
process.exit(ExitCodes.SUCCESS);
}
switch(argv._[0]) {
case 'user' :
handleUserCommand();
break;
default:
printUsage('');
process.exitCode = ExitCodes.BAD_COMMAND;
}
}
main();