From a2a082f681a900c0c064b5aca5227b6e4c56b12d Mon Sep 17 00:00:00 2001 From: AndrewZuo01 <59896149+AndrewZuo01@users.noreply.github.com> Date: Wed, 10 Jan 2024 10:27:03 +0800 Subject: [PATCH] update usercommand and fix callback (#1681) * update set pin friends * update set pin friends * update set pin friends * update set pin friends * update set pin friends * update set pin friends * fix bugs * fix bugs * debug * debug * debug * debug * debug * debug * debug * debug * debug * debug * debug * debug * Update go.mod * Update friend.go * debug * debug * debug * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * add pin friend test * I cannot solve todo in test.sh * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * update user command * Update go.mod * fix group notification * fix group notification * update openimsdk tools * update openim server remove duplicate code * update openim server remove duplicate code * update user command get * update user command get * update response of callback response error * update black ex * update join group ex * update user pb2map * update go sum * update go sum * update updateUserInfoEx * update updateUserInfoEx * update updateUserInfoEx add callback functions * fix dismiss group function * fix dismiss group function * fix dismiss group function * fix dismiss group function * update pin friend to update friend * fix go mod * fix err golangci-lint * fix UserPb2DBMap * update comments, update go.mod check for register username * update comments, update go.mod check for register username * update comments, update go.mod check for register username * update comments, update go.mod check for register username * fix callback * fix go.mod * fix debug * fix bugs * update notification * update notification * update notification * update notification * update notification * update notification * update notification * update notification * fix updateUserInfoEx * fix updateUserInfoEx * modify go.mod * fix updateUserInfoEx * fix updateUserInfoEx * fix updateUserInfoEx * update user command notification * update user command get all notification * update user command get all notification * fix type = 0 * fix type = 0 * fix type = 0 * fix type = 0 * fix type = 0 * fix type = 0 * fix typing cause callback * add ex to usercommand * add ex to usercommand * update updatefriends * fix updatefriend map * fix updatefriend FriendsInfoUpdateNotification * fix push online and offline user, but why typing trigger callback push? * fix push online and offline user, but why typing trigger callback push? * update user command record not found and user access check * update user command get all user access check * update go.mod * fix callback name and place * upadtae callback test * fix callback typing * fix callback typing * fix callback typing * fix callback typing * fix lint on processusercommand --------- Co-authored-by: Xinwei Xiong <3293172751@qq.com> --- deployments/templates/openim.yaml | 8 ++ internal/api/route.go | 1 + internal/api/user.go | 5 ++ internal/push/callback.go | 6 +- internal/push/push_to_client.go | 5 +- internal/rpc/friend/friend.go | 29 +++---- internal/rpc/group/callback.go | 8 +- internal/rpc/group/group.go | 2 +- internal/rpc/msg/callback.go | 8 +- internal/rpc/msg/send.go | 2 + internal/rpc/user/user.go | 108 +++++++++++++++++++++++-- pkg/callbackstruct/constant.go | 2 +- pkg/common/config/config.go | 2 +- pkg/common/db/cache/friend.go | 14 ++++ pkg/common/db/controller/friend.go | 30 ++----- pkg/common/db/controller/user.go | 17 ++-- pkg/common/db/mgo/friend.go | 54 +++---------- pkg/common/db/mgo/user.go | 80 ++++++++++++++++-- pkg/common/db/table/relation/friend.go | 8 +- pkg/common/db/table/relation/user.go | 5 +- pkg/rpcclient/notification/friend.go | 2 +- pkg/rpcclient/notification/user.go | 18 +++++ 22 files changed, 287 insertions(+), 127 deletions(-) diff --git a/deployments/templates/openim.yaml b/deployments/templates/openim.yaml index 6880e4c4e..4c84373a5 100644 --- a/deployments/templates/openim.yaml +++ b/deployments/templates/openim.yaml @@ -320,6 +320,14 @@ callback: enable: ${CALLBACK_ENABLE} timeout: ${CALLBACK_TIMEOUT} failedContinue: ${CALLBACK_FAILED_CONTINUE} + beforeUpdateUserInfoEx: + enable: ${CALLBACK_ENABLE} + timeout: ${CALLBACK_TIMEOUT} + failedContinue: ${CALLBACK_FAILED_CONTINUE} + afterUpdateUserInfoEx: + enable: ${CALLBACK_ENABLE} + timeout: ${CALLBACK_TIMEOUT} + failedContinue: ${CALLBACK_FAILED_CONTINUE} afterSendSingleMsg: enable: ${CALLBACK_ENABLE} timeout: ${CALLBACK_TIMEOUT} diff --git a/internal/api/route.go b/internal/api/route.go index 1c91f4dde..8729bc1b9 100644 --- a/internal/api/route.go +++ b/internal/api/route.go @@ -83,6 +83,7 @@ func NewGinRouter(discov discoveryregistry.SvcDiscoveryRegistry, rdb redis.Unive userRouterGroup.POST("/process_user_command_delete", ParseToken, u.ProcessUserCommandDelete) userRouterGroup.POST("/process_user_command_update", ParseToken, u.ProcessUserCommandUpdate) userRouterGroup.POST("/process_user_command_get", ParseToken, u.ProcessUserCommandGet) + userRouterGroup.POST("/process_user_command_get_all", ParseToken, u.ProcessUserCommandGetAll) userRouterGroup.POST("/add_notification_account", ParseToken, u.AddNotificationAccount) userRouterGroup.POST("/update_notification_account", ParseToken, u.UpdateNotificationAccountInfo) diff --git a/internal/api/user.go b/internal/api/user.go index 5f0e23631..03d22c354 100644 --- a/internal/api/user.go +++ b/internal/api/user.go @@ -221,6 +221,11 @@ func (u *UserApi) ProcessUserCommandGet(c *gin.Context) { a2r.Call(user.UserClient.ProcessUserCommandGet, u.Client, c) } +// ProcessUserCommandGet user general function get all +func (u *UserApi) ProcessUserCommandGetAll(c *gin.Context) { + a2r.Call(user.UserClient.ProcessUserCommandGetAll, u.Client, c) +} + func (u *UserApi) AddNotificationAccount(c *gin.Context) { a2r.Call(user.UserClient.AddNotificationAccount, u.Client, c) } diff --git a/internal/push/callback.go b/internal/push/callback.go index 2085493c5..99a58fb07 100644 --- a/internal/push/callback.go +++ b/internal/push/callback.go @@ -37,7 +37,7 @@ func callbackOfflinePush( msg *sdkws.MsgData, offlinePushUserIDs *[]string, ) error { - if !config.Config.Callback.CallbackOfflinePush.Enable { + if !config.Config.Callback.CallbackOfflinePush.Enable || msg.ContentType == constant.Typing { return nil } req := &callbackstruct.CallbackBeforePushReq{ @@ -73,7 +73,7 @@ func callbackOfflinePush( } func callbackOnlinePush(ctx context.Context, userIDs []string, msg *sdkws.MsgData) error { - if !config.Config.Callback.CallbackOnlinePush.Enable || utils.Contain(msg.SendID, userIDs...) { + if !config.Config.Callback.CallbackOnlinePush.Enable || utils.Contain(msg.SendID, userIDs...) || msg.ContentType == constant.Typing { return nil } req := callbackstruct.CallbackBeforePushReq{ @@ -107,7 +107,7 @@ func callbackBeforeSuperGroupOnlinePush( msg *sdkws.MsgData, pushToUserIDs *[]string, ) error { - if !config.Config.Callback.CallbackBeforeSuperGroupOnlinePush.Enable { + if !config.Config.Callback.CallbackBeforeSuperGroupOnlinePush.Enable || msg.ContentType == constant.Typing { return nil } req := callbackstruct.CallbackBeforeSuperGroupOnlinePushReq{ diff --git a/internal/push/push_to_client.go b/internal/push/push_to_client.go index 12b78ea2d..7cee7b99d 100644 --- a/internal/push/push_to_client.go +++ b/internal/push/push_to_client.go @@ -101,11 +101,9 @@ func (p *Pusher) DeleteMemberAndSetConversationSeq(ctx context.Context, groupID func (p *Pusher) Push2User(ctx context.Context, userIDs []string, msg *sdkws.MsgData) error { log.ZDebug(ctx, "Get msg from msg_transfer And push msg", "userIDs", userIDs, "msg", msg.String()) - // callback if err := callbackOnlinePush(ctx, userIDs, msg); err != nil { return err } - // push wsResults, err := p.GetConnsAndOnlinePush(ctx, msg, userIDs) if err != nil { @@ -120,7 +118,7 @@ func (p *Pusher) Push2User(ctx context.Context, userIDs []string, msg *sdkws.Msg } for _, v := range wsResults { - if msg.SendID != v.UserID && (!v.OnlinePush) { + if !v.OnlinePush && msg.SendID == v.UserID { if err = callbackOfflinePush(ctx, userIDs, msg, &[]string{}); err != nil { return err } @@ -130,6 +128,7 @@ func (p *Pusher) Push2User(ctx context.Context, userIDs []string, msg *sdkws.Msg return err } } + } return nil } diff --git a/internal/rpc/friend/friend.go b/internal/rpc/friend/friend.go index c53cb88f5..84702f548 100644 --- a/internal/rpc/friend/friend.go +++ b/internal/rpc/friend/friend.go @@ -452,22 +452,19 @@ func (s *friendServer) UpdateFriends( return nil, err } - for _, friendID := range req.FriendUserIDs { - if req.IsPinned != nil { - if err = s.friendDatabase.UpdateFriendPinStatus(ctx, req.OwnerUserID, friendID, req.IsPinned.Value); err != nil { - return nil, err - } - } - if req.Remark != nil { - if err = s.friendDatabase.UpdateFriendRemark(ctx, req.OwnerUserID, friendID, req.Remark.Value); err != nil { - return nil, err - } - } - if req.Ex != nil { - if err = s.friendDatabase.UpdateFriendEx(ctx, req.OwnerUserID, friendID, req.Ex.Value); err != nil { - return nil, err - } - } + val := make(map[string]any) + + if req.IsPinned != nil { + val["is_pinned"] = req.IsPinned.Value + } + if req.Remark != nil { + val["remark"] = req.Remark.Value + } + if req.Ex != nil { + val["ex"] = req.Ex.Value + } + if err = s.friendDatabase.UpdateFriends(ctx, req.OwnerUserID, req.FriendUserIDs, val); err != nil { + return nil, err } resp := &pbfriend.UpdateFriendsResp{} diff --git a/internal/rpc/group/callback.go b/internal/rpc/group/callback.go index 8779cb89b..d891f4d1e 100644 --- a/internal/rpc/group/callback.go +++ b/internal/rpc/group/callback.go @@ -279,20 +279,20 @@ func CallbackApplyJoinGroupBefore(ctx context.Context, req *callbackstruct.Callb return nil } -func CallbackTransferGroupOwnerAfter(ctx context.Context, req *pbgroup.TransferGroupOwnerReq) (err error) { - if !config.Config.Callback.CallbackTransferGroupOwnerAfter.Enable { +func CallbackAfterTransferGroupOwner(ctx context.Context, req *pbgroup.TransferGroupOwnerReq) (err error) { + if !config.Config.Callback.CallbackAfterTransferGroupOwner.Enable { return nil } cbReq := &callbackstruct.CallbackTransferGroupOwnerReq{ - CallbackCommand: callbackstruct.CallbackTransferGroupOwnerAfter, + CallbackCommand: callbackstruct.CallbackAfterTransferGroupOwner, GroupID: req.GroupID, OldOwnerUserID: req.OldOwnerUserID, NewOwnerUserID: req.NewOwnerUserID, } resp := &callbackstruct.CallbackTransferGroupOwnerResp{} - if err = http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackBeforeJoinGroup); err != nil { + if err = http.CallBackPostReturn(ctx, config.Config.Callback.CallbackUrl, cbReq, resp, config.Config.Callback.CallbackAfterTransferGroupOwner); err != nil { return err } return nil diff --git a/internal/rpc/group/group.go b/internal/rpc/group/group.go index b1ea0aa03..f9b73ad2b 100644 --- a/internal/rpc/group/group.go +++ b/internal/rpc/group/group.go @@ -1061,7 +1061,7 @@ func (s *groupServer) TransferGroupOwner(ctx context.Context, req *pbgroup.Trans return nil, err } - if err := CallbackTransferGroupOwnerAfter(ctx, req); err != nil { + if err := CallbackAfterTransferGroupOwner(ctx, req); err != nil { return nil, err } s.Notification.GroupOwnerTransferredNotification(ctx, req) diff --git a/internal/rpc/msg/callback.go b/internal/rpc/msg/callback.go index 5d192fb87..f98318bba 100644 --- a/internal/rpc/msg/callback.go +++ b/internal/rpc/msg/callback.go @@ -70,7 +70,7 @@ func GetContent(msg *sdkws.MsgData) string { } func callbackBeforeSendSingleMsg(ctx context.Context, msg *pbchat.SendMsgReq) error { - if !config.Config.Callback.CallbackBeforeSendSingleMsg.Enable { + if !config.Config.Callback.CallbackBeforeSendSingleMsg.Enable || msg.MsgData.ContentType == constant.Typing { return nil } req := &cbapi.CallbackBeforeSendSingleMsgReq{ @@ -85,7 +85,7 @@ func callbackBeforeSendSingleMsg(ctx context.Context, msg *pbchat.SendMsgReq) er } func callbackAfterSendSingleMsg(ctx context.Context, msg *pbchat.SendMsgReq) error { - if !config.Config.Callback.CallbackAfterSendSingleMsg.Enable { + if !config.Config.Callback.CallbackAfterSendSingleMsg.Enable || msg.MsgData.ContentType == constant.Typing { return nil } req := &cbapi.CallbackAfterSendSingleMsgReq{ @@ -100,7 +100,7 @@ func callbackAfterSendSingleMsg(ctx context.Context, msg *pbchat.SendMsgReq) err } func callbackBeforeSendGroupMsg(ctx context.Context, msg *pbchat.SendMsgReq) error { - if !config.Config.Callback.CallbackBeforeSendGroupMsg.Enable { + if !config.Config.Callback.CallbackBeforeSendGroupMsg.Enable || msg.MsgData.ContentType == constant.Typing { return nil } req := &cbapi.CallbackBeforeSendGroupMsgReq{ @@ -115,7 +115,7 @@ func callbackBeforeSendGroupMsg(ctx context.Context, msg *pbchat.SendMsgReq) err } func callbackAfterSendGroupMsg(ctx context.Context, msg *pbchat.SendMsgReq) error { - if !config.Config.Callback.CallbackAfterSendGroupMsg.Enable { + if !config.Config.Callback.CallbackAfterSendGroupMsg.Enable || msg.MsgData.ContentType == constant.Typing { return nil } req := &cbapi.CallbackAfterSendGroupMsgReq{ diff --git a/internal/rpc/msg/send.go b/internal/rpc/msg/send.go index dd08292bd..630b74a4a 100644 --- a/internal/rpc/msg/send.go +++ b/internal/rpc/msg/send.go @@ -65,6 +65,7 @@ func (m *msgServer) sendMsgSuperGroupChat( if err = callbackBeforeSendGroupMsg(ctx, req); err != nil { return nil, err } + if err := callbackMsgModify(ctx, req); err != nil { return nil, err } @@ -167,6 +168,7 @@ func (m *msgServer) sendMsgSingleChat(ctx context.Context, req *pbmsg.SendMsgReq if err = callbackBeforeSendSingleMsg(ctx, req); err != nil { return nil, err } + if err := callbackMsgModify(ctx, req); err != nil { return nil, err } diff --git a/internal/rpc/user/user.go b/internal/rpc/user/user.go index a1e2c75bc..21b419fa3 100644 --- a/internal/rpc/user/user.go +++ b/internal/rpc/user/user.go @@ -59,11 +59,6 @@ type userServer struct { RegisterCenter registry.SvcDiscoveryRegistry } -func (s *userServer) ProcessUserCommandGetAll(ctx context.Context, req *pbuser.ProcessUserCommandGetAllReq) (*pbuser.ProcessUserCommandGetAllResp, error) { - //TODO implement me - panic("implement me") -} - func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error { rdb, err := cache.NewRedis() if err != nil { @@ -385,28 +380,94 @@ func (s *userServer) GetSubscribeUsersStatus(ctx context.Context, // ProcessUserCommandAdd user general function add func (s *userServer) ProcessUserCommandAdd(ctx context.Context, req *pbuser.ProcessUserCommandAddReq) (*pbuser.ProcessUserCommandAddResp, error) { + err := authverify.CheckAccessV3(ctx, req.UserID) + if err != nil { + return nil, err + } + var value string + if req.Value != nil { + value = req.Value.Value + } + var ex string + if req.Ex != nil { + value = req.Ex.Value + } + // Assuming you have a method in s.UserDatabase to add a user command + err = s.UserDatabase.AddUserCommand(ctx, req.UserID, req.Type, req.Uuid, value, ex) + if err != nil { + return nil, err + } + tips := &sdkws.UserCommandAddTips{ + FromUserID: req.UserID, + ToUserID: req.UserID, + } + err = s.userNotificationSender.UserCommandAddNotification(ctx, tips) + if err != nil { + return nil, err + } return &pbuser.ProcessUserCommandAddResp{}, nil } // ProcessUserCommandDelete user general function delete func (s *userServer) ProcessUserCommandDelete(ctx context.Context, req *pbuser.ProcessUserCommandDeleteReq) (*pbuser.ProcessUserCommandDeleteResp, error) { - // Assuming you have a method in s.UserDatabase to delete a user command - err := s.UserDatabase.DeleteUserCommand(ctx, req.UserID, req.Type, req.Uuid) + err := authverify.CheckAccessV3(ctx, req.UserID) if err != nil { return nil, err } + err = s.UserDatabase.DeleteUserCommand(ctx, req.UserID, req.Type, req.Uuid) + if err != nil { + return nil, err + } + tips := &sdkws.UserCommandDeleteTips{ + FromUserID: req.UserID, + ToUserID: req.UserID, + } + err = s.userNotificationSender.UserCommandDeleteNotification(ctx, tips) + if err != nil { + return nil, err + } return &pbuser.ProcessUserCommandDeleteResp{}, nil } // ProcessUserCommandUpdate user general function update func (s *userServer) ProcessUserCommandUpdate(ctx context.Context, req *pbuser.ProcessUserCommandUpdateReq) (*pbuser.ProcessUserCommandUpdateResp, error) { + err := authverify.CheckAccessV3(ctx, req.UserID) + if err != nil { + return nil, err + } + val := make(map[string]any) + // Map fields from eax to val + if req.Value != nil { + val["value"] = req.Value.Value + } + if req.Ex != nil { + val["ex"] = req.Ex.Value + } + + // Assuming you have a method in s.UserDatabase to update a user command + err = s.UserDatabase.UpdateUserCommand(ctx, req.UserID, req.Type, req.Uuid, val) + if err != nil { + return nil, err + } + tips := &sdkws.UserCommandUpdateTips{ + FromUserID: req.UserID, + ToUserID: req.UserID, + } + err = s.userNotificationSender.UserCommandUpdateNotification(ctx, tips) + if err != nil { + return nil, err + } return &pbuser.ProcessUserCommandUpdateResp{}, nil } func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *pbuser.ProcessUserCommandGetReq) (*pbuser.ProcessUserCommandGetResp, error) { + err := authverify.CheckAccessV3(ctx, req.UserID) + if err != nil { + return nil, err + } // Fetch user commands from the database commands, err := s.UserDatabase.GetUserCommands(ctx, req.UserID, req.Type) if err != nil { @@ -419,14 +480,45 @@ func (s *userServer) ProcessUserCommandGet(ctx context.Context, req *pbuser.Proc for _, command := range commands { // No need to use index since command is already a pointer commandInfoSlice = append(commandInfoSlice, &pbuser.CommandInfoResp{ + Type: command.Type, + Uuid: command.Uuid, + Value: command.Value, + CreateTime: command.CreateTime, + Ex: command.Ex, + }) + } + + // Return the response with the slice + return &pbuser.ProcessUserCommandGetResp{CommandResp: commandInfoSlice}, nil +} + +func (s *userServer) ProcessUserCommandGetAll(ctx context.Context, req *pbuser.ProcessUserCommandGetAllReq) (*pbuser.ProcessUserCommandGetAllResp, error) { + err := authverify.CheckAccessV3(ctx, req.UserID) + if err != nil { + return nil, err + } + // Fetch user commands from the database + commands, err := s.UserDatabase.GetAllUserCommands(ctx, req.UserID) + if err != nil { + return nil, err + } + + // Initialize commandInfoSlice as an empty slice + commandInfoSlice := make([]*pbuser.AllCommandInfoResp, 0, len(commands)) + + for _, command := range commands { + // No need to use index since command is already a pointer + commandInfoSlice = append(commandInfoSlice, &pbuser.AllCommandInfoResp{ + Type: command.Type, Uuid: command.Uuid, Value: command.Value, CreateTime: command.CreateTime, + Ex: command.Ex, }) } // Return the response with the slice - return &pbuser.ProcessUserCommandGetResp{}, nil + return &pbuser.ProcessUserCommandGetAllResp{CommandResp: commandInfoSlice}, nil } func (s *userServer) AddNotificationAccount(ctx context.Context, req *pbuser.AddNotificationAccountReq) (*pbuser.AddNotificationAccountResp, error) { diff --git a/pkg/callbackstruct/constant.go b/pkg/callbackstruct/constant.go index cda98af16..f3bcf1383 100644 --- a/pkg/callbackstruct/constant.go +++ b/pkg/callbackstruct/constant.go @@ -41,7 +41,7 @@ const ( CallbackBeforeUpdateUserInfoExCommand = "callbackBeforeUpdateUserInfoExCommand" CallbackBeforeUserRegisterCommand = "callbackBeforeUserRegisterCommand" CallbackAfterUserRegisterCommand = "callbackAfterUserRegisterCommand" - CallbackTransferGroupOwnerAfter = "callbackTransferGroupOwnerAfter" + CallbackAfterTransferGroupOwner = "callbackAfterTransferGroupOwner" CallbackBeforeSetFriendRemark = "callbackBeforeSetFriendRemark" CallbackAfterSetFriendRemark = "callbackAfterSetFriendRemark" CallbackSingleMsgRead = "callbackSingleMsgRead" diff --git a/pkg/common/config/config.go b/pkg/common/config/config.go index 88e87e709..9696e9367 100644 --- a/pkg/common/config/config.go +++ b/pkg/common/config/config.go @@ -296,7 +296,7 @@ type configStruct struct { CallbackKillGroupMember CallBackConfig `yaml:"killGroupMember"` CallbackDismissGroup CallBackConfig `yaml:"dismissGroup"` CallbackBeforeJoinGroup CallBackConfig `yaml:"joinGroup"` - CallbackTransferGroupOwnerAfter CallBackConfig `yaml:"transferGroupOwner"` + CallbackAfterTransferGroupOwner CallBackConfig `yaml:"transferGroupOwner"` CallbackBeforeInviteUserToGroup CallBackConfig `yaml:"beforeInviteUserToGroup"` CallbackAfterJoinGroup CallBackConfig `yaml:"joinGroupAfter"` CallbackAfterSetGroupInfo CallBackConfig `yaml:"setGroupInfoAfter"` diff --git a/pkg/common/db/cache/friend.go b/pkg/common/db/cache/friend.go index 1708f7664..a2b60d48f 100644 --- a/pkg/common/db/cache/friend.go +++ b/pkg/common/db/cache/friend.go @@ -44,6 +44,8 @@ type FriendCache interface { GetFriend(ctx context.Context, ownerUserID, friendUserID string) (friend *relationtb.FriendModel, err error) // Delete friend when friend info changed DelFriend(ownerUserID, friendUserID string) FriendCache + // Delete friends when friends' info changed + DelFriends(ownerUserID string, friendUserIDs []string) FriendCache } // FriendCacheRedis is an implementation of the FriendCache interface using Redis. @@ -152,3 +154,15 @@ func (f *FriendCacheRedis) DelFriend(ownerUserID, friendUserID string) FriendCac return newFriendCache } + +// DelFriends deletes multiple friend infos from the cache. +func (f *FriendCacheRedis) DelFriends(ownerUserID string, friendUserIDs []string) FriendCache { + newFriendCache := f.NewCache() + + for _, friendUserID := range friendUserIDs { + key := f.getFriendKey(ownerUserID, friendUserID) + newFriendCache.AddKeys(key) // Assuming AddKeys marks the keys for deletion + } + + return newFriendCache +} diff --git a/pkg/common/db/controller/friend.go b/pkg/common/db/controller/friend.go index 924a179ba..3b98f5d7b 100644 --- a/pkg/common/db/controller/friend.go +++ b/pkg/common/db/controller/friend.go @@ -74,15 +74,8 @@ type FriendDatabase interface { // FindBothFriendRequests finds friend requests sent and received FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error) - // UpdateFriendPinStatus updates the pinned status of a friend - UpdateFriendPinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error) - - // UpdateFriendRemark updates the remark for a friend - UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error) - - // UpdateFriendEx updates the 'ex' field for a friend - UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error) - + // UpdateFriends updates fields for friends + UpdateFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, val map[string]any) (err error) } type friendDatabase struct { @@ -323,21 +316,12 @@ func (f *friendDatabase) FindFriendUserIDs(ctx context.Context, ownerUserID stri func (f *friendDatabase) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error) { return f.friendRequest.FindBothFriendRequests(ctx, fromUserID, toUserID) } -func (f *friendDatabase) UpdateFriendPinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error) { - if err := f.friend.UpdatePinStatus(ctx, ownerUserID, friendUserID, isPinned); err != nil { - return err +func (f *friendDatabase) UpdateFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, val map[string]any) (err error) { + if len(val) == 0 { + return nil } - return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx) -} -func (f *friendDatabase) UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error) { - if err := f.friend.UpdateFriendRemark(ctx, ownerUserID, friendUserID, remark); err != nil { + if err := f.friend.UpdateFriends(ctx, ownerUserID, friendUserIDs, val); err != nil { return err } - return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx) -} -func (f *friendDatabase) UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error) { - if err := f.friend.UpdateFriendEx(ctx, ownerUserID, friendUserID, ex); err != nil { - return err - } - return f.cache.DelFriend(ownerUserID, friendUserID).ExecDel(ctx) + return f.cache.DelFriends(ownerUserID, friendUserIDs).ExecDel(ctx) } diff --git a/pkg/common/db/controller/user.go b/pkg/common/db/controller/user.go index 445700e5e..cedae5c97 100644 --- a/pkg/common/db/controller/user.go +++ b/pkg/common/db/controller/user.go @@ -78,10 +78,11 @@ type UserDatabase interface { SetUserStatus(ctx context.Context, userID string, status, platformID int32) error //CRUD user command - AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error + AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string, ex string) error DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error - UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error + UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, val map[string]any) error GetUserCommands(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error) + GetAllUserCommands(ctx context.Context, userID string) ([]*user.AllCommandInfoResp, error) } type userDatabase struct { @@ -259,16 +260,20 @@ func (u *userDatabase) GetUserStatus(ctx context.Context, userIDs []string) ([]* func (u *userDatabase) SetUserStatus(ctx context.Context, userID string, status, platformID int32) error { return u.cache.SetUserStatus(ctx, userID, status, platformID) } -func (u *userDatabase) AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error { - return u.userDB.AddUserCommand(ctx, userID, Type, UUID, value) +func (u *userDatabase) AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string, ex string) error { + return u.userDB.AddUserCommand(ctx, userID, Type, UUID, value, ex) } func (u *userDatabase) DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error { return u.userDB.DeleteUserCommand(ctx, userID, Type, UUID) } -func (u *userDatabase) UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error { - return u.userDB.UpdateUserCommand(ctx, userID, Type, UUID, value) +func (u *userDatabase) UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, val map[string]any) error { + return u.userDB.UpdateUserCommand(ctx, userID, Type, UUID, val) } func (u *userDatabase) GetUserCommands(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error) { commands, err := u.userDB.GetUserCommand(ctx, userID, Type) return commands, err } +func (u *userDatabase) GetAllUserCommands(ctx context.Context, userID string) ([]*user.AllCommandInfoResp, error) { + commands, err := u.userDB.GetAllUserCommand(ctx, userID) + return commands, err +} diff --git a/pkg/common/db/mgo/friend.go b/pkg/common/db/mgo/friend.go index 72289181b..b4172d0fb 100644 --- a/pkg/common/db/mgo/friend.go +++ b/pkg/common/db/mgo/friend.go @@ -16,7 +16,6 @@ package mgo import ( "context" - "github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/mgoutil" "github.com/OpenIMSDK/tools/pagination" "go.mongodb.org/mongo-driver/mongo/options" @@ -144,49 +143,22 @@ func (f *FriendMgo) FindFriendUserIDs(ctx context.Context, ownerUserID string) ( return mgoutil.Find[string](ctx, f.coll, filter, options.Find().SetProjection(bson.M{"_id": 0, "friend_user_id": 1})) } -// UpdatePinStatus update friend's pin status -func (f *FriendMgo) UpdatePinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error) { - - filter := bson.M{"owner_user_id": ownerUserID, "friend_user_id": friendUserID} - // Create an update operation to set the "is_pinned" field to isPinned for all documents. - update := bson.M{"$set": bson.M{"is_pinned": isPinned}} - - // Perform the update operation for all documents in the collection. - _, err = f.coll.UpdateMany(ctx, filter, update) - - if err != nil { - return errs.Wrap(err, "update pin error") +func (f *FriendMgo) UpdateFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, val map[string]any) error { + // Ensure there are IDs to update + if len(friendUserIDs) == 0 { + return nil // Or return an error if you expect there to always be IDs } - return nil -} -func (f *FriendMgo) UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error) { - - filter := bson.M{"owner_user_id": ownerUserID, "friend_user_id": friendUserID} - // Create an update operation to set the "is_pinned" field to isPinned for all documents. - update := bson.M{"$set": bson.M{"remark": remark}} - - // Perform the update operation for all documents in the collection. - _, err = f.coll.UpdateMany(ctx, filter, update) - - if err != nil { - return errs.Wrap(err, "update remark error") + // Create a filter to match documents with the specified ownerUserID and any of the friendUserIDs + filter := bson.M{ + "owner_user_id": ownerUserID, + "friend_user_id": bson.M{"$in": friendUserIDs}, } - return nil -} -func (f *FriendMgo) UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error) { - - filter := bson.M{"owner_user_id": ownerUserID, "friend_user_id": friendUserID} - // Create an update operation to set the "is_pinned" field to isPinned for all documents. - update := bson.M{"$set": bson.M{"ex": ex}} - - // Perform the update operation for all documents in the collection. - _, err = f.coll.UpdateMany(ctx, filter, update) - - if err != nil { - return errs.Wrap(err, "update ex error") - } + // Create an update document + update := bson.M{"$set": val} - return nil + // Perform the update operation for all matching documents + _, err := mgoutil.UpdateMany(ctx, f.coll, filter, update) + return err } diff --git a/pkg/common/db/mgo/user.go b/pkg/common/db/mgo/user.go index 892a42003..b82966371 100644 --- a/pkg/common/db/mgo/user.go +++ b/pkg/common/db/mgo/user.go @@ -17,6 +17,7 @@ package mgo import ( "context" "github.com/OpenIMSDK/protocol/user" + "github.com/OpenIMSDK/tools/errs" "time" "github.com/OpenIMSDK/tools/mgoutil" @@ -100,7 +101,7 @@ func (u *UserMgo) CountTotal(ctx context.Context, before *time.Time) (count int6 return mgoutil.Count(ctx, u.coll, bson.M{"create_time": bson.M{"$lt": before}}) } -func (u *UserMgo) AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error { +func (u *UserMgo) AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string, ex string) error { collection := u.coll.Database().Collection("userCommands") // Create a new document instead of updating an existing one @@ -110,28 +111,48 @@ func (u *UserMgo) AddUserCommand(ctx context.Context, userID string, Type int32, "uuid": UUID, "createTime": time.Now().Unix(), // assuming you want the creation time in Unix timestamp "value": value, + "ex": ex, } _, err := collection.InsertOne(ctx, doc) return err } + func (u *UserMgo) DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error { collection := u.coll.Database().Collection("userCommands") filter := bson.M{"userID": userID, "type": Type, "uuid": UUID} - _, err := collection.DeleteOne(ctx, filter) + result, err := collection.DeleteOne(ctx, filter) + if result.DeletedCount == 0 { + // No records found to update + return errs.Wrap(errs.ErrRecordNotFound) + } return err } -func (u *UserMgo) UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error { +func (u *UserMgo) UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, val map[string]any) error { + if len(val) == 0 { + return nil + } + collection := u.coll.Database().Collection("userCommands") filter := bson.M{"userID": userID, "type": Type, "uuid": UUID} - update := bson.M{"$set": bson.M{"value": value}} + update := bson.M{"$set": val} - _, err := collection.UpdateOne(ctx, filter, update) - return err + result, err := collection.UpdateOne(ctx, filter, update) + if err != nil { + return err + } + + if result.MatchedCount == 0 { + // No records found to update + return errs.Wrap(errs.ErrRecordNotFound) + } + + return nil } + func (u *UserMgo) GetUserCommand(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error) { collection := u.coll.Database().Collection("userCommands") filter := bson.M{"userID": userID, "type": Type} @@ -147,19 +168,23 @@ func (u *UserMgo) GetUserCommand(ctx context.Context, userID string, Type int32) for cursor.Next(ctx) { var document struct { + Type int32 `bson:"type"` UUID string `bson:"uuid"` Value string `bson:"value"` CreateTime int64 `bson:"createTime"` + Ex string `bson:"ex"` } if err := cursor.Decode(&document); err != nil { return nil, err } - commandInfo := &user.CommandInfoResp{ // Change here: use a pointer to the struct + commandInfo := &user.CommandInfoResp{ + Type: document.Type, Uuid: document.UUID, Value: document.Value, CreateTime: document.CreateTime, + Ex: document.Ex, } commands = append(commands, commandInfo) @@ -171,7 +196,48 @@ func (u *UserMgo) GetUserCommand(ctx context.Context, userID string, Type int32) return commands, nil } +func (u *UserMgo) GetAllUserCommand(ctx context.Context, userID string) ([]*user.AllCommandInfoResp, error) { + collection := u.coll.Database().Collection("userCommands") + filter := bson.M{"userID": userID} + cursor, err := collection.Find(ctx, filter) + if err != nil { + return nil, err + } + defer cursor.Close(ctx) + + // Initialize commands as a slice of pointers + commands := []*user.AllCommandInfoResp{} + + for cursor.Next(ctx) { + var document struct { + Type int32 `bson:"type"` + UUID string `bson:"uuid"` + Value string `bson:"value"` + CreateTime int64 `bson:"createTime"` + Ex string `bson:"ex"` + } + + if err := cursor.Decode(&document); err != nil { + return nil, err + } + + commandInfo := &user.AllCommandInfoResp{ + Type: document.Type, + Uuid: document.UUID, + Value: document.Value, + CreateTime: document.CreateTime, + Ex: document.Ex, + } + + commands = append(commands, commandInfo) + } + + if err := cursor.Err(); err != nil { + return nil, err + } + return commands, nil +} func (u *UserMgo) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) { pipeline := bson.A{ bson.M{ diff --git a/pkg/common/db/table/relation/friend.go b/pkg/common/db/table/relation/friend.go index cc337701d..73f7454df 100644 --- a/pkg/common/db/table/relation/friend.go +++ b/pkg/common/db/table/relation/friend.go @@ -57,10 +57,6 @@ type FriendModelInterface interface { FindInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*FriendModel, err error) // FindFriendUserIDs retrieves a list of friend user IDs for a given owner. FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error) - // UpdatePinStatus update friend's pin status - UpdatePinStatus(ctx context.Context, ownerUserID string, friendUserID string, isPinned bool) (err error) - // UpdateFriendRemark update friend's remark - UpdateFriendRemark(ctx context.Context, ownerUserID string, friendUserID string, remark string) (err error) - // UpdateFriendEx update friend's ex - UpdateFriendEx(ctx context.Context, ownerUserID string, friendUserID string, ex string) (err error) + // UpdateFriends update friends' fields + UpdateFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, val map[string]any) (err error) } diff --git a/pkg/common/db/table/relation/user.go b/pkg/common/db/table/relation/user.go index 9844bdcee..a1b4269d1 100644 --- a/pkg/common/db/table/relation/user.go +++ b/pkg/common/db/table/relation/user.go @@ -65,8 +65,9 @@ type UserModelInterface interface { // 获取范围内用户增量 CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) //CRUD user command - AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error + AddUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string, ex string) error DeleteUserCommand(ctx context.Context, userID string, Type int32, UUID string) error - UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, value string) error + UpdateUserCommand(ctx context.Context, userID string, Type int32, UUID string, val map[string]any) error GetUserCommand(ctx context.Context, userID string, Type int32) ([]*user.CommandInfoResp, error) + GetAllUserCommand(ctx context.Context, userID string) ([]*user.AllCommandInfoResp, error) } diff --git a/pkg/rpcclient/notification/friend.go b/pkg/rpcclient/notification/friend.go index 00759b1b2..b98a1d38e 100644 --- a/pkg/rpcclient/notification/friend.go +++ b/pkg/rpcclient/notification/friend.go @@ -197,7 +197,7 @@ func (f *FriendNotificationSender) FriendRemarkSetNotification(ctx context.Conte return f.Notification(ctx, fromUserID, toUserID, constant.FriendRemarkSetNotification, &tips) } func (f *FriendNotificationSender) FriendsInfoUpdateNotification(ctx context.Context, toUserID string, friendIDs []string) error { - tips := sdkws.FriendsInfoUpdateTips{} + tips := sdkws.FriendsInfoUpdateTips{FromToUserID: &sdkws.FromToUserID{}} tips.FromToUserID.ToUserID = toUserID tips.FriendIDs = friendIDs return f.Notification(ctx, toUserID, toUserID, constant.FriendsInfoUpdateNotification, &tips) diff --git a/pkg/rpcclient/notification/user.go b/pkg/rpcclient/notification/user.go index 4feebf7b9..4347faece 100644 --- a/pkg/rpcclient/notification/user.go +++ b/pkg/rpcclient/notification/user.go @@ -103,3 +103,21 @@ func (u *UserNotificationSender) UserStatusChangeNotification( ) error { return u.Notification(ctx, tips.FromUserID, tips.ToUserID, constant.UserStatusChangeNotification, tips) } +func (u *UserNotificationSender) UserCommandUpdateNotification( + ctx context.Context, + tips *sdkws.UserCommandUpdateTips, +) error { + return u.Notification(ctx, tips.FromUserID, tips.ToUserID, constant.UserCommandUpdateNotification, tips) +} +func (u *UserNotificationSender) UserCommandAddNotification( + ctx context.Context, + tips *sdkws.UserCommandAddTips, +) error { + return u.Notification(ctx, tips.FromUserID, tips.ToUserID, constant.UserCommandAddNotification, tips) +} +func (u *UserNotificationSender) UserCommandDeleteNotification( + ctx context.Context, + tips *sdkws.UserCommandDeleteTips, +) error { + return u.Notification(ctx, tips.FromUserID, tips.ToUserID, constant.UserCommandDeleteNotification, tips) +}