Files
profile/themes/keepit/node_modules/speedtest-net/bin/index.js
Spencer Pincott 97737ca1ae Initial commit
2024-07-15 22:20:13 -04:00

263 lines
5.3 KiB
JavaScript
Executable File

#!/usr/bin/env node
require('draftlog').into(console).addLineListener(process.stdin);
var chalk = require('chalk');
var SpeedTestNet = require('../');
/*
* Keep track of current UI State
*/
var header, speeds, locate;
var step = 'Ping';
var statuses = {
Ping: true,
Download: false,
Upload: false,
};
/*
* Renders the header and Speeds (one below the other)
*/
var width = 24;
function updateLines() {
var spinner = Spinner();
var headerTxt = renderHeader(statuses, step);
var speedsTxt = renderStatus(statuses, step, spinner);
header('│' + headerTxt + '│');
speeds('│' + speedsTxt + '│');
}
/*
* Renders the Header (Showing PING DOWNLOAD UPLOAD) with it's colors and spacings
*/
function renderHeader(statuses) {
var txt = '';
// Build Header
for (var k in statuses) {
var status = statuses[k];
// Create header
var col = centerText(k, width);
// Set header status color
if (status === false) {
col = chalk.dim(col);
} else {
col = chalk.white(col);
}
txt += col;
}
return txt;
}
/*
* Renders the Status line (Showing Ping/Download/Upload results) with it's colors and spacings
*/
function renderStatus(statuses, step, spinner){
var txt = '';
// Build Status
for (var k in statuses) {
var status = statuses[k];
// Account for status where it's false/true
// (indicating not started and not received value yet)
status = status === false ? '' : status;
status = status === true ? '' : status;
status = status + '';
// Put spinner if no info
if (!status) {
status = spinner + ' ';
}
// Create status text
status = centerText(status, width);
// Dim unitis
status = status.replace(/(Mbps|ms)/gi, chalk.dim('$1'));
// If it's the current step, show as yellow
if (step == k) {
status = chalk.yellow(status);
} else {
status = chalk.blue(status);
}
txt += status;
}
return txt;
}
/*
* Pad Left/Right with same amount of spaces n times. compensate for odd numbers
*/
function centerText(text, n, length) {
// Account for text length first
n -= length || text.length;
// Pad to be even
if (n % 2 == 1) {
text = ' ' + text;
}
// Round n to lowest number
n = Math.floor(n / 2);
// Make spacer
var spacer = ' '.repeat(n);
// Fill in text
return spacer + text + spacer;
}
/*
* Converts a number to speed (in Mbps)
*/
function speedText(speed) {
// Depending on the speed, show more places
var places = ( speed < 2 ? 3 : 1);
// Make it fixed
var str = speed.toFixed(places);
// Concat with unit
return str + ' Mbps';
}
/*
* Function that return state of Spinner, and change its state with time
*/
var frames = [
'+---',
'-+--',
'--+-',
'---+',
'--+-',
'-+--',
];
var lastChange = 0;
function Spinner(){
if (Date.now() > lastChange + 30) {
frames.unshift(frames.pop());
lastChange = Date.now();
}
return frames[0];
}
/*
* Shows CLI UI
*/
console.log();
console.log('┌' + '─'.repeat(width * 3) + '┐');
console.log('│' + ' '.repeat(width * 3) + '│');
locate = console.draft('│' + ' '.repeat(width * 3) + '│');
console.log('│' + ' '.repeat(width * 3) + '│');
header = console.draft();
speeds = console.draft();
console.log('│' + ' '.repeat(width * 3) + '│');
console.log('│' + ' '.repeat(width * 3) + '│');
console.log('└' + '─'.repeat(width * 3) + '┘');
console.log();
console.log();
updateLines();
/*
* Start speed test
*/
var options = {
maxTime: 10000,
proxy: null,
sourceIp: null,
};
/*
* get parameters
*/
var errorParameter = null;
process.argv.forEach(function (val, index, array) {
if (index >= 2) {
if (val === '--proxy') {
if (array[index + 1] !== undefined) {
options.proxy = array[index + 1];
} else {
errorParameter = 'Error: bad parameters';
}
} else if (val === '--sourceip') {
if (array[index + 1] !== undefined) {
options.sourceIp = array[index + 1];
} else {
errorParameter = 'Error: bad parameters';
}
}
}
});
/*
* interrupt if error (parameters)
*/
if (errorParameter) {
console.log();
console.error(chalk.red(errorParameter));
console.log();
process.exit(1);
}
var test = SpeedTestNet(options);
var interval = setInterval(updateLines, 100);
var completedUpload = false;
var completedDownload = false;
test.on('downloadspeedprogress', function (speed){
if (!completedDownload) {
statuses.Download = speedText(speed);
}
});
test.on('uploadspeedprogress', function (speed){
if (!completedUpload) {
statuses.Upload = speedText(speed);
}
});
test.once('testserver', function (info){
// Round to 1 decimal place
var title = info.sponsor + ', ' + info.country + ' - ' + info.name;
title = centerText(title, width * 3);
locate('│' + chalk.yellow(title) + '│');
var ping = Math.round(info.bestPing * 10) / 10;
statuses.Ping = ping + ' ms';
step = 'Download';
});
test.once('downloadspeed', function (speed){
completedDownload = true;
step = 'Upload';
statuses.Download = speedText(speed);
});
test.once('uploadspeed', function (speed){
completedUpload = true;
step = 'Finished';
statuses.Upload = speedText(speed);
});
test.on('done', function () {
process.exit(0);
});
test.on('error', function (err) {
console.log();
console.error(chalk.red(err));
console.log();
process.exit(1);
});