77 lines
2.4 KiB
Python
77 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
import re
|
|
|
|
from aiogram import Bot
|
|
from aiogram.types import BufferedInputFile
|
|
|
|
from bot.ha_client import HaClient
|
|
from bot.tg_util import send_text, split_telegram_message
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
IMAGE_MD_RE = re.compile(r"!\[([^\]]*)\]\(([^)]+)\)")
|
|
TG_CAPTION_MAX = 1024
|
|
|
|
|
|
def parse_notice_content(content: str) -> tuple[str, list[str]]:
|
|
image_paths: list[str] = []
|
|
|
|
def _replace(match: re.Match[str]) -> str:
|
|
image_paths.append(match.group(2).strip())
|
|
return ""
|
|
|
|
text = IMAGE_MD_RE.sub(_replace, content)
|
|
text = _plain_markdown(text)
|
|
return text, image_paths
|
|
|
|
|
|
def _plain_markdown(text: str) -> str:
|
|
text = re.sub(r"```[^\n]*\n(.*?)```", r"\1", text, flags=re.DOTALL)
|
|
text = re.sub(r"\*\*([^*]+)\*\*", r"\1", text)
|
|
text = re.sub(r"\*([^*]+)\*", r"\1", text)
|
|
text = re.sub(r"__([^_]+)__", r"\1", text)
|
|
text = re.sub(r"`([^`]+)`", r"\1", text)
|
|
text = re.sub(r"\n{3,}", "\n\n", text)
|
|
return text.strip()
|
|
|
|
|
|
async def send_notice_content(
|
|
bot: Bot,
|
|
chat_id: int,
|
|
content: str,
|
|
client: HaClient,
|
|
*,
|
|
ha_api_base: str,
|
|
) -> None:
|
|
caption, image_paths = parse_notice_content(content)
|
|
if not image_paths:
|
|
await send_text(bot, chat_id, caption or content)
|
|
return
|
|
|
|
caption_chunks = split_telegram_message(caption, TG_CAPTION_MAX) if caption else []
|
|
first_caption = caption_chunks[0] if caption_chunks else None
|
|
|
|
for index, image_path in enumerate(image_paths):
|
|
try:
|
|
image_bytes = await client.download_media(image_path, ha_api_base=ha_api_base)
|
|
except Exception:
|
|
logger.exception("Failed to download image %s for chat_id=%s", image_path, chat_id)
|
|
fallback = f"{caption}\n\n(не удалось загрузить: {image_path})".strip()
|
|
await send_text(bot, chat_id, fallback or image_path)
|
|
return
|
|
|
|
cap = first_caption if index == 0 else None
|
|
await bot.send_photo(
|
|
chat_id,
|
|
BufferedInputFile(image_bytes, filename="image.png"),
|
|
caption=cap or None,
|
|
)
|
|
|
|
if len(caption_chunks) > 1:
|
|
for extra in caption_chunks[1:]:
|
|
await send_text(bot, chat_id, extra)
|
|
elif caption and not first_caption and len(caption) > TG_CAPTION_MAX:
|
|
await send_text(bot, chat_id, caption)
|