parent
4cb56a1326
commit
9edc65867c
@ -0,0 +1,146 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/openimsdk/protocol/conversation"
|
||||||
|
"github.com/openimsdk/protocol/msg"
|
||||||
|
"github.com/openimsdk/protocol/sdkws"
|
||||||
|
"github.com/openimsdk/tools/mcontext"
|
||||||
|
"github.com/openimsdk/tools/utils/datautil"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
const limitGetActiveConversation = 100
|
||||||
|
|
||||||
|
type JSSdk struct {
|
||||||
|
msg msg.MsgClient
|
||||||
|
conv conversation.ConversationClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func field[A, B, C any](ctx context.Context, fn func(ctx context.Context, req *A, opts ...grpc.CallOption) (*B, error), req *A, get func(*B) C) (C, error) {
|
||||||
|
resp, err := fn(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
var c C
|
||||||
|
return c, err
|
||||||
|
}
|
||||||
|
return get(resp), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *JSSdk) GetActiveConversation(ctx *gin.Context) ([]ConversationMsg, error) {
|
||||||
|
opUserID := mcontext.GetOpUserID(ctx)
|
||||||
|
conversationIDs, err := field(ctx, x.conv.GetConversationIDs,
|
||||||
|
&conversation.GetConversationIDsReq{UserID: opUserID}, (*conversation.GetConversationIDsResp).GetConversationIDs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(conversationIDs) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
activeConversation, err := field(ctx, x.msg.GetActiveConversation,
|
||||||
|
&msg.GetActiveConversationReq{ConversationIDs: conversationIDs}, (*msg.GetActiveConversationResp).GetConversations)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(activeConversation) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
sortConversations := sortActiveConversations{
|
||||||
|
Conversation: activeConversation,
|
||||||
|
}
|
||||||
|
if len(activeConversation) > 1 {
|
||||||
|
// todo get pinned conversation ids
|
||||||
|
}
|
||||||
|
sort.Sort(&sortConversations)
|
||||||
|
sortList := sortConversations.Top(limitGetActiveConversation)
|
||||||
|
conversations, err := field(ctx, x.conv.GetConversations,
|
||||||
|
&conversation.GetConversationsReq{ConversationIDs: datautil.Slice(sortList, func(c *msg.ActiveConversation) string {
|
||||||
|
return c.ConversationID
|
||||||
|
})}, (*conversation.GetConversationsResp).GetConversations)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
readSeq, err := field(ctx, x.msg.GetHasReadSeqs,
|
||||||
|
&msg.GetHasReadSeqsReq{UserID: opUserID, ConversationIDs: conversationIDs}, (*msg.SeqsInfoResp).GetMaxSeqs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
msgs, err := field(ctx, x.msg.GetSeqMessage,
|
||||||
|
&msg.GetSeqMessageReq{
|
||||||
|
UserID: opUserID,
|
||||||
|
Conversations: datautil.Slice(sortList, func(c *msg.ActiveConversation) *msg.ConversationSeqs {
|
||||||
|
return &msg.ConversationSeqs{
|
||||||
|
ConversationID: c.ConversationID,
|
||||||
|
Seqs: []int64{c.MaxSeq},
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}, (*msg.GetSeqMessageResp).GetMsgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conversationMap := datautil.SliceToMap(conversations, func(c *conversation.Conversation) string {
|
||||||
|
return c.ConversationID
|
||||||
|
})
|
||||||
|
resp := make([]ConversationMsg, 0, len(sortList))
|
||||||
|
for _, c := range sortList {
|
||||||
|
conv, ok := conversationMap[c.ConversationID]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
msgList, ok := msgs[c.ConversationID]
|
||||||
|
if ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var lastMsg *sdkws.MsgData
|
||||||
|
if len(msgList.Msgs) > 0 {
|
||||||
|
lastMsg = msgList.Msgs[0]
|
||||||
|
}
|
||||||
|
resp = append(resp, ConversationMsg{
|
||||||
|
Conversation: conv,
|
||||||
|
LastMsg: lastMsg,
|
||||||
|
MaxSeq: c.MaxSeq,
|
||||||
|
MaxSeqTime: c.LastTime,
|
||||||
|
ReadSeq: readSeq[c.ConversationID],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConversationMsg struct {
|
||||||
|
Conversation *conversation.Conversation `json:"conversation"`
|
||||||
|
LastMsg *sdkws.MsgData `json:"lastMsg"`
|
||||||
|
ReadSeq int64 `json:"readSeq"`
|
||||||
|
MaxSeq int64 `json:"maxSeq"`
|
||||||
|
MaxSeqTime int64 `json:"maxSeqTime"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type sortActiveConversations struct {
|
||||||
|
Conversation []*msg.ActiveConversation
|
||||||
|
PinnedConversationIDs map[string]struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s sortActiveConversations) Top(limit int) []*msg.ActiveConversation {
|
||||||
|
if limit > 0 && len(s.Conversation) > limit {
|
||||||
|
return s.Conversation[:limit]
|
||||||
|
}
|
||||||
|
return s.Conversation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s sortActiveConversations) Len() int {
|
||||||
|
return len(s.Conversation)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s sortActiveConversations) Less(i, j int) bool {
|
||||||
|
iv, jv := s.Conversation[i], s.Conversation[j]
|
||||||
|
_, ip := s.PinnedConversationIDs[iv.ConversationID]
|
||||||
|
_, jp := s.PinnedConversationIDs[jv.ConversationID]
|
||||||
|
if ip != jp {
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
return iv.LastTime > jv.LastTime
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s sortActiveConversations) Swap(i, j int) {
|
||||||
|
s.Conversation[i], s.Conversation[j] = s.Conversation[j], s.Conversation[i]
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/openimsdk/protocol/msg"
|
||||||
|
"sort"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestName(t *testing.T) {
|
||||||
|
val := sortActiveConversations{
|
||||||
|
Conversation: []*msg.ActiveConversation{
|
||||||
|
{
|
||||||
|
ConversationID: "100",
|
||||||
|
LastTime: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ConversationID: "200",
|
||||||
|
LastTime: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ConversationID: "300",
|
||||||
|
LastTime: 300,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ConversationID: "400",
|
||||||
|
LastTime: 400,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
//PinnedConversationIDs: map[string]struct{}{
|
||||||
|
// "100": {},
|
||||||
|
// "300": {},
|
||||||
|
//},
|
||||||
|
}
|
||||||
|
sort.Sort(&val)
|
||||||
|
t.Log(val)
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package msg
|
||||||
|
|
||||||
|
//func TestName(t *testing.T) {
|
||||||
|
// arr := seqTimes{
|
||||||
|
// {
|
||||||
|
// Time: 100,
|
||||||
|
// Pinned: true,
|
||||||
|
// Unread: 1,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// Time: 200,
|
||||||
|
// Pinned: true,
|
||||||
|
// Unread: 10,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// Time: 300,
|
||||||
|
// Pinned: false,
|
||||||
|
// Unread: 10,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// Time: 100,
|
||||||
|
// Pinned: false,
|
||||||
|
// Unread: 0,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// Time: 400,
|
||||||
|
// Pinned: true,
|
||||||
|
// Unread: 0,
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
// rand.Shuffle(len(arr), func(i, j int) {
|
||||||
|
// arr[i], arr[j] = arr[j], arr[i]
|
||||||
|
// })
|
||||||
|
// sort.Sort(arr)
|
||||||
|
// fmt.Println(arr)
|
||||||
|
//}
|
Loading…
Reference in new issue