mirror of
				https://github.com/KevinMidboe/ISPDowntimeMonitor.git
				synced 2025-10-29 17:50:12 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							
								
								
									
										128
									
								
								src/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -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: `<div style="font-size:11px;white-space:nowrap;margin-left:38px;"> | ||||||
|  |                         ${new Date().toLocaleString('nb-NO')} | ||||||
|  |                         <span style="margin-left: 10px;"> | ||||||
|  |                           ${ config.url } | ||||||
|  |                         </span> | ||||||
|  |                     </div>`, | ||||||
|  |     footerTemplate: `<div style="font-size:7px;white-space:nowrap;margin-left:38px;width:100%;"> | ||||||
|  |                         Generated PDF | ||||||
|  |                         <span style="display:inline-block;float:right;margin-right:10px;"> | ||||||
|  |                             <span class="pageNumber"></span> / <span class="totalPages"></span> | ||||||
|  |                         </span> | ||||||
|  |                     </div>`, | ||||||
|  |     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(); | ||||||
|  |  | ||||||
							
								
								
									
										40
									
								
								src/mail.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/mail.js
									
									
									
									
									
										Normal file
									
								
							| @@ -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: "<p>hello wordl</p>", | ||||||
|  |       attachments: [{ | ||||||
|  |         path: fileRef  | ||||||
|  |       }] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return this.sendMail(message)  | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = Mail | ||||||
		Reference in New Issue
	
	Block a user