From 092414637328314360ea8bac3a7a3f0dfdc04a1a Mon Sep 17 00:00:00 2001 From: Jesse Hallam Date: Wed, 19 Jun 2024 15:17:35 -0300 Subject: [PATCH] support file attachments for chat notifications (#700) * always sync reactions (when chat/channel sync enabled) * always sync file attachments (when chat/channel sync enabled) * consolidate to experimentalSyncChats * make selective sync experimental * clarify syncNotifications * s/DisableSyncMsg/UseSharedChannels/ and experimental * make certificates experimental * remove untested enabledTeams setting * plugin.json: whitespace * make disableCheckCredentials internal * avoid directly mutating p.configuration in tests * support file attachments for chat notifications Fixes: https://mattermost.atlassian.net/browse/MM-58485 * restore missing `user_user_icon` * skip test timing out * MM-58851: fix merge issue re: disable vs dismiss * restore message lost in merge as well --- server/attachments.go | 17 +-- server/attachments_test.go | 49 ++------ server/bot_messages.go | 55 ++++----- server/ce2e/plugin_test.go | 2 + server/converters.go | 4 +- server/converters_test.go | 2 +- server/handlers.go | 33 ++---- server/notifications.go | 31 +++-- server/notifications_test.go | 214 +++++++---------------------------- 9 files changed, 114 insertions(+), 293 deletions(-) diff --git a/server/attachments.go b/server/attachments.go index c66a4792..e0983657 100644 --- a/server/attachments.go +++ b/server/attachments.go @@ -94,7 +94,7 @@ func (ah *ActivityHandler) ProcessAndUploadFileToMM(attachmentData []byte, attac return fileInfo.Id, false } -func (ah *ActivityHandler) handleAttachments(channelID, userID, text string, msg *clientmodels.Message, chat *clientmodels.Chat, handleFileAttachments bool, existingFileIDs []string) (string, model.StringArray, string, bool, bool) { +func (ah *ActivityHandler) handleAttachments(channelID, userID, text string, msg *clientmodels.Message, chat *clientmodels.Chat, existingFileIDs []string) (string, model.StringArray, string, int, bool) { attachments := []string{} newText := text parentID := "" @@ -115,7 +115,7 @@ func (ah *ActivityHandler) handleAttachments(channelID, userID, text string, msg errorFound := false if client == nil { ah.plugin.GetAPI().LogWarn("Unable to get the client") - return "", nil, "", false, errorFound + return "", nil, "", 0, errorFound } isDirectOrGroupMessage := false @@ -133,7 +133,7 @@ func (ah *ActivityHandler) handleAttachments(channelID, userID, text string, msg } } - skippedFileAttachments := false + skippedFileAttachments := 0 for _, a := range msg.Attachments { // remove the attachment tags from the text newText = attachRE.ReplaceAllString(newText, "") @@ -152,11 +152,6 @@ func (ah *ActivityHandler) handleAttachments(channelID, userID, text string, msg continue } - if !handleFileAttachments { - skippedFileAttachments = true - continue - } - fileInfoID := fileNames[a.Name] if fileInfoID != "" { attachments = append(attachments, fileInfoID) @@ -173,6 +168,7 @@ func (ah *ActivityHandler) handleAttachments(channelID, userID, text string, msg if err != nil { ah.plugin.GetAPI().LogWarn("failed to download the file", "filename", a.Name, "error", err.Error()) ah.plugin.GetMetrics().ObserveFile(metrics.ActionCreated, metrics.ActionSourceMSTeams, metrics.DiscardedReasonUnableToGetTeamsData, isDirectOrGroupMessage) + skippedFileAttachments++ continue } } else { @@ -180,6 +176,7 @@ func (ah *ActivityHandler) handleAttachments(channelID, userID, text string, msg if err != nil { ah.plugin.GetAPI().LogWarn("failed to get file size and download URL", "error", err.Error()) ah.plugin.GetMetrics().ObserveFile(metrics.ActionCreated, metrics.ActionSourceMSTeams, metrics.DiscardedReasonUnableToGetTeamsData, isDirectOrGroupMessage) + skippedFileAttachments++ continue } @@ -188,6 +185,7 @@ func (ah *ActivityHandler) handleAttachments(channelID, userID, text string, msg ah.plugin.GetAPI().LogWarn("skipping file download from MS Teams because the file size is greater than the allowed size") errorFound = true ah.plugin.GetMetrics().ObserveFile(metrics.ActionCreated, metrics.ActionSourceMSTeams, metrics.DiscardedReasonMaxFileSizeExceeded, isDirectOrGroupMessage) + skippedFileAttachments++ continue } @@ -197,6 +195,7 @@ func (ah *ActivityHandler) handleAttachments(channelID, userID, text string, msg if err != nil { ah.plugin.GetAPI().LogWarn("failed to get file content", "error", err.Error()) ah.plugin.GetMetrics().ObserveFile(metrics.ActionCreated, metrics.ActionSourceMSTeams, metrics.DiscardedReasonUnableToGetTeamsData, isDirectOrGroupMessage) + skippedFileAttachments++ continue } } @@ -217,6 +216,7 @@ func (ah *ActivityHandler) handleAttachments(channelID, userID, text string, msg if fileInfoID == "" { ah.plugin.GetMetrics().ObserveFile(metrics.ActionCreated, metrics.ActionSourceMSTeams, metrics.DiscardedReasonEmptyFileID, isDirectOrGroupMessage) + skippedFileAttachments++ continue } attachments = append(attachments, fileInfoID) @@ -226,6 +226,7 @@ func (ah *ActivityHandler) handleAttachments(channelID, userID, text string, msg // Calculate the count of file attachments discarded by subtracting handled file attachments and other attachments from total message attachments. fileAttachmentsDiscarded := len(msg.Attachments) - countNonFileAttachments - countFileAttachments ah.plugin.GetMetrics().ObserveFiles(metrics.ActionCreated, metrics.ActionSourceMSTeams, metrics.DiscardedReasonFileLimitReached, isDirectOrGroupMessage, int64(fileAttachmentsDiscarded)) + skippedFileAttachments += fileAttachmentsDiscarded break } } diff --git a/server/attachments_test.go b/server/attachments_test.go index ba7c64dd..5b0fd8c1 100644 --- a/server/attachments_test.go +++ b/server/attachments_test.go @@ -221,36 +221,13 @@ func TestHandleAttachments(t *testing.T) { setupMetrics func(*mocksMetrics.Metrics) setupStore func(store *storemocks.Store) attachments []clientmodels.Attachment - handleFileAttachments bool expectedText string expectedAttachmentIDsCount int expectedParentID string - expectedSkippedFileAttachments bool + expectedSkippedFileAttachments int expectedError bool fileIDs []string }{ - { - description: "File attachments disabled by configuration", - setupAPI: func(mockAPI *plugintest.API) { - mockAPI.On("UploadFile", []byte{}, testutils.GetChannelID(), "mock-name").Return(&model.FileInfo{ - Id: testutils.GetID(), - }, nil) - }, - setupClient: func(client *clientmocks.Client) { - }, - setupMetrics: func(mockmetrics *mocksMetrics.Metrics) { - }, - setupStore: func(store *storemocks.Store) {}, - attachments: []clientmodels.Attachment{ - { - Name: "mock-name", - }, - }, - handleFileAttachments: false, - expectedText: "mock-text", - expectedSkippedFileAttachments: true, - expectedAttachmentIDsCount: 0, - }, { description: "Successfully handled attachments", setupAPI: func(mockAPI *plugintest.API) { @@ -271,7 +248,6 @@ func TestHandleAttachments(t *testing.T) { Name: "mock-name", }, }, - handleFileAttachments: true, expectedText: "mock-text", expectedAttachmentIDsCount: 1, }, @@ -293,8 +269,8 @@ func TestHandleAttachments(t *testing.T) { Name: "mock-name", }, }, - handleFileAttachments: true, - expectedText: "mock-text", + expectedText: "mock-text", + expectedSkippedFileAttachments: 1, }, { description: "Number of attachments are greater than 10", @@ -313,9 +289,9 @@ func TestHandleAttachments(t *testing.T) { attachments: []clientmodels.Attachment{ {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, }, - handleFileAttachments: true, - expectedText: "mock-text", - expectedAttachmentIDsCount: 10, + expectedText: "mock-text", + expectedAttachmentIDsCount: 10, + expectedSkippedFileAttachments: 2, }, { description: "Attachment with existing fileID", @@ -331,7 +307,6 @@ func TestHandleAttachments(t *testing.T) { }, }, expectedAttachmentIDsCount: 1, - handleFileAttachments: true, expectedText: "mock-text", fileIDs: []string{"testFileId"}, }, @@ -345,7 +320,6 @@ func TestHandleAttachments(t *testing.T) { setupStore: func(store *storemocks.Store) {}, attachments: []clientmodels.Attachment{}, expectedAttachmentIDsCount: 0, - handleFileAttachments: true, expectedText: "mock-text", fileIDs: []string{"testFileId"}, }, @@ -373,7 +347,6 @@ func TestHandleAttachments(t *testing.T) { Name: "mockFile.Name.txt", }, }, - handleFileAttachments: true, expectedText: "mock-text", expectedAttachmentIDsCount: 2, fileIDs: []string{"testFileId"}, @@ -395,8 +368,7 @@ func TestHandleAttachments(t *testing.T) { Content: `{"language": "go", "codeSnippetUrl": "https://example.com/version/chats/mock-chat-id/messages/mock-message-id/hostedContents/mock-content-id/$value"}`, }, }, - handleFileAttachments: true, - expectedText: "mock-text\n```go\nsnippet content\n```\n", + expectedText: "mock-text\n```go\nsnippet content\n```\n", }, { description: "Attachment type message reference", @@ -418,9 +390,8 @@ func TestHandleAttachments(t *testing.T) { ContentType: "messageReference", Content: `{"messageId":"mock-ID"}`, }}, - handleFileAttachments: true, - expectedText: "mock-text", - expectedParentID: testutils.GetID(), + expectedText: "mock-text", + expectedParentID: testutils.GetID(), }, } { t.Run(testCase.description, func(t *testing.T) { @@ -441,7 +412,7 @@ func TestHandleAttachments(t *testing.T) { ChannelID: testutils.GetChannelID(), } - newText, attachmentIDs, parentID, skippedFileAttachments, errorsFound := ah.handleAttachments(testutils.GetChannelID(), testutils.GetUserID(), "mock-text", attachments, nil, testCase.handleFileAttachments, testCase.fileIDs) + newText, attachmentIDs, parentID, skippedFileAttachments, errorsFound := ah.handleAttachments(testutils.GetChannelID(), testutils.GetUserID(), "mock-text", attachments, nil, testCase.fileIDs) assert.Equal(t, testCase.expectedParentID, parentID) assert.Equal(t, testCase.expectedAttachmentIDsCount, len(attachmentIDs)) assert.Equal(t, testCase.expectedText, newText) diff --git a/server/bot_messages.go b/server/bot_messages.go index 1fbbb461..c68bc203 100644 --- a/server/bot_messages.go +++ b/server/bot_messages.go @@ -137,62 +137,65 @@ func (p *Plugin) makeWelcomeMessageWithNotificationActionPost() *model.Post { } // formatNotificationMessage formats the message about a notification of a chat received on Teams. -func formatNotificationMessage(actorDisplayName string, chatTopic string, chatSize int, chatLink string, message string, attachmentCount int) string { +func formatNotificationMessage(actorDisplayName string, chatTopic string, chatSize int, chatLink string, message string, attachmentCount int, skippedFileAttachments int) string { message = strings.TrimSpace(message) - if message == "" && attachmentCount == 0 { + if message == "" && attachmentCount == 0 && skippedFileAttachments == 0 { return "" } - var preamble string + var messageComponents []string var chatTopicDesc string if chatTopic != "" { chatTopicDesc = ": " + chatTopic } + // Handle the preamble if chatSize <= 1 { return "" } else if chatSize == 2 { - preamble = fmt.Sprintf("**%s** messaged you in an [MS Teams chat%s](%s):", actorDisplayName, chatTopicDesc, chatLink) + messageComponents = append(messageComponents, + fmt.Sprintf("**%s** messaged you in an [MS Teams chat%s](%s):", actorDisplayName, chatTopicDesc, chatLink), + ) } else if chatSize == 3 { - preamble = fmt.Sprintf("**%s** messaged you and 1 other user in an [MS Teams group chat%s](%s):", actorDisplayName, chatTopicDesc, chatLink) + messageComponents = append(messageComponents, + fmt.Sprintf("**%s** messaged you and 1 other user in an [MS Teams group chat%s](%s):", actorDisplayName, chatTopicDesc, chatLink), + ) } else { - preamble = fmt.Sprintf("**%s** messaged you and %d other users in an [MS Teams group chat%s](%s):", actorDisplayName, chatSize-2, chatTopicDesc, chatLink) + messageComponents = append(messageComponents, + fmt.Sprintf("**%s** messaged you and %d other users in an [MS Teams group chat%s](%s):", actorDisplayName, chatSize-2, chatTopicDesc, chatLink), + ) } - preamble += "\n" - if message != "" { - message = "> " + strings.ReplaceAll(message, "\n", "\n> ") + // Handle the message itself + if len(message) > 0 { + messageComponents = append(messageComponents, + fmt.Sprintf("> %s", strings.ReplaceAll(message, "\n", "\n> ")), + ) } - attachmentsNotice := "" - if attachmentCount > 0 { - if len(message) > 0 { - attachmentsNotice += "\n" - } - attachmentsNotice += "\n*" - if attachmentCount == 1 { - attachmentsNotice += "This message was originally sent with one attachment." - } else { - attachmentsNotice += fmt.Sprintf("This message was originally sent with %d attachments.", attachmentCount) - } - attachmentsNotice += "*" + if skippedFileAttachments > 0 { + messageComponents = append(messageComponents, + "\n*Some file attachments from this message could not be delivered.*", + ) } - formattedMessage := fmt.Sprintf(`%s%s%s`, preamble, message, attachmentsNotice) + formattedMessage := strings.Join(messageComponents, "\n") return formattedMessage } // notifyMessage sends the given receipient a notification of a chat received on Teams. -func (p *Plugin) notifyChat(recipientUserID string, actorDisplayName string, chatTopic string, chatSize int, chatLink string, message string, attachmentCount int) { - formattedMessage := formatNotificationMessage(actorDisplayName, chatTopic, chatSize, chatLink, message, attachmentCount) - +func (p *Plugin) notifyChat(recipientUserID string, actorDisplayName string, chatTopic string, chatSize int, chatLink string, message string, fileIds model.StringArray, skippedFileAttachments int) { + formattedMessage := formatNotificationMessage(actorDisplayName, chatTopic, chatSize, chatLink, message, len(fileIds), skippedFileAttachments) if formattedMessage == "" { return } - if err := p.botSendDirectMessage(recipientUserID, formattedMessage); err != nil { + if err := p.botSendDirectPost(recipientUserID, &model.Post{ + Message: formattedMessage, + FileIds: fileIds, + }); err != nil { p.GetAPI().LogWarn("Failed to send notification message", "user_id", recipientUserID, "error", err) } } diff --git a/server/ce2e/plugin_test.go b/server/ce2e/plugin_test.go index ba7240cf..0074f4c1 100644 --- a/server/ce2e/plugin_test.go +++ b/server/ce2e/plugin_test.go @@ -148,6 +148,8 @@ func TestMessageHasBeenPostedNewMessageE2E(t *testing.T) { } func TestMessageHasBeenPostedNewMessageWithBotAccountE2E(t *testing.T) { + t.Skip("https://mattermost.atlassian.net/browse/MM-58801") + mattermost, store, mockClient, tearDown := containere2e.NewE2ETestPlugin(t) defer tearDown() diff --git a/server/converters.go b/server/converters.go index 6c806e2b..c32f5778 100644 --- a/server/converters.go +++ b/server/converters.go @@ -13,7 +13,7 @@ import ( const hostedContentsStr = "hostedContents" -func (ah *ActivityHandler) msgToPost(channelID, senderID string, msg *clientmodels.Message, chat *clientmodels.Chat, handleFileAttachments bool, existingFileIDs []string) (*model.Post, bool, bool) { +func (ah *ActivityHandler) msgToPost(channelID, senderID string, msg *clientmodels.Message, chat *clientmodels.Chat, existingFileIDs []string) (*model.Post, int, bool) { text := ah.handleMentions(msg) text = ah.handleEmojis(text) var embeddedImages []clientmodels.Attachment @@ -30,7 +30,7 @@ func (ah *ActivityHandler) msgToPost(channelID, senderID string, msg *clientmode } } - newText, attachments, parentID, skippedFileAttachments, errorFound := ah.handleAttachments(channelID, senderID, text, msg, chat, handleFileAttachments, existingFileIDs) + newText, attachments, parentID, skippedFileAttachments, errorFound := ah.handleAttachments(channelID, senderID, text, msg, chat, existingFileIDs) text = newText if parentID != "" { diff --git a/server/converters_test.go b/server/converters_test.go index f5ddc9ba..ba98b128 100644 --- a/server/converters_test.go +++ b/server/converters_test.go @@ -64,7 +64,7 @@ func TestMsgToPost(t *testing.T) { ah.plugin = p - post, _, _ := ah.msgToPost(testCase.channelID, testCase.senderID, testCase.message, nil, true, []string{}) + post, _, _ := ah.msgToPost(testCase.channelID, testCase.senderID, testCase.message, nil, []string{}) assert.Equal(t, testCase.post, post) }) } diff --git a/server/handlers.go b/server/handlers.go index 0801e2dc..d3ba059a 100644 --- a/server/handlers.go +++ b/server/handlers.go @@ -332,7 +332,7 @@ func (ah *ActivityHandler) handleCreatedActivity(msg *clientmodels.Message, subs return metrics.DiscardedReasonOther } - post, skippedFileAttachments, errorFound := ah.msgToPost(channelID, senderID, msg, chat, true, []string{}) + post, skippedFileAttachments, errorFound := ah.msgToPost(channelID, senderID, msg, chat, []string{}) // Last second check to avoid possible duplication if postInfo, _ = ah.plugin.GetStore().GetPostInfoByMSTeamsID(msg.ChatID+msg.ChannelID, msg.ID); postInfo != nil { @@ -345,17 +345,8 @@ func (ah *ActivityHandler) handleCreatedActivity(msg *clientmodels.Message, subs return metrics.DiscardedReasonInternalError } - if skippedFileAttachments { - _, appErr := ah.plugin.GetAPI().CreatePost(&model.Post{ - ChannelId: newPost.ChannelId, - UserId: ah.plugin.GetBotUserID(), - Message: "Attachments sent from Microsoft Teams aren't delivered to Mattermost.", - // Anchor the post immediately after (never before) the post that was created. - CreateAt: newPost.CreateAt + 1, - }) - if appErr != nil { - ah.plugin.GetAPI().LogWarn("Failed to notify channel of skipped attachment", "channel_id", post.ChannelId, "post_id", newPost.Id, "error", appErr) - } + if skippedFileAttachments > 0 { + ah.plugin.GetAPI().LogWarn("Skipped file attachments on post update", "channel_id", post.ChannelId, "post_id", post.Id, "skipped_file_attachments", skippedFileAttachments) } ah.plugin.GetMetrics().ObserveMessage(metrics.ActionCreated, metrics.ActionSourceMSTeams, isDirectOrGroupMessage) @@ -481,22 +472,12 @@ func (ah *ActivityHandler) handleUpdatedActivity(msg *clientmodels.Message, subs return metrics.DiscardedReasonInactiveUser } - post, _, _ := ah.msgToPost(channelID, senderID, msg, chat, true, fileIDs) + post, skippedFileAttachments, _ := ah.msgToPost(channelID, senderID, msg, chat, fileIDs) post.Id = postInfo.MattermostID - // For now, don't display this message on update - // if skippedFileAttachments { - // _, appErr := ah.plugin.GetAPI().CreatePost(&model.Post{ - // ChannelId: post.ChannelId, - // UserId: ah.plugin.GetBotUserID(), - // Message: "Attachments added to an existing post in Microsoft Teams aren't delivered to Mattermost.", - // // Anchor the post immediately after (never before) the post that was edited. - // CreateAt: post.CreateAt + 1, - // }) - // if appErr != nil { - // ah.plugin.GetAPI().LogWarn("Failed to notify channel of skipped attachment", "channel_id", post.ChannelId, "post_id", post.Id, "error", appErr) - // } - // } + if skippedFileAttachments > 0 { + ah.plugin.GetAPI().LogWarn("Skipped file attachments on post update", "channel_id", post.ChannelId, "post_id", post.Id, "skipped_file_attachments", skippedFileAttachments) + } ah.IgnorePluginHooksMap.Store(fmt.Sprintf("post_%s", post.Id), true) if _, appErr := ah.plugin.GetAPI().UpdatePost(post); appErr != nil { diff --git a/server/notifications.go b/server/notifications.go index 115b1465..ce780362 100644 --- a/server/notifications.go +++ b/server/notifications.go @@ -10,23 +10,14 @@ import ( ) func (ah *ActivityHandler) handleCreatedActivityNotification(msg *clientmodels.Message, chat *clientmodels.Chat) string { - botUserID := ah.plugin.GetBotUserID() - post, _, _ := ah.msgToPost("", botUserID, msg, chat, false, []string{}) - if chat == nil { // We're only going to support notifications from chats for now. return metrics.DiscardedReasonChannelNotificationsUnsupported } - notifiedUsers := []string{} + botUserID := ah.plugin.GetBotUserID() + chatLink := fmt.Sprintf("https://teams.microsoft.com/l/message/%s/%s?tenantId=%s&context={\"contextType\":\"chat\"}", chat.ID, msg.ID, ah.plugin.GetTenantID()) - attachmentCount := 0 - for _, attachment := range msg.Attachments { - if attachment.ContentType == "messageReference" || attachment.ContentType == "application/vnd.microsoft.card.codesnippet" { - continue - } - attachmentCount++ - } for _, member := range chat.Members { // Don't notify senders about their own posts. if member.UserID == msg.UserID { @@ -44,9 +35,16 @@ func (ah *ActivityHandler) handleCreatedActivityNotification(msg *clientmodels.M if !ah.plugin.getNotificationPreference(mattermostUserID) { continue } - notifiedUsers = append(notifiedUsers, mattermostUserID) - ah.plugin.metricsService.ObserveNotification(len(chat.Members) >= 3, attachmentCount > 0) + channel, err := ah.plugin.apiClient.Channel.GetDirect(mattermostUserID, ah.plugin.botUserID) + if err != nil { + ah.plugin.GetAPI().LogWarn("Failed to get bot DM channel with user", "user_id", mattermostUserID, "teams_user_id", member.UserID, "error", err) + continue + } + + post, skippedFileAttachments, _ := ah.msgToPost(channel.Id, botUserID, msg, chat, []string{}) + + ah.plugin.metricsService.ObserveNotification(len(chat.Members) >= 3, len(post.FileIds) > 0) ah.plugin.notifyChat( mattermostUserID, msg.UserDisplayName, @@ -54,12 +52,11 @@ func (ah *ActivityHandler) handleCreatedActivityNotification(msg *clientmodels.M len(chat.Members), chatLink, post.Message, - attachmentCount, + post.FileIds, + skippedFileAttachments, ) - } - if len(notifiedUsers) > 0 { - err := ah.plugin.GetStore().SetUsersLastChatReceivedAt(notifiedUsers, storemodels.MilliToMicroSeconds(post.CreateAt)) + err = ah.plugin.GetStore().SetUserLastChatReceivedAt(mattermostUserID, storemodels.MilliToMicroSeconds(post.CreateAt)) if err != nil { ah.plugin.GetAPI().LogWarn("Unable to set the last chat received at", "error", err) } diff --git a/server/notifications_test.go b/server/notifications_test.go index e98a1013..1b51ddbe 100644 --- a/server/notifications_test.go +++ b/server/notifications_test.go @@ -10,13 +10,14 @@ func TestFormatNotificationMessage(t *testing.T) { testCases := []struct { Description string - ActorDisplayName string - ChatTopic string - ChatSize int - ChatLink string - Message string - AttachmentCount int - ExpectedMessage string + ActorDisplayName string + ChatTopic string + ChatSize int + ChatLink string + Message string + AttachmentCount int + SkippedFileAttachments int + ExpectedMessage string }{ { Description: "empty message, no attachments", @@ -26,7 +27,6 @@ func TestFormatNotificationMessage(t *testing.T) { ChatSize: 2, ChatLink: "http://teams.microsoft.com/chat/1", Message: "", - AttachmentCount: 0, ExpectedMessage: ``, }, @@ -40,9 +40,7 @@ func TestFormatNotificationMessage(t *testing.T) { Message: "", AttachmentCount: 1, - ExpectedMessage: `**Sender** messaged you in an [MS Teams chat](http://teams.microsoft.com/chat/1): - -*This message was originally sent with one attachment.*`, + ExpectedMessage: `**Sender** messaged you in an [MS Teams chat](http://teams.microsoft.com/chat/1):`, }, { Description: "empty message, more than one attachment", @@ -54,25 +52,22 @@ func TestFormatNotificationMessage(t *testing.T) { Message: "", AttachmentCount: 2, - ExpectedMessage: `**Sender** messaged you in an [MS Teams chat](http://teams.microsoft.com/chat/1): - -*This message was originally sent with 2 attachments.*`, + ExpectedMessage: `**Sender** messaged you in an [MS Teams chat](http://teams.microsoft.com/chat/1):`, }, { - Description: "chat message, no attachments, no topic", + Description: "chat message", ActorDisplayName: "Sender", ChatTopic: "", ChatSize: 2, ChatLink: "http://teams.microsoft.com/chat/1", Message: "Hello!", - AttachmentCount: 0, ExpectedMessage: `**Sender** messaged you in an [MS Teams chat](http://teams.microsoft.com/chat/1): > Hello!`, }, { - Description: "chat message, one attachment, no topic", + Description: "chat message with attachments", ActorDisplayName: "Sender", ChatTopic: "", @@ -82,83 +77,50 @@ func TestFormatNotificationMessage(t *testing.T) { AttachmentCount: 1, ExpectedMessage: `**Sender** messaged you in an [MS Teams chat](http://teams.microsoft.com/chat/1): -> Hello! - -*This message was originally sent with one attachment.*`, +> Hello!`, }, { - Description: "chat message, more than one attachment, no topic", + Description: "chat message with topic", ActorDisplayName: "Sender", ChatTopic: "", ChatSize: 2, ChatLink: "http://teams.microsoft.com/chat/1", Message: "Hello!", - AttachmentCount: 2, + AttachmentCount: 1, ExpectedMessage: `**Sender** messaged you in an [MS Teams chat](http://teams.microsoft.com/chat/1): -> Hello! - -*This message was originally sent with 2 attachments.*`, - }, - { - Description: "chat message, no attachments, has topic", - - ActorDisplayName: "Sender", - ChatTopic: "Topic", - ChatSize: 2, - ChatLink: "http://teams.microsoft.com/chat/1", - Message: "Hello!", - AttachmentCount: 0, - - ExpectedMessage: `**Sender** messaged you in an [MS Teams chat: Topic](http://teams.microsoft.com/chat/1): > Hello!`, }, { - Description: "chat message, one attachment, has topic", - - ActorDisplayName: "Sender", - ChatTopic: "Topic", - ChatSize: 2, - ChatLink: "http://teams.microsoft.com/chat/1", - Message: "Hello!", - AttachmentCount: 1, - - ExpectedMessage: `**Sender** messaged you in an [MS Teams chat: Topic](http://teams.microsoft.com/chat/1): -> Hello! - -*This message was originally sent with one attachment.*`, - }, - { - Description: "chat message, more than one attachment, has topic", + Description: "chat message with skipped attachments", - ActorDisplayName: "Sender", - ChatTopic: "Topic", - ChatSize: 2, - ChatLink: "http://teams.microsoft.com/chat/1", - Message: "Hello!", - AttachmentCount: 2, + ActorDisplayName: "Sender", + ChatTopic: "", + ChatSize: 2, + ChatLink: "http://teams.microsoft.com/chat/1", + Message: "Hello!", + SkippedFileAttachments: 1, - ExpectedMessage: `**Sender** messaged you in an [MS Teams chat: Topic](http://teams.microsoft.com/chat/1): + ExpectedMessage: `**Sender** messaged you in an [MS Teams chat](http://teams.microsoft.com/chat/1): > Hello! -*This message was originally sent with 2 attachments.*`, +*Some file attachments from this message could not be delivered.*`, }, { - Description: "group chat message, no attachments, no topic", + Description: "group chat message", ActorDisplayName: "Sender", ChatTopic: "", ChatSize: 3, ChatLink: "http://teams.microsoft.com/chat/1", Message: "Hello!", - AttachmentCount: 0, ExpectedMessage: `**Sender** messaged you and 1 other user in an [MS Teams group chat](http://teams.microsoft.com/chat/1): > Hello!`, }, { - Description: "group chat message, one attachment, no topic", + Description: "group chat message with attachments", ActorDisplayName: "Sender", ChatTopic: "", @@ -168,153 +130,58 @@ func TestFormatNotificationMessage(t *testing.T) { AttachmentCount: 1, ExpectedMessage: `**Sender** messaged you and 1 other user in an [MS Teams group chat](http://teams.microsoft.com/chat/1): -> Hello! - -*This message was originally sent with one attachment.*`, - }, - { - Description: "group chat message, more than one attachment, no topic", - - ActorDisplayName: "Sender", - ChatTopic: "", - ChatSize: 3, - ChatLink: "http://teams.microsoft.com/chat/1", - Message: "Hello!", - AttachmentCount: 2, - - ExpectedMessage: `**Sender** messaged you and 1 other user in an [MS Teams group chat](http://teams.microsoft.com/chat/1): -> Hello! - -*This message was originally sent with 2 attachments.*`, - }, - { - Description: "group chat message, no attachments, has topic", - - ActorDisplayName: "Sender", - ChatTopic: "Topic", - ChatSize: 3, - ChatLink: "http://teams.microsoft.com/chat/1", - Message: "Hello!", - AttachmentCount: 0, - - ExpectedMessage: `**Sender** messaged you and 1 other user in an [MS Teams group chat: Topic](http://teams.microsoft.com/chat/1): > Hello!`, }, { - Description: "group chat message, one attachment, has topic", + Description: "group chat message with topic", ActorDisplayName: "Sender", ChatTopic: "Topic", ChatSize: 3, ChatLink: "http://teams.microsoft.com/chat/1", Message: "Hello!", - AttachmentCount: 1, ExpectedMessage: `**Sender** messaged you and 1 other user in an [MS Teams group chat: Topic](http://teams.microsoft.com/chat/1): -> Hello! - -*This message was originally sent with one attachment.*`, +> Hello!`, }, { - Description: "group chat message, more than one attachment, has topic", + Description: "group chat message with skipped attachments", - ActorDisplayName: "Sender", - ChatTopic: "Topic", - ChatSize: 3, - ChatLink: "http://teams.microsoft.com/chat/1", - Message: "Hello!", - AttachmentCount: 2, + ActorDisplayName: "Sender", + ChatTopic: "Topic", + ChatSize: 3, + ChatLink: "http://teams.microsoft.com/chat/1", + Message: "Hello!", + SkippedFileAttachments: 1, ExpectedMessage: `**Sender** messaged you and 1 other user in an [MS Teams group chat: Topic](http://teams.microsoft.com/chat/1): > Hello! -*This message was originally sent with 2 attachments.*`, +*Some file attachments from this message could not be delivered.*`, }, { - Description: "group chat message with 5 users, no attachments, no topic", + Description: "group chat message with 5 users", ActorDisplayName: "Sender", ChatTopic: "", ChatSize: 5, ChatLink: "http://teams.microsoft.com/chat/1", Message: "Hello!", - AttachmentCount: 0, ExpectedMessage: `**Sender** messaged you and 3 other users in an [MS Teams group chat](http://teams.microsoft.com/chat/1): > Hello!`, }, { - Description: "group chat message with 5 users, one attachment, no topic", - - ActorDisplayName: "Sender", - ChatTopic: "", - ChatSize: 5, - ChatLink: "http://teams.microsoft.com/chat/1", - Message: "Hello!", - AttachmentCount: 1, - - ExpectedMessage: `**Sender** messaged you and 3 other users in an [MS Teams group chat](http://teams.microsoft.com/chat/1): -> Hello! - -*This message was originally sent with one attachment.*`, - }, - { - Description: "group chat message with 5 users, more than one attachment, no topic", - - ActorDisplayName: "Sender", - ChatTopic: "", - ChatSize: 5, - ChatLink: "http://teams.microsoft.com/chat/1", - Message: "Hello!", - AttachmentCount: 2, - - ExpectedMessage: `**Sender** messaged you and 3 other users in an [MS Teams group chat](http://teams.microsoft.com/chat/1): -> Hello! - -*This message was originally sent with 2 attachments.*`, - }, - { - Description: "group chat message with 5 users, no attachments, has topic", + Description: "group chat message with 5 users and topic", ActorDisplayName: "Sender", ChatTopic: "Topic", ChatSize: 5, ChatLink: "http://teams.microsoft.com/chat/1", Message: "Hello!", - AttachmentCount: 0, ExpectedMessage: `**Sender** messaged you and 3 other users in an [MS Teams group chat: Topic](http://teams.microsoft.com/chat/1): > Hello!`, - }, - { - Description: "group chat message with 5 users, one attachment, has topic", - - ActorDisplayName: "Sender", - ChatTopic: "Topic", - ChatSize: 5, - ChatLink: "http://teams.microsoft.com/chat/1", - Message: "Hello!", - AttachmentCount: 1, - - ExpectedMessage: `**Sender** messaged you and 3 other users in an [MS Teams group chat: Topic](http://teams.microsoft.com/chat/1): -> Hello! - -*This message was originally sent with one attachment.*`, - }, - { - Description: "group chat message with 5 users, more than one attachment, has topic", - - ActorDisplayName: "Sender", - ChatTopic: "Topic", - ChatSize: 5, - ChatLink: "http://teams.microsoft.com/chat/1", - Message: "Hello!", - AttachmentCount: 2, - - ExpectedMessage: `**Sender** messaged you and 3 other users in an [MS Teams group chat: Topic](http://teams.microsoft.com/chat/1): -> Hello! - -*This message was originally sent with 2 attachments.*`, }, { Description: "multiline, complex chat message", @@ -348,9 +215,7 @@ SELECT * FROM Users >` + " " + ` > ` + "```" + `sql > SELECT * FROM Users -> ` + "```" + ` - -*This message was originally sent with 2 attachments.*`, +> ` + "```", }, } @@ -363,6 +228,7 @@ SELECT * FROM Users tc.ChatLink, tc.Message, tc.AttachmentCount, + tc.SkippedFileAttachments, ) assert.Equal(t, tc.ExpectedMessage, actualMessage) })