fix: implement true Telegram Rich Messages via LinkPreviewOptions
This commit is contained in:
@@ -12,7 +12,7 @@ from zoneinfo import ZoneInfo
|
||||
|
||||
from aiogram import Bot
|
||||
from aiogram.exceptions import TelegramRetryAfter
|
||||
from aiogram.types import FSInputFile, InputMediaPhoto, InputMediaVideo
|
||||
from aiogram.types import FSInputFile, InputMediaPhoto, InputMediaVideo, LinkPreviewOptions
|
||||
from loguru import logger
|
||||
|
||||
from ..config import settings
|
||||
@@ -356,6 +356,56 @@ class TelegramPoster:
|
||||
async def send_post(self, post: dict[str, Any]) -> list[int]:
|
||||
text = self.build_text(post)
|
||||
media_rows = await self.load_media(int(post["id"]))
|
||||
|
||||
# If no media, just send text
|
||||
if not media_rows:
|
||||
return await self.send_text(text)
|
||||
|
||||
# Telegram Rich Message (Single message, block layout, up to 4096 chars)
|
||||
# We use LinkPreviewOptions with the first media URL to show it above the text.
|
||||
first_url = None
|
||||
for row in media_rows:
|
||||
url = str(row.get("original_url") or "").strip()
|
||||
if url.startswith("http"):
|
||||
first_url = url
|
||||
break
|
||||
|
||||
if first_url:
|
||||
# Send as a Rich Message with Link Preview
|
||||
message = await self.tg_retry(
|
||||
lambda: self.bot.send_message(
|
||||
text=text,
|
||||
link_preview_options=LinkPreviewOptions(
|
||||
url=first_url,
|
||||
show_above_text=True
|
||||
),
|
||||
**self.chat_kwargs()
|
||||
)
|
||||
)
|
||||
message_ids = [int(message.message_id)]
|
||||
|
||||
# If it's an album (multiple media), we can send the rest as a media group without caption
|
||||
if len(media_rows) > 1:
|
||||
media_items = []
|
||||
for item in media_rows[1:]:
|
||||
media = self.media_value(item)
|
||||
if not media: continue
|
||||
media_type = str(item.get("media_type") or "")
|
||||
if media_type == "photo":
|
||||
media_items.append({"type": "photo", "media": media})
|
||||
elif media_type == "video":
|
||||
media_items.append({"type": "video", "media": media})
|
||||
|
||||
rest = media_items
|
||||
for start in range(0, len(rest), self.media_group_max_items):
|
||||
chunk = rest[start : start + self.media_group_max_items]
|
||||
message_ids.extend(await self.send_media_items(chunk, caption=None))
|
||||
if self.send_delay_sec:
|
||||
await asyncio.sleep(self.send_delay_sec)
|
||||
|
||||
return message_ids
|
||||
|
||||
# Fallback if no valid HTTP URL was found for Rich Message
|
||||
media_items = []
|
||||
for item in media_rows:
|
||||
media = self.media_value(item)
|
||||
@@ -366,12 +416,13 @@ class TelegramPoster:
|
||||
media_items.append({"type": "photo", "media": media})
|
||||
elif media_type == "video":
|
||||
media_items.append({"type": "video", "media": media})
|
||||
message_ids: list[int] = []
|
||||
|
||||
if not media_items:
|
||||
return await self.send_text(text)
|
||||
|
||||
first_caption = text[: self.caption_limit]
|
||||
first = media_items[: self.media_group_max_items]
|
||||
message_ids = []
|
||||
message_ids.extend(await self.send_media_items(first, first_caption))
|
||||
if self.send_delay_sec:
|
||||
await asyncio.sleep(self.send_delay_sec)
|
||||
|
||||
Reference in New Issue
Block a user