Aller au contenu principal
Développeurs Mises à jour en direct

Mettre à jour des messages en direct

Un message n’a pas à rester tel qu’il a été publié. Affiche la progression pendant qu’une tâche tourne, remplace un chargement par le résultat, retire les boutons une fois que quelqu’un a décidé, ou supprime-le. Tout le monde dans le salon voit le changement aussitôt.

Ce que vous pouvez faire

  • Mettre à jour la carteChange le texte, la couleur et les boutons, sur place.
  • Afficher la progressionUn chargement qui passe par des étapes, puis le résultat.
  • Le supprimerRetire un message quand il n’est plus vrai.
  • L’écouterLes réponses, réactions et appuis sur les boutons de ton message, en direct.

Dans l'app

Publiée avec un chargement

Mise à jour : étape 2 sur 3

Mise à jour : terminée, avec un bouton

Un seul message, mis à jour deux fois via son URL de callback. Personne ne voit trois messages, seulement un qui change.

Démarrage rapide

  1. Garde l’URL de callback

    Chaque publication par webhook et chaque requête de commande arrive avec une callback_url pour ce message.

    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 pour mettre à jour

    Envoie le nouvel état. La carte change sur place pour tout le monde.

    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 pour supprimer

    Aucun corps nécessaire.

    bash
    curl -X DELETE "$CALLBACK_URL"

Mettre à jour un message

Envoie du JSON en PUT à la callback_url. N’envoie que ce que tu veux changer.

ChampTypeCe qu’il fait
message_containerobjectLa nouvelle carte. Voir cartes de message.
actionsarrayDe nouveaux boutons. "actions": [] les retire tous ; sans le champ, ils sont conservés.
contentstringUn nouveau texte.
title, description, color, loader, ...stringRaccourci : les champs de carte placés au premier niveau sont regroupés dans une carte pour toi.
Un nouveau message_container remplace l’ancienne carte en entier : un champ que tu omets disparaît. Seuls son type, son nom et son avatar sont conservés. Envoie donc la carte complète à chaque fois.

Réponses

StatutCodeSignification
200{"success": true}Acceptée. La mise à jour suit juste après.
400MISSING_FIELDSRien à mettre à jour dans le corps.
400INVALID_BODYLe corps n’est pas du JSON valide.
400un code de boutonUn bouton pose problème, voir boutons.
401INVALID_TOKENL’URL n’est pas valide.
404TOKEN_NOT_FOUNDL’URL a expiré ou a servi à supprimer le message.
502PUBLISH_FAILEDLa mise à jour n’a pas pu être livrée. Réessaie.

Combien de temps elle fonctionne

30 minutes à partir du moment où le message a été publié, ou où la commande a été utilisée. Une mise à jour ne prolonge pas ce délai. Supprimer le message rend l’URL inutilisable. Une mise à jour ne permet pas d’ajouter des fichiers.

Afficher la progression

Publie une carte avec un chargement, mets à jour sa ligne secondaire à mesure que la tâche avance, et termine sur le résultat. Le chargement est un indicateur qui tourne, avec une ligne et une ligne plus petite en dessous (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' }]
});

Supprimer un message

Envoie DELETE à la callback_url et le message disparaît pour tout le monde. L’URL ne peut plus servir ensuite.

Écouter un message

Une stream_url est un flux en direct (Server-Sent Events) de ce qui se passe sur ton message. Ouvre-la et les événements arrivent au fur et à mesure, chacun sous forme de ligne JSON data: dont le type indique de quoi il s’agit :

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: {}
ÉvénementQuandDonnées
actionUn bouton a été pressé.action_id, et le bouton stocké dans action avec son payload
reactionUne réaction a été ajoutée ou retirée.emoji, et action : add, remove ou removeall
replyQuelqu’un a répondu au message.Le content de la réponse
expiredLe flux se ferme. Envoyé comme événement nommé.Aucune
Les événements ne sont pas conservés pour plus tard. Ouvre le flux dès que tu as l’URL : ce qui se passe avant ta connexion n’est pas envoyé. Chaque événement porte aussi le message_id, l’auteur de l’action (member_guid, member) et le moment (ts). Une ligne de commentaire toutes les 20 secondes garde la connexion ouverte.

Écouter en 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();
});

Où en obtenir une

D’où elle vientOuverte pendant
Une publication par webhook avec des boutons10 minutes, ou une heure avec "sse_event_extended_timeout": true
Chaque requête de commande10 minutes

Erreurs

StatutCodeSignification
401INVALID_TOKENLe jeton dans l’URL est faux.
404NOT_FOUNDLe flux a expiré ou n’a jamais existé.

Continuer