mirror of
				https://github.com/openimsdk/open-im-server.git
				synced 2025-11-04 11:22:10 +08:00 
			
		
		
		
	* fix: GroupApplicationAcceptedNotification * fix: GroupApplicationAcceptedNotification * fix: NotificationUserInfoUpdate * cicd: robot automated Change * fix: component * fix: getConversationInfo * feat: cron task * feat: cron task * feat: cron task * feat: cron task * feat: cron task * fix: minio config url recognition error * update gomake version * update gomake version * fix: seq conversion bug * fix: redis pipe exec * fix: ImportFriends * fix: A large number of logs keysAndValues length is not even * feat: mark read aggregate write * feat: online status supports redis cluster * feat: online status supports redis cluster * feat: online status supports redis cluster * merge * merge * read seq is written to mongo * read seq is written to mongo * fix: invitation to join group notification * fix: friend op_user_id * feat: optimizing asynchronous context * feat: optimizing memamq size * feat: add GetSeqMessage * feat: GroupApplicationAgreeMemberEnterNotification * feat: GroupApplicationAgreeMemberEnterNotification * feat: go.mod * feat: go.mod * feat: join group notification and get seq * feat: join group notification and get seq * feat: avoid pulling messages from sessions with a large number of max seq values of 0 * feat: API supports gzip * go.mod * fix: nil pointer error on close * fix: listen error * fix: listen error * update go.mod * feat: add log * fix: token parse token value * fix: GetMsgBySeqs boundary issues * fix: sn_ not sort * fix: sn_ not sort * fix: sn_ not sort * fix: jssdk add * fix: jssdk support * fix: jssdk support * fix: jssdk support --------- Co-authored-by: withchao <withchao@users.noreply.github.com>
		
			
				
	
	
		
			263 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			263 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package jssdk
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"github.com/gin-gonic/gin"
 | 
						|
	"github.com/openimsdk/protocol/conversation"
 | 
						|
	"github.com/openimsdk/protocol/group"
 | 
						|
	"github.com/openimsdk/protocol/jssdk"
 | 
						|
	"github.com/openimsdk/protocol/msg"
 | 
						|
	"github.com/openimsdk/protocol/relation"
 | 
						|
	"github.com/openimsdk/protocol/sdkws"
 | 
						|
	"github.com/openimsdk/protocol/user"
 | 
						|
	"github.com/openimsdk/tools/mcontext"
 | 
						|
	"github.com/openimsdk/tools/utils/datautil"
 | 
						|
	"sort"
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	maxGetActiveConversation     = 500
 | 
						|
	defaultGetActiveConversation = 100
 | 
						|
)
 | 
						|
 | 
						|
func NewJSSdkApi(user user.UserClient, friend relation.FriendClient, group group.GroupClient, msg msg.MsgClient, conv conversation.ConversationClient) *JSSdk {
 | 
						|
	return &JSSdk{
 | 
						|
		user:   user,
 | 
						|
		friend: friend,
 | 
						|
		group:  group,
 | 
						|
		msg:    msg,
 | 
						|
		conv:   conv,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
type JSSdk struct {
 | 
						|
	user   user.UserClient
 | 
						|
	friend relation.FriendClient
 | 
						|
	group  group.GroupClient
 | 
						|
	msg    msg.MsgClient
 | 
						|
	conv   conversation.ConversationClient
 | 
						|
}
 | 
						|
 | 
						|
func (x *JSSdk) GetActiveConversations(c *gin.Context) {
 | 
						|
	call(c, x.getActiveConversations)
 | 
						|
}
 | 
						|
 | 
						|
func (x *JSSdk) GetConversations(c *gin.Context) {
 | 
						|
	call(c, x.getConversations)
 | 
						|
}
 | 
						|
 | 
						|
func (x *JSSdk) fillConversations(ctx context.Context, conversations []*jssdk.ConversationMsg) error {
 | 
						|
	if len(conversations) == 0 {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	var (
 | 
						|
		userIDs  []string
 | 
						|
		groupIDs []string
 | 
						|
	)
 | 
						|
	for _, c := range conversations {
 | 
						|
		if c.Conversation.GroupID == "" {
 | 
						|
			userIDs = append(userIDs, c.Conversation.UserID)
 | 
						|
		} else {
 | 
						|
			groupIDs = append(groupIDs, c.Conversation.GroupID)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	var (
 | 
						|
		userMap   map[string]*sdkws.UserInfo
 | 
						|
		friendMap map[string]*relation.FriendInfoOnly
 | 
						|
		groupMap  map[string]*sdkws.GroupInfo
 | 
						|
	)
 | 
						|
	if len(userIDs) > 0 {
 | 
						|
		users, err := field(ctx, x.user.GetDesignateUsers, &user.GetDesignateUsersReq{UserIDs: userIDs}, (*user.GetDesignateUsersResp).GetUsersInfo)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		friends, err := field(ctx, x.friend.GetFriendInfo, &relation.GetFriendInfoReq{OwnerUserID: conversations[0].Conversation.OwnerUserID, FriendUserIDs: userIDs}, (*relation.GetFriendInfoResp).GetFriendInfos)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		userMap = datautil.SliceToMap(users, (*sdkws.UserInfo).GetUserID)
 | 
						|
		friendMap = datautil.SliceToMap(friends, (*relation.FriendInfoOnly).GetFriendUserID)
 | 
						|
	}
 | 
						|
	if len(groupIDs) > 0 {
 | 
						|
		resp, err := x.group.GetGroupsInfo(ctx, &group.GetGroupsInfoReq{GroupIDs: groupIDs})
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		groupMap = datautil.SliceToMap(resp.GroupInfos, (*sdkws.GroupInfo).GetGroupID)
 | 
						|
	}
 | 
						|
	for _, c := range conversations {
 | 
						|
		if c.Conversation.GroupID == "" {
 | 
						|
			c.User = userMap[c.Conversation.UserID]
 | 
						|
			c.Friend = friendMap[c.Conversation.UserID]
 | 
						|
		} else {
 | 
						|
			c.Group = groupMap[c.Conversation.GroupID]
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (x *JSSdk) getActiveConversations(ctx context.Context, req *jssdk.GetActiveConversationsReq) (*jssdk.GetActiveConversationsResp, error) {
 | 
						|
	if req.Count <= 0 || req.Count > maxGetActiveConversation {
 | 
						|
		req.Count = defaultGetActiveConversation
 | 
						|
	}
 | 
						|
	req.OwnerUserID = mcontext.GetOpUserID(ctx)
 | 
						|
	conversationIDs, err := field(ctx, x.conv.GetConversationIDs,
 | 
						|
		&conversation.GetConversationIDsReq{UserID: req.OwnerUserID}, (*conversation.GetConversationIDsResp).GetConversationIDs)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	if len(conversationIDs) == 0 {
 | 
						|
		return &jssdk.GetActiveConversationsResp{}, nil
 | 
						|
	}
 | 
						|
	readSeq, err := field(ctx, x.msg.GetHasReadSeqs,
 | 
						|
		&msg.GetHasReadSeqsReq{UserID: req.OwnerUserID, ConversationIDs: conversationIDs}, (*msg.SeqsInfoResp).GetMaxSeqs)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	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 &jssdk.GetActiveConversationsResp{}, nil
 | 
						|
	}
 | 
						|
	sortConversations := sortActiveConversations{
 | 
						|
		Conversation: activeConversation,
 | 
						|
	}
 | 
						|
	if len(activeConversation) > 1 {
 | 
						|
		pinnedConversationIDs, err := field(ctx, x.conv.GetPinnedConversationIDs,
 | 
						|
			&conversation.GetPinnedConversationIDsReq{UserID: req.OwnerUserID}, (*conversation.GetPinnedConversationIDsResp).GetConversationIDs)
 | 
						|
		if err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
		sortConversations.PinnedConversationIDs = datautil.SliceSet(pinnedConversationIDs)
 | 
						|
	}
 | 
						|
	sort.Sort(&sortConversations)
 | 
						|
	sortList := sortConversations.Top(int(req.Count))
 | 
						|
	conversations, err := field(ctx, x.conv.GetConversations,
 | 
						|
		&conversation.GetConversationsReq{
 | 
						|
			OwnerUserID: req.OwnerUserID,
 | 
						|
			ConversationIDs: datautil.Slice(sortList, func(c *msg.ActiveConversation) string {
 | 
						|
				return c.ConversationID
 | 
						|
			})}, (*conversation.GetConversationsResp).GetConversations)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	msgs, err := field(ctx, x.msg.GetSeqMessage,
 | 
						|
		&msg.GetSeqMessageReq{
 | 
						|
			UserID: req.OwnerUserID,
 | 
						|
			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([]*jssdk.ConversationMsg, 0, len(sortList))
 | 
						|
	for _, c := range sortList {
 | 
						|
		conv, ok := conversationMap[c.ConversationID]
 | 
						|
		if !ok {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		var lastMsg *sdkws.MsgData
 | 
						|
		if msgList, ok := msgs[c.ConversationID]; ok && len(msgList.Msgs) > 0 {
 | 
						|
			lastMsg = msgList.Msgs[0]
 | 
						|
		}
 | 
						|
		resp = append(resp, &jssdk.ConversationMsg{
 | 
						|
			Conversation: conv,
 | 
						|
			LastMsg:      lastMsg,
 | 
						|
			MaxSeq:       c.MaxSeq,
 | 
						|
			ReadSeq:      readSeq[c.ConversationID],
 | 
						|
		})
 | 
						|
	}
 | 
						|
	if err := x.fillConversations(ctx, resp); err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	var unreadCount int64
 | 
						|
	for _, c := range activeConversation {
 | 
						|
		count := c.MaxSeq - readSeq[c.ConversationID]
 | 
						|
		if count > 0 {
 | 
						|
			unreadCount += count
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return &jssdk.GetActiveConversationsResp{
 | 
						|
		Conversations: resp,
 | 
						|
		UnreadCount:   unreadCount,
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
func (x *JSSdk) getConversations(ctx context.Context, req *jssdk.GetConversationsReq) (*jssdk.GetConversationsResp, error) {
 | 
						|
	req.OwnerUserID = mcontext.GetOpUserID(ctx)
 | 
						|
	conversations, err := field(ctx, x.conv.GetConversations, &conversation.GetConversationsReq{OwnerUserID: req.OwnerUserID, ConversationIDs: req.ConversationIDs}, (*conversation.GetConversationsResp).GetConversations)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	if len(conversations) == 0 {
 | 
						|
		return &jssdk.GetConversationsResp{}, nil
 | 
						|
	}
 | 
						|
	req.ConversationIDs = datautil.Slice(conversations, func(c *conversation.Conversation) string {
 | 
						|
		return c.ConversationID
 | 
						|
	})
 | 
						|
	maxSeqs, err := field(ctx, x.msg.GetMaxSeqs,
 | 
						|
		&msg.GetMaxSeqsReq{ConversationIDs: req.ConversationIDs}, (*msg.SeqsInfoResp).GetMaxSeqs)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	readSeqs, err := field(ctx, x.msg.GetHasReadSeqs,
 | 
						|
		&msg.GetHasReadSeqsReq{UserID: req.OwnerUserID, ConversationIDs: req.ConversationIDs}, (*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([]*jssdk.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, &jssdk.ConversationMsg{
 | 
						|
			Conversation: c,
 | 
						|
			LastMsg:      lastMsg,
 | 
						|
			MaxSeq:       maxSeqs[c.ConversationID],
 | 
						|
			ReadSeq:      readSeqs[c.ConversationID],
 | 
						|
		})
 | 
						|
	}
 | 
						|
	if err := x.fillConversations(ctx, resp); err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	var unreadCount int64
 | 
						|
	for conversationID, maxSeq := range maxSeqs {
 | 
						|
		count := maxSeq - readSeqs[conversationID]
 | 
						|
		if count > 0 {
 | 
						|
			unreadCount += count
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return &jssdk.GetConversationsResp{
 | 
						|
		Conversations: resp,
 | 
						|
		UnreadCount:   unreadCount,
 | 
						|
	}, nil
 | 
						|
}
 |