263 lines
5.3 KiB
JavaScript
Executable File
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);
|
|
});
|