Merge branch 'master' of ssh://numinibsd/git/base/enigma-bbs
Conflicts: mods/themes/luciano_blocktronics/CCHANGE.ANS
This commit is contained in:
commit
d777f2c199
|
@ -24,9 +24,9 @@ ENiGMA½ is a modern BBS software with a nostalgic flair!
|
||||||
## In the Works
|
## In the Works
|
||||||
* More ES6+ usage, and **documentation**!
|
* More ES6+ usage, and **documentation**!
|
||||||
* File areas
|
* File areas
|
||||||
* ACS support for more areas
|
* More ACS support coverage
|
||||||
* SysOp dashboard (ye ol' WFC)
|
* SysOp dashboard (ye ol' WFC)
|
||||||
* Missing functionality such as searching, pipe code support in message areas, etc.
|
* Missing functionality such as searching, message area coloring, etc.
|
||||||
* String localization
|
* String localization
|
||||||
* A lot more! Feel free to request features via [the issue tracker](https://github.com/NuSkooler/enigma-bbs/issues)
|
* A lot more! Feel free to request features via [the issue tracker](https://github.com/NuSkooler/enigma-bbs/issues)
|
||||||
|
|
||||||
|
@ -61,6 +61,9 @@ Please see the [Quickstart](docs/index.md#quickstart)
|
||||||
* [M. Griffin](https://github.com/M-griffin), author of [Enthral BBS](https://github.com/M-griffin/Enthral), [Oblivion/2 XRM](https://github.com/M-griffin/Oblivion2-XRM) and [EtherTerm](https://github.com/M-griffin/EtherTerm)!
|
* [M. Griffin](https://github.com/M-griffin), author of [Enthral BBS](https://github.com/M-griffin/Enthral), [Oblivion/2 XRM](https://github.com/M-griffin/Oblivion2-XRM) and [EtherTerm](https://github.com/M-griffin/EtherTerm)!
|
||||||
* [Caphood](http://www.reddit.com/user/Caphood), supreme SysOp of [BLACK ƒlag](http://www.bbsnexus.com/directory/listing/blackflag.html) BBS
|
* [Caphood](http://www.reddit.com/user/Caphood), supreme SysOp of [BLACK ƒlag](http://www.bbsnexus.com/directory/listing/blackflag.html) BBS
|
||||||
* Luciano Ayres of [Blocktronics](http://blocktronics.org/), creator of the "Mystery Skulls" default ENiGMA½ theme!
|
* Luciano Ayres of [Blocktronics](http://blocktronics.org/), creator of the "Mystery Skulls" default ENiGMA½ theme!
|
||||||
|
* Sudndeath for Xibalba ANSI work!
|
||||||
|
* Jack Phlash for kick ass ENiGMA½ and Xibalba ASCII (Check out [IMPURE60](http://pc.textmod.es/pack/impure60/)!!)
|
||||||
|
* Avon of [Agency BBS](http://bbs.geek.nz/) and fsxNet
|
||||||
|
|
||||||
## License
|
## License
|
||||||
Released under the [BSD 2-clause](https://opensource.org/licenses/BSD-2-Clause) license:
|
Released under the [BSD 2-clause](https://opensource.org/licenses/BSD-2-Clause) license:
|
||||||
|
|
|
@ -16,7 +16,7 @@ let async = require('async');
|
||||||
let util = require('util');
|
let util = require('util');
|
||||||
let _ = require('lodash');
|
let _ = require('lodash');
|
||||||
let assert = require('assert');
|
let assert = require('assert');
|
||||||
let mkdirp = require('mkdirp');
|
let mkdirs = require('fs-extra').mkdirs;
|
||||||
|
|
||||||
// our main entry point
|
// our main entry point
|
||||||
exports.bbsMain = bbsMain;
|
exports.bbsMain = bbsMain;
|
||||||
|
@ -78,7 +78,7 @@ function bbsMain() {
|
||||||
],
|
],
|
||||||
function complete(err) {
|
function complete(err) {
|
||||||
if(err) {
|
if(err) {
|
||||||
logger.log.error(err);
|
console.error('Error initializing: ' + util.inspect(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -89,7 +89,7 @@ function initialize(cb) {
|
||||||
[
|
[
|
||||||
function createMissingDirectories(callback) {
|
function createMissingDirectories(callback) {
|
||||||
async.each(Object.keys(conf.config.paths), function entry(pathKey, next) {
|
async.each(Object.keys(conf.config.paths), function entry(pathKey, next) {
|
||||||
mkdirp(conf.config.paths[pathKey], function dirCreated(err) {
|
mkdirs(conf.config.paths[pathKey], function dirCreated(err) {
|
||||||
if(err) {
|
if(err) {
|
||||||
console.error('Could not create path: ' + conf.config.paths[pathKey] + ': ' + err.toString());
|
console.error('Could not create path: ' + conf.config.paths[pathKey] + ': ' + err.toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -220,8 +220,8 @@ function getQuotePrefix(name) {
|
||||||
// http://ftsc.org/docs/fts-0004.001
|
// http://ftsc.org/docs/fts-0004.001
|
||||||
//
|
//
|
||||||
function getOrigin(address) {
|
function getOrigin(address) {
|
||||||
const origin = _.has(Config.messageNetworks.originName) ?
|
const origin = _.has(Config, 'messageNetworks.originLine') ?
|
||||||
Config.messageNetworks.originName :
|
Config.messageNetworks.originLine :
|
||||||
Config.general.boardName;
|
Config.general.boardName;
|
||||||
|
|
||||||
const addrStr = new Address(address).toString('5D');
|
const addrStr = new Address(address).toString('5D');
|
||||||
|
|
|
@ -15,13 +15,13 @@ let Message = require('../message.js');
|
||||||
let moment = require('moment');
|
let moment = require('moment');
|
||||||
let _ = require('lodash');
|
let _ = require('lodash');
|
||||||
let paths = require('path');
|
let paths = require('path');
|
||||||
let mkdirp = require('mkdirp');
|
|
||||||
let async = require('async');
|
let async = require('async');
|
||||||
let fs = require('fs');
|
let fs = require('fs');
|
||||||
let later = require('later');
|
let later = require('later');
|
||||||
let temp = require('temp').track(); // track() cleans up temp dir/files for us
|
let temp = require('temp').track(); // track() cleans up temp dir/files for us
|
||||||
let assert = require('assert');
|
let assert = require('assert');
|
||||||
let gaze = require('gaze');
|
let gaze = require('gaze');
|
||||||
|
let fse = require('fs-extra');
|
||||||
|
|
||||||
exports.moduleInfo = {
|
exports.moduleInfo = {
|
||||||
name : 'FTN BSO',
|
name : 'FTN BSO',
|
||||||
|
@ -627,7 +627,7 @@ function FTNMessageScanTossModule() {
|
||||||
async.waterfall(
|
async.waterfall(
|
||||||
[
|
[
|
||||||
function createOutgoingDir(callback) {
|
function createOutgoingDir(callback) {
|
||||||
mkdirp(outgoingDir, err => {
|
fse.mkdirs(outgoingDir, err => {
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -680,13 +680,13 @@ function FTNMessageScanTossModule() {
|
||||||
outgoingDir,
|
outgoingDir,
|
||||||
`${paths.basename(oldPath, 'pk_')}${ext}`);
|
`${paths.basename(oldPath, 'pk_')}${ext}`);
|
||||||
|
|
||||||
fs.rename(oldPath, newPath, nextFile);
|
fse.move(oldPath, newPath, nextFile);
|
||||||
} else {
|
} else {
|
||||||
const newPath = paths.join(outgoingDir, paths.basename(oldPath));
|
const newPath = paths.join(outgoingDir, paths.basename(oldPath));
|
||||||
fs.rename(oldPath, newPath, err => {
|
fse.move(oldPath, newPath, err => {
|
||||||
if(err) {
|
if(err) {
|
||||||
Log.warn(
|
Log.warn(
|
||||||
{ oldPath : oldPath, newPath : newPath },
|
{ oldPath : oldPath, newPath : newPath, error : err.toString() },
|
||||||
'Failed moving temporary bundle file!');
|
'Failed moving temporary bundle file!');
|
||||||
|
|
||||||
return nextFile();
|
return nextFile();
|
||||||
|
@ -734,7 +734,7 @@ function FTNMessageScanTossModule() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Message.getMessageIdsByMetaValue('FtnKludge', 'MSGID', message.meta.FtnKludge.REPLY, (err, msgIds) => {
|
Message.getMessageIdsByMetaValue('FtnKludge', 'MSGID', message.meta.FtnKludge.REPLY, (err, msgIds) => {
|
||||||
if(!err) {
|
if(msgIds && msgIds.length > 0) {
|
||||||
assert(1 === msgIds.length);
|
assert(1 === msgIds.length);
|
||||||
message.replyToMsgId = msgIds[0];
|
message.replyToMsgId = msgIds[0];
|
||||||
}
|
}
|
||||||
|
@ -742,7 +742,7 @@ function FTNMessageScanTossModule() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.importNetMailToArea = function(localAreaTag, header, message, cb) {
|
this.importEchoMailToArea = function(localAreaTag, header, message, cb) {
|
||||||
async.series(
|
async.series(
|
||||||
[
|
[
|
||||||
function validateDestinationAddress(callback) {
|
function validateDestinationAddress(callback) {
|
||||||
|
@ -807,6 +807,12 @@ function FTNMessageScanTossModule() {
|
||||||
let packetHeader;
|
let packetHeader;
|
||||||
|
|
||||||
const packetOpts = { keepTearAndOrigin : true };
|
const packetOpts = { keepTearAndOrigin : true };
|
||||||
|
|
||||||
|
let importStats = {
|
||||||
|
areaSuccess : {}, // areaTag->count
|
||||||
|
areaFail : {}, // areaTag->count
|
||||||
|
otherFail : 0,
|
||||||
|
};
|
||||||
|
|
||||||
new ftnMailPacket.Packet(packetOpts).read(packetPath, (entryType, entryData, next) => {
|
new ftnMailPacket.Packet(packetOpts).read(packetPath, (entryType, entryData, next) => {
|
||||||
if('header' === entryType) {
|
if('header' === entryType) {
|
||||||
|
@ -831,15 +837,21 @@ function FTNMessageScanTossModule() {
|
||||||
//
|
//
|
||||||
const localAreaTag = self.getLocalAreaTagByFtnAreaTag(areaTag);
|
const localAreaTag = self.getLocalAreaTagByFtnAreaTag(areaTag);
|
||||||
if(localAreaTag) {
|
if(localAreaTag) {
|
||||||
self.importNetMailToArea(localAreaTag, packetHeader, message, err => {
|
self.importEchoMailToArea(localAreaTag, packetHeader, message, err => {
|
||||||
if(err) {
|
if(err) {
|
||||||
|
// bump area fail stats
|
||||||
|
importStats.areaFail[localAreaTag] = (importStats.areaFail[localAreaTag] || 0) + 1;
|
||||||
|
|
||||||
if('SQLITE_CONSTRAINT' === err.code) {
|
if('SQLITE_CONSTRAINT' === err.code) {
|
||||||
Log.info(
|
Log.info(
|
||||||
{ subject : message.subject, uuid : message.uuid },
|
{ area : localAreaTag, subject : message.subject, uuid : message.uuid },
|
||||||
'Not importing non-unique message');
|
'Not importing non-unique message');
|
||||||
|
|
||||||
return next(null);
|
return next(null);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// bump area success
|
||||||
|
importStats.areaSuccess[localAreaTag] = (importStats.areaSuccess[localAreaTag] || 0) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
next(err);
|
next(err);
|
||||||
|
@ -849,14 +861,25 @@ function FTNMessageScanTossModule() {
|
||||||
// No local area configured for this import
|
// No local area configured for this import
|
||||||
//
|
//
|
||||||
// :TODO: Handle the "catch all" case, if configured
|
// :TODO: Handle the "catch all" case, if configured
|
||||||
|
Log.warn( { areaTag : areaTag }, 'No local area configured for this packet file!');
|
||||||
|
|
||||||
|
// bump generic failure
|
||||||
|
importStats.otherFail += 1;
|
||||||
|
|
||||||
|
return next(null);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
// NetMail
|
// NetMail
|
||||||
//
|
//
|
||||||
|
Log.warn('NetMail import not yet implemented!');
|
||||||
|
return next(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, err => {
|
}, err => {
|
||||||
|
const finalStats = Object.assign(importStats, { packetPath : packetPath } );
|
||||||
|
Log.info(finalStats, 'Import complete');
|
||||||
|
|
||||||
cb(err);
|
cb(err);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -874,10 +897,13 @@ function FTNMessageScanTossModule() {
|
||||||
},
|
},
|
||||||
function importPacketFiles(packetFiles, callback) {
|
function importPacketFiles(packetFiles, callback) {
|
||||||
let rejects = [];
|
let rejects = [];
|
||||||
async.each(packetFiles, (packetFile, nextFile) => {
|
async.eachSeries(packetFiles, (packetFile, nextFile) => {
|
||||||
self.importMessagesFromPacketFile(paths.join(importDir, packetFile), '', err => {
|
self.importMessagesFromPacketFile(paths.join(importDir, packetFile), '', err => {
|
||||||
// :TODO: check err -- log / track rejects, etc.
|
|
||||||
if(err) {
|
if(err) {
|
||||||
|
Log.debug(
|
||||||
|
{ path : paths.join(importDir, packetFile), error : err.toString() },
|
||||||
|
'Failed to import packet file');
|
||||||
|
|
||||||
rejects.push(packetFile);
|
rejects.push(packetFile);
|
||||||
}
|
}
|
||||||
nextFile();
|
nextFile();
|
||||||
|
@ -920,7 +946,15 @@ function FTNMessageScanTossModule() {
|
||||||
},
|
},
|
||||||
function discoverBundles(callback) {
|
function discoverBundles(callback) {
|
||||||
fs.readdir(importDir, (err, files) => {
|
fs.readdir(importDir, (err, files) => {
|
||||||
files = files.filter(f => '.pkt' !== paths.extname(f));
|
// :TODO: Need to be explicit about files to attempt an extract, e.g. *.su?, *.mo?, ...
|
||||||
|
// :TODO: if we do much more of this, probably just use the glob module
|
||||||
|
//files = files.filter(f => '.pkt' !== paths.extname(f));
|
||||||
|
|
||||||
|
const bundleRegExp = /\.(su|mo|tu|we|th|fr|sa)[0-9A-Za-z]/;
|
||||||
|
files = files.filter(f => {
|
||||||
|
const fext = paths.extname(f);
|
||||||
|
return bundleRegExp.test(fext);
|
||||||
|
});
|
||||||
|
|
||||||
async.map(files, (file, transform) => {
|
async.map(files, (file, transform) => {
|
||||||
const fullPath = paths.join(importDir, file);
|
const fullPath = paths.join(importDir, file);
|
||||||
|
@ -1059,6 +1093,15 @@ FTNMessageScanTossModule.prototype.startup = function(cb) {
|
||||||
if(_.isObject(this.moduleConfig.schedule)) {
|
if(_.isObject(this.moduleConfig.schedule)) {
|
||||||
const exportSchedule = this.parseScheduleString(this.moduleConfig.schedule.export);
|
const exportSchedule = this.parseScheduleString(this.moduleConfig.schedule.export);
|
||||||
if(exportSchedule) {
|
if(exportSchedule) {
|
||||||
|
Log.debug(
|
||||||
|
{
|
||||||
|
schedule : this.moduleConfig.schedule.export,
|
||||||
|
schedOK : -1 === exportSchedule.sched.error,
|
||||||
|
immediate : exportSchedule.immediate ? true : false,
|
||||||
|
},
|
||||||
|
'Export schedule loaded'
|
||||||
|
);
|
||||||
|
|
||||||
if(exportSchedule.sched && this.exportingStart()) {
|
if(exportSchedule.sched && this.exportingStart()) {
|
||||||
this.exportTimer = later.setInterval( () => {
|
this.exportTimer = later.setInterval( () => {
|
||||||
|
|
||||||
|
@ -1076,7 +1119,16 @@ FTNMessageScanTossModule.prototype.startup = function(cb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const importSchedule = this.parseScheduleString(this.moduleConfig.schedule.import);
|
const importSchedule = this.parseScheduleString(this.moduleConfig.schedule.import);
|
||||||
if(importSchedule) {
|
if(importSchedule) {
|
||||||
|
Log.debug(
|
||||||
|
{
|
||||||
|
schedule : this.moduleConfig.schedule.import,
|
||||||
|
schedOK : -1 === importSchedule.sched.error,
|
||||||
|
watchFile : _.isString(importSchedule.watchFile) ? importSchedule.watchFile : 'None',
|
||||||
|
},
|
||||||
|
'Import schedule loaded'
|
||||||
|
);
|
||||||
|
|
||||||
if(importSchedule.sched) {
|
if(importSchedule.sched) {
|
||||||
this.importTimer = later.setInterval( () => {
|
this.importTimer = later.setInterval( () => {
|
||||||
tryImportNow('Performing scheduled message import/toss...');
|
tryImportNow('Performing scheduled message import/toss...');
|
||||||
|
@ -1150,22 +1202,6 @@ FTNMessageScanTossModule.prototype.performExport = function(cb) {
|
||||||
return cb(new Error('Missing or invalid configuration'));
|
return cb(new Error('Missing or invalid configuration'));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Select all messages that have a message_id > our last scan ID.
|
|
||||||
// Additionally exclude messages that have a ftn_attr_flags FtnProperty meta
|
|
||||||
// as those came via import!
|
|
||||||
//
|
|
||||||
/*
|
|
||||||
const getNewUuidsSql =
|
|
||||||
`SELECT message_id, message_uuid
|
|
||||||
FROM message m
|
|
||||||
WHERE area_tag = ? AND message_id > ? AND
|
|
||||||
(SELECT COUNT(message_id)
|
|
||||||
FROM message_meta
|
|
||||||
WHERE message_id = m.message_id AND meta_category = 'FtnProperty' AND meta_name = 'ftn_attr_flags') = 0
|
|
||||||
ORDER BY message_id;`;
|
|
||||||
*/
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Select all messages with a |message_id| > |lastScanId|.
|
// Select all messages with a |message_id| > |lastScanId|.
|
||||||
// Additionally exclude messages with the System state_flags0 which will be present for
|
// Additionally exclude messages with the System state_flags0 which will be present for
|
||||||
|
@ -1182,7 +1218,7 @@ FTNMessageScanTossModule.prototype.performExport = function(cb) {
|
||||||
WHERE message_id = m.message_id AND meta_category = 'System' AND meta_name = 'state_flags0') = 0
|
WHERE message_id = m.message_id AND meta_category = 'System' AND meta_name = 'state_flags0') = 0
|
||||||
ORDER BY message_id;`;
|
ORDER BY message_id;`;
|
||||||
|
|
||||||
var self = this;
|
let self = this;
|
||||||
|
|
||||||
async.each(Object.keys(Config.messageNetworks.ftn.areas), (areaTag, nextArea) => {
|
async.each(Object.keys(Config.messageNetworks.ftn.areas), (areaTag, nextArea) => {
|
||||||
const areaConfig = Config.messageNetworks.ftn.areas[areaTag];
|
const areaConfig = Config.messageNetworks.ftn.areas[areaTag];
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
## Configuration
|
# Configuration
|
||||||
Configuration files in ENiGMA½ are simple UTF-8 encoded [HJSON](http://hjson.org/) files. HJSON is just like JSON but simplified and much more resilient to human error.
|
Configuration files in ENiGMA½ are simple UTF-8 encoded [HJSON](http://hjson.org/) files. HJSON is just like JSON but simplified and much more resilient to human error.
|
||||||
|
|
||||||
### System Configuraiton
|
## System Configuraiton
|
||||||
The main system configuration file, `config.hjson` both overrides defaults and provides additional configuration such as message areas. The default path is `~/.config/enigma-bbs/config.hjson` though you can override this with the `--config` parameter when invoking `main.js`. Values found in core/config.js may be overridden by simply providing the object members you wish replace.
|
The main system configuration file, `config.hjson` both overrides defaults and provides additional configuration such as message areas. The default path is `~/.config/enigma-bbs/config.hjson` though you can override this with the `--config` parameter when invoking `main.js`. Values found in core/config.js may be overridden by simply providing the object members you wish replace.
|
||||||
|
|
||||||
**Windows note**: **~** resolves to *C:\Users\YOURLOGINNAME\* on modern installations, e.g. *C:\Users\NuSkooler\\.config\enigma-bbs\config.hjson*
|
**Windows note**: **~** resolves to *C:\Users\YOURLOGINNAME\* on modern installations, e.g. *C:\Users\NuSkooler\\.config\enigma-bbs\config.hjson*
|
||||||
|
|
||||||
#### Example: System Name
|
### Example: System Name
|
||||||
`core/config.js` provides the default system name as follows:
|
`core/config.js` provides the default system name as follows:
|
||||||
```javascript
|
```javascript
|
||||||
general : {
|
general : {
|
||||||
|
@ -21,8 +21,34 @@ general: {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### A Sample Configuration
|
### Specific Areas of Interest
|
||||||
Below is a **sample** `config.hjson` illustrating various (but not all!) elements that can be configured / tweaked.
|
|
||||||
|
#### Archivers
|
||||||
|
External archivers can be configured for various tasks such as EchoMail bundle handling.
|
||||||
|
|
||||||
|
TODO: Document further inc. Members & defaults
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
|
||||||
|
```hjson
|
||||||
|
archivers: {'
|
||||||
|
zip: {
|
||||||
|
// byte signature in HEX of ZIP archives
|
||||||
|
sig: "504b0304"
|
||||||
|
// offset of sig
|
||||||
|
offset: 0
|
||||||
|
compressCmd: "7za"
|
||||||
|
compressArgs: [ "a", "-tzip", "{archivePath}", "{fileList}" ]
|
||||||
|
decompressCmd: "7za"
|
||||||
|
decompressArgs: [ "e", "-o{extractPath}", "{archivePath}" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### A Sample Configuration
|
||||||
|
Below is a **sample** `config.hjson` illustrating various (but certainly not all!) elements that can be configured / tweaked.
|
||||||
|
|
||||||
|
**This is for illustration purposes! Do not cut & paste this configuration!**
|
||||||
|
|
||||||
|
|
||||||
```hjson
|
```hjson
|
||||||
|
@ -106,5 +132,5 @@ Below is a **sample** `config.hjson` illustrating various (but not all!) element
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Menus
|
## Menus
|
||||||
TODO: Documentation on menu.hjson, etc.
|
TODO: Documentation on menu.hjson, etc.
|
|
@ -35,7 +35,7 @@ npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
## Generate a SSH Private Key
|
## Generate a SSH Private Key
|
||||||
To utilize the SSH server, a SSH Private Key will need generated. This step can be skipped if desired by disabling the SSH server in `config.hjson`.
|
To utilize the SSH server, a SSH Private Key will need generated. This step can be skipped if you do not wish to enable SSH access.
|
||||||
```bash
|
```bash
|
||||||
openssl genrsa -des3 -out ./misc/ssh_private_key.pem 2048
|
openssl genrsa -des3 -out ./misc/ssh_private_key.pem 2048
|
||||||
```
|
```
|
||||||
|
@ -44,30 +44,33 @@ openssl genrsa -des3 -out ./misc/ssh_private_key.pem 2048
|
||||||
The main system configuration is handled via `~/.config/enigma-bbs/config.hjson`. This is a [HJSON](http://hjson.org/) file (compiliant JSON is also OK). See [Configuration](config.md) for more information.
|
The main system configuration is handled via `~/.config/enigma-bbs/config.hjson`. This is a [HJSON](http://hjson.org/) file (compiliant JSON is also OK). See [Configuration](config.md) for more information.
|
||||||
|
|
||||||
```hjson
|
```hjson
|
||||||
general: {
|
{
|
||||||
boardName: Super Awesome BBS
|
general: {
|
||||||
}
|
boardName: Super Awesome BBS
|
||||||
|
}
|
||||||
|
|
||||||
servers: {
|
servers: {
|
||||||
ssh: {
|
ssh: {
|
||||||
privateKeyPass: YOUR_PK_PASS
|
privateKeyPass: YOUR_PK_PASS
|
||||||
enabled: true /* set to false to disable the SSH server */
|
enabled: true /* set to false to disable the SSH server */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
messageConferences: {
|
messageConferences: {
|
||||||
local_general: {
|
local_general: {
|
||||||
name: Local
|
name: Local
|
||||||
desc: Local Discussions
|
desc: Local Discussions
|
||||||
default: true
|
default: true
|
||||||
|
|
||||||
areas: {
|
areas: {
|
||||||
local_music: {
|
local_music: {
|
||||||
name: Music Discussion
|
name: Music Discussion
|
||||||
desc: Music, bands, etc.
|
desc: Music, bands, etc.
|
||||||
default: true
|
default: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
# Message Networks
|
# Message Networks
|
||||||
Message networks are configured in `messageNetworks` section of `config.hjson`. Each network type has it's own sub section such as `ftn` for FidoNet Technology Network (FTN) style networks. Message Networks tie directly with [Message Areas](msg_conf_area.md) that are also defined in `config.hjson`.
|
Message networks are configured in `messageNetworks` section of `config.hjson`. Each network type has it's own sub section such as `ftn` for FidoNet Technology Network (FTN) style networks. Message Networks tie directly with [Message Areas](msg_conf_area.md) that are also defined in `config.hjson`.
|
||||||
|
|
||||||
|
**Members**:
|
||||||
|
* `ftn`: Configure FTN networks (described below)
|
||||||
|
* `originLine` (optional): Overrwrite the default origin line for networks that support it. For example: `originLine: Xibalba - xibalba.l33t.codes:44510`
|
||||||
|
|
||||||
## FidoNet Technology Network (FTN)
|
## FidoNet Technology Network (FTN)
|
||||||
FTN networks are configured under the `messageNetworks::ftn` section of `config.hjson`.
|
FTN networks are configured under the `messageNetworks::ftn` section of `config.hjson`.
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
/* jslint node: true */
|
/* jslint node: true */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var MenuModule = require('../core/menu_module.js').MenuModule;
|
let MenuModule = require('../core/menu_module.js').MenuModule;
|
||||||
var DropFile = require('../core/dropfile.js').DropFile;
|
let DropFile = require('../core/dropfile.js').DropFile;
|
||||||
var door = require('../core/door.js');
|
let door = require('../core/door.js');
|
||||||
var theme = require('../core/theme.js');
|
let theme = require('../core/theme.js');
|
||||||
var ansi = require('../core/ansi_term.js');
|
let ansi = require('../core/ansi_term.js');
|
||||||
|
|
||||||
var async = require('async');
|
let async = require('async');
|
||||||
var assert = require('assert');
|
let assert = require('assert');
|
||||||
var mkdirp = require('mkdirp');
|
let paths = require('path');
|
||||||
var paths = require('path');
|
let _ = require('lodash');
|
||||||
var _ = require('lodash');
|
let net = require('net');
|
||||||
var net = require('net');
|
let mkdirs = require('fs-extra').mkdirs;
|
||||||
|
|
||||||
// :TODO: This should really be a system module... needs a little work to allow for such
|
// :TODO: This should really be a system module... needs a little work to allow for such
|
||||||
|
|
||||||
exports.getModule = AbracadabraModule;
|
exports.getModule = AbracadabraModule;
|
||||||
|
|
||||||
var activeDoorNodeInstances = {};
|
let activeDoorNodeInstances = {};
|
||||||
|
|
||||||
var doorInstances = {}; // name -> { count : <instCount>, { <nodeNum> : <inst> } }
|
let doorInstances = {}; // name -> { count : <instCount>, { <nodeNum> : <inst> } }
|
||||||
|
|
||||||
exports.moduleInfo = {
|
exports.moduleInfo = {
|
||||||
name : 'Abracadabra',
|
name : 'Abracadabra',
|
||||||
|
@ -66,7 +66,7 @@ exports.moduleInfo = {
|
||||||
function AbracadabraModule(options) {
|
function AbracadabraModule(options) {
|
||||||
MenuModule.call(this, options);
|
MenuModule.call(this, options);
|
||||||
|
|
||||||
var self = this;
|
let self = this;
|
||||||
|
|
||||||
this.config = options.menuConfig.config;
|
this.config = options.menuConfig.config;
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ function AbracadabraModule(options) {
|
||||||
self.dropFile = new DropFile(self.client, self.config.dropFileType);
|
self.dropFile = new DropFile(self.client, self.config.dropFileType);
|
||||||
var fullPath = self.dropFile.fullPath;
|
var fullPath = self.dropFile.fullPath;
|
||||||
|
|
||||||
mkdirp(paths.dirname(fullPath), function dirCreated(err) {
|
mkdirs(paths.dirname(fullPath), function dirCreated(err) {
|
||||||
if(err) {
|
if(err) {
|
||||||
callback(err);
|
callback(err);
|
||||||
} else {
|
} else {
|
||||||
|
@ -153,7 +153,7 @@ function AbracadabraModule(options) {
|
||||||
|
|
||||||
this.runDoor = function() {
|
this.runDoor = function() {
|
||||||
|
|
||||||
var exeInfo = {
|
const exeInfo = {
|
||||||
cmd : self.config.cmd,
|
cmd : self.config.cmd,
|
||||||
args : self.config.args,
|
args : self.config.args,
|
||||||
io : self.config.io || 'stdio',
|
io : self.config.io || 'stdio',
|
||||||
|
@ -163,9 +163,9 @@ function AbracadabraModule(options) {
|
||||||
//inhSocket : self.client.output._handle.fd,
|
//inhSocket : self.client.output._handle.fd,
|
||||||
};
|
};
|
||||||
|
|
||||||
var doorInstance = new door.Door(self.client, exeInfo);
|
const doorInstance = new door.Door(self.client, exeInfo);
|
||||||
|
|
||||||
doorInstance.on('finished', function doorFinished() {
|
doorInstance.on('finished', () => {
|
||||||
self.prevMenu();
|
self.prevMenu();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -23,14 +23,14 @@
|
||||||
"later": "1.2.0",
|
"later": "1.2.0",
|
||||||
"lodash": "^3.10.1",
|
"lodash": "^3.10.1",
|
||||||
"minimist": "1.2.x",
|
"minimist": "1.2.x",
|
||||||
"mkdirp": "0.5.x",
|
|
||||||
"moment": "^2.11.0",
|
"moment": "^2.11.0",
|
||||||
"node-uuid": "^1.4.7",
|
"node-uuid": "^1.4.7",
|
||||||
"ptyw.js": "^0.3.7",
|
"ptyw.js": "^0.3.7",
|
||||||
"sqlite3": "^3.1.1",
|
"sqlite3": "^3.1.1",
|
||||||
"ssh2": "^0.4.13",
|
"ssh2": "^0.4.13",
|
||||||
"string-format": "davidchambers/string-format#mini-language",
|
"string-format": "davidchambers/string-format#mini-language",
|
||||||
"temp": "^0.8.3"
|
"temp": "^0.8.3",
|
||||||
|
"fs-extra" : "0.26.x"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.12.2"
|
"node": ">=0.12.2"
|
||||||
|
|
Loading…
Reference in New Issue