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 8e61f30e9c)

# Conflicts:
#	go.mod
#	go.sum
This commit is contained in:
chao
2025-05-26 10:06:35 +08:00
committed by withchao
parent e254bbf1fc
commit bc326704f1
16 changed files with 389 additions and 126 deletions
+7 -5
View File
@@ -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(),
+14 -7
View File
@@ -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)
}
+13 -11
View File
@@ -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)
}
@@ -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)
}
+4 -2
View File
@@ -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)
}
@@ -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)
}
@@ -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)
}