| name | telegram |
| description | Канал доставки в Telegram (Bot API). Общий ресурс: используется из meeting-analysis, email-assistant и др. Отправка текстового (plain, parse_mode=HTML) и структурного (rich, sendRichMessage) сообщения Виктору. Здесь — канон: скрипты, форматирование, edge cases. Invocable-обёртка для оператора — .claude/skills/send-telegram/. |
Telegram (канал доставки)
Канон канала. Скрипты доставки в Telegram + правила форматирования. Общий ресурс — вызывается из meeting-analysis, email-assistant и будущих скиллов. Invocable-точка /send-telegram (.claude/skills/send-telegram/) ссылается сюда.
Два скрипта, оба в этой папке:
send_telegram.sh — plain (по умолчанию): markdown → HTML → sendMessage (parse_mode=HTML), нарезка по строкам ≤4096.
send_telegram_rich.sh — rich (структурный): markdown → sendRichMessage (Bot API 10.1), при отказе API фолбэк на plain.
The Iron Law
Два режима: быстрый и с превью. Спроси пользователя: «Показать превью или сразу отправить?». Если пользователь уже указал режим в запросе («сразу отправь», «без превью» → быстрый; «покажи сначала», «превью» → с превью), не переспрашивай.
Плоский или rich. Структурный вывод (таблицы, ≥2 секции, дайджест) → rich-режим (см. «Rich-режим» ниже). Короткое сообщение в 2-3 строки → обычный режим.
Алгоритм
1. Получить текст
Текст сообщения — из аргументов ($ARGUMENTS) или из контекста разговора. Если неясно что отправлять — спроси.
2. Выбрать режим
Спроси: «Показать превью или сразу отправить в Telegram?»
Не спрашивай если пользователь уже указал режим:
- «сразу», «без превью», «just send» → быстрый
- «покажи», «превью», «preview» → с превью
3a. Быстрый режим
Сразу к шагу 3c.
3b. Режим с превью
Показать текст в code block. После «ОК» или правок → шаг 3c.
3c. Адаптировать формат под Telegram (только обычный режим)
Сначала развилка: если выбран rich-режим — этот шаг ПРОПУСТИ (rich принимает markdown как есть, см. «Rich-режим»). Адаптация ниже — только для обычного режима.
Перед отправкой — привести текст к формату, который Telegram отобразит корректно:
## заголовок → 📋 **заголовок** (Telegram не поддерживает markdown-заголовки)
- [x] текст → - ✅ текст (скрипт убирает только [ ], не [x])
--- → убрать (скрипт убирает, но лучше не полагаться)
4. Отправить (обычный режим)
bash product/plugin/skills/channels/telegram/send_telegram.sh "ТЕКСТ_СООБЩЕНИЯ"
Проверить: ответ содержит "ok":true. Скрипт возвращает ненулевой exit при недоставке любого чанка. (Rich-режим отправляется скриптом send_telegram_rich.sh — см. «Rich-режим».)
5. Подтвердить
Сообщить результат:
- Успех: «Отправлено в Telegram»
- Ошибка: показать ответ API
Edge Cases
| Ситуация | Действие |
|---|
.env не найден | Скрипт ищет TELEGRAM_BOT_TOKEN/TELEGRAM_CHAT_ID в env → ./.env → git-root/.env. Если нигде нет — сообщить: «.env с TELEGRAM_BOT_TOKEN не найден» |
| Текст >4096 символов | Скрипт режет по строкам (теги не рвутся). Предупредить: «Длинное сообщение, Telegram разобьёт на части» |
| Rich: лимиты sendRichMessage | До 32768 символов, 500 блоков, 16 уровней вложенности, 50 медиа, 20 колонок таблицы. Больше — разбей на несколько сообщений по секциям |
| curl вернул ошибку | Скрипт вернёт ненулевой exit. Если 403 — напомнить про Allow network egress (Cowork) |
| Пустой текст | Скрипт вернёт ошибку. Спросить что отправлять |
Пример
Запрос: «Скинь в тг список задач на завтра»
- Claude формирует текст из контекста разговора
- Спрашивает: «Показать превью или сразу отправить в Telegram?»
- Пользователь: «сразу» →
bash product/plugin/skills/channels/telegram/send_telegram.sh "Задачи на завтра: ..."
- Ответ API
"ok":true → «Отправлено в Telegram»
Запрос: «отправь в телегу без превью: Встреча перенесена на 15:00»
- Режим указан явно → сразу отправка
bash product/plugin/skills/channels/telegram/send_telegram.sh "Встреча перенесена на 15:00"
- «Отправлено в Telegram»
Форматирование
Структура сообщения (обязательно)
Никогда не отправляй "портянку" — сплошной текст без структуры. Любое сообщение длиннее 2-3 строк должно быть структурировано.
Принципы:
- Приветствие — отдельная строка
- Суть (о чём сообщение) — отдельная строка
- Каждый смысловой блок — под жирным подзаголовком, текст с новой строки
- Подпись — курсивом (
__текст__), отделена пустой строкой
Пример правильного сообщения:
Саша, привет!
Небольшое техническое обновление.
Исправлен баг в claude/skills/scaffold-update.md.
**Что за скилл:**
обновляет рабочие файлы (overview, active, progress, team) после обработки встречи.
**Что исправлено:**
в секции «Ограничения» была строка со ссылкой на management/team.md — файл, которого нет. У тебя team/ давно развёрнут, ссылка была битая. Удалена.
__— Claude, помощник Виктора по svaib__
Антипаттерн (запрещено):
Саша, привет! Небольшое техническое обновление. Исправил баг в скилле scaffold-update.md (claude/skills/) — это скилл, который обновляет твои рабочие файлы (overview, active, progress, team и т.д.) после обработки встречи. В секции «Ограничения» была строка...
Технические возможности скрипта
Скрипт конвертирует markdown → HTML (parse_mode=HTML):
| Приём | Что писать | Результат в Telegram |
|---|
| Жирный | **текст** | текст |
| Курсив | __текст__ | текст |
| Заголовок секции | **Что сделано:** | Что сделано: |
| Эмодзи-маркеры | 📌, ✅, ❗️, 🔧 | Как есть |
| Список | - Пункт | - Пункт |
| Чекбокс | - [ ] Пункт | - Пункт (скрипт убирает [ ]) |
| Разделитель | --- | Убирается (пустая строка) |
Правило: жирным — подзаголовки блоков. Курсивом — подпись. Эмодзи — по ситуации (не больше 2-3 на сообщение). Не перегружать.
Rich-режим (sendRichMessage, Bot API 10.1)
Для структурного вывода — отдельный скрипт. Бот шлёт document-grade сообщение прямо в чат. Контент — GFM-подобный markdown.
Когда: читатель — человек и структура реально помогает (таблица, код, ≥2 секции). Короткие сообщения в 2-3 строки — обычный режим, не rich.
Как:
bash product/plugin/skills/channels/telegram/send_telegram_rich.sh "MARKDOWN"
Проверить ответ "ok":true. Фолбэк срабатывает только при подтверждённом отказе API (ok:false) — тогда скрипт шлёт обычным send_telegram.sh. При сетевом timeout фолбэка НЕТ (исход неизвестен — чтобы не словить двойную доставку), скрипт вернёт ошибку. И фолбэк теряет rich-форматирование: таблицы / <details> / код уйдут сырой разметкой — это аварийная доставка текста, не замена rich.
Проверенная палитра элементов
Всё ниже подтверждено на живом рендере (по rich_message.blocks в ответе API):
| Элемент | Синтаксис | Примечание |
|---|
| Заголовок | ## Текст (число # → size 1–6) | |
| Разделитель | --- | зазоры между секциями — этим |
| Таблица | GFM (пайпы + строка-разделитель) | |
| Код | fenced-блок с языком | подсветка синтаксиса |
| Чек-лист | - [x] / - [ ] | рендерит галочки |
| Сворачивающийся блок | <details><summary>…</summary>…</details> | raw-HTML внутри markdown работает |
| Формула | $…$, вкл. \sqrt{}, \cdot | |
| Картинка | alt | нужен публичный URL — см. ниже |
| Цитата | > текст | |
Картинки — URL, доступный серверам Telegram по HTTP/HTTPS. Telegram сам выкачивает картинку по ссылке (на практике кэширует к себе); локальный файл в markdown не вставить.
- Бери готовый публичный URL. Своего хостинга нет — можно положить в наш репо (
meta/marketing/brand/ → raw.githubusercontent.com/SolomonikVik/svaib/main/…), но коммит в репо — только с явного разрешения Виктора (запрос «отправь в телеграм» сам по себе права на коммит не даёт).
- Готовый логотип уже в репо:
meta/marketing/brand/svaib-logo.png.
Два правила, которые легко нарушить (проверено)
- Зазоры между секциями — разделителем
---, не пустыми строками. Пустой блок с неразрывным пробелом (U+00A0) Telegram схлопывает (особенно рядом с заголовками) — секции слипаются. --- — настоящий блок, не исчезает.
- Списки: вложение только «хвостом». Плоские списки — ок. Вложенные буллеты — только под последним пунктом. Нельзя продолжать нумерацию после вложенного блока: «2 → вложенные → 3» ломает рендер (пункт 3 съезжает под вложение). Правильно: «1, 2, 3 → вложенные под 3».
Рендер зависит от клиента-получателя: телефон — чисто, десктоп пока сыровато (фича от июня 2026). Фолбэк тут НЕ помогает — он только на ошибку API, а не на плохой рендер при ok:true.
Скрипты
- Обычный (по умолчанию): send_telegram.sh — резолвит
.env (env → pwd → git-root) → экранирует HTML → конвертирует markdown (** → <b>) → sendMessage (parse_mode=HTML) → режет по строкам ≤4096 → проверяет ok (ненулевой exit при недоставке).
- Rich (структурный): send_telegram_rich.sh — markdown →
sendRichMessage (Bot API 10.1) → при отказе API фолбэк на обычный.
Related
.claude/skills/send-telegram/ — invocable-обёртка для оператора (/send-telegram), ссылается на этот канон
- reader-telegram — чтение постов из Telegram-каналов (обратная операция: read vs send)
- telegram-post-writer — генерация драфта поста для канала @svaib_lab