diff --git a/app/utils/message_patch.py b/app/utils/message_patch.py index 134ff1ea..7302f6ef 100644 --- a/app/utils/message_patch.py +++ b/app/utils/message_patch.py @@ -1,3 +1,5 @@ +import html +import re from pathlib import Path from typing import Any, Dict @@ -63,6 +65,14 @@ def append_privacy_hint(text: str | None, language: str | None) -> str: return hint +def _strip_html(text: str | None) -> str: + if not text: + return "" + + plain_text = html.unescape(re.sub(r"<[^>]+>", "", text)) + return plain_text.strip() + + def prepare_privacy_safe_kwargs(kwargs: Dict[str, Any] | None = None) -> Dict[str, Any]: safe_kwargs: Dict[str, Any] = dict(kwargs or {}) safe_kwargs.pop("reply_markup", None) @@ -100,7 +110,10 @@ async def _answer_with_photo(self: Message, text: str = None, **kwargs): safe_kwargs = prepare_privacy_safe_kwargs(kwargs) return await _original_answer(self, fallback_text, **safe_kwargs) # Фоллбек, если Telegram ругается на caption или другое ограничение: отправим как текст - return await _original_answer(self, text, **kwargs) + fallback_text = _strip_html(text) + safe_kwargs = dict(kwargs) + safe_kwargs.pop("parse_mode", None) + return await _original_answer(self, fallback_text, **safe_kwargs) except Exception: return await _original_answer(self, text, **kwargs) return await _original_answer(self, text, **kwargs) @@ -153,7 +166,10 @@ async def _edit_with_photo(self: Message, text: str, **kwargs): await self.delete() except Exception: pass - return await _original_answer(self, text, **kwargs) + fallback_text = _strip_html(text) + safe_kwargs = dict(kwargs) + safe_kwargs.pop("parse_mode", None) + return await _original_answer(self, fallback_text, **safe_kwargs) return await _original_edit_text(self, text, **kwargs) @@ -162,4 +178,3 @@ def patch_message_methods(): return Message.answer = _answer_with_photo Message.edit_text = _edit_with_photo - diff --git a/app/utils/photo_message.py b/app/utils/photo_message.py index f7e65752..95d04110 100644 --- a/app/utils/photo_message.py +++ b/app/utils/photo_message.py @@ -1,3 +1,6 @@ +import html +import re + from aiogram import types from aiogram.exceptions import TelegramBadRequest from aiogram.types import FSInputFile, InputMediaPhoto @@ -33,6 +36,14 @@ def _get_language(callback: types.CallbackQuery) -> str | None: return None +def _strip_html(text: str | None) -> str: + if not text: + return "" + + plain_text = html.unescape(re.sub(r"<[^>]+>", "", text)) + return plain_text.strip() + + def _build_base_kwargs(keyboard: types.InlineKeyboardMarkup | None, parse_mode: str | None): kwargs: dict[str, object] = {} if parse_mode is not None: @@ -57,6 +68,19 @@ async def _answer_text( kwargs = prepare_privacy_safe_kwargs(kwargs) kwargs.setdefault("parse_mode", parse_mode or "HTML") + try: + await callback.message.answer( + caption, + **kwargs, + ) + return + except TelegramBadRequest as send_error: + if is_privacy_restricted_error(send_error): + caption = append_privacy_hint(caption, language) + kwargs = prepare_privacy_safe_kwargs(kwargs) + else: + caption = _strip_html(caption) + kwargs.pop("parse_mode", None) await callback.message.answer( caption,