-
-
Save peterc/a7d63960ca6dcf165477b310d0d08afb to your computer and use it in GitHub Desktop.
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); | |
} |
Was not aware of promisify, will take a look! Thanks! :)
That didn't work as-is, but this did:
async function checkValidity(url) {
return fetch(url)
.then(res => { return res.text() })
.then(resultText => util.promisify(parseString)(resultText))
.then(res => res['env:Envelope']['env:Body'][0]['m:feedvalidationresponse'][0]['m:validity'][0]);
}
A few tips:
res => { return res.text() } // no
res => res.text() // yes
const parseString = require('xml2js').parseString; // no
const {parseString} = require('xml2js'); // yes
I’d rewrite:
const {promisify} = require('util');
const parseStringAsync = promisify(parseString);
async function checkValidity(url) {
const res = await fetch(url);
const resultText = await res.text();
const parsed = await parseStringAsync(resultText);
return parsed['env:Envelope']['env:Body'][0]['m:feedvalidationresponse'][0]['m:validity'][0];
}
If you do the promisifying yourself, you should not use an async function as the callback and you should handle errors:
function parseStringAsync(str) {
return new Promise((resolve, reject) => {
parseString(str, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
})
});
}
Aha, now let me look at your updated version, as it does look nicer than the chain of then
s!
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.
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?
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.
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];
}
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();
My attempt at simplifying
checkValidity
And this allows throwing of errors 😄