From 36155c0dc0ad9f85b0089c3fb20e3bb37f0266da Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Wed, 27 Jun 2018 14:08:37 -0400 Subject: [PATCH 01/16] Use Mustache template for email --- index.js | 20 +++++++++++++------- package-lock.json | 5 +++++ package.json | 7 ++++++- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index 8ebda31..7607028 100644 --- a/index.js +++ b/index.js @@ -6,6 +6,7 @@ var email = require('emailjs'); var fs = require('fs'); var path = require('path'); var program = require('commander'); +const Mustache = require('mustache'); var scrawl = require('./www/scrawl'); var Twitter = require('twitter'); var wp = require('wordpress'); @@ -50,6 +51,17 @@ gDate = gDate.match(/([0-9]{4}-[0-9]{2}-[0-9]{2})/)[1]; scrawl.group = 'JSON-LD CG Telecon'; scrawl.people = JSON.parse(peopleJson); +const EMAIL_BODY = `Thanks to {{scribe}} for scribing this week! The minutes +for this week's JSON-LD CG telecon are now available: + +https://json-ld.github.io/minutes/{{gDate}}/ + +Full text of the discussion follows for W3C archival purposes. +Audio from the meeting is available as well (link provided below). + +---------------------------------------------------------------- +{{{content}}}`; + /************************* Utility Functions *********************************/ function postToWordpress(username, password, content, callback) { var client = wp.createClient({ @@ -286,13 +298,7 @@ async.waterfall([ function(callback) { var content = scrawl.generateMinutes(gLogData, 'text', gDate, haveAudio); var scribe = content.match(/Scribe:\n\s(.*)\n/g)[0] .replace(/\n/g, '').replace('Scribe: ', ''); - content = 'Thanks to ' + scribe + ' for scribing this week! The minutes\n' + - 'for this week\'s JSON-LD CG telecon are now available:\n\n' + - 'https://json-ld.github.io/minutes/'+ gDate + '/\n\n' + - 'Full text of the discussion follows for W3C archival purposes.\n' + - 'Audio from the meeting is available as well (link provided below).\n\n' + - '----------------------------------------------------------------\n' + - content; + content = Mustache.render(EMAIL_BODY, {scribe, gDate, content}); if(process.env.SCRAWL_EMAIL_USERNAME && process.env.SCRAWL_EMAIL_PASSWORD && process.env.SCRAWL_EMAIL_SERVER) { diff --git a/package-lock.json b/package-lock.json index 978465d..c285eb2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -248,6 +248,11 @@ "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.4.tgz", "integrity": "sha512-1xFTAknSLfc47DIxHDUbnJWC+UwgWxATmymaxIPQpmMh7LBm7ZbwVEsuushqwL2GYZU0jie4xO+TK44hJPjNSQ==" }, + "mustache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.0.tgz", + "integrity": "sha1-QCj3d4sXcIpImTCm5SrDvKDaQdA=" + }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", diff --git a/package.json b/package.json index 78d01a2..a21aec6 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,11 @@ "name": "scrawl", "version": "0.4.0", "description": "IRC log processing tool for scribes to assist in creating minutes for W3C group.", - "keywords": ["IRC", "W3C", "minutes"], + "keywords": [ + "IRC", + "W3C", + "minutes" + ], "repository": { "type": "git", "url": "git@github.com:json-ld/scrawl.js.git" @@ -21,6 +25,7 @@ "mailparser": "~0.2.26", "mime": "^2.3.1", "moment": "~2.19.3", + "mustache": "^2.3.0", "prompt": "^1.0.0", "twitter": "~0.2.5", "underscore": "~1.5.0", From b81d57c0fa04e36c5e6083b423c288964bae860e Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Wed, 27 Jun 2018 14:12:38 -0400 Subject: [PATCH 02/16] Move more email config stuff to top Use Mustache for email subjects --- index.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 7607028..682fbe0 100644 --- a/index.js +++ b/index.js @@ -51,6 +51,11 @@ gDate = gDate.match(/([0-9]{4}-[0-9]{2}-[0-9]{2})/)[1]; scrawl.group = 'JSON-LD CG Telecon'; scrawl.people = JSON.parse(peopleJson); +const EMAIL_TO = 'JSON-LD CG '; +const EMAIL_FROM = 'gregg@greggkellogg.net'; +// Mustache template -- vars: gDate +const EMAIL_SUBJECT = '[MINUTES] W3C JSON-LD CG Call - {{gDate}} 12pm ET'; +// Mustache template -- vars: scribe, gDate, content const EMAIL_BODY = `Thanks to {{scribe}} for scribing this week! The minutes for this week's JSON-LD CG telecon are now available: @@ -126,10 +131,10 @@ function sendEmail(username, password, hostname, content, callback) { // send the message server.send({ text: content, - from: 'gregg@greggkellogg.net', + from: EMAIL_FROM, //from: username + '@' + hostname, - to: 'JSON-LD CG ', - subject: '[MINUTES] W3C JSON-LD CG Call - ' + gDate + ' 12pm ET' + to: EMAIL_TO, + subject: Mustache.render(EMAIL_SUBJECT, {gDate}) }, function(err, message) { if(err) { console.log('scrawl:', err); From 24aaae383d233afe2339ceb6574d1778821636ae Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Wed, 27 Jun 2018 14:17:19 -0400 Subject: [PATCH 03/16] Use Mustache template for G+ content --- index.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 682fbe0..172b235 100644 --- a/index.js +++ b/index.js @@ -67,6 +67,18 @@ Audio from the meeting is available as well (link provided below). ---------------------------------------------------------------- {{{content}}}`; +const GPLUS_BODY = `*JSON-LD CG Meeting Summary for {{gDate}}* + +We discussed {{formattedItems}}. + +{{{content}}} + +Full transcript and audio logs are available here: + +https://json-ld.github.io/minutes/{{gDate}}/ + +#w3c #json-ld`; + /************************* Utility Functions *********************************/ function postToWordpress(username, password, content, callback) { var client = wp.createClient({ @@ -368,11 +380,7 @@ async.waterfall([ function(callback) { } // format in a way that is readable on G+ - content = '*JSON-LD CG Meeting Summary for ' + gDate + '*\n\n' + - 'We discussed ' + formattedItems + '.\n\n' + - content + '\nFull transcript and audio logs are available here:\n\n' + - 'https://json-ld.github.io/minutes/' + gDate + '/\n\n' + - '#w3c #json-ld'; + content = Mustache.render(GPLUS_BODY, {gDate, formattedItems, content}); console.log('scrawl: You will need to paste this to your G+ stream:\n'); console.log(content); From 55bb60dca333207b1bb75cab14f2d0a67e5c61a5 Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Wed, 27 Jun 2018 14:21:44 -0400 Subject: [PATCH 04/16] Use Mustache for tweet --- index.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 172b235..fd24175 100644 --- a/index.js +++ b/index.js @@ -79,6 +79,10 @@ https://json-ld.github.io/minutes/{{gDate}}/ #w3c #json-ld`; +const TWITTER_BODY = `JSON-LD CG discusses {{message}}: +https://json-ld.github.io/minutes/{{gDate}}/ #w3c #json-ld`; + + /************************* Utility Functions *********************************/ function postToWordpress(username, password, content, callback) { var client = wp.createClient({ @@ -423,9 +427,8 @@ async.waterfall([ function(callback) { } }, function(err, results) { // construct the tweet - var tweet = 'JSON-LD CG discusses ' + - results.message + ': https://json-ld.github.io/minutes/' + - gDate + '/ #w3c #json-ld'; + var tweet = Mustache.render(TWITTER_BODY, + {message: results.message, gDate}); // send the tweet twitter.updateStatus(tweet, function(data) { From 016455d975c8d99464eb52fc0f3ceeaed05eadae Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Wed, 27 Jun 2018 14:29:50 -0400 Subject: [PATCH 05/16] Add constants for configuring WordPress content --- index.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index fd24175..fdba93c 100644 --- a/index.js +++ b/index.js @@ -67,6 +67,7 @@ Audio from the meeting is available as well (link provided below). ---------------------------------------------------------------- {{{content}}}`; +// Mustache template - vars: gDate, formattedItems, content const GPLUS_BODY = `*JSON-LD CG Meeting Summary for {{gDate}}* We discussed {{formattedItems}}. @@ -79,9 +80,14 @@ https://json-ld.github.io/minutes/{{gDate}}/ #w3c #json-ld`; +// Mustache template - vars: message, gDate const TWITTER_BODY = `JSON-LD CG discusses {{message}}: https://json-ld.github.io/minutes/{{gDate}}/ #w3c #json-ld`; +// Mustache template - vars: gDate +const WORDPRESS_TITLE = 'JSON-LD CG Meeting Minutes for {{gDate}}'; +// Location of date-based minutes folders; MUST end in a forward slash +const MINUTES_BASE_URL = 'https://json-ld.github.io/minutes/' /************************* Utility Functions *********************************/ function postToWordpress(username, password, content, callback) { @@ -97,12 +103,12 @@ function postToWordpress(username, password, content, callback) { wpSummary = wpSummary.substring( wpSummary.indexOf('
'), wpSummary.indexOf('
') + 5); wpSummary = wpSummary.replace(/href=\"#/g, - 'href="https://json-ld.github.io/minutes/' + gDate + '/#'); + 'href="' + MINUTES_BASE_URL + gDate + '/#'); wpSummary = wpSummary.replace(/href=\"audio/g, - 'href="https://json-ld.github.io/minutes/' + gDate + '/audio'); + 'href="' + MINUTES_BASE_URL + gDate + '/audio'); wpSummary = wpSummary.replace(/
<\/div>/g, ''); wpSummary += '

Detailed minutes and recorded audio for this call are ' + - 'available in the archive.

'; // calculate the proper post date @@ -446,7 +452,7 @@ async.waterfall([ function(callback) { console.log('scrawl: Creating new blog post.'); } var content = { - post_title: 'JSON-LD CG Meeting Minutes for ' + gDate, + post_title: Mustache.render(WORDPRESS_TITLE, {gDate}), post_content: scrawl.generateMinutes(gLogData, 'html', gDate, haveAudio) }; @@ -460,7 +466,7 @@ async.waterfall([ function(callback) { prompt.get({ properties: { username: { - description: 'Enter the JSON-LD WordPress username', + description: 'Enter the WordPress username', pattern: /^.{4,}$/, message: 'The username must be at least 4 characters.', 'default': 'msporny' From 3185b2f5bc3fdd8942a91f184e76ec70810f9bfd Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Wed, 27 Jun 2018 14:30:52 -0400 Subject: [PATCH 06/16] Output EMAIL_TO value, not hard coded to addr --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index fdba93c..e220f5e 100644 --- a/index.js +++ b/index.js @@ -164,7 +164,7 @@ function sendEmail(username, password, hostname, content, callback) { } if(!program.quiet) { - console.log('scrawl: Sent minutes email to public-linked-json@w3.org'); + console.log(`scrawl: Sent minutes email to ${EMAIL_TO}`); } callback(); }); From b3a6538bfc83c7e5d6ffa8231727e66eb65615e5 Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Thu, 28 Jun 2018 10:04:31 -0400 Subject: [PATCH 07/16] Make base URL & chairs configurable Added `chairs: true` to people.json format --- index.js | 2 ++ people.json.example | 3 ++- www/scrawl.js | 15 +++++++++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index e220f5e..6c59ae7 100644 --- a/index.js +++ b/index.js @@ -89,6 +89,8 @@ const WORDPRESS_TITLE = 'JSON-LD CG Meeting Minutes for {{gDate}}'; // Location of date-based minutes folders; MUST end in a forward slash const MINUTES_BASE_URL = 'https://json-ld.github.io/minutes/' +scrawl.minutes_base_url = MINUTES_BASE_URL; + /************************* Utility Functions *********************************/ function postToWordpress(username, password, content, callback) { var client = wp.createClient({ diff --git a/people.json.example b/people.json.example index 9c4bd5d..decb28c 100644 --- a/people.json.example +++ b/people.json.example @@ -6,7 +6,8 @@ ], "homepage": "https://example.com/~person-nick" }, - "Other Person": { + "Chair Person": { + "chair": true, "homepage": "http://example.com/~other-person" } } diff --git a/www/scrawl.js b/www/scrawl.js index 3917b5b..08c306e 100644 --- a/www/scrawl.js +++ b/www/scrawl.js @@ -44,6 +44,11 @@ scrawl.updateCounter = 1; scrawl.updateCounterTimeout = null; + // TODO: make it clearer what's internal only and what's configurable + // ...these happen to be configurable... + scrawl.minutes_base_url = ''; + scrawl.chair = []; + scrawl.wordwrap = function(str, width, brk, cut ) { brk = brk || '\n'; @@ -737,7 +742,7 @@ rval += 'Present:\n ' + scrawl.wordwrap(peoplePresent, 65, '\n ') + '\n'; if(context.audio) { - rval += 'Audio:\n https://json-ld.github.io/minutes/' + + rval += 'Audio:\n ' + scrawl.minutes_base_url + time.getFullYear() + '-' + month + '-' + day + '/audio.ogg\n\n'; } else { @@ -757,11 +762,17 @@ var aliases = scrawl.generateAliases(); scrawl.counter = 0; + // TODO: expose this better? + // TODO: return objects so we can link things + var chair = Object.keys(scrawl.people).filter((key) => { + return 'chair' in scrawl.people[key] && scrawl.people[key].chair; + }); + // initialize the IRC log scanning context var context = { 'group': scrawl.group, - 'chair': ['Gregg Kellogg', 'Rob Sanderson'], + 'chair': chair, 'present': {}, 'scribe': [], 'topics': [], From 7f6a796a574ed6e0b86e9ad04080bad3b5df6d8b Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Thu, 28 Jun 2018 11:19:39 -0400 Subject: [PATCH 08/16] Begin setup of YAML config Where all the Mustaches and other configs will live --- index.js | 32 ++++++++++++++++++++++++++++---- package-lock.json | 27 +++++++++++++++++++++++++++ package.json | 1 + 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 6c59ae7..ddc9c9c 100644 --- a/index.js +++ b/index.js @@ -10,25 +10,49 @@ const Mustache = require('mustache'); var scrawl = require('./www/scrawl'); var Twitter = require('twitter'); var wp = require('wordpress'); +const yaml = require('js-yaml'); program .version('0.4.0') + // the setup switches + .option('-c, --config ', 'The YAML configuration file.') .option('-d, --directory ', 'The directory to process.') + // the do something switches .option('-m, --html', 'If set, write the minutes to an index.html file') .option('-w, --wordpress', 'If set, publish the minutes to the blog') .option('-e, --email', 'If set, publish the minutes to the mailing list') .option('-t, --twitter', 'If set, publish the minutes to Twitter') .option('-g, --google', 'If set, publish the minutes to G+') .option('-i, --index', 'Build meeting index') + // the tweak the cli switch .option('-q, --quiet', 'Don\'t print status information to the console') .parse(process.argv); +var base_dir = __dirname; +var config = {}; +if (program.config) { + try { + config = yaml.safeLoad(fs.readFileSync(program.config, 'utf8')); + // paths in the config file are relative to the config files location + base_dir = path.resolve(path.dirname(program.config)); + } catch (e) { + console.error(e.message); + } +} + if(!program.directory) { console.error('Error: You must specify a directory to process'); program.outputHelp(); process.exit(1); } +if (!program.html && !program.wordpress && !program.email && !program.twitter + && !program.google && !program.index) { + console.error('Error: Nothing to do...'); + program.outputHelp(); + process.exit(1); +} + // setup global variables const dstDir = path.resolve(path.join(program.directory)); const logFile = path.resolve(dstDir, 'irc.log'); @@ -37,11 +61,11 @@ const indexFile = path.resolve(dstDir, 'index.html'); const minutesDir = path.join(dstDir, '/..'); var htmlHeader = fs.readFileSync( - __dirname + '/www/_partials/header.html', {encoding: 'utf8'}); + path.join(base_dir, 'www/_partials/header.html'), {encoding: 'utf8'}); var htmlFooter = fs.readFileSync( - __dirname + '/www/_partials/footer.html', {encoding: 'utf8'}); + path.join(base_dir, 'www/_partials/footer.html'), {encoding: 'utf8'}); var peopleJson = fs.readFileSync( - __dirname + '/www/people.json', {encoding: 'utf8'}); + path.join(base_dir, 'www/people.json'), {encoding: 'utf8'}); var gLogData = ''; var haveAudio = false; var gDate = path.basename(dstDir); @@ -277,7 +301,7 @@ async.waterfall([ function(callback) { } const summaryIntro = fs.readFileSync( - __dirname + '/www/_partials/summary-intro.html', {encoding: 'utf8'}); + path.join(base_dir, 'www/_partials/summary-intro.html'), {encoding: 'utf8'}); // write out summary file var summaryHtml = htmlHeader + '
' + summaryIntro; diff --git a/package-lock.json b/package-lock.json index c285eb2..47006a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,14 @@ "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-0.3.2.tgz", "integrity": "sha1-WYc/Nej89sc2HBAjkmHXbhU0i7I=" }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, "async": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", @@ -111,6 +119,11 @@ "iconv-lite": "0.4.21" } }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + }, "eyes": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", @@ -180,6 +193,15 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "keygrip": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.2.tgz", @@ -336,6 +358,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", diff --git a/package.json b/package.json index a21aec6..5123656 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "commander": "~1.0.0", "emailjs": "~2.1.0", "html-entities": "~1.0.10", + "js-yaml": "^3.12.0", "mailparser": "~0.2.26", "mime": "^2.3.1", "moment": "~2.19.3", From b66e62069287a47a90d5d6cbc8615cee880fee48 Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Thu, 28 Jun 2018 11:32:04 -0400 Subject: [PATCH 09/16] Use config.partials --- index.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index ddc9c9c..f2788f6 100644 --- a/index.js +++ b/index.js @@ -60,10 +60,14 @@ const audioFile = path.resolve(dstDir, 'audio.ogg'); const indexFile = path.resolve(dstDir, 'index.html'); const minutesDir = path.join(dstDir, '/..'); +const partialsDir = ('partials' in config) + ? path.join(base_dir, config.partials) + : path.join(base_dir, 'www/_partials/'); + var htmlHeader = fs.readFileSync( - path.join(base_dir, 'www/_partials/header.html'), {encoding: 'utf8'}); + path.join(partialsDir, 'header.html'), {encoding: 'utf8'}); var htmlFooter = fs.readFileSync( - path.join(base_dir, 'www/_partials/footer.html'), {encoding: 'utf8'}); + path.join(partialsDir, 'footer.html'), {encoding: 'utf8'}); var peopleJson = fs.readFileSync( path.join(base_dir, 'www/people.json'), {encoding: 'utf8'}); var gLogData = ''; From 57bfbcb2bf3d09a537fe56ac0e3d34a81ac5ea1c Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Thu, 28 Jun 2018 11:44:14 -0400 Subject: [PATCH 10/16] Use config.people --- index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index f2788f6..3c80b82 100644 --- a/index.js +++ b/index.js @@ -63,13 +63,15 @@ const minutesDir = path.join(dstDir, '/..'); const partialsDir = ('partials' in config) ? path.join(base_dir, config.partials) : path.join(base_dir, 'www/_partials/'); +const peoplePath = ('people' in config) + ? path.join(base_dir, config.people) + : path.join(base_dir, 'www/people.json'); var htmlHeader = fs.readFileSync( path.join(partialsDir, 'header.html'), {encoding: 'utf8'}); var htmlFooter = fs.readFileSync( path.join(partialsDir, 'footer.html'), {encoding: 'utf8'}); -var peopleJson = fs.readFileSync( - path.join(base_dir, 'www/people.json'), {encoding: 'utf8'}); +var peopleJson = fs.readFileSync(peoplePath, {encoding: 'utf8'}); var gLogData = ''; var haveAudio = false; var gDate = path.basename(dstDir); From c8f547072629b08736893d9986c38322782e2703 Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Thu, 28 Jun 2018 12:09:05 -0400 Subject: [PATCH 11/16] Use config.email[to|from|subject|body] Mustache templates are used for `subject` and `body` --- index.js | 52 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/index.js b/index.js index 3c80b82..8f39170 100644 --- a/index.js +++ b/index.js @@ -78,25 +78,9 @@ var gDate = path.basename(dstDir); gDate = gDate.match(/([0-9]{4}-[0-9]{2}-[0-9]{2})/)[1]; // configure scrawl -scrawl.group = 'JSON-LD CG Telecon'; +scrawl.group = config.group || 'Telecon'; scrawl.people = JSON.parse(peopleJson); -const EMAIL_TO = 'JSON-LD CG '; -const EMAIL_FROM = 'gregg@greggkellogg.net'; -// Mustache template -- vars: gDate -const EMAIL_SUBJECT = '[MINUTES] W3C JSON-LD CG Call - {{gDate}} 12pm ET'; -// Mustache template -- vars: scribe, gDate, content -const EMAIL_BODY = `Thanks to {{scribe}} for scribing this week! The minutes -for this week's JSON-LD CG telecon are now available: - -https://json-ld.github.io/minutes/{{gDate}}/ - -Full text of the discussion follows for W3C archival purposes. -Audio from the meeting is available as well (link provided below). - ----------------------------------------------------------------- -{{{content}}}`; - // Mustache template - vars: gDate, formattedItems, content const GPLUS_BODY = `*JSON-LD CG Meeting Summary for {{gDate}}* @@ -353,11 +337,43 @@ async.waterfall([ function(callback) { console.log('scrawl: Sending new minutes email.'); } + if (!('email' in config)) { + callback('Error: Email configuration is missing'); + return; + } else if (!('from' in config.email) || !('to' in config.email)) { + callback('Error: You must supply a `to` and `from` config value'); + return; + } + + // see sendEmail() + // TODO: don't use global constants... + const EMAIL_TO = config.email.to; + const EMAIL_FROM = config.email.from; + + // Mustache template -- vars: gDate + // TODO: dates are always Eastern Time...maybe the world is round? + // TODO: also the time is still hard coded T_T + const EMAIL_SUBJECT = config.email.subject || '[MINUTES] {{gDate}} 12pm ET'; + // Mustache template -- vars: scribe, gDate, content, minutes_base_url, haveAudio + const EMAIL_BODY = config.email.body || `Thanks to {{scribe}} for scribing this week! The minutes +for this week's telecon are now available: + +{{{minutes_base_url}}}{{gDate}}/ + +Full text of the discussion follows for archival purposes. +{{#haveAudio}}Audio from the meeting is available as well (link provided below).{{/haveAudio}} + +---------------------------------------------------------------- +{{{content}}}`; + // generate the body of the email var content = scrawl.generateMinutes(gLogData, 'text', gDate, haveAudio); var scribe = content.match(/Scribe:\n\s(.*)\n/g)[0] .replace(/\n/g, '').replace('Scribe: ', ''); - content = Mustache.render(EMAIL_BODY, {scribe, gDate, content}); + content = Mustache.render(EMAIL_BODY, + {scribe, gDate, content, + minutes_base_url: scrawl.minutes_base_url, + haveAudio}); if(process.env.SCRAWL_EMAIL_USERNAME && process.env.SCRAWL_EMAIL_PASSWORD && process.env.SCRAWL_EMAIL_SERVER) { From 85b184c7847f98ceccf43b1d728aae7a5121f73a Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Thu, 28 Jun 2018 12:14:55 -0400 Subject: [PATCH 12/16] Use config.gplus.body --- index.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 8f39170..df19ec6 100644 --- a/index.js +++ b/index.js @@ -81,8 +81,10 @@ gDate = gDate.match(/([0-9]{4}-[0-9]{2}-[0-9]{2})/)[1]; scrawl.group = config.group || 'Telecon'; scrawl.people = JSON.parse(peopleJson); -// Mustache template - vars: gDate, formattedItems, content -const GPLUS_BODY = `*JSON-LD CG Meeting Summary for {{gDate}}* +// Mustache template - vars: gDate, formattedItems, content, minutes_base_url +const GPLUS_BODY = ('gplus' in config && 'body' in config.gplus) + ? config.gplus.body + : `*Meeting Summary for {{gDate}}* We discussed {{formattedItems}}. @@ -90,9 +92,8 @@ We discussed {{formattedItems}}. Full transcript and audio logs are available here: -https://json-ld.github.io/minutes/{{gDate}}/ - -#w3c #json-ld`; +{{{minutes_base_url}}}{{gDate}}/ +`; // Mustache template - vars: message, gDate const TWITTER_BODY = `JSON-LD CG discusses {{message}}: @@ -438,7 +439,8 @@ Full text of the discussion follows for archival purposes. } // format in a way that is readable on G+ - content = Mustache.render(GPLUS_BODY, {gDate, formattedItems, content}); + content = Mustache.render(GPLUS_BODY, {gDate, formattedItems, content, + minutes_base_url: scrawl.minutes_base_url}); console.log('scrawl: You will need to paste this to your G+ stream:\n'); console.log(content); From 41e30328d541dcf116b38321c9b311e3f5a1e6bb Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Thu, 28 Jun 2018 12:22:00 -0400 Subject: [PATCH 13/16] Use config.twitter.body --- index.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index df19ec6..b97e396 100644 --- a/index.js +++ b/index.js @@ -95,9 +95,11 @@ Full transcript and audio logs are available here: {{{minutes_base_url}}}{{gDate}}/ `; -// Mustache template - vars: message, gDate -const TWITTER_BODY = `JSON-LD CG discusses {{message}}: -https://json-ld.github.io/minutes/{{gDate}}/ #w3c #json-ld`; +// Mustache template - vars: group, message, gDate, minutes_base_url +const TWITTER_BODY = ('twitter' in config && 'body' in config.twitter) + ? config.twitter.body + : `{{group}} discusses {{message}}: +{{{minutes_base_url}}}{{gDate}}/`; // Mustache template - vars: gDate const WORDPRESS_TITLE = 'JSON-LD CG Meeting Minutes for {{gDate}}'; @@ -484,7 +486,9 @@ Full text of the discussion follows for archival purposes. }, function(err, results) { // construct the tweet var tweet = Mustache.render(TWITTER_BODY, - {message: results.message, gDate}); + {group: scrawl.group, + message: results.message, gDate, + minutes_base_url: scrawl.minutes_base_url}); // send the tweet twitter.updateStatus(tweet, function(data) { From 212eda7617fc7664db0ca4552df434cbec4aea17 Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Thu, 28 Jun 2018 12:24:28 -0400 Subject: [PATCH 14/16] Use config.wordpress.title --- index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index b97e396..b0f91a1 100644 --- a/index.js +++ b/index.js @@ -102,7 +102,9 @@ const TWITTER_BODY = ('twitter' in config && 'body' in config.twitter) {{{minutes_base_url}}}{{gDate}}/`; // Mustache template - vars: gDate -const WORDPRESS_TITLE = 'JSON-LD CG Meeting Minutes for {{gDate}}'; +const WORDPRESS_TITLE = ('wordpress' in config && 'title' in config.wordpress) + ? config.wordpress.title + : 'Meeting Minutes for {{gDate}}'; // Location of date-based minutes folders; MUST end in a forward slash const MINUTES_BASE_URL = 'https://json-ld.github.io/minutes/' From 1800e497a6a05473e09dd99be9b226fc6027e9ce Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Thu, 28 Jun 2018 12:38:58 -0400 Subject: [PATCH 15/16] Use config.minutes_base_url --- index.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index b0f91a1..36da2af 100644 --- a/index.js +++ b/index.js @@ -81,6 +81,14 @@ gDate = gDate.match(/([0-9]{4}-[0-9]{2}-[0-9]{2})/)[1]; scrawl.group = config.group || 'Telecon'; scrawl.people = JSON.parse(peopleJson); +// we can't make any URLs without this...so fail... +if (!('minutes_base_url' in config)) { + console.error('Error: The `minutes_base_url` was not set in the config'); + process.exit(1); +} +// Location of date-based minutes folders; MUST end in a forward slash +scrawl.minutes_base_url = config.minutes_base_url; + // Mustache template - vars: gDate, formattedItems, content, minutes_base_url const GPLUS_BODY = ('gplus' in config && 'body' in config.gplus) ? config.gplus.body @@ -105,10 +113,6 @@ const TWITTER_BODY = ('twitter' in config && 'body' in config.twitter) const WORDPRESS_TITLE = ('wordpress' in config && 'title' in config.wordpress) ? config.wordpress.title : 'Meeting Minutes for {{gDate}}'; -// Location of date-based minutes folders; MUST end in a forward slash -const MINUTES_BASE_URL = 'https://json-ld.github.io/minutes/' - -scrawl.minutes_base_url = MINUTES_BASE_URL; /************************* Utility Functions *********************************/ function postToWordpress(username, password, content, callback) { @@ -124,12 +128,12 @@ function postToWordpress(username, password, content, callback) { wpSummary = wpSummary.substring( wpSummary.indexOf('
'), wpSummary.indexOf('
') + 5); wpSummary = wpSummary.replace(/href=\"#/g, - 'href="' + MINUTES_BASE_URL + gDate + '/#'); + 'href="' + scrawl.minutes_base_url + gDate + '/#'); wpSummary = wpSummary.replace(/href=\"audio/g, - 'href="' + MINUTES_BASE_URL + gDate + '/audio'); + 'href="' + scrawl.minutes_base_url + gDate + '/audio'); wpSummary = wpSummary.replace(/
<\/div>/g, ''); wpSummary += '

Detailed minutes and recorded audio for this call are ' + - 'available in the archive.

'; // calculate the proper post date From 874c6f7e9873e711c75e3351eeac58ecbb41a5ba Mon Sep 17 00:00:00 2001 From: Benjamin Young Date: Thu, 28 Jun 2018 12:53:58 -0400 Subject: [PATCH 16/16] Update README; add config.yaml.example --- .gitignore | 1 + README.md | 32 +++++++++++++++++------------ config.yaml.example | 49 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 13 deletions(-) create mode 100644 config.yaml.example diff --git a/.gitignore b/.gitignore index a256f58..8c9ce13 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules/ +config.yaml people.json publish.sh diff --git a/README.md b/README.md index b45fd71..c0d56cf 100644 --- a/README.md +++ b/README.md @@ -28,20 +28,11 @@ Scrawl works on directories structured like: The output files will be added to the same directory for simpler hosting of all the things. -Now, we need to setup the nicknames of all the people in the group. -So, copy `people.json.example` to `www/people.json` and fill in names, -homepages, and nicknames as needed. +There are **two** important setup files: + - `config.yaml` (see `config.yaml.example`) + - `people.json` (see `people.json.example`) -To edit logs in a Web page, it's recommended to install the `http-server` node -package and use that (for now): - -```sh -$ npm i -g http-server -$ http-server www/ -``` - -Once that's done, you can visit `http://localhost:8080/` to paste IRC logs, see -the output, and copy/paste the HTML (etc) wherever you need it. +Once those two files are configured to your contentment, see below. ## Command Line Usage @@ -96,6 +87,21 @@ The WordPress, Google, and Twitter related switches also require some custom environment variables to be setup. For examples of those, see the [publish.sh.example](publish.sh.example). +## Web-based editor + +You can edit logs in a small Web app. To do so, it's recommended to install the +`http-server` node package and use that (for now): + +```sh +$ npm i -g http-server +$ http-server www/ +``` + +Once that's done, you can visit `http://localhost:8080/` to paste IRC logs, see +the output, and copy/paste the HTML (etc) wherever you need it. + +For this to work you'll need to put `people.json` in your `www/` folder. + ## Wrapping bash scripts If you're on a machine that has bash available, there are a couple useful tools diff --git a/config.yaml.example b/config.yaml.example new file mode 100644 index 0000000..e4ce01e --- /dev/null +++ b/config.yaml.example @@ -0,0 +1,49 @@ +--- +# required - or URLs are not produce-able +minutes_base_url: https://json-ld.github.io/minutes/ + +group: JSON-LD CG Telecon # default: Telecon +people: www/people.json # default: www/people.json +partials: www/_partials/ # default: www/_partials/ + +# The `content` and `minutes_base_url` Mustache variables MUST are pre-escaped +# so use {{{content}}} (3 curley braces) to properly unescape them for text. + +email: # required for -e + from: gregg@greggkellogg.net # required! + to: JSON-LD CG # required! + # Mustache template - vars: gDate + subject: "[MINUTES] W3C JSON-LD CG Call - {{gDate}} 12pm ET" + # Mustache template - vars: content, gDate, scribe, minutes_base_url + body: |- + Thanks to {{scribe}} for scribing this week! The minutes + for this week's JSON-LD CG telecon are now available: + {{{minutes_base_url}}}{{gDate}}/ + + Full text of the discussion follows for W3C archival purposes. + Audio from the meeting is available as well (link provided below). + + ---------------------------------------------------------------- + {{{content}}} +gplus: # required for -g + # Mustache template - vars: content, formattedItems, gDate, minutes_base_url + body: |- + *JSON-LD CG Meeting Summary for {{gDate}}* + + We discussed {{formattedItems}}. + + {{{content}}} + + Full transcript and audio logs are available here: + + {{{minutes_base_url}}}{{gDate}}/ + + #w3c #json-ld +twitter: # required for -t + # Mustache template - vars: group, message, gDate, minutes_base_url + body: |- + JSON-LD CG discusses {{message}}: + {{{minutes_base_url}}}{{gDate}}/ #w3c #json-ld +wordpress: # required for -w + # Mustache template - vars: gDate + title: "JSON-LD CG Meeting Minutes for {{gDate}}"