Repository: slack-go/slack
Pull request #1083 (2022-06-29 13:05:43)

Metadata Support
## Disclaimer

I am somewhat new to this library AND to writing Go Code, feel free to correct me or suggest changes I am happily learning!

## Should this be an issue instead [NO]

## API changes

Add support for Metadata, as requested by: 
https://github.com/slack-go/slack/issues/1057

https://api.slack.com/metadata/publishing

Changes:
* added `MsgOptionMetadata` in `chat.go`, so we can add metadata to postMessage
* added `includeAllMetadata` to conversationHistory to retrieve existing metadata.




Patch:
diff --git a/chat.go b/chat.go
index 34848d1..4448e9f 100644
--- a/chat.go
+++ b/chat.go
@@ -64,6 +64,9 @@ type PostMessageParameters struct {
 	// chat.postEphemeral support
 	Channel string `json:"channel"`
 	User    string `json:"user"`
+
+	// chat metadata support
+	MetaData SlackMetadata `json:"metadata"`
 }
 
 // NewPostMessageParameters provides an instance of PostMessageParameters with all the sane default values set
@@ -285,6 +288,7 @@ type sendConfig struct {
 	endpoint        string
 	values          url.Values
 	attachments     []Attachment
+	metadata        SlackMetadata
 	blocks          Blocks
 	responseType    string
 	replaceOriginal bool
@@ -306,6 +310,7 @@ func (t sendConfig) BuildRequestContext(ctx context.Context, token, channelID st
 			endpoint:        t.endpoint,
 			values:          t.values,
 			attachments:     t.attachments,
+			metadata:        t.metadata,
 			blocks:          t.blocks,
 			responseType:    t.responseType,
 			replaceOriginal: t.replaceOriginal,
@@ -336,6 +341,7 @@ type responseURLSender struct {
 	endpoint        string
 	values          url.Values
 	attachments     []Attachment
+	metadata        SlackMetadata
 	blocks          Blocks
 	responseType    string
 	replaceOriginal bool
@@ -352,6 +358,7 @@ func (t responseURLSender) BuildRequestContext(ctx context.Context) (*http.Reque
 		Timestamp:       t.values.Get("ts"),
 		Attachments:     t.attachments,
 		Blocks:          t.blocks,
+		Metadata:        t.metadata,
 		ResponseType:    t.responseType,
 		ReplaceOriginal: t.replaceOriginal,
 		DeleteOriginal:  t.deleteOriginal,
@@ -662,6 +669,18 @@ func MsgOptionIconEmoji(iconEmoji string) MsgOption {
 	}
 }
 
+// MsgOptionMetadata sets message metadata
+func MsgOptionMetadata(metadata SlackMetadata) MsgOption {
+	return func(config *sendConfig) error {
+		config.metadata = metadata
+		meta, err := json.Marshal(metadata)
+		if err == nil {
+			config.values.Set("metadata", string(meta))
+		}
+		return err
+	}
+}
+
 // UnsafeMsgOptionEndpoint deliver the message to the specified endpoint.
 // NOTE: USE AT YOUR OWN RISK: No issues relating to the use of this Option
 // will be supported by the library, it is subject to change without notice that
diff --git a/conversation.go b/conversation.go
index 2993626..e523716 100644
--- a/conversation.go
+++ b/conversation.go
@@ -571,12 +571,13 @@ func (api *Client) JoinConversationContext(ctx context.Context, channelID string
 }
 
 type GetConversationHistoryParameters struct {
-	ChannelID string
-	Cursor    string
-	Inclusive bool
-	Latest    string
-	Limit     int
-	Oldest    string
+	ChannelID          string
+	Cursor             string
+	Inclusive          bool
+	Latest             string
+	Limit              int
+	Oldest             string
+	IncludeAllMetadata bool
 }
 
 type GetConversationHistoryResponse struct {
@@ -615,6 +616,11 @@ func (api *Client) GetConversationHistoryContext(ctx context.Context, params *Ge
 	if params.Oldest != "" {
 		values.Add("oldest", params.Oldest)
 	}
+	if params.IncludeAllMetadata {
+		values.Add("include_all_metadata", "1")
+	} else {
+		values.Add("include_all_metadata", "0")
+	}
 
 	response := GetConversationHistoryResponse{}
 
diff --git a/messages.go b/messages.go
index 1a3110e..3334045 100644
--- a/messages.go
+++ b/messages.go
@@ -129,6 +129,9 @@ type Msg struct {
 	ReplaceOriginal bool   `json:"replace_original"`
 	DeleteOriginal  bool   `json:"delete_original"`
 
+	// metadata
+	Metadata SlackMetadata `json:"metadata,omitempty"`
+
 	// Block type Message
 	Blocks Blocks `json:"blocks,omitempty"`
 	// permalink
diff --git a/metadata.go b/metadata.go
new file mode 100644
index 0000000..a8c0650
--- /dev/null
+++ b/metadata.go
@@ -0,0 +1,7 @@
+package slack
+
+// SlackMetadata https://api.slack.com/reference/metadata
+type SlackMetadata struct {
+	EventType    string                 `json:"event_type"`
+	EventPayload map[string]interface{} `json:"event_payload"`
+}


Test patch:
diff --git a/chat_test.go b/chat_test.go
index 40cea90..7a549fa 100644
--- a/chat_test.go
+++ b/chat_test.go
@@ -82,6 +82,14 @@ func TestPostMessage(t *testing.T) {
 	blockStr := `[{"type":"context","block_id":"context","elements":[{"type":"plain_text","text":"hello"}]}]`
 
 	tests := map[string]messageTest{
+		"OnlyBasicProperties": {
+			endpoint: "/chat.postMessage",
+			opt:      []MsgOption{},
+			expected: url.Values{
+				"channel": []string{"CXXX"},
+				"token":   []string{"testing-token"},
+			},
+		},
 		"Blocks": {
 			endpoint: "/chat.postMessage",
 			opt: []MsgOption{
@@ -109,6 +117,24 @@ func TestPostMessage(t *testing.T) {
 				"token":       []string{"testing-token"},
 			},
 		},
+		"Metadata": {
+			endpoint: "/chat.postMessage",
+			opt: []MsgOption{
+				MsgOptionMetadata(
+					SlackMetadata{
+						EventType: "testing-event",
+						EventPayload: map[string]interface{}{
+							"id":   13,
+							"name": "testing-name",
+						},
+					}),
+			},
+			expected: url.Values{
+				"metadata": []string{`{"event_type":"testing-event","event_payload":{"id":13,"name":"testing-name"}}`},
+				"channel":  []string{"CXXX"},
+				"token":    []string{"testing-token"},
+			},
+		},
 		"Unfurl": {
 			endpoint: "/chat.unfurl",
 			opt: []MsgOption{