Оформленные посты в Telegram: вёрстка (заголовки, таблицы, списки, details, сноски, LaTeX, карусель tg-slideshow и коллаж tg-collage) и её публикация — ботом через sendRichMessage / sendMediaGroup либо руками через редактор «Статья». Использовать при задачах про постинг в Telegram-канал, карусель в посте, длинные оформленные посты, вёрстку текста под Telegram, а также когда нужно с нуля поднять бота на aiogram. Содержит развилку «нужен ли вообще бот».
Installs into .claude/skills of the current project.
Are you the author of Tg Rich Post?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/seozavr-tg-rich-post)
---
name: tg-rich-post
description: "Оформленные посты в Telegram: вёрстка (заголовки, таблицы, списки, details, сноски, LaTeX, карусель tg-slideshow и коллаж tg-collage) и её публикация — ботом через sendRichMessage / sendMediaGroup либо руками через редактор «Статья». Использовать при задачах про постинг в Telegram-канал, карусель в посте, длинные оформленные посты, вёрстку текста под Telegram, а также когда нужно с нуля поднять бота на aiogram. Содержит развилку «нужен ли вообще бот»."
---
# tg-rich-post
Собрать Telegram-бота и опубликовать пост так, как задумано: с настоящей свайп-каруселью,
заголовками, таблицами и сворачиваемыми блоками — либо классическим альбомом, если важна
совместимость со всеми клиентами.
## ⚠️ Сначала прочитай это
**Rich Messages появились в Bot API 10.1 (11 июня 2026).** Модели с более ранним cutoff
про них не знают и начинают выдумывать несуществующие методы. Всё, что нужно знать,
собрано в этом скилле и сверено с первоисточником 2026-08-05. Если сомневаешься —
проверяй по `core.telegram.org/bots/api`, а не по памяти.
Проверенный факт: `aiogram >= 3.30.0` реализует Bot API 10.2, метод доступен как
`bot.send_rich_message(...)`. Никаких ручных HTTP-запросов не нужно.
## Сначала: а нужен ли вообще бот
С июля 2026 (Telegram 12.9) человек собирает такой же пост руками: скрепка в поле
ввода → **«Статья»**. Там есть заголовки, таблицы, списки, цитаты, код, формулы,
фото и видео и слайды. Условие одно — **подписка Premium**.
Без Premium редактор открывается и даёт набрать текст, но расширенное форматирование
и **отправка заблокированы** — на кнопке отправки замок, всплывает «Оформите Telegram
Premium, чтобы отправлять статьи с расширенным форматированием» (проверено 2026-08-05).
Так что «нет подписки» — это не «неудобно», а «руками невозможно»: остаётся бот.
Поэтому первый вопрос пользователю, а не первая строка кода:
| Бот оправдан | Бота писать не надо |
|---|---|
| Premium нет, а пост нужен | Premium есть, постов пара в день |
| Постов много: лента, выпуск каждый день | Каждый пост всё равно смотрят глазами перед отправкой |
| Текст рождает модель или скрипт | Верстка разовая |
| Один шаблон на все выпуски | Каждый пост уникален по форме |
| Публикация по событию, без человека | Публикует человек, когда захочет |
Отдельно про расписание: **в клиенте планирование постов есть, а в Bot API — нет**
(параметра `schedule_date` в документации не существует). Если задача — «поставить
неделю постов заранее», руками это делается быстрее, чем ботом.
Если бот не нужен — скилл всё равно полезен: `references/grammar.md` описывает ту же
разметку, что понимает редактор. Рабочая связка без единой строчки кода — **модель
верстает разметку, человек вставляет её в «Статью»**.
## Что выбрать (если бот нужен)
| | Альбом `sendMediaGroup` | Rich Message `sendRichMessage` |
|---|---|---|
| Медиа | 2–10 | до 50 |
| Текст | подпись 1024 символа | 32768 символов, до 500 блоков |
| Карусель | нет, сетка превью | `<tg-slideshow>` — свайп внутри поста |
| Разметка | b/i/u/s/code/spoiler/ссылки | + заголовки, таблицы, списки, `<details>`, врезки, сноски, LaTeX, карты |
| Старые клиенты | видят нормально | видят «сообщение не поддерживается» |
Практическое правило: **если пост живёт в канале с широкой аудиторией — альбом;
если важна форма (лонгрид, дайджест, витрина) — rich.** Проверить на своей аудитории
дешевле, чем гадать: отправь оба варианта в тестовый чат и посмотри с двух устройств.
Premium боту не нужен. В каналы публиковать можно — бот должен быть админом с правом
публикации.
## Порядок работы
1. **Бот и чат.** Если их ещё нет — `references/bootstrap.md`: BotFather, `.env`, тестовый
канал, как узнать id. Не выдумывай токен и id, они приходят от пользователя.
2. **Каркас.** Взять `assets/minimal_bot.py` — рабочий однофайловый бот с командами
`/id`, `/album`, `/rich`. Для проекта побольше разложить по модулям, но начинать с него.
3. **Разметка.** Собрать HTML или Markdown по `references/grammar.md`. Там точный список
поддерживаемых тегов — Telegram молча игнорирует всё, чего нет в списке.
4. **Проверка до отправки.** Прогнать разметку через `check_rich()` из
`assets/minimal_bot.py`: лимиты и висячие ссылки `tg://photo?id=…`. Telegram на такие
ошибки отвечает невнятным BAD_REQUEST, а локальная проверка называет причину.
5. **Отправка в тестовый чат, не в боевой канал.** Сначала посмотреть глазами.
6. **Если упало** — `references/troubleshooting.md`, там разобраны реальные ошибки.
## Медиа в rich-разметке
Единственная нетривиальная часть. Картинка в разметке — это ссылка вида
`tg://photo?id=<id>`, а сам файл едет отдельно в поле `media`:
```python
from aiogram.types import (FSInputFile, InputMediaPhoto,
InputRichMessage, InputRichMessageMedia)
html = """<h2>Заголовок</h2>
<tg-slideshow>
<img src="tg://photo?id=p1"/>
<img src="tg://photo?id=p2"/>
<figcaption>Подпись к карусели<cite>Автор</cite></figcaption>
</tg-slideshow>
<p>Текст под каруселью.</p>"""
await bot.send_rich_message(
chat_id,
InputRichMessage(
html=html,
media=[
InputRichMessageMedia(id="p1", media=InputMediaPhoto(media=FSInputFile("1.jpg"))),
InputRichMessageMedia(id="p2", media=InputMediaPhoto(media=FSInputFile("2.jpg"))),
],
),
)
```
Правила: `id` — 1–64 символа `A-Za-z0-9_-`; каждый упомянутый в разметке id должен быть
в `media`, и наоборот; медиа задаётся **только отдельным блоком** (не внутри абзаца);
вместо `tg://` можно дать прямой HTTP(S)-URL, но не путь к локальному файлу.
## Три ошибки, на которых спотыкаются все
1. `chat not found` — id канала или супергруппы нужен с префиксом `-100`:
`1234567890` → `-1001234567890`. Для публичного канала проще `@username`.
2. `show_caption_above_media must be the same for all messages` — в альбоме этот флаг
должен стоять у **всех** элементов, хотя подпись ставится только на первый.
3. Пост виден как «сообщение не поддерживается» — это не баг, а старый клиент у читателя.
Решение: либо альбом, либо сознательно принять потерю части аудитории.
Остальное — `references/troubleshooting.md`.
## Чего Bot API не умеет
Отложенного постинга нет: расписание пишется своё (APScheduler, cron, очередь).
У человека в клиенте планирование есть — ещё одна причина не писать бота ради
«постов по расписанию», если постит всё равно человек.
Редактировать rich-сообщение можно через `editMessageText` с параметром `rich_message`.
## Приёмка
- [ ] пост дошёл в тестовый чат, ошибок в логе нет
- [ ] посмотрен на телефоне и на десктопе
- [ ] посмотрен на заведомо старом клиенте — что видит читатель вместо поста
- [ ] проверена пересылка поста в другой чат
- [ ] превью в списке чатов и в уведомлении выглядит осмысленно
- [ ] только после этого — публикация в боевой канал