From 54cc4862b29c441d3c9a7f7847e9a6a411a974f9 Mon Sep 17 00:00:00 2001
From: Leonid Pershin
Date: Fri, 31 Jul 2026 08:07:49 +0300
Subject: [PATCH] Refactor Telegram API and enhance TelegramPanel form handling
Updated the TelegramApi class to improve URL construction for API calls by introducing a new MethodUrl method, ensuring proper handling of bot tokens. Refactored the TelegramPanel component to use a form for input fields, allowing for better user experience and submission handling. Adjusted password input fields to use 'new-password' for improved security. These changes aim to enhance the functionality and usability of the Telegram integration.
---
.../Notifications/TelegramApi.cs | 11 ++++++++--
.../Notifications/TelegramApiUrlTests.cs | 22 +++++++++++++++++++
.../features/admin/telegram/TelegramPanel.tsx | 18 ++++++++++-----
3 files changed, 44 insertions(+), 7 deletions(-)
create mode 100644 backend/tests/TeleWave.Application.Tests/Notifications/TelegramApiUrlTests.cs
diff --git a/backend/src/TeleWave.Infrastructure/Notifications/TelegramApi.cs b/backend/src/TeleWave.Infrastructure/Notifications/TelegramApi.cs
index 8f122b6..984a177 100644
--- a/backend/src/TeleWave.Infrastructure/Notifications/TelegramApi.cs
+++ b/backend/src/TeleWave.Infrastructure/Notifications/TelegramApi.cs
@@ -185,11 +185,10 @@ public sealed class TelegramApi(ILogger logger) : ITelegramApi
using var handler = CreateHandler(settings);
using var client = new HttpClient(handler)
{
- BaseAddress = new Uri("https://api.telegram.org/"),
Timeout = timeout ?? TimeSpan.FromSeconds(30),
};
- var url = $"bot{settings.BotToken}/{method}";
+ var url = MethodUrl(settings.BotToken, method);
using var response = payload is null
? await client.PostAsync(url, null, cancellationToken)
: await client.PostAsJsonAsync(url, payload, Json, cancellationToken);
@@ -205,6 +204,14 @@ public sealed class TelegramApi(ILogger logger) : ITelegramApi
return await response.Content.ReadFromJsonAsync(Json, cancellationToken);
}
+ ///
+ /// Адрес метода — абсолютным, а не относительным к BaseAddress. Токен содержит двоеточие
+ /// («8613942817:AAH…»), и как относительный путь «bot8613942817:AAH…/getUpdates» разбирается
+ /// в схему «bot8613942817»: запрос падает с «scheme is not supported», не дойдя до сети.
+ ///
+ public static Uri MethodUrl(string token, string method) =>
+ new($"https://api.telegram.org/bot{token}/{method}");
+
///
/// Транспорт с прокси, если он задан. SOCKS5 поддерживает сам начиная
/// с .NET 6 — достаточно схемы в адресе, отдельной библиотеки не нужно.
diff --git a/backend/tests/TeleWave.Application.Tests/Notifications/TelegramApiUrlTests.cs b/backend/tests/TeleWave.Application.Tests/Notifications/TelegramApiUrlTests.cs
new file mode 100644
index 0000000..0612434
--- /dev/null
+++ b/backend/tests/TeleWave.Application.Tests/Notifications/TelegramApiUrlTests.cs
@@ -0,0 +1,22 @@
+using TeleWave.Infrastructure.Notifications;
+using Xunit;
+
+namespace TeleWave.Application.Tests.Notifications;
+
+///
+/// Адрес метода Bot API. Отдельный тест на одну строку — потому что ошибка в ней не видна ни при
+/// сборке, ни в юнит-тестах логики: токен содержит двоеточие, и относительный путь превращается
+/// в «схему» ещё до обращения к сети.
+///
+public class TelegramApiUrlTests
+{
+ [Fact]
+ public void MethodUrl_KeepsTokenInPath_AndStaysHttps()
+ {
+ var url = TelegramApi.MethodUrl("8613942817:AAHrandom-part_x", "getUpdates");
+
+ Assert.Equal("https", url.Scheme);
+ Assert.Equal("api.telegram.org", url.Host);
+ Assert.Equal("/bot8613942817:AAHrandom-part_x/getUpdates", url.AbsolutePath);
+ }
+}
diff --git a/frontend/src/features/admin/telegram/TelegramPanel.tsx b/frontend/src/features/admin/telegram/TelegramPanel.tsx
index 825f938..8455dd2 100644
--- a/frontend/src/features/admin/telegram/TelegramPanel.tsx
+++ b/frontend/src/features/admin/telegram/TelegramPanel.tsx
@@ -101,7 +101,15 @@ export function TelegramPanel() {
)}
-
+ {/* Форма, а не просто панель: поле пароля вне
+