From 4c28d3868ca2b2131b6ac5fd9589fa2bdef02fb5 Mon Sep 17 00:00:00 2001 From: machka-pasla Date: Sat, 9 Aug 2025 09:43:02 +0300 Subject: [PATCH 1/3] Implement validation for broadcast message input in admin handler - Updated the broadcast message handler to trim whitespace from the input text and added a check for empty messages. - If the message is empty, an error response is sent to prompt the user for valid input, enhancing user experience and preventing empty broadcasts. --- bot/handlers/admin/broadcast.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/bot/handlers/admin/broadcast.py b/bot/handlers/admin/broadcast.py index 7c701b3..aed5146 100644 --- a/bot/handlers/admin/broadcast.py +++ b/bot/handlers/admin/broadcast.py @@ -58,7 +58,7 @@ async def broadcast_message_prompt_handler( await state.set_state(AdminStates.waiting_for_broadcast_message) -@router.message(AdminStates.waiting_for_broadcast_message, F.text) +@router.message(AdminStates.waiting_for_broadcast_message) async def process_broadcast_message_handler( message: types.Message, state: FSMContext, @@ -76,9 +76,14 @@ async def process_broadcast_message_handler( _ = lambda key, **kwargs: i18n.gettext(current_lang, key, **kwargs) # Сохраняем в state исходный текст и entities - text = message.text or message.caption or "" + text = (message.text or message.caption or "").strip() entities = message.entities or message.caption_entities or [] + # Если текст пустой (например, прислали стикер/фото без подписи) — просим ввести текст + if not text: + await message.answer(_("admin_broadcast_error_no_message")) + return + await state.update_data( broadcast_text=text, broadcast_entities=entities, From 8eb5daada53c5c71c330f46ca4619026c418b4b3 Mon Sep 17 00:00:00 2001 From: machka-pasla Date: Sat, 9 Aug 2025 09:46:33 +0300 Subject: [PATCH 2/3] Add HTML validation for broadcast messages in admin handler - Implemented a preliminary check for HTML validity in broadcast messages by attempting to send a test message before processing. - Added error handling for invalid HTML, providing user feedback in both English and Russian. - Updated localization files to include new error messages for invalid HTML input. --- bot/handlers/admin/broadcast.py | 29 ++++++++++++++++++++++++++++- locales/en.json | 2 ++ locales/ru.json | 1 + 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/bot/handlers/admin/broadcast.py b/bot/handlers/admin/broadcast.py index aed5146..6a56cc7 100644 --- a/bot/handlers/admin/broadcast.py +++ b/bot/handlers/admin/broadcast.py @@ -1,7 +1,7 @@ import logging import asyncio from aiogram import Router, F, types, Bot -from aiogram.exceptions import TelegramRetryAfter +from aiogram.exceptions import TelegramRetryAfter, TelegramBadRequest from aiogram.fsm.context import FSMContext from typing import Optional @@ -65,6 +65,7 @@ async def process_broadcast_message_handler( i18n_data: dict, settings: Settings, session: AsyncSession, + bot: Bot, ): current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE) i18n: Optional[JsonI18n] = i18n_data.get("i18n_instance") @@ -84,6 +85,31 @@ async def process_broadcast_message_handler( await message.answer(_("admin_broadcast_error_no_message")) return + # Предварительная проверка HTML: попробуем отправить и сразу удалить + # Если HTML некорректный, Telegram вернёт ошибку парсинга + try: + test_msg = await bot.send_message( + chat_id=message.chat.id, + text=text, + parse_mode="HTML", + disable_web_page_preview=True, + disable_notification=True, + ) + # Удалим тестовое сообщение + try: + await bot.delete_message(chat_id=message.chat.id, message_id=test_msg.message_id) + except Exception: + pass + except TelegramBadRequest as e: + await message.answer( + _( + "admin_broadcast_invalid_html", + default="❌ Некорректный HTML в сообщении. Пожалуйста, отправьте корректный HTML (поддерживаются теги Telegram) или уберите теги.\nОшибка: {error}", + error=str(e), + ) + ) + return + await state.update_data( broadcast_text=text, broadcast_entities=entities, @@ -190,6 +216,7 @@ async def confirm_broadcast_callback_handler( chat_id=uid, text=text, entities=entities, + parse_mode=None, # переопределяем глобальный HTML, т.к. используем entities ) sent_count += 1 diff --git a/locales/en.json b/locales/en.json index a7e77f4..071301c 100644 --- a/locales/en.json +++ b/locales/en.json @@ -165,6 +165,8 @@ "admin_broadcast_cancelled_alert": "Broadcast cancelled!", "admin_broadcast_cancelled_nav_back": "Broadcast cancelled. You are returned to the admin panel.", + "admin_broadcast_invalid_html": "❌ Invalid HTML in message. Please send valid HTML (Telegram-supported tags) or remove tags.", + "admin_promo_create_prompt": "Enter promo details in the format: CODE BONUS_DAYS MAX_USES [VALIDITY_DAYS]\nExample: {example_format}\n(Validity is optional; default is indefinite)", "admin_promo_invalid_format": "Invalid format. Please use: CODE BONUS_DAYS MAX_USES [VALIDITY_DAYS]", "admin_promo_invalid_code_format": "Code must be 3–30 alphanumeric characters.", diff --git a/locales/ru.json b/locales/ru.json index 34063e2..e66e70a 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -268,6 +268,7 @@ "sync_critical_error": "❌ Критическая ошибка синхронизации", "no_errors_placeholder": "нет", "admin_sync_initiated_from_panel": "Синхронизация запущена...", + "admin_broadcast_invalid_html": "❌ Некорректный HTML в сообщении. Пожалуйста, отправьте корректный HTML (поддерживаются теги Telegram) или уберите теги.", "admin_panel_user_creation_failed": "❌ Не удалось создать пользователя на панели для TG ID {user_id}. Панель недоступна?", "error_displaying_logs_too_long": "Ошибка: логи слишком длинные для отображения одним сообщением. Попробуйте найти логи по конкретному пользователю.", "error_displaying_statistics": "Ошибка отображения статистики.", From 4e58fda4a5ebbcb4658045f5dd84c0d27537e47a Mon Sep 17 00:00:00 2001 From: machka-pasla Date: Sat, 9 Aug 2025 09:51:21 +0300 Subject: [PATCH 3/3] Update broadcast message handler to enforce HTML parsing and disable web page previews - Changed the parse_mode to "HTML" for broadcast messages to ensure proper formatting. - Added disable_web_page_preview option to enhance message presentation and control over content display. --- bot/handlers/admin/broadcast.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bot/handlers/admin/broadcast.py b/bot/handlers/admin/broadcast.py index 6a56cc7..9b856f1 100644 --- a/bot/handlers/admin/broadcast.py +++ b/bot/handlers/admin/broadcast.py @@ -215,8 +215,8 @@ async def confirm_broadcast_callback_handler( await queue_manager.send_message( chat_id=uid, text=text, - entities=entities, - parse_mode=None, # переопределяем глобальный HTML, т.к. используем entities + parse_mode="HTML", + disable_web_page_preview=True, ) sent_count += 1