pull/1427/head
withchao 2 years ago
parent 9e8791a4f4
commit 55fade28db

@ -16,12 +16,10 @@ package group
import ( import (
"context" "context"
"crypto/md5"
"encoding/binary"
"encoding/json"
"fmt" "fmt"
"github.com/OpenIMSDK/tools/tx" "github.com/OpenIMSDK/tools/tx"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo" "github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/grouphash"
"math/big" "math/big"
"math/rand" "math/rand"
"strconv" "strconv"
@ -91,7 +89,7 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
msgRpcClient := rpcclient.NewMessageRpcClient(client) msgRpcClient := rpcclient.NewMessageRpcClient(client)
conversationRpcClient := rpcclient.NewConversationRpcClient(client) conversationRpcClient := rpcclient.NewConversationRpcClient(client)
var gs groupServer var gs groupServer
database := controller.NewGroupDatabase(rdb, groupDB, groupMemberDB, groupRequestDB, tx.NewMongo(mongo.GetClient()), gs.groupMemberHashCode) database := controller.NewGroupDatabase(rdb, groupDB, groupMemberDB, groupRequestDB, tx.NewMongo(mongo.GetClient()), grouphash.NewGroupHashFromGroupServer(&gs))
gs.db = database gs.db = database
gs.User = userRpcClient gs.User = userRpcClient
gs.Notification = notification.NewGroupNotificationSender(database, &msgRpcClient, &userRpcClient, func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error) { gs.Notification = notification.NewGroupNotificationSender(database, &msgRpcClient, &userRpcClient, func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error) {
@ -427,14 +425,6 @@ func (s *groupServer) InviteUserToGroup(ctx context.Context, req *pbgroup.Invite
} }
func (s *groupServer) GetGroupAllMember(ctx context.Context, req *pbgroup.GetGroupAllMemberReq) (*pbgroup.GetGroupAllMemberResp, error) { func (s *groupServer) GetGroupAllMember(ctx context.Context, req *pbgroup.GetGroupAllMemberReq) (*pbgroup.GetGroupAllMemberResp, error) {
resp := &pbgroup.GetGroupAllMemberResp{}
group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil {
return nil, err
}
if group.Status == constant.GroupStatusDismissed {
return nil, errs.ErrData.Wrap("group dismissed")
}
members, err := s.db.FindGroupMemberAll(ctx, req.GroupID) members, err := s.db.FindGroupMemberAll(ctx, req.GroupID)
if err != nil { if err != nil {
return nil, err return nil, err
@ -442,6 +432,7 @@ func (s *groupServer) GetGroupAllMember(ctx context.Context, req *pbgroup.GetGro
if err := s.PopulateGroupMember(ctx, members...); err != nil { if err := s.PopulateGroupMember(ctx, members...); err != nil {
return nil, err return nil, err
} }
resp := &pbgroup.GetGroupAllMemberResp{}
resp.Members = utils.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo { resp.Members = utils.Slice(members, func(e *relationtb.GroupMemberModel) *sdkws.GroupMemberFullInfo {
return convert.Db2PbGroupMember(e) return convert.Db2PbGroupMember(e)
}) })
@ -1601,36 +1592,36 @@ func (s *groupServer) GetGroupUsersReqApplicationList(ctx context.Context, req *
return resp, nil return resp, nil
} }
func (s *groupServer) groupMemberHashCode(ctx context.Context, groupID string) (uint64, error) { //func (s *groupServer) groupMemberHashCode(ctx context.Context, groupID string) (uint64, error) {
userIDs, err := s.db.FindGroupMemberUserID(ctx, groupID) // userIDs, err := s.db.FindGroupMemberUserID(ctx, groupID)
if err != nil { // if err != nil {
return 0, err // return 0, err
} // }
var members []*sdkws.GroupMemberFullInfo // var members []*sdkws.GroupMemberFullInfo
if len(userIDs) > 0 { // if len(userIDs) > 0 {
resp, err := s.GetGroupMembersInfo(ctx, &pbgroup.GetGroupMembersInfoReq{GroupID: groupID, UserIDs: userIDs}) // resp, err := s.GetGroupMembersInfo(ctx, &pbgroup.GetGroupMembersInfoReq{GroupID: groupID, UserIDs: userIDs})
if err != nil { // if err != nil {
return 0, err // return 0, err
} // }
members = resp.Members // members = resp.Members
utils.Sort(userIDs, true) // utils.Sort(userIDs, true)
} // }
memberMap := utils.SliceToMap(members, func(e *sdkws.GroupMemberFullInfo) string { // memberMap := utils.SliceToMap(members, func(e *sdkws.GroupMemberFullInfo) string {
return e.UserID // return e.UserID
}) // })
res := make([]*sdkws.GroupMemberFullInfo, 0, len(members)) // res := make([]*sdkws.GroupMemberFullInfo, 0, len(members))
for _, userID := range userIDs { // for _, userID := range userIDs {
member, ok := memberMap[userID] // member, ok := memberMap[userID]
if !ok { // if !ok {
continue // continue
} // }
member.AppMangerLevel = 0 // member.AppMangerLevel = 0
res = append(res, member) // res = append(res, member)
} // }
data, err := json.Marshal(res) // data, err := json.Marshal(res)
if err != nil { // if err != nil {
return 0, err // return 0, err
} // }
sum := md5.Sum(data) // sum := md5.Sum(data)
return binary.BigEndian.Uint64(sum[:]), nil // return binary.BigEndian.Uint64(sum[:]), nil
} //}

@ -17,6 +17,7 @@ package tools
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo"
"math" "math"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
@ -77,24 +78,35 @@ func InitMsgTool() (*MsgTool, error) {
return nil, err return nil, err
} }
discov, err := kdisc.NewDiscoveryRegister(config.Config.Envs.Discovery) discov, err := kdisc.NewDiscoveryRegister(config.Config.Envs.Discovery)
/*
discov, err := zookeeper.NewClient(config.Config.Zookeeper.ZkAddr, config.Config.Zookeeper.Schema,
zookeeper.WithFreq(time.Hour), zookeeper.WithRoundRobin(), zookeeper.WithUserNameAndPassword(config.Config.Zookeeper.Username,
config.Config.Zookeeper.Password), zookeeper.WithTimeout(10), zookeeper.WithLogger(log.NewZkLogger()))*/
if err != nil { if err != nil {
return nil, err return nil, err
} }
discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials())) discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
userDB := relation.NewUserGorm(db) userDB, err := newmgo.NewUserMongo(mongo.GetDatabase())
if err != nil {
return nil, err
}
msgDatabase := controller.InitCommonMsgDatabase(rdb, mongo.GetDatabase()) msgDatabase := controller.InitCommonMsgDatabase(rdb, mongo.GetDatabase())
userMongoDB := unrelation.NewUserMongoDriver(mongo.GetDatabase()) userMongoDB := unrelation.NewUserMongoDriver(mongo.GetDatabase())
userDatabase := controller.NewUserDatabase( userDatabase := controller.NewUserDatabase(
userDB, userDB,
cache.NewUserCacheRedis(rdb, relation.NewUserGorm(db), cache.GetDefaultOpt()), cache.NewUserCacheRedis(rdb, userDB, cache.GetDefaultOpt()),
tx.NewMongo(mongo.GetClient()), tx.NewMongo(mongo.GetClient()),
userMongoDB, userMongoDB,
) )
groupDatabase := controller.InitGroupDatabase(db, rdb, mongo.GetDatabase(), nil) groupDB, err := newmgo.NewGroupMongo(mongo.GetDatabase())
if err != nil {
return nil, err
}
groupMemberDB, err := newmgo.NewGroupMember(mongo.GetDatabase())
if err != nil {
return nil, err
}
groupRequestDB, err := newmgo.NewGroupRequestMgo(mongo.GetDatabase())
if err != nil {
return nil, err
}
groupDatabase := controller.NewGroupDatabase(rdb, groupDB, groupMemberDB, groupRequestDB, tx.NewMongo(mongo.GetClient()), nil)
conversationDatabase := controller.NewConversationDatabase( conversationDatabase := controller.NewConversationDatabase(
relation.NewConversationGorm(db), relation.NewConversationGorm(db),
cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), relation.NewConversationGorm(db)), cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), relation.NewConversationGorm(db)),

@ -44,6 +44,10 @@ const (
groupRoleLevelMemberIDsKey = "GROUP_ROLE_LEVEL_MEMBER_IDS:" groupRoleLevelMemberIDsKey = "GROUP_ROLE_LEVEL_MEMBER_IDS:"
) )
type GroupHash interface {
GetGroupHash(ctx context.Context, groupID string) (uint64, error)
}
type GroupCache interface { type GroupCache interface {
metaCache metaCache
NewCache() GroupCache NewCache() GroupCache
@ -87,7 +91,7 @@ type GroupCacheRedis struct {
groupRequestDB relationtb.GroupRequestModelInterface groupRequestDB relationtb.GroupRequestModelInterface
expireTime time.Duration expireTime time.Duration
rcClient *rockscache.Client rcClient *rockscache.Client
hashCode func(ctx context.Context, groupID string) (uint64, error) groupHash GroupHash
} }
func NewGroupCacheRedis( func NewGroupCacheRedis(
@ -95,7 +99,7 @@ func NewGroupCacheRedis(
groupDB relationtb.GroupModelInterface, groupDB relationtb.GroupModelInterface,
groupMemberDB relationtb.GroupMemberModelInterface, groupMemberDB relationtb.GroupMemberModelInterface,
groupRequestDB relationtb.GroupRequestModelInterface, groupRequestDB relationtb.GroupRequestModelInterface,
hashCode func(ctx context.Context, groupID string) (uint64, error), hashCode GroupHash,
opts rockscache.Options, opts rockscache.Options,
) GroupCache { ) GroupCache {
rcClient := rockscache.NewClient(rdb, opts) rcClient := rockscache.NewClient(rdb, opts)
@ -103,7 +107,7 @@ func NewGroupCacheRedis(
return &GroupCacheRedis{ return &GroupCacheRedis{
rcClient: rcClient, expireTime: groupExpireTime, rcClient: rcClient, expireTime: groupExpireTime,
groupDB: groupDB, groupMemberDB: groupMemberDB, groupRequestDB: groupRequestDB, groupDB: groupDB, groupMemberDB: groupMemberDB, groupRequestDB: groupRequestDB,
hashCode: hashCode, groupHash: hashCode,
metaCache: NewMetaCacheRedis(rcClient), metaCache: NewMetaCacheRedis(rcClient),
} }
} }
@ -169,7 +173,6 @@ func (g *GroupCacheRedis) GetGroupMemberIndex(groupMember *relationtb.GroupMembe
return 0, errIndex return 0, errIndex
} }
// groupInfo.
func (g *GroupCacheRedis) GetGroupsInfo(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error) { func (g *GroupCacheRedis) GetGroupsInfo(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error) {
return batchGetCache2(ctx, g.rcClient, g.expireTime, groupIDs, func(groupID string) string { return batchGetCache2(ctx, g.rcClient, g.expireTime, groupIDs, func(groupID string) string {
return g.getGroupInfoKey(groupID) return g.getGroupInfoKey(groupID)
@ -220,14 +223,19 @@ func (g *GroupCacheRedis) DelGroupAllRoleLevel(groupID string) GroupCache {
return g.DelGroupRoleLevel(groupID, []int32{constant.GroupOwner, constant.GroupAdmin, constant.GroupOrdinaryUsers}) return g.DelGroupRoleLevel(groupID, []int32{constant.GroupOwner, constant.GroupAdmin, constant.GroupOrdinaryUsers})
} }
// groupMembersHash.
func (g *GroupCacheRedis) GetGroupMembersHash(ctx context.Context, groupID string) (hashCode uint64, err error) { func (g *GroupCacheRedis) GetGroupMembersHash(ctx context.Context, groupID string) (hashCode uint64, err error) {
if g.groupHash == nil {
return 0, errs.ErrInternalServer.Wrap("group hash is nil")
}
return getCache(ctx, g.rcClient, g.getGroupMembersHashKey(groupID), g.expireTime, func(ctx context.Context) (uint64, error) { return getCache(ctx, g.rcClient, g.getGroupMembersHashKey(groupID), g.expireTime, func(ctx context.Context) (uint64, error) {
return g.hashCode(ctx, groupID) return g.groupHash.GetGroupHash(ctx, groupID)
}) })
} }
func (g *GroupCacheRedis) GetGroupMemberHashMap(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error) { func (g *GroupCacheRedis) GetGroupMemberHashMap(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error) {
if g.groupHash == nil {
return nil, errs.ErrInternalServer.Wrap("group hash is nil")
}
res := make(map[string]*relationtb.GroupSimpleUserID) res := make(map[string]*relationtb.GroupSimpleUserID)
for _, groupID := range groupIDs { for _, groupID := range groupIDs {
hash, err := g.GetGroupMembersHash(ctx, groupID) hash, err := g.GetGroupMembersHash(ctx, groupID)

@ -73,7 +73,7 @@ type GroupDatabase interface {
DeleteGroupMemberHash(ctx context.Context, groupIDs []string) error DeleteGroupMemberHash(ctx context.Context, groupIDs []string) error
} }
func NewGroupDatabase(rdb redis.UniversalClient, groupDB relationtb.GroupModelInterface, groupMemberDB relationtb.GroupMemberModelInterface, groupRequestDB relationtb.GroupRequestModelInterface, ctxTx tx.CtxTx, hashCode func(ctx context.Context, groupID string) (uint64, error)) GroupDatabase { func NewGroupDatabase(rdb redis.UniversalClient, groupDB relationtb.GroupModelInterface, groupMemberDB relationtb.GroupMemberModelInterface, groupRequestDB relationtb.GroupRequestModelInterface, ctxTx tx.CtxTx, groupHash cache.GroupHash) GroupDatabase {
rcOptions := rockscache.NewDefaultOptions() rcOptions := rockscache.NewDefaultOptions()
rcOptions.StrongConsistency = true rcOptions.StrongConsistency = true
rcOptions.RandomExpireAdjustment = 0.2 rcOptions.RandomExpireAdjustment = 0.2
@ -82,7 +82,7 @@ func NewGroupDatabase(rdb redis.UniversalClient, groupDB relationtb.GroupModelIn
groupMemberDB: groupMemberDB, groupMemberDB: groupMemberDB,
groupRequestDB: groupRequestDB, groupRequestDB: groupRequestDB,
ctxTx: ctxTx, ctxTx: ctxTx,
cache: cache.NewGroupCacheRedis(rdb, groupDB, groupMemberDB, groupRequestDB, hashCode, rcOptions), cache: cache.NewGroupCacheRedis(rdb, groupDB, groupMemberDB, groupRequestDB, groupHash, rcOptions),
} }
} }

@ -14,184 +14,185 @@
package relation package relation
import ( //
"context" //import (
// "context"
"gorm.io/gorm" //
// "gorm.io/gorm"
"github.com/OpenIMSDK/protocol/constant" //
"github.com/OpenIMSDK/tools/ormutil" // "github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/utils" // "github.com/OpenIMSDK/tools/ormutil"
// "github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" //
) // "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
//)
var _ relation.GroupMemberModelInterface = (*GroupMemberGorm)(nil) //
//var _ relation.GroupMemberModelInterface = (*GroupMemberGorm)(nil)
type GroupMemberGorm struct { //
*MetaDB //type GroupMemberGorm struct {
} // *MetaDB
//}
func NewGroupMemberDB(db *gorm.DB) relation.GroupMemberModelInterface { //
return &GroupMemberGorm{NewMetaDB(db, &relation.GroupMemberModel{})} //func NewGroupMemberDB(db *gorm.DB) relation.GroupMemberModelInterface {
} // return &GroupMemberGorm{NewMetaDB(db, &relation.GroupMemberModel{})}
//}
func (g *GroupMemberGorm) NewTx(tx any) relation.GroupMemberModelInterface { //
return &GroupMemberGorm{NewMetaDB(tx.(*gorm.DB), &relation.GroupMemberModel{})} //func (g *GroupMemberGorm) NewTx(tx any) relation.GroupMemberModelInterface {
} // return &GroupMemberGorm{NewMetaDB(tx.(*gorm.DB), &relation.GroupMemberModel{})}
//}
func (g *GroupMemberGorm) Create(ctx context.Context, groupMemberList []*relation.GroupMemberModel) (err error) { //
return utils.Wrap(g.db(ctx).Create(&groupMemberList).Error, "") //func (g *GroupMemberGorm) Create(ctx context.Context, groupMemberList []*relation.GroupMemberModel) (err error) {
} // return utils.Wrap(g.db(ctx).Create(&groupMemberList).Error, "")
//}
func (g *GroupMemberGorm) Delete(ctx context.Context, groupID string, userIDs []string) (err error) { //
return utils.Wrap( //func (g *GroupMemberGorm) Delete(ctx context.Context, groupID string, userIDs []string) (err error) {
g.db(ctx).Where("group_id = ? and user_id in (?)", groupID, userIDs).Delete(&relation.GroupMemberModel{}).Error, // return utils.Wrap(
"", // g.db(ctx).Where("group_id = ? and user_id in (?)", groupID, userIDs).Delete(&relation.GroupMemberModel{}).Error,
) // "",
} // )
//}
func (g *GroupMemberGorm) DeleteGroup(ctx context.Context, groupIDs []string) (err error) { //
return utils.Wrap(g.db(ctx).Where("group_id in (?)", groupIDs).Delete(&relation.GroupMemberModel{}).Error, "") //func (g *GroupMemberGorm) DeleteGroup(ctx context.Context, groupIDs []string) (err error) {
} // return utils.Wrap(g.db(ctx).Where("group_id in (?)", groupIDs).Delete(&relation.GroupMemberModel{}).Error, "")
//}
func (g *GroupMemberGorm) Update(ctx context.Context, groupID string, userID string, data map[string]any) (err error) { //
return utils.Wrap(g.db(ctx).Where("group_id = ? and user_id = ?", groupID, userID).Updates(data).Error, "") //func (g *GroupMemberGorm) Update(ctx context.Context, groupID string, userID string, data map[string]any) (err error) {
} // return utils.Wrap(g.db(ctx).Where("group_id = ? and user_id = ?", groupID, userID).Updates(data).Error, "")
//}
func (g *GroupMemberGorm) UpdateRoleLevel( //
ctx context.Context, //func (g *GroupMemberGorm) UpdateRoleLevel(
groupID string, // ctx context.Context,
userID string, // groupID string,
roleLevel int32, // userID string,
) (rowsAffected int64, err error) { // roleLevel int32,
db := g.db(ctx).Where("group_id = ? and user_id = ?", groupID, userID).Updates(map[string]any{ //) (rowsAffected int64, err error) {
"role_level": roleLevel, // db := g.db(ctx).Where("group_id = ? and user_id = ?", groupID, userID).Updates(map[string]any{
}) // "role_level": roleLevel,
return db.RowsAffected, utils.Wrap(db.Error, "") // })
} // return db.RowsAffected, utils.Wrap(db.Error, "")
//}
func (g *GroupMemberGorm) Find( //
ctx context.Context, //func (g *GroupMemberGorm) Find(
groupIDs []string, // ctx context.Context,
userIDs []string, // groupIDs []string,
roleLevels []int32, // userIDs []string,
) (groupMembers []*relation.GroupMemberModel, err error) { // roleLevels []int32,
db := g.db(ctx) //) (groupMembers []*relation.GroupMemberModel, err error) {
if len(groupIDs) > 0 { // db := g.db(ctx)
db = db.Where("group_id in (?)", groupIDs) // if len(groupIDs) > 0 {
} // db = db.Where("group_id in (?)", groupIDs)
if len(userIDs) > 0 { // }
db = db.Where("user_id in (?)", userIDs) // if len(userIDs) > 0 {
} // db = db.Where("user_id in (?)", userIDs)
if len(roleLevels) > 0 { // }
db = db.Where("role_level in (?)", roleLevels) // if len(roleLevels) > 0 {
} // db = db.Where("role_level in (?)", roleLevels)
return groupMembers, utils.Wrap(db.Find(&groupMembers).Error, "") // }
} // return groupMembers, utils.Wrap(db.Find(&groupMembers).Error, "")
//}
func (g *GroupMemberGorm) Take( //
ctx context.Context, //func (g *GroupMemberGorm) Take(
groupID string, // ctx context.Context,
userID string, // groupID string,
) (groupMember *relation.GroupMemberModel, err error) { // userID string,
groupMember = &relation.GroupMemberModel{} //) (groupMember *relation.GroupMemberModel, err error) {
return groupMember, utils.Wrap( // groupMember = &relation.GroupMemberModel{}
g.db(ctx).Where("group_id = ? and user_id = ?", groupID, userID).Take(groupMember).Error, // return groupMember, utils.Wrap(
"", // g.db(ctx).Where("group_id = ? and user_id = ?", groupID, userID).Take(groupMember).Error,
) // "",
} // )
//}
func (g *GroupMemberGorm) TakeOwner( //
ctx context.Context, //func (g *GroupMemberGorm) TakeOwner(
groupID string, // ctx context.Context,
) (groupMember *relation.GroupMemberModel, err error) { // groupID string,
groupMember = &relation.GroupMemberModel{} //) (groupMember *relation.GroupMemberModel, err error) {
return groupMember, utils.Wrap( // groupMember = &relation.GroupMemberModel{}
g.db(ctx).Where("group_id = ? and role_level = ?", groupID, constant.GroupOwner).Take(groupMember).Error, // return groupMember, utils.Wrap(
"", // g.db(ctx).Where("group_id = ? and role_level = ?", groupID, constant.GroupOwner).Take(groupMember).Error,
) // "",
} // )
//}
func (g *GroupMemberGorm) SearchMember( //
ctx context.Context, //func (g *GroupMemberGorm) SearchMember(
keyword string, // ctx context.Context,
groupIDs []string, // keyword string,
userIDs []string, // groupIDs []string,
roleLevels []int32, // userIDs []string,
pageNumber, showNumber int32, // roleLevels []int32,
) (total uint32, groupList []*relation.GroupMemberModel, err error) { // pageNumber, showNumber int32,
db := g.db(ctx) //) (total uint32, groupList []*relation.GroupMemberModel, err error) {
ormutil.GormIn(&db, "group_id", groupIDs) // db := g.db(ctx)
ormutil.GormIn(&db, "user_id", userIDs) // ormutil.GormIn(&db, "group_id", groupIDs)
ormutil.GormIn(&db, "role_level", roleLevels) // ormutil.GormIn(&db, "user_id", userIDs)
return ormutil.GormSearch[relation.GroupMemberModel](db, []string{"nickname"}, keyword, pageNumber, showNumber) // ormutil.GormIn(&db, "role_level", roleLevels)
} // return ormutil.GormSearch[relation.GroupMemberModel](db, []string{"nickname"}, keyword, pageNumber, showNumber)
//}
func (g *GroupMemberGorm) MapGroupMemberNum( //
ctx context.Context, //func (g *GroupMemberGorm) MapGroupMemberNum(
groupIDs []string, // ctx context.Context,
) (count map[string]uint32, err error) { // groupIDs []string,
return ormutil.MapCount(g.db(ctx).Where("group_id in (?)", groupIDs), "group_id") //) (count map[string]uint32, err error) {
} // return ormutil.MapCount(g.db(ctx).Where("group_id in (?)", groupIDs), "group_id")
//}
func (g *GroupMemberGorm) FindJoinUserID( //
ctx context.Context, //func (g *GroupMemberGorm) FindJoinUserID(
groupIDs []string, // ctx context.Context,
) (groupUsers map[string][]string, err error) { // groupIDs []string,
var groupMembers []*relation.GroupMemberModel //) (groupUsers map[string][]string, err error) {
if err := g.db(ctx).Select("group_id, user_id").Where("group_id in (?)", groupIDs).Find(&groupMembers).Error; err != nil { // var groupMembers []*relation.GroupMemberModel
return nil, utils.Wrap(err, "") // if err := g.db(ctx).Select("group_id, user_id").Where("group_id in (?)", groupIDs).Find(&groupMembers).Error; err != nil {
} // return nil, utils.Wrap(err, "")
groupUsers = make(map[string][]string) // }
for _, item := range groupMembers { // groupUsers = make(map[string][]string)
v, ok := groupUsers[item.GroupID] // for _, item := range groupMembers {
if !ok { // v, ok := groupUsers[item.GroupID]
groupUsers[item.GroupID] = []string{item.UserID} // if !ok {
} else { // groupUsers[item.GroupID] = []string{item.UserID}
groupUsers[item.GroupID] = append(v, item.UserID) // } else {
} // groupUsers[item.GroupID] = append(v, item.UserID)
} // }
return groupUsers, nil // }
} // return groupUsers, nil
//}
func (g *GroupMemberGorm) FindMemberUserID(ctx context.Context, groupID string) (userIDs []string, err error) { //
return userIDs, utils.Wrap(g.db(ctx).Where("group_id = ?", groupID).Pluck("user_id", &userIDs).Error, "") //func (g *GroupMemberGorm) FindMemberUserID(ctx context.Context, groupID string) (userIDs []string, err error) {
} // return userIDs, utils.Wrap(g.db(ctx).Where("group_id = ?", groupID).Pluck("user_id", &userIDs).Error, "")
//}
func (g *GroupMemberGorm) FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) { //
return groupIDs, utils.Wrap(g.db(ctx).Where("user_id = ?", userID).Pluck("group_id", &groupIDs).Error, "") //func (g *GroupMemberGorm) FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
} // return groupIDs, utils.Wrap(g.db(ctx).Where("user_id = ?", userID).Pluck("group_id", &groupIDs).Error, "")
//}
func (g *GroupMemberGorm) TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error) { //
return count, utils.Wrap(g.db(ctx).Where("group_id = ?", groupID).Count(&count).Error, "") //func (g *GroupMemberGorm) TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error) {
} // return count, utils.Wrap(g.db(ctx).Where("group_id = ?", groupID).Count(&count).Error, "")
//}
func (g *GroupMemberGorm) FindUsersJoinedGroupID(ctx context.Context, userIDs []string) (map[string][]string, error) { //
var groupMembers []*relation.GroupMemberModel //func (g *GroupMemberGorm) FindUsersJoinedGroupID(ctx context.Context, userIDs []string) (map[string][]string, error) {
err := g.db(ctx).Select("group_id, user_id").Where("user_id IN (?)", userIDs).Find(&groupMembers).Error // var groupMembers []*relation.GroupMemberModel
if err != nil { // err := g.db(ctx).Select("group_id, user_id").Where("user_id IN (?)", userIDs).Find(&groupMembers).Error
return nil, err // if err != nil {
} // return nil, err
result := make(map[string][]string) // }
for _, groupMember := range groupMembers { // result := make(map[string][]string)
v, ok := result[groupMember.UserID] // for _, groupMember := range groupMembers {
if !ok { // v, ok := result[groupMember.UserID]
result[groupMember.UserID] = []string{groupMember.GroupID} // if !ok {
} else { // result[groupMember.UserID] = []string{groupMember.GroupID}
result[groupMember.UserID] = append(v, groupMember.GroupID) // } else {
} // result[groupMember.UserID] = append(v, groupMember.GroupID)
} // }
return result, nil // }
} // return result, nil
//}
func (g *GroupMemberGorm) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) { //
return groupIDs, utils.Wrap( //func (g *GroupMemberGorm) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
g.db(ctx). // return groupIDs, utils.Wrap(
Model(&relation.GroupMemberModel{}). // g.db(ctx).
Where("user_id = ? and (role_level = ? or role_level = ?)", userID, constant.GroupOwner, constant.GroupAdmin). // Model(&relation.GroupMemberModel{}).
Pluck("group_id", &groupIDs). // Where("user_id = ? and (role_level = ? or role_level = ?)", userID, constant.GroupOwner, constant.GroupAdmin).
Error, // Pluck("group_id", &groupIDs).
"", // Error,
) // "",
} // )
//}

@ -14,124 +14,125 @@
package relation package relation
import ( //
"context" //import (
"time" // "context"
// "time"
"github.com/OpenIMSDK/tools/errs" //
// "github.com/OpenIMSDK/tools/errs"
"gorm.io/gorm" //
// "gorm.io/gorm"
"github.com/OpenIMSDK/tools/utils" //
// "github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" //
) // "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
//)
type UserGorm struct { //
*MetaDB //type UserGorm struct {
} // *MetaDB
//}
func NewUserGorm(db *gorm.DB) relation.UserModelInterface { //
//return &UserGorm{NewMetaDB(db, &relation.UserModel{})} //func NewUserGorm(db *gorm.DB) relation.UserModelInterface {
return nil // //return &UserGorm{NewMetaDB(db, &relation.UserModel{})}
} // return nil
//}
// 插入多条. //
func (u *UserGorm) Create(ctx context.Context, users []*relation.UserModel) (err error) { //// 插入多条.
return utils.Wrap(u.db(ctx).Create(&users).Error, "") //func (u *UserGorm) Create(ctx context.Context, users []*relation.UserModel) (err error) {
} // return utils.Wrap(u.db(ctx).Create(&users).Error, "")
//}
// 更新用户信息 零值. //
func (u *UserGorm) UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error) { //// 更新用户信息 零值.
return utils.Wrap(u.db(ctx).Model(&relation.UserModel{}).Where("user_id = ?", userID).Updates(args).Error, "") //func (u *UserGorm) UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error) {
} // return utils.Wrap(u.db(ctx).Model(&relation.UserModel{}).Where("user_id = ?", userID).Updates(args).Error, "")
//}
// 更新多个用户信息 非零值. //
func (u *UserGorm) Update(ctx context.Context, user *relation.UserModel) (err error) { //// 更新多个用户信息 非零值.
return utils.Wrap(u.db(ctx).Model(user).Updates(user).Error, "") //func (u *UserGorm) Update(ctx context.Context, user *relation.UserModel) (err error) {
} // return utils.Wrap(u.db(ctx).Model(user).Updates(user).Error, "")
//}
// 获取指定用户信息 不存在,也不返回错误. //
func (u *UserGorm) Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) { //// 获取指定用户信息 不存在,也不返回错误.
err = utils.Wrap(u.db(ctx).Where("user_id in (?)", userIDs).Find(&users).Error, "") //func (u *UserGorm) Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) {
return users, err // err = utils.Wrap(u.db(ctx).Where("user_id in (?)", userIDs).Find(&users).Error, "")
} // return users, err
//}
// 获取某个用户信息 不存在,则返回错误. //
func (u *UserGorm) Take(ctx context.Context, userID string) (user *relation.UserModel, err error) { //// 获取某个用户信息 不存在,则返回错误.
user = &relation.UserModel{} //func (u *UserGorm) Take(ctx context.Context, userID string) (user *relation.UserModel, err error) {
err = utils.Wrap(u.db(ctx).Where("user_id = ?", userID).Take(&user).Error, "") // user = &relation.UserModel{}
return user, err // err = utils.Wrap(u.db(ctx).Where("user_id = ?", userID).Take(&user).Error, "")
} // return user, err
//}
// 获取用户信息 不存在,不返回错误. //
func (u *UserGorm) Page( //// 获取用户信息 不存在,不返回错误.
ctx context.Context, //func (u *UserGorm) Page(
pageNumber, showNumber int32, // ctx context.Context,
) (users []*relation.UserModel, count int64, err error) { // pageNumber, showNumber int32,
err = utils.Wrap(u.db(ctx).Count(&count).Error, "") //) (users []*relation.UserModel, count int64, err error) {
if err != nil { // err = utils.Wrap(u.db(ctx).Count(&count).Error, "")
return // if err != nil {
} // return
err = utils.Wrap( // }
u.db(ctx). // err = utils.Wrap(
Limit(int(showNumber)). // u.db(ctx).
Offset(int((pageNumber-1)*showNumber)). // Limit(int(showNumber)).
Find(&users). // Offset(int((pageNumber-1)*showNumber)).
Order("create_time DESC"). // Find(&users).
Error, // Order("create_time DESC").
"", // Error,
) // "",
return // )
} // return
//}
// 获取所有用户ID. //
func (u *UserGorm) GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error) { //// 获取所有用户ID.
if pageNumber == 0 || showNumber == 0 { //func (u *UserGorm) GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error) {
return userIDs, errs.Wrap(u.db(ctx).Pluck("user_id", &userIDs).Error) // if pageNumber == 0 || showNumber == 0 {
} else { // return userIDs, errs.Wrap(u.db(ctx).Pluck("user_id", &userIDs).Error)
return userIDs, errs.Wrap(u.db(ctx).Limit(int(showNumber)).Offset(int((pageNumber-1)*showNumber)).Pluck("user_id", &userIDs).Error) // } else {
} // return userIDs, errs.Wrap(u.db(ctx).Limit(int(showNumber)).Offset(int((pageNumber-1)*showNumber)).Pluck("user_id", &userIDs).Error)
} // }
//}
func (u *UserGorm) GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error) { //
err = u.db(ctx).Model(&relation.UserModel{}).Where("user_id = ?", userID).Pluck("global_recv_msg_opt", &opt).Error //func (u *UserGorm) GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error) {
return opt, err // err = u.db(ctx).Model(&relation.UserModel{}).Where("user_id = ?", userID).Pluck("global_recv_msg_opt", &opt).Error
} // return opt, err
//}
func (u *UserGorm) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) { //
db := u.db(ctx).Model(&relation.UserModel{}) //func (u *UserGorm) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
if before != nil { // db := u.db(ctx).Model(&relation.UserModel{})
db = db.Where("create_time < ?", before) // if before != nil {
} // db = db.Where("create_time < ?", before)
if err := db.Count(&count).Error; err != nil { // }
return 0, err // if err := db.Count(&count).Error; err != nil {
} // return 0, err
return count, nil // }
} // return count, nil
//}
func (u *UserGorm) CountRangeEverydayTotal( //
ctx context.Context, //func (u *UserGorm) CountRangeEverydayTotal(
start time.Time, // ctx context.Context,
end time.Time, // start time.Time,
) (map[string]int64, error) { // end time.Time,
var res []struct { //) (map[string]int64, error) {
Date time.Time `gorm:"column:date"` // var res []struct {
Count int64 `gorm:"column:count"` // Date time.Time `gorm:"column:date"`
} // Count int64 `gorm:"column:count"`
err := u.db(ctx). // }
Model(&relation.UserModel{}). // err := u.db(ctx).
Select("DATE(create_time) AS date, count(1) AS count"). // Model(&relation.UserModel{}).
Where("create_time >= ? and create_time < ?", start, end). // Select("DATE(create_time) AS date, count(1) AS count").
Group("date"). // Where("create_time >= ? and create_time < ?", start, end).
Find(&res). // Group("date").
Error // Find(&res).
if err != nil { // Error
return nil, errs.Wrap(err) // if err != nil {
} // return nil, errs.Wrap(err)
v := make(map[string]int64) // }
for _, r := range res { // v := make(map[string]int64)
v[r.Date.Format("2006-01-02")] = r.Count // for _, r := range res {
} // v[r.Date.Format("2006-01-02")] = r.Count
return v, nil // }
} // return v, nil
//}

@ -99,16 +99,6 @@ func (m *Mongo) CreateMsgIndex() error {
return m.createMongoIndex(unrelation.Msg, true, "doc_id") return m.createMongoIndex(unrelation.Msg, true, "doc_id")
} }
func (m *Mongo) CreateSuperGroupIndex() error {
if err := m.createMongoIndex(unrelation.CSuperGroup, true, "group_id"); err != nil {
return err
}
if err := m.createMongoIndex(unrelation.CUserToSuperGroup, true, "user_id"); err != nil {
return err
}
return nil
}
func (m *Mongo) createMongoIndex(collection string, isUnique bool, keys ...string) error { func (m *Mongo) createMongoIndex(collection string, isUnique bool, keys ...string) error {
db := m.db.Database(config.Config.Mongo.Database).Collection(collection) db := m.db.Database(config.Config.Mongo.Database).Collection(collection)
opts := options.CreateIndexes().SetMaxTime(10 * time.Second) opts := options.CreateIndexes().SetMaxTime(10 * time.Second)

@ -14,149 +14,150 @@
package unrelation package unrelation
import ( //
"context" //import (
// "context"
"go.mongodb.org/mongo-driver/bson" //
"go.mongodb.org/mongo-driver/mongo" // "go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options" // "go.mongodb.org/mongo-driver/mongo"
// "go.mongodb.org/mongo-driver/mongo/options"
"github.com/OpenIMSDK/tools/utils" //
// "github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation" //
) // "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
//)
func NewSuperGroupMongoDriver(database *mongo.Database) unrelation.SuperGroupModelInterface { //
return &SuperGroupMongoDriver{ //func NewSuperGroupMongoDriver(database *mongo.Database) unrelation.SuperGroupModelInterface {
superGroupCollection: database.Collection(unrelation.CSuperGroup), // return &SuperGroupMongoDriver{
userToSuperGroupCollection: database.Collection(unrelation.CUserToSuperGroup), // superGroupCollection: database.Collection(unrelation.CSuperGroup),
} // userToSuperGroupCollection: database.Collection(unrelation.CUserToSuperGroup),
} // }
//}
type SuperGroupMongoDriver struct { //
superGroupCollection *mongo.Collection //type SuperGroupMongoDriver struct {
userToSuperGroupCollection *mongo.Collection // superGroupCollection *mongo.Collection
} // userToSuperGroupCollection *mongo.Collection
//}
func (s *SuperGroupMongoDriver) CreateSuperGroup(ctx context.Context, groupID string, initMemberIDs []string) error { //
_, err := s.superGroupCollection.InsertOne(ctx, &unrelation.SuperGroupModel{ //func (s *SuperGroupMongoDriver) CreateSuperGroup(ctx context.Context, groupID string, initMemberIDs []string) error {
GroupID: groupID, // _, err := s.superGroupCollection.InsertOne(ctx, &unrelation.SuperGroupModel{
MemberIDs: initMemberIDs, // GroupID: groupID,
}) // MemberIDs: initMemberIDs,
if err != nil { // })
return err // if err != nil {
} // return err
for _, userID := range initMemberIDs { // }
_, err = s.userToSuperGroupCollection.UpdateOne( // for _, userID := range initMemberIDs {
ctx, // _, err = s.userToSuperGroupCollection.UpdateOne(
bson.M{"user_id": userID}, // ctx,
bson.M{"$addToSet": bson.M{"group_id_list": groupID}}, // bson.M{"user_id": userID},
&options.UpdateOptions{ // bson.M{"$addToSet": bson.M{"group_id_list": groupID}},
Upsert: utils.ToPtr(true), // &options.UpdateOptions{
}, // Upsert: utils.ToPtr(true),
) // },
if err != nil { // )
return err // if err != nil {
} // return err
} // }
return nil // }
} // return nil
//}
func (s *SuperGroupMongoDriver) TakeSuperGroup( //
ctx context.Context, //func (s *SuperGroupMongoDriver) TakeSuperGroup(
groupID string, // ctx context.Context,
) (group *unrelation.SuperGroupModel, err error) { // groupID string,
if err := s.superGroupCollection.FindOne(ctx, bson.M{"group_id": groupID}).Decode(&group); err != nil { //) (group *unrelation.SuperGroupModel, err error) {
return nil, utils.Wrap(err, "") // if err := s.superGroupCollection.FindOne(ctx, bson.M{"group_id": groupID}).Decode(&group); err != nil {
} // return nil, utils.Wrap(err, "")
return group, nil // }
} // return group, nil
//}
func (s *SuperGroupMongoDriver) FindSuperGroup( //
ctx context.Context, //func (s *SuperGroupMongoDriver) FindSuperGroup(
groupIDs []string, // ctx context.Context,
) (groups []*unrelation.SuperGroupModel, err error) { // groupIDs []string,
cursor, err := s.superGroupCollection.Find(ctx, bson.M{"group_id": bson.M{ //) (groups []*unrelation.SuperGroupModel, err error) {
"$in": groupIDs, // cursor, err := s.superGroupCollection.Find(ctx, bson.M{"group_id": bson.M{
}}) // "$in": groupIDs,
if err != nil { // }})
return nil, err // if err != nil {
} // return nil, err
defer cursor.Close(ctx) // }
if err := cursor.All(ctx, &groups); err != nil { // defer cursor.Close(ctx)
return nil, utils.Wrap(err, "") // if err := cursor.All(ctx, &groups); err != nil {
} // return nil, utils.Wrap(err, "")
return groups, nil // }
} // return groups, nil
//}
func (s *SuperGroupMongoDriver) AddUserToSuperGroup(ctx context.Context, groupID string, userIDs []string) error { //
_, err := s.superGroupCollection.UpdateOne( //func (s *SuperGroupMongoDriver) AddUserToSuperGroup(ctx context.Context, groupID string, userIDs []string) error {
ctx, // _, err := s.superGroupCollection.UpdateOne(
bson.M{"group_id": groupID}, // ctx,
bson.M{"$addToSet": bson.M{"member_id_list": bson.M{"$each": userIDs}}}, // bson.M{"group_id": groupID},
) // bson.M{"$addToSet": bson.M{"member_id_list": bson.M{"$each": userIDs}}},
if err != nil { // )
return err // if err != nil {
} // return err
upsert := true // }
opts := &options.UpdateOptions{ // upsert := true
Upsert: &upsert, // opts := &options.UpdateOptions{
} // Upsert: &upsert,
for _, userID := range userIDs { // }
_, err = s.userToSuperGroupCollection.UpdateOne( // for _, userID := range userIDs {
ctx, // _, err = s.userToSuperGroupCollection.UpdateOne(
bson.M{"user_id": userID}, // ctx,
bson.M{"$addToSet": bson.M{"group_id_list": groupID}}, // bson.M{"user_id": userID},
opts, // bson.M{"$addToSet": bson.M{"group_id_list": groupID}},
) // opts,
if err != nil { // )
return utils.Wrap(err, "transaction failed") // if err != nil {
} // return utils.Wrap(err, "transaction failed")
} // }
return nil // }
} // return nil
//}
func (s *SuperGroupMongoDriver) RemoverUserFromSuperGroup(ctx context.Context, groupID string, userIDs []string) error { //
_, err := s.superGroupCollection.UpdateOne( //func (s *SuperGroupMongoDriver) RemoverUserFromSuperGroup(ctx context.Context, groupID string, userIDs []string) error {
ctx, // _, err := s.superGroupCollection.UpdateOne(
bson.M{"group_id": groupID}, // ctx,
bson.M{"$pull": bson.M{"member_id_list": bson.M{"$in": userIDs}}}, // bson.M{"group_id": groupID},
) // bson.M{"$pull": bson.M{"member_id_list": bson.M{"$in": userIDs}}},
if err != nil { // )
return err // if err != nil {
} // return err
err = s.RemoveGroupFromUser(ctx, groupID, userIDs) // }
if err != nil { // err = s.RemoveGroupFromUser(ctx, groupID, userIDs)
return err // if err != nil {
} // return err
return nil // }
} // return nil
//}
func (s *SuperGroupMongoDriver) GetSuperGroupByUserID( //
ctx context.Context, //func (s *SuperGroupMongoDriver) GetSuperGroupByUserID(
userID string, // ctx context.Context,
) (*unrelation.UserToSuperGroupModel, error) { // userID string,
var user unrelation.UserToSuperGroupModel //) (*unrelation.UserToSuperGroupModel, error) {
err := s.userToSuperGroupCollection.FindOne(ctx, bson.M{"user_id": userID}).Decode(&user) // var user unrelation.UserToSuperGroupModel
return &user, utils.Wrap(err, "") // err := s.userToSuperGroupCollection.FindOne(ctx, bson.M{"user_id": userID}).Decode(&user)
} // return &user, utils.Wrap(err, "")
//}
func (s *SuperGroupMongoDriver) DeleteSuperGroup(ctx context.Context, groupID string) error { //
group, err := s.TakeSuperGroup(ctx, groupID) //func (s *SuperGroupMongoDriver) DeleteSuperGroup(ctx context.Context, groupID string) error {
if err != nil { // group, err := s.TakeSuperGroup(ctx, groupID)
return err // if err != nil {
} // return err
if _, err := s.superGroupCollection.DeleteOne(ctx, bson.M{"group_id": groupID}); err != nil { // }
return utils.Wrap(err, "") // if _, err := s.superGroupCollection.DeleteOne(ctx, bson.M{"group_id": groupID}); err != nil {
} // return utils.Wrap(err, "")
return s.RemoveGroupFromUser(ctx, groupID, group.MemberIDs) // }
} // return s.RemoveGroupFromUser(ctx, groupID, group.MemberIDs)
//}
func (s *SuperGroupMongoDriver) RemoveGroupFromUser(ctx context.Context, groupID string, userIDs []string) error { //
_, err := s.userToSuperGroupCollection.UpdateOne( //func (s *SuperGroupMongoDriver) RemoveGroupFromUser(ctx context.Context, groupID string, userIDs []string) error {
ctx, // _, err := s.userToSuperGroupCollection.UpdateOne(
bson.M{"user_id": bson.M{"$in": userIDs}}, // ctx,
bson.M{"$pull": bson.M{"group_id_list": groupID}}, // bson.M{"user_id": bson.M{"$in": userIDs}},
) // bson.M{"$pull": bson.M{"group_id_list": groupID}},
return utils.Wrap(err, "") // )
} // return utils.Wrap(err, "")
//}

@ -0,0 +1,87 @@
package grouphash
import (
"context"
"crypto/md5"
"encoding/binary"
"encoding/json"
"github.com/OpenIMSDK/protocol/group"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/utils"
)
func NewGroupHashFromGroupClient(x group.GroupClient) *GroupHash {
return &GroupHash{
getGroupAllUserIDs: func(ctx context.Context, groupID string) ([]string, error) {
resp, err := x.GetGroupMemberUserIDs(ctx, &group.GetGroupMemberUserIDsReq{GroupID: groupID})
if err != nil {
return nil, err
}
return resp.UserIDs, nil
},
getGroupMemberInfo: func(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error) {
resp, err := x.GetGroupMembersInfo(ctx, &group.GetGroupMembersInfoReq{GroupID: groupID, UserIDs: userIDs})
if err != nil {
return nil, err
}
return resp.Members, nil
},
}
}
func NewGroupHashFromGroupServer(x group.GroupServer) *GroupHash {
return &GroupHash{
getGroupAllUserIDs: func(ctx context.Context, groupID string) ([]string, error) {
resp, err := x.GetGroupMemberUserIDs(ctx, &group.GetGroupMemberUserIDsReq{GroupID: groupID})
if err != nil {
return nil, err
}
return resp.UserIDs, nil
},
getGroupMemberInfo: func(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error) {
resp, err := x.GetGroupMembersInfo(ctx, &group.GetGroupMembersInfoReq{GroupID: groupID, UserIDs: userIDs})
if err != nil {
return nil, err
}
return resp.Members, nil
},
}
}
type GroupHash struct {
getGroupAllUserIDs func(ctx context.Context, groupID string) ([]string, error)
getGroupMemberInfo func(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error)
}
func (gh *GroupHash) GetGroupHash(ctx context.Context, groupID string) (uint64, error) {
userIDs, err := gh.getGroupAllUserIDs(ctx, groupID)
if err != nil {
return 0, err
}
var members []*sdkws.GroupMemberFullInfo
if len(userIDs) > 0 {
members, err = gh.getGroupMemberInfo(ctx, groupID, userIDs)
if err != nil {
return 0, err
}
utils.Sort(userIDs, true)
}
memberMap := utils.SliceToMap(members, func(e *sdkws.GroupMemberFullInfo) string {
return e.UserID
})
res := make([]*sdkws.GroupMemberFullInfo, 0, len(members))
for _, userID := range userIDs {
member, ok := memberMap[userID]
if !ok {
continue
}
member.AppMangerLevel = 0
res = append(res, member)
}
data, err := json.Marshal(res)
if err != nil {
return 0, err
}
sum := md5.Sum(data)
return binary.BigEndian.Uint64(sum[:]), nil
}
Loading…
Cancel
Save