From 317ad2f906dfd97b9ad620e6481a72801dde713d Mon Sep 17 00:00:00 2001 From: Mikhail Rogachev Date: Wed, 29 Nov 2023 19:28:04 +0400 Subject: [PATCH] feat: Ignore AC notifications created before the request to join the community (#4385) * fix: Ignore AC notifications created before the request to join the community * review fixes --- protocol/communities/manager.go | 14 ++++++ protocol/messenger.go | 49 ++++++++++++-------- protocol/messenger_activity_center_test.go | 54 ++++++++++++++++++++++ 3 files changed, 99 insertions(+), 18 deletions(-) diff --git a/protocol/communities/manager.go b/protocol/communities/manager.go index 9725039f9..fb611a289 100644 --- a/protocol/communities/manager.go +++ b/protocol/communities/manager.go @@ -2975,6 +2975,20 @@ func (m *Manager) GetRequestToJoinIDByPkAndCommunityID(pk *ecdsa.PublicKey, comm return m.persistence.GetRequestToJoinIDByPkAndCommunityID(common.PubkeyToHex(pk), communityID) } +func (m *Manager) GetCommunityRequestToJoinClock(pk *ecdsa.PublicKey, communityID string) (uint64, error) { + request, err := m.persistence.GetRequestToJoinByPkAndCommunityID(common.PubkeyToHex(pk), []byte(communityID)) + if errors.Is(err, sql.ErrNoRows) { + return 0, nil + } else if err != nil { + return 0, err + } + + if request == nil || request.State != RequestToJoinStateAccepted { + return 0, nil + } + return request.Clock, nil +} + func (m *Manager) UpdateCommunityDescriptionMagnetlinkMessageClock(communityID types.HexBytes, clock uint64) error { community, err := m.GetByIDString(communityID.String()) if err != nil { diff --git a/protocol/messenger.go b/protocol/messenger.go index 18d698a35..69e287f39 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -3457,6 +3457,23 @@ func (r *ReceivedMessageState) addNewActivityCenterNotification(publicKey ecdsa. return fmt.Errorf("chat ID '%s' not present", message.LocalChatID) } + isNotification, notificationType := showMentionOrReplyActivityCenterNotification(publicKey, message, chat, responseTo) + if !isNotification { + return nil + } + + if chat.CommunityChat() { + joinedClock, err := m.communitiesManager.GetCommunityRequestToJoinClock(&publicKey, message.CommunityID) + if err != nil { + return err + } + + // Ignore mentions & replies in community before joining + if message.Clock < joinedClock { + return nil + } + } + // Use albumId as notificationId to prevent multiple notifications // for same message with multiple images var notificationID string @@ -3480,26 +3497,22 @@ func (r *ReceivedMessageState) addNewActivityCenterNotification(publicKey ecdsa. notificationID = message.ID } - isNotification, notificationType := showMentionOrReplyActivityCenterNotification(publicKey, message, chat, responseTo) - if isNotification { - notification := &ActivityCenterNotification{ - ID: types.FromHex(notificationID), - Name: chat.Name, - Message: message, - ReplyMessage: responseTo, - Type: notificationType, - Timestamp: message.WhisperTimestamp, - ChatID: chat.ID, - CommunityID: chat.CommunityID, - Author: message.From, - UpdatedAt: m.GetCurrentTimeInMillis(), - AlbumMessages: albumMessages, - Read: message.Seen, - } - return m.addActivityCenterNotification(r.Response, notification, nil) + notification := &ActivityCenterNotification{ + ID: types.FromHex(notificationID), + Name: chat.Name, + Message: message, + ReplyMessage: responseTo, + Type: notificationType, + Timestamp: message.WhisperTimestamp, + ChatID: chat.ID, + CommunityID: chat.CommunityID, + Author: message.From, + UpdatedAt: m.GetCurrentTimeInMillis(), + AlbumMessages: albumMessages, + Read: message.Seen, } - return nil + return m.addActivityCenterNotification(r.Response, notification, nil) } func (m *Messenger) buildMessageState() *ReceivedMessageState { diff --git a/protocol/messenger_activity_center_test.go b/protocol/messenger_activity_center_test.go index 51e6b2033..3a514b0a6 100644 --- a/protocol/messenger_activity_center_test.go +++ b/protocol/messenger_activity_center_test.go @@ -441,3 +441,57 @@ func (s *MessengerActivityCenterMessageSuite) TestMarkAllActivityCenterNotificat s.confirmMentionAndReplyNotificationsRead(alice, mentionMessage, replyMessage, true) } + +func (s *MessengerActivityCenterMessageSuite) TestAliceDoesNotReceiveCommunityNotificationsBeforeJoined() { + alice := s.m + bob := s.newMessenger() + _, err := bob.Start() + s.Require().NoError(err) + defer bob.Shutdown() // nolint: errcheck + + // Create a community + community, chat := s.createCommunity(bob) + s.Require().NotNil(community) + s.Require().NotNil(chat) + + // Bob sends a mention message + mentionMessage := common.NewMessage() + mentionMessage.ChatId = chat.ID + mentionMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN + mentionMessage.Text = "Good news, @" + common.EveryoneMentionTag + " !" + + response, err := bob.SendChatMessage(context.Background(), mentionMessage) + s.Require().NoError(err) + s.Require().Len(response.Messages(), 1) + s.Require().True(response.Messages()[0].Mentioned) + + // Alice joins the community + s.advertiseCommunityTo(community, bob, alice) + s.joinCommunity(community, bob, alice) + + // Bob sends an another mention message + mentionMessage = common.NewMessage() + mentionMessage.ChatId = chat.ID + mentionMessage.ContentType = protobuf.ChatMessage_TEXT_PLAIN + mentionMessage.Text = "Welcome new joiners, @" + common.EveryoneMentionTag + " !" + + response, err = bob.SendChatMessage(context.Background(), mentionMessage) + s.Require().NoError(err) + s.Require().Len(response.Messages(), 1) + s.Require().True(response.Messages()[0].Mentioned) + + // check alice got only second mention message + response, err = WaitOnMessengerResponse( + alice, + func(r *MessengerResponse) bool { + return len(r.Messages()) == 1 && len(r.ActivityCenterNotifications()) == 1 && + r.Messages()[0].ID == r.ActivityCenterNotifications()[0].Message.ID && + r.ActivityCenterNotifications()[0].Type == ActivityCenterNotificationTypeMention + }, + "no messages", + ) + s.Require().NoError(err) + + s.Require().False(response.ActivityCenterNotifications()[0].Read) + s.Require().Equal(response.ActivityCenterNotifications()[0].ID.String(), response.ActivityCenterNotifications()[0].Message.ID) +}