Skip to content

Instantly share code, notes, and snippets.

@peterc
Last active August 28, 2018 20:49
Show Gist options
  • Save peterc/a7d63960ca6dcf165477b310d0d08afb to your computer and use it in GitHub Desktop.
Save peterc/a7d63960ca6dcf165477b310d0d08afb to your computer and use it in GitHub Desktop.
An ES6 variant of a serverless function written in Python..
const fetch = require('node-fetch');
const parseString = require('xml2js').parseString;
const util = require('util');
const hostnames = ["react.statuscode.com", "javascriptweekly.com", "nodeweekly.com"];
function checkValidity(url) {
return fetch(url)
.then(res => res.text())
.then(resultText => promisify(parseString)(resultText))
.then(res => res['env:Envelope']['env:Body'][0]['m:feedvalidationresponse'][0]['m:validity'][0]);
}
async function postSlackMessage(message, channel = '#experiments') {
let slackData = { text: message, channel: channel };
return fetch(process.env['SLACK_URL'], { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(slackData) })
}
async function lambda_handler(event, context) {
for (let hostname of hostnames) {
let url = `https://validator.w3.org/feed/check.cgi?url=https%3A%2F%2F${hostname}%2Frss&output=soap12`;
if (await checkValidity(url)) {
await postSlackMessage(`:white_check_mark: ${hostname} has valid RSS`);
} else {
await postSlackMessage(`:x: ${hostname} has INVALID RSS`, '#editorial');
}
}
}
if (process.argv[2] == 'test') {
lambda_handler(null, null);
}
@vkarpov15
Copy link

Also, just as a warning, don't do this:

parseString(resultText, async function(err, result) {
  res(result['env:Envelope']['env:Body'][0]['m:feedvalidationresponse'][0]['m:validity'][0]);
})

In general, you shouldn't mark a callback as async because then calling the callback creates a promise that is never used.

@peterc
Copy link
Author

peterc commented Aug 28, 2018

Thanks for the tip @vkarpov15

Also, a total cheat version partly inspired by Jon :-D

async function checkValidity(url) {
  let res = await fetch(url).then(res => res.text());
  return res.match("<m:validity>true");
}

The XML will remain consistently formatted.. right?

@yevhenpavliuk
Copy link

const checkValidity = url =>
  fetch(url)
    .then(response => response.text())
    .then(text => text.includes("<m:validity>true"));

Although checking if the XML contains a substring may be enough in this particular case, I would not rely on it.

@ThisIsMissEm
Copy link

ThisIsMissEm commented Aug 28, 2018

Try:

function checkValidity(url) {
  const res = await fetch(url)
  const resultText = await res.text()
  
  const parsed = await promisify(parseString)(resultText))

  return parsed['env:Envelope']['env:Body'][0]['m:feedvalidationresponse'][0]['m:validity'][0];
}

@peterc
Copy link
Author

peterc commented Aug 28, 2018

Thanks for the help folks! Here's where I'm at so far, since this is so scrappy:

const fetch = require('node-fetch');

const hostnames = ["react.statuscode.com", "javascriptweekly.com", "nodeweekly.com"];

async function checkValidity(url) {
  const res = await fetch(url).then(res => res.text());
  return res.match("<m:validity>true");
}

async function postSlackMessage(message, channel) {
  const slackData = { text: message, channel: channel };
  await fetch(process.env['SLACK_URL'], { method: 'POST', body: JSON.stringify(slackData) })
}

async function doValidity(hostname) {
  const url = `https://validator.w3.org/feed/check.cgi?url=https%3A%2F%2F${hostname}%2Frss&output=soap12`;

  if (checkValidity(url)) {
    postSlackMessage(`:white_check_mark: ${hostname} has valid RSS (JS)`, '#experiments');
  } else {
    postSlackMessage(`:x: ${hostname} has INVALID RSS (JS)`, '#editorial');
  }
}

exports.lambdaHandler = (event, context, callback) => {
  hostnames.map(hostname => doValidity(hostname));
  if (callback) callback(null, "success");
};

if (process.argv[2] == 'test') exports.lambdaHandler();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment