## Дизайн ### 1. Формат карточки (publisher/card.py) `make_card(post, comment=None)` теперь собирает текст репоста: ``` [комментарий модератора (если задан)] [пустая строка] [полный текст исходного поста] [пустая строка] 🔗 Оригинал: (или атрибуция «Дед в АйТи (@dedinit) · t.me/dedinit/» для своих) ``` - Полный текст поста (post["text"]) вместо сниппета/summary; обрезка до Telegram-лимита (MAX_TEXT=4096) с учётом ссылки и комментария. - Служебная информация (📁 направление/язык, 📰 источник, 👁 просмотры) убирается из тела поста — это был «агрегаторный» вид. Просмотры/реакции остаются только в бандле и вебе. - Ссылка на оригинал — всегда последней строкой (для внешних: `🔗 Оригинал: `; для своих: атрибуция + ссылка `t.me/dedinit/` как раньше). - HTML-экранирование текста поста и комментария (вход — непроверенный текст, правило XSS). ### 2. Медиа (publisher/card.py + services/publisher) - Медиа отправляется ПЕРВЫМ сообщением (фото или видео), затем — текст. - Разрешить video: `card.py` фильтр `.mp4` больше не отбрасывает (content_type=video). - `services/publisher/app/telegram.py` — новый `send_video(chat_id, path, caption="")` (Bot API sendVideo), общий `send_media` по расширению. - Caption у медиа: короткий (`⬇️ Пост ниже` или комментарий), НЕ дублировать весь текст (раньше photo caption обрезался до 1024 и текст всё равно слался вторым). ### 3. Отключение предпросмотра ссылки (services/publisher/app/telegram.py) `send_message` → добавить параметр: ```python link_preview_options={"is_disabled": True} ``` чтобы Telegram НЕ добавлял предпросмотр оригинальной ссылки в конце поста. ### 4. Веб: поле «Комментарий» (web/app.py + templates/candidates.html) - В форме approve (для всех постов — и свои, и внешние) текстовое поле ``. - `approve`: `comment = (await request.form()).get("comment", "").strip()` → в card. - Комментарий уходит в published? Нет (не меняем схему БД) — только в текст поста и в метаданные бандла? Для простоты: комментарий включается в текст карточки (и, если хочется, в frontmatter бандла `comment:` — опционально, без схемы БД). ### 5. Полный текст в бандле - Бандл (web/store.py) УЖЕ хранит полный текст поста — не меняется. ### 6. Обратная совместимость - `make_card(post)` без comment работает (comment=None). - Старый `send_photo`/`send_message` остаются; main.py выбирает: если media → send_media, потом send_message (link_preview disabled). - Если текст пустой (пост только медиа) — текст-сообщение можно пропустить? Нет: ссылка на оригинал должна быть → текст генерируется всегда (минимум ссылка). ### 7. Проверка - Юнит: `make_card` с comment → комментарий первым, полный текст, ссылка, без служебки. - Карточка ≤4096 (обрезается). - sendVideo работает для реального mp4 (в Docker медиа-маунт уже есть). - В канале: медиа + текст + ссылка, предпросмотра ссылки нет. - Веб: поле комментария видно, approve с комментарием → в канале комментарий первым.