diff --git a/store/sqlstore/post_store.go b/store/sqlstore/post_store.go index 16e5394147..ab96f31fd1 100644 --- a/store/sqlstore/post_store.go +++ b/store/sqlstore/post_store.go @@ -2981,8 +2981,13 @@ func (s *SqlPostStore) GetTopDMsForUserSince(userID string, since int64, offset topDMsBuilder := s.getQueryBuilder().Select("count(p.id) as MessageCount", aggregator).FromSelect(channelSelector, "vch"). Join("ChannelMembers as cm on cm.ChannelId = vch.Id"). Join("Posts as p on p.ChannelId = vch.Id"). - Where(sq.Gt{ - "p.UpdateAt": since, + Where(sq.And{ + sq.Gt{ + "p.UpdateAt": since, + }, + sq.Eq{ + "p.DeleteAt": 0, + }, }).GroupBy("vch.id") topDMsBuilder = topDMsBuilder.OrderBy("MessageCount DESC").Limit(uint64(limit)).Offset(uint64(offset)) @@ -3004,13 +3009,14 @@ func (s *SqlPostStore) GetTopDMsForUserSince(userID string, since int64, offset func postProcessTopDMs(userID string, topDMs []*model.TopDM) []*model.TopDM { for _, topDM := range topDMs { - // divide message count by 2, because it's counted twice due to channel memberships being 2 for dms. - topDM.MessageCount = topDM.MessageCount / 2 participants := strings.Split(topDM.Participants, ",") if len(participants) == 1 { // chatting to self topDM.SecondParticipant = userID continue + } else { + // divide message count by 2, because it's counted twice due to channel memberships being 2 for dms. + topDM.MessageCount = topDM.MessageCount / 2 } if participants[0] == userID { topDM.SecondParticipant = participants[1] diff --git a/store/storetest/post_store.go b/store/storetest/post_store.go index 15147cbfb6..33984b58a4 100644 --- a/store/storetest/post_store.go +++ b/store/storetest/post_store.go @@ -58,6 +58,7 @@ func TestPostStore(t *testing.T, ss store.Store, s SqlStore) { t.Run("HasAutoResponsePostByUserSince", func(t *testing.T) { testHasAutoResponsePostByUserSince(t, ss) }) t.Run("GetPostsSinceForSync", func(t *testing.T) { testGetPostsSinceForSync(t, ss, s) }) t.Run("GetNthRecentPostTime", func(t *testing.T) { testGetNthRecentPostTime(t, ss) }) + t.Run("GetTopDMsForUserSince", func(t *testing.T) { testGetTopDMsForUserSince(t, ss, s) }) } func testPostStoreSave(t *testing.T, ss store.Store) { @@ -3861,3 +3862,115 @@ func testGetNthRecentPostTime(t *testing.T, ss store.Store) { assert.Error(t, err) assert.IsType(t, &store.ErrNotFound{}, err) } + +func testGetTopDMsForUserSince(t *testing.T, ss store.Store, s SqlStore) { + // users + user := model.User{Id: model.NewId()} + u1 := model.User{Id: model.NewId()} + u2 := model.User{Id: model.NewId()} + u3 := model.User{Id: model.NewId()} + u4 := model.User{Id: model.NewId()} + // user direct messages + chUser1, nErr := ss.Channel().CreateDirectChannel(&u1, &user) + require.NoError(t, nErr) + chUser2, nErr := ss.Channel().CreateDirectChannel(&u2, &user) + require.NoError(t, nErr) + chUser3, nErr := ss.Channel().CreateDirectChannel(&u3, &user) + require.NoError(t, nErr) + // other user direct message + chUser3User4, nErr := ss.Channel().CreateDirectChannel(&u3, &u4) + require.NoError(t, nErr) + + // sample post data + // for u1 + _, err := ss.Post().Save(&model.Post{ + ChannelId: chUser1.Id, + UserId: u1.Id, + }) + require.NoError(t, err) + _, err = ss.Post().Save(&model.Post{ + ChannelId: chUser1.Id, + UserId: user.Id, + }) + require.NoError(t, err) + // for u2: 1 post + postToDelete, err := ss.Post().Save(&model.Post{ + ChannelId: chUser2.Id, + UserId: u2.Id, + }) + require.NoError(t, err) + // for user-u3: 3 posts + for i := 0; i < 3; i++ { + _, err = ss.Post().Save(&model.Post{ + ChannelId: chUser3.Id, + UserId: user.Id, + }) + require.NoError(t, err) + } + // for u4-u3: 4 posts + _, err = ss.Post().Save(&model.Post{ + ChannelId: chUser3User4.Id, + UserId: u3.Id, + }) + require.NoError(t, err) + _, err = ss.Post().Save(&model.Post{ + ChannelId: chUser3User4.Id, + UserId: u4.Id, + }) + require.NoError(t, err) + _, err = ss.Post().Save(&model.Post{ + ChannelId: chUser3User4.Id, + UserId: u3.Id, + }) + require.NoError(t, err) + + _, err = ss.Post().Save(&model.Post{ + ChannelId: chUser3User4.Id, + UserId: u4.Id, + }) + require.NoError(t, err) + t.Run("should return topDMs when userid is specified ", func(t *testing.T) { + topDMs, err := ss.Post().GetTopDMsForUserSince(user.Id, 100, 0, 100) + require.NoError(t, err) + // len of topDMs.Items should be 3 + require.Len(t, topDMs.Items, 3) + // check order, magnitude of items + // fmt.Println(topDMs.Items[0].MessageCount, topDMs.Items[1].MessageCount, topDMs.Items[2].MessageCount) + require.Equal(t, topDMs.Items[0].SecondParticipant, u3.Id) + require.Equal(t, topDMs.Items[0].MessageCount, int64(3)) + require.Equal(t, topDMs.Items[1].SecondParticipant, u1.Id) + require.Equal(t, topDMs.Items[1].MessageCount, int64(2)) + require.Equal(t, topDMs.Items[2].SecondParticipant, u2.Id) + require.Equal(t, topDMs.Items[2].MessageCount, int64(1)) + // this also ensures that u3-u4 conversation doesn't show up in others' top DMs. + }) + t.Run("topDMs should only consider user's DM channels ", func(t *testing.T) { + // u4 only takes part in one conversation + topDMs, err := ss.Post().GetTopDMsForUserSince(u4.Id, 100, 0, 100) + require.NoError(t, err) + // len of topDMs.Items should be 3 + require.Len(t, topDMs.Items, 1) + // check order, magnitude of items + require.Equal(t, topDMs.Items[0].SecondParticipant, u3.Id) + require.Equal(t, topDMs.Items[0].MessageCount, int64(4)) + }) + t.Run("topDMs will consider self dms", func(t *testing.T) { + chUser, nErr := ss.Channel().CreateDirectChannel(&user, &user) + require.NoError(t, nErr) + _, err = ss.Post().Save(&model.Post{ + ChannelId: chUser.Id, + UserId: user.Id, + }) + // delete u2 post + err := ss.Post().Delete(postToDelete.Id, 200, user.Id) + require.NoError(t, err) + // u4 only takes part in one conversation + topDMs, err := ss.Post().GetTopDMsForUserSince(user.Id, 100, 0, 100) + require.NoError(t, err) + // len of topDMs.Items should be 3 + require.Len(t, topDMs.Items, 3) + // check order, magnitude of items + require.Equal(t, topDMs.Items[2].SecondParticipant, user.Id) + require.Equal(t, topDMs.Items[2].MessageCount, int64(1)) + }) +}