/* jslint node: true */ 'use strict'; // enigma-bbs const { MenuModule } = require('../core/menu_module.js'); const { resetScreen } = require('../core/ansi_term.js'); const { Errors } = require('./enig_error.js'); const { trackDoorRunBegin, trackDoorRunEnd } = require('./door_util.js'); // deps const async = require('async'); const RLogin = require('rlogin'); exports.moduleInfo = { name: 'CombatNet', desc: 'CombatNet Access Module', author: 'Dave Stephens', }; exports.getModule = class CombatNetModule extends MenuModule { constructor(options) { super(options); // establish defaults this.config = options.menuConfig.config; this.config.host = this.config.host || 'bbs.combatnet.us'; this.config.rloginPort = this.config.rloginPort || 4513; } initSequence() { const self = this; async.series( [ function validateConfig(callback) { return self.validateConfigFields( { host: 'string', password: 'string', bbsTag: 'string', rloginPort: 'number', }, callback ); }, function establishRloginConnection(callback) { self.client.term.write(resetScreen()); self.client.term.write('Connecting to CombatNet, please wait...\n'); let doorTracking; const restorePipeToNormal = function () { if (self.client.term.output) { self.client.term.output.removeListener( 'data', sendToRloginBuffer ); if (doorTracking) { trackDoorRunEnd(doorTracking); } } }; const rlogin = new RLogin({ clientUsername: self.config.password, serverUsername: `${self.config.bbsTag}${self.client.user.username}`, host: self.config.host, port: self.config.rloginPort, terminalType: self.client.term.termClient, terminalSpeed: 57600, }); // If there was an error ... rlogin.on('error', err => { self.client.log.info( `CombatNet rlogin client error: ${err.message}` ); restorePipeToNormal(); return callback(err); }); // If we've been disconnected ... rlogin.on('disconnect', () => { self.client.log.info('Disconnected from CombatNet'); restorePipeToNormal(); return callback(null); }); function sendToRloginBuffer(buffer) { rlogin.send(buffer); } rlogin.on( 'connect', /* The 'connect' event handler will be supplied with one argument, a boolean indicating whether or not the connection was established. */ function (state) { if (state) { self.client.log.info('Connected to CombatNet'); self.client.term.output.on('data', sendToRloginBuffer); doorTracking = trackDoorRunBegin(self.client); } else { return callback( Errors.General( 'Failed to establish establish CombatNet connection' ) ); } } ); // If data (a Buffer) has been received from the server ... rlogin.on('data', data => { self.client.term.rawWrite(data); }); // connect... rlogin.connect(); // note: no explicit callback() until we're finished! }, ], err => { if (err) { self.client.log.warn({ error: err.message }, 'CombatNet error'); } // if the client is still here, go to previous self.prevMenu(); } ); } };