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.
This commit is contained in:
machka-pasla
2025-08-09 09:46:33 +03:00
parent 4c28d3868c
commit 8eb5daada5
3 changed files with 31 additions and 1 deletions
+28 -1
View File
@@ -1,7 +1,7 @@
import logging import logging
import asyncio import asyncio
from aiogram import Router, F, types, Bot 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 aiogram.fsm.context import FSMContext
from typing import Optional from typing import Optional
@@ -65,6 +65,7 @@ async def process_broadcast_message_handler(
i18n_data: dict, i18n_data: dict,
settings: Settings, settings: Settings,
session: AsyncSession, session: AsyncSession,
bot: Bot,
): ):
current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE) current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE)
i18n: Optional[JsonI18n] = i18n_data.get("i18n_instance") 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")) await message.answer(_("admin_broadcast_error_no_message"))
return 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( await state.update_data(
broadcast_text=text, broadcast_text=text,
broadcast_entities=entities, broadcast_entities=entities,
@@ -190,6 +216,7 @@ async def confirm_broadcast_callback_handler(
chat_id=uid, chat_id=uid,
text=text, text=text,
entities=entities, entities=entities,
parse_mode=None, # переопределяем глобальный HTML, т.к. используем entities
) )
sent_count += 1 sent_count += 1
+2
View File
@@ -165,6 +165,8 @@
"admin_broadcast_cancelled_alert": "Broadcast cancelled!", "admin_broadcast_cancelled_alert": "Broadcast cancelled!",
"admin_broadcast_cancelled_nav_back": "Broadcast cancelled. You are returned to the admin panel.", "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: <code>{example_format}</code>\n(Validity is optional; default is indefinite)", "admin_promo_create_prompt": "Enter promo details in the format: CODE BONUS_DAYS MAX_USES [VALIDITY_DAYS]\nExample: <code>{example_format}</code>\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_format": "Invalid format. Please use: CODE BONUS_DAYS MAX_USES [VALIDITY_DAYS]",
"admin_promo_invalid_code_format": "Code must be 330 alphanumeric characters.", "admin_promo_invalid_code_format": "Code must be 330 alphanumeric characters.",
+1
View File
@@ -268,6 +268,7 @@
"sync_critical_error": "❌ Критическая ошибка синхронизации", "sync_critical_error": "❌ Критическая ошибка синхронизации",
"no_errors_placeholder": "нет", "no_errors_placeholder": "нет",
"admin_sync_initiated_from_panel": "Синхронизация запущена...", "admin_sync_initiated_from_panel": "Синхронизация запущена...",
"admin_broadcast_invalid_html": "❌ Некорректный HTML в сообщении. Пожалуйста, отправьте корректный HTML (поддерживаются теги Telegram) или уберите теги.",
"admin_panel_user_creation_failed": "❌ Не удалось создать пользователя на панели для TG ID {user_id}. Панель недоступна?", "admin_panel_user_creation_failed": "❌ Не удалось создать пользователя на панели для TG ID {user_id}. Панель недоступна?",
"error_displaying_logs_too_long": "Ошибка: логи слишком длинные для отображения одним сообщением. Попробуйте найти логи по конкретному пользователю.", "error_displaying_logs_too_long": "Ошибка: логи слишком длинные для отображения одним сообщением. Попробуйте найти логи по конкретному пользователю.",
"error_displaying_statistics": "Ошибка отображения статистики.", "error_displaying_statistics": "Ошибка отображения статистики.",