This page looks best with JavaScript enabled

Checking Web Value with NodeJS/Puppeteer

 ·  🎃 kr0m

In a previous occasion , we used Puppeteer to automate clicking a button on a web interface. In this case, we will log in and read some values to verify the correct functioning of the network interfaces of a router. Additionally, if it detects an incorrect speed on any of the ports, it will send us a message via Telegram.

The data we are going to read is marked in red in the screenshot:

You can find the Puppeteer project on Github: https://github.com/puppeteer/puppeteer

Install Node.js:

pkg install npm-node17
emerge -av net-libs/nodejs

Instalamos Puppeteer como usuario regular, este intentará descargar una copia de Chrome pero en FreeBSD se queja de que no es una plataforma soportada:

Error: Unsupported platform: freebsd

Para solventarlo tan solo debemos instalarlo indicando que no queremos descargar ninguna copia de Chrome, ya que nosotros ya disponemos de una en local instalada por sl sistema operativo:

PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true npm install puppeteer
npm install puppeteer

Instalamos la librería de envío de mensajes a través de Telegram:

npm install simple-telegram-message

En mi caso utilizo esta extensión de Chrome para crear el script base y a partir de este ir adaptándolo a mis necesidades:
https://chrome.google.com/webstore/detail/puppeteer-recorder/djeegiggegleadkkbgopoonhjimgehda

El script final quedaría del siguiente modo:

vi routerSpeed.js

// npm install simple-telegram-message
const { sendMessageFor } = require('simple-telegram-message')
//const sendMessage = sendMessageFor(process.env.TELEGRAM_TOKEN, 'user_id|channel_id')
const sendMessage = sendMessageFor('345555217:AAgr5t1d5567NgjghCfCGfdrCN56hjGGt5', '12345678')

// PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true npm install puppeteer
const puppeteer = require('puppeteer');

function delay(time) {
    return new Promise(function(resolve) {
        setTimeout(resolve, time)
    });
}

(async () => {
    //const browser = await puppeteer.launch({headless: false, executablePath: '/usr/local/bin/chrome'})
    const browser = await puppeteer.launch({headless: true, executablePath: '/usr/local/bin/chrome'})
  
    const page = await browser.newPage()
    
    const navigationPromise = page.waitForNavigation()
    await page.goto('http://192.168.X.X/login')
    
    await page.setViewport({ width: 1022, height: 1025 })
    
    await navigationPromise
  
    console.log('>> Making login');

    await page.waitForSelector('#username')
    await page.click('#username')
    await page.type('#username', 'USERNAME')
    
    
    await page.waitForSelector('#userpassword')
    await page.click('#userpassword')
    await page.type('#userpassword', 'PASSWORD')
    
    await page.waitForSelector('.form-login > div > .btnbox > #loginBtn > span')
    await page.click('.form-login > div > .btnbox > #loginBtn > span')

    console.log('>> Waiting for page');
    await delay(10000)

    console.log('>> Accessing system information page');

    await page.waitForSelector('.row > #card_sys > .card > #card_sysinfo > .fa-2x')
    await page.click('.row > #card_sys > .card > #card_sysinfo > .fa-2x')

    console.log('>> Waiting for page');
    await delay(9000)

    console.log('>> Reading port speed values');

    let [element0] = await page.$x('//*[@id="popup"]/div/div[2]/div/div[1]/div[2]/ul/li[1]/span[3]');
    let text0 = await page.evaluate(element => element.textContent, element0);
    //console.log('LAN Speed0: ' + text0);
    if (text0 == '-') {
        console.log('LAN Speed0: NO LINK');
    } else if (text0 == '1000M/Full') {
        console.log('LAN Speed0: ' + text0);
    } else {
        console.log('Wrong LAN Speed0: ' + text0);
        sendMessage('Router: Wrong LAN Speed0: ' + text0);
    }

    let [element1] = await page.$x('//*[@id="popup"]/div/div[2]/div/div[1]/div[2]/ul/li[2]/span[3]');
    let text1 = await page.evaluate(element => element.textContent, element1);
    //console.log('LAN Speed1: ' + text1);
    if (text1 == '-') {
        console.log('LAN Speed1: NO LINK');
    } else if (text1 == '1000M/Full') {
        console.log('LAN Speed1: ' + text1);
    } else {
        console.log('LAN Speed1: ' + text1);
        sendMessage('Router: Wrong LAN Speed1: ' + text1);
    }

    let [element2] = await page.$x('//*[@id="popup"]/div/div[2]/div/div[1]/div[2]/ul/li[3]/span[3]');
    let text2 = await page.evaluate(element => element.textContent, element2);
    //console.log('LAN Speed2: ' + text2);
    if (text2 == '-') {
        console.log('LAN Speed2: NO LINK');
    } else if (text2 == '1000M/Full') {
        console.log('LAN Speed2: ' + text2);
    } else {
        console.log('LAN Speed2: ' + text2);
        sendMessage('Router: Wrong LAN Speed2: ' + text2);
    }

    let [element3] = await page.$x('//*[@id="popup"]/div/div[2]/div/div[1]/div[2]/ul/li[4]/span[3]');
    let text3 = await page.evaluate(element => element.textContent, element3);
    //console.log('LAN Speed3: ' + text3);
    if (text3 == '-') {
        console.log('LAN Speed3: NO LINK');
    } else if (text3 == '1000M/Full') {
        console.log('LAN Speed3: ' + text3);
    } else {
        console.log('LAN Speed3: ' + text3);
        sendMessage('Router: Wrong LAN Speed3: ' + text3);
    }

    let [element4] = await page.$x('//*[@id="popup"]/div/div[2]/div/div[1]/div[2]/ul/li[5]/span[3]');
    let text4 = await page.evaluate(element => element.textContent, element4);
    //console.log('WAN Speed: ' + text4);
    if (text4 == '-') {
        console.log('WAN Speed: NO LINK');
    } else if (text4 == '1000M/Full') {
        console.log('WAN Speed: ' + text4);
    } else {
        console.log('Wrong WAN Speed: ' + text4);
        sendMessage('Router: Wrong WAN Speed: ' + text4);
    }

    await browser.close()
  })()

The XPath of web elements can be easily obtained from Chrome:

Inspect element -> Right-click on the element on the right side -> Copy -> Copy XPath

Este script se puede crontabear y así tener un sistema básico de monitorización de la velocidad de los puertos del router:

crontab -e

*/1 * * * * /usr/local/bin/node /home/kr0m/.scripts/routerSpeed/routerSpeed.js
If you liked the article, you can treat me to a RedBull here