Last week I blogged about my first experience working with OpenWhisk triggers and rules, specifically the Cron trigger which lets you execute actions according to a schedule. Today I'm sharing another example, which, while not as complex as the 911 scraper, I thought was kind of fun.

As a blogger, I try to keep to a certain amount of posts per month. While I a absolutely care more about quality than quantity, I still try to maintain a certain amount of content per month. I thought it would be fun to create an OpenWhisk action that would nag me if I hadn't blogged in a few days. This turned out to be rather simple:

  • First, I get the RSS feed.
  • Then I parse the XML. There's packages to read RSS, but there's also xml2js which just does a basic conversion.
  • I can then check the date of the most recent article and compare it to now.
  • If it's been too long, nag!

Let's start with the action:


const request = require('request');
const parseString = require('xml2js').parseString;

//number of days you have till i bug you
const NAG_DAY = 2;

//SendGrid API Key
const SG_KEY = 'SG.whywontanyonecommentonthestuffiputhere';
const helper = require('sendgrid').mail;

function doNag(last) {

	let from_email = new helper.Email('raymondcamden@gmail.com');
	let to_email = new helper.Email('raymondcamden@gmail.com');
	let subject = 'You Need to Blog!';

	let content = `
You have not blogged in the past ${NAG_DAY} days!
Your last post was on ${last}.
`
	let mailContent = new helper.Content('text/plain', content);
	let mail = new helper.Mail(from_email, subject, to_email, mailContent);
	let sg = require('sendgrid')(SG_KEY);

	var request = sg.emptyRequest({
		method: 'POST',
		path: '/v3/mail/send',
		body: mail.toJSON()
	});
		
	sg.API(request, function(error, response) {
		if(error) {
			console.log(error.response.body);
		} else {
			//right now we do nothing really
		}
	});
}

function main() {

	let rssurl = 'http://feeds.feedburner.com/raymondcamdensblog';

	return new Promise((resolve, reject) => {

		request.get(rssurl, function(error, response, body) {
			if(error) return reject(error);

			parseString(body, function(err, result) {
				if(err) return reject(err);

				//Latest post:
				let latest = result.rss.channel[0].item[0];
				//now lets try to parse the date
				let latestDate = new Date(latest.pubDate[0]).getTime();
				//alright then - so compare Now to latestDate
				let now = Date.now();
				//difference is how much time (duh)
				let diff = now - latestDate;
				if(diff > (NAG_DAY * 24 * 60 * 60 * 1000)) {
					console.log('got to nag!');
					doNag(latest.pubDate[0]);
					resolve({status:true});
				} else {
					resolve({status:false});
				}
			});

		});

	});
}

exports.main = main;

Start with the main function which is OpenWhisk's entry point to the function. I use the request library to open up my RSS feed and then parseString from the xml2js library. I can then get the most recent blog entry (which is the first entry in a RSS feed) and make a date object with it.

Once I have that - then it's math. I set the constant NAG_DAY to 2, which is a bit too low if you ask me, but I had blogged on Friday so I needed a value that would trigger the alert. (For folks curious, I try to blog once every 3 days.) If we need to nag, we then simply call doNag.

The doNag function just writes an email using the Sendgrid API and fires it out. And that's it.

So then I had to make this "live" - which beforehand would have meant provisioning a server and all that, but with the wonders of Serverless (yes, I'm half-joking here ;) I just did the following:

  • Sent the action up to OpenWhisk with the CLI (wsk action create --kind nodejs:6 rssnag rssnag.zip)
  • Made the trigger (wsk trigger create checkBlog --feed /whisk.system/alarms/alarm --param cron "* * 1 * *"). That Cron value is for once a day, and yes I had to use http://crontab-generator.org again.
  • Made the rule (wsk rule create blogNagRule checkBlog rssnag)

And that's it. To test I used the OpenWhisk UI on IBM Bluemix and manually triggered it. And the result....

Email ftw