mirror of
https://github.com/henrywhitaker3/Speedtest-Tracker.git
synced 2025-12-21 13:23:04 +01:00
@@ -1,6 +1,6 @@
|
||||
# Speedtest Tracker
|
||||
|
||||
[](https://hub.docker.com/r/henrywhitaker3/speedtest-tracker) [](https://github.com/henrywhitaker3/Speedtest-Tracker/actions) [](https://github.com/henrywhitaker3/Speedtest-Tracker/actions) [](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) [](https://github.com/henrywhitaker3/Speedtest-Tracker/issues) [](https://github.com/henrywhitaker3/Speedtest-Tracker/commits)  [](https://github.com/henrywhitaker3/Speedtest-Tracker/blob/master/LICENSE)
|
||||
[](https://hub.docker.com/r/henrywhitaker3/speedtest-tracker) [](https://github.com/henrywhitaker3/Speedtest-Tracker/actions) [](https://github.com/henrywhitaker3/Speedtest-Tracker/actions) [](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) [](https://github.com/henrywhitaker3/Speedtest-Tracker/issues) [](https://github.com/henrywhitaker3/Speedtest-Tracker/commits)  [](https://github.com/henrywhitaker3/Speedtest-Tracker/blob/master/LICENSE)
|
||||
|
||||
This program runs a speedtest check every hour and graphs the results. The back-end is written in [Laravel](https://laravel.com/) and the front-end uses [React](https://reactjs.org/). It uses the [Ookla's speedtest cli](https://www.speedtest.net/apps/cli) package to get the data and uses [Chart.js](https://www.chartjs.org/) to plot the results.
|
||||
|
||||
|
||||
@@ -26,13 +26,13 @@ class BackupHelper {
|
||||
case 'csv':
|
||||
$data = Speedtest::get();
|
||||
|
||||
$csv = Storage::disk('local')->getDriver()->getAdapter()->getPathPrefix() . $name . '.csv';
|
||||
$csv = storage_path() . '/app/' . $name . '.csv';
|
||||
$name = $name . '.csv';
|
||||
$handle = fopen($csv, 'w+');
|
||||
fputcsv($handle, array('id', 'ping', 'download', 'upload', 'created_at', 'updated_at'));
|
||||
fputcsv($handle, array('id', 'ping', 'download', 'upload', 'server_id', 'server_name', 'server_host', 'url', 'scheduled', 'failed', 'created_at', 'updated_at'));
|
||||
|
||||
foreach($data as $d) {
|
||||
fputcsv($handle, array($d->id, $d->ping, $d->download, $d->upload, $d->created_at, $d->updated_at));
|
||||
fputcsv($handle, BackupHelper::createCSVBackupArray($d));
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
@@ -62,22 +62,24 @@ class BackupHelper {
|
||||
if($format == 'json') {
|
||||
foreach($array as $test) {
|
||||
try {
|
||||
$st = Speedtest::create([
|
||||
'ping' => $test['ping'],
|
||||
'download' => $test['download'],
|
||||
'upload' => $test['upload'],
|
||||
'created_at' => $test['created_at'],
|
||||
]);
|
||||
$data = BackupHelper::backupJSONToArray($test);
|
||||
|
||||
if($data === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Speedtest::create($data);
|
||||
} catch(Exception $e) {
|
||||
Log::error($e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if($format == 'csv') {
|
||||
$csv = explode(PHP_EOL, $array);
|
||||
$headers = 'id,ping,download,upload,created_at,updated_at';
|
||||
if($csv[0] != $headers) {
|
||||
Log::error('Incorrect CSV format');
|
||||
|
||||
$headers = BackupHelper::validateCSV($csv[0]);
|
||||
if($headers === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -85,14 +87,14 @@ class BackupHelper {
|
||||
$csv = array_values($csv);
|
||||
|
||||
for($i = 0; $i < sizeof($csv); $i++) {
|
||||
$e = explode(',', $csv[$i]);
|
||||
$data = BackupHelper::backupCSVToArray($csv[$i]);
|
||||
|
||||
if($data === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$st = Speedtest::create([
|
||||
'ping' => $e[1],
|
||||
'download' => $e[2],
|
||||
'upload' => $e[3],
|
||||
'created_at' => substr($e[4], 1, -1),
|
||||
]);
|
||||
Speedtest::create($data);
|
||||
} catch(Exception $e) {
|
||||
Log::error($e);
|
||||
continue;
|
||||
@@ -104,4 +106,179 @@ class BackupHelper {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a CSV file passed for restore
|
||||
*
|
||||
* @param String $csv The line containing the CSV headers
|
||||
* @return bool|string
|
||||
*/
|
||||
public static function validateCSV(String $csv)
|
||||
{
|
||||
$headers = [
|
||||
'old' => 'id,ping,download,upload,created_at,updated_at',
|
||||
'new' => 'id,ping,download,upload,server_id,server_name,server_host,url,scheduled,failed,created_at,updated_at',
|
||||
];
|
||||
$backupHeaders = null;
|
||||
|
||||
foreach($headers as $key => $h) {
|
||||
if($csv == $h) {
|
||||
$backupHeaders = $key;
|
||||
}
|
||||
}
|
||||
|
||||
if($backupHeaders === null) {
|
||||
Log::info('Incorrect CSV format');
|
||||
return false;
|
||||
}
|
||||
|
||||
return $backupHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array from the raw CSV data
|
||||
*
|
||||
* @param String $line The line of CSV data
|
||||
* @param String $header The type of backup header
|
||||
* @return array|bool
|
||||
*/
|
||||
public static function backupCSVToArray(String $line, String $header = 'new')
|
||||
{
|
||||
$basic = explode(',', $line);
|
||||
|
||||
if($header == 'old') {
|
||||
$array = [
|
||||
'ping' => $basic[1],
|
||||
'download' => $basic[2],
|
||||
'upload' => $basic[3],
|
||||
'created_at' => substr($basic[4], 1, -1),
|
||||
];
|
||||
}
|
||||
|
||||
if($header == 'new') {
|
||||
$array = [
|
||||
'ping' => $basic[1],
|
||||
'download' => $basic[2],
|
||||
'upload' => $basic[3],
|
||||
'server_id' => $basic[4],
|
||||
'server_name' => $basic[5],
|
||||
'server_host' => $basic[6],
|
||||
'url' => $basic[7],
|
||||
'scheduled' => $basic[8],
|
||||
'failed' => $basic[9],
|
||||
'created_at' => substr($basic[10], 1, -1),
|
||||
];
|
||||
}
|
||||
|
||||
if(!isset($array)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return BackupHelper::cleanRestoreDataArray($array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean an array, setting values with '' to null
|
||||
*
|
||||
* @param array $array
|
||||
* @return array
|
||||
*/
|
||||
public static function cleanRestoreDataArray(array $array)
|
||||
{
|
||||
foreach($array as $key => $val) {
|
||||
if($val === '') {
|
||||
$array[$key] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array from the JSON data
|
||||
*
|
||||
* @param array $json json_decoded data
|
||||
* @return array|bool
|
||||
*/
|
||||
public static function backupJSONToArray($json)
|
||||
{
|
||||
$required = [
|
||||
'ping',
|
||||
'upload',
|
||||
'download',
|
||||
'created_at',
|
||||
];
|
||||
|
||||
$extras = [
|
||||
'server_id',
|
||||
'server_name',
|
||||
'server_host',
|
||||
'url',
|
||||
'failed',
|
||||
'scheduled'
|
||||
];
|
||||
|
||||
$array = [];
|
||||
|
||||
foreach($required as $req) {
|
||||
if(!array_key_exists($req, $json)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$val = $json[$req];
|
||||
|
||||
if($val === '') {
|
||||
$val = null;
|
||||
}
|
||||
|
||||
$array[$req] = $val;
|
||||
}
|
||||
|
||||
foreach($extras as $extra) {
|
||||
if(array_key_exists($extra, $json)) {
|
||||
$val = $json[$extra];
|
||||
|
||||
if($val === '') {
|
||||
$val = null;
|
||||
}
|
||||
$array[$extra] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array to store in CSV
|
||||
*
|
||||
* @param Speedtest $test
|
||||
* @return array
|
||||
*/
|
||||
public static function createCSVBackupArray(Speedtest $test)
|
||||
{
|
||||
$data = [
|
||||
$test->id,
|
||||
$test->ping,
|
||||
$test->download,
|
||||
$test->upload,
|
||||
$test->server_id,
|
||||
$test->server_name,
|
||||
$test->server_host,
|
||||
$test->url,
|
||||
$test->scheduled,
|
||||
$test->failed,
|
||||
$test->created_at,
|
||||
$test->updated_at
|
||||
];
|
||||
|
||||
foreach($data as $key => $val) {
|
||||
if(strpos($val, ',') !== false) {
|
||||
$val = str_replace(',', ' -', $val);
|
||||
}
|
||||
|
||||
$data[$key] = $val;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,14 @@
|
||||
{
|
||||
"1.7.18": [
|
||||
{
|
||||
"description": "Fixed issue with widgets not updating when switching between failed/successful tests.",
|
||||
"link": ""
|
||||
},
|
||||
{
|
||||
"description": "Updated backup/restore functions to reflect new DB fields.",
|
||||
"link": ""
|
||||
}
|
||||
],
|
||||
"1.7.17": [
|
||||
{
|
||||
"description": "Updated dependencies.",
|
||||
|
||||
@@ -10,7 +10,6 @@ parameters:
|
||||
level: 5
|
||||
|
||||
ignoreErrors:
|
||||
- '#Unsafe usage of new static#'
|
||||
|
||||
excludes_analyse:
|
||||
- ./*/*/FileToBeExcluded.php
|
||||
|
||||
2
public/js/app.js
vendored
2
public/js/app.js
vendored
File diff suppressed because one or more lines are too long
30
resources/js/components/Data/Restore.js
vendored
30
resources/js/components/Data/Restore.js
vendored
@@ -75,6 +75,36 @@ export default class Restore extends Component {
|
||||
inputName: 'created_at',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: "server_id",
|
||||
inputName: 'server_id',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: "server_name",
|
||||
inputName: 'server_name',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: "server_host",
|
||||
inputName: 'server_host',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: "url",
|
||||
inputName: 'url',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: "scheduled",
|
||||
inputName: 'scheduled',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: "failed",
|
||||
inputName: 'failed',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: "updated_at",
|
||||
inputName: 'updated_at',
|
||||
|
||||
Reference in New Issue
Block a user