From 12a039930bc148e65a33b430649f17272ba9c6e0 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Wed, 27 May 2020 19:58:12 +0200 Subject: [PATCH] Check ISP website & send mail if services are down Scrape, navigate and print ISP's status page for a given address. This only works with telenor and the URL must be a search for a given address. If any services are found to be down a mail is sent from and to accounts set in config.js. --- src/index.js | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/mail.js | 40 ++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 src/index.js create mode 100644 src/mail.js diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..cbe6446 --- /dev/null +++ b/src/index.js @@ -0,0 +1,128 @@ +// custom-header-footer.js + +// const common = require('./common') +const puppeteer = require('puppeteer') +const config = require('../config') +const Mail = require( './mail.js'); +const mail = new Mail(); + +let browser = undefined; +if (config.debug == false) + console.log = () => {} + +const savePageToPDF = page => { + const pdfOptions = { + path: `telenor-downtime.pdf`, + format: "A4", + printBackground: true, + displayHeaderFooter: true, + headerTemplate: `
+ ${new Date().toLocaleString('nb-NO')} + + ${ config.url } + +
`, + footerTemplate: `
+ Generated PDF + + / + +
`, + margin: { + top: '38px', + right: '38px', + bottom: '38px', + left: '38px' + } + } + + console.log('Saving page content to pdf.') + return page.setViewport({ width: 1920, height: 1080 }) + .then(() => page.pdf(pdfOptions)) + .then(() => Promise.resolve(page)) + } + +const exitWithError = (err, message=undefined) => { + if (message) + console.error(message); + else + console.error('Unexpected error occured') + + if (config.debug === true) + console.error(err) + + closeBrowser(); + process.exit(1); +} + +const dismissCookiePrompt = page => { + console.log("Dismissing cookie consent prompt") + + return page.$('a#consent_prompt_submit') + .catch(err => exitWithError(err, 'Could not find cookie consent prompt on page')) + .then(consentLink => { + if (consentLink == null) + page.evaluate(() => document.body.innerHTML) + else + consentLink.evaluate(link => link.click()) + + return page + }) +} + +const getServiceMessages = page => { + const statusTextOkTemplate = 'Vi fant ingen registrerte feil' + + return page.evaluate((statusTextTemplate) => { + const messages = []; + document.querySelectorAll(".service-message-wrapper").forEach(serviceMessage => { + messages.push({ + iconStatus: serviceMessage.classList.contains('color-ok'), + statusText: serviceMessage.getElementsByClassName('short-info')[0].innerText, + isOk: serviceMessage.innerText.includes(statusTextTemplate) + }) + }) + + return messages + }, statusTextOkTemplate) +}; + +const notifyIfDown = serviceMessages => { + const servicesDown = serviceMessages.filter(message => message.isOk == false) + + if (servicesDown.length) { + console.log("Following services are down:\n", servicesDown) + + mail.sendAttachment('./telenor-downtime.pdf') + .then(resp => console.log(`Message id: ${resp.messageId} sent.\nResponse content: ${resp}`)) + } else { + console.info("All service operational"); + } +} + +const webscraper = async pageURL => { + browser = await puppeteer.launch({ headless: true }) + const page = await browser.newPage() + + console.log(`Opening page with url: ${pageURL}`) + return page.goto(pageURL) + .then(() => Promise.resolve(page)) + .catch(err => exitWithError(err, `Unable to reach url: ${pageURL}`)) +} + +function closeBrowser() { + browser.close(); +} + + +function run() { + webscraper(config.url) + .then(page => dismissCookiePrompt(page)) + .then(page => savePageToPDF(page)) + .then(page => getServiceMessages(page)) + .then(serviceMessages => notifyIfDown(serviceMessages)) + .then(closeBrowser) +} + +run(); + diff --git a/src/mail.js b/src/mail.js new file mode 100644 index 0000000..dbea9a6 --- /dev/null +++ b/src/mail.js @@ -0,0 +1,40 @@ +const nodemailer = require( 'nodemailer') +const config = require('../config.js') + +class Mail { + constructor(sender=undefined, password=undefined, recipient=undefined) { + this.sender = sender || config.senderEmail; + this.password = password || config.senderPassword; + this.recipient = recipient || config.recipientEmail; + this.transporter = this.setupTransporter(); + } + + setupTransporter() { + return nodemailer.createTransport({ + service: 'gmail', + auth: { + user: this.sender, + pass: this.password + } + }) + } + + sendMail = message => this.transporter.sendMail(message); + + sendAttachment = fileRef => { + const message = { + from: `"Fred Foo 👻" <${this.sender}>`, + to: this.recipient, + subject: 'Telenor nedetid', + text: "hello wordl", + html: "

hello wordl

", + attachments: [{ + path: fileRef + }] + } + + return this.sendMail(message) + } +} + +module.exports = Mail