/* SRD Website ```````````````````````````````````````````````````````````````````````````````` This is a webapp for serving an RPG SRD in a publicly available format constructed from a collection of md and configuration files in a git repository located at `srd`. */ /* ==== REQUIRES ============================================================ */ const express = require('express') const doT = require('dot') const path = require('path') const fs = require('fs') /* ==== CONFIGURATION ======================================================= */ const exp = express() const app = { config: { srd: 'srd', plugins: {}, port: 7331, }, live: { dictionary: {}, conf: {}, menu: '', }, express: exp, dot: null, } const pub = __dirname + '/public' const views = __dirname + '/views' const routes = __dirname + '/routes' app.dot = doT.process({'path': views}) try { app.config = {...app.config, ...require(__dirname + '/config.js')} } catch(err) { if (err.code === 'MODULE_NOT_FOUND') { console.error('missing config') } } exp.use(express.static(pub)) exp.use(express.static(path.join(__dirname, app.config.srd))) exp.engine('dot', (template, options, cb) => { return cb(null, app.dot[path.parse(template).name](options)) }) exp.set('views', views) exp.set('view engine', 'dot') /* ==== PLUGINS ============================================================= */ const plugins = [] try { fs.readdirSync('plugins').forEach(f => { let plugin_path = path.resolve('plugins', f) if (fs.lstatSync(plugin_path).isDirectory()) { console.log('plugin require:', f) try { let plugin = { defaults: null, config: {}, log: (...args) => { console.log.apply(console, [f+':', ...args]) }, error: (...args) => { console.error.apply(console, [f+':', ...args]) }, module: require(plugin_path), } if (app.config.plugins[f]) { plugin.config = app.config.plugins[f] } plugin.defaults = o => { plugin.config = {...o, ...plugin.config} } console.log('...ok') plugins.push(plugin) } catch(err) { if (err.code === 'MODULE_NOT_FOUND') { console.error('plugin', plugin_path, 'is not a valid module') } else { console.error('...fail: ', err) } } } }) if (plugins.length === 0) { console.warn('no plugins found'); } else { // Sort our plugins according to desired priorities. Higher numbers plugins.sort((first, second) => { let first_priority = 0 let second_priority = 0 if (first.config.priority !== undefined) { first_priority = first.config.priority } else if (first.module === Object(first.module)) { if (first.module.priority !== undefined) { first_priority = first.module.priority } } if (second.config.priority !== undefined) { second_priority = second.config.priority } else if (second.module === Object(second.module)) { if (second.module.priority !== undefined) { second_priority = second.module.priority } } if (first_priority > second_priority) { return -1 } else if (first_priority < second_priority) { return 1 } return 0 }) // Call any needed preloads. for (let plugin of plugins) { // Call preload if the module is an object. if (plugin.module === Object(plugin.module)) { if (plugin.module.preload) { console.log('plugin preload:', f) try { plugin.module.preload(plugin, app) console.log('...ok') } catch(err) { console.error('...fail: ', err) } } } } } } catch(err) { if (err.code === 'ENOENT') { console.warn('no plugins directory') } else { console.error('plugins', err) } } /* ==== CMDLINE ============================================================= */ const port = app.config.port process.argv.forEach((val, index, array) => { let parts = val.split('=') let key = '' let value = '' if (parts[0].substr(0, 2) == '--') { key = parts[0].substr(2) value = parts[1] } if (key == 'port') { if (value != '') { port = Number(value) } } }) /* ==== RUN ================================================================= */ const server = exp.listen(port, async () => { const host = server.address().address const port = server.address().port for (let plugin of plugins) { try { if (plugin.module instanceof Function) { await plugin.module(plugin, app) } else if (plugin.module === Object(plugin.module)) { if (plugin.module.load) { await plugin.module.load(plugin, app) } } } catch(err) { console.error('plugin', err) } } console.log('running on', port) }) process.on('SIGINT', () => { process.exit() }) process.on('exit', () => { fs.writeFileSync(path.join(__dirname + '/config.js'), 'module.exports = ' + JSON.stringify(app.config, null, '\t')) })