UNPKG

newswriter

Version:

NewsWriter is a generic tool for maintaining news and announcements on a website news page. Details are held in an SQLite database, from which the tool generates the index page (typically the top page of the target site), individual pages for events and a

359 lines (343 loc) 12.6 kB
(function () { var optsClass = function (config) { this.config = config; } optsClass.prototype.getOpts = function () { var argparse = require('argparse') var ArgumentParser = argparse.ArgumentParser; var fs = require('fs'); var optparse = new ArgumentParser({ version: '0.0.1', addHelp:true, description: 'GSL Frontpage, a front-end for the English landing page of the Graduate School of Law, Nagoya University' }); optparse.addArgument( [ '-S', '--output-style' ], { help: 'Style to use for output' } ); optparse.addArgument( [ '-L', '--default-language' ], { help: 'Default language for user interface ("en" or "ja", defaults to "en")' } ); optparse.addArgument( [ '-O', '--organization-name' ], { help: 'Organization name for Atom feeds' } ); optparse.addArgument( [ '-o', '--organization-nickname' ], { help: 'Short form of organization name, for UI display' } ); optparse.addArgument( [ '-M', '--admin-email' ], { help: 'Admin email for Atom feeds' } ); optparse.addArgument( [ '-C', '--copyright-notice' ], { help: 'Copyright notice for Atom feeds' } ); optparse.addArgument( [ '-H', '--newswriter-hostname' ], { help: 'Host name for external access' } ); optparse.addArgument( [ '-p', '--newswriter-port' ], { help: 'Port on which to listen for local connections' } ); optparse.addArgument( [ '-F', '--newswriter-top-relative' ], { help: 'Relative path to NewsWriter (default: "newswriter")' } ); optparse.addArgument( [ '-W', '--target-hostname' ], { help: 'Hostname of server that will host the generated web pages' } ); optparse.addArgument( [ '-f', '--target-top-relative' ], { help: 'Relative URL to top of target server' } ); optparse.addArgument( [ '-i', '--target-announcements-relative' ], { help: 'Relative URL to announcements on target server' } ); optparse.addArgument( [ '-s', '--target-events-relative' ], { help: 'Relative URL to events directory on target server' } ); optparse.addArgument( [ '-t', '--fs-top-page-file' ], { help: 'Filesystem path to top page on target server' } ); optparse.addArgument( [ '-T', '--fs-top-feed-file' ], { help: 'Filesystem path to top (consolidated) feed object on target server' } ); optparse.addArgument( [ '-c', '--fs-calendar-file' ], { help: 'Filesystem path to consolidated calendar on target server' } ); optparse.addArgument( [ '-n', '--fs-announcement-feed-file' ], { help: 'Filesystem path to announcements feed on target server' } ); optparse.addArgument( [ '-e', '--fs-event-feed-file' ], { help: 'Filesystem path to events feed on target server' } ); optparse.addArgument( [ '-N', '--fs-announcements-dir' ], { help: 'Explicit path to announcements directory on target server' } ); optparse.addArgument( [ '-E', '--fs-events-dir' ], { help: 'Filesystem path to events directory on target server' } ); optparse.addArgument( [ '-w', '--rsync-binary' ], { help: 'Absolute path to rsync binary on NewsWriter server' } ); optparse.addArgument( [ '-x', '--ssh-binary' ], { help: 'Absolute path to ssh binary on NewsWriter server' } ); optparse.addArgument( [ '-y', '--account-name' ], { help: 'Name of account on target server for ssh access' } ); optparse.addArgument( [ '-z', '--sshpass-binary' ], { help: 'Absolute path to sshpass binary on NewsWriter server' } ); optparse.addArgument( [ '-Z', '--fs-local-dir' ], { help: 'Path to published files on local system. Conflicts with options -w through -z.' } ); var args = optparse.parseArgs(); if (args.newswriter_port) { console.log("Reading config from newswriter-" + args.newswriter_port + ".cfg"); try { // Layer instance config over default system values var newconfig = JSON.parse(fs.readFileSync('newswriter-' + args.newswriter_port + '.cfg')); for (var key in newconfig) { this.config[key] = newconfig[key]; } } catch (err) { console.log("Warning: Error reading config file: "+err); //process.exit(); } } var saveConfig = false; for (var key in args) { if (['isset','set','unset','get'].indexOf(key) > -1) continue; if (args[key] !== null && this.config[key] !== args[key]) { saveConfig = true; if (!args[key]) { this.config[key] = null; } else { this.config[key] = args[key]; } } } // Put all opt error handling here var rsyncOpts = { 'rsync_binary':{ req:[], conflict:[] }, 'ssh_binary':{ req:['rsync_binary','account_name'], conflict:['fs_local_dir'] }, 'sshpass_binary':{ req:['rsync_binary','ssh_binary','account_name'], conflict:['fs_local_dir'] }, 'account_name':{ req:['rsync_binary','ssh_binary'], conflict:['fs_local_dir'] }, 'fs_local_dir':{ req:['rsync_binary'], conflict:['ssh_binary','sshpass_binary','account_name'] } }; var configOops = []; for (var key in this.config) { if (rsyncOpts[key]) { var reqs = rsyncOpts[key].req; var conflicts = rsyncOpts[key].conflict; for (var i=0,ilen=reqs.length;i<ilen;i+=1) { var req = reqs[i]; if (this.config[key] && !this.config[req]) { console.log(" ERROR: option " + key + " requires " + req); return false; } } for (var i=0,ilen=conflicts.length;i<ilen;i+=1) { var conflict = conflicts[i]; if (this.config[key] && this.config[conflict]) { console.log(" ERROR: cannot use " + conflict + " with option " + key); return false; } } } else { if (null === this.config[key]) { configOops.push(key); } } } if (configOops.length) { optparse.printHelp(); for (var i=0,ilen=configOops.length;i<ilen;i+=1) { console.log(" ERROR: must set option "+configOops[i]); } return false; } if (saveConfig) { var configJson = JSON.stringify(this.config,null,2); fs.writeFileSync('newswriter-' + this.config.newswriter_port + '.cfg', configJson); console.log("Wrote config parameters to newswriter-" + this.config.newswriter_port + '.cfg'); console.log("NewsWriter can now be run with the single option: -p " + this.config.newswriter_port); } // Clean up some path values function stripSlashes (val) { if ("string" !== typeof val) return val; while (val && val.slice(0,1) === '/') { val = val.slice(1); } while (val && val.slice(-1) === '/') { val = val.slice(0,-1); } return val; } var relatives = ['newswriter_top_relative']; for (var i=0,ilen=relatives.length;i<ilen;i+=1) { this.config[relatives[i]] = stripSlashes(this.config[relatives[i]]); } var UrlEngine = function (config) { this.config = config; this.testInstance = true; var port = ':' + config.newswriter_port; if (config.newswriter_hostname.match(/.*\..*/) && config.newswriter_hostname !== '127.0.0.1') { this.testInstance = false; port = ''; } if ('string' === typeof arg) { this.hostname_and_port + '/' + config.newswriter_top_relative + '/' + arg; } else { var stub = null; if (this.testInstance) { stub = ''; } else { stub = config.newswriter_top_relative + '/admin.html'; } this.hostname_and_port = config.newswriter_hostname + port; } }; UrlEngine.prototype.init = function (id,key) { this.id = id; this.key = key; if (this.testInstance) { this.stub = ''; this.adminstuff = 'admin=' + this.key + '&'; } else { this.stub = this.config.newswriter_top_relative + '/admin.html'; this.adminstuff = ''; } }; UrlEngine.prototype.getQueryString = function (obj) { var ret = []; for (var key in obj) { ret.push(key + '=' + obj[key]) } return ret.join('&'); }; UrlEngine.prototype.xmlEscape = function (str) { return str.replace(/&/g,'&amp;'); }; UrlEngine.prototype.page = function (id,key,xmlEscape) { if (!this.id || !this.key) throw "getHostURL() run before init() in UrlEngine."; var queryString = this.adminstuff + this.getQueryString({id:id,key:key}); if (xmlEscape) { queryString = this.xmlEscape(queryString); } return 'http://' + this.hostname_and_port + '/' + this.stub + '?' + queryString; }; UrlEngine.prototype.feed = function (id,key,xmlEscape) { if (!this.id || !this.key) throw "getHostURL() run before init() in UrlEngine."; var queryString = this.getQueryString({page:'pending',id:id,key:key}); if (xmlEscape) { queryString = this.xmlEscape(queryString); } return 'http://' + this.hostname_and_port + '/' + this.stub + '?' + queryString; }; UrlEngine.prototype.hostname = function () { return this.hostname_and_port; }; UrlEngine.prototype.hostpath = function () { var ret; if (this.testInstance) { ret = 'http://' + this.hostname_and_port; } else { ret = 'http://' + this.hostname_and_port + '/' + this.config.newswriter_top_relative; } return ret; }; UrlEngine.prototype.target = function () { return 'http://' + this.config.target_hostname; }; this.config.urlEngine = new UrlEngine(this.config); return this.config; } exports.optsClass = optsClass; })();