Crie cartões de mensagem
Tudo o que um bot publica, seja por um webhook, numa resposta a um comando ou numa atualização por botão, é um cartão. Um bom cartão mostra o que aconteceu num relance: uma borda colorida, um título, um status e os detalhes embaixo.
O que você pode fazer
- Mostre um statusUma pílula colorida como Open, Merged ou Passing, com as linhas adicionadas e removidas.
- Liste os detalhesLinhas de rótulo e valor que os membros copiam com um toque.
- Escreva em markdownNegrito, código inline, blocos de código, citações e caixas de seleção.
- Mostre que está trabalhandoUm spinner enquanto o seu bot pensa, e depois o raciocínio dele atrás de um botão de alternância.
No app
Quatro cartões como os membros os veem. Cada um é poucas linhas de JSON.
Anatomia de um cartão
As partes de um cartão, de cima para baixo. Deixe de fora o que você não precisa: um cartão só com título também vale.
- Cabeçalho“Message from” e um nome: o nome do webhook ou, numa resposta a comando, o nome da sua comunidade. Uma resposta pode acrescentar um
badge, como o repositório. - Título e statusO
title, que vira link quando você definetitle_url, com a pílula destatusao lado. - SubtítuloUma segunda linha em negrito,
sub_title. - DescriçãoO corpo, em markdown.
- CamposLinhas de rótulo e valor, com um botão de copiar.
- RodapéO horário e as linhas adicionadas e removidas, se você as enviar.
{
"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
}
}Todos os campos
Estes campos vão em message_container. Um cartão precisa de uma descrição ou de um loader. Os campos marcados como “Respostas a comandos” são descartados quando você publica por um webhook.
| Campo | Tipo | O que faz |
|---|---|---|
type | string | embed_message (o padrão) ou system_message. |
badge | string | Um pequeno selo depois do nome no cabeçalho, como acme/web. Respostas a comandos |
avatar_url | string | Uma imagem sobre o ícone do cartão. |
color | string | A cor da borda. Veja as cores abaixo. |
title | string | A primeira linha, em negrito. |
title_url | string | Transforma o título num link. |
sub_title | string | Uma segunda linha em negrito embaixo do título. |
description | string | O corpo, em markdown. |
fields | array | [{ "field": "…", "value": "…" }]: linhas de rótulo e valor. |
image_url, image_base64 | string | Uma imagem no cartão. |
images | array | [{ "image_url": "…" }]: uma galeria de várias imagens. |
status | object ou string | Uma pílula colorida ao lado do título. Veja abaixo. Respostas a comandos |
additions, deletions, files_changed | number | Estatísticas de diff no rodapé. Respostas a comandos |
loader, loader_text, loader_sub_text | boolean, string | Um spinner no lugar do corpo. |
thinking | string | Raciocínio atrás de um botão Show thinking. Respostas a comandos |
thinking entendem markdown: **bold**, _italic_, ~~strike~~, `inline code`, blocos de código entre crases triplas, > quotes, caixas de seleção - [x], @menções e :emoji:.Status e estatísticas de diff
Uma pílula de status conta a história antes que alguém leia o texto. Ela fica ao lado do título, ou no rodapé quando não há título; as estatísticas de diff aparecem ao lado do horário. As duas funcionam em respostas a comandos, e a integração nativa com o GitHub usa ambas. Um webhook as descarta.
{
"message_container": {
"color": "red",
"title": "Build failed on main",
"status": { "label": "Failing", "color": "red" },
"description": "`search.test.js`: 2 of 212 tests failed."
}
}| Campo | Tipo | O que faz |
|---|---|---|
status | object ou string | Uma string simples é o rótulo: "status": "Open". |
status.label | string | O texto da pílula. Sem ele, não há pílula. |
status.color | string | green, purple, red, orange, yellow, blue ou gray. |
status.icon | string | Um ícone opcional da lista abaixo. |
additions | number | Linhas adicionadas, mostradas como +86 em verde. |
deletions | number | Linhas removidas, mostradas como -12 em vermelho. |
files_changed | number | Arquivos alterados, mostrados como 3 files. |
Ícones
| Valor | Ícone | Uso típico |
|---|---|---|
pull_request | git-pull-request | Um pull request aberto |
pull_request_closed | git-pull-request-closed | Fechado sem merge |
merge, merged | git-merge | Mesclado |
commit | git-commit | Um commit enviado |
issue | circle-dot | Uma issue aberta |
issue_closed | circle-check | Uma issue fechada |
check | circle-check | Testes passaram, um job deu certo |
Um mapeamento que funciona para o GitHub
A integração nativa com o GitHub usa estes valores; copie-os para as suas próprias ferramentas.
| Evento | Rótulo | Cor | Ícone |
|---|---|---|---|
| Pull request aberto | Open | green | pull_request |
| Rascunho | Draft | gray | pull_request |
| Mesclado | Merged | purple | merged |
| Fechado sem merge | Closed | red | pull_request_closed |
| Issue aberta | Open | green | issue |
| Issue fechada | Closed | purple | issue_closed |
| Commit enviado | Commit | gray | commit |
| Testes passaram | Passing | green | check |
| Testes falharam | Failing | red | nenhum |
Loader e raciocínio
Para qualquer coisa que leve um momento, como uma resposta de IA ou um job longo, publique primeiro um cartão com um spinner e depois troque pelo resultado. O loader funciona em webhooks e em respostas a comandos. Numa resposta a comando, você também pode colocar o raciocínio do modelo em thinking: os membros veem um botão Show thinking em vez de um paredão de texto.
Primeiro: o loader
Depois: a resposta, com o raciocínio recolhido
{
"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…"
}
}| Campo | Tipo | O que faz |
|---|---|---|
loader | boolean | true mostra o spinner no lugar do corpo. |
loader_text | string | A linha ao lado do spinner, como “Pensando…”. |
loader_sub_text | string | Uma linha menor embaixo dela. |
thinking | string | Raciocínio recolhido embaixo da descrição, em markdown. |
Para trocar o loader pela resposta, atualize a mensagem com um cartão novo sem loader. Como fazer isso está em atualizações ao vivo.
Descrições longas
Uma descrição pode ter até 50.000 bytes. Passando dos primeiros 1.000, os membros veem o começo e um botão Show more que carrega o resto, para que um relatório longo não inunde o canal.
Mensagens de sistema
Defina "type": "system_message" para um aviso em vez de uma publicação de bot: janelas de manutenção, mudanças de regras, qualquer coisa que fale em nome da própria comunidade. Aceita os mesmos campos e botões.
{
"message_container": {
"type": "system_message",
"color": "orange",
"title": "Maintenance tonight",
"description": "The build servers are down from 22:00 to 23:00."
}
}Cores
A cor da borda é o sinal mais rápido de um cartão. Use sempre a mesma cor para o mesmo tipo de notícia.
| Cor | Use para |
|---|---|
green | Sucesso: passou, implantado, concluído |
red | Falha: falhou, fora do ar, rejeitado |
orange | Um aviso que merece uma olhada |
yellow | Esperando alguém: aprovações, perguntas |
blue | Informação, o padrão |
purple | Eventos de código, ou algo especial |
Monte seu embed
Edite os campos ou o payload JSON: os dois ficam sincronizados. A prévia mostra a mensagem exatamente como ela vai aparecer num canal. Este é o body real do webhook; copie quando estiver tudo certo.