diff --git a/go.mod b/go.mod index 99374edb5..a7890a5c2 100644 --- a/go.mod +++ b/go.mod @@ -155,5 +155,4 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect ) -replace github.com/OpenIMSDK/protocol => github.com/luhaoling/protocol v0.0.0-20231214085358-66b74ceb5e6d - +replace github.com/OpenIMSDK/protocol => github.com/luhaoling/protocol v0.0.0-20231216092325-dc37832fcfe2 diff --git a/go.sum b/go.sum index 1546949f1..5668ddecc 100644 --- a/go.sum +++ b/go.sum @@ -225,8 +225,8 @@ github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205Ah github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= github.com/lithammer/shortuuid v3.0.0+incompatible h1:NcD0xWW/MZYXEHa6ITy6kaXN5nwm/V115vj2YXfhS0w= github.com/lithammer/shortuuid v3.0.0+incompatible/go.mod h1:FR74pbAuElzOUuenUHTK2Tciko1/vKuIKS9dSkDrA4w= -github.com/luhaoling/protocol v0.0.0-20231214085358-66b74ceb5e6d h1:nm04eTkcQ4LMfliuXqRnd+pwpJLTkQM7N3e8Q+gKNmk= -github.com/luhaoling/protocol v0.0.0-20231214085358-66b74ceb5e6d/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= +github.com/luhaoling/protocol v0.0.0-20231216092325-dc37832fcfe2 h1:GgOMW6SJ3gkWWJ+liO4pQac2AO4e7TsMww1j9+Z337c= +github.com/luhaoling/protocol v0.0.0-20231216092325-dc37832fcfe2/go.mod h1:F25dFrwrIx3lkNoiuf6FkCfxuwf8L4Z8UIsdTHP/r0Y= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= diff --git a/internal/api/conversation.go b/internal/api/conversation.go index e422de677..6463cbde6 100644 --- a/internal/api/conversation.go +++ b/internal/api/conversation.go @@ -33,6 +33,10 @@ func (o *ConversationApi) GetAllConversations(c *gin.Context) { a2r.Call(conversation.ConversationClient.GetAllConversations, o.Client, c) } +func (o *ConversationApi) GetConversationsList(c *gin.Context) { + a2r.Call(conversation.ConversationClient.GetConversationList, o.Client, c) +} + func (o *ConversationApi) GetConversation(c *gin.Context) { a2r.Call(conversation.ConversationClient.GetConversation, o.Client, c) } diff --git a/internal/api/msg.go b/internal/api/msg.go index 24bbfc87d..6aed2f6f5 100644 --- a/internal/api/msg.go +++ b/internal/api/msg.go @@ -125,10 +125,6 @@ func (m *MessageApi) GetConversationsHasReadAndMaxSeq(c *gin.Context) { a2r.Call(msg.MsgClient.GetConversationsHasReadAndMaxSeq, m.Client, c) } -func (m *MessageApi) GetConversationsList(c *gin.Context) { - a2r.Call(msg.MsgClient.GetConversationList, m.Client, c) -} - func (m *MessageApi) SetConversationHasReadSeq(c *gin.Context) { a2r.Call(msg.MsgClient.SetConversationHasReadSeq, m.Client, c) } diff --git a/internal/api/route.go b/internal/api/route.go index 44fe344a9..80e42008d 100644 --- a/internal/api/route.go +++ b/internal/api/route.go @@ -175,7 +175,6 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive msgGroup.POST("/mark_msgs_as_read", m.MarkMsgsAsRead) msgGroup.POST("/mark_conversation_as_read", m.MarkConversationAsRead) msgGroup.POST("/get_conversations_has_read_and_max_seq", m.GetConversationsHasReadAndMaxSeq) - msgGroup.POST("/get_conversations_list", m.GetConversationsList) msgGroup.POST("/set_conversation_has_read_seq", m.SetConversationHasReadSeq) msgGroup.POST("/clear_conversation_msg", m.ClearConversationsMsg) @@ -192,6 +191,7 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive conversationGroup := r.Group("/conversation", ParseToken) { c := NewConversationApi(*conversationRpc) + conversationGroup.POST("/get_conversations_list", c.GetConversationsList) conversationGroup.POST("/get_all_conversations", c.GetAllConversations) conversationGroup.POST("/get_conversation", c.GetConversation) conversationGroup.POST("/get_conversations", c.GetConversations) diff --git a/internal/rpc/conversation/conversaion.go b/internal/rpc/conversation/conversaion.go index 88c9ff7ff..3c90d720b 100644 --- a/internal/rpc/conversation/conversaion.go +++ b/internal/rpc/conversation/conversaion.go @@ -17,6 +17,9 @@ package conversation import ( "context" "errors" + "github.com/OpenIMSDK/protocol/sdkws" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/localcache" + "sort" "github.com/OpenIMSDK/tools/tx" @@ -41,6 +44,10 @@ import ( ) type conversationServer struct { + Conversation *rpcclient.ConversationRpcClient + MsgDatabase controller.CommonMsgDatabase + User *rpcclient.UserRpcClient + ConversationLocalCache *localcache.ConversationLocalCache groupRpcClient *rpcclient.GroupRpcClient conversationDatabase controller.ConversationDatabase conversationNotificationSender *notification.ConversationNotificationSender @@ -82,6 +89,69 @@ func (c *conversationServer) GetConversation(ctx context.Context, req *pbconvers return resp, nil } +func (m *conversationServer) GetConversationList(ctx context.Context, req *pbconversation.GetConversationListReq) (resp *pbconversation.GetConversationListResp, err error) { + var conversationIDs []string + if len(req.ConversationIDs) == 0 { + conversationIDs, err = m.conversationDatabase.GetConversationIDs(ctx, req.UserID) + if err != nil { + return nil, err + } + } else { + conversationIDs = req.ConversationIDs + } + + conversations, err := m.Conversation.GetConversations(ctx, req.UserID, conversationIDs) + if err != nil { + return nil, err + } + + maxSeqs, err := m.MsgDatabase.GetMaxSeqs(ctx, conversationIDs) + if err != nil { + return nil, err + } + + chatLogs, err := m.MsgDatabase.FindOneByDocIDs(ctx, conversationIDs, maxSeqs) + if err != nil { + return nil, err + } + + conversationMsg, err := m.getConversationInfo(ctx, chatLogs, req.UserID) + if err != nil { + return nil, err + } + + hasReadSeqs, err := m.MsgDatabase.GetHasReadSeqs(ctx, req.UserID, conversationIDs) + if err != nil { + return nil, err + } + + conversation_unreadCount := make(map[string]int64) + for conversationID, maxSeq := range maxSeqs { + conversation_unreadCount[conversationID] = maxSeq - hasReadSeqs[conversationID] + } + + conversation_isPinkTime := make(map[int64]string) + conversation_notPinkTime := make(map[int64]string) + for _, v := range conversations { + conversationID := v.ConversationID + time := conversationMsg[conversationID].MsgInfo.LatestMsgRecvTime + conversationMsg[conversationID].RecvMsgOpt = v.RecvMsgOpt + if v.IsPinned { + conversationMsg[conversationID].IsPinned = v.IsPinned + conversation_isPinkTime[time] = conversationID + continue + } + conversation_notPinkTime[time] = conversationID + } + resp = &pbconversation.GetConversationListResp{ + ConversationElems: []*pbconversation.ConversationElem{}, + } + + m.conversationSort(conversation_isPinkTime, resp, conversation_unreadCount, conversationMsg) + m.conversationSort(conversation_notPinkTime, resp, conversation_unreadCount, conversationMsg) + return resp, nil +} + func (c *conversationServer) GetAllConversations(ctx context.Context, req *pbconversation.GetAllConversationsReq) (*pbconversation.GetAllConversationsResp, error) { conversations, err := c.conversationDatabase.GetUserAllConversation(ctx, req.OwnerUserID) if err != nil { @@ -348,3 +418,102 @@ func (c *conversationServer) GetConversationOfflinePushUserIDs( } return &pbconversation.GetConversationOfflinePushUserIDsResp{UserIDs: utils.Keys(userIDSet)}, nil } + +func (c *conversationServer) conversationSort( + conversations map[int64]string, + resp *pbconversation.GetConversationListResp, + conversation_unreadCount map[string]int64, + conversationMsg map[string]*pbconversation.ConversationElem, +) { + keys := []int64{} + for key := range conversations { + keys = append(keys, key) + } + + sort.Slice(keys[:], func(i, j int) bool { + return keys[i] > keys[j] + }) + index := 0 + + cons := make([]*pbconversation.ConversationElem, len(conversations)) + for _, v := range keys { + conversationID := conversations[v] + conversationElem := conversationMsg[conversationID] + conversationElem.UnreadCount = conversation_unreadCount[conversationID] + cons[index] = conversationElem + index++ + } + resp.ConversationElems = append(resp.ConversationElems, cons...) +} + +func (c *conversationServer) getConversationInfo( + ctx context.Context, + chatLogs map[string]*sdkws.MsgData, + userID string) (map[string]*pbconversation.ConversationElem, error) { + var ( + sendIDs []string + groupIDs []string + sendMap = make(map[string]*sdkws.UserInfo) + groupMap = make(map[string]*sdkws.GroupInfo) + conversationMsg = make(map[string]*pbconversation.ConversationElem) + ) + for _, chatLog := range chatLogs { + switch chatLog.SessionType { + case constant.SingleChatType: + if chatLog.SendID == userID { + sendIDs = append(sendIDs, chatLog.RecvID) + } + sendIDs = append(sendIDs, chatLog.SendID) + case constant.GroupChatType, constant.SuperGroupChatType: + groupIDs = append(groupIDs, chatLog.GroupID) + sendIDs = append(sendIDs, chatLog.SendID) + } + } + if len(sendIDs) != 0 { + sendInfos, err := c.User.GetUsersInfo(ctx, sendIDs) + if err != nil { + return nil, err + } + for _, sendInfo := range sendInfos { + sendMap[sendInfo.UserID] = sendInfo + } + } + if len(groupIDs) != 0 { + groupInfos, err := c.groupRpcClient.GetGroupInfos(ctx, groupIDs, false) + if err != nil { + return nil, err + } + for _, groupInfo := range groupInfos { + groupMap[groupInfo.GroupID] = groupInfo + } + } + for conversationID, chatLog := range chatLogs { + pbchatLog := &pbconversation.ConversationElem{} + msgInfo := &pbconversation.MsgInfo{} + if err := utils.CopyStructFields(msgInfo, chatLog); err != nil { + return nil, err + } + switch chatLog.SessionType { + case constant.SingleChatType: + if chatLog.SendID == userID { + msgInfo.FaceURL = sendMap[chatLog.RecvID].FaceURL + msgInfo.SenderName = sendMap[chatLog.RecvID].Nickname + break + } + msgInfo.FaceURL = sendMap[chatLog.SendID].FaceURL + msgInfo.SenderName = sendMap[chatLog.SendID].Nickname + case constant.GroupChatType, constant.SuperGroupChatType: + msgInfo.GroupName = groupMap[chatLog.GroupID].GroupName + msgInfo.GroupFaceURL = groupMap[chatLog.GroupID].FaceURL + msgInfo.GroupMemberCount = groupMap[chatLog.GroupID].MemberCount + msgInfo.GroupID = chatLog.GroupID + msgInfo.GroupType = groupMap[chatLog.GroupID].GroupType + msgInfo.SenderName = sendMap[chatLog.SendID].Nickname + } + pbchatLog.ConversationID = conversationID + msgInfo.LatestMsgRecvTime = chatLog.SendTime + pbchatLog.MsgInfo = msgInfo + conversationMsg[conversationID] = pbchatLog + } + return conversationMsg, nil +} diff --git a/internal/rpc/msg/as_read.go b/internal/rpc/msg/as_read.go index 1bdde5ce5..2ff7ff4d9 100644 --- a/internal/rpc/msg/as_read.go +++ b/internal/rpc/msg/as_read.go @@ -16,10 +16,8 @@ package msg import ( "context" - cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" - "sort" - utils2 "github.com/OpenIMSDK/tools/utils" + cbapi "github.com/openimsdk/open-im-server/v3/pkg/callbackstruct" "github.com/redis/go-redis/v9" @@ -71,69 +69,6 @@ func (m *msgServer) GetConversationsHasReadAndMaxSeq(ctx context.Context, req *m return resp, nil } -func (m *msgServer) GetConversationList(ctx context.Context, req *msg.GetConversationListReq) (resp *msg.GetConversationListResp, err error) { - var conversationIDs []string - if len(req.ConversationIDs) == 0 { - conversationIDs, err = m.ConversationLocalCache.GetConversationIDs(ctx, req.UserID) - if err != nil { - return nil, err - } - } else { - conversationIDs = req.ConversationIDs - } - - conversations, err := m.Conversation.GetConversations(ctx, req.UserID, conversationIDs) - if err != nil { - return nil, err - } - - maxSeqs, err := m.MsgDatabase.GetMaxSeqs(ctx, conversationIDs) - if err != nil { - return nil, err - } - - chatLogs, err := m.MsgDatabase.FindOneByDocIDs(ctx, conversationIDs, maxSeqs) - if err != nil { - return nil, err - } - - conversationMsg, err := m.getConversationInfo(ctx, chatLogs, req.UserID) - if err != nil { - return nil, err - } - - hasReadSeqs, err := m.MsgDatabase.GetHasReadSeqs(ctx, req.UserID, conversationIDs) - if err != nil { - return nil, err - } - - conversation_unreadCount := make(map[string]int64) - for conversationID, maxSeq := range maxSeqs { - conversation_unreadCount[conversationID] = maxSeq - hasReadSeqs[conversationID] - } - - conversation_isPinkTime := make(map[int64]string) - conversation_notPinkTime := make(map[int64]string) - for _, v := range conversations { - conversationID := v.ConversationID - time := conversationMsg[conversationID].MsgInfo.LatestMsgRecvTime - conversationMsg[conversationID].RecvMsgOpt = v.RecvMsgOpt - if v.IsPinned { - conversationMsg[conversationID].IsPinned = v.IsPinned - conversation_isPinkTime[time] = conversationID - continue - } - conversation_notPinkTime[time] = conversationID - } - resp = &msg.GetConversationListResp{ - ConversationElems: []*msg.ConversationElem{}, - } - - m.conversationSort(conversation_isPinkTime, resp, conversation_unreadCount, conversationMsg) - m.conversationSort(conversation_notPinkTime, resp, conversation_unreadCount, conversationMsg) - return resp, nil -} - func (m *msgServer) SetConversationHasReadSeq( ctx context.Context, req *msg.SetConversationHasReadSeqReq, @@ -288,102 +223,3 @@ func (m *msgServer) sendMarkAsReadNotification( } return nil } - -func (m *msgServer) conversationSort( - conversations map[int64]string, - resp *msg.GetConversationListResp, - conversation_unreadCount map[string]int64, - conversationMsg map[string]*msg.ConversationElem, -) { - keys := []int64{} - for key := range conversations { - keys = append(keys, key) - } - - sort.Slice(keys[:], func(i, j int) bool { - return keys[i] > keys[j] - }) - index := 0 - - cons := make([]*msg.ConversationElem, len(conversations)) - for _, v := range keys { - conversationID := conversations[v] - conversationElem := conversationMsg[conversationID] - conversationElem.UnreadCount = conversation_unreadCount[conversationID] - cons[index] = conversationElem - index++ - } - resp.ConversationElems = append(resp.ConversationElems, cons...) -} - -func (m *msgServer) getConversationInfo( - ctx context.Context, - chatLogs map[string]*sdkws.MsgData, - userID string) (map[string]*msg.ConversationElem, error) { - var ( - sendIDs []string - groupIDs []string - sendMap = make(map[string]*sdkws.UserInfo) - groupMap = make(map[string]*sdkws.GroupInfo) - conversationMsg = make(map[string]*msg.ConversationElem) - ) - for _, chatLog := range chatLogs { - switch chatLog.SessionType { - case constant.SingleChatType: - if chatLog.SendID == userID { - sendIDs = append(sendIDs, chatLog.RecvID) - } - sendIDs = append(sendIDs, chatLog.SendID) - case constant.GroupChatType, constant.SuperGroupChatType: - groupIDs = append(groupIDs, chatLog.GroupID) - sendIDs = append(sendIDs, chatLog.SendID) - } - } - if len(sendIDs) != 0 { - sendInfos, err := m.User.GetUsersInfo(ctx, sendIDs) - if err != nil { - return nil, err - } - for _, sendInfo := range sendInfos { - sendMap[sendInfo.UserID] = sendInfo - } - } - if len(groupIDs) != 0 { - groupInfos, err := m.Group.GetGroupInfos(ctx, groupIDs, false) - if err != nil { - return nil, err - } - for _, groupInfo := range groupInfos { - groupMap[groupInfo.GroupID] = groupInfo - } - } - for conversationID, chatLog := range chatLogs { - pbchatLog := &msg.ConversationElem{} - msgInfo := &msg.MsgInfo{} - if err := utils2.CopyStructFields(msgInfo, chatLog); err != nil { - return nil, err - } - switch chatLog.SessionType { - case constant.SingleChatType: - if chatLog.SendID == userID { - msgInfo.FaceURL = sendMap[chatLog.RecvID].FaceURL - msgInfo.SenderName = sendMap[chatLog.RecvID].Nickname - break - } - msgInfo.FaceURL = sendMap[chatLog.SendID].FaceURL - msgInfo.SenderName = sendMap[chatLog.SendID].Nickname - case constant.GroupChatType, constant.SuperGroupChatType: - msgInfo.GroupName = groupMap[chatLog.GroupID].GroupName - msgInfo.GroupFaceURL = groupMap[chatLog.GroupID].FaceURL - msgInfo.GroupMemberCount = groupMap[chatLog.GroupID].MemberCount - msgInfo.GroupID = chatLog.GroupID - msgInfo.GroupType = groupMap[chatLog.GroupID].GroupType - msgInfo.SenderName = sendMap[chatLog.SendID].Nickname - } - pbchatLog.ConversationID = conversationID - msgInfo.LatestMsgRecvTime = chatLog.SendTime - pbchatLog.MsgInfo = msgInfo - conversationMsg[conversationID] = pbchatLog - } - return conversationMsg, nil -}