Repository: slack-go/slack (go)

Issue:
file_ids for chat.update
To work correctly with files, it is necessary to implement support the file_ids optional field for chat.update.
at now, MsgOptionFileIDs is not exist (

Pull request description:
feat: add ability to add file ids when updating a message
Closes #1450.

Patch:
diff --git a/chat.go b/chat.go
index 11324c9..85c4848 100644
--- a/chat.go
+++ b/chat.go
@@ -68,6 +68,9 @@ type PostMessageParameters struct {
 
 	// chat metadata support
 	MetaData SlackMetadata `json:"metadata"`
+
+	// file_ids support
+	FileIDs []string `json:"file_ids,omitempty"`
 }
 
 // NewPostMessageParameters provides an instance of PostMessageParameters with all the sane default values set
@@ -715,6 +718,23 @@ func MsgOptionLinkNames(linkName bool) MsgOption {
 	}
 }
 
+// MsgOptionFileIDs sets file IDs for the message
+func MsgOptionFileIDs(fileIDs []string) MsgOption {
+	return func(config *sendConfig) error {
+		if len(fileIDs) == 0 {
+			return nil
+		}
+
+		fileIDsBytes, err := json.Marshal(fileIDs)
+		if err != nil {
+			return err
+		}
+
+		config.values.Set("file_ids", string(fileIDsBytes))
+		return nil
+	}
+}
+
 // 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
@@ -778,6 +798,10 @@ func MsgOptionPostMessageParameters(params PostMessageParameters) MsgOption {
 			config.values.Set("reply_broadcast", "true")
 		}
 
+		if len(params.FileIDs) > 0 {
+			return MsgOptionFileIDs(params.FileIDs)(config)
+		}
+
 		return nil
 	}
 }


Test patch:
diff --git a/chat_test.go b/chat_test.go
index ab326f2..010389d 100644
--- a/chat_test.go
+++ b/chat_test.go
@@ -367,3 +367,61 @@ func TestSendMessageContextRedactsTokenInDebugLog(t *testing.T) {
 		})
 	}
 }
+
+func TestUpdateMessage(t *testing.T) {
+	type messageTest struct {
+		endpoint string
+		opt      []MsgOption
+		expected url.Values
+	}
+	tests := map[string]messageTest{
+		"empty file_ids": {
+			endpoint: "/chat.update",
+			opt:      []MsgOption{},
+			expected: url.Values{
+				"channel": []string{"CXXX"},
+				"token":   []string{"testing-token"},
+				"ts":      []string{"1234567890.123456"},
+			},
+		},
+		"with file_ids": {
+			endpoint: "/chat.update",
+			opt: []MsgOption{
+				MsgOptionFileIDs([]string{"F123", "F456"}),
+			},
+			expected: url.Values{
+				"channel":  []string{"CXXX"},
+				"token":    []string{"testing-token"},
+				"ts":       []string{"1234567890.123456"},
+				"file_ids": []string{`["F123","F456"]`},
+			},
+		},
+	}
+
+	once.Do(startServer)
+	api := New(validToken, OptionAPIURL("http://"+serverAddr+"/"))
+
+	for name, test := range tests {
+		t.Run(name, func(t *testing.T) {
+			http.DefaultServeMux = new(http.ServeMux)
+			http.HandleFunc(test.endpoint, func(rw http.ResponseWriter, r *http.Request) {
+				body, err := io.ReadAll(r.Body)
+				if err != nil {
+					t.Errorf("unexpected error: %v", err)
+					return
+				}
+				actual, err := url.ParseQuery(string(body))
+				if err != nil {
+					t.Errorf("unexpected error: %v", err)
+					return
+				}
+				if !reflect.DeepEqual(actual, test.expected) {
+					t.Errorf("\nexpected: %s\n  actual: %s", test.expected, actual)
+					return
+				}
+			})
+
+			_, _, _, _ = api.UpdateMessage("CXXX", "1234567890.123456", test.opt...)
+		})
+	}
+}