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