From 7bbb5ef3d513f223948b6ba71bde16e68f45fb28 Mon Sep 17 00:00:00 2001 From: Tom Moulard Date: Tue, 30 Apr 2024 17:43:37 +0200 Subject: [PATCH] feat: send files in send_messages --- .golangci.yml | 1 + pkg/message/send_message.go | 43 ++++++++++- pkg/message/send_message_test.go | 128 +++++++++++++++++++++++-------- 3 files changed, 135 insertions(+), 37 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 8fe5888..6453d07 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -97,6 +97,7 @@ issues: - path: '(.+)_test.go' linters: - funlen + - gosec - path: 'pkg/client/errors_test.go' text: 'tests: ExampleHandleError refers to unknown identifier: HandleError' linters: diff --git a/pkg/message/send_message.go b/pkg/message/send_message.go index 52945ec..4486c3e 100644 --- a/pkg/message/send_message.go +++ b/pkg/message/send_message.go @@ -6,15 +6,41 @@ import ( "fmt" ) +// File is a fiel to send. +type File struct { + // URL specifies the URL of the file hosted on the server of your own or + // other third-party companies. + URL string `json:"url"` + // FileName specifies the name of the file. The file_name can be any string + // you've set to this property. If no file_name value is supplied, the + // files.file_name property defaults to an empty string. + FileName string `json:"file_name,omitempty"` + // FileSize specifies the size of the file in bytes. The file_size can be set + // to be any int you've set to this property. If no files.file_size value is + // supplied, it defaults to 0. File size is stored in bytes. + FileSize int `json:"file_size,omitempty"` + // FileType specifies the type of the file. The file_type can be set to any + // string you've set to this property. If no files.file_type value is + // supplied, it defaults to an empty string. + FileType string `json:"file_type,omitempty"` +} + // SendMessageRequest is the request to send a message. type SendMessageRequest struct { // MessageType specifies the type of the message. MessageType MessageType `json:"message_type"` // UserID specifies the user ID of the sender. UserID string `json:"user_id"` + // Message specifies the content of the message. - Message string `json:"message"` + Message string `json:"message,omitempty"` + // Files specifies the data of files to upload to the Sendbird server by + // their location. + Files []File `json:"files,omitempty"` + // Thumbnails specifies an array of external thumbnail image URLs to store a + // reference to those images in the Sendbird server. + Thumbnails []string `json:"thumbnails,omitempty"` // CustomType specifies a custom message type used for message grouping. The // length is limited to 128 characters. CustomType string `json:"custom_type,omitempty"` @@ -97,8 +123,19 @@ func (smr *SendMessageRequest) Validate() error { return errors.New("message type is required") case smr.UserID == "": return errors.New("user ID is required") - case smr.Message == "": - return errors.New("message is required") + } + + switch { + case smr.MessageType == MessageTypeText && smr.Message == "": + return errors.New("message is required for text message") + case smr.MessageType == MessageTypeFile && len(smr.Files) == 0: + return errors.New("files are required for file message") + case smr.MessageType == MessageTypeFile: + for _, file := range smr.Files { + if file.URL == "" { + return errors.New("file URL is required") + } + } } return nil diff --git a/pkg/message/send_message_test.go b/pkg/message/send_message_test.go index 05d8840..daa43a0 100644 --- a/pkg/message/send_message_test.go +++ b/pkg/message/send_message_test.go @@ -35,7 +35,7 @@ func TestValidateSMR(t *testing.T) { assertErr: assert.Error, }, { - name: "Without Message Type", + name: "without Message Type", smr: SendMessageRequest{ UserID: "42", Message: "Hello, World!", @@ -43,7 +43,7 @@ func TestValidateSMR(t *testing.T) { assertErr: assert.Error, }, { - name: "Without user id", + name: "without user id", smr: SendMessageRequest{ MessageType: MessageTypeText, Message: "Hello, World!", @@ -51,7 +51,7 @@ func TestValidateSMR(t *testing.T) { assertErr: assert.Error, }, { - name: "Without message", + name: "text message without message", smr: SendMessageRequest{ MessageType: MessageTypeText, UserID: "42", @@ -59,7 +59,24 @@ func TestValidateSMR(t *testing.T) { assertErr: assert.Error, }, { - name: "Valid", + name: "file message without files", + smr: SendMessageRequest{ + MessageType: MessageTypeFile, + UserID: "42", + }, + assertErr: assert.Error, + }, + { + name: "file message with files, but not url", + smr: SendMessageRequest{ + MessageType: MessageTypeFile, + UserID: "42", + Files: []File{{}}, + }, + assertErr: assert.Error, + }, + { + name: "valid text message", smr: SendMessageRequest{ MessageType: MessageTypeText, UserID: "42", @@ -67,6 +84,18 @@ func TestValidateSMR(t *testing.T) { }, assertErr: assert.NoError, }, + { + name: "valid file message", + smr: SendMessageRequest{ + MessageType: MessageTypeFile, + UserID: "42", + Files: []File{ + {URL: "https://example.com/file1"}, + {URL: "https://example.com/file2"}, + }, + }, + assertErr: assert.NoError, + }, } for _, test := range tests { @@ -82,38 +111,69 @@ func TestValidateSMR(t *testing.T) { func TestSendMessage(t *testing.T) { t.Parallel() - client := newClientMock(t) - message := NewMessage(client) - - sendMessageRequest := SendMessageRequest{ - MessageType: MessageTypeText, - UserID: "42", - Message: "Hello, World!", - CustomType: "custom-type", - Data: `{ "key": "value" }`, - SendPush: ptr(true), - PushMessageTemplate: "push-notification-template", - MentionType: MentionTypeChannels, - MentionUserIDs: []string{"mention-user-id"}, - IsSilent: ptr(true), - MarkAsRead: ptr(true), - SortedMetaArray: []MetaArray{{Key: "key1", Value: []string{"value1"}}, {Key: "key2", Value: []string{"value2"}}}, - CreatedAt: 42, - PollID: 42, - IncludePollDetails: ptr(true), - DedupID: "dedup-id", - ApnsBundleID: "apns-bundle-id", - Sound: "sound", - Volume: 0.5, + tests := []struct { + name string + smrq SendMessageRequest + smrp SendMessageResponse + }{ + { + name: "Text Message", + smrq: SendMessageRequest{ + MessageType: MessageTypeText, + UserID: "42", + Message: "Hello, World!", + CustomType: "custom-type", + Data: `{ "key": "value" }`, + SendPush: ptr(true), + PushMessageTemplate: "push-notification-template", + MentionType: MentionTypeChannels, + MentionUserIDs: []string{"mention-user-id"}, + IsSilent: ptr(true), + MarkAsRead: ptr(true), + SortedMetaArray: []MetaArray{ + {Key: "key1", Value: []string{"value1"}}, + {Key: "key2", Value: []string{"value2"}}, + }, + CreatedAt: 42, + PollID: 42, + IncludePollDetails: ptr(true), + DedupID: "dedup-id", + ApnsBundleID: "apns-bundle-id", + Sound: "sound", + Volume: 0.5, + }, + smrp: SendMessageResponse{ + MessageID: 42, + }, + }, + { + name: "File Message", + smrq: SendMessageRequest{ + MessageType: MessageTypeFile, + UserID: "42", + Files: []File{ + {URL: "https://example.com/file1"}, + {URL: "https://example.com/file2"}, + }, + }, + smrp: SendMessageResponse{ + MessageID: 42, + }, + }, } - sendMessageResponse := &SendMessageResponse{ - MessageID: 42, - } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + t.Parallel() - client.OnPost("/group_channels/url/messages", sendMessageRequest, &SendMessageResponse{}).Return(sendMessageResponse, nil) + client := newClientMock(t) + message := NewMessage(client) + client.OnPost("/group_channels/url/messages", test.smrq, &SendMessageResponse{}).Return(&test.smrp, nil) - cur, err := message.SendMessage(context.Background(), ChannelTypeGroup, "url", sendMessageRequest) - require.NoError(t, err) - assert.Equal(t, sendMessageResponse, cur) + cur, err := message.SendMessage(context.Background(), ChannelTypeGroup, "url", test.smrq) + require.NoError(t, err) + require.NotNil(t, cur) + assert.Equal(t, test.smrp, *cur) + }) + } }