From bc326704f150577fabfe2ec17f34bf6b6ccd13cd Mon Sep 17 00:00:00 2001 From: chao <48119764+withchao@users.noreply.github.com> Date: Mon, 26 May 2025 10:06:35 +0800 Subject: [PATCH] feat: optimize friend and group applications (#3384) * pb * fix: Modifying other fields while setting IsPrivateChat does not take effect * fix: quote message error revoke * refactoring scheduled tasks * refactoring scheduled tasks * refactoring scheduled tasks * refactoring scheduled tasks * refactoring scheduled tasks * refactoring scheduled tasks * upgrading pkg tools * fix * fix * optimize log output * feat: support GetLastMessage * feat: support GetLastMessage * feat: s3 switch * feat: s3 switch * fix: GetUsersOnline * feat: SendBusinessNotification supported configuration parameters * feat: SendBusinessNotification supported configuration parameters * feat: SendBusinessNotification supported configuration parameters * feat: seq conversion failed without exiting * fix: DeleteDoc crash * fix: fill send time * fix: fill send time * fix: crash caused by withdrawing messages from users who have left the group * fix: user msg timestamp * seq read config * seq read config * fix: the source message of the reference is withdrawn, and the referenced message is deleted * feat: optimize the default notification.yml * fix: shouldPushOffline * fix: the sorting is wrong after canceling the administrator in group settings * feat: Sending messages supports returning fields modified by webhook * feat: Sending messages supports returning fields modified by webhook * feat: Sending messages supports returning fields modified by webhook * fix: oss specifies content-type when uploading * fix: the version number contains a line break * fix: the version number contains a line break * feat: GetConversationsHasReadAndMaxSeq support pinned * feat: GetConversationsHasReadAndMaxSeq support pinned * feat: GetConversationsHasReadAndMaxSeq support pinned * fix: transferring the group owner to a muted member, incremental version error * feat: unified conversion code * feat: update gomake * fix: in standalone mode, the user online status is wrong * fix: add permission check * fix: add permission check * fix: add rpc interface permission check * fix: CreateGroupChatConversations * feat: optimize friend and group applications * feat: optimize friend and group applications * feat: optimize friend and group applications * feat: optimize friend and group applications (cherry picked from commit 8e61f30e9c59916671e4a75844dcc0a4dfcd5d8a) # Conflicts: # go.mod # go.sum --- go.mod | 4 +- go.sum | 12 +- internal/api/friend.go | 4 + internal/api/group.go | 4 + internal/api/router.go | 2 + internal/rpc/group/group.go | 53 +++++- internal/rpc/group/notification.go | 70 +++++++- internal/rpc/relation/friend.go | 37 ++++- internal/rpc/relation/notification.go | 156 +++++++++++------- pkg/common/convert/friend.go | 12 +- pkg/common/storage/controller/friend.go | 21 ++- pkg/common/storage/controller/group.go | 24 +-- pkg/common/storage/database/friend_request.go | 6 +- pkg/common/storage/database/group_request.go | 6 +- .../storage/database/mgo/friend_request.go | 48 ++++-- .../storage/database/mgo/group_request.go | 56 ++++++- 16 files changed, 389 insertions(+), 126 deletions(-) diff --git a/go.mod b/go.mod index 5a2b0c263..020457282 100644 --- a/go.mod +++ b/go.mod @@ -12,8 +12,8 @@ require ( github.com/gorilla/websocket v1.5.1 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 github.com/mitchellh/mapstructure v1.5.0 - github.com/openimsdk/protocol v0.0.72-alpha.78 - github.com/openimsdk/tools v0.0.50-alpha.74 + github.com/openimsdk/protocol v0.0.73-alpha.12 + github.com/openimsdk/tools v0.0.50-alpha.84 github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.18.0 github.com/stretchr/testify v1.9.0 diff --git a/go.sum b/go.sum index af3515763..6298f98c9 100644 --- a/go.sum +++ b/go.sum @@ -345,12 +345,12 @@ github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y= github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= -github.com/openimsdk/gomake v0.0.14-alpha.5 h1:VY9c5x515lTfmdhhPjMvR3BBRrRquAUCFsz7t7vbv7Y= -github.com/openimsdk/gomake v0.0.14-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI= -github.com/openimsdk/protocol v0.0.72-alpha.78 h1:n9HVj5olMPiGLF3Z4apPvvYzn2yOpyrsn2/YiAaIsxw= -github.com/openimsdk/protocol v0.0.72-alpha.78/go.mod h1:WF7EuE55vQvpyUAzDXcqg+B+446xQyEba0X35lTINmw= -github.com/openimsdk/tools v0.0.50-alpha.74 h1:yh10SiMiivMEjicEQg+QAsH4pvaO+4noMPdlw+ew0Kc= -github.com/openimsdk/tools v0.0.50-alpha.74/go.mod h1:n2poR3asX1e1XZce4O+MOWAp+X02QJRFvhcLCXZdzRo= +github.com/openimsdk/gomake v0.0.15-alpha.5 h1:eEZCEHm+NsmcO3onXZPIUbGFCYPYbsX5beV3ZyOsGhY= +github.com/openimsdk/gomake v0.0.15-alpha.5/go.mod h1:PndCozNc2IsQIciyn9mvEblYWZwJmAI+06z94EY+csI= +github.com/openimsdk/protocol v0.0.73-alpha.12 h1:2NYawXeHChYUeSme6QJ9pOLh+Empce2WmwEtbP4JvKk= +github.com/openimsdk/protocol v0.0.73-alpha.12/go.mod h1:WF7EuE55vQvpyUAzDXcqg+B+446xQyEba0X35lTINmw= +github.com/openimsdk/tools v0.0.50-alpha.84 h1:jN60Ys/0edZjL/TDmm/5VSJFP4pGYRipkWqhILJbq/8= +github.com/openimsdk/tools v0.0.50-alpha.84/go.mod h1:n2poR3asX1e1XZce4O+MOWAp+X02QJRFvhcLCXZdzRo= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= diff --git a/internal/api/friend.go b/internal/api/friend.go index 7d84ff0dc..0943e8a5d 100644 --- a/internal/api/friend.go +++ b/internal/api/friend.go @@ -114,3 +114,7 @@ func (o *FriendApi) GetIncrementalBlacks(c *gin.Context) { func (o *FriendApi) GetFullFriendUserIDs(c *gin.Context) { a2r.Call(c, relation.FriendClient.GetFullFriendUserIDs, o.Client) } + +func (o *FriendApi) GetSelfUnhandledApplyCount(c *gin.Context) { + a2r.Call(c, relation.FriendClient.GetSelfUnhandledApplyCount, o.Client) +} diff --git a/internal/api/group.go b/internal/api/group.go index 97b6b73f0..926d19a8a 100644 --- a/internal/api/group.go +++ b/internal/api/group.go @@ -165,3 +165,7 @@ func (o *GroupApi) GetFullGroupMemberUserIDs(c *gin.Context) { func (o *GroupApi) GetFullJoinGroupIDs(c *gin.Context) { a2r.Call(c, group.GroupClient.GetFullJoinGroupIDs, o.Client) } + +func (o *GroupApi) GetGroupApplicationUnhandledCount(c *gin.Context) { + a2r.Call(c, group.GroupClient.GetGroupApplicationUnhandledCount, o.Client) +} diff --git a/internal/api/router.go b/internal/api/router.go index 72cafc6b3..bad891fda 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -149,6 +149,7 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co friendRouterGroup.POST("/update_friends", f.UpdateFriends) friendRouterGroup.POST("/get_incremental_friends", f.GetIncrementalFriends) friendRouterGroup.POST("/get_full_friend_user_ids", f.GetFullFriendUserIDs) + friendRouterGroup.POST("/get_self_unhandled_apply_count", f.GetSelfUnhandledApplyCount) } g := NewGroupApi(group.NewGroupClient(groupConn)) @@ -185,6 +186,7 @@ func newGinRouter(ctx context.Context, client discovery.SvcDiscoveryRegistry, co groupRouterGroup.POST("/get_incremental_group_members_batch", g.GetIncrementalGroupMemberBatch) groupRouterGroup.POST("/get_full_group_member_user_ids", g.GetFullGroupMemberUserIDs) groupRouterGroup.POST("/get_full_join_group_ids", g.GetFullJoinGroupIDs) + groupRouterGroup.POST("/get_group_application_unhandled_count", g.GetGroupApplicationUnhandledCount) } // certificate { diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go index 9a9f4d4d9..768cce3d2 100644 --- a/internal/rpc/group/group.go +++ b/internal/rpc/group/group.go @@ -426,7 +426,7 @@ func (g *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite ReqMessage: request.ReqMsg, JoinSource: request.JoinSource, InviterUserID: request.InviterUserID, - }) + }, request) } return &pbgroup.InviteUserToGroupResp{}, nil } @@ -679,15 +679,34 @@ func (g *groupServer) getGroupMembersInfo(ctx context.Context, groupID string, u // GetGroupApplicationList handles functions that get a list of group requests. func (g *groupServer) GetGroupApplicationList(ctx context.Context, req *pbgroup.GetGroupApplicationListReq) (*pbgroup.GetGroupApplicationListResp, error) { - groupIDs, err := g.db.FindUserManagedGroupID(ctx, req.FromUserID) - if err != nil { - return nil, err + var ( + groupIDs []string + err error + ) + if len(req.GroupIDs) == 0 { + groupIDs, err = g.db.FindUserManagedGroupID(ctx, req.FromUserID) + if err != nil { + return nil, err + } + } else { + req.GroupIDs = datautil.Distinct(req.GroupIDs) + if !authverify.IsAdmin(ctx) { + for _, groupID := range req.GroupIDs { + if err := g.CheckGroupAdmin(ctx, groupID); err != nil { + return nil, err + } + } + } + groupIDs = req.GroupIDs } resp := &pbgroup.GetGroupApplicationListResp{} if len(groupIDs) == 0 { return resp, nil } - total, groupRequests, err := g.db.PageGroupRequest(ctx, groupIDs, req.Pagination) + handleResults := datautil.Slice(req.HandleResults, func(e int32) int { + return int(e) + }) + total, groupRequests, err := g.db.PageGroupRequest(ctx, groupIDs, handleResults, req.Pagination) if err != nil { return nil, err } @@ -752,6 +771,23 @@ func (g *groupServer) GetGroupsInfo(ctx context.Context, req *pbgroup.GetGroupsI }, nil } +func (g *groupServer) GetGroupApplicationUnhandledCount(ctx context.Context, req *pbgroup.GetGroupApplicationUnhandledCountReq) (*pbgroup.GetGroupApplicationUnhandledCountResp, error) { + if err := authverify.CheckAccess(ctx, req.UserID); err != nil { + return nil, err + } + groupIDs, err := g.db.FindUserManagedGroupID(ctx, req.UserID) + if err != nil { + return nil, err + } + count, err := g.db.GetGroupApplicationUnhandledCount(ctx, groupIDs, req.Time) + if err != nil { + return nil, err + } + return &pbgroup.GetGroupApplicationUnhandledCountResp{ + Count: count, + }, nil +} + func (g *groupServer) getGroupsInfo(ctx context.Context, groupIDs []string) ([]*sdkws.GroupInfo, error) { if len(groupIDs) == 0 { return nil, nil @@ -933,7 +969,7 @@ func (g *groupServer) JoinGroup(ctx context.Context, req *pbgroup.JoinGroupReq) if err = g.db.CreateGroupRequest(ctx, []*model.GroupRequest{&groupRequest}); err != nil { return nil, err } - g.notification.JoinGroupApplicationNotification(ctx, req) + g.notification.JoinGroupApplicationNotification(ctx, req, &groupRequest) return &pbgroup.JoinGroupResp{}, nil } @@ -1320,7 +1356,10 @@ func (g *groupServer) GetUserReqApplicationList(ctx context.Context, req *pbgrou if err != nil { return nil, err } - total, requests, err := g.db.PageGroupRequestUser(ctx, req.UserID, req.Pagination) + handleResults := datautil.Slice(req.HandleResults, func(e int32) int { + return int(e) + }) + total, requests, err := g.db.PageGroupRequestUser(ctx, req.UserID, req.GroupIDs, handleResults, req.Pagination) if err != nil { return nil, err } diff --git a/internal/rpc/group/notification.go b/internal/rpc/group/notification.go index 973c219e9..7894ccc00 100644 --- a/internal/rpc/group/notification.go +++ b/internal/rpc/group/notification.go @@ -20,6 +20,7 @@ import ( "fmt" "time" + "github.com/google/uuid" "github.com/openimsdk/open-im-server/v3/pkg/rpcli" "github.com/openimsdk/open-im-server/v3/pkg/authverify" @@ -364,13 +365,46 @@ func (g *NotificationSender) GroupInfoSetAnnouncementNotification(ctx context.Co g.Notification(ctx, mcontext.GetOpUserID(ctx), tips.Group.GroupID, constant.GroupInfoSetAnnouncementNotification, tips, notification.WithRpcGetUserName(), notification.WithSendMessage(sendMessage)) } -func (g *NotificationSender) JoinGroupApplicationNotification(ctx context.Context, req *pbgroup.JoinGroupReq) { +func (g *NotificationSender) uuid() string { + return uuid.New().String() +} + +func (g *NotificationSender) getGroupRequest(ctx context.Context, groupID string, userID string) (*sdkws.GroupRequest, error) { + request, err := g.db.TakeGroupRequest(ctx, groupID, userID) + if err != nil { + return nil, err + } + users, err := g.getUsersInfo(ctx, []string{userID}) + if err != nil { + return nil, err + } + if len(users) == 0 { + return nil, servererrs.ErrUserIDNotFound.WrapMsg(fmt.Sprintf("user %s not found", userID)) + } + info, ok := users[0].(*sdkws.UserInfo) + if !ok { + info = &sdkws.UserInfo{ + UserID: users[0].GetUserID(), + Nickname: users[0].GetNickname(), + FaceURL: users[0].GetFaceURL(), + Ex: users[0].GetEx(), + } + } + return convert.Db2PbGroupRequest(request, info, nil), nil +} + +func (g *NotificationSender) JoinGroupApplicationNotification(ctx context.Context, req *pbgroup.JoinGroupReq, dbReq *model.GroupRequest) { var err error defer func() { if err != nil { log.ZError(ctx, stringutil.GetFuncName(1)+" failed", err) } }() + request, err := g.getGroupRequest(ctx, dbReq.GroupID, dbReq.UserID) + if err != nil { + log.ZError(ctx, "JoinGroupApplicationNotification getGroupRequest", err, "dbReq", dbReq) + return + } var group *sdkws.GroupInfo group, err = g.getGroupInfo(ctx, req.GroupID) if err != nil { @@ -386,7 +420,13 @@ func (g *NotificationSender) JoinGroupApplicationNotification(ctx context.Contex return } userIDs = append(userIDs, req.InviterUserID, mcontext.GetOpUserID(ctx)) - tips := &sdkws.JoinGroupApplicationTips{Group: group, Applicant: user, ReqMsg: req.ReqMessage} + tips := &sdkws.JoinGroupApplicationTips{ + Group: group, + Applicant: user, + ReqMsg: req.ReqMessage, + Uuid: g.uuid(), + Request: request, + } for _, userID := range datautil.Distinct(userIDs) { g.Notification(ctx, mcontext.GetOpUserID(ctx), userID, constant.JoinGroupApplicationNotification, tips) } @@ -416,6 +456,11 @@ func (g *NotificationSender) GroupApplicationAcceptedNotification(ctx context.Co log.ZError(ctx, stringutil.GetFuncName(1)+" failed", err) } }() + request, err := g.getGroupRequest(ctx, req.GroupID, req.FromUserID) + if err != nil { + log.ZError(ctx, "GroupApplicationAcceptedNotification getGroupRequest", err, "req", req) + return + } var group *sdkws.GroupInfo group, err = g.getGroupInfo(ctx, req.GroupID) if err != nil { @@ -431,8 +476,14 @@ func (g *NotificationSender) GroupApplicationAcceptedNotification(ctx context.Co if err = g.fillOpUser(ctx, &opUser, group.GroupID); err != nil { return } + tips := &sdkws.GroupApplicationAcceptedTips{ + Group: group, + OpUser: opUser, + HandleMsg: req.HandledMsg, + Uuid: g.uuid(), + Request: request, + } for _, userID := range append(userIDs, req.FromUserID) { - tips := &sdkws.GroupApplicationAcceptedTips{Group: group, OpUser: opUser, HandleMsg: req.HandledMsg} if userID == req.FromUserID { tips.ReceiverAs = applicantReceiver } else { @@ -449,6 +500,11 @@ func (g *NotificationSender) GroupApplicationRejectedNotification(ctx context.Co log.ZError(ctx, stringutil.GetFuncName(1)+" failed", err) } }() + request, err := g.getGroupRequest(ctx, req.GroupID, req.FromUserID) + if err != nil { + log.ZError(ctx, "GroupApplicationAcceptedNotification getGroupRequest", err, "req", req) + return + } var group *sdkws.GroupInfo group, err = g.getGroupInfo(ctx, req.GroupID) if err != nil { @@ -464,8 +520,14 @@ func (g *NotificationSender) GroupApplicationRejectedNotification(ctx context.Co if err = g.fillOpUser(ctx, &opUser, group.GroupID); err != nil { return } + tips := &sdkws.GroupApplicationRejectedTips{ + Group: group, + OpUser: opUser, + HandleMsg: req.HandledMsg, + Uuid: g.uuid(), + Request: request, + } for _, userID := range append(userIDs, req.FromUserID) { - tips := &sdkws.GroupApplicationAcceptedTips{Group: group, OpUser: opUser, HandleMsg: req.HandledMsg} if userID == req.FromUserID { tips.ReceiverAs = applicantReceiver } else { diff --git a/internal/rpc/relation/friend.go b/internal/rpc/relation/friend.go index e5164ac93..c7612b477 100644 --- a/internal/rpc/relation/friend.go +++ b/internal/rpc/relation/friend.go @@ -341,13 +341,16 @@ func (s *friendServer) GetPaginationFriendsApplyTo(ctx context.Context, req *rel return nil, err } - total, friendRequests, err := s.db.PageFriendRequestToMe(ctx, req.UserID, req.Pagination) + handleResults := datautil.Slice(req.HandleResults, func(e int32) int { + return int(e) + }) + total, friendRequests, err := s.db.PageFriendRequestToMe(ctx, req.UserID, handleResults, req.Pagination) if err != nil { return nil, err } resp = &relation.GetPaginationFriendsApplyToResp{} - resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.userClient.GetUsersInfoMap) + resp.FriendRequests, err = convert.FriendRequestDB2Pb(ctx, friendRequests, s.getCommonUserMap) if err != nil { return nil, err } @@ -364,7 +367,10 @@ func (s *friendServer) GetPaginationFriendsApplyFrom(ctx context.Context, req *r return nil, err } - total, friendRequests, err := s.db.PageFriendRequestFromMe(ctx, req.UserID, req.Pagination) + handleResults := datautil.Slice(req.HandleResults, func(e int32) int { + return int(e) + }) + total, friendRequests, err := s.db.PageFriendRequestFromMe(ctx, req.UserID, handleResults, req.Pagination) if err != nil { return nil, err } @@ -545,3 +551,28 @@ func (s *friendServer) UpdateFriends( s.notificationSender.FriendsInfoUpdateNotification(ctx, req.OwnerUserID, req.FriendUserIDs) return resp, nil } + +func (s *friendServer) GetSelfUnhandledApplyCount(ctx context.Context, req *relation.GetSelfUnhandledApplyCountReq) (*relation.GetSelfUnhandledApplyCountResp, error) { + if err := authverify.CheckAccess(ctx, req.UserID); err != nil { + return nil, err + } + + count, err := s.db.GetUnhandledCount(ctx, req.UserID, req.Time) + if err != nil { + return nil, err + } + + return &relation.GetSelfUnhandledApplyCountResp{ + Count: count, + }, nil +} + +func (s *friendServer) getCommonUserMap(ctx context.Context, userIDs []string) (map[string]common_user.CommonUser, error) { + users, err := s.userClient.GetUsersInfo(ctx, userIDs) + if err != nil { + return nil, err + } + return datautil.SliceToMapAny(users, func(e *sdkws.UserInfo) (string, common_user.CommonUser) { + return e.UserID, e + }), nil +} diff --git a/internal/rpc/relation/notification.go b/internal/rpc/relation/notification.go index caf2dafe1..d6a03003e 100644 --- a/internal/rpc/relation/notification.go +++ b/internal/rpc/relation/notification.go @@ -19,6 +19,9 @@ import ( "github.com/openimsdk/open-im-server/v3/pkg/rpcli" "github.com/openimsdk/protocol/msg" + "github.com/openimsdk/tools/errs" + "github.com/openimsdk/tools/log" + "github.com/openimsdk/tools/utils/datautil" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/database" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/versionctx" @@ -52,9 +55,7 @@ func WithFriendDB(db controller.FriendDatabase) friendNotificationSenderOptions } } -func WithDBFunc( - fn func(ctx context.Context, userIDs []string) (users []*relationtb.User, err error), -) friendNotificationSenderOptions { +func WithDBFunc(fn func(ctx context.Context, userIDs []string) (users []*relationtb.User, err error)) friendNotificationSenderOptions { return func(s *FriendNotificationSender) { f := func(ctx context.Context, userIDs []string) (result []common_user.CommonUser, err error) { users, err := fn(ctx, userIDs) @@ -70,9 +71,7 @@ func WithDBFunc( } } -func WithRpcFunc( - fn func(ctx context.Context, userIDs []string) ([]*sdkws.UserInfo, error), -) friendNotificationSenderOptions { +func WithRpcFunc(fn func(ctx context.Context, userIDs []string) ([]*sdkws.UserInfo, error)) friendNotificationSenderOptions { return func(s *FriendNotificationSender) { f := func(ctx context.Context, userIDs []string) (result []common_user.CommonUser, err error) { users, err := fn(ctx, userIDs) @@ -100,10 +99,7 @@ func NewFriendNotificationSender(conf *config.Notification, msgClient *rpcli.Msg return f } -func (f *FriendNotificationSender) getUsersInfoMap( - ctx context.Context, - userIDs []string, -) (map[string]*sdkws.UserInfo, error) { +func (f *FriendNotificationSender) getUsersInfoMap(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error) { users, err := f.getUsersInfo(ctx, userIDs) if err != nil { return nil, err @@ -116,10 +112,7 @@ func (f *FriendNotificationSender) getUsersInfoMap( } //nolint:unused -func (f *FriendNotificationSender) getFromToUserNickname( - ctx context.Context, - fromUserID, toUserID string, -) (string, string, error) { +func (f *FriendNotificationSender) getFromToUserNickname(ctx context.Context, fromUserID, toUserID string) (string, string, error) { users, err := f.getUsersInfoMap(ctx, []string{fromUserID, toUserID}) if err != nil { return "", "", nil @@ -132,60 +125,107 @@ func (f *FriendNotificationSender) UserInfoUpdatedNotification(ctx context.Conte f.Notification(ctx, mcontext.GetOpUserID(ctx), changedUserID, constant.UserInfoUpdatedNotification, &tips) } +func (f *FriendNotificationSender) getCommonUserMap(ctx context.Context, userIDs []string) (map[string]common_user.CommonUser, error) { + users, err := f.getUsersInfo(ctx, userIDs) + if err != nil { + return nil, err + } + return datautil.SliceToMap(users, func(e common_user.CommonUser) string { + return e.GetUserID() + }), nil +} + +func (f *FriendNotificationSender) getFriendRequests(ctx context.Context, fromUserID, toUserID string) (*sdkws.FriendRequest, error) { + if f.db == nil { + return nil, errs.ErrInternalServer.WithDetail("db is nil") + } + friendRequests, err := f.db.FindBothFriendRequests(ctx, fromUserID, toUserID) + if err != nil { + return nil, err + } + requests, err := convert.FriendRequestDB2Pb(ctx, friendRequests, f.getCommonUserMap) + if err != nil { + return nil, err + } + for _, request := range requests { + if request.FromUserID == fromUserID && request.ToUserID == toUserID { + return request, nil + } + } + return nil, errs.ErrRecordNotFound.WrapMsg("friend request not found", "fromUserID", fromUserID, "toUserID", toUserID) +} + func (f *FriendNotificationSender) FriendApplicationAddNotification(ctx context.Context, req *relation.ApplyToAddFriendReq) { - tips := sdkws.FriendApplicationTips{FromToUserID: &sdkws.FromToUserID{ - FromUserID: req.FromUserID, - ToUserID: req.ToUserID, - }} + request, err := f.getFriendRequests(ctx, req.FromUserID, req.ToUserID) + if err != nil { + log.ZError(ctx, "FriendApplicationAddNotification get friend request", err, "fromUserID", req.FromUserID, "toUserID", req.ToUserID) + return + } + tips := sdkws.FriendApplicationTips{ + FromToUserID: &sdkws.FromToUserID{ + FromUserID: req.FromUserID, + ToUserID: req.ToUserID, + }, + Request: request, + } f.Notification(ctx, req.FromUserID, req.ToUserID, constant.FriendApplicationNotification, &tips) } -func (f *FriendNotificationSender) FriendApplicationAgreedNotification( - ctx context.Context, - req *relation.RespondFriendApplyReq, -) { - tips := sdkws.FriendApplicationApprovedTips{FromToUserID: &sdkws.FromToUserID{ - FromUserID: req.FromUserID, - ToUserID: req.ToUserID, - }, HandleMsg: req.HandleMsg} +func (f *FriendNotificationSender) FriendApplicationAgreedNotification(ctx context.Context, req *relation.RespondFriendApplyReq) { + request, err := f.getFriendRequests(ctx, req.FromUserID, req.ToUserID) + if err != nil { + log.ZError(ctx, "FriendApplicationAgreedNotification get friend request", err, "fromUserID", req.FromUserID, "toUserID", req.ToUserID) + return + } + tips := sdkws.FriendApplicationApprovedTips{ + FromToUserID: &sdkws.FromToUserID{ + FromUserID: req.FromUserID, + ToUserID: req.ToUserID, + }, + HandleMsg: req.HandleMsg, + Request: request, + } f.Notification(ctx, req.ToUserID, req.FromUserID, constant.FriendApplicationApprovedNotification, &tips) } -func (f *FriendNotificationSender) FriendApplicationRefusedNotification( - ctx context.Context, - req *relation.RespondFriendApplyReq, -) { - tips := sdkws.FriendApplicationApprovedTips{FromToUserID: &sdkws.FromToUserID{ - FromUserID: req.FromUserID, - ToUserID: req.ToUserID, - }, HandleMsg: req.HandleMsg} +func (f *FriendNotificationSender) FriendApplicationRefusedNotification(ctx context.Context, req *relation.RespondFriendApplyReq) { + request, err := f.getFriendRequests(ctx, req.FromUserID, req.ToUserID) + if err != nil { + log.ZError(ctx, "FriendApplicationRefusedNotification get friend request", err, "fromUserID", req.FromUserID, "toUserID", req.ToUserID) + return + } + tips := sdkws.FriendApplicationRejectedTips{ + FromToUserID: &sdkws.FromToUserID{ + FromUserID: req.FromUserID, + ToUserID: req.ToUserID, + }, + HandleMsg: req.HandleMsg, + Request: request, + } f.Notification(ctx, req.ToUserID, req.FromUserID, constant.FriendApplicationRejectedNotification, &tips) } -func (f *FriendNotificationSender) FriendAddedNotification( - ctx context.Context, - operationID, opUserID, fromUserID, toUserID string, -) error { - tips := sdkws.FriendAddedTips{Friend: &sdkws.FriendInfo{}, OpUser: &sdkws.PublicUserInfo{}} - user, err := f.getUsersInfo(ctx, []string{opUserID}) - if err != nil { - return err - } - tips.OpUser.UserID = user[0].GetUserID() - tips.OpUser.Ex = user[0].GetEx() - tips.OpUser.Nickname = user[0].GetNickname() - tips.OpUser.FaceURL = user[0].GetFaceURL() - friends, err := f.db.FindFriendsWithError(ctx, fromUserID, []string{toUserID}) - if err != nil { - return err - } - tips.Friend, err = convert.FriendDB2Pb(ctx, friends[0], f.getUsersInfoMap) - if err != nil { - return err - } - f.Notification(ctx, fromUserID, toUserID, constant.FriendAddedNotification, &tips) - return nil -} +//func (f *FriendNotificationSender) FriendAddedNotification(ctx context.Context, operationID, opUserID, fromUserID, toUserID string) error { +// tips := sdkws.FriendAddedTips{Friend: &sdkws.FriendInfo{}, OpUser: &sdkws.PublicUserInfo{}} +// user, err := f.getUsersInfo(ctx, []string{opUserID}) +// if err != nil { +// return err +// } +// tips.OpUser.UserID = user[0].GetUserID() +// tips.OpUser.Ex = user[0].GetEx() +// tips.OpUser.Nickname = user[0].GetNickname() +// tips.OpUser.FaceURL = user[0].GetFaceURL() +// friends, err := f.db.FindFriendsWithError(ctx, fromUserID, []string{toUserID}) +// if err != nil { +// return err +// } +// tips.Friend, err = convert.FriendDB2Pb(ctx, friends[0], f.getUsersInfoMap) +// if err != nil { +// return err +// } +// f.Notification(ctx, fromUserID, toUserID, constant.FriendAddedNotification, &tips) +// return nil +//} func (f *FriendNotificationSender) FriendDeletedNotification(ctx context.Context, req *relation.DeleteFriendReq) { tips := sdkws.FriendDeletedTips{FromToUserID: &sdkws.FromToUserID{ diff --git a/pkg/common/convert/friend.go b/pkg/common/convert/friend.go index 6d346b0f4..e783ecb24 100644 --- a/pkg/common/convert/friend.go +++ b/pkg/common/convert/friend.go @@ -17,7 +17,9 @@ package convert import ( "context" "fmt" + "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model" + "github.com/openimsdk/open-im-server/v3/pkg/notification/common_user" "github.com/openimsdk/protocol/relation" "github.com/openimsdk/protocol/sdkws" @@ -98,7 +100,7 @@ func FriendOnlyDB2PbOnly(friendsDB []*model.Friend) []*relation.FriendInfoOnly { }) } -func FriendRequestDB2Pb(ctx context.Context, friendRequests []*model.FriendRequest, getUsers func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error)) ([]*sdkws.FriendRequest, error) { +func FriendRequestDB2Pb(ctx context.Context, friendRequests []*model.FriendRequest, getUsers func(ctx context.Context, userIDs []string) (map[string]common_user.CommonUser, error)) ([]*sdkws.FriendRequest, error) { if len(friendRequests) == 0 { return nil, nil } @@ -117,11 +119,11 @@ func FriendRequestDB2Pb(ctx context.Context, friendRequests []*model.FriendReque fromUser := users[friendRequest.FromUserID] res = append(res, &sdkws.FriendRequest{ FromUserID: friendRequest.FromUserID, - FromNickname: fromUser.Nickname, - FromFaceURL: fromUser.FaceURL, + FromNickname: fromUser.GetNickname(), + FromFaceURL: fromUser.GetFaceURL(), ToUserID: friendRequest.ToUserID, - ToNickname: toUser.Nickname, - ToFaceURL: toUser.FaceURL, + ToNickname: toUser.GetNickname(), + ToFaceURL: toUser.GetFaceURL(), HandleResult: friendRequest.HandleResult, ReqMsg: friendRequest.ReqMsg, CreateTime: friendRequest.CreateTime.UnixMilli(), diff --git a/pkg/common/storage/controller/friend.go b/pkg/common/storage/controller/friend.go index 88a5fc863..806468ea1 100644 --- a/pkg/common/storage/controller/friend.go +++ b/pkg/common/storage/controller/friend.go @@ -17,10 +17,11 @@ package controller import ( "context" "fmt" + "time" + "github.com/openimsdk/open-im-server/v3/pkg/common/storage/database" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model" - "time" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache" "github.com/openimsdk/protocol/constant" @@ -61,10 +62,10 @@ type FriendDatabase interface { PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*model.Friend, err error) // PageFriendRequestFromMe retrieves the friend requests sent by the user with pagination - PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error) + PageFriendRequestFromMe(ctx context.Context, userID string, handleResults []int, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error) // PageFriendRequestToMe retrieves the friend requests received by the user with pagination - PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error) + PageFriendRequestToMe(ctx context.Context, userID string, handleResults []int, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error) // FindFriendsWithError fetches specified friends of a user and returns an error if any do not exist FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*model.Friend, err error) @@ -87,6 +88,8 @@ type FriendDatabase interface { FindFriendUserID(ctx context.Context, friendUserID string) ([]string, error) OwnerIncrVersion(ctx context.Context, ownerUserID string, friendUserIDs []string, state int32) error + + GetUnhandledCount(ctx context.Context, userID string, ts int64) (int64, error) } type friendDatabase struct { @@ -334,13 +337,13 @@ func (f *friendDatabase) PageInWhoseFriends(ctx context.Context, friendUserID st } // PageFriendRequestFromMe retrieves friend requests sent by me. It does not return an error if the result is empty. -func (f *friendDatabase) PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error) { - return f.friendRequest.FindFromUserID(ctx, userID, pagination) +func (f *friendDatabase) PageFriendRequestFromMe(ctx context.Context, userID string, handleResults []int, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error) { + return f.friendRequest.FindFromUserID(ctx, userID, handleResults, pagination) } // PageFriendRequestToMe retrieves friend requests received by me. It does not return an error if the result is empty. -func (f *friendDatabase) PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error) { - return f.friendRequest.FindToUserID(ctx, userID, pagination) +func (f *friendDatabase) PageFriendRequestToMe(ctx context.Context, userID string, handleResults []int, pagination pagination.Pagination) (total int64, friends []*model.FriendRequest, err error) { + return f.friendRequest.FindToUserID(ctx, userID, handleResults, pagination) } // FindFriendsWithError retrieves specified friends' information for ownerUserID. Returns an error if any friend does not exist. @@ -397,3 +400,7 @@ func (f *friendDatabase) OwnerIncrVersion(ctx context.Context, ownerUserID strin } return f.cache.DelMaxFriendVersion(ownerUserID).ChainExecDel(ctx) } + +func (f *friendDatabase) GetUnhandledCount(ctx context.Context, userID string, ts int64) (int64, error) { + return f.friendRequest.GetUnhandledCount(ctx, userID, ts) +} diff --git a/pkg/common/storage/controller/group.go b/pkg/common/storage/controller/group.go index 072429ed0..539f7dccc 100644 --- a/pkg/common/storage/controller/group.go +++ b/pkg/common/storage/controller/group.go @@ -68,7 +68,7 @@ type GroupDatabase interface { // FindUserManagedGroupID retrieves group IDs managed by a user. FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) // PageGroupRequest paginates through group requests for specified groups. - PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) + PageGroupRequest(ctx context.Context, groupIDs []string, handleResults []int, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) // GetGroupRoleLevelMemberIDs retrieves user IDs of group members with a specific role level. GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error) @@ -100,7 +100,7 @@ type GroupDatabase interface { // FindGroupRequests retrieves multiple group join requests. FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*model.GroupRequest, error) // PageGroupRequestUser paginates through group join requests made by a user. - PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) + PageGroupRequestUser(ctx context.Context, userID string, groupIDs []string, handleResults []int, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) // CountTotal counts the total number of groups as of a certain date. CountTotal(ctx context.Context, before *time.Time) (count int64, err error) @@ -124,6 +124,8 @@ type GroupDatabase interface { SearchJoinGroup(ctx context.Context, userID string, keyword string, pagination pagination.Pagination) (int64, []*model.Group, error) FindJoinGroupID(ctx context.Context, userID string) ([]string, error) + + GetGroupApplicationUnhandledCount(ctx context.Context, groupIDs []string, ts int64) (int64, error) } func NewGroupDatabase( @@ -304,8 +306,8 @@ func (g *groupDatabase) FindUserManagedGroupID(ctx context.Context, userID strin return g.groupMemberDB.FindUserManagedGroupID(ctx, userID) } -func (g *groupDatabase) PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) { - return g.groupRequestDB.PageGroup(ctx, groupIDs, pagination) +func (g *groupDatabase) PageGroupRequest(ctx context.Context, groupIDs []string, handleResults []int, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) { + return g.groupRequestDB.PageGroup(ctx, groupIDs, handleResults, pagination) } func (g *groupDatabase) PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*model.GroupMember, err error) { @@ -463,16 +465,12 @@ func (g *groupDatabase) CreateGroupRequest(ctx context.Context, requests []*mode }) } -func (g *groupDatabase) TakeGroupRequest( - ctx context.Context, - groupID string, - userID string, -) (*model.GroupRequest, error) { +func (g *groupDatabase) TakeGroupRequest(ctx context.Context, groupID string, userID string) (*model.GroupRequest, error) { return g.groupRequestDB.Take(ctx, groupID, userID) } -func (g *groupDatabase) PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) { - return g.groupRequestDB.Page(ctx, userID, pagination) +func (g *groupDatabase) PageGroupRequestUser(ctx context.Context, userID string, groupIDs []string, handleResults []int, pagination pagination.Pagination) (int64, []*model.GroupRequest, error) { + return g.groupRequestDB.Page(ctx, userID, groupIDs, handleResults, pagination) } func (g *groupDatabase) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) { @@ -565,3 +563,7 @@ func (g *groupDatabase) MemberGroupIncrVersion(ctx context.Context, groupID stri } return g.cache.DelMaxGroupMemberVersion(groupID).ChainExecDel(ctx) } + +func (g *groupDatabase) GetGroupApplicationUnhandledCount(ctx context.Context, groupIDs []string, ts int64) (int64, error) { + return g.groupRequestDB.GetUnhandledCount(ctx, groupIDs, ts) +} diff --git a/pkg/common/storage/database/friend_request.go b/pkg/common/storage/database/friend_request.go index f163b4831..c0df77823 100644 --- a/pkg/common/storage/database/friend_request.go +++ b/pkg/common/storage/database/friend_request.go @@ -16,6 +16,7 @@ package database import ( "context" + "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model" "github.com/openimsdk/tools/db/pagination" ) @@ -33,8 +34,9 @@ type FriendRequest interface { Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *model.FriendRequest, err error) Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *model.FriendRequest, err error) // Get list of friend requests received by toUserID - FindToUserID(ctx context.Context, toUserID string, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error) + FindToUserID(ctx context.Context, toUserID string, handleResults []int, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error) // Get list of friend requests sent by fromUserID - FindFromUserID(ctx context.Context, fromUserID string, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error) + FindFromUserID(ctx context.Context, fromUserID string, handleResults []int, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*model.FriendRequest, err error) + GetUnhandledCount(ctx context.Context, userID string, ts int64) (int64, error) } diff --git a/pkg/common/storage/database/group_request.go b/pkg/common/storage/database/group_request.go index 7309584f0..766ea2cd5 100644 --- a/pkg/common/storage/database/group_request.go +++ b/pkg/common/storage/database/group_request.go @@ -16,6 +16,7 @@ package database import ( "context" + "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model" "github.com/openimsdk/tools/db/pagination" ) @@ -26,6 +27,7 @@ type GroupRequest interface { UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error) Take(ctx context.Context, groupID string, userID string) (groupRequest *model.GroupRequest, err error) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*model.GroupRequest, error) - Page(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) - PageGroup(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) + Page(ctx context.Context, userID string, groupIDs []string, handleResults []int, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) + PageGroup(ctx context.Context, groupIDs []string, handleResults []int, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) + GetUnhandledCount(ctx context.Context, groupIDs []string, ts int64) (int64, error) } diff --git a/pkg/common/storage/database/mgo/friend_request.go b/pkg/common/storage/database/mgo/friend_request.go index 4eed2f4a2..95edb77df 100644 --- a/pkg/common/storage/database/mgo/friend_request.go +++ b/pkg/common/storage/database/mgo/friend_request.go @@ -16,24 +16,32 @@ package mgo import ( "context" + "github.com/openimsdk/open-im-server/v3/pkg/common/storage/database" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model" + "go.mongodb.org/mongo-driver/mongo/options" "github.com/openimsdk/tools/db/mongoutil" "github.com/openimsdk/tools/db/pagination" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" ) func NewFriendRequestMongo(db *mongo.Database) (database.FriendRequest, error) { coll := db.Collection(database.FriendRequestName) - _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{ - Keys: bson.D{ - {Key: "from_user_id", Value: 1}, - {Key: "to_user_id", Value: 1}, + _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{ + { + Keys: bson.D{ + {Key: "from_user_id", Value: 1}, + {Key: "to_user_id", Value: 1}, + }, + Options: options.Index().SetUnique(true), + }, + { + Keys: bson.D{ + {Key: "create_time", Value: -1}, + }, }, - Options: options.Index().SetUnique(true), }) if err != nil { return nil, err @@ -45,12 +53,24 @@ type FriendRequestMgo struct { coll *mongo.Collection } -func (f *FriendRequestMgo) FindToUserID(ctx context.Context, toUserID string, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error) { - return mongoutil.FindPage[*model.FriendRequest](ctx, f.coll, bson.M{"to_user_id": toUserID}, pagination) +func (f *FriendRequestMgo) sort() any { + return bson.D{{Key: "create_time", Value: -1}} } -func (f *FriendRequestMgo) FindFromUserID(ctx context.Context, fromUserID string, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error) { - return mongoutil.FindPage[*model.FriendRequest](ctx, f.coll, bson.M{"from_user_id": fromUserID}, pagination) +func (f *FriendRequestMgo) FindToUserID(ctx context.Context, toUserID string, handleResults []int, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error) { + filter := bson.M{"to_user_id": toUserID} + if len(handleResults) > 0 { + filter["handle_result"] = bson.M{"$in": handleResults} + } + return mongoutil.FindPage[*model.FriendRequest](ctx, f.coll, filter, pagination, options.Find().SetSort(f.sort())) +} + +func (f *FriendRequestMgo) FindFromUserID(ctx context.Context, fromUserID string, handleResults []int, pagination pagination.Pagination) (total int64, friendRequests []*model.FriendRequest, err error) { + filter := bson.M{"from_user_id": fromUserID} + if len(handleResults) > 0 { + filter["handle_result"] = bson.M{"$in": handleResults} + } + return mongoutil.FindPage[*model.FriendRequest](ctx, f.coll, filter, pagination, options.Find().SetSort(f.sort())) } func (f *FriendRequestMgo) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*model.FriendRequest, err error) { @@ -110,3 +130,11 @@ func (f *FriendRequestMgo) Find(ctx context.Context, fromUserID, toUserID string func (f *FriendRequestMgo) Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *model.FriendRequest, err error) { return f.Find(ctx, fromUserID, toUserID) } + +func (f *FriendRequestMgo) GetUnhandledCount(ctx context.Context, userID string, ts int64) (int64, error) { + filter := bson.M{"to_user_id": userID, "handle_result": 0} + if ts != 0 { + filter["req_time"] = bson.M{"$gt": ts} + } + return mongoutil.Count(ctx, f.coll, filter) +} diff --git a/pkg/common/storage/database/mgo/group_request.go b/pkg/common/storage/database/mgo/group_request.go index b1942b708..c67bbb3ea 100644 --- a/pkg/common/storage/database/mgo/group_request.go +++ b/pkg/common/storage/database/mgo/group_request.go @@ -16,8 +16,10 @@ package mgo import ( "context" + "github.com/openimsdk/open-im-server/v3/pkg/common/storage/database" "github.com/openimsdk/open-im-server/v3/pkg/common/storage/model" + "github.com/openimsdk/tools/utils/datautil" "github.com/openimsdk/tools/db/mongoutil" "github.com/openimsdk/tools/db/pagination" @@ -29,12 +31,19 @@ import ( func NewGroupRequestMgo(db *mongo.Database) (database.GroupRequest, error) { coll := db.Collection(database.GroupRequestName) - _, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{ - Keys: bson.D{ - {Key: "group_id", Value: 1}, - {Key: "user_id", Value: 1}, + _, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{ + { + Keys: bson.D{ + {Key: "group_id", Value: 1}, + {Key: "user_id", Value: 1}, + }, + Options: options.Index().SetUnique(true), + }, + { + Keys: bson.D{ + {Key: "req_time", Value: -1}, + }, }, - Options: options.Index().SetUnique(true), }) if err != nil { return nil, errs.Wrap(err) @@ -66,10 +75,39 @@ func (g *GroupRequestMgo) FindGroupRequests(ctx context.Context, groupID string, return mongoutil.Find[*model.GroupRequest](ctx, g.coll, bson.M{"group_id": groupID, "user_id": bson.M{"$in": userIDs}}) } -func (g *GroupRequestMgo) Page(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) { - return mongoutil.FindPage[*model.GroupRequest](ctx, g.coll, bson.M{"user_id": userID}, pagination) +func (g *GroupRequestMgo) sort() any { + return bson.D{{Key: "req_time", Value: -1}} } -func (g *GroupRequestMgo) PageGroup(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) { - return mongoutil.FindPage[*model.GroupRequest](ctx, g.coll, bson.M{"group_id": bson.M{"$in": groupIDs}}, pagination) +func (g *GroupRequestMgo) Page(ctx context.Context, userID string, groupIDs []string, handleResults []int, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) { + filter := bson.M{"user_id": userID} + if len(groupIDs) > 0 { + filter["group_id"] = bson.M{"$in": datautil.Distinct(groupIDs)} + } + if len(handleResults) > 0 { + filter["handle_result"] = bson.M{"$in": handleResults} + } + return mongoutil.FindPage[*model.GroupRequest](ctx, g.coll, filter, pagination, options.Find().SetSort(g.sort())) +} + +func (g *GroupRequestMgo) PageGroup(ctx context.Context, groupIDs []string, handleResults []int, pagination pagination.Pagination) (total int64, groups []*model.GroupRequest, err error) { + if len(groupIDs) == 0 { + return 0, nil, nil + } + filter := bson.M{"group_id": bson.M{"$in": groupIDs}} + if len(handleResults) > 0 { + filter["handle_result"] = bson.M{"$in": handleResults} + } + return mongoutil.FindPage[*model.GroupRequest](ctx, g.coll, filter, pagination, options.Find().SetSort(g.sort())) +} + +func (g *GroupRequestMgo) GetUnhandledCount(ctx context.Context, groupIDs []string, ts int64) (int64, error) { + if len(groupIDs) == 0 { + return 0, nil + } + filter := bson.M{"group_id": bson.M{"$in": groupIDs}, "handle_result": 0} + if ts != 0 { + filter["req_time"] = bson.M{"$gt": ts} + } + return mongoutil.Count(ctx, g.coll, filter) }