Nachrichten live aktualisieren
Eine Nachricht muss nicht so bleiben, wie sie gepostet wurde. Zeig den Fortschritt, während ein Job läuft, tausch einen Loader gegen das Ergebnis, nimm die Buttons weg, sobald jemand entschieden hat, oder lösch sie. Alle im Kanal sehen die Änderung sofort.
Was du damit machen kannst
- Die Karte aktualisierenÄndere Text, Farbe und Buttons, an Ort und Stelle.
- Fortschritt zeigenEin Loader, der Schritt für Schritt weiterläuft, und dann das Ergebnis.
- Sie löschenEntferne eine Nachricht, sobald sie nicht mehr stimmt.
- MithörenAntworten, Reaktionen und Button-Drücke auf deine Nachricht, live.
In der App
Mit einem Loader gepostet
Aktualisiert: Schritt 2 von 3
Aktualisiert: fertig, mit einem Button
Eine Nachricht, zweimal über ihre Callback-URL aktualisiert. Niemand sieht drei Nachrichten, nur eine, die sich ändert.
Schnellstart
Die Callback-URL aufbewahren
Jeder Post per Webhook und jeder Request zu einem Befehl bringt eine
callback_urlfür diese Nachricht mit.bashBODY='{"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-..."}PUT zum Aktualisieren
Sende den neuen Zustand. Die Karte ändert sich für alle an Ort und Stelle.
bashcurl -X PUT "$CALLBACK_URL" -H "Content-Type: application/json" \ -d '{"message_container": {"color": "green", "title": "Deploy complete", "description": "v2.1 is live."}}'DELETE zum Entfernen
Kein Body nötig.
bashcurl -X DELETE "$CALLBACK_URL"
Eine Nachricht aktualisieren
Sende JSON per PUT an die callback_url. Schick nur, was du ändern willst.
| Feld | Typ | Was es tut |
|---|---|---|
message_container | object | Die neue Karte. Siehe Nachrichtenkarten. |
actions | array | Neue Buttons. "actions": [] entfernt alle; lässt du das Feld weg, bleiben sie. |
content | string | Neuer Text. |
title, description, color, loader, ... | string | Kurzform: Kartenfelder auf oberster Ebene werden für dich in eine Karte verpackt. |
message_container ersetzt die alte Karte vollständig: Ein Feld, das du weglässt, ist weg. Nur Typ, Name und Avatar werden übernommen. Sende also jedes Mal die komplette Karte.Antworten
| Status | Code | Bedeutung |
|---|---|---|
200 | {"success": true} | Angenommen. Das Update folgt direkt danach. |
400 | MISSING_FIELDS | Im Body steht nichts zum Aktualisieren. |
400 | INVALID_BODY | Der Body ist kein gültiges JSON. |
400 | ein Button-Code | Mit einem Button stimmt etwas nicht, siehe Buttons. |
401 | INVALID_TOKEN | Die URL ist nicht gültig. |
404 | TOKEN_NOT_FOUND | Die URL ist abgelaufen oder wurde schon zum Löschen der Nachricht verwendet. |
502 | PUBLISH_FAILED | Das Update konnte nicht zugestellt werden. Versuch es erneut. |
Wie lange sie funktioniert
30 Minuten ab dem Moment, in dem die Nachricht gepostet oder der Befehl benutzt wurde. Ein Update verlängert das nicht. Das Löschen der Nachricht verbraucht die URL. Über ein Update lassen sich keine Dateien hinzufügen.
Fortschritt zeigen
Poste eine Karte mit Loader, aktualisiere ihren Untertext, während der Job vorankommt, und ende mit dem Ergebnis. Der Loader ist ein Spinner mit einer Zeile und einer kleineren Zeile darunter (loader_text, loader_sub_text).
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' }]
});Eine Nachricht löschen
Sende DELETE an die callback_url, und die Nachricht ist für alle weg. Danach lässt sich die URL nicht mehr verwenden.
Eine Nachricht mithören
Eine stream_url ist ein Live-Stream (Server-Sent Events) dessen, was auf deiner Nachricht passiert. Öffne ihn, und Events kommen an, sobald sie passieren, jedes als JSON-Zeile data:, deren type sagt, was es ist:
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: {}| Event | Wann | Daten |
|---|---|---|
action | Ein Button wurde gedrückt. | action_id und der gespeicherte Button in action samt payload |
reaction | Eine Reaktion wurde hinzugefügt oder entfernt. | emoji und action: add, remove oder removeall |
reply | Jemand hat auf die Nachricht geantwortet. | Der content der Antwort |
expired | Der Stream wird geschlossen. Als benanntes Event gesendet. | Keine |
message_id, wer es ausgelöst hat (member_guid, member) und wann (ts). Eine Kommentarzeile alle 20 Sekunden hält die Verbindung offen.Mithören in 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();
});Wo du einen bekommst
| Woher du ihn bekommst | Wie lange offen |
|---|---|
| Ein Webhook-Post mit Buttons | 10 Minuten, oder eine Stunde mit "sse_event_extended_timeout": true |
| Jeder Request zu einem Befehl | 10 Minuten |
Fehler
| Status | Code | Bedeutung |
|---|---|---|
401 | INVALID_TOKEN | Das Token in der URL ist falsch. |
404 | NOT_FOUND | Der Stream ist abgelaufen oder hat nie existiert. |