Оформляйте карточки сообщений
Всё, что публикует бот, будь то вебхук, ответ на команду или обновление по кнопке, является карточкой. Хорошая карточка с одного взгляда говорит, что произошло: цветная кромка, заголовок, статус и подробности под ними.
Что можно сделать
- Показывайте статусЦветная плашка вроде «Открыт», «Слит» или «Успешно», с числом добавленных и удалённых строк.
- Перечисляйте подробностиСтроки «название: значение», которые участники копируют одним нажатием.
- Пишите в markdownЖирный шрифт, встроенный код, блоки кода, цитаты и чекбоксы.
- Показывайте, что идёт работаСпиннер, пока бот думает, а потом его размышления за переключателем.
В приложении
Четыре карточки такими, какими их видят участники. Каждая занимает несколько строк JSON.
Устройство карточки
Части карточки сверху вниз. Пропустите то, что вам не нужно: карточка из одного заголовка тоже подойдёт.
- Шапка«Сообщение от» и имя: имя вебхука или, для ответа на команду, название вашего сообщества. Ответ может добавить
badge, например репозиторий. - Заголовок и статус
title, который становится ссылкой, если заданtitle_url, а рядом плашкаstatus. - ПодзаголовокВторая строка жирным шрифтом,
sub_title. - ОписаниеОсновной текст в markdown.
- ПоляСтроки «название: значение» с кнопкой копирования.
- Нижняя строкаВремя, а также добавленные и удалённые строки, если вы их передали.
{
"message_container": {
"type": "embed_message",
"badge": "acme/web",
"color": "purple",
"title": "Pull request #212 opened",
"title_url": "https://github.com/acme/web/pull/212",
"status": { "label": "Open", "color": "green", "icon": "pull_request" },
"sub_title": "Faster search in the channel list",
"description": "Search now runs **per keystroke** with a 120 ms debounce.",
"fields": [
{ "field": "Author", "value": "maya" },
{ "field": "Reviewers", "value": "dani, sam" }
],
"additions": 86,
"deletions": 12,
"files_changed": 3
}
}Все поля
Они передаются в message_container. Карточке нужно описание или индикатор загрузки. Поля с пометкой «Ответы на команды» отбрасываются, если публиковать через вебхук.
| Поле | Тип | Что делает |
|---|---|---|
type | string | embed_message (по умолчанию) или system_message. |
badge | string | Небольшой чип после имени в шапке, например acme/web. Ответы на команды |
avatar_url | string | Изображение поверх иконки карточки. |
color | string | Цвет кромки. См. цвета ниже. |
title | string | Первая строка жирным шрифтом. |
title_url | string | Превращает заголовок в ссылку. |
sub_title | string | Вторая строка жирным шрифтом под заголовком. |
description | string | Основной текст в markdown. |
fields | array | [{ "field": "…", "value": "…" }]: строки «название: значение». |
image_url, image_base64 | string | Изображение на карточке. |
images | array | [{ "image_url": "…" }]: галерея из нескольких изображений. |
status | object или string | Цветная плашка рядом с заголовком. См. ниже. Ответы на команды |
additions, deletions, files_changed | number | Статистика diff в нижней строке. Ответы на команды |
loader, loader_text, loader_sub_text | boolean, string | Спиннер вместо основного текста. |
thinking | string | Размышления за переключателем Показать размышления. Ответы на команды |
thinking понимают markdown: **bold**, _italic_, ~~strike~~, `inline code`, блоки кода в тройных обратных кавычках, > quotes, чекбоксы - [x], @упоминания и :emoji:.Статус и статистика diff
Плашка статуса рассказывает суть ещё до того, как кто-то прочтёт текст. Она стоит рядом с заголовком, а если заголовка нет, то в нижней строке; статистика diff отображается рядом со временем. И то и другое работает в ответах на команды, и их использует встроенная интеграция GitHub. Вебхук их отбрасывает.
{
"message_container": {
"color": "red",
"title": "Build failed on main",
"status": { "label": "Failing", "color": "red" },
"description": "`search.test.js`: 2 of 212 tests failed."
}
}| Поле | Тип | Что делает |
|---|---|---|
status | object или string | Обычная строка считается меткой: "status": "Open". |
status.label | string | Текст плашки. Без него плашки нет. |
status.color | string | green, purple, red, orange, yellow, blue или gray. |
status.icon | string | Необязательная иконка из списка ниже. |
additions | number | Добавленные строки, показываются зелёным +86. |
deletions | number | Удалённые строки, показываются красным -12. |
files_changed | number | Затронутые файлы, показываются как 3 files. |
Иконки
| Значение | Иконка | Типичное применение |
|---|---|---|
pull_request | git-pull-request | Открыт pull request |
pull_request_closed | git-pull-request-closed | Закрыт без слияния |
merge, merged | git-merge | Слит |
commit | git-commit | Отправлен коммит |
issue | circle-dot | Открыт issue |
issue_closed | circle-check | Закрыт issue |
check | circle-check | Тесты прошли, задача выполнена успешно |
Соответствие, которое подходит для GitHub
Их использует встроенная интеграция GitHub; скопируйте их для своих инструментов.
| Событие | Метка | Цвет | Иконка |
|---|---|---|---|
| Открыт pull request | Open | green | pull_request |
| Черновик | Draft | gray | pull_request |
| Слит | Merged | purple | merged |
| Закрыт без слияния | Closed | red | pull_request_closed |
| Открыт issue | Open | green | issue |
| Закрыт issue | Closed | purple | issue_closed |
| Отправлен коммит | Commit | gray | commit |
| Тесты прошли | Passing | green | check |
| Тесты не прошли | Failing | red | нет |
Загрузка и размышления
Для всего, что занимает время, например ответа ИИ или долгой задачи, сначала опубликуйте карточку со спиннером, а потом замените её результатом. Индикатор загрузки работает и в вебхуках, и в ответах на команды. В ответе на команду рассуждения модели можно также поместить в thinking: вместо стены текста участники увидят переключатель Показать размышления.
Сначала: индикатор загрузки
Потом: ответ, размышления свёрнуты
{
"message_container": {
"type": "embed_message",
"color": "blue",
"loader": true,
"loader_text": "Thinking…",
"loader_sub_text": "Reading the last 50 messages"
}
}{
"message_container": {
"type": "embed_message",
"color": "blue",
"sub_title": "maya: when is the standup?",
"description": "Standup is at **09:30**, in #daily.",
"thinking": "Checked the pinned messages and the recurring event in #daily…"
}
}| Поле | Тип | Что делает |
|---|---|---|
loader | boolean | true показывает спиннер вместо основного текста. |
loader_text | string | Строка рядом со спиннером, например «Думаю…». |
loader_sub_text | string | Строка поменьше под ней. |
thinking | string | Свёрнутые размышления под описанием, в markdown. |
Чтобы заменить индикатор загрузки ответом, обновите сообщение новой карточкой без loader. Как это сделать, описано на странице обновлений вживую.
Длинные описания
Описание может занимать до 50 000 байт. После первых 1 000 участники видят начало и кнопку Показать больше, которая загружает остальное, так что длинный отчёт не заваливает канал.
Системные сообщения
Задайте "type": "system_message" для объявления, а не поста бота: окна обслуживания, изменения правил, всё, что говорит от имени самого сообщества. Такое сообщение принимает те же поля и кнопки.
{
"message_container": {
"type": "system_message",
"color": "orange",
"title": "Maintenance tonight",
"description": "The build servers are down from 22:00 to 23:00."
}
}Цвета
Цвет кромки считывается на карточке быстрее всего. Всегда используйте один и тот же цвет для одного и того же рода новостей.
| Цвет | Для чего |
|---|---|
green | Успех: пройдено, выкачено, готово |
red | Неудача: ошибка, недоступно, отклонено |
orange | Предупреждение, на которое стоит взглянуть |
yellow | Ждёт чьего-то решения: одобрения, вопросы |
blue | Информация, по умолчанию |
purple | События в коде или что-то особенное |
Соберите свой embed
Редактируйте поля или JSON-payload. Они синхронизируются в обе стороны. Сообщение отображается точно так же, как в канале. Это настоящее тело webhook-запроса; скопируйте его, когда всё будет готово.