mirror of
https://gitverse.ru/kpa39l/vesti.git
synced 2026-09-29 09:55:03 +00:00
86 lines
4.4 KiB
Python
86 lines
4.4 KiB
Python
# Форматирование карточки поста для Telegram (MUST: ≤4096 символов).
|
|
# «Богатый репост»: [комментарий модератора] + полный текст поста + ссылка на оригинал.
|
|
# Без служебной информации (направление/источник/просмотры) — она в вебе и бандле.
|
|
# Текст — plain (не HTML): исходный текст поста не перекодируем, ссылки Telegram
|
|
# распознаёт сам; предпросмотр ссылки отключается на уровне sendMessage.
|
|
|
|
import re
|
|
|
|
MAX_TEXT = 4096
|
|
|
|
# фото/видео, поддерживаемые Bot API sendPhoto/sendVideo
|
|
MEDIA_EXTS = (".jpg", ".jpeg", ".png", ".gif", ".webp", ".mp4", ".mov", ".avi", ".mkv")
|
|
|
|
|
|
def make_card(post: dict, comment: str | None = None) -> dict:
|
|
"""Собирает карточку «богатого репоста». Возвращает {"media": path|None, "text": str}.
|
|
|
|
post: dict из БД (id, text, url, media_path, is_own, tg_channel, tg_post_id, ...).
|
|
Формат текста:
|
|
[комментарий модератора] — если задан, первым блоком
|
|
[полный текст исходного поста] — без сниппета/суммари
|
|
[ссылка на оригинал] — последней строкой (атрибуция для своих)
|
|
|
|
Текст НЕ содержит служебки (📁 направление/язык, 📰 источник, 👁 просмотры) —
|
|
это был «агрегаторный» вид карточки.
|
|
"""
|
|
comment = (comment or "").strip()
|
|
# тело: пересказ (rewritten_text) приоритетнее исходного текста
|
|
body = (post.get("rewritten_text") or post.get("text") or "").strip()
|
|
rewritten = bool((post.get("rewritten_text") or "").strip())
|
|
|
|
# ссылка на оригинал / атрибуция своего контента
|
|
is_own = int(post.get("is_own") or 0) == 1
|
|
orig = None
|
|
if post.get("tg_channel") == "dedinit" and post.get("tg_post_id"):
|
|
orig = f"https://t.me/dedinit/{post['tg_post_id']}"
|
|
elif post.get("url"):
|
|
orig = post.get("url")
|
|
if rewritten:
|
|
# пересказ — публикация от имени автора канала (не пересылка)
|
|
tail = "✍️ Дед в АйТи (@dedinit)" + (f" · Источник: {orig}" if orig else "")
|
|
elif is_own:
|
|
tail = "✍️ Дед в АйТи (@dedinit)" + (f" · {orig}" if orig else "")
|
|
elif orig:
|
|
tail = f"🔗 Оригинал: {orig}"
|
|
else:
|
|
tail = None
|
|
|
|
parts = []
|
|
if comment:
|
|
parts.append(comment)
|
|
if body:
|
|
parts.append(body)
|
|
if tail:
|
|
parts.append(tail)
|
|
if not parts:
|
|
parts = ["(пост без текста)"]
|
|
|
|
text = "\n\n".join(parts)
|
|
|
|
if len(text) > MAX_TEXT:
|
|
# обрезаем полный текст, но сохраняем ссылку/атрибуцию в конце
|
|
tail_block = ("\n\n" + tail) if tail else ""
|
|
budget = MAX_TEXT - len(tail_block) - 3
|
|
body_cut = text[:budget].rstrip() + "…"
|
|
text = body_cut + tail_block
|
|
if len(text) > MAX_TEXT:
|
|
text = text[: MAX_TEXT - 3] + "…"
|
|
|
|
# медиа: фото И видео (раньше отбрасывалось всё кроме картинок)
|
|
media = post.get("media_path") or post.get("media_local") or None
|
|
if media and not str(media).lower().endswith(MEDIA_EXTS):
|
|
media = None
|
|
if media:
|
|
# нормализация пути: media_path в БД = 'media/<file>', но старые файлы
|
|
# физически лежат в media/media/<file> (баг краулера до 2026-09-12).
|
|
# Пробуем оба варианта, отдаём тот, что существует.
|
|
import os as _os
|
|
cands = [
|
|
str(media),
|
|
str(_os.path.join("media", str(media).replace("media/", "", 1)))
|
|
if str(media).startswith("media/") else None,
|
|
]
|
|
found = next((c for c in cands if c and _os.path.exists(c)), None)
|
|
media = found or media # если ни один не найден — оставляем как есть (publisher retry)
|
|
return {"media": media, "text": text} |