From c4e2e7f627067193daf5590b0f5bac03de1f2d71 Mon Sep 17 00:00:00 2001 From: Alex Justesen Date: Mon, 15 Dec 2025 09:57:54 -0500 Subject: [PATCH 1/7] fix: adjust speedtest button size based on request context (#2550) Co-authored-by: Alex Justesen <1144087+alexjustesen@users.noreply.github.com> --- app/Livewire/Topbar/Actions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Livewire/Topbar/Actions.php b/app/Livewire/Topbar/Actions.php index 5f687ae86..9077724c8 100644 --- a/app/Livewire/Topbar/Actions.php +++ b/app/Livewire/Topbar/Actions.php @@ -67,7 +67,7 @@ public function speedtestAction(): Action ->modalWidth('lg') ->modalSubmitActionLabel(__('results.start')) ->button() - ->size(Size::Medium) + ->size(request()->is('filament*') ? Size::Medium : Size::Large) ->color('primary') ->label(__('results.speedtest')) ->icon('tabler-rocket') From 74062c902d9985f95cf25c53ee0069a23cddee51 Mon Sep 17 00:00:00 2001 From: Alex Justesen Date: Mon, 15 Dec 2025 19:55:37 -0500 Subject: [PATCH 2/7] Update form method to use Schema instead of Form in ListOoklaServers (#2551) Co-authored-by: Alex Justesen <1144087+alexjustesen@users.noreply.github.com> --- app/Filament/Pages/Tools/ListOoklaServers.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/Filament/Pages/Tools/ListOoklaServers.php b/app/Filament/Pages/Tools/ListOoklaServers.php index d2d5ea3eb..c82ad82b3 100644 --- a/app/Filament/Pages/Tools/ListOoklaServers.php +++ b/app/Filament/Pages/Tools/ListOoklaServers.php @@ -7,9 +7,9 @@ use Filament\Forms\Components\Textarea; use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; -use Filament\Forms\Form; use Filament\Notifications\Notification; use Filament\Pages\Page; +use Filament\Schemas\Schema; class ListOoklaServers extends Page implements HasForms { @@ -69,10 +69,10 @@ public function fetchServers(): void } } - public function form(Form $form): Form + public function form(Schema $schema): Schema { - return $form - ->schema([ + return $schema + ->components([ Textarea::make('servers') ->label(false) ->rows(20) From 3381265bdf5082bc66fc37466d3657f8fbabc711 Mon Sep 17 00:00:00 2001 From: Alex Justesen Date: Tue, 16 Dec 2025 06:48:11 -0500 Subject: [PATCH 3/7] fix: datetime format for next speedtest banner (#2554) Co-authored-by: Alex Justesen <1144087+alexjustesen@users.noreply.github.com> --- resources/views/livewire/next-speedtest-banner.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/next-speedtest-banner.blade.php b/resources/views/livewire/next-speedtest-banner.blade.php index ce65f81d7..e66d3c1ee 100644 --- a/resources/views/livewire/next-speedtest-banner.blade.php +++ b/resources/views/livewire/next-speedtest-banner.blade.php @@ -8,7 +8,7 @@

- Next scheduled test at {{ $this->nextSpeedtest->timezone(config('app.display_timezone'))->format('F jS, Y, g:i a') }}. + Next scheduled test at {{ $this->nextSpeedtest->timezone(config('app.display_timezone'))->format(config('app.datetime_format')) }}.

From 963fc051ad6a8645c0ab2ee585854c9b5cd79c65 Mon Sep 17 00:00:00 2001 From: Alex Justesen Date: Tue, 16 Dec 2025 07:55:52 -0500 Subject: [PATCH 4/7] update external IP fetching logic to handle failures (#2555) Co-authored-by: Alex Justesen <1144087+alexjustesen@users.noreply.github.com> --- app/Actions/GetExternalIpAddress.php | 20 +++++++++++++++----- app/Jobs/Ookla/SkipSpeedtestJob.php | 18 +++++++++++++++++- config/speedtest.php | 6 +++++- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/app/Actions/GetExternalIpAddress.php b/app/Actions/GetExternalIpAddress.php index 6a4d0b114..48417c1f1 100644 --- a/app/Actions/GetExternalIpAddress.php +++ b/app/Actions/GetExternalIpAddress.php @@ -12,18 +12,28 @@ class GetExternalIpAddress { use AsAction; - public function handle(): bool|string + public function handle(?string $url = null): array { + $url = $url ?? config('speedtest.preflight.get_external_ip_url'); + try { $response = Http::retry(3, 100) ->timeout(5) - ->get(url: 'https://icanhazip.com/'); + ->get(url: $url); } catch (Throwable $e) { - Log::error('Failed to fetch external IP address.', [$e->getMessage()]); + $message = sprintf('Failed to fetch external IP address from "%s". See the logs for more details.', $url); + + Log::error($message, [$e->getMessage()]); - return false; + return [ + 'ok' => false, + 'body' => $message, + ]; } - return Str::trim($response->body()); + return [ + 'ok' => $response->ok(), + 'body' => Str::of($response->body())->trim()->toString(), + ]; } } diff --git a/app/Jobs/Ookla/SkipSpeedtestJob.php b/app/Jobs/Ookla/SkipSpeedtestJob.php index 13c444133..12c276fc1 100644 --- a/app/Jobs/Ookla/SkipSpeedtestJob.php +++ b/app/Jobs/Ookla/SkipSpeedtestJob.php @@ -4,6 +4,7 @@ use App\Actions\GetExternalIpAddress; use App\Enums\ResultStatus; +use App\Events\SpeedtestFailed; use App\Events\SpeedtestSkipped; use App\Helpers\Network; use App\Models\Result; @@ -47,8 +48,23 @@ public function handle(): void $externalIp = GetExternalIpAddress::run(); + if ($externalIp['ok'] === false) { + $this->result->update([ + 'data->type' => 'log', + 'data->level' => 'error', + 'data->message' => $externalIp['body'], + 'status' => ResultStatus::Failed, + ]); + + SpeedtestFailed::dispatch($this->result); + + $this->batch()->cancel(); + + return; + } + $shouldSkip = $this->shouldSkip( - externalIp: $externalIp, + externalIp: $externalIp['body'], ); if ($shouldSkip === false) { diff --git a/config/speedtest.php b/config/speedtest.php index ec4e255a3..937125766 100644 --- a/config/speedtest.php +++ b/config/speedtest.php @@ -29,7 +29,11 @@ 'interface' => env('SPEEDTEST_INTERFACE'), - 'checkinternet_url' => env('SPEEDTEST_CHECKINTERNET_URL', 'https://icanhazip.com'), + 'preflight' => [ + 'get_external_ip_url' => env('SPEEDTEST_CHECKINTERNET_URL') ?? env('SPEEDTEST_GET_EXTERNAL_IP_URL', 'https://icanhazip.com'), + ], + + 'checkinternet_url' => env('SPEEDTEST_CHECKINTERNET_URL'), // ! DEPRECATED, use preflight.get_external_ip_url instead /** * IP filtering settings. From 03e02b6eb900b478b297868b48c8cb52c92f8613 Mon Sep 17 00:00:00 2001 From: Alex Justesen Date: Tue, 16 Dec 2025 09:24:42 -0500 Subject: [PATCH 5/7] check for internet using ping (#2556) Co-authored-by: Alex Justesen <1144087+alexjustesen@users.noreply.github.com> --- app/Actions/CheckInternetConnection.php | 33 -------- app/Actions/GetExternalIpAddress.php | 2 +- app/Actions/PingHostname.php | 27 ++++++ app/Jobs/CheckForInternetConnectionJob.php | 10 ++- composer.json | 2 +- composer.lock | 98 +++++++++++++--------- config/speedtest.php | 5 +- 7 files changed, 98 insertions(+), 79 deletions(-) delete mode 100644 app/Actions/CheckInternetConnection.php create mode 100644 app/Actions/PingHostname.php diff --git a/app/Actions/CheckInternetConnection.php b/app/Actions/CheckInternetConnection.php deleted file mode 100644 index 22e26f78d..000000000 --- a/app/Actions/CheckInternetConnection.php +++ /dev/null @@ -1,33 +0,0 @@ -timeout(5) - ->get(config('speedtest.checkinternet_url')); - - if (! $response->ok()) { - return false; - } - - return Str::trim($response->body()); - } catch (Throwable $e) { - Log::error('Failed to connect to the internet.', [$e->getMessage()]); - - return false; - } - } -} diff --git a/app/Actions/GetExternalIpAddress.php b/app/Actions/GetExternalIpAddress.php index 48417c1f1..d47cc0a6f 100644 --- a/app/Actions/GetExternalIpAddress.php +++ b/app/Actions/GetExternalIpAddress.php @@ -14,7 +14,7 @@ class GetExternalIpAddress public function handle(?string $url = null): array { - $url = $url ?? config('speedtest.preflight.get_external_ip_url'); + $url = $url ?? config('speedtest.preflight.external_ip_url'); try { $response = Http::retry(3, 100) diff --git a/app/Actions/PingHostname.php b/app/Actions/PingHostname.php new file mode 100644 index 000000000..7707f1abe --- /dev/null +++ b/app/Actions/PingHostname.php @@ -0,0 +1,27 @@ +run(); + + return $ping; + } +} diff --git a/app/Jobs/CheckForInternetConnectionJob.php b/app/Jobs/CheckForInternetConnectionJob.php index 37c5e6f04..c0f39a61f 100644 --- a/app/Jobs/CheckForInternetConnectionJob.php +++ b/app/Jobs/CheckForInternetConnectionJob.php @@ -2,7 +2,7 @@ namespace App\Jobs; -use App\Actions\CheckInternetConnection; +use App\Actions\PingHostname; use App\Enums\ResultStatus; use App\Events\SpeedtestChecking; use App\Events\SpeedtestFailed; @@ -44,14 +44,18 @@ public function handle(): void SpeedtestChecking::dispatch($this->result); - if (CheckInternetConnection::run() !== false) { + $ping = PingHostname::run(); + + if ($ping->isSuccess()) { return; } + $message = sprintf('Failed to connected to hostname "%s". Error received "%s".', $ping->getHost(), $ping->error()?->value); + $this->result->update([ 'data->type' => 'log', 'data->level' => 'error', - 'data->message' => 'Failed to connect to the internet.', + 'data->message' => $message, 'status' => ResultStatus::Failed, ]); diff --git a/composer.json b/composer.json index 77cf9452a..4fe2349e4 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,6 @@ "dragonmantank/cron-expression": "^3.6.0", "filament/filament": "4.1.0", "filament/spatie-laravel-settings-plugin": "^4.1", - "geerlingguy/ping": "^1.2.1", "influxdata/influxdb-client-php": "^3.8", "laravel-notification-channels/telegram": "^6.0", "laravel/framework": "^12.41.1", @@ -36,6 +35,7 @@ "spatie/laravel-query-builder": "^6.3.6", "spatie/laravel-settings": "^3.6.0", "spatie/laravel-webhook-server": "^3.8.3", + "spatie/ping": "^1.1.1", "zircote/swagger-php": "^5.7.6" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 23ff73cb5..6c492d7d9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "405d221f03e4de1894ce759a9e751448", + "content-hash": "374762e19dbfc99374c14f3f12a4ae3e", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -1779,43 +1779,6 @@ ], "time": "2025-12-03T09:33:47+00:00" }, - { - "name": "geerlingguy/ping", - "version": "1.2.1", - "source": { - "type": "git", - "url": "https://github.com/geerlingguy/Ping.git", - "reference": "e0206326e23c99e3e8820e24705f8ca517adff93" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/geerlingguy/Ping/zipball/e0206326e23c99e3e8820e24705f8ca517adff93", - "reference": "e0206326e23c99e3e8820e24705f8ca517adff93", - "shasum": "" - }, - "type": "library", - "autoload": { - "classmap": [ - "JJG/Ping.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jeff Geerling", - "email": "jeff@jeffgeerling.com" - } - ], - "description": "A PHP class to ping hosts.", - "support": { - "issues": "https://github.com/geerlingguy/Ping/issues", - "source": "https://github.com/geerlingguy/Ping/tree/1.2.1" - }, - "time": "2019-07-29T21:54:12+00:00" - }, { "name": "graham-campbell/result-type", "version": "v1.1.3", @@ -6919,6 +6882,65 @@ ], "time": "2025-02-14T12:55:41+00:00" }, + { + "name": "spatie/ping", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/ping.git", + "reference": "6123a6209148e8919f58121d256f43c75856ab35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/ping/zipball/6123a6209148e8919f58121d256f43c75856ab35", + "reference": "6123a6209148e8919f58121d256f43c75856ab35", + "shasum": "" + }, + "require": { + "php": "^8.4", + "symfony/process": "^7.0" + }, + "require-dev": { + "laravel/pint": "^1.0", + "pestphp/pest": "^3.0", + "spatie/pest-expectations": "^1.13", + "spatie/ray": "^1.28" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\Ping\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "role": "Developer" + } + ], + "description": "Run an ICMP ping and get structured results", + "homepage": "https://github.com/spatie/ping", + "keywords": [ + "ping", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/ping/issues", + "source": "https://github.com/spatie/ping/tree/1.1.1" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2025-08-12T20:58:12+00:00" + }, { "name": "spatie/shiki-php", "version": "2.3.2", diff --git a/config/speedtest.php b/config/speedtest.php index 937125766..204bf21ec 100644 --- a/config/speedtest.php +++ b/config/speedtest.php @@ -30,11 +30,10 @@ 'interface' => env('SPEEDTEST_INTERFACE'), 'preflight' => [ - 'get_external_ip_url' => env('SPEEDTEST_CHECKINTERNET_URL') ?? env('SPEEDTEST_GET_EXTERNAL_IP_URL', 'https://icanhazip.com'), + 'external_ip_url' => env('SPEEDTEST_CHECKINTERNET_URL') ?? env('SPEEDTEST_EXTERNAL_IP_URL', 'https://icanhazip.com'), + 'internet_check_hostname' => env('SPEEDTEST_CHECKINTERNET_URL') ?? env('SPEEDTEST_INTERNET_CHECK_HOSTNAME', 'icanhazip.com'), ], - 'checkinternet_url' => env('SPEEDTEST_CHECKINTERNET_URL'), // ! DEPRECATED, use preflight.get_external_ip_url instead - /** * IP filtering settings. */ From c7c467ff8a08f6ea2aeb0225186b2a92eb199b2c Mon Sep 17 00:00:00 2001 From: Alex Justesen Date: Tue, 16 Dec 2025 09:32:52 -0500 Subject: [PATCH 6/7] move skip IPs configuration to preflight settings (#2557) Co-authored-by: Alex Justesen <1144087+alexjustesen@users.noreply.github.com> --- app/Jobs/Ookla/SkipSpeedtestJob.php | 4 ++-- config/speedtest.php | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/Jobs/Ookla/SkipSpeedtestJob.php b/app/Jobs/Ookla/SkipSpeedtestJob.php index 12c276fc1..948fe792d 100644 --- a/app/Jobs/Ookla/SkipSpeedtestJob.php +++ b/app/Jobs/Ookla/SkipSpeedtestJob.php @@ -92,11 +92,11 @@ private function shouldSkip(string $externalIp): bool|string $skipIPs = array_filter( array_map( 'trim', - explode(',', config('speedtest.skip_ips')), + explode(',', config('speedtest.preflight.skip_ips')), ), ); - if (count($skipIPs) < 1) { + if (empty($skipIPs)) { return false; } diff --git a/config/speedtest.php b/config/speedtest.php index 204bf21ec..48dc7d083 100644 --- a/config/speedtest.php +++ b/config/speedtest.php @@ -32,6 +32,7 @@ 'preflight' => [ 'external_ip_url' => env('SPEEDTEST_CHECKINTERNET_URL') ?? env('SPEEDTEST_EXTERNAL_IP_URL', 'https://icanhazip.com'), 'internet_check_hostname' => env('SPEEDTEST_CHECKINTERNET_URL') ?? env('SPEEDTEST_INTERNET_CHECK_HOSTNAME', 'icanhazip.com'), + 'skip_ips' => env('SPEEDTEST_SKIP_IPS'), ], /** @@ -39,8 +40,6 @@ */ 'allowed_ips' => env('ALLOWED_IPS'), - 'skip_ips' => env('SPEEDTEST_SKIP_IPS', ''), - /** * Threshold settings. */ From cd0915f601371d822c89f52972dc9887e99085cf Mon Sep 17 00:00:00 2001 From: Alex Justesen Date: Tue, 16 Dec 2025 09:47:48 -0500 Subject: [PATCH 7/7] Release v1.13.0 (#2558) Co-authored-by: Alex Justesen <1144087+alexjustesen@users.noreply.github.com> --- config/speedtest.php | 4 ++-- resources/views/filament/pages/dashboard.blade.php | 3 +++ resources/views/livewire/latest-result-stats.blade.php | 8 ++++---- resources/views/livewire/platform-stats.blade.php | 6 +++--- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/config/speedtest.php b/config/speedtest.php index 48dc7d083..b68a6a040 100644 --- a/config/speedtest.php +++ b/config/speedtest.php @@ -6,9 +6,9 @@ /** * General settings. */ - 'build_date' => Carbon::parse('2025-12-15'), + 'build_date' => Carbon::parse('2025-12-16'), - 'build_version' => 'v1.12.4', + 'build_version' => 'v1.13.0', 'content_width' => env('CONTENT_WIDTH', '7xl'), diff --git a/resources/views/filament/pages/dashboard.blade.php b/resources/views/filament/pages/dashboard.blade.php index 42a849976..b92cde2a9 100644 --- a/resources/views/filament/pages/dashboard.blade.php +++ b/resources/views/filament/pages/dashboard.blade.php @@ -11,6 +11,7 @@ class="col-span-1" icon="tabler-book" icon-size="md" + :compact="true" > {{ __('general.documentation') }} @@ -35,6 +36,7 @@ class="col-span-1" class="col-span-1" icon="tabler-cash-banknote-heart" icon-size="md" + :compact="true" > {{ __('general.donations') }} @@ -59,6 +61,7 @@ class="col-span-1" class="col-span-1" icon="tabler-brand-github" icon-size="md" + :compact="true" > {{ __('general.speedtest_tracker') }} diff --git a/resources/views/livewire/latest-result-stats.blade.php b/resources/views/livewire/latest-result-stats.blade.php index a3cc2b708..c1c69eeec 100644 --- a/resources/views/livewire/latest-result-stats.blade.php +++ b/resources/views/livewire/latest-result-stats.blade.php @@ -24,7 +24,7 @@ - + {{ __('general.download') }} @@ -63,7 +63,7 @@

- + {{ __('general.upload') }} @@ -102,7 +102,7 @@

- + {{ __('general.ping') }} @@ -135,7 +135,7 @@

- + {{ __('results.packet_loss') }} diff --git a/resources/views/livewire/platform-stats.blade.php b/resources/views/livewire/platform-stats.blade.php index 567c1f31a..f8f149e6e 100644 --- a/resources/views/livewire/platform-stats.blade.php +++ b/resources/views/livewire/platform-stats.blade.php @@ -23,7 +23,7 @@ --}} - + Total tests @@ -31,7 +31,7 @@

{{ $this->platformStats['total'] }}

- + Total completed tests @@ -39,7 +39,7 @@

{{ $this->platformStats['completed'] }}

- + Total failed tests