fix(telegram): show API errors when sending test notifications (#12219)

This commit is contained in:
Andras Bacsai
2026-10-19 21:17:35 +02:00
committed by GitHub
parent 36f36daec9
commit 3acfa6b9a6
3 changed files with 85 additions and 6 deletions
+15 -5
View File
@@ -8,6 +8,7 @@ use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Http\Client\Response;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Http;
@@ -49,6 +50,19 @@ class SendMessageToTelegramJob implements ShouldBeEncrypted, ShouldQueue
* Execute the job.
*/
public function handle(): void
{
$response = $this->sendMessage();
// 401: invalid bot token, 403: the bot was blocked or removed from the chat, 400 "chat not found": wrong chat ID.
$isConfigurationError = in_array($response->status(), [401, 403], true)
|| ($response->status() === 400 && Str::contains((string) $response->json('description'), 'chat not found', true));
$this->handleNotificationResponse($response, 'Telegram', $isConfigurationError);
}
/**
* Call the Telegram sendMessage API and return its response without handling errors.
*/
public function sendMessage(): Response
{
$url = 'https://api.telegram.org/bot'.$this->token.'/sendMessage';
$inlineButtons = [];
@@ -78,11 +92,7 @@ class SendMessageToTelegramJob implements ShouldBeEncrypted, ShouldQueue
if ($this->threadId) {
$payload['message_thread_id'] = $this->threadId;
}
$response = Http::post($url, $payload);
// 401: invalid bot token, 403: the bot was blocked or removed from the chat, 400 "chat not found": wrong chat ID.
$isConfigurationError = in_array($response->status(), [401, 403], true)
|| ($response->status() === 400 && Str::contains((string) $response->json('description'), 'chat not found', true));
$this->handleNotificationResponse($response, 'Telegram', $isConfigurationError);
return Http::post($url, $payload);
}
}
+18 -1
View File
@@ -2,6 +2,7 @@
namespace App\Livewire\Notifications;
use App\Jobs\SendMessageToTelegramJob;
use App\Livewire\Notifications\Concerns\TogglesNotificationEvents;
use App\Models\Team;
use App\Models\TelegramNotificationSettings;
@@ -306,7 +307,23 @@ class Telegram extends Component
{
try {
$this->authorize('sendTest', $this->settings);
$this->team->notify(new Test(channel: 'telegram'));
// Send synchronously so that the user sees the error from Telegram (a queued test always "succeeds").
$message = (new Test(channel: 'telegram'))->toTelegram();
$response = (new SendMessageToTelegramJob(
text: $message['message'],
buttons: $message['buttons'],
token: (string) $this->settings->telegram_token,
chatId: (string) $this->settings->telegram_chat_id,
))->sendMessage();
if ($response->failed()) {
$reason = $response->json('description') ?? "HTTP {$response->status()}";
$this->dispatch('error', 'Telegram rejected the test notification.', e($reason));
return;
}
$this->dispatch('success', 'Test notification sent.');
} catch (\Throwable $e) {
return handleError($e, $this);
@@ -0,0 +1,52 @@
<?php
use App\Livewire\Notifications\Telegram as TelegramNotification;
use App\Models\InstanceSettings;
use App\Models\Team;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Queue;
use Livewire\Livewire;
uses(RefreshDatabase::class);
beforeEach(function () {
InstanceSettings::unguarded(fn () => InstanceSettings::updateOrCreate(['id' => 0], ['id' => 0]));
$this->team = Team::factory()->create();
$this->team->telegramNotificationSettings->update([
'telegram_enabled' => true,
'telegram_token' => 'bot-token',
'telegram_chat_id' => '123456',
]);
$admin = User::factory()->create();
$admin->teams()->attach($this->team, ['role' => 'admin']);
$this->actingAs($admin);
session(['currentTeam' => $this->team]);
Queue::fake();
});
it('shows the error from Telegram when the test notification is rejected', function () {
Http::fake(['api.telegram.org/*' => Http::response(['ok' => false, 'description' => 'Bad Request: chat not found'], 400)]);
Livewire::test(TelegramNotification::class)
->call('sendTestNotification')
->assertDispatched('error', 'Telegram rejected the test notification.', 'Bad Request: chat not found')
->assertNotDispatched('success');
Queue::assertNothingPushed();
});
it('sends the test notification synchronously and reports success', function () {
Http::fake(['api.telegram.org/*' => Http::response(['ok' => true, 'result' => []])]);
Livewire::test(TelegramNotification::class)
->call('sendTestNotification')
->assertDispatched('success', 'Test notification sent.');
Http::assertSent(fn ($request) => $request->url() === 'https://api.telegram.org/botbot-token/sendMessage'
&& $request['chat_id'] === '123456');
Queue::assertNothingPushed();
});