diff --git a/app/telegram_layer/formatter.py b/app/telegram_layer/formatter.py index c4f3f95..da62933 100644 --- a/app/telegram_layer/formatter.py +++ b/app/telegram_layer/formatter.py @@ -2,6 +2,17 @@ from aiogram.types import Message from app.models.domain import TgIncomingMessage +TG_CAPTION_MAX_LEN = 1024 +TG_MESSAGE_MAX_LEN = 4096 + + +def split_text_for_media_caption(text: str) -> tuple[str | None, str | None]: + if not text: + return None, None + if len(text) <= TG_CAPTION_MAX_LEN: + return text, None + return None, text + def format_tg_author(message: Message) -> tuple[str, str | None]: user = message.from_user diff --git a/app/telegram_layer/worker.py b/app/telegram_layer/worker.py index a11246f..d2edcea 100644 --- a/app/telegram_layer/worker.py +++ b/app/telegram_layer/worker.py @@ -33,7 +33,10 @@ from app.models.tasks import ( from app.queue.protocols import QueuePort from app.storage.protocols import StoragePort from app.telegram_layer.bot_holder import BotHolder -from app.telegram_layer.formatter import format_topic_pin_text +from app.telegram_layer.formatter import ( + format_topic_pin_text, + split_text_for_media_caption, +) from app.topic_locks import TopicLockRegistry logger = structlog.get_logger(__name__) @@ -302,6 +305,26 @@ class TelegramWorker: thread_id=mapping.tg_thread_id, ) + async def _send_overflow_text( + self, + bot, + *, + thread_id: int, + text: str, + reply_to_message_id: int, + ) -> None: + await bot.send_message( + chat_id=self._settings.tg_forum_channel_id, + message_thread_id=thread_id, + text=text, + reply_to_message_id=reply_to_message_id, + ) + logger.info( + "tg_caption_overflow_sent", + thread_id=thread_id, + text_len=len(text), + ) + async def _dispatch_content( self, bot, @@ -321,6 +344,8 @@ class TelegramWorker: if not media: return await bot.send_message(text=text or " ", **kwargs) + caption, overflow = split_text_for_media_caption(text) + downloaded: list = [] try: max_client = self._max_holder.client @@ -354,33 +379,43 @@ class TelegramWorker: if len(uploads) == 1: item, upload = uploads[0] if item.kind == "photo": - return await bot.send_photo( - photo=upload, caption=text or None, **kwargs + sent = await bot.send_photo( + photo=upload, caption=caption, **kwargs ) - if item.kind == "video": - return await bot.send_video( - video=upload, caption=text or None, **kwargs - ) - return await bot.send_document( - document=upload, caption=text or None, **kwargs - ) - - group = [] - for idx, (item, upload) in enumerate(uploads): - caption = text if idx == 0 else None - if item.kind == "photo": - group.append(InputMediaPhoto(media=upload, caption=caption)) elif item.kind == "video": - group.append(InputMediaVideo(media=upload, caption=caption)) + sent = await bot.send_video( + video=upload, caption=caption, **kwargs + ) else: - group.append(InputMediaDocument(media=upload, caption=caption)) + sent = await bot.send_document( + document=upload, caption=caption, **kwargs + ) + else: + group = [] + for idx, (item, upload) in enumerate(uploads): + item_caption = caption if idx == 0 else None + if item.kind == "photo": + group.append(InputMediaPhoto(media=upload, caption=item_caption)) + elif item.kind == "video": + group.append(InputMediaVideo(media=upload, caption=item_caption)) + else: + group.append(InputMediaDocument(media=upload, caption=item_caption)) - messages = await bot.send_media_group( - chat_id=chat_id, - message_thread_id=thread_id, - media=group, - ) - return messages[0] + messages = await bot.send_media_group( + chat_id=chat_id, + message_thread_id=thread_id, + media=group, + ) + sent = messages[0] + + if overflow: + await self._send_overflow_text( + bot, + thread_id=thread_id, + text=overflow, + reply_to_message_id=sent.message_id, + ) + return sent finally: cleanup_paths(downloaded)