|
|
|
@ -6,6 +6,8 @@ import (
|
|
|
|
|
"github.com/openimsdk/protocol/conversation"
|
|
|
|
|
"github.com/openimsdk/protocol/msg"
|
|
|
|
|
"github.com/openimsdk/protocol/sdkws"
|
|
|
|
|
"github.com/openimsdk/tools/a2r"
|
|
|
|
|
"github.com/openimsdk/tools/apiresp"
|
|
|
|
|
"github.com/openimsdk/tools/mcontext"
|
|
|
|
|
"github.com/openimsdk/tools/utils/datautil"
|
|
|
|
|
"google.golang.org/grpc"
|
|
|
|
@ -14,21 +16,27 @@ import (
|
|
|
|
|
|
|
|
|
|
const limitGetActiveConversation = 100
|
|
|
|
|
|
|
|
|
|
func NewJSSdkApi(msg msg.MsgClient, conv conversation.ConversationClient) *JSSdk {
|
|
|
|
|
return &JSSdk{
|
|
|
|
|
msg: msg,
|
|
|
|
|
conv: conv,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
func (x *JSSdk) GetActiveConversation(c *gin.Context) {
|
|
|
|
|
call(c, x.getActiveConversation)
|
|
|
|
|
}
|
|
|
|
|
return get(resp), nil
|
|
|
|
|
|
|
|
|
|
func (x *JSSdk) GetConversations(c *gin.Context) {
|
|
|
|
|
call(c, x.getConversations)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (x *JSSdk) GetActiveConversation(ctx *gin.Context) ([]ConversationMsg, error) {
|
|
|
|
|
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)
|
|
|
|
@ -50,22 +58,29 @@ func (x *JSSdk) GetActiveConversation(ctx *gin.Context) ([]ConversationMsg, erro
|
|
|
|
|
Conversation: activeConversation,
|
|
|
|
|
}
|
|
|
|
|
if len(activeConversation) > 1 {
|
|
|
|
|
// todo get pinned conversation ids
|
|
|
|
|
pinnedConversationIDs, err := field(ctx, x.conv.GetPinnedConversationIDs,
|
|
|
|
|
&conversation.GetPinnedConversationIDsReq{UserID: opUserID}, (*conversation.GetPinnedConversationIDsResp).GetConversationIDs)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
sortConversations.PinnedConversationIDs = datautil.SliceSet(pinnedConversationIDs)
|
|
|
|
|
}
|
|
|
|
|
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 {
|
|
|
|
|
&conversation.GetConversationsReq{
|
|
|
|
|
OwnerUserID: opUserID,
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
//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,
|
|
|
|
@ -88,20 +103,67 @@ func (x *JSSdk) GetActiveConversation(ctx *gin.Context) ([]ConversationMsg, erro
|
|
|
|
|
if !ok {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
msgList, ok := msgs[c.ConversationID]
|
|
|
|
|
if ok {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
var lastMsg *sdkws.MsgData
|
|
|
|
|
if len(msgList.Msgs) > 0 {
|
|
|
|
|
if msgList, ok := msgs[c.ConversationID]; ok && 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],
|
|
|
|
|
//MaxSeq: c.MaxSeq,
|
|
|
|
|
//MaxSeqTime: c.LastTime,
|
|
|
|
|
//ReadSeq: readSeq[c.ConversationID],
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
return resp, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (x *JSSdk) getConversations(ctx *gin.Context) ([]ConversationMsg, error) {
|
|
|
|
|
req, err := a2r.ParseRequest[conversation.GetConversationsReq](ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
req.OwnerUserID = mcontext.GetOpUserID(ctx)
|
|
|
|
|
conversations, err := field(ctx, x.conv.GetConversations, req, (*conversation.GetConversationsResp).GetConversations)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
if len(conversations) == 0 {
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
maxSeqs, err := field(ctx, x.msg.GetMaxSeqs,
|
|
|
|
|
&msg.GetMaxSeqsReq{ConversationIDs: datautil.Slice(conversations, func(c *conversation.Conversation) string {
|
|
|
|
|
return c.ConversationID
|
|
|
|
|
})}, (*msg.SeqsInfoResp).GetMaxSeqs)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
conversationSeqs := make([]*msg.ConversationSeqs, 0, len(conversations))
|
|
|
|
|
for _, c := range conversations {
|
|
|
|
|
if seq := maxSeqs[c.ConversationID]; seq > 0 {
|
|
|
|
|
conversationSeqs = append(conversationSeqs, &msg.ConversationSeqs{
|
|
|
|
|
ConversationID: c.ConversationID,
|
|
|
|
|
Seqs: []int64{seq},
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var msgs map[string]*sdkws.PullMsgs
|
|
|
|
|
if len(conversationSeqs) > 0 {
|
|
|
|
|
msgs, err = field(ctx, x.msg.GetSeqMessage,
|
|
|
|
|
&msg.GetSeqMessageReq{UserID: req.OwnerUserID, Conversations: conversationSeqs}, (*msg.GetSeqMessageResp).GetMsgs)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
resp := make([]ConversationMsg, 0, len(conversations))
|
|
|
|
|
for _, c := range conversations {
|
|
|
|
|
var lastMsg *sdkws.MsgData
|
|
|
|
|
if msgList, ok := msgs[c.ConversationID]; ok && len(msgList.Msgs) > 0 {
|
|
|
|
|
lastMsg = msgList.Msgs[0]
|
|
|
|
|
}
|
|
|
|
|
resp = append(resp, ConversationMsg{
|
|
|
|
|
Conversation: c,
|
|
|
|
|
LastMsg: lastMsg,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
return resp, nil
|
|
|
|
@ -110,9 +172,9 @@ func (x *JSSdk) GetActiveConversation(ctx *gin.Context) ([]ConversationMsg, erro
|
|
|
|
|
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"`
|
|
|
|
|
//ReadSeq int64 `json:"readSeq"`
|
|
|
|
|
//MaxSeq int64 `json:"maxSeq"`
|
|
|
|
|
//MaxSeqTime int64 `json:"maxSeqTime"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type sortActiveConversations struct {
|
|
|
|
@ -144,3 +206,21 @@ func (s sortActiveConversations) Less(i, j int) bool {
|
|
|
|
|
func (s sortActiveConversations) Swap(i, j int) {
|
|
|
|
|
s.Conversation[i], s.Conversation[j] = s.Conversation[j], s.Conversation[i]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 call[R any](c *gin.Context, fn func(ctx *gin.Context) (R, error)) {
|
|
|
|
|
resp, err := fn(c)
|
|
|
|
|
if err != nil {
|
|
|
|
|
apiresp.GinError(c, err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
apiresp.GinSuccess(c, resp)
|
|
|
|
|
}
|
|
|
|
|