diff --git a/core/bbs.js b/core/bbs.js index fba64c66..9cc7d96f 100644 --- a/core/bbs.js +++ b/core/bbs.js @@ -11,6 +11,7 @@ var database = require('./database.js'); var iconv = require('iconv-lite'); var paths = require('path'); var async = require('async'); +var util = require('util'); exports.bbsMain = bbsMain; @@ -51,22 +52,15 @@ function bbsMain() { conf.createDefault(); } - logger.init(); + initialize(function onInit(err) { + if(err) { + console.error('Error initializing: ' + util.inspect(err)); + return; + } - process.on('SIGINT', function onSigInt() { - // :TODO: for any client in |clientConnections|, if 'ready', send a "Server Disconnecting" + semi-gracefull hangup - // e.g. client.disconnectNow() - - logger.log.info('Process interrupted, shutting down'); - process.exit(); + startListening(); }); - - database.initializeDatabases(); - - preServingInit(); - - startListening(); -}; +} function parseArgs() { var args = []; @@ -91,11 +85,13 @@ function initialize(cb) { process.exit(); }); + iconv.extendNodeEncodings(); + callback(null); }, function initDatabases(callback) { database.initializeDatabases(); - callback(null); + callback(null); }, function initThemes(callback) { // Have to pull in here so it's after Config init @@ -112,10 +108,6 @@ function initialize(cb) { ); } -function preServingInit() { - iconv.extendNodeEncodings(); -} - var clientConnections = []; function startListening() { @@ -151,14 +143,13 @@ function startListening() { } addNewClient(client); - //client.runtime.id = clientConnections.push(client) - 1; //logger.log.info({ clientId : client.runtime.id, from : client.address(), server : module.moduleInfo.name }, 'Client connected'); client.on('ready', function onClientReady() { // Go to module -- use default error handler prepareClient(client, function onPrepared() { - modules.goto(conf.config.entryMod, client); + require('./connect.js').connectEntry(client); }); }); @@ -199,6 +190,7 @@ function removeClient(client) { } function prepareClient(client, cb) { + // :TODO: it feels like this should go somewhere else... and be a bit more elegant. if('*' === conf.config.preLoginTheme) { var theme = require('./theme.js'); theme.getRandomTheme(function onRandTheme(err, themeId) { diff --git a/core/config.js b/core/config.js index 627a97ac..791b2a4a 100644 --- a/core/config.js +++ b/core/config.js @@ -7,7 +7,7 @@ var miscUtil = require('./misc_util.js'); module.exports = { // :TODO: remove this ... anti-pattern! - config : undefined, + //config : undefined, defaultPath : function() { var base = miscUtil.resolvePath('~/'); @@ -26,7 +26,7 @@ module.exports = { bbsName : 'Another Fine ENiGMA½ BBS', // :TODO: probably replace this with 'firstMenu' or somthing once that's available - entryMod : 'connect', + entryMod : 'matrix', preLoginTheme : '*', diff --git a/mods/connect.js b/core/connect.js similarity index 71% rename from mods/connect.js rename to core/connect.js index fe5bf57a..f07ea8c9 100644 --- a/mods/connect.js +++ b/core/connect.js @@ -1,21 +1,17 @@ /* jslint node: true */ 'use strict'; -var ansi = require('../core/ansi_term.js'); -var artwork = require('../core/art.js'); -var modules = require('../core/modules.js'); -var Log = require('../core/logger.js').log; +var ansi = require('./ansi_term.js'); +var artwork = require('./art.js'); +var modules = require('./modules.js'); +var Log = require('./logger.js').log; +var Config = require('./config.js').config; var packageJson = require('../package.json'); +var assert = require('assert'); var util = require('util'); -exports.moduleInfo = { - name : 'Connect', - desc : 'First module upon connection', - author : 'NuSkooler', -}; - -exports.entryPoint = entryPoint; +exports.connectEntry = connectEntry; function ansiQueryTermSizeIfNeeded(client) { if(client.term.termHeight > 0 || client.term.termWidth > 0) { @@ -30,10 +26,13 @@ function ansiQueryTermSizeIfNeeded(client) { return; } + assert(2 === pos.length); client.term.termHeight = pos[0]; client.term.termWidth = pos[1]; - Log.debug({ termWidth : client.term.termWidth, termHeight : client.term.termHeight, updateSource : 'ANSI CPR' }, 'Window size updated'); + Log.debug( + { termWidth : client.term.termWidth, termHeight : client.term.termHeight, updateSource : 'ANSI CPR' }, + 'Window size updated'); }; client.once('cursor position report', onCPR); @@ -46,7 +45,21 @@ function ansiQueryTermSizeIfNeeded(client) { client.term.write(ansi.queryScreenSize()); } -function entryPoint(client) { +function prepareTerminal(term) { + term.write(ansi.normal()); + term.write(ansi.disableVT100LineWrapping()); + // :TODO: set xterm stuff -- see x84/others +} + +function displayBanner(term) { + // :TODO: add URL to banner + term.write(ansi.fromPipeCode(util.format('' + + '|33Conected to |32EN|33|01i|32|22GMA|32|01½|00 |33BBS version|31|01 %s\n' + + '|00|33Copyright (c) 2014 Bryan Ashby\n' + + '|00', packageJson.version))); +} + +function connectEntry(client) { var term = client.term; // @@ -55,24 +68,8 @@ function entryPoint(client) { // ansiQueryTermSizeIfNeeded(client); - term.write(ansi.normal()); - - term.write(ansi.disableVT100LineWrapping()); - - - - // - // If we don't yet know the client term width/height, try - // a nonstandard ANSI query - // - - // :TODO: set xterm stuff -- see x84/others - - // :TODO: add URL to banner - term.write(ansi.fromPipeCode(util.format('' + - '|33Conected to |32EN|33|01i|32|22GMA|32|01½|00 |33BBS version|31|01 %s\n' + - '|00|33Copyright (c) 2014 Bryan Ashby\n' + - '|00', packageJson.version))); + prepareTerminal(term); + displayBanner(term); setTimeout(function onTimeout() { term.write(ansi.clearScreen()); @@ -87,7 +84,7 @@ function entryPoint(client) { setTimeout(function onTimeout() { term.write(ansi.clearScreen()); - modules.goto('matrix', client); + modules.goto(Config.entryMod, client); }, timeout); }); }, 500); diff --git a/core/menu_view.js b/core/menu_view.js new file mode 100644 index 00000000..07c7924b --- /dev/null +++ b/core/menu_view.js @@ -0,0 +1,31 @@ +/* jslint node: true */ +'use strict'; + +var View = require('./view.js').View; +var ansi = require('./ansi_term.js'); +var util = require('util'); +var assert = require('assert'); + +exports.MenuView = MenuView; + +function MenuView(client, options) { + View.call(this, client, options); + + this.items = []; + if(this.options.items) { + this.options.items.forEach(function onItem(itemText) { + this.items.push({ + text : itemText, + focused : false, + selected : false, + }); + }); + } + + this.itemSpacing = this.options.itemSpacing || 1; + this.focusPrefix = this.options.focusPrefix || ''; + this.focusSuffix = this.options.focusSuffix || ''; +} + +util.inherits(MenuView, View); + diff --git a/core/text_view.js b/core/text_view.js index edd0029c..365a4e6d 100644 --- a/core/text_view.js +++ b/core/text_view.js @@ -13,8 +13,6 @@ exports.TextView = TextView; function TextView(client, options) { View.call(this, client, options); - var self = this; - if(this.options.maxLength) { this.maxLength = this.options.maxLength; } @@ -31,7 +29,7 @@ function TextView(client, options) { this.setText(this.options.text || ''); - this.isPasswordTextStyle = 'P' === self.textStyle || 'password' === self.textStyle; + this.isPasswordTextStyle = 'P' === this.textStyle || 'password' === this.textStyle; if(this.isPasswordTextStyle) { this.textMaskChar = miscUtil.valueWithDefault(this.options.textMaskChar, '*').substr(0, 1); diff --git a/core/theme.js b/core/theme.js index e9eb28ed..2878f68a 100644 --- a/core/theme.js +++ b/core/theme.js @@ -33,15 +33,14 @@ function getThemeInfo(themeID, cb) { var availableThemes = {}; function initAvailableThemes(cb) { - // lazy init async.waterfall( [ function getDir(callback) { - fs.readdir(Config.paths.themes, function onReadDir(err, files) { + fs.readdir(Config.paths.themes, function onReadDir(err, files) { callback(err, files); }); }, - function filterFiles(files, callback) { + function filterFiles(files, callback) { var filtered = files.filter(function onFilter(file) { return fs.statSync(paths.join(Config.paths.themes, file)).isDirectory(); }); @@ -56,9 +55,9 @@ function initAvailableThemes(cb) { } availableThemes[themeId] = info; } - callback(null); }); }); + callback(null); } ], function onComplete(err) { diff --git a/core/vertical_menu_view.js b/core/vertical_menu_view.js new file mode 100644 index 00000000..0fe606e4 --- /dev/null +++ b/core/vertical_menu_view.js @@ -0,0 +1,17 @@ +/* jslint node: true */ +'use strict'; + +var MenuView = require('./menu_view.js').MenuView; +var ansi = require('./ansi_term.js'); +var util = require('util'); +var assert = require('assert'); + +function VerticalMenuView(client, options) { + MenuView.call(this, client, options); +} + +util.inherits(VerticalMenuView, MenuView); + +VerticalMenuView.prototype.redraw = function() { + VerticalMenuView.super_.prototype.redraw.call(this); +}; \ No newline at end of file diff --git a/mods/matrix.js b/mods/matrix.js index 2f7851af..95dbc00f 100644 --- a/mods/matrix.js +++ b/mods/matrix.js @@ -40,8 +40,6 @@ function entryPoint(client) { return; } - console.log(mci); - user.authenticate('NuSkooler', 'password', client, function onAuth(isValid) { console.log(isValid); });