Skip to content

Commit

Permalink
🐛 improve error handling with telegram api
Browse files Browse the repository at this point in the history
fixes #2815
  • Loading branch information
MrKrisKrisu committed Aug 7, 2024
1 parent fbe5608 commit 024e01e
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 22 deletions.
11 changes: 11 additions & 0 deletions app/Exceptions/TelegramException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace App\Exceptions;

use Exception;

class TelegramException extends Exception
{
//
}

6 changes: 3 additions & 3 deletions app/Http/Controllers/Backend/EventController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

namespace App\Http\Controllers\Backend;

use App\Exceptions\TelegramException;
use App\Http\Controllers\Controller;
use App\Models\EventSuggestion;
use App\Models\Station;
use App\Models\User;
use App\Services\TelegramService;
use Carbon\Carbon;
use Exception;

abstract class EventController extends Controller
{
Expand Down Expand Up @@ -54,8 +54,8 @@ public static function suggestEvent(
])
);
}
} catch (Exception $e) {
report($e);
} catch (TelegramException $exception) {
report($exception);
}

return $eventSuggestion;
Expand Down
21 changes: 13 additions & 8 deletions app/Http/Controllers/Frontend/Admin/EventController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use App\Enum\EventRejectionReason;
use App\Exceptions\HafasException;
use App\Exceptions\TelegramException;
use App\Http\Controllers\Backend\Admin\EventController as AdminEventBackend;
use App\Http\Controllers\Controller;
use App\Http\Controllers\HafasController;
Expand Down Expand Up @@ -181,14 +182,18 @@ public function acceptSuggestion(Request $request): RedirectResponse {

$eventSuggestion->update(['processed' => true]);
if (!App::runningUnitTests() && TelegramService::isAdminActive()) {
TelegramService::admin()->sendMessage(
strtr("<b>Event suggestion accepted</b>" . PHP_EOL .
"Title: :name" . PHP_EOL
. "Accepting user: :username" . PHP_EOL, [
':name' => $eventSuggestion->name,
':username' => auth()->user()->username,
])
);
try {
TelegramService::admin()->sendMessage(
strtr("<b>Event suggestion accepted</b>" . PHP_EOL .
"Title: :name" . PHP_EOL
. "Accepting user: :username" . PHP_EOL, [
':name' => $eventSuggestion->name,
':username' => auth()->user()->username,
])
);
} catch (TelegramException $exception) {
report($exception);
}
}

$eventSuggestion->user->notify(new EventSuggestionProcessed($eventSuggestion, $event));
Expand Down
15 changes: 10 additions & 5 deletions app/Observers/ReportObserver.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\Observers;

use App\Enum\Report\ReportStatus;
use App\Exceptions\TelegramException;
use App\Models\Report;
use App\Services\TelegramService;
use Illuminate\Support\Facades\App;
Expand All @@ -15,11 +16,15 @@ public function created(Report $report): void {
if (App::runningUnitTests() || !TelegramService::isAdminActive()) {
return;
}
$telegramMessageId = TelegramService::admin()->sendMessage("<b>🚨 New Report for " . $report->subject_type . "</b>" . PHP_EOL
. "Reason: " . $report->reason?->value . PHP_EOL
. "Description: " . ($report->description ?? 'None') . PHP_EOL
. "View Report: " . config('app.url') . "/admin/reports/" . $report->id . PHP_EOL);
$report->update(['admin_notification_id' => $telegramMessageId]);
try {
$telegramMessageId = TelegramService::admin()->sendMessage("<b>🚨 New Report for " . $report->subject_type . "</b>" . PHP_EOL
. "Reason: " . $report->reason?->value . PHP_EOL
. "Description: " . ($report->description ?? 'None') . PHP_EOL
. "View Report: " . config('app.url') . "/admin/reports/" . $report->id . PHP_EOL);
$report->update(['admin_notification_id' => $telegramMessageId]);
} catch (TelegramException $exception) {
report($exception);
}
}

public function updated(Report $report): void {
Expand Down
19 changes: 14 additions & 5 deletions app/Services/TelegramService.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@

namespace App\Services;

use App\Exceptions\TelegramException;
use Illuminate\Support\Facades\Http;

class TelegramService
class TelegramService
{

const TELEGRAM_API_URL = 'https://api.telegram.org/bot';

private string $chatId;
private string $token;
public readonly string $chatId;
private readonly string $token;

public function __construct(string $chatId, string $token) {
$this->chatId = $chatId;
Expand All @@ -26,21 +27,29 @@ public static function admin(): self {
}

/**
* @param string $text
* @param string $parseMode
*
* @return int Telegram Message ID
* @throws TelegramException
*/
public function sendMessage(string $text, string $parseMode = 'HTML'): int {
$response = Http::post(self::TELEGRAM_API_URL . $this->token . '/sendMessage', [
'chat_id' => $this->chatId,
'text' => $text,
'parse_mode' => $parseMode,
]);
if (!$response->ok()) {
throw new TelegramException('Telegram API error: ' . $response->body());
}
return $response->json('result.message_id');
}

public function deleteMessage(int $messageId): void {
Http::post(self::TELEGRAM_API_URL . $this->token . '/deleteMessage', [
public function deleteMessage(int $messageId): bool {
$response = Http::post(self::TELEGRAM_API_URL . $this->token . '/deleteMessage', [
'chat_id' => $this->chatId,
'message_id' => $messageId,
]);
return $response->ok();
}
}
54 changes: 54 additions & 0 deletions tests/Feature/TelegramServiceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace Tests\Feature;

use App\Exceptions\TelegramException;
use App\Services\TelegramService;
use Illuminate\Support\Facades\Http;
use Tests\FeatureTestCase;

class TelegramServiceTest extends FeatureTestCase
{

private const CHAT_ID = '123456789';
private const TOKEN = '123456789:ABC-DEF1234ghIkl-zyx57W2v1u123ew11';

public function testSendTelegramMessage(): void {
Http::fake(['https://api.telegram.org/bot' . self::TOKEN . '/sendMessage' => Http::response(['result' => ['message_id' => 123]])]);
$telegramService = new TelegramService(self::CHAT_ID, self::TOKEN);
$messageId = $telegramService->sendMessage('Hello, World!');
$this->assertIsInt($messageId);
}

public function testSendTelegramMessageWithWrongCredentials(): void {
Http::fake([
'https://api.telegram.org/bot' . self::TOKEN . '/sendMessage' => Http::response(
body: [
'ok' => false,
'error_code' => 401,
'description' => 'Unauthorized',
],
status: 401
)
]);
$telegramService = new TelegramService(self::CHAT_ID, self::TOKEN);
$this->expectException(TelegramException::class);
$telegramService->sendMessage('Hello, World!');
}

public function testDeleteTelegramMessage(): void {
Http::fake(['https://api.telegram.org/bot' . self::TOKEN . '/deleteMessage' => Http::response()]);
$telegramService = new TelegramService(self::CHAT_ID, self::TOKEN);
$this->assertTrue($telegramService->deleteMessage(123));
}

public function testAdminChatSelector(): void {
config(['services.telegram.admin.active' => true]);
$this->assertTrue(TelegramService::isAdminActive());

config(['services.telegram.admin.chat_id' => self::CHAT_ID]);
config(['services.telegram.admin.token' => self::TOKEN]);
$telegramService = TelegramService::admin();
$this->assertEquals(self::CHAT_ID, $telegramService->chatId);
}
}
8 changes: 7 additions & 1 deletion tests/FeatureTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ abstract class FeatureTestCase extends BaseTestCase

protected function setUp(): void {
parent::setUp();

if (!in_array('RefreshDatabase', class_uses($this), true)) {
//if class doesn't use RefreshDatabase trait, skip the migration and seeding
return;
}

$this->artisan('db:seed --class=Database\\\\Seeders\\\\Constants\\\\PermissionSeeder');
$this->artisan('db:seed --class=Database\\\\Seeders\\\\PrivacyAgreementSeeder');
}
Expand Down Expand Up @@ -171,7 +177,7 @@ public function createOAuthClient(User $user, bool $confidential): OAuthClient {
}

public function createWebhook(User $user, OAuthClient $client, array $events): Webhook {
$events = array_map(function ($event) {
$events = array_map(function($event) {
return $event->value;
}, $events);
$request = WebhookController::createWebhookRequest($user, $client, 'stub', "https://example.com", $events);
Expand Down

0 comments on commit 024e01e

Please sign in to comment.