From e767d8a0e7c7a11ee1f5a5df0596b908063e54b4 Mon Sep 17 00:00:00 2001 From: Henry Whitaker Date: Wed, 17 Jun 2020 21:23:30 +0100 Subject: [PATCH] Changed speedtest client --- Dockerfile | 20 +++-- README.md | 6 +- conf/laravel-worker.conf | 2 +- conf/site/README.md | 2 +- conf/site/app/Bin/.gitignore | 1 + conf/site/app/Helpers/SpeedtestHelper.php | 97 ++++++++++++++++++++++- conf/site/changelog.json | 6 ++ conf/site/config/speedtest.php | 2 +- 8 files changed, 123 insertions(+), 13 deletions(-) create mode 100644 conf/site/app/Bin/.gitignore diff --git a/Dockerfile b/Dockerfile index 3e5c107a..333b32bf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,16 +3,26 @@ MAINTAINER henrywhitaker3@outlook.com # Install apt stuff RUN apk add --no-cache --upgrade \ - python3 \ - py-pip \ + gcc \ + cmake \ + curl-dev \ + libxml2-dev \ + build-base \ + openssl-dev \ supervisor -# Install speedtest-cli -RUN pip3 install speedtest-cli - # Copy over static files COPY conf/ /setup/ +# Get and compile SpeedTest++ +RUN cd /tmp && \ + git clone https://github.com/taganaka/SpeedTest && \ + cd SpeedTest && \ + cmake -DCMAKE_BUILD_TYPE=Release . && \ + cd /tmp/SpeedTest && \ + make install && \ + mv /usr/local/bin/SpeedTest /setup/site/app/Bin/ + # Setup new init script RUN cp /setup/entrypoint/init.sh /etc/cont-init.d/50-speedtest diff --git a/README.md b/README.md index e2240695..52625bb6 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Speedtest Tracker -[![Docker pulls](https://img.shields.io/docker/pulls/henrywhitaker3/speedtest-tracker)](https://hub.docker.com/r/henrywhitaker3/speedtest-tracker) [![last_commit](https://img.shields.io/github/last-commit/henrywhitaker3/Speedtest-Tracker)](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) [![issues](https://img.shields.io/github/issues/henrywhitaker3/Speedtest-Tracker)](https://github.com/henrywhitaker3/Speedtest-Tracker/issues) [![commit_freq](https://img.shields.io/github/commit-activity/m/henrywhitaker3/Speedtest-Tracker)](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) ![version](https://img.shields.io/badge/version-v1.5.2-success) [![license](https://img.shields.io/github/license/henrywhitaker3/Speedtest-Tracker)](https://github.com/henrywhitaker3/Speedtest-Tracker/blob/master/LICENSE) +[![Docker pulls](https://img.shields.io/docker/pulls/henrywhitaker3/speedtest-tracker)](https://hub.docker.com/r/henrywhitaker3/speedtest-tracker) [![last_commit](https://img.shields.io/github/last-commit/henrywhitaker3/Speedtest-Tracker)](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) [![issues](https://img.shields.io/github/issues/henrywhitaker3/Speedtest-Tracker)](https://github.com/henrywhitaker3/Speedtest-Tracker/issues) [![commit_freq](https://img.shields.io/github/commit-activity/m/henrywhitaker3/Speedtest-Tracker)](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) ![version](https://img.shields.io/badge/version-v1.5.3-success) [![license](https://img.shields.io/github/license/henrywhitaker3/Speedtest-Tracker)](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 [speedtest-cli](https://github.com/sivel/speedtest-cli) package to get the data and uses [Chart.js](https://www.chartjs.org/) to plot the results. +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 [SpeedTest++](https://github.com/taganaka/SpeedTest) package to get the data and uses [Chart.js](https://www.chartjs.org/) to plot the results. ![speedtest](https://user-images.githubusercontent.com/36062479/78822484-a82b8300-79ca-11ea-8525-fdeae496a0bd.gif) @@ -35,8 +35,8 @@ Container images are configured using parameters passed at runtime (such as thos | Parameter | Function | | :----: | --- | | `-p 8765:80` | Exposes the webserver on port 8765 | -| `-e SLACK_WEBHOOK` | Optional. Put a slack webhook here to get slack notifications when a speedtest is run. To use discord webhooks, just append `/slack` to the end of your discord webhook URL | | `-v /config` | All the config files reside here. | +| `-e SLACK_WEBHOOK` | Optional. Put a slack webhook here to get slack notifications when a speedtest is run. To use discord webhooks, just append `/slack` to the end of your discord webhook URL | | `-e PUID` | Optional. Supply a local user ID for volume permissions | | `-e PGID` | Optional. Supply a local group ID for volume permissions | diff --git a/conf/laravel-worker.conf b/conf/laravel-worker.conf index 86dcfd7e..9eab9417 100644 --- a/conf/laravel-worker.conf +++ b/conf/laravel-worker.conf @@ -1,6 +1,6 @@ [program:laravel-worker] process_name=%(program_name)s_%(process_num)02d -command=php /config/www/artisan queue:work +command=php /config/www/artisan queue:work --timeout=120 autostart=true autorestart=true user=abc diff --git a/conf/site/README.md b/conf/site/README.md index b3d479f1..ff1ad75d 100644 --- a/conf/site/README.md +++ b/conf/site/README.md @@ -1,6 +1,6 @@ # Speedtest Tracker -[![Docker pulls](https://img.shields.io/docker/pulls/henrywhitaker3/speedtest-tracker)](https://hub.docker.com/r/henrywhitaker3/speedtest-tracker) [![last_commit](https://img.shields.io/github/last-commit/henrywhitaker3/Speedtest-Tracker)](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) [![issues](https://img.shields.io/github/issues/henrywhitaker3/Speedtest-Tracker)](https://github.com/henrywhitaker3/Speedtest-Tracker/issues) ![version](https://img.shields.io/badge/version-v1.5.2-success) [![license](https://img.shields.io/github/license/henrywhitaker3/Speedtest-Tracker)](https://github.com/henrywhitaker3/Speedtest-Tracker/blob/master/LICENSE) +[![Docker pulls](https://img.shields.io/docker/pulls/henrywhitaker3/speedtest-tracker)](https://hub.docker.com/r/henrywhitaker3/speedtest-tracker) [![last_commit](https://img.shields.io/github/last-commit/henrywhitaker3/Speedtest-Tracker)](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) [![issues](https://img.shields.io/github/issues/henrywhitaker3/Speedtest-Tracker)](https://github.com/henrywhitaker3/Speedtest-Tracker/issues) ![version](https://img.shields.io/badge/version-v1.5.3-success) [![license](https://img.shields.io/github/license/henrywhitaker3/Speedtest-Tracker)](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 [speedtest-cli](https://github.com/sivel/speedtest-cli) package to get the data and uses [Chart.js](https://www.chartjs.org/) to plot the results. diff --git a/conf/site/app/Bin/.gitignore b/conf/site/app/Bin/.gitignore new file mode 100644 index 00000000..34bd0299 --- /dev/null +++ b/conf/site/app/Bin/.gitignore @@ -0,0 +1 @@ +SpeedTest diff --git a/conf/site/app/Helpers/SpeedtestHelper.php b/conf/site/app/Helpers/SpeedtestHelper.php index 0118d604..00373cf9 100644 --- a/conf/site/app/Helpers/SpeedtestHelper.php +++ b/conf/site/app/Helpers/SpeedtestHelper.php @@ -3,9 +3,14 @@ namespace App\Helpers; use App\Speedtest; +use Carbon\Carbon; use Exception; +use GuzzleHttp\Client; +use GuzzleHttp\Psr7\Request; +use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Log; use JsonException; +use SimpleXMLElement; class SpeedtestHelper { public static function runSpeedtest($output = false) @@ -34,14 +39,102 @@ class SpeedtestHelper { public static function output() { $server = SettingsHelper::get('server')['value']; + $binPath = app_path() . DIRECTORY_SEPARATOR . 'Bin' . DIRECTORY_SEPARATOR . 'SpeedTest'; if($server != '' && $server != false) { $server = explode(',', $server); $server = $server[array_rand($server)]; + $server = SpeedtestHelper::resolveServer($server); + if($server == false) { + Log::error('Speedtest server undefined'); + return false; + } + $server = $server['host']; - return shell_exec('speedtest-cli --json --server ' . $server); + return shell_exec($binPath . ' --output json --test-server ' . $server); } - return shell_exec('speedtest-cli --json'); + return shell_exec($binPath . ' --output json'); + } + + /* + * Resolve the server host/port from speedtest server id + */ + public static function resolveServer($id) + { + $ttl = Carbon::now()->addMinutes(120); + $ids = Cache::remember('servers', $ttl, function () { + $urls = [ + 'http://www.speedtest.net/speedtest-servers-static.php', + 'http://c.speedtest.net/speedtest-servers-static.php', + 'http://www.speedtest.net/speedtest-servers.php', + 'http://c.speedtest.net/speedtest-servers.php', + ]; + + $client = new Client([]); + + $ids = []; + foreach($urls as $url) { + try { + $response = $client->get($url); + if($response->getStatusCode() == 200) { + $data = (string) $response->getBody(); + $data = simplexml_load_string($data); + $data = SpeedtestHelper::xmlToArray($data); + $data = $data['settings']['servers']['server']; + foreach($data as $s) { + $ids[$s['attributes']['id']] = $s['attributes']; + } + } else { + continue; + } + } catch(Exception $e) { + Log::error('Speedtest server resolver error'); + Log::error($e->getMessage()); + continue; + } + } + return $ids; + }); + + if(array_key_exists($id, $ids)) { + return $ids[$id]; + } else { + return false; + } + } + + public static function xmlToArray(SimpleXMLElement $xml): array + { + $parser = function (SimpleXMLElement $xml, array $collection = []) use (&$parser) { + $nodes = $xml->children(); + $attributes = $xml->attributes(); + + if (0 !== count($attributes)) { + foreach ($attributes as $attrName => $attrValue) { + $collection['attributes'][$attrName] = strval($attrValue); + } + } + + if (0 === $nodes->count()) { + $collection['value'] = strval($xml); + return $collection; + } + + foreach ($nodes as $nodeName => $nodeValue) { + if (count($nodeValue->xpath('../' . $nodeName)) < 2) { + $collection[$nodeName] = $parser($nodeValue); + continue; + } + + $collection[$nodeName][] = $parser($nodeValue); + } + + return $collection; + }; + + return [ + $xml->getName() => $parser($xml) + ]; } public static function latest() diff --git a/conf/site/changelog.json b/conf/site/changelog.json index 023f60f6..8a5d3d9c 100644 --- a/conf/site/changelog.json +++ b/conf/site/changelog.json @@ -1,4 +1,10 @@ { + "1.5.3": [ + { + "description": "Changed speedtest client", + "link": "" + } + ], "1.5.2": [ { "description": "Updated dependencies", diff --git a/conf/site/config/speedtest.php b/conf/site/config/speedtest.php index 22103759..f6d46508 100644 --- a/conf/site/config/speedtest.php +++ b/conf/site/config/speedtest.php @@ -7,7 +7,7 @@ return [ |-------------------------------------------------------------------------- */ - 'version' => '1.5.2', + 'version' => '1.5.3', /* |--------------------------------------------------------------------------