Pular para o conteúdo principal
Desenvolvedores Atualizações ao vivo

Atualize mensagens ao vivo

Uma mensagem não precisa ficar como foi publicada. Mostre o progresso enquanto um job roda, troque um loader pelo resultado, tire os botões quando alguém já decidiu ou apague a mensagem. Todos no canal veem a mudança na hora.

O que você pode fazer

  • Atualize o cartãoMude o texto, a cor e os botões, no mesmo lugar.
  • Mostre o progressoUm loader que passa pelas etapas, e depois o resultado.
  • ApagueRemova uma mensagem quando ela deixar de ser verdade.
  • EscuteRespostas, reações e toques em botões na sua mensagem, ao vivo.

No app

Publicado com um loader

Atualizado: etapa 2 de 3

Atualizado: concluído, com um botão

Uma mensagem, atualizada duas vezes pela callback URL dela. Ninguém vê três mensagens, só uma que muda.

Início rápido

  1. Guarde a callback URL

    Toda publicação por webhook e toda requisição de comando vem com uma callback_url para aquela mensagem.

    bash
    BODY='{"message_container": {"color": "blue", "loader": true, "loader_text": "Deploying…"}}'
    SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$MSSGS_WEBHOOK_SECRET" | sed 's/^.* //')
    
    curl -X POST "$MSSGS_WEBHOOK_URL" -H "Content-Type: application/json" \
      -H "X-Mssgs-Signature: sha256=$SIG" -d "$BODY"
    
    # {"success": true, "message_id": "...", "callback_url": "https://mss.gs/api/v1/trigger-callback/8f14e45f-..."}
  2. PUT para atualizar

    Envie o novo estado. O cartão muda no mesmo lugar para todos.

    bash
    curl -X PUT "$CALLBACK_URL" -H "Content-Type: application/json" \
      -d '{"message_container": {"color": "green", "title": "Deploy complete", "description": "v2.1 is live."}}'
  3. DELETE para remover

    Não precisa de corpo.

    bash
    curl -X DELETE "$CALLBACK_URL"

Atualizar uma mensagem

Faça um PUT de JSON na callback_url. Envie só o que você quer mudar.

CampoTipoO que faz
message_containerobjectO novo cartão. Veja cartões de mensagem.
actionsarrayNovos botões. "actions": [] tira todos; deixar o campo de fora mantém os atuais.
contentstringNovo texto.
title, description, color, loader, ...stringAtalho: campos de cartão no nível superior são embrulhados num cartão para você.
Um novo message_container substitui o cartão antigo por inteiro: um campo que você deixar de fora some. Só o tipo, o nome e o avatar são mantidos. Então envie o cartão completo toda vez.

Respostas

StatusCódigoSignificado
200{"success": true}Aceito. A atualização vem logo em seguida.
400MISSING_FIELDSNada para atualizar no corpo.
400INVALID_BODYO corpo não é um JSON válido.
400um código de botãoHá algo errado com um botão, veja botões.
401INVALID_TOKENA URL não é válida.
404TOKEN_NOT_FOUNDA URL expirou ou foi usada para apagar a mensagem.
502PUBLISH_FAILEDA atualização não pôde ser entregue. Tente de novo.

Por quanto tempo funciona

30 minutos a partir do momento em que a mensagem foi publicada, ou em que o comando foi usado. Atualizar não prolonga esse prazo. Apagar a mensagem esgota a URL. Não é possível adicionar arquivos por uma atualização.

Mostrar progresso

Publique um cartão com um loader, atualize o subtexto dele à medida que o job avança e termine com o resultado. O loader é um spinner com uma linha e uma linha menor embaixo (loader_text, loader_sub_text).

javascript
const { callback_url } = await post({
  message_container: { color: 'blue', loader: true, loader_text: 'Deploying…', loader_sub_text: 'Step 1 of 3: building' }
});

const update = (body) => {
  return fetch(callback_url, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
};

await build();
await update({ message_container: { color: 'blue', loader: true, loader_text: 'Deploying…', loader_sub_text: 'Step 2 of 3: running migrations' } });

await migrate();
await update({
  message_container: { color: 'green', title: 'Deploy complete', description: 'v2.1 is live on production.' },
  actions: [{ type: 'url:https://ci.example.com/deploys/218', text: 'View logs', color: 'green' }]
});

Apagar uma mensagem

Envie DELETE para a callback_url e a mensagem some para todos. Depois disso, a URL não pode ser usada de novo.

Escutar uma mensagem

Uma stream_url é um stream ao vivo (Server-Sent Events) do que acontece na sua mensagem. Abra-a e os eventos chegam na hora em que acontecem, cada um como uma linha JSON data: cujo type diz o que ele é:

sse
curl -N "$STREAM_URL"

data: {"type": "reaction", "message_id": "...", "emoji": ":tada:", "action": "add", "member_guid": "...", "member": {...}, "ts": 1790000000000}

data: {"type": "action", "message_id": "...", "action_id": "approve", "action": {"id": "approve", "payload": {"deploy": 218}, ...}, "member_guid": "...", "member": {...}, "ts": 1790000004200}

data: {"type": "reply", "message_id": "...", "content": "Ship it!", "member_guid": "...", "member": {...}, "ts": 1790000009800}

event: expired
data: {}
EventoQuandoDados
actionUm botão foi tocado.action_id, e o botão guardado em action com o payload dele
reactionUma reação foi adicionada ou removida.emoji, e action: add, remove ou removeall
replyAlguém respondeu à mensagem.O content da resposta
expiredO stream está fechando. Enviado como evento nomeado.Nenhum
Os eventos não ficam guardados para depois. Abra o stream assim que tiver a URL: o que acontece antes de você se conectar não é enviado. Todo evento também traz o message_id, quem fez (member_guid, member) e quando (ts). Uma linha de comentário a cada 20 segundos mantém a conexão aberta.

Escutando em JavaScript

javascript
const events = new EventSource(streamUrl);

// Every event arrives as a plain message; its kind is in "type".
events.onmessage = (e) => {
  const ev = JSON.parse(e.data);
  if ((ev.type === 'action') && (ev.action_id === 'approve')) {
    startDeploy(ev.action.payload.deploy);
  }
};

// The one named event: the stream is closing.
events.addEventListener('expired', () => {
  events.close();
});

Onde você recebe uma

De onde vemAberto por
Uma publicação por webhook com botões10 minutos, ou uma hora com "sse_event_extended_timeout": true
Toda requisição de comando10 minutos

Erros

StatusCódigoSignificado
401INVALID_TOKENO token na URL está errado.
404NOT_FOUNDO stream expirou ou nunca existiu.

Continue criando