Metadata and safe edits
Keep application metadata attached while constructing an updated message. Follow each language’s ownership rules; metadata is not visible message content.
Output
Local preview of the selected language’s tested example. Slack client appearance may differ; controls here do not send requests.
Updated
Metadata accompanies the message and is not shown in Slack.
{
"event_type": "build",
"event_payload": {
"count": 0,
"enabled": false,
"missing": null
}
}
Serialized output
{
"channel": "C1",
"mrkdwn": true,
"text": "Updated",
"metadata": {
"event_type": "build",
"event_payload": {
"count": 0,
"enabled": false,
"missing": null
}
}
}
Code
Metadata is application data, not visible Slack message content. Copy Python models before changing a shared template.
from copy import deepcopy
from slackblocks import Message
original = Message(channel="C1", text="Ready", metadata={
"event_type": "build", "event_payload": {"count": 0, "enabled": False, "missing": None},
})
updated = deepcopy(original) # Python models are mutable.
updated.text = "Updated"
assert original.text == "Ready"
print(updated.json())
import * as S from "@nicklambourne/slackblocks";
const metadata = {event_type: "build", event_payload: {count: 0, enabled: false, missing: null}};
const original = S.Message().channel("C1").text("Ready").metadata(metadata).build();
const updated = S.Message().channel("C1").text("Updated").metadata(metadata).build();
if (original.text !== "Ready") throw new Error("Original changed");
console.log(JSON.stringify(updated));
package main
import (
"encoding/json"
s "github.com/nicklambourne/slackblocks/go/v3"
"os"
)
func main() {
metadata := s.Object{"event_type": "build", "event_payload": s.Object{"count": 0, "enabled": false, "missing": nil}}
original, err := s.NewMessage().Channel("C1").Text("Ready").Metadata(metadata).Build()
if err != nil {
panic(err)
}
value, err := s.NewMessage().Channel("C1").Text("Updated").Metadata(metadata).Build()
if original["text"] != "Ready" {
panic("Original changed")
}
if err != nil {
panic(err)
}
if err := json.NewEncoder(os.Stdout).Encode(value); err != nil {
panic(err)
}
}
The Java metadata setter rejects null values. Omit absent fields; do not substitute an explicit null. Built values snapshot the supplied metadata.
import io.github.nicklambourne.slackblocks.*;
import io.github.nicklambourne.slackblocks.block.*;
import io.github.nicklambourne.slackblocks.component.*;
import io.github.nicklambourne.slackblocks.element.*;
import io.github.nicklambourne.slackblocks.object.*;
import io.github.nicklambourne.slackblocks.payload.*;
import java.util.List;
import java.util.Map;
public final class Recipe {
public static void main(String[] args) throws Exception {
var fields = new java.util.LinkedHashMap<String, Object>();
fields.put("count", 0); fields.put("enabled", false);
var metadata = Map.<String, Object>of("event_type", "build", "event_payload", fields);
var original = MessagePayload.builder().channel("C1").text("Ready").metadata(metadata).build();
var value = MessagePayload.builder().channel("C1").text("Updated").metadata(metadata).build();
if (!original.toMap().get("text").equals("Ready")) throw new AssertionError("Original changed");
System.out.println(value.toJson());
}
}
using System;
using System.Collections.Generic;
using Slackblocks;
using Slackblocks.Blocks;
using Slackblocks.Components;
using Slackblocks.Elements;
using Slackblocks.Objects;
using Slackblocks.Payloads;
var metadata = new Dictionary<string, object?> {
["event_type"] = "build", ["event_payload"] = new Dictionary<string, object?> { ["count"] = 0, ["enabled"] = false, ["missing"] = null },
};
var original = new MessagePayload("C1", text: "Ready", metadata: metadata);
var value = new MessagePayload("C1", text: "Updated", metadata: metadata);
if (original.Text != "Ready") throw new InvalidOperationException("Original changed");
Console.WriteLine(value.ToJson());
require "slackblocks"
include Slackblocks
original = MessagePayload.new(channel: "C1", text: "Ready", metadata: {
"event_type" => "build", "event_payload" => {"count" => 0, "enabled" => false, "missing" => nil}
})
value = original.with(text: "Updated")
raise "Original changed" unless original.text == "Ready"
puts value.to_json
use slackblocks::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let original = MessagePayload::builder("C1").text("Ready")
.metadata(serde_json::from_value(serde_json::json!({"event_type": "build", "event_payload": {"count": 0, "enabled": false, "missing": null}}))?)
.build()?;
let updated = original.clone().into_builder().text("Updated").build()?;
assert_eq!(original.text(), Some("Ready"));
println!("{}", serde_json::to_string(&updated)?);
Ok(())
}
<?php
declare(strict_types=1);
require 'vendor/autoload.php';
use Slackblocks as S;
$metadata = new S\JsonObject(['event_type' => 'deployment', 'event_payload' => (object) ['context' => (object) [], 'optional' => null, 'enabled' => false, 'count' => 0]]);
$message = new S\MessagePayload(channel: 'C1', text: 'Ready', metadata: $metadata, unfurlLinks: false);
$edited = $message->with(text: 'Complete');
assert($message->text === 'Ready');
echo $edited->toJson();
original = Slackblocks.Message.new!(channel: "C1", metadata: %{
"event_type" => "build", "event_payload" => %{"count" => 0, "enabled" => false, "missing" => nil, "object" => %{}, "array" => []}
})
updated = Slackblocks.Message.change!(original, text: "Updated")
Slackblocks.to_map!(updated)
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson (encode)
import qualified Data.Aeson
import qualified Data.Map.Strict as Map
import Slackblocks
example = do
original <-
buildMessagePayload
( (messagePayload "C1")
{ messagePayloadMetadata =
Just
( Map.fromList
[ ("event_type", Data.Aeson.String "build"),
("event_payload", Data.Aeson.object ["count" Data.Aeson..= (0 :: Integer), "enabled" Data.Aeson..= False, "missing" Data.Aeson..= Data.Aeson.Null])
]
)
}
)
buildMessagePayload ((inspectMessagePayload original) {messagePayloadText = Just "Updated"})