Merge pull request #1447 from cubxxw/feat/mongo

Feat/mongo
pull/1450/head
Xinwei Xiong 2 years ago committed by GitHub
commit 76e32ddfcf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -133,7 +133,7 @@ require (
golang.org/x/arch v0.3.0 // indirect golang.org/x/arch v0.3.0 // indirect
golang.org/x/net v0.17.0 // indirect golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.13.0 // indirect golang.org/x/oauth2 v0.13.0 // indirect
golang.org/x/sys v0.13.0 // indirect golang.org/x/sys v0.14.0 // indirect
golang.org/x/text v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect

@ -438,8 +438,8 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=

@ -152,7 +152,7 @@ func (m *MessageApi) DeleteMsgPhysical(c *gin.Context) {
} }
func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendMsgReq *msg.SendMsgReq, err error) { func (m *MessageApi) getSendMsgReq(c *gin.Context, req apistruct.SendMsg) (sendMsgReq *msg.SendMsgReq, err error) {
var data interface{} var data any
log.ZDebug(c, "getSendMsgReq", "req", req.Content) log.ZDebug(c, "getSendMsgReq", "req", req.Content)
switch req.ContentType { switch req.ContentType {
case constant.Text: case constant.Text:

@ -22,8 +22,8 @@ import (
) )
type Encoder interface { type Encoder interface {
Encode(data interface{}) ([]byte, error) Encode(data any) ([]byte, error)
Decode(encodeData []byte, decodeData interface{}) error Decode(encodeData []byte, decodeData any) error
} }
type GobEncoder struct{} type GobEncoder struct{}
@ -32,7 +32,7 @@ func NewGobEncoder() *GobEncoder {
return &GobEncoder{} return &GobEncoder{}
} }
func (g *GobEncoder) Encode(data interface{}) ([]byte, error) { func (g *GobEncoder) Encode(data any) ([]byte, error) {
buff := bytes.Buffer{} buff := bytes.Buffer{}
enc := gob.NewEncoder(&buff) enc := gob.NewEncoder(&buff)
err := enc.Encode(data) err := enc.Encode(data)
@ -42,7 +42,7 @@ func (g *GobEncoder) Encode(data interface{}) ([]byte, error) {
return buff.Bytes(), nil return buff.Bytes(), nil
} }
func (g *GobEncoder) Decode(encodeData []byte, decodeData interface{}) error { func (g *GobEncoder) Decode(encodeData []byte, decodeData any) error {
buff := bytes.NewBuffer(encodeData) buff := bytes.NewBuffer(encodeData)
dec := gob.NewDecoder(buff) dec := gob.NewDecoder(buff)
err := dec.Decode(decodeData) err := dec.Decode(decodeData)

@ -46,7 +46,7 @@ type LongConnServer interface {
wsHandler(w http.ResponseWriter, r *http.Request) wsHandler(w http.ResponseWriter, r *http.Request)
GetUserAllCons(userID string) ([]*Client, bool) GetUserAllCons(userID string) ([]*Client, bool)
GetUserPlatformCons(userID string, platform int) ([]*Client, bool, bool) GetUserPlatformCons(userID string, platform int) ([]*Client, bool, bool)
Validate(s interface{}) error Validate(s any) error
SetCacheHandler(cache cache.MsgModel) SetCacheHandler(cache cache.MsgModel)
SetDiscoveryRegistry(client discoveryregistry.SvcDiscoveryRegistry) SetDiscoveryRegistry(client discoveryregistry.SvcDiscoveryRegistry)
KickUserConn(client *Client) error KickUserConn(client *Client) error
@ -57,6 +57,12 @@ type LongConnServer interface {
MessageHandler MessageHandler
} }
var bufferPool = sync.Pool{
New: func() any {
return make([]byte, 1024)
},
}
type WsServer struct { type WsServer struct {
port int port int
wsMaxConnNum int64 wsMaxConnNum int64
@ -116,7 +122,7 @@ func (ws *WsServer) UnRegister(c *Client) {
ws.unregisterChan <- c ws.unregisterChan <- c
} }
func (ws *WsServer) Validate(s interface{}) error { func (ws *WsServer) Validate(s any) error {
return nil return nil
} }
@ -139,7 +145,7 @@ func NewWsServer(opts ...Option) (*WsServer, error) {
wsMaxConnNum: config.maxConnNum, wsMaxConnNum: config.maxConnNum,
handshakeTimeout: config.handshakeTimeout, handshakeTimeout: config.handshakeTimeout,
clientPool: sync.Pool{ clientPool: sync.Pool{
New: func() interface{} { New: func() any {
return new(Client) return new(Client)
}, },
}, },

@ -61,7 +61,7 @@ type TriggerChannelValue struct {
type Cmd2Value struct { type Cmd2Value struct {
Cmd int Cmd int
Value interface{} Value any
} }
type ContextMsg struct { type ContextMsg struct {
message *sdkws.MsgData message *sdkws.MsgData

@ -23,7 +23,7 @@ import (
type Resp struct { type Resp struct {
Code int `json:"code"` Code int `json:"code"`
Msg string `json:"msg"` Msg string `json:"msg"`
Data interface{} `json:"data"` Data any `json:"data"`
} }
func (r *Resp) parseError() (err error) { func (r *Resp) parseError() (err error) {

@ -159,7 +159,7 @@ func (g *Client) singlePush(ctx context.Context, token, userID string, pushReq P
return g.request(ctx, pushURL, pushReq, token, nil) return g.request(ctx, pushURL, pushReq, token, nil)
} }
func (g *Client) request(ctx context.Context, url string, input interface{}, token string, output interface{}) error { func (g *Client) request(ctx context.Context, url string, input any, token string, output any) error {
header := map[string]string{"token": token} header := map[string]string{"token": token}
resp := &Resp{} resp := &Resp{}
resp.Data = output resp.Data = output
@ -170,7 +170,7 @@ func (g *Client) postReturn(
ctx context.Context, ctx context.Context,
url string, url string,
header map[string]string, header map[string]string,
input interface{}, input any,
output RespI, output RespI,
timeout int, timeout int,
) error { ) error {

@ -23,7 +23,7 @@ const (
) )
type Audience struct { type Audience struct {
Object interface{} Object any
audience map[string][]string audience map[string][]string
} }

@ -18,7 +18,7 @@ type Message struct {
MsgContent string `json:"msg_content"` MsgContent string `json:"msg_content"`
Title string `json:"title,omitempty"` Title string `json:"title,omitempty"`
ContentType string `json:"content_type,omitempty"` ContentType string `json:"content_type,omitempty"`
Extras map[string]interface{} `json:"extras,omitempty"` Extras map[string]any `json:"extras,omitempty"`
} }
func (m *Message) SetMsgContent(c string) { func (m *Message) SetMsgContent(c string) {
@ -33,9 +33,9 @@ func (m *Message) SetContentType(c string) {
m.ContentType = c m.ContentType = c
} }
func (m *Message) SetExtras(key string, value interface{}) { func (m *Message) SetExtras(key string, value any) {
if m.Extras == nil { if m.Extras == nil {
m.Extras = make(map[string]interface{}) m.Extras = make(map[string]any)
} }
m.Extras[key] = value m.Extras[key] = value
} }

@ -29,7 +29,7 @@ const (
) )
type Platform struct { type Platform struct {
Os interface{} Os any
osArry []string osArry []string
} }

@ -15,11 +15,11 @@
package body package body
type PushObj struct { type PushObj struct {
Platform interface{} `json:"platform"` Platform any `json:"platform"`
Audience interface{} `json:"audience"` Audience any `json:"audience"`
Notification interface{} `json:"notification,omitempty"` Notification any `json:"notification,omitempty"`
Message interface{} `json:"message,omitempty"` Message any `json:"message,omitempty"`
Options interface{} `json:"options,omitempty"` Options any `json:"options,omitempty"`
} }
func (p *PushObj) SetPlatform(pf *Platform) { func (p *PushObj) SetPlatform(pf *Platform) {

@ -69,11 +69,11 @@ func (j *JPush) Push(ctx context.Context, userIDs []string, title, content strin
pushObj.SetNotification(&no) pushObj.SetNotification(&no)
pushObj.SetMessage(&msg) pushObj.SetMessage(&msg)
pushObj.SetOptions(&opt) pushObj.SetOptions(&opt)
var resp interface{} var resp any
return j.request(ctx, pushObj, resp, 5) return j.request(ctx, pushObj, resp, 5)
} }
func (j *JPush) request(ctx context.Context, po body.PushObj, resp interface{}, timeout int) error { func (j *JPush) request(ctx context.Context, po body.PushObj, resp any, timeout int) error {
return http2.PostReturn( return http2.PostReturn(
ctx, ctx,
config.Config.Push.Jpns.PushUrl, config.Config.Push.Jpns.PushUrl,

@ -133,7 +133,7 @@ func (p *Pusher) Push2User(ctx context.Context, userIDs []string, msg *sdkws.Msg
return nil return nil
} }
func (p *Pusher) UnmarshalNotificationElem(bytes []byte, t interface{}) error { func (p *Pusher) UnmarshalNotificationElem(bytes []byte, t any) error {
var notification sdkws.NotificationElem var notification sdkws.NotificationElem
if err := json.Unmarshal(bytes, &notification); err != nil { if err := json.Unmarshal(bytes, &notification); err != nil {
return err return err

@ -16,6 +16,10 @@ package conversation
import ( import (
"context" "context"
"errors"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo"
tx2 "github.com/openimsdk/open-im-server/v3/pkg/common/db/tx"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
"google.golang.org/grpc" "google.golang.org/grpc"
@ -24,13 +28,11 @@ import (
"github.com/OpenIMSDK/tools/discoveryregistry" "github.com/OpenIMSDK/tools/discoveryregistry"
"github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/tools/utils" "github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/convert" "github.com/openimsdk/open-im-server/v3/pkg/common/convert"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
@ -43,24 +45,28 @@ type conversationServer struct {
} }
func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error { func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error {
db, err := relation.NewGormDB() rdb, err := cache.NewRedis()
if err != nil { if err != nil {
return err return err
} }
if err := db.AutoMigrate(&tablerelation.ConversationModel{}); err != nil { mongo, err := unrelation.NewMongo()
if err != nil {
return err return err
} }
rdb, err := cache.NewRedis() tx, err := tx2.NewAuto(context.Background(), mongo.GetClient())
if err != nil {
return err
}
conversationDB, err := newmgo.NewConversationMongo(mongo.GetDatabase())
if err != nil { if err != nil {
return err return err
} }
conversationDB := relation.NewConversationGorm(db)
groupRpcClient := rpcclient.NewGroupRpcClient(client) groupRpcClient := rpcclient.NewGroupRpcClient(client)
msgRpcClient := rpcclient.NewMessageRpcClient(client) msgRpcClient := rpcclient.NewMessageRpcClient(client)
pbconversation.RegisterConversationServer(server, &conversationServer{ pbconversation.RegisterConversationServer(server, &conversationServer{
conversationNotificationSender: notification.NewConversationNotificationSender(&msgRpcClient), conversationNotificationSender: notification.NewConversationNotificationSender(&msgRpcClient),
groupRpcClient: &groupRpcClient, groupRpcClient: &groupRpcClient,
conversationDatabase: controller.NewConversationDatabase(conversationDB, cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), conversationDB), tx.NewGorm(db)), conversationDatabase: controller.NewConversationDatabase(conversationDB, cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), conversationDB), tx),
}) })
return nil return nil
} }
@ -145,7 +151,7 @@ func (c *conversationServer) SetConversations(ctx context.Context,
conversation.ConversationType = req.Conversation.ConversationType conversation.ConversationType = req.Conversation.ConversationType
conversation.UserID = req.Conversation.UserID conversation.UserID = req.Conversation.UserID
conversation.GroupID = req.Conversation.GroupID conversation.GroupID = req.Conversation.GroupID
m := make(map[string]interface{}) m := make(map[string]any)
if req.Conversation.RecvMsgOpt != nil { if req.Conversation.RecvMsgOpt != nil {
m["recv_msg_opt"] = req.Conversation.RecvMsgOpt.Value m["recv_msg_opt"] = req.Conversation.RecvMsgOpt.Value
if req.Conversation.RecvMsgOpt.Value != conv.RecvMsgOpt { if req.Conversation.RecvMsgOpt.Value != conv.RecvMsgOpt {
@ -229,11 +235,12 @@ func (c *conversationServer) SetConversations(ctx context.Context,
// 获取超级大群开启免打扰的用户ID. // 获取超级大群开启免打扰的用户ID.
func (c *conversationServer) GetRecvMsgNotNotifyUserIDs(ctx context.Context, req *pbconversation.GetRecvMsgNotNotifyUserIDsReq) (*pbconversation.GetRecvMsgNotNotifyUserIDsResp, error) { func (c *conversationServer) GetRecvMsgNotNotifyUserIDs(ctx context.Context, req *pbconversation.GetRecvMsgNotNotifyUserIDsReq) (*pbconversation.GetRecvMsgNotNotifyUserIDsResp, error) {
userIDs, err := c.conversationDatabase.FindRecvMsgNotNotifyUserIDs(ctx, req.GroupID) //userIDs, err := c.conversationDatabase.FindRecvMsgNotNotifyUserIDs(ctx, req.GroupID)
if err != nil { //if err != nil {
return nil, err // return nil, err
} //}
return &pbconversation.GetRecvMsgNotNotifyUserIDsResp{UserIDs: userIDs}, nil //return &pbconversation.GetRecvMsgNotNotifyUserIDsResp{UserIDs: userIDs}, nil
return nil, errors.New("deprecated")
} }
// create conversation without notification for msg redis transfer. // create conversation without notification for msg redis transfer.
@ -284,7 +291,7 @@ func (c *conversationServer) CreateGroupChatConversations(ctx context.Context, r
func (c *conversationServer) SetConversationMaxSeq(ctx context.Context, req *pbconversation.SetConversationMaxSeqReq) (*pbconversation.SetConversationMaxSeqResp, error) { func (c *conversationServer) SetConversationMaxSeq(ctx context.Context, req *pbconversation.SetConversationMaxSeqReq) (*pbconversation.SetConversationMaxSeqResp, error) {
if err := c.conversationDatabase.UpdateUsersConversationFiled(ctx, req.OwnerUserID, req.ConversationID, if err := c.conversationDatabase.UpdateUsersConversationFiled(ctx, req.OwnerUserID, req.ConversationID,
map[string]interface{}{"max_seq": req.MaxSeq}); err != nil { map[string]any{"max_seq": req.MaxSeq}); err != nil {
return nil, err return nil, err
} }
return &pbconversation.SetConversationMaxSeqResp{}, nil return &pbconversation.SetConversationMaxSeqResp{}, nil

@ -37,8 +37,9 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/relation" "github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo"
tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
) )
@ -52,41 +53,61 @@ type friendServer struct {
} }
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error { func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
db, err := relation.NewGormDB() // Initialize MongoDB
mongo, err := unrelation.NewMongo()
if err != nil { if err != nil {
return err return err
} }
if err := db.AutoMigrate(&tablerelation.FriendModel{}, &tablerelation.FriendRequestModel{}, &tablerelation.BlackModel{}); err != nil {
// Initialize Redis
rdb, err := cache.NewRedis()
if err != nil {
return err return err
} }
rdb, err := cache.NewRedis()
friendMongoDB, err := newmgo.NewFriendMongo(mongo.GetDatabase())
if err != nil {
return err
}
friendRequestMongoDB, err := newmgo.NewFriendRequestMongo(mongo.GetDatabase())
if err != nil { if err != nil {
return err return err
} }
blackDB := relation.NewBlackGorm(db)
friendDB := relation.NewFriendGorm(db) blackMongoDB, err := newmgo.NewBlackMongo(mongo.GetDatabase())
if err != nil {
return err
}
// Initialize RPC clients
userRpcClient := rpcclient.NewUserRpcClient(client) userRpcClient := rpcclient.NewUserRpcClient(client)
msgRpcClient := rpcclient.NewMessageRpcClient(client) msgRpcClient := rpcclient.NewMessageRpcClient(client)
// Initialize notification sender
notificationSender := notification.NewFriendNotificationSender( notificationSender := notification.NewFriendNotificationSender(
&msgRpcClient, &msgRpcClient,
notification.WithRpcFunc(userRpcClient.GetUsersInfo), notification.WithRpcFunc(userRpcClient.GetUsersInfo),
) )
// Register Friend server with refactored MongoDB and Redis integrations
pbfriend.RegisterFriendServer(server, &friendServer{ pbfriend.RegisterFriendServer(server, &friendServer{
friendDatabase: controller.NewFriendDatabase( friendDatabase: controller.NewFriendDatabase(
friendDB, friendMongoDB,
relation.NewFriendRequestGorm(db), friendRequestMongoDB,
cache.NewFriendCacheRedis(rdb, friendDB, cache.GetDefaultOpt()), cache.NewFriendCacheRedis(rdb, friendMongoDB, cache.GetDefaultOpt()),
tx.NewGorm(db), tx.NewMongo(mongo.GetClient()),
), ),
blackDatabase: controller.NewBlackDatabase( blackDatabase: controller.NewBlackDatabase(
blackDB, blackMongoDB,
cache.NewBlackCacheRedis(rdb, blackDB, cache.GetDefaultOpt()), cache.NewBlackCacheRedis(rdb, blackMongoDB, cache.GetDefaultOpt()),
), ),
userRpcClient: &userRpcClient, userRpcClient: &userRpcClient,
notificationSender: notificationSender, notificationSender: notificationSender,
RegisterCenter: client, RegisterCenter: client,
conversationRpcClient: rpcclient.NewConversationRpcClient(client), conversationRpcClient: rpcclient.NewConversationRpcClient(client),
}) })
return nil return nil
} }

@ -26,7 +26,7 @@ func (s *groupServer) GetGroupInfoCache(
ctx context.Context, ctx context.Context,
req *pbgroup.GetGroupInfoCacheReq, req *pbgroup.GetGroupInfoCacheReq,
) (resp *pbgroup.GetGroupInfoCacheResp, err error) { ) (resp *pbgroup.GetGroupInfoCacheResp, err error) {
group, err := s.GroupDatabase.TakeGroup(ctx, req.GroupID) group, err := s.db.TakeGroup(ctx, req.GroupID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -38,7 +38,7 @@ func (s *groupServer) GetGroupMemberCache(
ctx context.Context, ctx context.Context,
req *pbgroup.GetGroupMemberCacheReq, req *pbgroup.GetGroupMemberCacheReq,
) (resp *pbgroup.GetGroupMemberCacheResp, err error) { ) (resp *pbgroup.GetGroupMemberCacheResp, err error) {
members, err := s.GroupDatabase.TakeGroupMember(ctx, req.GroupID, req.GroupMemberID) members, err := s.db.TakeGroupMember(ctx, req.GroupID, req.GroupMemberID)
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -17,119 +17,145 @@ package group
import ( import (
"context" "context"
"github.com/OpenIMSDK/tools/utils"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
) )
func (s *groupServer) FindGroupMember(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error) { //func (s *groupServer) FindGroupMember(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error) {
members, err := s.GroupDatabase.FindGroupMember(ctx, groupIDs, userIDs, roleLevels) // members, err := s.db.FindGroupMember(ctx, groupIDs, userIDs, roleLevels)
if err != nil { // if err != nil {
return nil, err // return nil, err
} // }
emptyUserIDs := make(map[string]struct{}) // emptyUserIDs := make(map[string]struct{})
for _, member := range members { // for _, member := range members {
if member.Nickname == "" || member.FaceURL == "" { // if member.Nickname == "" || member.FaceURL == "" {
emptyUserIDs[member.UserID] = struct{}{} // emptyUserIDs[member.UserID] = struct{}{}
} // }
} // }
if len(emptyUserIDs) > 0 { // if len(emptyUserIDs) > 0 {
users, err := s.User.GetPublicUserInfoMap(ctx, utils.Keys(emptyUserIDs), true) // users, err := s.User.GetPublicUserInfoMap(ctx, utils.Keys(emptyUserIDs), true)
if err != nil { // if err != nil {
return nil, err // return nil, err
} // }
for i, member := range members { // for i, member := range members {
user, ok := users[member.UserID] // user, ok := users[member.UserID]
if !ok { // if !ok {
continue // continue
} // }
if member.Nickname == "" { // if member.Nickname == "" {
members[i].Nickname = user.Nickname // members[i].Nickname = user.Nickname
} // }
if member.FaceURL == "" { // if member.FaceURL == "" {
members[i].FaceURL = user.FaceURL // members[i].FaceURL = user.FaceURL
} // }
} // }
} // }
return members, nil // return members, nil
} //}
func (s *groupServer) TakeGroupMember( func (s *groupServer) PopulateGroupMember(ctx context.Context, members ...*relationtb.GroupMemberModel) error {
ctx context.Context, return s.Notification.PopulateGroupMember(ctx, members...)
groupID string, //if len(members) == 0 {
userID string, // return nil
) (*relationtb.GroupMemberModel, error) { //}
member, err := s.GroupDatabase.TakeGroupMember(ctx, groupID, userID) //emptyUserIDs := make(map[string]struct{})
if err != nil { //for _, member := range members {
return nil, err // if member.Nickname == "" || member.FaceURL == "" {
} // emptyUserIDs[member.UserID] = struct{}{}
if member.Nickname == "" || member.FaceURL == "" { // }
user, err := s.User.GetPublicUserInfo(ctx, userID) //}
if err != nil { //if len(emptyUserIDs) > 0 {
return nil, err // users, err := s.User.GetPublicUserInfoMap(ctx, utils.Keys(emptyUserIDs), true)
} // if err != nil {
if member.Nickname == "" { // return err
member.Nickname = user.Nickname // }
} // for i, member := range members {
if member.FaceURL == "" { // user, ok := users[member.UserID]
member.FaceURL = user.FaceURL // if !ok {
} // continue
} // }
return member, nil // if member.Nickname == "" {
// members[i].Nickname = user.Nickname
// }
// if member.FaceURL == "" {
// members[i].FaceURL = user.FaceURL
// }
// }
//}
//return nil
} }
func (s *groupServer) TakeGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) { //func (s *groupServer) TakeGroupMembers(ctx context.Context, groupID string, userID string) (*relationtb.GroupMemberModel, error) {
owner, err := s.GroupDatabase.TakeGroupOwner(ctx, groupID) // member, err := s.db.TakeGroupMember(ctx, groupID, userID)
if err != nil { // if err != nil {
return nil, err // return nil, err
} // }
if owner.Nickname == "" || owner.FaceURL == "" { // if member.Nickname == "" || member.FaceURL == "" {
user, err := s.User.GetUserInfo(ctx, owner.UserID) // user, err := s.User.GetPublicUserInfo(ctx, userID)
if err != nil { // if err != nil {
return nil, err // return nil, err
} // }
if owner.Nickname == "" { // if member.Nickname == "" {
owner.Nickname = user.Nickname // member.Nickname = user.Nickname
} // }
if owner.FaceURL == "" { // if member.FaceURL == "" {
owner.FaceURL = user.FaceURL // member.FaceURL = user.FaceURL
} // }
} // }
return owner, nil // return member, nil
} //}
func (s *groupServer) PageGetGroupMember( //func (s *groupServer) TakeGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) {
ctx context.Context, // owner, err := s.db.TakeGroupOwner(ctx, groupID)
groupID string, // if err != nil {
pageNumber, showNumber int32, // return nil, err
) (uint32, []*relationtb.GroupMemberModel, error) { // }
total, members, err := s.GroupDatabase.PageGetGroupMember(ctx, groupID, pageNumber, showNumber) // if owner.Nickname == "" || owner.FaceURL == "" {
if err != nil { // user, err := s.User.GetUserInfo(ctx, owner.UserID)
return 0, nil, err // if err != nil {
} // return nil, err
emptyUserIDs := make(map[string]struct{}) // }
for _, member := range members { // if owner.Nickname == "" {
if member.Nickname == "" || member.FaceURL == "" { // owner.Nickname = user.Nickname
emptyUserIDs[member.UserID] = struct{}{} // }
} // if owner.FaceURL == "" {
} // owner.FaceURL = user.FaceURL
if len(emptyUserIDs) > 0 { // }
users, err := s.User.GetPublicUserInfoMap(ctx, utils.Keys(emptyUserIDs), true) // }
if err != nil { // return owner, nil
return 0, nil, err //}
} //
for i, member := range members { //func (s *groupServer) PageGetGroupMember(
user, ok := users[member.UserID] // ctx context.Context,
if !ok { // groupID string,
continue // pageNumber, showNumber int32,
} //) (uint32, []*relationtb.GroupMemberModel, error) {
if member.Nickname == "" { // total, members, err := s.db.PageGetGroupMember(ctx, groupID, pageNumber, showNumber)
members[i].Nickname = user.Nickname // if err != nil {
} // return 0, nil, err
if member.FaceURL == "" { // }
members[i].FaceURL = user.FaceURL // emptyUserIDs := make(map[string]struct{})
} // for _, member := range members {
} // if member.Nickname == "" || member.FaceURL == "" {
} // emptyUserIDs[member.UserID] = struct{}{}
return total, members, nil // }
} // }
// if len(emptyUserIDs) > 0 {
// users, err := s.User.GetPublicUserInfoMap(ctx, utils.Keys(emptyUserIDs), true)
// if err != nil {
// return 0, nil, err
// }
// for i, member := range members {
// user, ok := users[member.UserID]
// if !ok {
// continue
// }
// if member.Nickname == "" {
// members[i].Nickname = user.Nickname
// }
// if member.FaceURL == "" {
// members[i].FaceURL = user.FaceURL
// }
// }
// }
// return total, members, nil
//}

File diff suppressed because it is too large Load Diff

@ -26,16 +26,16 @@ func (s *groupServer) GroupCreateCount(ctx context.Context, req *group.GroupCrea
if req.Start > req.End { if req.Start > req.End {
return nil, errs.ErrArgs.Wrap("start > end") return nil, errs.ErrArgs.Wrap("start > end")
} }
total, err := s.GroupDatabase.CountTotal(ctx, nil) total, err := s.db.CountTotal(ctx, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
start := time.UnixMilli(req.Start) start := time.UnixMilli(req.Start)
before, err := s.GroupDatabase.CountTotal(ctx, &start) before, err := s.db.CountTotal(ctx, &start)
if err != nil { if err != nil {
return nil, err return nil, err
} }
count, err := s.GroupDatabase.CountRangeEverydayTotal(ctx, start, time.UnixMilli(req.End)) count, err := s.db.CountRangeEverydayTotal(ctx, start, time.UnixMilli(req.End))
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -16,99 +16,14 @@ package group
import ( import (
"context" "context"
"fmt" "errors"
"strings"
"github.com/OpenIMSDK/protocol/constant"
pbgroup "github.com/OpenIMSDK/protocol/group" pbgroup "github.com/OpenIMSDK/protocol/group"
sdkws "github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/convert"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
) )
func (s *groupServer) GetJoinedSuperGroupList( func (s *groupServer) GetJoinedSuperGroupList(context.Context, *pbgroup.GetJoinedSuperGroupListReq) (*pbgroup.GetJoinedSuperGroupListResp, error) {
ctx context.Context, return nil, errors.New("deprecated")
req *pbgroup.GetJoinedSuperGroupListReq,
) (*pbgroup.GetJoinedSuperGroupListResp, error) {
resp := &pbgroup.GetJoinedSuperGroupListResp{}
groupIDs, err := s.GroupDatabase.FindJoinSuperGroup(ctx, req.UserID)
if err != nil {
return nil, err
}
if len(groupIDs) == 0 {
return resp, nil
}
owners, err := s.FindGroupMember(ctx, groupIDs, nil, []int32{constant.GroupOwner})
if err != nil {
return nil, err
}
ownerMap := utils.SliceToMap(owners, func(e *relation.GroupMemberModel) string {
return e.GroupID
})
if ids := utils.Single(groupIDs, utils.Keys(ownerMap)); len(ids) > 0 {
return nil, errs.ErrData.Wrap(fmt.Sprintf("super group %s not owner", strings.Join(ids, ",")))
}
groups, err := s.GroupDatabase.FindGroup(ctx, groupIDs)
if err != nil {
return nil, err
}
groupMap := utils.SliceToMap(groups, func(e *relation.GroupModel) string {
return e.GroupID
})
if ids := utils.Single(groupIDs, utils.Keys(groupMap)); len(ids) > 0 {
return nil, errs.ErrData.Wrap(fmt.Sprintf("super group info %s not found", strings.Join(ids, ",")))
}
superGroupMembers, err := s.GroupDatabase.FindSuperGroup(ctx, groupIDs)
if err != nil {
return nil, err
}
superGroupMemberMap := utils.SliceToMapAny(
superGroupMembers,
func(e *unrelation.SuperGroupModel) (string, []string) {
return e.GroupID, e.MemberIDs
},
)
resp.Groups = utils.Slice(groupIDs, func(groupID string) *sdkws.GroupInfo {
return convert.Db2PbGroupInfo(groupMap[groupID], ownerMap[groupID].UserID, uint32(len(superGroupMemberMap)))
})
return resp, nil
} }
func (s *groupServer) GetSuperGroupsInfo( func (s *groupServer) GetSuperGroupsInfo(context.Context, *pbgroup.GetSuperGroupsInfoReq) (resp *pbgroup.GetSuperGroupsInfoResp, err error) {
ctx context.Context, return nil, errors.New("deprecated")
req *pbgroup.GetSuperGroupsInfoReq,
) (resp *pbgroup.GetSuperGroupsInfoResp, err error) {
resp = &pbgroup.GetSuperGroupsInfoResp{}
if len(req.GroupIDs) == 0 {
return nil, errs.ErrArgs.Wrap("groupIDs empty")
}
groups, err := s.GroupDatabase.FindGroup(ctx, req.GroupIDs)
if err != nil {
return nil, err
}
superGroupMembers, err := s.GroupDatabase.FindSuperGroup(ctx, req.GroupIDs)
if err != nil {
return nil, err
}
superGroupMemberMap := utils.SliceToMapAny(
superGroupMembers,
func(e *unrelation.SuperGroupModel) (string, []string) {
return e.GroupID, e.MemberIDs
},
)
owners, err := s.FindGroupMember(ctx, req.GroupIDs, nil, []int32{constant.GroupOwner})
if err != nil {
return nil, err
}
ownerMap := utils.SliceToMap(owners, func(e *relation.GroupMemberModel) string {
return e.GroupID
})
resp.GroupInfos = utils.Slice(groups, func(e *relation.GroupModel) *sdkws.GroupInfo {
return convert.Db2PbGroupInfo(e, ownerMap[e.GroupID].UserID, uint32(len(superGroupMemberMap[e.GroupID])))
})
return resp, nil
} }

@ -120,7 +120,7 @@ func (t *thirdServer) SearchLogs(ctx context.Context, req *third.SearchLogsReq)
if req.StartTime > req.EndTime { if req.StartTime > req.EndTime {
return nil, errs.ErrArgs.Wrap("startTime>endTime") return nil, errs.ErrArgs.Wrap("startTime>endTime")
} }
total, logs, err := t.thirdDatabase.SearchLogs(ctx, req.Keyword, time.UnixMilli(req.StartTime), time.UnixMilli(req.EndTime), req.Pagination.PageNumber, req.Pagination.ShowNumber) total, logs, err := t.thirdDatabase.SearchLogs(ctx, req.Keyword, time.UnixMilli(req.StartTime), time.UnixMilli(req.EndTime), req.Pagination)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -128,18 +128,16 @@ func (t *thirdServer) SearchLogs(ctx context.Context, req *third.SearchLogsReq)
for _, log := range logs { for _, log := range logs {
userIDs = append(userIDs, log.UserID) userIDs = append(userIDs, log.UserID)
} }
users, err := t.thirdDatabase.FindUsers(ctx, userIDs) userMap, err := t.userRpcClient.GetUsersInfoMap(ctx, userIDs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
IDtoName := make(map[string]string)
for _, user := range users {
IDtoName[user.UserID] = user.Nickname
}
for _, pbLog := range pbLogs { for _, pbLog := range pbLogs {
pbLog.Nickname = IDtoName[pbLog.UserID] if user, ok := userMap[pbLog.UserID]; ok {
pbLog.Nickname = user.Nickname
}
} }
resp.LogsInfos = pbLogs resp.LogsInfos = pbLogs
resp.Total = total resp.Total = uint32(total)
return &resp, nil return &resp, nil
} }

@ -64,7 +64,7 @@ func (t *thirdServer) InitiateMultipartUpload(ctx context.Context, req *third.In
Key: haErr.Object.Key, Key: haErr.Object.Key,
Size: haErr.Object.Size, Size: haErr.Object.Size,
ContentType: req.ContentType, ContentType: req.ContentType,
Cause: req.Cause, Group: req.Cause,
CreateTime: time.Now(), CreateTime: time.Now(),
} }
if err := t.s3dataBase.SetObject(ctx, obj); err != nil { if err := t.s3dataBase.SetObject(ctx, obj); err != nil {
@ -143,7 +143,7 @@ func (t *thirdServer) CompleteMultipartUpload(ctx context.Context, req *third.Co
Key: result.Key, Key: result.Key,
Size: result.Size, Size: result.Size,
ContentType: req.ContentType, ContentType: req.ContentType,
Cause: req.Cause, Group: req.Cause,
CreateTime: time.Now(), CreateTime: time.Now(),
} }
if err := t.s3dataBase.SetObject(ctx, obj); err != nil { if err := t.s3dataBase.SetObject(ctx, obj); err != nil {

@ -17,6 +17,8 @@ package third
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
"net/url" "net/url"
"time" "time"
@ -33,13 +35,22 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
) )
func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error { func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error {
mongo, err := unrelation.NewMongo()
if err != nil {
return err
}
logdb, err := newmgo.NewLogMongo(mongo.GetDatabase())
if err != nil {
return err
}
s3db, err := newmgo.NewS3Mongo(mongo.GetDatabase())
if err != nil {
return err
}
apiURL := config.Config.Object.ApiURL apiURL := config.Config.Object.ApiURL
if apiURL == "" { if apiURL == "" {
return fmt.Errorf("api url is empty") return fmt.Errorf("api url is empty")
@ -55,13 +66,6 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
if err != nil { if err != nil {
return err return err
} }
db, err := relation.NewGormDB()
if err != nil {
return err
}
if err := db.AutoMigrate(&relationtb.ObjectModel{}); err != nil {
return err
}
// 根据配置文件策略选择 oss 方式 // 根据配置文件策略选择 oss 方式
enable := config.Config.Object.Enable enable := config.Config.Object.Enable
var o s3.Interface var o s3.Interface
@ -78,17 +82,11 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
if err != nil { if err != nil {
return err return err
} }
//specialerror.AddErrHandler(func(err error) errs.CodeError {
// if o.IsNotFound(err) {
// return errs.ErrRecordNotFound
// }
// return nil
//})
third.RegisterThirdServer(server, &thirdServer{ third.RegisterThirdServer(server, &thirdServer{
apiURL: apiURL, apiURL: apiURL,
thirdDatabase: controller.NewThirdDatabase(cache.NewMsgCacheModel(rdb), db), thirdDatabase: controller.NewThirdDatabase(cache.NewMsgCacheModel(rdb), logdb),
userRpcClient: rpcclient.NewUserRpcClient(client), userRpcClient: rpcclient.NewUserRpcClient(client),
s3dataBase: controller.NewS3Database(rdb, o, relation.NewObjectInfo(db)), s3dataBase: controller.NewS3Database(rdb, o, s3db),
defaultExpire: time.Hour * 24 * 7, defaultExpire: time.Hour * 24 * 7,
}) })
return nil return nil

@ -17,6 +17,8 @@ package user
import ( import (
"context" "context"
"errors" "errors"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo"
tx2 "github.com/openimsdk/open-im-server/v3/pkg/common/db/tx"
"strings" "strings"
"time" "time"
@ -24,7 +26,6 @@ import (
"github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/tx"
"github.com/openimsdk/open-im-server/v3/pkg/authverify" "github.com/openimsdk/open-im-server/v3/pkg/authverify"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation" "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
@ -35,7 +36,6 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/convert" "github.com/openimsdk/open-im-server/v3/pkg/common/convert"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
@ -55,10 +55,6 @@ type userServer struct {
} }
func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error { func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
db, err := relation.NewGormDB()
if err != nil {
return err
}
rdb, err := cache.NewRedis() rdb, err := cache.NewRedis()
if err != nil { if err != nil {
return err return err
@ -67,9 +63,6 @@ func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
if err != nil { if err != nil {
return err return err
} }
if err := db.AutoMigrate(&tablerelation.UserModel{}); err != nil {
return err
}
users := make([]*tablerelation.UserModel, 0) users := make([]*tablerelation.UserModel, 0)
if len(config.Config.Manager.UserID) != len(config.Config.Manager.Nickname) { if len(config.Config.Manager.UserID) != len(config.Config.Manager.Nickname) {
return errors.New("len(config.Config.Manager.AppManagerUid) != len(config.Config.Manager.Nickname)") return errors.New("len(config.Config.Manager.AppManagerUid) != len(config.Config.Manager.Nickname)")
@ -77,10 +70,17 @@ func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
for k, v := range config.Config.Manager.UserID { for k, v := range config.Config.Manager.UserID {
users = append(users, &tablerelation.UserModel{UserID: v, Nickname: config.Config.Manager.Nickname[k], AppMangerLevel: constant.AppAdmin}) users = append(users, &tablerelation.UserModel{UserID: v, Nickname: config.Config.Manager.Nickname[k], AppMangerLevel: constant.AppAdmin})
} }
userDB := relation.NewUserGorm(db) userDB, err := newmgo.NewUserMongo(mongo.GetDatabase())
if err != nil {
return err
}
tx, err := tx2.NewAuto(context.Background(), mongo.GetClient())
if err != nil {
return err
}
cache := cache.NewUserCacheRedis(rdb, userDB, cache.GetDefaultOpt()) cache := cache.NewUserCacheRedis(rdb, userDB, cache.GetDefaultOpt())
userMongoDB := unrelation.NewUserMongoDriver(mongo.GetDatabase()) userMongoDB := unrelation.NewUserMongoDriver(mongo.GetDatabase())
database := controller.NewUserDatabase(userDB, cache, tx.NewGorm(db), userMongoDB) database := controller.NewUserDatabase(userDB, cache, tx, userMongoDB)
friendRpcClient := rpcclient.NewFriendRpcClient(client) friendRpcClient := rpcclient.NewFriendRpcClient(client)
groupRpcClient := rpcclient.NewGroupRpcClient(client) groupRpcClient := rpcclient.NewGroupRpcClient(client)
msgRpcClient := rpcclient.NewMessageRpcClient(client) msgRpcClient := rpcclient.NewMessageRpcClient(client)
@ -118,12 +118,11 @@ func (s *userServer) UpdateUserInfo(ctx context.Context, req *pbuser.UpdateUserI
if err := CallbackBeforeUpdateUserInfo(ctx, req); err != nil { if err := CallbackBeforeUpdateUserInfo(ctx, req); err != nil {
return nil, err return nil, err
} }
user := convert.UserPb2DB(req.UserInfo) data := convert.UserPb2DBMap(req.UserInfo)
if err != nil { if len(data) == 0 {
return nil, err return nil, errs.ErrArgs.Wrap("no data to update")
} }
err = s.Update(ctx, user) if err := s.UpdateByMap(ctx, req.UserInfo.UserID, data); err != nil {
if err != nil {
return nil, err return nil, err
} }
_ = s.friendNotificationSender.UserInfoUpdatedNotification(ctx, req.UserInfo.UserID) _ = s.friendNotificationSender.UserInfoUpdatedNotification(ctx, req.UserInfo.UserID)
@ -150,7 +149,7 @@ func (s *userServer) SetGlobalRecvMessageOpt(ctx context.Context, req *pbuser.Se
if _, err := s.FindWithError(ctx, []string{req.UserID}); err != nil { if _, err := s.FindWithError(ctx, []string{req.UserID}); err != nil {
return nil, err return nil, err
} }
m := make(map[string]interface{}, 1) m := make(map[string]any, 1)
m["global_recv_msg_opt"] = req.GlobalRecvMsgOpt m["global_recv_msg_opt"] = req.GlobalRecvMsgOpt
if err := s.UpdateByMap(ctx, req.UserID, m); err != nil { if err := s.UpdateByMap(ctx, req.UserID, m); err != nil {
return nil, err return nil, err
@ -172,7 +171,7 @@ func (s *userServer) AccountCheck(ctx context.Context, req *pbuser.AccountCheckR
if err != nil { if err != nil {
return nil, err return nil, err
} }
userIDs := make(map[string]interface{}, 0) userIDs := make(map[string]any, 0)
for _, v := range users { for _, v := range users {
userIDs[v.UserID] = nil userIDs[v.UserID] = nil
} }
@ -189,12 +188,7 @@ func (s *userServer) AccountCheck(ctx context.Context, req *pbuser.AccountCheckR
} }
func (s *userServer) GetPaginationUsers(ctx context.Context, req *pbuser.GetPaginationUsersReq) (resp *pbuser.GetPaginationUsersResp, err error) { func (s *userServer) GetPaginationUsers(ctx context.Context, req *pbuser.GetPaginationUsersReq) (resp *pbuser.GetPaginationUsersResp, err error) {
var pageNumber, showNumber int32 total, users, err := s.Page(ctx, req.Pagination)
if req.Pagination != nil {
pageNumber = req.Pagination.PageNumber
showNumber = req.Pagination.ShowNumber
}
users, total, err := s.Page(ctx, pageNumber, showNumber)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -259,11 +253,11 @@ func (s *userServer) GetGlobalRecvMessageOpt(ctx context.Context, req *pbuser.Ge
// GetAllUserID Get user account by page. // GetAllUserID Get user account by page.
func (s *userServer) GetAllUserID(ctx context.Context, req *pbuser.GetAllUserIDReq) (resp *pbuser.GetAllUserIDResp, err error) { func (s *userServer) GetAllUserID(ctx context.Context, req *pbuser.GetAllUserIDReq) (resp *pbuser.GetAllUserIDResp, err error) {
userIDs, err := s.UserDatabase.GetAllUserID(ctx, req.Pagination.PageNumber, req.Pagination.ShowNumber) total, userIDs, err := s.UserDatabase.GetAllUserID(ctx, req.Pagination)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &pbuser.GetAllUserIDResp{UserIDs: userIDs}, nil return &pbuser.GetAllUserIDResp{Total: int32(total), UserIDs: userIDs}, nil
} }
// SubscribeOrCancelUsersStatus Subscribe online or cancel online users. // SubscribeOrCancelUsersStatus Subscribe online or cancel online users.

@ -0,0 +1,132 @@
package user
import (
"context"
"errors"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/protocol/user"
"github.com/OpenIMSDK/tools/log"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo"
tablerelation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
tx2 "github.com/openimsdk/open-im-server/v3/pkg/common/db/tx"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
"github.com/redis/go-redis/v9"
"math/rand"
"net"
"strconv"
"testing"
)
var (
rdb redis.UniversalClient
mgo *unrelation.Mongo
ctx context.Context
)
func InitDB() error {
addr := "172.16.8.142"
pwd := "openIM123"
config.Config.Redis.Address = []string{net.JoinHostPort(addr, "16379")}
config.Config.Redis.Password = pwd
config.Config.Mongo.Address = []string{net.JoinHostPort(addr, "37017")}
config.Config.Mongo.Database = "openIM_v3"
config.Config.Mongo.Username = "root"
config.Config.Mongo.Password = pwd
config.Config.Mongo.MaxPoolSize = 100
var err error
rdb, err = cache.NewRedis()
if err != nil {
return err
}
mgo, err = unrelation.NewMongo()
if err != nil {
return err
}
tx, err := tx2.NewAuto(context.Background(), mgo.GetClient())
if err != nil {
return err
}
config.Config.Object.Enable = "minio"
config.Config.Object.ApiURL = "http://" + net.JoinHostPort(addr, "10002")
config.Config.Object.Minio.Bucket = "openim"
config.Config.Object.Minio.Endpoint = "http://" + net.JoinHostPort(addr, "10005")
config.Config.Object.Minio.AccessKeyID = "root"
config.Config.Object.Minio.SecretAccessKey = pwd
config.Config.Object.Minio.SignEndpoint = config.Config.Object.Minio.Endpoint
config.Config.Manager.UserID = []string{"openIM123456"}
config.Config.Manager.Nickname = []string{"openIM123456"}
ctx = context.WithValue(context.Background(), constant.OperationID, "debugOperationID")
ctx = context.WithValue(context.Background(), constant.OpUserID, config.Config.Manager.UserID[0])
if err := log.InitFromConfig("", "", 6, true, false, "", 2, 1); err != nil {
panic(err)
}
users := make([]*tablerelation.UserModel, 0)
if len(config.Config.Manager.UserID) != len(config.Config.Manager.Nickname) {
return errors.New("len(config.Config.Manager.AppManagerUid) != len(config.Config.Manager.Nickname)")
}
for k, v := range config.Config.Manager.UserID {
users = append(users, &tablerelation.UserModel{UserID: v, Nickname: config.Config.Manager.Nickname[k], AppMangerLevel: constant.AppAdmin})
}
userDB, err := newmgo.NewUserMongo(mgo.GetDatabase())
if err != nil {
return err
}
//var client registry.SvcDiscoveryRegistry
//_= client
cache := cache.NewUserCacheRedis(rdb, userDB, cache.GetDefaultOpt())
userMongoDB := unrelation.NewUserMongoDriver(mgo.GetDatabase())
database := controller.NewUserDatabase(userDB, cache, tx, userMongoDB)
//friendRpcClient := rpcclient.NewFriendRpcClient(client)
//groupRpcClient := rpcclient.NewGroupRpcClient(client)
//msgRpcClient := rpcclient.NewMessageRpcClient(client)
userSrv = &userServer{
UserDatabase: database,
//RegisterCenter: client,
//friendRpcClient: &friendRpcClient,
//groupRpcClient: &groupRpcClient,
//friendNotificationSender: notification.NewFriendNotificationSender(&msgRpcClient, notification.WithDBFunc(database.FindWithError)),
//userNotificationSender: notification.NewUserNotificationSender(&msgRpcClient, notification.WithUserFunc(database.FindWithError)),
}
return nil
}
func init() {
if err := InitDB(); err != nil {
panic(err)
}
}
var userSrv *userServer
func TestName(t *testing.T) {
userID := strconv.Itoa(int(rand.Uint32()))
res, err := userSrv.UserRegister(ctx, &user.UserRegisterReq{
Secret: config.Config.Secret,
Users: []*sdkws.UserInfo{
{
UserID: userID,
Nickname: userID,
FaceURL: "",
Ex: "",
},
},
})
if err != nil {
panic(err)
}
t.Log(res)
}

@ -16,6 +16,7 @@ package tools
import ( import (
"context" "context"
"github.com/OpenIMSDK/protocol/sdkws"
"math/rand" "math/rand"
"time" "time"
@ -91,7 +92,11 @@ func (c *MsgTool) ConversationsDestructMsgs() {
} }
for i := 0; i < count; i++ { for i := 0; i < count; i++ {
pageNumber := rand.Int63() % maxPage pageNumber := rand.Int63() % maxPage
conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, int32(pageNumber), batchNum) pagination := &sdkws.RequestPagination{
PageNumber: int32(pageNumber),
ShowNumber: batchNum,
}
conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, pagination)
if err != nil { if err != nil {
log.ZError(ctx, "PageConversationIDs failed", err, "pageNumber", pageNumber) log.ZError(ctx, "PageConversationIDs failed", err, "pageNumber", pageNumber)
continue continue
@ -133,7 +138,7 @@ func (c *MsgTool) ConversationsDestructMsgs() {
continue continue
} }
if len(seqs) > 0 { if len(seqs) > 0 {
if err := c.conversationDatabase.UpdateUsersConversationFiled(ctx, []string{conversation.OwnerUserID}, conversation.ConversationID, map[string]interface{}{"latest_msg_destruct_time": now}); err != nil { if err := c.conversationDatabase.UpdateUsersConversationFiled(ctx, []string{conversation.OwnerUserID}, conversation.ConversationID, map[string]any{"latest_msg_destruct_time": now}); err != nil {
log.ZError(ctx, "updateUsersConversationFiled failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID) log.ZError(ctx, "updateUsersConversationFiled failed", err, "conversationID", conversation.ConversationID, "ownerUserID", conversation.OwnerUserID)
continue continue
} }

@ -17,6 +17,9 @@ package tools
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo"
tx2 "github.com/openimsdk/open-im-server/v3/pkg/common/db/tx"
"math" "math"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
@ -31,13 +34,11 @@ import (
"github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/mcontext" "github.com/OpenIMSDK/tools/mcontext"
"github.com/OpenIMSDK/tools/mw" "github.com/OpenIMSDK/tools/mw"
"github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/tools/utils" "github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/config" "github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller" "github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation" "github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification" "github.com/openimsdk/open-im-server/v3/pkg/rpcclient/notification"
@ -72,33 +73,48 @@ func InitMsgTool() (*MsgTool, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
db, err := relation.NewGormDB() discov, err := kdisc.NewDiscoveryRegister(config.Config.Envs.Discovery)
if err != nil { if err != nil {
return nil, err return nil, err
} }
discov, err := kdisc.NewDiscoveryRegister(config.Config.Envs.Discovery) discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
/* userDB, err := newmgo.NewUserMongo(mongo.GetDatabase())
discov, err := zookeeper.NewClient(config.Config.Zookeeper.ZkAddr, config.Config.Zookeeper.Schema, if err != nil {
zookeeper.WithFreq(time.Hour), zookeeper.WithRoundRobin(), zookeeper.WithUserNameAndPassword(config.Config.Zookeeper.Username, return nil, err
config.Config.Zookeeper.Password), zookeeper.WithTimeout(10), zookeeper.WithLogger(log.NewZkLogger()))*/ }
tx, err := tx2.NewAuto(context.Background(), mongo.GetClient())
if err != nil { if err != nil {
return nil, err return nil, err
} }
discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
userDB := relation.NewUserGorm(db)
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.NewGorm(db), tx,
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
}
conversationDB, err := newmgo.NewConversationMongo(mongo.GetDatabase())
if err != nil {
return nil, err
}
groupDatabase := controller.NewGroupDatabase(rdb, groupDB, groupMemberDB, groupRequestDB, tx, nil)
conversationDatabase := controller.NewConversationDatabase( conversationDatabase := controller.NewConversationDatabase(
relation.NewConversationGorm(db), conversationDB,
cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), relation.NewConversationGorm(db)), cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), conversationDB),
tx.NewGorm(db), tx,
) )
msgRpcClient := rpcclient.NewMessageRpcClient(discov) msgRpcClient := rpcclient.NewMessageRpcClient(discov)
msgNotificationSender := notification.NewMsgNotificationSender(rpcclient.WithRpcClient(&msgRpcClient)) msgNotificationSender := notification.NewMsgNotificationSender(rpcclient.WithRpcClient(&msgRpcClient))
@ -144,7 +160,11 @@ func (c *MsgTool) AllConversationClearMsgAndFixSeq() {
} }
for i := 0; i < count; i++ { for i := 0; i < count; i++ {
pageNumber := rand.Int63() % maxPage pageNumber := rand.Int63() % maxPage
conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, int32(pageNumber), batchNum) pagination := &sdkws.RequestPagination{
PageNumber: int32(pageNumber),
ShowNumber: batchNum,
}
conversationIDs, err := c.conversationDatabase.PageConversationIDs(ctx, pagination)
if err != nil { if err != nil {
log.ZError(ctx, "PageConversationIDs failed", err, "pageNumber", pageNumber) log.ZError(ctx, "PageConversationIDs failed", err, "pageNumber", pageNumber)
continue continue

@ -32,7 +32,7 @@ func (c *MsgTool) convertTools() {
for _, conversationID := range conversationIDs { for _, conversationID := range conversationIDs {
conversationIDs = append(conversationIDs, msgprocessor.GetNotificationConversationIDByConversationID(conversationID)) conversationIDs = append(conversationIDs, msgprocessor.GetNotificationConversationIDByConversationID(conversationID))
} }
userIDs, err := c.userDatabase.GetAllUserID(ctx, 0, 0) _, userIDs, err := c.userDatabase.GetAllUserID(ctx, nil)
if err != nil { if err != nil {
log.ZError(ctx, "get all user ids failed", err) log.ZError(ctx, "get all user ids failed", err)
return return

@ -36,7 +36,7 @@ type SendMsg struct {
SenderPlatformID int32 `json:"senderPlatformID"` SenderPlatformID int32 `json:"senderPlatformID"`
// Content is the actual content of the message, required and excluded from Swagger documentation. // Content is the actual content of the message, required and excluded from Swagger documentation.
Content map[string]interface{} `json:"content" binding:"required" swaggerignore:"true"` Content map[string]any `json:"content" binding:"required" swaggerignore:"true"`
// ContentType is an integer that represents the type of the content. // ContentType is an integer that represents the type of the content.
ContentType int32 `json:"contentType" binding:"required"` ContentType int32 `json:"contentType" binding:"required"`

@ -28,7 +28,7 @@ import (
) )
func Secret() jwt.Keyfunc { func Secret() jwt.Keyfunc {
return func(token *jwt.Token) (interface{}, error) { return func(token *jwt.Token) (any, error) {
return []byte(config.Config.Secret), nil return []byte(config.Config.Secret), nil
} }
} }
@ -55,7 +55,7 @@ func CheckAdmin(ctx context.Context) error {
return errs.ErrNoPermission.Wrap(fmt.Sprintf("user %s is not admin userID", mcontext.GetOpUserID(ctx))) return errs.ErrNoPermission.Wrap(fmt.Sprintf("user %s is not admin userID", mcontext.GetOpUserID(ctx)))
} }
func ParseRedisInterfaceToken(redisToken interface{}) (*tokenverify.Claims, error) { func ParseRedisInterfaceToken(redisToken any) (*tokenverify.Claims, error) {
return tokenverify.GetClaimFromToken(string(redisToken.([]uint8)), Secret()) return tokenverify.GetClaimFromToken(string(redisToken.([]uint8)), Secret())
} }

@ -71,7 +71,7 @@ func GetOptionsByNotification(cfg NotificationConf) msgprocessor.Options {
return opts return opts
} }
func initConfig(config interface{}, configName, configFolderPath string) error { func initConfig(config any, configName, configFolderPath string) error {
configFolderPath = filepath.Join(configFolderPath, configName) configFolderPath = filepath.Join(configFolderPath, configName)
_, err := os.Stat(configFolderPath) _, err := os.Stat(configFolderPath)
if err != nil { if err != nil {

@ -76,7 +76,7 @@ func TestGetOptionsByNotification(t *testing.T) {
func Test_initConfig(t *testing.T) { func Test_initConfig(t *testing.T) {
type args struct { type args struct {
config interface{} config any
configName string configName string
configFolderPath string configFolderPath string
} }

@ -16,6 +16,7 @@ package convert
import ( import (
"context" "context"
"fmt"
"github.com/OpenIMSDK/protocol/sdkws" "github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/utils" "github.com/OpenIMSDK/tools/utils"
@ -31,23 +32,22 @@ func FriendPb2DB(friend *sdkws.FriendInfo) *relation.FriendModel {
return dbFriend return dbFriend
} }
func FriendDB2Pb( func FriendDB2Pb(ctx context.Context, friendDB *relation.FriendModel,
ctx context.Context,
friendDB *relation.FriendModel,
getUsers func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error), getUsers func(ctx context.Context, userIDs []string) (map[string]*sdkws.UserInfo, error),
) (*sdkws.FriendInfo, error) { ) (*sdkws.FriendInfo, error) {
pbfriend := &sdkws.FriendInfo{FriendUser: &sdkws.UserInfo{}}
utils.CopyStructFields(pbfriend, friendDB)
users, err := getUsers(ctx, []string{friendDB.FriendUserID}) users, err := getUsers(ctx, []string{friendDB.FriendUserID})
if err != nil { if err != nil {
return nil, err return nil, err
} }
pbfriend.FriendUser.UserID = users[friendDB.FriendUserID].UserID user, ok := users[friendDB.FriendUserID]
pbfriend.FriendUser.Nickname = users[friendDB.FriendUserID].Nickname if !ok {
pbfriend.FriendUser.FaceURL = users[friendDB.FriendUserID].FaceURL return nil, fmt.Errorf("user not found: %s", friendDB.FriendUserID)
pbfriend.FriendUser.Ex = users[friendDB.FriendUserID].Ex }
pbfriend.CreateTime = friendDB.CreateTime.Unix()
return pbfriend, nil return &sdkws.FriendInfo{
FriendUser: user,
CreateTime: friendDB.CreateTime.Unix(),
}, nil
} }
func FriendsDB2Pb( func FriendsDB2Pb(
@ -118,3 +118,37 @@ func FriendRequestDB2Pb(
} }
return res, nil return res, nil
} }
// FriendPb2DBMap converts a FriendInfo protobuf object to a map suitable for database operations.
// It only includes non-zero or non-empty fields in the map.
func FriendPb2DBMap(friend *sdkws.FriendInfo) map[string]any {
if friend == nil {
return nil
}
val := make(map[string]any)
// Assuming FriendInfo has similar fields to those in FriendModel.
// Add or remove fields based on your actual FriendInfo and FriendModel structures.
if friend.FriendUser != nil {
if friend.FriendUser.UserID != "" {
val["friend_user_id"] = friend.FriendUser.UserID
}
if friend.FriendUser.Nickname != "" {
val["nickname"] = friend.FriendUser.Nickname
}
if friend.FriendUser.FaceURL != "" {
val["face_url"] = friend.FriendUser.FaceURL
}
if friend.FriendUser.Ex != "" {
val["ex"] = friend.FriendUser.Ex
}
}
if friend.CreateTime != 0 {
val["create_time"] = friend.CreateTime // You might need to convert this to a proper time format.
}
// Include other fields from FriendInfo as needed, similar to the above pattern.
return val
}

@ -22,29 +22,53 @@ import (
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
) )
func UsersDB2Pb(users []*relationtb.UserModel) (result []*sdkws.UserInfo) { func UsersDB2Pb(users []*relationtb.UserModel) []*sdkws.UserInfo {
result := make([]*sdkws.UserInfo, 0, len(users))
for _, user := range users { for _, user := range users {
var userPb sdkws.UserInfo userPb := &sdkws.UserInfo{
userPb.UserID = user.UserID UserID: user.UserID,
userPb.Nickname = user.Nickname Nickname: user.Nickname,
userPb.FaceURL = user.FaceURL FaceURL: user.FaceURL,
userPb.Ex = user.Ex Ex: user.Ex,
userPb.CreateTime = user.CreateTime.UnixMilli() CreateTime: user.CreateTime.UnixMilli(),
userPb.AppMangerLevel = user.AppMangerLevel AppMangerLevel: user.AppMangerLevel,
userPb.GlobalRecvMsgOpt = user.GlobalRecvMsgOpt GlobalRecvMsgOpt: user.GlobalRecvMsgOpt,
result = append(result, &userPb) }
result = append(result, userPb)
} }
return result return result
} }
func UserPb2DB(user *sdkws.UserInfo) *relationtb.UserModel { func UserPb2DB(user *sdkws.UserInfo) *relationtb.UserModel {
var userDB relationtb.UserModel return &relationtb.UserModel{
userDB.UserID = user.UserID UserID: user.UserID,
userDB.Nickname = user.Nickname Nickname: user.Nickname,
userDB.FaceURL = user.FaceURL FaceURL: user.FaceURL,
userDB.Ex = user.Ex Ex: user.Ex,
userDB.CreateTime = time.UnixMilli(user.CreateTime) CreateTime: time.UnixMilli(user.CreateTime),
userDB.AppMangerLevel = user.AppMangerLevel AppMangerLevel: user.AppMangerLevel,
userDB.GlobalRecvMsgOpt = user.GlobalRecvMsgOpt GlobalRecvMsgOpt: user.GlobalRecvMsgOpt,
return &userDB }
}
func UserPb2DBMap(user *sdkws.UserInfo) map[string]any {
if user == nil {
return nil
}
val := make(map[string]any)
fields := map[string]any{
"nickname": user.Nickname,
"face_url": user.FaceURL,
"ex": user.Ex,
"app_manager_level": user.AppMangerLevel,
"global_recv_msg_opt": user.GlobalRecvMsgOpt,
}
for key, value := range fields {
if v, ok := value.(string); ok && v != "" {
val[key] = v
} else if v, ok := value.(int32); ok && v != 0 {
val[key] = v
}
}
return val
} }

@ -0,0 +1,86 @@
// Copyright © 2023 OpenIM. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package convert
import (
"reflect"
"testing"
"github.com/OpenIMSDK/protocol/sdkws"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
func TestUsersDB2Pb(t *testing.T) {
type args struct {
users []*relationtb.UserModel
}
tests := []struct {
name string
args args
wantResult []*sdkws.UserInfo
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if gotResult := UsersDB2Pb(tt.args.users); !reflect.DeepEqual(gotResult, tt.wantResult) {
t.Errorf("UsersDB2Pb() = %v, want %v", gotResult, tt.wantResult)
}
})
}
}
func TestUserPb2DB(t *testing.T) {
type args struct {
user *sdkws.UserInfo
}
tests := []struct {
name string
args args
want *relationtb.UserModel
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := UserPb2DB(tt.args.user); !reflect.DeepEqual(got, tt.want) {
t.Errorf("UserPb2DB() = %v, want %v", got, tt.want)
}
})
}
}
func TestUserPb2DBMap(t *testing.T) {
user := &sdkws.UserInfo{
Nickname: "TestUser",
FaceURL: "http://openim.io/logo.jpg",
Ex: "Extra Data",
AppMangerLevel: 1,
GlobalRecvMsgOpt: 2,
}
expected := map[string]any{
"nickname": "TestUser",
"face_url": "http://openim.io/logo.jpg",
"ex": "Extra Data",
"app_manager_level": int32(1),
"global_recv_msg_opt": int32(2),
}
result := UserPb2DBMap(user)
if !reflect.DeepEqual(result, expected) {
t.Errorf("UserPb2DBMap returned unexpected map. Got %v, want %v", result, expected)
}
}

@ -26,7 +26,6 @@ import (
"github.com/OpenIMSDK/tools/utils" "github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
) )
@ -67,10 +66,10 @@ type ConversationCache interface {
GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error) GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error)
DelUserRecvMsgOpt(ownerUserID, conversationID string) ConversationCache DelUserRecvMsgOpt(ownerUserID, conversationID string) ConversationCache
// get one super group recv msg but do not notification userID list // get one super group recv msg but do not notification userID list
GetSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) (userIDs []string, err error) //GetSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) (userIDs []string, err error)
DelSuperGroupRecvMsgNotNotifyUserIDs(groupID string) ConversationCache DelSuperGroupRecvMsgNotNotifyUserIDs(groupID string) ConversationCache
// get one super group recv msg but do not notification userID list hash // get one super group recv msg but do not notification userID list hash
GetSuperGroupRecvMsgNotNotifyUserIDsHash(ctx context.Context, groupID string) (hash uint64, err error) //GetSuperGroupRecvMsgNotNotifyUserIDsHash(ctx context.Context, groupID string) (hash uint64, err error)
DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID string) ConversationCache DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID string) ConversationCache
//GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error) //GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error)
@ -101,20 +100,20 @@ type ConversationRedisCache struct {
expireTime time.Duration expireTime time.Duration
} }
func NewNewConversationRedis( //func NewNewConversationRedis(
rdb redis.UniversalClient, // rdb redis.UniversalClient,
conversationDB *relation.ConversationGorm, // conversationDB *relation.ConversationGorm,
options rockscache.Options, // options rockscache.Options,
) ConversationCache { //) ConversationCache {
rcClient := rockscache.NewClient(rdb, options) // rcClient := rockscache.NewClient(rdb, options)
//
return &ConversationRedisCache{ // return &ConversationRedisCache{
rcClient: rcClient, // rcClient: rcClient,
metaCache: NewMetaCacheRedis(rcClient), // metaCache: NewMetaCacheRedis(rcClient),
conversationDB: conversationDB, // conversationDB: conversationDB,
expireTime: conversationExpireTime, // expireTime: conversationExpireTime,
} // }
} //}
func (c *ConversationRedisCache) NewCache() ConversationCache { func (c *ConversationRedisCache) NewCache() ConversationCache {
return &ConversationRedisCache{ return &ConversationRedisCache{
@ -282,11 +281,11 @@ func (c *ConversationRedisCache) GetUserRecvMsgOpt(ctx context.Context, ownerUse
}) })
} }
func (c *ConversationRedisCache) GetSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) (userIDs []string, err error) { //func (c *ConversationRedisCache) GetSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) (userIDs []string, err error) {
return getCache(ctx, c.rcClient, c.getSuperGroupRecvNotNotifyUserIDsKey(groupID), c.expireTime, func(ctx context.Context) (userIDs []string, err error) { // return getCache(ctx, c.rcClient, c.getSuperGroupRecvNotNotifyUserIDsKey(groupID), c.expireTime, func(ctx context.Context) (userIDs []string, err error) {
return c.conversationDB.FindSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID) // return c.conversationDB.FindSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
}) // })
} //}
func (c *ConversationRedisCache) DelUsersConversation(conversationID string, ownerUserIDs ...string) ConversationCache { func (c *ConversationRedisCache) DelUsersConversation(conversationID string, ownerUserIDs ...string) ConversationCache {
keys := make([]string, 0, len(ownerUserIDs)) keys := make([]string, 0, len(ownerUserIDs))
@ -313,19 +312,19 @@ func (c *ConversationRedisCache) DelSuperGroupRecvMsgNotNotifyUserIDs(groupID st
return cache return cache
} }
func (c *ConversationRedisCache) GetSuperGroupRecvMsgNotNotifyUserIDsHash(ctx context.Context, groupID string) (hash uint64, err error) { //func (c *ConversationRedisCache) GetSuperGroupRecvMsgNotNotifyUserIDsHash(ctx context.Context, groupID string) (hash uint64, err error) {
return getCache(ctx, c.rcClient, c.getSuperGroupRecvNotNotifyUserIDsHashKey(groupID), c.expireTime, func(ctx context.Context) (hash uint64, err error) { // return getCache(ctx, c.rcClient, c.getSuperGroupRecvNotNotifyUserIDsHashKey(groupID), c.expireTime, func(ctx context.Context) (hash uint64, err error) {
userIDs, err := c.GetSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID) // userIDs, err := c.GetSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
if err != nil { // if err != nil {
return 0, err // return 0, err
} // }
utils.Sort(userIDs, true) // utils.Sort(userIDs, true)
bi := big.NewInt(0) // bi := big.NewInt(0)
bi.SetString(utils.Md5(strings.Join(userIDs, ";"))[0:8], 16) // bi.SetString(utils.Md5(strings.Join(userIDs, ";"))[0:8], 16)
return bi.Uint64(), nil // return bi.Uint64(), nil
}, // },
) // )
} //}
func (c *ConversationRedisCache) DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID string) ConversationCache { func (c *ConversationRedisCache) DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID string) ConversationCache {
cache := c.NewCache() cache := c.NewCache()

@ -33,19 +33,20 @@ const (
friendKey = "FRIEND_INFO:" friendKey = "FRIEND_INFO:"
) )
// args fn will exec when no data in msgCache. // FriendCache is an interface for caching friend-related data.
type FriendCache interface { type FriendCache interface {
metaCache metaCache
NewCache() FriendCache NewCache() FriendCache
GetFriendIDs(ctx context.Context, ownerUserID string) (friendIDs []string, err error) GetFriendIDs(ctx context.Context, ownerUserID string) (friendIDs []string, err error)
// call when friendID List changed // Called when friendID list changed
DelFriendIDs(ownerUserID ...string) FriendCache DelFriendIDs(ownerUserID ...string) FriendCache
// get single friendInfo from msgCache // Get single friendInfo from the cache
GetFriend(ctx context.Context, ownerUserID, friendUserID string) (friend *relationtb.FriendModel, err error) GetFriend(ctx context.Context, ownerUserID, friendUserID string) (friend *relationtb.FriendModel, err error)
// del friend when friend info changed // Delete friend when friend info changed
DelFriend(ownerUserID, friendUserID string) FriendCache DelFriend(ownerUserID, friendUserID string) FriendCache
} }
// FriendCacheRedis is an implementation of the FriendCache interface using Redis.
type FriendCacheRedis struct { type FriendCacheRedis struct {
metaCache metaCache
friendDB relationtb.FriendModelInterface friendDB relationtb.FriendModelInterface
@ -53,6 +54,7 @@ type FriendCacheRedis struct {
rcClient *rockscache.Client rcClient *rockscache.Client
} }
// NewFriendCacheRedis creates a new instance of FriendCacheRedis.
func NewFriendCacheRedis(rdb redis.UniversalClient, friendDB relationtb.FriendModelInterface, func NewFriendCacheRedis(rdb redis.UniversalClient, friendDB relationtb.FriendModelInterface,
options rockscache.Options) FriendCache { options rockscache.Options) FriendCache {
rcClient := rockscache.NewClient(rdb, options) rcClient := rockscache.NewClient(rdb, options)
@ -64,6 +66,7 @@ func NewFriendCacheRedis(rdb redis.UniversalClient, friendDB relationtb.FriendMo
} }
} }
// NewCache creates a new instance of FriendCacheRedis with the same configuration.
func (f *FriendCacheRedis) NewCache() FriendCache { func (f *FriendCacheRedis) NewCache() FriendCache {
return &FriendCacheRedis{ return &FriendCacheRedis{
rcClient: f.rcClient, rcClient: f.rcClient,
@ -73,24 +76,29 @@ func (f *FriendCacheRedis) NewCache() FriendCache {
} }
} }
// getFriendIDsKey returns the key for storing friend IDs in the cache.
func (f *FriendCacheRedis) getFriendIDsKey(ownerUserID string) string { func (f *FriendCacheRedis) getFriendIDsKey(ownerUserID string) string {
return friendIDsKey + ownerUserID return friendIDsKey + ownerUserID
} }
// getTwoWayFriendsIDsKey returns the key for storing two-way friend IDs in the cache.
func (f *FriendCacheRedis) getTwoWayFriendsIDsKey(ownerUserID string) string { func (f *FriendCacheRedis) getTwoWayFriendsIDsKey(ownerUserID string) string {
return TwoWayFriendsIDsKey + ownerUserID return TwoWayFriendsIDsKey + ownerUserID
} }
// getFriendKey returns the key for storing friend info in the cache.
func (f *FriendCacheRedis) getFriendKey(ownerUserID, friendUserID string) string { func (f *FriendCacheRedis) getFriendKey(ownerUserID, friendUserID string) string {
return friendKey + ownerUserID + "-" + friendUserID return friendKey + ownerUserID + "-" + friendUserID
} }
// GetFriendIDs retrieves friend IDs from the cache or the database if not found.
func (f *FriendCacheRedis) GetFriendIDs(ctx context.Context, ownerUserID string) (friendIDs []string, err error) { func (f *FriendCacheRedis) GetFriendIDs(ctx context.Context, ownerUserID string) (friendIDs []string, err error) {
return getCache(ctx, f.rcClient, f.getFriendIDsKey(ownerUserID), f.expireTime, func(ctx context.Context) ([]string, error) { return getCache(ctx, f.rcClient, f.getFriendIDsKey(ownerUserID), f.expireTime, func(ctx context.Context) ([]string, error) {
return f.friendDB.FindFriendUserIDs(ctx, ownerUserID) return f.friendDB.FindFriendUserIDs(ctx, ownerUserID)
}) })
} }
// DelFriendIDs deletes friend IDs from the cache.
func (f *FriendCacheRedis) DelFriendIDs(ownerUserIDs ...string) FriendCache { func (f *FriendCacheRedis) DelFriendIDs(ownerUserIDs ...string) FriendCache {
newGroupCache := f.NewCache() newGroupCache := f.NewCache()
keys := make([]string, 0, len(ownerUserIDs)) keys := make([]string, 0, len(ownerUserIDs))
@ -102,7 +110,7 @@ func (f *FriendCacheRedis) DelFriendIDs(ownerUserIDs ...string) FriendCache {
return newGroupCache return newGroupCache
} }
// todo. // GetTwoWayFriendIDs retrieves two-way friend IDs from the cache.
func (f *FriendCacheRedis) GetTwoWayFriendIDs(ctx context.Context, ownerUserID string) (twoWayFriendIDs []string, err error) { func (f *FriendCacheRedis) GetTwoWayFriendIDs(ctx context.Context, ownerUserID string) (twoWayFriendIDs []string, err error) {
friendIDs, err := f.GetFriendIDs(ctx, ownerUserID) friendIDs, err := f.GetFriendIDs(ctx, ownerUserID)
if err != nil { if err != nil {
@ -121,6 +129,7 @@ func (f *FriendCacheRedis) GetTwoWayFriendIDs(ctx context.Context, ownerUserID s
return twoWayFriendIDs, nil return twoWayFriendIDs, nil
} }
// DelTwoWayFriendIDs deletes two-way friend IDs from the cache.
func (f *FriendCacheRedis) DelTwoWayFriendIDs(ctx context.Context, ownerUserID string) FriendCache { func (f *FriendCacheRedis) DelTwoWayFriendIDs(ctx context.Context, ownerUserID string) FriendCache {
newFriendCache := f.NewCache() newFriendCache := f.NewCache()
newFriendCache.AddKeys(f.getTwoWayFriendsIDsKey(ownerUserID)) newFriendCache.AddKeys(f.getTwoWayFriendsIDsKey(ownerUserID))
@ -128,14 +137,15 @@ func (f *FriendCacheRedis) DelTwoWayFriendIDs(ctx context.Context, ownerUserID s
return newFriendCache return newFriendCache
} }
func (f *FriendCacheRedis) GetFriend(ctx context.Context, ownerUserID, // GetFriend retrieves friend info from the cache or the database if not found.
friendUserID string) (friend *relationtb.FriendModel, err error) { func (f *FriendCacheRedis) GetFriend(ctx context.Context, ownerUserID, friendUserID string) (friend *relationtb.FriendModel, err error) {
return getCache(ctx, f.rcClient, f.getFriendKey(ownerUserID, return getCache(ctx, f.rcClient, f.getFriendKey(ownerUserID,
friendUserID), f.expireTime, func(ctx context.Context) (*relationtb.FriendModel, error) { friendUserID), f.expireTime, func(ctx context.Context) (*relationtb.FriendModel, error) {
return f.friendDB.Take(ctx, ownerUserID, friendUserID) return f.friendDB.Take(ctx, ownerUserID, friendUserID)
}) })
} }
// DelFriend deletes friend info from the cache.
func (f *FriendCacheRedis) DelFriend(ownerUserID, friendUserID string) FriendCache { func (f *FriendCacheRedis) DelFriend(ownerUserID, friendUserID string) FriendCache {
newFriendCache := f.NewCache() newFriendCache := f.NewCache()
newFriendCache.AddKeys(f.getFriendKey(ownerUserID, friendUserID)) newFriendCache.AddKeys(f.getFriendKey(ownerUserID, friendUserID))

@ -16,6 +16,10 @@ package cache
import ( import (
"context" "context"
"fmt"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/errs"
"strconv"
"time" "time"
"github.com/OpenIMSDK/tools/log" "github.com/OpenIMSDK/tools/log"
@ -26,7 +30,6 @@ import (
"github.com/OpenIMSDK/tools/utils" "github.com/OpenIMSDK/tools/utils"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
unrelationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
) )
const ( const (
@ -35,12 +38,16 @@ const (
groupMemberIDsKey = "GROUP_MEMBER_IDS:" groupMemberIDsKey = "GROUP_MEMBER_IDS:"
groupMembersHashKey = "GROUP_MEMBERS_HASH2:" groupMembersHashKey = "GROUP_MEMBERS_HASH2:"
groupMemberInfoKey = "GROUP_MEMBER_INFO:" groupMemberInfoKey = "GROUP_MEMBER_INFO:"
joinedSuperGroupsKey = "JOIN_SUPER_GROUPS:" //groupOwnerInfoKey = "GROUP_OWNER_INFO:"
SuperGroupMemberIDsKey = "SUPER_GROUP_MEMBER_IDS:"
joinedGroupsKey = "JOIN_GROUPS_KEY:" joinedGroupsKey = "JOIN_GROUPS_KEY:"
groupMemberNumKey = "GROUP_MEMBER_NUM_CACHE:" groupMemberNumKey = "GROUP_MEMBER_NUM_CACHE:"
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
@ -48,11 +55,6 @@ type GroupCache interface {
GetGroupInfo(ctx context.Context, groupID string) (group *relationtb.GroupModel, err error) GetGroupInfo(ctx context.Context, groupID string) (group *relationtb.GroupModel, err error)
DelGroupsInfo(groupIDs ...string) GroupCache DelGroupsInfo(groupIDs ...string) GroupCache
GetJoinedSuperGroupIDs(ctx context.Context, userID string) (joinedSuperGroupIDs []string, err error)
DelJoinedSuperGroupIDs(userIDs ...string) GroupCache
GetSuperGroupMemberIDs(ctx context.Context, groupIDs ...string) (models []*unrelationtb.SuperGroupModel, err error)
DelSuperGroupMemberIDs(groupIDs ...string) GroupCache
GetGroupMembersHash(ctx context.Context, groupID string) (hashCode uint64, err error) GetGroupMembersHash(ctx context.Context, groupID string) (hashCode uint64, err error)
GetGroupMemberHashMap(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error) GetGroupMemberHashMap(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error)
DelGroupMembersHash(groupID string) GroupCache DelGroupMembersHash(groupID string) GroupCache
@ -69,9 +71,15 @@ type GroupCache interface {
GetGroupMembersInfo(ctx context.Context, groupID string, userID []string) (groupMembers []*relationtb.GroupMemberModel, err error) GetGroupMembersInfo(ctx context.Context, groupID string, userID []string) (groupMembers []*relationtb.GroupMemberModel, err error)
GetAllGroupMembersInfo(ctx context.Context, groupID string) (groupMembers []*relationtb.GroupMemberModel, err error) GetAllGroupMembersInfo(ctx context.Context, groupID string) (groupMembers []*relationtb.GroupMemberModel, err error)
GetGroupMembersPage(ctx context.Context, groupID string, userID []string, showNumber, pageNumber int32) (total uint32, groupMembers []*relationtb.GroupMemberModel, err error) GetGroupMembersPage(ctx context.Context, groupID string, userID []string, showNumber, pageNumber int32) (total uint32, groupMembers []*relationtb.GroupMemberModel, err error)
FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) ([]*relationtb.GroupMemberModel, error)
GetGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error)
GetGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error)
DelGroupRoleLevel(groupID string, roleLevel []int32) GroupCache
DelGroupAllRoleLevel(groupID string) GroupCache
DelGroupMembersInfo(groupID string, userID ...string) GroupCache DelGroupMembersInfo(groupID string, userID ...string) GroupCache
GetGroupRoleLevelMemberInfo(ctx context.Context, groupID string, roleLevel int32) ([]*relationtb.GroupMemberModel, error)
GetGroupRolesLevelMemberInfo(ctx context.Context, groupID string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error)
GetGroupMemberNum(ctx context.Context, groupID string) (memberNum int64, err error) GetGroupMemberNum(ctx context.Context, groupID string) (memberNum int64, err error)
DelGroupsMemberNum(groupID ...string) GroupCache DelGroupsMemberNum(groupID ...string) GroupCache
} }
@ -81,10 +89,9 @@ type GroupCacheRedis struct {
groupDB relationtb.GroupModelInterface groupDB relationtb.GroupModelInterface
groupMemberDB relationtb.GroupMemberModelInterface groupMemberDB relationtb.GroupMemberModelInterface
groupRequestDB relationtb.GroupRequestModelInterface groupRequestDB relationtb.GroupRequestModelInterface
mongoDB unrelationtb.SuperGroupModelInterface
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(
@ -92,8 +99,7 @@ func NewGroupCacheRedis(
groupDB relationtb.GroupModelInterface, groupDB relationtb.GroupModelInterface,
groupMemberDB relationtb.GroupMemberModelInterface, groupMemberDB relationtb.GroupMemberModelInterface,
groupRequestDB relationtb.GroupRequestModelInterface, groupRequestDB relationtb.GroupRequestModelInterface,
mongoClient unrelationtb.SuperGroupModelInterface, hashCode GroupHash,
hashCode func(ctx context.Context, groupID string) (uint64, error),
opts rockscache.Options, opts rockscache.Options,
) GroupCache { ) GroupCache {
rcClient := rockscache.NewClient(rdb, opts) rcClient := rockscache.NewClient(rdb, opts)
@ -101,8 +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,
mongoDB: mongoClient, groupHash: hashCode,
hashCode: hashCode,
metaCache: NewMetaCacheRedis(rcClient), metaCache: NewMetaCacheRedis(rcClient),
} }
} }
@ -114,7 +119,6 @@ func (g *GroupCacheRedis) NewCache() GroupCache {
groupDB: g.groupDB, groupDB: g.groupDB,
groupMemberDB: g.groupMemberDB, groupMemberDB: g.groupMemberDB,
groupRequestDB: g.groupRequestDB, groupRequestDB: g.groupRequestDB,
mongoDB: g.mongoDB,
metaCache: NewMetaCacheRedis(g.rcClient, g.metaCache.GetPreDelKeys()...), metaCache: NewMetaCacheRedis(g.rcClient, g.metaCache.GetPreDelKeys()...),
} }
} }
@ -123,18 +127,10 @@ func (g *GroupCacheRedis) getGroupInfoKey(groupID string) string {
return groupInfoKey + groupID return groupInfoKey + groupID
} }
func (g *GroupCacheRedis) getJoinedSuperGroupsIDKey(userID string) string {
return joinedSuperGroupsKey + userID
}
func (g *GroupCacheRedis) getJoinedGroupsKey(userID string) string { func (g *GroupCacheRedis) getJoinedGroupsKey(userID string) string {
return joinedGroupsKey + userID return joinedGroupsKey + userID
} }
func (g *GroupCacheRedis) getSuperGroupMemberIDsKey(groupID string) string {
return SuperGroupMemberIDsKey + groupID
}
func (g *GroupCacheRedis) getGroupMembersHashKey(groupID string) string { func (g *GroupCacheRedis) getGroupMembersHashKey(groupID string) string {
return groupMembersHashKey + groupID return groupMembersHashKey + groupID
} }
@ -151,6 +147,10 @@ func (g *GroupCacheRedis) getGroupMemberNumKey(groupID string) string {
return groupMemberNumKey + groupID return groupMemberNumKey + groupID
} }
func (g *GroupCacheRedis) getGroupRoleLevelMemberIDsKey(groupID string, roleLevel int32) string {
return groupRoleLevelMemberIDsKey + groupID + "-" + strconv.Itoa(int(roleLevel))
}
func (g *GroupCacheRedis) GetGroupIndex(group *relationtb.GroupModel, keys []string) (int, error) { func (g *GroupCacheRedis) GetGroupIndex(group *relationtb.GroupModel, keys []string) (int, error) {
key := g.getGroupInfoKey(group.GroupID) key := g.getGroupInfoKey(group.GroupID)
for i, _key := range keys { for i, _key := range keys {
@ -173,15 +173,7 @@ 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) {
//var keys []string
//for _, group := range groupIDs {
// keys = append(keys, g.getGroupInfoKey(group))
//}
//return batchGetCache(ctx, g.rcClient, keys, g.expireTime, g.GetGroupIndex, func(ctx context.Context) ([]*relationtb.GroupModel, error) {
// return g.groupDB.Find(ctx, groupIDs)
//})
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)
}, func(ctx context.Context, groupID string) (*relationtb.GroupModel, error) { }, func(ctx context.Context, groupID string) (*relationtb.GroupModel, error) {
@ -206,123 +198,44 @@ func (g *GroupCacheRedis) DelGroupsInfo(groupIDs ...string) GroupCache {
return newGroupCache return newGroupCache
} }
func (g *GroupCacheRedis) GetJoinedSuperGroupIDs(ctx context.Context, userID string) (joinedSuperGroupIDs []string, err error) { func (g *GroupCacheRedis) DelGroupsOwner(groupIDs ...string) GroupCache {
return getCache(ctx, g.rcClient, g.getJoinedSuperGroupsIDKey(userID), g.expireTime, func(ctx context.Context) ([]string, error) {
userGroup, err := g.mongoDB.GetSuperGroupByUserID(ctx, userID)
if err != nil {
return nil, err
}
return userGroup.GroupIDs, nil
},
)
}
func (g *GroupCacheRedis) GetSuperGroupMemberIDs(ctx context.Context, groupIDs ...string) (models []*unrelationtb.SuperGroupModel, err error) {
//var keys []string
//for _, group := range groupIDs {
// keys = append(keys, g.getSuperGroupMemberIDsKey(group))
//}
//return batchGetCache(ctx, g.rcClient, keys, g.expireTime, func(model *unrelationtb.SuperGroupModel, keys []string) (int, error) {
// for i, key := range keys {
// if g.getSuperGroupMemberIDsKey(model.GroupID) == key {
// return i, nil
// }
// }
// return 0, errIndex
//},
// func(ctx context.Context) ([]*unrelationtb.SuperGroupModel, error) {
// return g.mongoDB.FindSuperGroup(ctx, groupIDs)
// })
return batchGetCache2(ctx, g.rcClient, g.expireTime, groupIDs, func(groupID string) string {
return g.getSuperGroupMemberIDsKey(groupID)
}, func(ctx context.Context, groupID string) (*unrelationtb.SuperGroupModel, error) {
return g.mongoDB.TakeSuperGroup(ctx, groupID)
})
}
// userJoinSuperGroup.
func (g *GroupCacheRedis) DelJoinedSuperGroupIDs(userIDs ...string) GroupCache {
newGroupCache := g.NewCache() newGroupCache := g.NewCache()
keys := make([]string, 0, len(userIDs)) keys := make([]string, 0, len(groupIDs))
for _, userID := range userIDs { for _, groupID := range groupIDs {
keys = append(keys, g.getJoinedSuperGroupsIDKey(userID)) keys = append(keys, g.getGroupRoleLevelMemberIDsKey(groupID, constant.GroupOwner))
} }
newGroupCache.AddKeys(keys...) newGroupCache.AddKeys(keys...)
return newGroupCache return newGroupCache
} }
func (g *GroupCacheRedis) DelSuperGroupMemberIDs(groupIDs ...string) GroupCache { func (g *GroupCacheRedis) DelGroupRoleLevel(groupID string, roleLevels []int32) GroupCache {
newGroupCache := g.NewCache() newGroupCache := g.NewCache()
keys := make([]string, 0, len(groupIDs)) keys := make([]string, 0, len(roleLevels))
for _, groupID := range groupIDs { for _, roleLevel := range roleLevels {
keys = append(keys, g.getSuperGroupMemberIDsKey(groupID)) keys = append(keys, g.getGroupRoleLevelMemberIDsKey(groupID, roleLevel))
} }
newGroupCache.AddKeys(keys...) newGroupCache.AddKeys(keys...)
return newGroupCache return newGroupCache
} }
// groupMembersHash. func (g *GroupCacheRedis) DelGroupAllRoleLevel(groupID string) GroupCache {
return g.DelGroupRoleLevel(groupID, []int32{constant.GroupOwner, constant.GroupAdmin, constant.GroupOrdinaryUsers})
}
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)
}) })
//return getCache(ctx, g.rcClient, g.getGroupMembersHashKey(groupID), g.expireTime,
// func(ctx context.Context) (uint64, error) {
// userIDs, err := g.GetGroupMemberIDs(ctx, groupID)
// if err != nil {
// return 0, err
// }
// log.ZInfo(ctx, "GetGroupMembersHash", "groupID", groupID, "userIDs", userIDs)
// var members []*relationtb.GroupMemberModel
// if len(userIDs) > 0 {
// members, err = g.GetGroupMembersInfo(ctx, groupID, userIDs)
// if err != nil {
// return 0, err
// }
// utils.Sort(userIDs, true)
// }
// memberMap := make(map[string]*relationtb.GroupMemberModel)
// for i, member := range members {
// memberMap[member.UserID] = members[i]
// }
// data := make([]string, 0, len(members)*11)
// for _, userID := range userIDs {
// member, ok := memberMap[userID]
// if !ok {
// continue
// }
// data = append(data,
// member.GroupID,
// member.UserID,
// member.Nickname,
// member.FaceURL,
// strconv.Itoa(int(member.RoleLevel)),
// strconv.FormatInt(member.JoinTime.UnixMilli(), 10),
// strconv.Itoa(int(member.JoinSource)),
// member.InviterUserID,
// member.OperatorUserID,
// strconv.FormatInt(member.MuteEndTime.UnixMilli(), 10),
// member.Ex,
// )
// }
// log.ZInfo(ctx, "hash data info", "userIDs.len", len(userIDs), "hash.data.len", len(data))
// log.ZInfo(ctx, "json hash data", "groupID", groupID, "data", data)
// val, err := json.Marshal(data)
// if err != nil {
// return 0, err
// }
// sum := md5.Sum(val)
// code := binary.BigEndian.Uint64(sum[:])
// log.ZInfo(ctx, "GetGroupMembersHash", "groupID", groupID, "hashCode", code, "num", len(members))
// return code, nil
// },
//)
} }
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)
@ -347,7 +260,6 @@ func (g *GroupCacheRedis) DelGroupMembersHash(groupID string) GroupCache {
return cache return cache
} }
// groupMemberIDs.
func (g *GroupCacheRedis) GetGroupMemberIDs(ctx context.Context, groupID string) (groupMemberIDs []string, err error) { func (g *GroupCacheRedis) GetGroupMemberIDs(ctx context.Context, groupID string) (groupMemberIDs []string, err error) {
return getCache(ctx, g.rcClient, g.getGroupMemberIDsKey(groupID), g.expireTime, func(ctx context.Context) ([]string, error) { return getCache(ctx, g.rcClient, g.getGroupMemberIDsKey(groupID), g.expireTime, func(ctx context.Context) ([]string, error) {
return g.groupMemberDB.FindMemberUserID(ctx, groupID) return g.groupMemberDB.FindMemberUserID(ctx, groupID)
@ -398,13 +310,6 @@ func (g *GroupCacheRedis) GetGroupMemberInfo(ctx context.Context, groupID, userI
} }
func (g *GroupCacheRedis) GetGroupMembersInfo(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupMemberModel, error) { func (g *GroupCacheRedis) GetGroupMembersInfo(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupMemberModel, error) {
//var keys []string
//for _, userID := range userIDs {
// keys = append(keys, g.getGroupMemberInfoKey(groupID, userID))
//}
//return batchGetCache(ctx, g.rcClient, keys, g.expireTime, g.GetGroupMemberIndex, func(ctx context.Context) ([]*relationtb.GroupMemberModel, error) {
// return g.groupMemberDB.Find(ctx, []string{groupID}, userIDs, nil)
//})
return batchGetCache2(ctx, g.rcClient, g.expireTime, userIDs, func(userID string) string { return batchGetCache2(ctx, g.rcClient, g.expireTime, userIDs, func(userID string) string {
return g.getGroupMemberInfoKey(groupID, userID) return g.getGroupMemberInfoKey(groupID, userID)
}, func(ctx context.Context, userID string) (*relationtb.GroupMemberModel, error) { }, func(ctx context.Context, userID string) (*relationtb.GroupMemberModel, error) {
@ -412,12 +317,7 @@ func (g *GroupCacheRedis) GetGroupMembersInfo(ctx context.Context, groupID strin
}) })
} }
func (g *GroupCacheRedis) GetGroupMembersPage( func (g *GroupCacheRedis) GetGroupMembersPage(ctx context.Context, groupID string, userIDs []string, showNumber, pageNumber int32) (total uint32, groupMembers []*relationtb.GroupMemberModel, err error) {
ctx context.Context,
groupID string,
userIDs []string,
showNumber, pageNumber int32,
) (total uint32, groupMembers []*relationtb.GroupMemberModel, err error) {
groupMemberIDs, err := g.GetGroupMemberIDs(ctx, groupID) groupMemberIDs, err := g.GetGroupMemberIDs(ctx, groupID)
if err != nil { if err != nil {
return 0, nil, err return 0, nil, err
@ -446,13 +346,6 @@ func (g *GroupCacheRedis) GetAllGroupMemberInfo(ctx context.Context, groupID str
if err != nil { if err != nil {
return nil, err return nil, err
} }
//var keys []string
//for _, groupMemberID := range groupMemberIDs {
// keys = append(keys, g.getGroupMemberInfoKey(groupID, groupMemberID))
//}
//return batchGetCache(ctx, g.rcClient, keys, g.expireTime, g.GetGroupMemberIndex, func(ctx context.Context) ([]*relationtb.GroupMemberModel, error) {
// return g.groupMemberDB.Find(ctx, []string{groupID}, groupMemberIDs, nil)
//})
return g.GetGroupMembersInfo(ctx, groupID, groupMemberIDs) return g.GetGroupMembersInfo(ctx, groupID, groupMemberIDs)
} }
@ -483,3 +376,68 @@ func (g *GroupCacheRedis) DelGroupsMemberNum(groupID ...string) GroupCache {
return cache return cache
} }
func (g *GroupCacheRedis) GetGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) {
members, err := g.GetGroupRoleLevelMemberInfo(ctx, groupID, constant.GroupOwner)
if err != nil {
return nil, err
}
if len(members) == 0 {
return nil, errs.ErrRecordNotFound.Wrap(fmt.Sprintf("group %s owner not found", groupID))
}
return members[0], nil
}
func (g *GroupCacheRedis) GetGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error) {
members := make([]*relationtb.GroupMemberModel, 0, len(groupIDs))
for _, groupID := range groupIDs {
items, err := g.GetGroupRoleLevelMemberInfo(ctx, groupID, constant.GroupOwner)
if err != nil {
return nil, err
}
if len(items) > 0 {
members = append(members, items[0])
}
}
return members, nil
}
func (g *GroupCacheRedis) GetGroupRoleLevelMemberIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error) {
return getCache(ctx, g.rcClient, g.getGroupRoleLevelMemberIDsKey(groupID, roleLevel), g.expireTime, func(ctx context.Context) ([]string, error) {
return g.groupMemberDB.FindRoleLevelUserIDs(ctx, groupID, roleLevel)
})
}
func (g *GroupCacheRedis) GetGroupRoleLevelMemberInfo(ctx context.Context, groupID string, roleLevel int32) ([]*relationtb.GroupMemberModel, error) {
userIDs, err := g.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
if err != nil {
return nil, err
}
return g.GetGroupMembersInfo(ctx, groupID, userIDs)
}
func (g *GroupCacheRedis) GetGroupRolesLevelMemberInfo(ctx context.Context, groupID string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error) {
var userIDs []string
for _, roleLevel := range roleLevels {
ids, err := g.GetGroupRoleLevelMemberIDs(ctx, groupID, roleLevel)
if err != nil {
return nil, err
}
userIDs = append(userIDs, ids...)
}
return g.GetGroupMembersInfo(ctx, groupID, userIDs)
}
func (g *GroupCacheRedis) FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) (_ []*relationtb.GroupMemberModel, err error) {
if len(groupIDs) == 0 {
groupIDs, err = g.GetJoinedGroupIDs(ctx, userID)
if err != nil {
return nil, err
}
}
return batchGetCache2(ctx, g.rcClient, g.expireTime, groupIDs, func(groupID string) string {
return g.getGroupMemberInfoKey(groupID, userID)
}, func(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) {
return g.groupMemberDB.Take(ctx, groupID, userID)
})
}

@ -38,7 +38,7 @@ const (
var errIndex = errors.New("err index") var errIndex = errors.New("err index")
type metaCache interface { type metaCache interface {
ExecDel(ctx context.Context) error ExecDel(ctx context.Context, distinct ...bool) error
// delete key rapid // delete key rapid
DelKey(ctx context.Context, key string) error DelKey(ctx context.Context, key string) error
AddKeys(keys ...string) AddKeys(keys ...string)
@ -57,7 +57,10 @@ type metaCacheRedis struct {
retryInterval time.Duration retryInterval time.Duration
} }
func (m *metaCacheRedis) ExecDel(ctx context.Context) error { func (m *metaCacheRedis) ExecDel(ctx context.Context, distinct ...bool) error {
if len(distinct) > 0 && distinct[0] {
m.keys = utils.Distinct(m.keys)
}
if len(m.keys) > 0 { if len(m.keys) > 0 {
log.ZDebug(ctx, "delete cache", "keys", m.keys) log.ZDebug(ctx, "delete cache", "keys", m.keys)
for _, key := range m.keys { for _, key := range m.keys {

@ -287,7 +287,7 @@ func (c *msgCache) GetTokensWithoutError(ctx context.Context, userID string, pla
func (c *msgCache) SetTokenMapByUidPid(ctx context.Context, userID string, platform int, m map[string]int) error { func (c *msgCache) SetTokenMapByUidPid(ctx context.Context, userID string, platform int, m map[string]int) error {
key := uidPidToken + userID + ":" + constant.PlatformIDToName(platform) key := uidPidToken + userID + ":" + constant.PlatformIDToName(platform)
mm := make(map[string]interface{}) mm := make(map[string]any)
for k, v := range m { for k, v := range m {
mm[k] = v mm[k] = v
} }

@ -14,8 +14,8 @@ import (
type ObjectCache interface { type ObjectCache interface {
metaCache metaCache
GetName(ctx context.Context, name string) (*relationtb.ObjectModel, error) GetName(ctx context.Context, engine string, name string) (*relationtb.ObjectModel, error)
DelObjectName(names ...string) ObjectCache DelObjectName(engine string, names ...string) ObjectCache
} }
func NewObjectCacheRedis(rdb redis.UniversalClient, objDB relationtb.ObjectInfoModelInterface) ObjectCache { func NewObjectCacheRedis(rdb redis.UniversalClient, objDB relationtb.ObjectInfoModelInterface) ObjectCache {
@ -44,23 +44,23 @@ func (g *objectCacheRedis) NewCache() ObjectCache {
} }
} }
func (g *objectCacheRedis) DelObjectName(names ...string) ObjectCache { func (g *objectCacheRedis) DelObjectName(engine string, names ...string) ObjectCache {
objectCache := g.NewCache() objectCache := g.NewCache()
keys := make([]string, 0, len(names)) keys := make([]string, 0, len(names))
for _, name := range names { for _, name := range names {
keys = append(keys, g.getObjectKey(name)) keys = append(keys, g.getObjectKey(name, engine))
} }
objectCache.AddKeys(keys...) objectCache.AddKeys(keys...)
return objectCache return objectCache
} }
func (g *objectCacheRedis) getObjectKey(name string) string { func (g *objectCacheRedis) getObjectKey(engine string, name string) string {
return "OBJECT:" + name return "OBJECT:" + engine + ":" + name
} }
func (g *objectCacheRedis) GetName(ctx context.Context, name string) (*relationtb.ObjectModel, error) { func (g *objectCacheRedis) GetName(ctx context.Context, engine string, name string) (*relationtb.ObjectModel, error) {
return getCache(ctx, g.rcClient, g.getObjectKey(name), g.expireTime, func(ctx context.Context) (*relationtb.ObjectModel, error) { return getCache(ctx, g.rcClient, g.getObjectKey(name, engine), g.expireTime, func(ctx context.Context) (*relationtb.ObjectModel, error) {
return g.objDB.Take(ctx, name) return g.objDB.Take(ctx, engine, name)
}) })
} }

@ -18,6 +18,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"errors" "errors"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"hash/crc32" "hash/crc32"
"strconv" "strconv"
"time" "time"
@ -31,8 +32,6 @@ import (
"github.com/dtm-labs/rockscache" "github.com/dtm-labs/rockscache"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
) )
const ( const (
@ -60,6 +59,7 @@ type UserCache interface {
type UserCacheRedis struct { type UserCacheRedis struct {
metaCache metaCache
rdb redis.UniversalClient rdb redis.UniversalClient
//userDB relationtb.UserModelInterface
userDB relationtb.UserModelInterface userDB relationtb.UserModelInterface
expireTime time.Duration expireTime time.Duration
rcClient *rockscache.Client rcClient *rockscache.Client
@ -100,39 +100,13 @@ func (u *UserCacheRedis) getUserGlobalRecvMsgOptKey(userID string) string {
} }
func (u *UserCacheRedis) GetUserInfo(ctx context.Context, userID string) (userInfo *relationtb.UserModel, err error) { func (u *UserCacheRedis) GetUserInfo(ctx context.Context, userID string) (userInfo *relationtb.UserModel, err error) {
return getCache( return getCache(ctx, u.rcClient, u.getUserInfoKey(userID), u.expireTime, func(ctx context.Context) (*relationtb.UserModel, error) {
ctx,
u.rcClient,
u.getUserInfoKey(userID),
u.expireTime,
func(ctx context.Context) (*relationtb.UserModel, error) {
return u.userDB.Take(ctx, userID) return u.userDB.Take(ctx, userID)
}, },
) )
} }
func (u *UserCacheRedis) GetUsersInfo(ctx context.Context, userIDs []string) ([]*relationtb.UserModel, error) { func (u *UserCacheRedis) GetUsersInfo(ctx context.Context, userIDs []string) ([]*relationtb.UserModel, error) {
//var keys []string
//for _, userID := range userIDs {
// keys = append(keys, u.getUserInfoKey(userID))
//}
//return batchGetCache(
// ctx,
// u.rcClient,
// keys,
// u.expireTime,
// func(user *relationtb.UserModel, keys []string) (int, error) {
// for i, key := range keys {
// if key == u.getUserInfoKey(user.UserID) {
// return i, nil
// }
// }
// return 0, errIndex
// },
// func(ctx context.Context) ([]*relationtb.UserModel, error) {
// return u.userDB.Find(ctx, userIDs)
// },
//)
return batchGetCache2(ctx, u.rcClient, u.expireTime, userIDs, func(userID string) string { return batchGetCache2(ctx, u.rcClient, u.expireTime, userIDs, func(userID string) string {
return u.getUserInfoKey(userID) return u.getUserInfoKey(userID)
}, func(ctx context.Context, userID string) (*relationtb.UserModel, error) { }, func(ctx context.Context, userID string) (*relationtb.UserModel, error) {
@ -214,8 +188,7 @@ func (u *UserCacheRedis) SetUserStatus(ctx context.Context, userID string, statu
UserIDNum := crc32.ChecksumIEEE([]byte(userID)) UserIDNum := crc32.ChecksumIEEE([]byte(userID))
modKey := strconv.Itoa(int(UserIDNum % statusMod)) modKey := strconv.Itoa(int(UserIDNum % statusMod))
key := olineStatusKey + modKey key := olineStatusKey + modKey
log.ZDebug(ctx, "SetUserStatus args", "userID", userID, "status", status, log.ZDebug(ctx, "SetUserStatus args", "userID", userID, "status", status, "platformID", platformID, "modKey", modKey, "key", key)
"platformID", platformID, "modKey", modKey, "key", key)
isNewKey, err := u.rdb.Exists(ctx, key).Result() isNewKey, err := u.rdb.Exists(ctx, key).Result()
if err != nil { if err != nil {
return errs.Wrap(err) return errs.Wrap(err)

@ -16,6 +16,7 @@ package controller
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time" "time"
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor" "github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
@ -31,7 +32,7 @@ import (
type ConversationDatabase interface { type ConversationDatabase interface {
// UpdateUserConversationFiled 更新用户该会话的属性信息 // UpdateUserConversationFiled 更新用户该会话的属性信息
UpdateUsersConversationFiled(ctx context.Context, userIDs []string, conversationID string, args map[string]interface{}) error UpdateUsersConversationFiled(ctx context.Context, userIDs []string, conversationID string, args map[string]any) error
// CreateConversation 创建一批新的会话 // CreateConversation 创建一批新的会话
CreateConversation(ctx context.Context, conversations []*relationtb.ConversationModel) error CreateConversation(ctx context.Context, conversations []*relationtb.ConversationModel) error
// SyncPeerUserPrivateConversation 同步对端私聊会话内部保证事务操作 // SyncPeerUserPrivateConversation 同步对端私聊会话内部保证事务操作
@ -39,26 +40,26 @@ type ConversationDatabase interface {
// FindConversations 根据会话ID获取某个用户的多个会话 // FindConversations 根据会话ID获取某个用户的多个会话
FindConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*relationtb.ConversationModel, error) FindConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*relationtb.ConversationModel, error)
// FindRecvMsgNotNotifyUserIDs 获取超级大群开启免打扰的用户ID // FindRecvMsgNotNotifyUserIDs 获取超级大群开启免打扰的用户ID
FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) //FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
// GetUserAllConversation 获取一个用户在服务器上所有的会话 // GetUserAllConversation 获取一个用户在服务器上所有的会话
GetUserAllConversation(ctx context.Context, ownerUserID string) ([]*relationtb.ConversationModel, error) GetUserAllConversation(ctx context.Context, ownerUserID string) ([]*relationtb.ConversationModel, error)
// SetUserConversations 设置用户多个会话属性,如果会话不存在则创建,否则更新,内部保证原子性 // SetUserConversations 设置用户多个会话属性,如果会话不存在则创建,否则更新,内部保证原子性
SetUserConversations(ctx context.Context, ownerUserID string, conversations []*relationtb.ConversationModel) error SetUserConversations(ctx context.Context, ownerUserID string, conversations []*relationtb.ConversationModel) error
// SetUsersConversationFiledTx 设置多个用户会话关于某个字段的更新操作,如果会话不存在则创建,否则更新,内部保证事务操作 // SetUsersConversationFiledTx 设置多个用户会话关于某个字段的更新操作,如果会话不存在则创建,否则更新,内部保证事务操作
SetUsersConversationFiledTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, filedMap map[string]interface{}) error SetUsersConversationFiledTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, filedMap map[string]any) error
CreateGroupChatConversation(ctx context.Context, groupID string, userIDs []string) error CreateGroupChatConversation(ctx context.Context, groupID string, userIDs []string) error
GetConversationIDs(ctx context.Context, userID string) ([]string, error) GetConversationIDs(ctx context.Context, userID string) ([]string, error)
GetUserConversationIDsHash(ctx context.Context, ownerUserID string) (hash uint64, err error) GetUserConversationIDsHash(ctx context.Context, ownerUserID string) (hash uint64, err error)
GetAllConversationIDs(ctx context.Context) ([]string, error) GetAllConversationIDs(ctx context.Context) ([]string, error)
GetAllConversationIDsNumber(ctx context.Context) (int64, error) GetAllConversationIDsNumber(ctx context.Context) (int64, error)
PageConversationIDs(ctx context.Context, pageNumber, showNumber int32) (conversationIDs []string, err error) PageConversationIDs(ctx context.Context, pagination pagination.Pagination) (conversationIDs []string, err error)
//GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error) //GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error)
GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relationtb.ConversationModel, error) GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relationtb.ConversationModel, error)
GetConversationIDsNeedDestruct(ctx context.Context) ([]*relationtb.ConversationModel, error) GetConversationIDsNeedDestruct(ctx context.Context) ([]*relationtb.ConversationModel, error)
GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error) GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)
} }
func NewConversationDatabase(conversation relationtb.ConversationModelInterface, cache cache.ConversationCache, tx tx.Tx) ConversationDatabase { func NewConversationDatabase(conversation relationtb.ConversationModelInterface, cache cache.ConversationCache, tx tx.CtxTx) ConversationDatabase {
return &conversationDatabase{ return &conversationDatabase{
conversationDB: conversation, conversationDB: conversation,
cache: cache, cache: cache,
@ -69,22 +70,21 @@ func NewConversationDatabase(conversation relationtb.ConversationModelInterface,
type conversationDatabase struct { type conversationDatabase struct {
conversationDB relationtb.ConversationModelInterface conversationDB relationtb.ConversationModelInterface
cache cache.ConversationCache cache cache.ConversationCache
tx tx.Tx tx tx.CtxTx
} }
func (c *conversationDatabase) SetUsersConversationFiledTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, filedMap map[string]interface{}) (err error) { func (c *conversationDatabase) SetUsersConversationFiledTx(ctx context.Context, userIDs []string, conversation *relationtb.ConversationModel, filedMap map[string]any) (err error) {
return c.tx.Transaction(ctx, func(ctx context.Context) error {
cache := c.cache.NewCache() cache := c.cache.NewCache()
if conversation.GroupID != "" { if conversation.GroupID != "" {
cache = cache.DelSuperGroupRecvMsgNotNotifyUserIDs(conversation.GroupID).DelSuperGroupRecvMsgNotNotifyUserIDsHash(conversation.GroupID) cache = cache.DelSuperGroupRecvMsgNotNotifyUserIDs(conversation.GroupID).DelSuperGroupRecvMsgNotNotifyUserIDsHash(conversation.GroupID)
} }
if err := c.tx.Transaction(func(tx any) error { haveUserIDs, err := c.conversationDB.FindUserID(ctx, userIDs, []string{conversation.ConversationID})
conversationTx := c.conversationDB.NewTx(tx)
haveUserIDs, err := conversationTx.FindUserID(ctx, userIDs, []string{conversation.ConversationID})
if err != nil { if err != nil {
return err return err
} }
if len(haveUserIDs) > 0 { if len(haveUserIDs) > 0 {
_, err = conversationTx.UpdateByMap(ctx, haveUserIDs, conversation.ConversationID, filedMap) _, err = c.conversationDB.UpdateByMap(ctx, haveUserIDs, conversation.ConversationID, filedMap)
if err != nil { if err != nil {
return err return err
} }
@ -112,20 +112,17 @@ func (c *conversationDatabase) SetUsersConversationFiledTx(ctx context.Context,
conversations = append(conversations, temp) conversations = append(conversations, temp)
} }
if len(conversations) > 0 { if len(conversations) > 0 {
err = conversationTx.Create(ctx, conversations) err = c.conversationDB.Create(ctx, conversations)
if err != nil { if err != nil {
return err return err
} }
cache = cache.DelConversationIDs(NotUserIDs...).DelUserConversationIDsHash(NotUserIDs...).DelConversations(conversation.ConversationID, NotUserIDs...) cache = cache.DelConversationIDs(NotUserIDs...).DelUserConversationIDsHash(NotUserIDs...).DelConversations(conversation.ConversationID, NotUserIDs...)
} }
return nil
}); err != nil {
return err
}
return cache.ExecDel(ctx) return cache.ExecDel(ctx)
})
} }
func (c *conversationDatabase) UpdateUsersConversationFiled(ctx context.Context, userIDs []string, conversationID string, args map[string]interface{}) error { func (c *conversationDatabase) UpdateUsersConversationFiled(ctx context.Context, userIDs []string, conversationID string, args map[string]any) error {
_, err := c.conversationDB.UpdateByMap(ctx, userIDs, conversationID, args) _, err := c.conversationDB.UpdateByMap(ctx, userIDs, conversationID, args)
if err != nil { if err != nil {
return err return err
@ -153,19 +150,18 @@ func (c *conversationDatabase) CreateConversation(ctx context.Context, conversat
} }
func (c *conversationDatabase) SyncPeerUserPrivateConversationTx(ctx context.Context, conversations []*relationtb.ConversationModel) error { func (c *conversationDatabase) SyncPeerUserPrivateConversationTx(ctx context.Context, conversations []*relationtb.ConversationModel) error {
return c.tx.Transaction(ctx, func(ctx context.Context) error {
cache := c.cache.NewCache() cache := c.cache.NewCache()
if err := c.tx.Transaction(func(tx any) error {
conversationTx := c.conversationDB.NewTx(tx)
for _, conversation := range conversations { for _, conversation := range conversations {
for _, v := range [][2]string{{conversation.OwnerUserID, conversation.UserID}, {conversation.UserID, conversation.OwnerUserID}} { for _, v := range [][2]string{{conversation.OwnerUserID, conversation.UserID}, {conversation.UserID, conversation.OwnerUserID}} {
ownerUserID := v[0] ownerUserID := v[0]
userID := v[1] userID := v[1]
haveUserIDs, err := conversationTx.FindUserID(ctx, []string{ownerUserID}, []string{conversation.ConversationID}) haveUserIDs, err := c.conversationDB.FindUserID(ctx, []string{ownerUserID}, []string{conversation.ConversationID})
if err != nil { if err != nil {
return err return err
} }
if len(haveUserIDs) > 0 { if len(haveUserIDs) > 0 {
_, err := conversationTx.UpdateByMap(ctx, []string{ownerUserID}, conversation.ConversationID, map[string]interface{}{"is_private_chat": conversation.IsPrivateChat}) _, err := c.conversationDB.UpdateByMap(ctx, []string{ownerUserID}, conversation.ConversationID, map[string]any{"is_private_chat": conversation.IsPrivateChat})
if err != nil { if err != nil {
return err return err
} }
@ -176,18 +172,15 @@ func (c *conversationDatabase) SyncPeerUserPrivateConversationTx(ctx context.Con
newConversation.UserID = userID newConversation.UserID = userID
newConversation.ConversationID = conversation.ConversationID newConversation.ConversationID = conversation.ConversationID
newConversation.IsPrivateChat = conversation.IsPrivateChat newConversation.IsPrivateChat = conversation.IsPrivateChat
if err := conversationTx.Create(ctx, []*relationtb.ConversationModel{&newConversation}); err != nil { if err := c.conversationDB.Create(ctx, []*relationtb.ConversationModel{&newConversation}); err != nil {
return err return err
} }
cache = cache.DelConversationIDs(ownerUserID).DelUserConversationIDsHash(ownerUserID) cache = cache.DelConversationIDs(ownerUserID).DelUserConversationIDsHash(ownerUserID)
} }
} }
} }
return nil
}); err != nil {
return err
}
return cache.ExecDel(ctx) return cache.ExecDel(ctx)
})
} }
func (c *conversationDatabase) FindConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*relationtb.ConversationModel, error) { func (c *conversationDatabase) FindConversations(ctx context.Context, ownerUserID string, conversationIDs []string) ([]*relationtb.ConversationModel, error) {
@ -203,28 +196,26 @@ func (c *conversationDatabase) GetUserAllConversation(ctx context.Context, owner
} }
func (c *conversationDatabase) SetUserConversations(ctx context.Context, ownerUserID string, conversations []*relationtb.ConversationModel) error { func (c *conversationDatabase) SetUserConversations(ctx context.Context, ownerUserID string, conversations []*relationtb.ConversationModel) error {
return c.tx.Transaction(ctx, func(ctx context.Context) error {
cache := c.cache.NewCache() cache := c.cache.NewCache()
groupIDs := utils.Distinct(utils.Filter(conversations, func(e *relationtb.ConversationModel) (string, bool) { groupIDs := utils.Distinct(utils.Filter(conversations, func(e *relationtb.ConversationModel) (string, bool) {
return e.GroupID, e.GroupID != "" return e.GroupID, e.GroupID != ""
})) }))
for _, groupID := range groupIDs { for _, groupID := range groupIDs {
cache = cache.DelSuperGroupRecvMsgNotNotifyUserIDs(groupID).DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID) cache = cache.DelSuperGroupRecvMsgNotNotifyUserIDs(groupID).DelSuperGroupRecvMsgNotNotifyUserIDsHash(groupID)
} }
if err := c.tx.Transaction(func(tx any) error {
var conversationIDs []string var conversationIDs []string
for _, conversation := range conversations { for _, conversation := range conversations {
conversationIDs = append(conversationIDs, conversation.ConversationID) conversationIDs = append(conversationIDs, conversation.ConversationID)
cache = cache.DelConversations(conversation.OwnerUserID, conversation.ConversationID) cache = cache.DelConversations(conversation.OwnerUserID, conversation.ConversationID)
} }
conversationTx := c.conversationDB.NewTx(tx) existConversations, err := c.conversationDB.Find(ctx, ownerUserID, conversationIDs)
existConversations, err := conversationTx.Find(ctx, ownerUserID, conversationIDs)
if err != nil { if err != nil {
return err return err
} }
if len(existConversations) > 0 { if len(existConversations) > 0 {
for _, conversation := range conversations { for _, conversation := range conversations {
err = conversationTx.Update(ctx, conversation) err = c.conversationDB.Update(ctx, conversation)
if err != nil { if err != nil {
return err return err
} }
@ -248,21 +239,18 @@ func (c *conversationDatabase) SetUserConversations(ctx context.Context, ownerUs
} }
cache = cache.DelConversationIDs(ownerUserID).DelUserConversationIDsHash(ownerUserID).DelConversationNotReceiveMessageUserIDs(utils.Slice(notExistConversations, func(e *relationtb.ConversationModel) string { return e.ConversationID })...) cache = cache.DelConversationIDs(ownerUserID).DelUserConversationIDsHash(ownerUserID).DelConversationNotReceiveMessageUserIDs(utils.Slice(notExistConversations, func(e *relationtb.ConversationModel) string { return e.ConversationID })...)
} }
return nil
}); err != nil {
return err
}
return cache.ExecDel(ctx) return cache.ExecDel(ctx)
})
} }
func (c *conversationDatabase) FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) { //func (c *conversationDatabase) FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) {
return c.cache.GetSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID) // return c.cache.GetSuperGroupRecvMsgNotNotifyUserIDs(ctx, groupID)
} //}
func (c *conversationDatabase) CreateGroupChatConversation(ctx context.Context, groupID string, userIDs []string) error { func (c *conversationDatabase) CreateGroupChatConversation(ctx context.Context, groupID string, userIDs []string) error {
return c.tx.Transaction(ctx, func(ctx context.Context) error {
cache := c.cache.NewCache() cache := c.cache.NewCache()
conversationID := msgprocessor.GetConversationIDBySessionType(constant.SuperGroupChatType, groupID) conversationID := msgprocessor.GetConversationIDBySessionType(constant.SuperGroupChatType, groupID)
if err := c.tx.Transaction(func(tx any) error {
existConversationUserIDs, err := c.conversationDB.FindUserID(ctx, userIDs, []string{conversationID}) existConversationUserIDs, err := c.conversationDB.FindUserID(ctx, userIDs, []string{conversationID})
if err != nil { if err != nil {
return err return err
@ -281,18 +269,15 @@ func (c *conversationDatabase) CreateGroupChatConversation(ctx context.Context,
return err return err
} }
} }
_, err = c.conversationDB.UpdateByMap(ctx, existConversationUserIDs, conversationID, map[string]interface{}{"max_seq": 0}) _, err = c.conversationDB.UpdateByMap(ctx, existConversationUserIDs, conversationID, map[string]any{"max_seq": 0})
if err != nil { if err != nil {
return err return err
} }
for _, v := range existConversationUserIDs { for _, v := range existConversationUserIDs {
cache = cache.DelConversations(v, conversationID) cache = cache.DelConversations(v, conversationID)
} }
return nil return c.cache.ExecDel(ctx)
}); err != nil { })
return err
}
return cache.ExecDel(ctx)
} }
func (c *conversationDatabase) GetConversationIDs(ctx context.Context, userID string) ([]string, error) { func (c *conversationDatabase) GetConversationIDs(ctx context.Context, userID string) ([]string, error) {
@ -311,14 +296,10 @@ func (c *conversationDatabase) GetAllConversationIDsNumber(ctx context.Context)
return c.conversationDB.GetAllConversationIDsNumber(ctx) return c.conversationDB.GetAllConversationIDsNumber(ctx)
} }
func (c *conversationDatabase) PageConversationIDs(ctx context.Context, pageNumber, showNumber int32) ([]string, error) { func (c *conversationDatabase) PageConversationIDs(ctx context.Context, pagination pagination.Pagination) ([]string, error) {
return c.conversationDB.PageConversationIDs(ctx, pageNumber, showNumber) return c.conversationDB.PageConversationIDs(ctx, pagination)
} }
//func (c *conversationDatabase) GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (map[string]int64, error) {
// return c.cache.GetUserAllHasReadSeqs(ctx, ownerUserID)
//}
func (c *conversationDatabase) GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relationtb.ConversationModel, error) { func (c *conversationDatabase) GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relationtb.ConversationModel, error) {
return c.conversationDB.GetConversationsByConversationID(ctx, conversationIDs) return c.conversationDB.GetConversationsByConversationID(ctx, conversationIDs)
} }

@ -127,7 +127,7 @@ func (f *friendDatabase) AddFriendRequest(
} }
// 无错误 则更新 // 无错误 则更新
if err == nil { if err == nil {
m := make(map[string]interface{}, 1) m := make(map[string]any, 1)
m["handle_result"] = 0 m["handle_result"] = 0
m["handle_msg"] = "" m["handle_msg"] = ""
m["req_msg"] = reqMsg m["req_msg"] = reqMsg

@ -16,23 +16,17 @@ package controller
import ( import (
"context" "context"
"fmt"
"time"
"github.com/dtm-labs/rockscache" "github.com/dtm-labs/rockscache"
"github.com/redis/go-redis/v9" "github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"go.mongodb.org/mongo-driver/mongo" "time"
"gorm.io/gorm"
"github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/tx" "github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/tools/utils" "github.com/OpenIMSDK/tools/utils"
"github.com/redis/go-redis/v9"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
unrelationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
) )
type GroupDatabase interface { type GroupDatabase interface {
@ -40,23 +34,25 @@ type GroupDatabase interface {
CreateGroup(ctx context.Context, groups []*relationtb.GroupModel, groupMembers []*relationtb.GroupMemberModel) error CreateGroup(ctx context.Context, groups []*relationtb.GroupModel, groupMembers []*relationtb.GroupMemberModel) error
TakeGroup(ctx context.Context, groupID string) (group *relationtb.GroupModel, err error) TakeGroup(ctx context.Context, groupID string) (group *relationtb.GroupModel, err error)
FindGroup(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error) FindGroup(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error)
FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error) SearchGroup(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*relationtb.GroupModel, error)
SearchGroup(ctx context.Context, keyword string, pageNumber, showNumber int32) (uint32, []*relationtb.GroupModel, error)
UpdateGroup(ctx context.Context, groupID string, data map[string]any) error UpdateGroup(ctx context.Context, groupID string, data map[string]any) error
DismissGroup(ctx context.Context, groupID string, deleteMember bool) error // 解散群,并删除群成员 DismissGroup(ctx context.Context, groupID string, deleteMember bool) error // 解散群,并删除群成员
GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error)
// GroupMember
TakeGroupMember(ctx context.Context, groupID string, userID string) (groupMember *relationtb.GroupMemberModel, err error) TakeGroupMember(ctx context.Context, groupID string, userID string) (groupMember *relationtb.GroupMemberModel, err error)
TakeGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) TakeGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error)
FindGroupMember(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error) FindGroupMembers(ctx context.Context, groupID string, userIDs []string) (groupMembers []*relationtb.GroupMemberModel, err error) // *
FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) (groupMembers []*relationtb.GroupMemberModel, err error) // *
FindGroupMemberRoleLevels(ctx context.Context, groupID string, roleLevels []int32) (groupMembers []*relationtb.GroupMemberModel, err error) // *
FindGroupMemberAll(ctx context.Context, groupID string) (groupMembers []*relationtb.GroupMemberModel, err error) // *
FindGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error)
FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error) FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error)
FindGroupMemberNum(ctx context.Context, groupID string) (uint32, error) FindGroupMemberNum(ctx context.Context, groupID string) (uint32, error)
FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
PageGroupRequest(ctx context.Context, groupIDs []string, pageNumber, showNumber int32) (uint32, []*relationtb.GroupRequestModel, error) PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error)
PageGetJoinGroup(ctx context.Context, userID string, pageNumber, showNumber int32) (total uint32, totalGroupMembers []*relationtb.GroupMemberModel, err error) PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error)
PageGetGroupMember(ctx context.Context, groupID string, pageNumber, showNumber int32) (total uint32, totalGroupMembers []*relationtb.GroupMemberModel, err error) PageGetGroupMember(ctx context.Context, groupID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error)
SearchGroupMember(ctx context.Context, keyword string, groupIDs []string, userIDs []string, roleLevels []int32, pageNumber, showNumber int32) (uint32, []*relationtb.GroupMemberModel, error) SearchGroupMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (int64, []*relationtb.GroupMemberModel, error)
HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *relationtb.GroupMemberModel) error HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *relationtb.GroupMemberModel) error
DeleteGroupMember(ctx context.Context, groupID string, userIDs []string) error DeleteGroupMember(ctx context.Context, groupID string, userIDs []string) error
MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error) MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error)
@ -67,15 +63,8 @@ type GroupDatabase interface {
// GroupRequest // GroupRequest
CreateGroupRequest(ctx context.Context, requests []*relationtb.GroupRequestModel) error CreateGroupRequest(ctx context.Context, requests []*relationtb.GroupRequestModel) error
TakeGroupRequest(ctx context.Context, groupID string, userID string) (*relationtb.GroupRequestModel, error) TakeGroupRequest(ctx context.Context, groupID string, userID string) (*relationtb.GroupRequestModel, error)
FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (int64, []*relationtb.GroupRequestModel, error) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupRequestModel, error)
PageGroupRequestUser(ctx context.Context, userID string, pageNumber, showNumber int32) (uint32, []*relationtb.GroupRequestModel, error) PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error)
// SuperGroupModelInterface
FindSuperGroup(ctx context.Context, groupIDs []string) ([]*unrelationtb.SuperGroupModel, error)
FindJoinSuperGroup(ctx context.Context, userID string) ([]string, error)
CreateSuperGroup(ctx context.Context, groupID string, initMemberIDList []string) error
DeleteSuperGroup(ctx context.Context, groupID string) error
DeleteSuperGroupMember(ctx context.Context, groupID string, userIDs []string) error
CreateSuperGroupMember(ctx context.Context, groupID string, userIDs []string) error
// 获取群总数 // 获取群总数
CountTotal(ctx context.Context, before *time.Time) (count int64, err error) CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
@ -84,127 +73,105 @@ type GroupDatabase interface {
DeleteGroupMemberHash(ctx context.Context, groupIDs []string) error DeleteGroupMemberHash(ctx context.Context, groupIDs []string) error
} }
func NewGroupDatabase( func NewGroupDatabase(rdb redis.UniversalClient, groupDB relationtb.GroupModelInterface, groupMemberDB relationtb.GroupMemberModelInterface, groupRequestDB relationtb.GroupRequestModelInterface, ctxTx tx.CtxTx, groupHash cache.GroupHash) GroupDatabase {
group relationtb.GroupModelInterface,
member relationtb.GroupMemberModelInterface,
request relationtb.GroupRequestModelInterface,
tx tx.Tx,
ctxTx tx.CtxTx,
superGroup unrelationtb.SuperGroupModelInterface,
cache cache.GroupCache,
) GroupDatabase {
database := &groupDatabase{
groupDB: group,
groupMemberDB: member,
groupRequestDB: request,
tx: tx,
ctxTx: ctxTx,
cache: cache,
mongoDB: superGroup,
}
return database
}
func InitGroupDatabase(db *gorm.DB, rdb redis.UniversalClient, database *mongo.Database, hashCode func(ctx context.Context, groupID string) (uint64, error)) GroupDatabase {
rcOptions := rockscache.NewDefaultOptions() rcOptions := rockscache.NewDefaultOptions()
rcOptions.StrongConsistency = true rcOptions.StrongConsistency = true
rcOptions.RandomExpireAdjustment = 0.2 rcOptions.RandomExpireAdjustment = 0.2
return NewGroupDatabase( return &groupDatabase{
relation.NewGroupDB(db), groupDB: groupDB,
relation.NewGroupMemberDB(db), groupMemberDB: groupMemberDB,
relation.NewGroupRequest(db), groupRequestDB: groupRequestDB,
tx.NewGorm(db), ctxTx: ctxTx,
tx.NewMongo(database.Client()), cache: cache.NewGroupCacheRedis(rdb, groupDB, groupMemberDB, groupRequestDB, groupHash, rcOptions),
unrelation.NewSuperGroupMongoDriver(database), }
cache.NewGroupCacheRedis(
rdb,
relation.NewGroupDB(db),
relation.NewGroupMemberDB(db),
relation.NewGroupRequest(db),
unrelation.NewSuperGroupMongoDriver(database),
hashCode,
rcOptions,
),
)
} }
type groupDatabase struct { type groupDatabase struct {
groupDB relationtb.GroupModelInterface groupDB relationtb.GroupModelInterface
groupMemberDB relationtb.GroupMemberModelInterface groupMemberDB relationtb.GroupMemberModelInterface
groupRequestDB relationtb.GroupRequestModelInterface groupRequestDB relationtb.GroupRequestModelInterface
tx tx.Tx
ctxTx tx.CtxTx ctxTx tx.CtxTx
cache cache.GroupCache cache cache.GroupCache
mongoDB unrelationtb.SuperGroupModelInterface
} }
func (g *groupDatabase) GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error) { func (g *groupDatabase) FindGroupMembers(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupMemberModel, error) {
return g.groupDB.GetGroupIDsByGroupType(ctx, groupType) return g.cache.GetGroupMembersInfo(ctx, groupID, userIDs)
} }
func (g *groupDatabase) FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error) { func (g *groupDatabase) FindGroupMemberUser(ctx context.Context, groupIDs []string, userID string) ([]*relationtb.GroupMemberModel, error) {
return g.cache.GetGroupMemberIDs(ctx, groupID) return g.cache.FindGroupMemberUser(ctx, groupIDs, userID)
} }
func (g *groupDatabase) FindGroupMemberNum(ctx context.Context, groupID string) (uint32, error) { func (g *groupDatabase) FindGroupMemberRoleLevels(ctx context.Context, groupID string, roleLevels []int32) ([]*relationtb.GroupMemberModel, error) {
num, err := g.cache.GetGroupMemberNum(ctx, groupID) return g.cache.GetGroupRolesLevelMemberInfo(ctx, groupID, roleLevels)
if err != nil {
return 0, err
} }
return uint32(num), nil
func (g *groupDatabase) FindGroupMemberAll(ctx context.Context, groupID string) ([]*relationtb.GroupMemberModel, error) {
return g.cache.GetAllGroupMembersInfo(ctx, groupID)
} }
func (g *groupDatabase) CreateGroup( func (g *groupDatabase) FindGroupsOwner(ctx context.Context, groupIDs []string) ([]*relationtb.GroupMemberModel, error) {
ctx context.Context, return g.cache.GetGroupsOwner(ctx, groupIDs)
groups []*relationtb.GroupModel, }
groupMembers []*relationtb.GroupMemberModel,
) error { func (g *groupDatabase) CreateGroup(ctx context.Context, groups []*relationtb.GroupModel, groupMembers []*relationtb.GroupMemberModel) error {
cache := g.cache.NewCache() if len(groups)+len(groupMembers) == 0 {
if err := g.tx.Transaction(func(tx any) error { return nil
}
return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
c := g.cache.NewCache()
if len(groups) > 0 { if len(groups) > 0 {
if err := g.groupDB.NewTx(tx).Create(ctx, groups); err != nil { if err := g.groupDB.Create(ctx, groups); err != nil {
return err return err
} }
for _, group := range groups {
c = c.DelGroupsInfo(group.GroupID).
DelGroupMembersHash(group.GroupID).
DelGroupMembersHash(group.GroupID).
DelGroupsMemberNum(group.GroupID).
DelGroupMemberIDs(group.GroupID).
DelGroupAllRoleLevel(group.GroupID)
}
} }
if len(groupMembers) > 0 { if len(groupMembers) > 0 {
if err := g.groupMemberDB.NewTx(tx).Create(ctx, groupMembers); err != nil { if err := g.groupMemberDB.Create(ctx, groupMembers); err != nil {
return err return err
} }
for _, groupMember := range groupMembers {
c = c.DelGroupMembersHash(groupMember.GroupID).
DelGroupsMemberNum(groupMember.GroupID).
DelGroupMemberIDs(groupMember.GroupID).
DelJoinedGroupID(groupMember.UserID).
DelGroupMembersInfo(groupMember.GroupID, groupMember.UserID).
DelGroupAllRoleLevel(groupMember.GroupID)
}
} }
createGroupIDs := utils.DistinctAnyGetComparable(groups, func(group *relationtb.GroupModel) string { return c.ExecDel(ctx, true)
return group.GroupID
}) })
m := make(map[string]struct{})
for _, groupMember := range groupMembers {
if _, ok := m[groupMember.GroupID]; !ok {
m[groupMember.GroupID] = struct{}{}
cache = cache.DelGroupMemberIDs(groupMember.GroupID).DelGroupMembersHash(groupMember.GroupID).DelGroupsMemberNum(groupMember.GroupID)
} }
cache = cache.DelJoinedGroupID(groupMember.UserID).DelGroupMembersInfo(groupMember.GroupID, groupMember.UserID)
func (g *groupDatabase) FindGroupMemberUserID(ctx context.Context, groupID string) ([]string, error) {
return g.cache.GetGroupMemberIDs(ctx, groupID)
} }
cache = cache.DelGroupsInfo(createGroupIDs...)
return nil func (g *groupDatabase) FindGroupMemberNum(ctx context.Context, groupID string) (uint32, error) {
}); err != nil { num, err := g.cache.GetGroupMemberNum(ctx, groupID)
return err if err != nil {
return 0, err
} }
return cache.ExecDel(ctx) return uint32(num), nil
} }
func (g *groupDatabase) TakeGroup(ctx context.Context, groupID string) (group *relationtb.GroupModel, err error) { func (g *groupDatabase) TakeGroup(ctx context.Context, groupID string) (*relationtb.GroupModel, error) {
return g.cache.GetGroupInfo(ctx, groupID) return g.cache.GetGroupInfo(ctx, groupID)
} }
func (g *groupDatabase) FindGroup(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error) { func (g *groupDatabase) FindGroup(ctx context.Context, groupIDs []string) ([]*relationtb.GroupModel, error) {
return g.cache.GetGroupsInfo(ctx, groupIDs) return g.cache.GetGroupsInfo(ctx, groupIDs)
} }
func (g *groupDatabase) SearchGroup( func (g *groupDatabase) SearchGroup(ctx context.Context, keyword string, pagination pagination.Pagination) (int64, []*relationtb.GroupModel, error) {
ctx context.Context, return g.groupDB.Search(ctx, keyword, pagination)
keyword string,
pageNumber, showNumber int32,
) (uint32, []*relationtb.GroupModel, error) {
return g.groupDB.Search(ctx, keyword, pageNumber, showNumber)
} }
func (g *groupDatabase) UpdateGroup(ctx context.Context, groupID string, data map[string]any) error { func (g *groupDatabase) UpdateGroup(ctx context.Context, groupID string, data map[string]any) error {
@ -215,166 +182,97 @@ func (g *groupDatabase) UpdateGroup(ctx context.Context, groupID string, data ma
} }
func (g *groupDatabase) DismissGroup(ctx context.Context, groupID string, deleteMember bool) error { func (g *groupDatabase) DismissGroup(ctx context.Context, groupID string, deleteMember bool) error {
cache := g.cache.NewCache() return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
if err := g.tx.Transaction(func(tx any) error { c := g.cache.NewCache()
if err := g.groupDB.NewTx(tx).UpdateStatus(ctx, groupID, constant.GroupStatusDismissed); err != nil { if err := g.groupDB.UpdateState(ctx, groupID, constant.GroupStatusDismissed); err != nil {
return err return err
} }
if deleteMember { if deleteMember {
if err := g.groupMemberDB.NewTx(tx).DeleteGroup(ctx, []string{groupID}); err != nil {
return err
}
userIDs, err := g.cache.GetGroupMemberIDs(ctx, groupID) userIDs, err := g.cache.GetGroupMemberIDs(ctx, groupID)
if err != nil { if err != nil {
return err return err
} }
cache = cache.DelJoinedGroupID(userIDs...).DelGroupMemberIDs(groupID).DelGroupsMemberNum(groupID).DelGroupMembersHash(groupID) if err := g.groupMemberDB.Delete(ctx, groupID, nil); err != nil {
}
cache = cache.DelGroupsInfo(groupID)
return nil
}); err != nil {
return err return err
} }
return cache.ExecDel(ctx) c = c.DelJoinedGroupID(userIDs...).
DelGroupMemberIDs(groupID).
DelGroupsMemberNum(groupID).
DelGroupMembersHash(groupID).
DelGroupAllRoleLevel(groupID).
DelGroupMembersInfo(groupID, userIDs...)
}
return c.DelGroupsInfo(groupID).ExecDel(ctx)
})
} }
func (g *groupDatabase) TakeGroupMember( func (g *groupDatabase) TakeGroupMember(ctx context.Context, groupID string, userID string) (*relationtb.GroupMemberModel, error) {
ctx context.Context,
groupID string,
userID string,
) (groupMember *relationtb.GroupMemberModel, err error) {
return g.cache.GetGroupMemberInfo(ctx, groupID, userID) return g.cache.GetGroupMemberInfo(ctx, groupID, userID)
} }
func (g *groupDatabase) TakeGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) { func (g *groupDatabase) TakeGroupOwner(ctx context.Context, groupID string) (*relationtb.GroupMemberModel, error) {
return g.groupMemberDB.TakeOwner(ctx, groupID) // todo cache group owner return g.cache.GetGroupOwner(ctx, groupID)
} }
func (g *groupDatabase) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) { func (g *groupDatabase) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
return g.groupMemberDB.FindUserManagedGroupID(ctx, userID) return g.groupMemberDB.FindUserManagedGroupID(ctx, userID)
} }
func (g *groupDatabase) PageGroupRequest( func (g *groupDatabase) PageGroupRequest(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error) {
ctx context.Context, return g.groupRequestDB.PageGroup(ctx, groupIDs, pagination)
groupIDs []string,
pageNumber, showNumber int32,
) (uint32, []*relationtb.GroupRequestModel, error) {
return g.groupRequestDB.PageGroup(ctx, groupIDs, pageNumber, showNumber)
} }
func (g *groupDatabase) FindGroupMember(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) (totalGroupMembers []*relationtb.GroupMemberModel, err error) { func (g *groupDatabase) PageGetJoinGroup(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error) {
if len(groupIDs) == 0 && len(roleLevels) == 0 && len(userIDs) == 1 {
gIDs, err := g.cache.GetJoinedGroupIDs(ctx, userIDs[0])
if err != nil {
return nil, err
}
var res []*relationtb.GroupMemberModel
for _, groupID := range gIDs {
v, err := g.cache.GetGroupMemberInfo(ctx, groupID, userIDs[0])
if err != nil {
return nil, err
}
res = append(res, v)
}
return res, nil
}
if len(roleLevels) == 0 {
for _, groupID := range groupIDs {
groupMembers, err := g.cache.GetGroupMembersInfo(ctx, groupID, userIDs)
if err != nil {
return nil, err
}
totalGroupMembers = append(totalGroupMembers, groupMembers...)
}
return totalGroupMembers, nil
}
return g.groupMemberDB.Find(ctx, groupIDs, userIDs, roleLevels)
}
func (g *groupDatabase) PageGetJoinGroup(
ctx context.Context,
userID string,
pageNumber, showNumber int32,
) (total uint32, totalGroupMembers []*relationtb.GroupMemberModel, err error) {
groupIDs, err := g.cache.GetJoinedGroupIDs(ctx, userID) groupIDs, err := g.cache.GetJoinedGroupIDs(ctx, userID)
if err != nil { if err != nil {
return 0, nil, err return 0, nil, err
} }
for _, groupID := range utils.Paginate(groupIDs, int(pageNumber), int(showNumber)) { for _, groupID := range utils.Paginate(groupIDs, int(pagination.GetPageNumber()), int(pagination.GetShowNumber())) {
groupMembers, err := g.cache.GetGroupMembersInfo(ctx, groupID, []string{userID}) groupMembers, err := g.cache.GetGroupMembersInfo(ctx, groupID, []string{userID})
if err != nil { if err != nil {
return 0, nil, err return 0, nil, err
} }
totalGroupMembers = append(totalGroupMembers, groupMembers...) totalGroupMembers = append(totalGroupMembers, groupMembers...)
} }
return uint32(len(groupIDs)), totalGroupMembers, nil return int64(len(groupIDs)), totalGroupMembers, nil
} }
func (g *groupDatabase) PageGetGroupMember( func (g *groupDatabase) PageGetGroupMember(ctx context.Context, groupID string, pagination pagination.Pagination) (total int64, totalGroupMembers []*relationtb.GroupMemberModel, err error) {
ctx context.Context,
groupID string,
pageNumber, showNumber int32,
) (total uint32, totalGroupMembers []*relationtb.GroupMemberModel, err error) {
groupMemberIDs, err := g.cache.GetGroupMemberIDs(ctx, groupID) groupMemberIDs, err := g.cache.GetGroupMemberIDs(ctx, groupID)
if err != nil { if err != nil {
return 0, nil, err return 0, nil, err
} }
pageIDs := utils.Paginate(groupMemberIDs, int(pageNumber), int(showNumber)) pageIDs := utils.Paginate(groupMemberIDs, int(pagination.GetPageNumber()), int(pagination.GetShowNumber()))
if len(pageIDs) == 0 { if len(pageIDs) == 0 {
return uint32(len(groupMemberIDs)), nil, nil return int64(len(groupMemberIDs)), nil, nil
} }
members, err := g.cache.GetGroupMembersInfo(ctx, groupID, pageIDs) members, err := g.cache.GetGroupMembersInfo(ctx, groupID, pageIDs)
if err != nil { if err != nil {
return 0, nil, err return 0, nil, err
} }
return uint32(len(groupMemberIDs)), members, nil return int64(len(groupMemberIDs)), members, nil
} }
func (g *groupDatabase) SearchGroupMember( func (g *groupDatabase) SearchGroupMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (int64, []*relationtb.GroupMemberModel, error) {
ctx context.Context, return g.groupMemberDB.SearchMember(ctx, keyword, groupID, pagination)
keyword string,
groupIDs []string,
userIDs []string,
roleLevels []int32,
pageNumber, showNumber int32,
) (uint32, []*relationtb.GroupMemberModel, error) {
return g.groupMemberDB.SearchMember(ctx, keyword, groupIDs, userIDs, roleLevels, pageNumber, showNumber)
} }
func (g *groupDatabase) HandlerGroupRequest( func (g *groupDatabase) HandlerGroupRequest(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32, member *relationtb.GroupMemberModel) error {
ctx context.Context, return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
groupID string, if err := g.groupRequestDB.UpdateHandler(ctx, groupID, userID, handledMsg, handleResult); err != nil {
userID string,
handledMsg string,
handleResult int32,
member *relationtb.GroupMemberModel,
) error {
//cache := g.cache.NewCache()
//if err := g.tx.Transaction(func(tx any) error {
// if err := g.groupRequestDB.NewTx(tx).UpdateHandler(ctx, groupID, userID, handledMsg, handleResult); err != nil {
// return err
// }
// if member != nil {
// if err := g.groupMemberDB.NewTx(tx).Create(ctx, []*relationtb.GroupMemberModel{member}); err != nil {
// return err
// }
// cache = cache.DelGroupMembersHash(groupID).DelGroupMemberIDs(groupID).DelGroupsMemberNum(groupID).DelJoinedGroupID(member.UserID)
// }
// return nil
//}); err != nil {
// return err
//}
//return cache.ExecDel(ctx)
return g.tx.Transaction(func(tx any) error {
if err := g.groupRequestDB.NewTx(tx).UpdateHandler(ctx, groupID, userID, handledMsg, handleResult); err != nil {
return err return err
} }
if member != nil { if member != nil {
if err := g.groupMemberDB.NewTx(tx).Create(ctx, []*relationtb.GroupMemberModel{member}); err != nil { if err := g.groupMemberDB.Create(ctx, []*relationtb.GroupMemberModel{member}); err != nil {
return err return err
} }
if err := g.cache.NewCache().DelGroupMembersHash(groupID).DelGroupMembersInfo(groupID, member.UserID).DelGroupMemberIDs(groupID).DelGroupsMemberNum(groupID).DelJoinedGroupID(member.UserID).ExecDel(ctx); err != nil { c := g.cache.DelGroupMembersHash(groupID).
DelGroupMembersInfo(groupID, member.UserID).
DelGroupMemberIDs(groupID).
DelGroupsMemberNum(groupID).
DelJoinedGroupID(member.UserID).
DelGroupRoleLevel(groupID, []int32{member.RoleLevel})
if err := c.ExecDel(ctx); err != nil {
return err return err
} }
} }
@ -391,13 +289,11 @@ func (g *groupDatabase) DeleteGroupMember(ctx context.Context, groupID string, u
DelGroupsMemberNum(groupID). DelGroupsMemberNum(groupID).
DelJoinedGroupID(userIDs...). DelJoinedGroupID(userIDs...).
DelGroupMembersInfo(groupID, userIDs...). DelGroupMembersInfo(groupID, userIDs...).
DelGroupAllRoleLevel(groupID).
ExecDel(ctx) ExecDel(ctx)
} }
func (g *groupDatabase) MapGroupMemberUserID( func (g *groupDatabase) MapGroupMemberUserID(ctx context.Context, groupIDs []string) (map[string]*relationtb.GroupSimpleUserID, error) {
ctx context.Context,
groupIDs []string,
) (map[string]*relationtb.GroupSimpleUserID, error) {
return g.cache.GetGroupMemberHashMap(ctx, groupIDs) return g.cache.GetGroupMemberHashMap(ctx, groupIDs)
} }
@ -414,62 +310,54 @@ func (g *groupDatabase) MapGroupMemberNum(ctx context.Context, groupIDs []string
} }
func (g *groupDatabase) TransferGroupOwner(ctx context.Context, groupID string, oldOwnerUserID, newOwnerUserID string, roleLevel int32) error { func (g *groupDatabase) TransferGroupOwner(ctx context.Context, groupID string, oldOwnerUserID, newOwnerUserID string, roleLevel int32) error {
return g.tx.Transaction(func(tx any) error { return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
rowsAffected, err := g.groupMemberDB.NewTx(tx).UpdateRoleLevel(ctx, groupID, oldOwnerUserID, roleLevel) if err := g.groupMemberDB.UpdateRoleLevel(ctx, groupID, oldOwnerUserID, roleLevel); err != nil {
if err != nil {
return err return err
} }
if rowsAffected != 1 { if err := g.groupMemberDB.UpdateRoleLevel(ctx, groupID, newOwnerUserID, constant.GroupOwner); err != nil {
return utils.Wrap(fmt.Errorf("oldOwnerUserID %s rowsAffected = %d", oldOwnerUserID, rowsAffected), "")
}
rowsAffected, err = g.groupMemberDB.NewTx(tx).UpdateRoleLevel(ctx, groupID, newOwnerUserID, constant.GroupOwner)
if err != nil {
return err return err
} }
if rowsAffected != 1 { return g.cache.DelGroupMembersInfo(groupID, oldOwnerUserID, newOwnerUserID).
return utils.Wrap(fmt.Errorf("newOwnerUserID %s rowsAffected = %d", newOwnerUserID, rowsAffected), "") DelGroupAllRoleLevel(groupID).
} DelGroupMembersHash(groupID).ExecDel(ctx)
return g.cache.DelGroupMembersInfo(groupID, oldOwnerUserID, newOwnerUserID).DelGroupMembersHash(groupID).ExecDel(ctx)
}) })
} }
func (g *groupDatabase) UpdateGroupMember( func (g *groupDatabase) UpdateGroupMember(ctx context.Context, groupID string, userID string, data map[string]any) error {
ctx context.Context,
groupID string,
userID string,
data map[string]any,
) error {
if err := g.groupMemberDB.Update(ctx, groupID, userID, data); err != nil { if err := g.groupMemberDB.Update(ctx, groupID, userID, data); err != nil {
return err return err
} }
return g.cache.DelGroupMembersInfo(groupID, userID).ExecDel(ctx) c := g.cache.DelGroupMembersInfo(groupID, userID)
if g.groupMemberDB.IsUpdateRoleLevel(data) {
c = c.DelGroupAllRoleLevel(groupID)
}
return c.ExecDel(ctx)
} }
func (g *groupDatabase) UpdateGroupMembers(ctx context.Context, data []*relationtb.BatchUpdateGroupMember) error { func (g *groupDatabase) UpdateGroupMembers(ctx context.Context, data []*relationtb.BatchUpdateGroupMember) error {
cache := g.cache.NewCache() return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
if err := g.tx.Transaction(func(tx any) error { c := g.cache.NewCache()
for _, item := range data { for _, item := range data {
if err := g.groupMemberDB.NewTx(tx).Update(ctx, item.GroupID, item.UserID, item.Map); err != nil { if err := g.groupMemberDB.Update(ctx, item.GroupID, item.UserID, item.Map); err != nil {
return err return err
} }
cache = cache.DelGroupMembersInfo(item.GroupID, item.UserID) if g.groupMemberDB.IsUpdateRoleLevel(item.Map) {
c = c.DelGroupAllRoleLevel(item.GroupID)
} }
return nil c = c.DelGroupMembersInfo(item.GroupID, item.UserID).DelGroupMembersHash(item.GroupID)
}); err != nil {
return err
} }
return cache.ExecDel(ctx) return c.ExecDel(ctx, true)
})
} }
func (g *groupDatabase) CreateGroupRequest(ctx context.Context, requests []*relationtb.GroupRequestModel) error { func (g *groupDatabase) CreateGroupRequest(ctx context.Context, requests []*relationtb.GroupRequestModel) error {
return g.tx.Transaction(func(tx any) error { return g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
db := g.groupRequestDB.NewTx(tx)
for _, request := range requests { for _, request := range requests {
if err := db.Delete(ctx, request.GroupID, request.UserID); err != nil { if err := g.groupRequestDB.Delete(ctx, request.GroupID, request.UserID); err != nil {
return err return err
} }
} }
return db.Create(ctx, requests) return g.groupRequestDB.Create(ctx, requests)
}) })
} }
@ -481,65 +369,8 @@ func (g *groupDatabase) TakeGroupRequest(
return g.groupRequestDB.Take(ctx, groupID, userID) return g.groupRequestDB.Take(ctx, groupID, userID)
} }
func (g *groupDatabase) PageGroupRequestUser( func (g *groupDatabase) PageGroupRequestUser(ctx context.Context, userID string, pagination pagination.Pagination) (int64, []*relationtb.GroupRequestModel, error) {
ctx context.Context, return g.groupRequestDB.Page(ctx, userID, pagination)
userID string,
pageNumber, showNumber int32,
) (uint32, []*relationtb.GroupRequestModel, error) {
return g.groupRequestDB.Page(ctx, userID, pageNumber, showNumber)
}
func (g *groupDatabase) FindSuperGroup(
ctx context.Context,
groupIDs []string,
) (models []*unrelationtb.SuperGroupModel, err error) {
return g.cache.GetSuperGroupMemberIDs(ctx, groupIDs...)
}
func (g *groupDatabase) FindJoinSuperGroup(ctx context.Context, userID string) ([]string, error) {
return g.cache.GetJoinedSuperGroupIDs(ctx, userID)
}
func (g *groupDatabase) CreateSuperGroup(ctx context.Context, groupID string, initMemberIDs []string) error {
if err := g.mongoDB.CreateSuperGroup(ctx, groupID, initMemberIDs); err != nil {
return err
}
return g.cache.DelSuperGroupMemberIDs(groupID).DelJoinedSuperGroupIDs(initMemberIDs...).ExecDel(ctx)
}
func (g *groupDatabase) DeleteSuperGroup(ctx context.Context, groupID string) error {
cache := g.cache.NewCache()
if err := g.ctxTx.Transaction(ctx, func(ctx context.Context) error {
if err := g.mongoDB.DeleteSuperGroup(ctx, groupID); err != nil {
return err
}
models, err := g.cache.GetSuperGroupMemberIDs(ctx, groupID)
if err != nil {
return err
}
cache = cache.DelSuperGroupMemberIDs(groupID)
if len(models) > 0 {
cache = cache.DelJoinedSuperGroupIDs(models[0].MemberIDs...)
}
return nil
}); err != nil {
return err
}
return cache.ExecDel(ctx)
}
func (g *groupDatabase) DeleteSuperGroupMember(ctx context.Context, groupID string, userIDs []string) error {
if err := g.mongoDB.RemoverUserFromSuperGroup(ctx, groupID, userIDs); err != nil {
return err
}
return g.cache.DelSuperGroupMemberIDs(groupID).DelJoinedSuperGroupIDs(userIDs...).ExecDel(ctx)
}
func (g *groupDatabase) CreateSuperGroupMember(ctx context.Context, groupID string, userIDs []string) error {
if err := g.mongoDB.AddUserToSuperGroup(ctx, groupID, userIDs); err != nil {
return err
}
return g.cache.DelSuperGroupMemberIDs(groupID).DelJoinedSuperGroupIDs(userIDs...).ExecDel(ctx)
} }
func (g *groupDatabase) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) { func (g *groupDatabase) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
@ -550,14 +381,10 @@ func (g *groupDatabase) CountRangeEverydayTotal(ctx context.Context, start time.
return g.groupDB.CountRangeEverydayTotal(ctx, start, end) return g.groupDB.CountRangeEverydayTotal(ctx, start, end)
} }
func (g *groupDatabase) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (int64, []*relationtb.GroupRequestModel, error) { func (g *groupDatabase) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*relationtb.GroupRequestModel, error) {
return g.groupRequestDB.FindGroupRequests(ctx, groupID, userIDs) return g.groupRequestDB.FindGroupRequests(ctx, groupID, userIDs)
} }
func (g *groupDatabase) FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*relationtb.GroupModel, err error) {
return g.groupDB.FindNotDismissedGroup(ctx, groupIDs)
}
func (g *groupDatabase) DeleteGroupMemberHash(ctx context.Context, groupIDs []string) error { func (g *groupDatabase) DeleteGroupMemberHash(ctx context.Context, groupIDs []string) error {
if len(groupIDs) == 0 { if len(groupIDs) == 0 {
return nil return nil
@ -566,6 +393,5 @@ func (g *groupDatabase) DeleteGroupMemberHash(ctx context.Context, groupIDs []st
for _, groupID := range groupIDs { for _, groupID := range groupIDs {
c = c.DelGroupMembersHash(groupID) c = c.DelGroupMembersHash(groupID)
} }
return c.ExecDel(ctx) return c.ExecDel(ctx)
} }

@ -235,7 +235,7 @@ func Test_FindBySeq(t *testing.T) {
func TestName(t *testing.T) { func TestName(t *testing.T) {
db := GetDB() db := GetDB()
var seqs []int64 var seqs []int64
for i := int64(1); i <= 4; i++ { for i := int64(1); i <= 50; i++ {
seqs = append(seqs, i) seqs = append(seqs, i)
} }
msgs, err := db.getMsgBySeqsRange(context.Background(), "4931176757", "si_3866692501_4931176757", seqs, seqs[0], seqs[len(seqs)-1]) msgs, err := db.getMsgBySeqsRange(context.Background(), "4931176757", "si_3866692501_4931176757", seqs, seqs[0], seqs[len(seqs)-1])

@ -72,14 +72,15 @@ func (s *s3Database) CompleteMultipartUpload(ctx context.Context, uploadID strin
} }
func (s *s3Database) SetObject(ctx context.Context, info *relation.ObjectModel) error { func (s *s3Database) SetObject(ctx context.Context, info *relation.ObjectModel) error {
info.Engine = s.s3.Engine()
if err := s.db.SetObject(ctx, info); err != nil { if err := s.db.SetObject(ctx, info); err != nil {
return err return err
} }
return s.cache.DelObjectName(info.Name).ExecDel(ctx) return s.cache.DelObjectName(info.Engine, info.Name).ExecDel(ctx)
} }
func (s *s3Database) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (time.Time, string, error) { func (s *s3Database) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (time.Time, string, error) {
obj, err := s.cache.GetName(ctx, name) obj, err := s.cache.GetName(ctx, s.s3.Engine(), name)
if err != nil { if err != nil {
return time.Time{}, "", err return time.Time{}, "", err
} }

@ -16,12 +16,10 @@ package controller
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time" "time"
"gorm.io/gorm"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
dbimpl "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
) )
@ -31,20 +29,13 @@ type ThirdDatabase interface {
// about log for debug // about log for debug
UploadLogs(ctx context.Context, logs []*relation.Log) error UploadLogs(ctx context.Context, logs []*relation.Log) error
DeleteLogs(ctx context.Context, logID []string, userID string) error DeleteLogs(ctx context.Context, logID []string, userID string) error
SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pageNumber int32, showNumber int32) (uint32, []*relation.Log, error) SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*relation.Log, error)
GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*relation.Log, error) GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*relation.Log, error)
FindUsers(ctx context.Context, userIDs []string) ([]*relation.UserModel, error)
} }
type thirdDatabase struct { type thirdDatabase struct {
cache cache.MsgModel cache cache.MsgModel
logdb relation.LogInterface logdb relation.LogInterface
userdb relation.UserModelInterface
}
// FindUsers implements ThirdDatabase.
func (t *thirdDatabase) FindUsers(ctx context.Context, userIDs []string) ([]*relation.UserModel, error) {
return t.userdb.Find(ctx, userIDs)
} }
// DeleteLogs implements ThirdDatabase. // DeleteLogs implements ThirdDatabase.
@ -58,8 +49,8 @@ func (t *thirdDatabase) GetLogs(ctx context.Context, LogIDs []string, userID str
} }
// SearchLogs implements ThirdDatabase. // SearchLogs implements ThirdDatabase.
func (t *thirdDatabase) SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pageNumber int32, showNumber int32) (uint32, []*relation.Log, error) { func (t *thirdDatabase) SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*relation.Log, error) {
return t.logdb.Search(ctx, keyword, start, end, pageNumber, showNumber) return t.logdb.Search(ctx, keyword, start, end, pagination)
} }
// UploadLogs implements ThirdDatabase. // UploadLogs implements ThirdDatabase.
@ -67,8 +58,8 @@ func (t *thirdDatabase) UploadLogs(ctx context.Context, logs []*relation.Log) er
return t.logdb.Create(ctx, logs) return t.logdb.Create(ctx, logs)
} }
func NewThirdDatabase(cache cache.MsgModel, db *gorm.DB) ThirdDatabase { func NewThirdDatabase(cache cache.MsgModel, logdb relation.LogInterface) ThirdDatabase {
return &thirdDatabase{cache: cache, logdb: dbimpl.NewLogGorm(db), userdb: dbimpl.NewUserGorm(db)} return &thirdDatabase{cache: cache, logdb: logdb}
} }
func (t *thirdDatabase) FcmUpdateToken( func (t *thirdDatabase) FcmUpdateToken(

@ -16,6 +16,9 @@ package controller
import ( import (
"context" "context"
"github.com/OpenIMSDK/tools/tx"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time" "time"
"github.com/OpenIMSDK/protocol/user" "github.com/OpenIMSDK/protocol/user"
@ -23,11 +26,9 @@ import (
unrelationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation" unrelationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/unrelation"
"github.com/OpenIMSDK/tools/errs" "github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/tools/utils" "github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache" "github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
) )
type UserDatabase interface { type UserDatabase interface {
@ -38,15 +39,15 @@ type UserDatabase interface {
// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db // Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db
Create(ctx context.Context, users []*relation.UserModel) (err error) Create(ctx context.Context, users []*relation.UserModel) (err error)
// Update update (non-zero value) external guarantee userID exists // Update update (non-zero value) external guarantee userID exists
Update(ctx context.Context, user *relation.UserModel) (err error) //Update(ctx context.Context, user *relation.UserModel) (err error)
// UpdateByMap update (zero value) external guarantee userID exists // UpdateByMap update (zero value) external guarantee userID exists
UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error) UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error)
// Page If not found, no error is returned // Page If not found, no error is returned
Page(ctx context.Context, pageNumber, showNumber int32) (users []*relation.UserModel, count int64, err error) Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error)
// IsExist true as long as one exists // IsExist true as long as one exists
IsExist(ctx context.Context, userIDs []string) (exist bool, err error) IsExist(ctx context.Context, userIDs []string) (exist bool, err error)
// GetAllUserID Get all user IDs // GetAllUserID Get all user IDs
GetAllUserID(ctx context.Context, pageNumber, showNumber int32) ([]string, error) GetAllUserID(ctx context.Context, pagination pagination.Pagination) (int64, []string, error)
// InitOnce Inside the function, first query whether it exists in the db, if it exists, do nothing; if it does not exist, insert it // InitOnce Inside the function, first query whether it exists in the db, if it exists, do nothing; if it does not exist, insert it
InitOnce(ctx context.Context, users []*relation.UserModel) (err error) InitOnce(ctx context.Context, users []*relation.UserModel) (err error)
// CountTotal Get the total number of users // CountTotal Get the total number of users
@ -68,31 +69,45 @@ type UserDatabase interface {
} }
type userDatabase struct { type userDatabase struct {
tx tx.CtxTx
userDB relation.UserModelInterface userDB relation.UserModelInterface
cache cache.UserCache cache cache.UserCache
tx tx.Tx
mongoDB unrelationtb.UserModelInterface mongoDB unrelationtb.UserModelInterface
} }
func NewUserDatabase(userDB relation.UserModelInterface, cache cache.UserCache, tx tx.Tx, mongoDB unrelationtb.UserModelInterface) UserDatabase { func NewUserDatabase(userDB relation.UserModelInterface, cache cache.UserCache, tx tx.CtxTx, mongoDB unrelationtb.UserModelInterface) UserDatabase {
return &userDatabase{userDB: userDB, cache: cache, tx: tx, mongoDB: mongoDB} return &userDatabase{userDB: userDB, cache: cache, tx: tx, mongoDB: mongoDB}
} }
func (u *userDatabase) InitOnce(ctx context.Context, users []*relation.UserModel) (err error) {
func (u *userDatabase) InitOnce(ctx context.Context, users []*relation.UserModel) error {
// Extract user IDs from the given user models.
userIDs := utils.Slice(users, func(e *relation.UserModel) string { userIDs := utils.Slice(users, func(e *relation.UserModel) string {
return e.UserID return e.UserID
}) })
result, err := u.userDB.Find(ctx, userIDs)
// Find existing users in the database.
existingUsers, err := u.userDB.Find(ctx, userIDs)
if err != nil { if err != nil {
return err return err
} }
miss := utils.SliceAnySub(users, result, func(e *relation.UserModel) string { return e.UserID })
if len(miss) > 0 { // Determine which users are missing from the database.
_ = u.userDB.Create(ctx, miss) missingUsers := utils.SliceAnySub(users, existingUsers, func(e *relation.UserModel) string {
return e.UserID
})
// Create records for missing users.
if len(missingUsers) > 0 {
if err := u.userDB.Create(ctx, missingUsers); err != nil {
return err
}
} }
return nil return nil
} }
// FindWithError Get the information of the specified user and return an error if the userID is not found. // FindWithError Get the information of the specified user and return an error if the userID is not found.
func (u *userDatabase) FindWithError(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) { func (u *userDatabase) FindWithError(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) {
users, err = u.cache.GetUsersInfo(ctx, userIDs) users, err = u.cache.GetUsersInfo(ctx, userIDs)
@ -107,50 +122,42 @@ func (u *userDatabase) FindWithError(ctx context.Context, userIDs []string) (use
// Find Get the information of the specified user. If the userID is not found, no error will be returned. // Find Get the information of the specified user. If the userID is not found, no error will be returned.
func (u *userDatabase) Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) { func (u *userDatabase) Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) {
users, err = u.cache.GetUsersInfo(ctx, userIDs) return u.cache.GetUsersInfo(ctx, userIDs)
return
} }
// Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db. // Create Insert multiple external guarantees that the userID is not repeated and does not exist in the db.
func (u *userDatabase) Create(ctx context.Context, users []*relation.UserModel) (err error) { func (u *userDatabase) Create(ctx context.Context, users []*relation.UserModel) (err error) {
if err := u.tx.Transaction(func(tx any) error { return u.tx.Transaction(ctx, func(ctx context.Context) error {
err = u.userDB.Create(ctx, users) if err = u.userDB.Create(ctx, users); err != nil {
if err != nil {
return err return err
} }
return nil return u.cache.DelUsersInfo(utils.Slice(users, func(e *relation.UserModel) string {
}); err != nil { return e.UserID
return err })...).ExecDel(ctx)
} })
var userIDs []string
for _, user := range users {
userIDs = append(userIDs, user.UserID)
}
return u.cache.DelUsersInfo(userIDs...).ExecDel(ctx)
} }
// Update (non-zero value) externally guarantees that userID exists. //// Update (non-zero value) externally guarantees that userID exists.
func (u *userDatabase) Update(ctx context.Context, user *relation.UserModel) (err error) { //func (u *userDatabase) Update(ctx context.Context, user *relation.UserModel) (err error) {
if err := u.userDB.Update(ctx, user); err != nil { // if err := u.userDB.Update(ctx, user); err != nil {
return err // return err
} // }
return u.cache.DelUsersInfo(user.UserID).ExecDel(ctx) // return u.cache.DelUsersInfo(user.UserID).ExecDel(ctx)
} //}
// UpdateByMap update (zero value) externally guarantees that userID exists. // UpdateByMap update (zero value) externally guarantees that userID exists.
func (u *userDatabase) UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error) { func (u *userDatabase) UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error) {
return u.tx.Transaction(ctx, func(ctx context.Context) error {
if err := u.userDB.UpdateByMap(ctx, userID, args); err != nil { if err := u.userDB.UpdateByMap(ctx, userID, args); err != nil {
return err return err
} }
return u.cache.DelUsersInfo(userID).ExecDel(ctx) return u.cache.DelUsersInfo(userID).ExecDel(ctx)
})
} }
// Page Gets, returns no error if not found. // Page Gets, returns no error if not found.
func (u *userDatabase) Page( func (u *userDatabase) Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
ctx context.Context, return u.userDB.Page(ctx, pagination)
pageNumber, showNumber int32,
) (users []*relation.UserModel, count int64, err error) {
return u.userDB.Page(ctx, pageNumber, showNumber)
} }
// IsExist Does userIDs exist? As long as there is one, it will be true. // IsExist Does userIDs exist? As long as there is one, it will be true.
@ -166,8 +173,8 @@ func (u *userDatabase) IsExist(ctx context.Context, userIDs []string) (exist boo
} }
// GetAllUserID Get all user IDs. // GetAllUserID Get all user IDs.
func (u *userDatabase) GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error) { func (u *userDatabase) GetAllUserID(ctx context.Context, pagination pagination.Pagination) (total int64, userIDs []string, err error) {
return u.userDB.GetAllUserID(ctx, pageNumber, showNumber) return u.userDB.GetAllUserID(ctx, pagination)
} }
// CountTotal Get the total number of users. // CountTotal Get the total number of users.

@ -0,0 +1,129 @@
package newmgo
import (
"context"
"github.com/OpenIMSDK/protocol/constant"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo/mgotool"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"time"
)
func NewConversationMongo(db *mongo.Database) (*ConversationMgo, error) {
return &ConversationMgo{
coll: db.Collection("conversation"),
}, nil
}
type ConversationMgo struct {
coll *mongo.Collection
}
func (c *ConversationMgo) Create(ctx context.Context, conversations []*relation.ConversationModel) (err error) {
return mgotool.InsertMany(ctx, c.coll, conversations)
}
func (c *ConversationMgo) Delete(ctx context.Context, groupIDs []string) (err error) {
return mgotool.DeleteMany(ctx, c.coll, bson.M{"group_id": bson.M{"$in": groupIDs}})
}
func (c *ConversationMgo) UpdateByMap(ctx context.Context, userIDs []string, conversationID string, args map[string]any) (rows int64, err error) {
res, err := mgotool.UpdateMany(ctx, c.coll, bson.M{"owner_user_id": bson.M{"$in": userIDs}, "conversation_id": conversationID}, bson.M{"$set": args})
if err != nil {
return 0, err
}
return res.ModifiedCount, nil
}
func (c *ConversationMgo) Update(ctx context.Context, conversation *relation.ConversationModel) (err error) {
return mgotool.UpdateOne(ctx, c.coll, bson.M{"owner_user_id": conversation.OwnerUserID, "conversation_id": conversation.ConversationID}, bson.M{"$set": conversation}, true)
}
func (c *ConversationMgo) Find(ctx context.Context, ownerUserID string, conversationIDs []string) (conversations []*relation.ConversationModel, err error) {
return mgotool.Find[*relation.ConversationModel](ctx, c.coll, bson.M{"owner_user_id": ownerUserID, "conversation_id": bson.M{"$in": conversationIDs}})
}
func (c *ConversationMgo) FindUserID(ctx context.Context, userIDs []string, conversationIDs []string) ([]string, error) {
return mgotool.Find[string](ctx, c.coll, bson.M{"owner_user_id": bson.M{"$in": userIDs}, "conversation_id": bson.M{"$in": conversationIDs}}, options.Find().SetProjection(bson.M{"_id": 0, "owner_user_id": 1}))
}
func (c *ConversationMgo) FindUserIDAllConversationID(ctx context.Context, userID string) ([]string, error) {
return mgotool.Find[string](ctx, c.coll, bson.M{"owner_user_id": userID}, options.Find().SetProjection(bson.M{"_id": 0, "conversation_id": 1}))
}
func (c *ConversationMgo) Take(ctx context.Context, userID, conversationID string) (conversation *relation.ConversationModel, err error) {
return mgotool.FindOne[*relation.ConversationModel](ctx, c.coll, bson.M{"owner_user_id": userID, "conversation_id": conversationID})
}
func (c *ConversationMgo) FindConversationID(ctx context.Context, userID string, conversationIDs []string) (existConversationID []string, err error) {
return mgotool.Find[string](ctx, c.coll, bson.M{"owner_user_id": userID, "conversation_id": bson.M{"$in": conversationIDs}}, options.Find().SetProjection(bson.M{"_id": 0, "conversation_id": 1}))
}
func (c *ConversationMgo) FindUserIDAllConversations(ctx context.Context, userID string) (conversations []*relation.ConversationModel, err error) {
return mgotool.Find[*relation.ConversationModel](ctx, c.coll, bson.M{"owner_user_id": userID})
}
func (c *ConversationMgo) FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) {
return mgotool.Find[string](ctx, c.coll, bson.M{"group_id": groupID, "recv_msg_opt": constant.ReceiveNotNotifyMessage}, options.Find().SetProjection(bson.M{"_id": 0, "owner_user_id": 1}))
}
func (c *ConversationMgo) GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error) {
return mgotool.FindOne[int](ctx, c.coll, bson.M{"owner_user_id": ownerUserID, "conversation_id": conversationID}, options.FindOne().SetProjection(bson.M{"recv_msg_opt": 1}))
}
func (c *ConversationMgo) GetAllConversationIDs(ctx context.Context) ([]string, error) {
return mgotool.Aggregate[string](ctx, c.coll, []bson.M{
{"$group": bson.M{"_id": "$conversation_id"}},
{"$project": bson.M{"_id": 0, "conversation_id": "$_id"}},
})
}
func (c *ConversationMgo) GetAllConversationIDsNumber(ctx context.Context) (int64, error) {
counts, err := mgotool.Aggregate[int64](ctx, c.coll, []bson.M{
{"$group": bson.M{"_id": "$conversation_id"}},
{"$project": bson.M{"_id": 0, "conversation_id": "$_id"}},
})
if err != nil {
return 0, err
}
if len(counts) == 0 {
return 0, nil
}
return counts[0], nil
}
func (c *ConversationMgo) PageConversationIDs(ctx context.Context, pagination pagination.Pagination) (conversationIDs []string, err error) {
return mgotool.FindPageOnly[string](ctx, c.coll, bson.M{}, pagination, options.Find().SetProjection(bson.M{"conversation_id": 1}))
}
func (c *ConversationMgo) GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*relation.ConversationModel, error) {
return mgotool.Find[*relation.ConversationModel](ctx, c.coll, bson.M{"conversation_id": bson.M{"$in": conversationIDs}})
}
func (c *ConversationMgo) GetConversationIDsNeedDestruct(ctx context.Context) ([]*relation.ConversationModel, error) {
//"is_msg_destruct = 1 && msg_destruct_time != 0 && (UNIX_TIMESTAMP(NOW()) > (msg_destruct_time + UNIX_TIMESTAMP(latest_msg_destruct_time)) || latest_msg_destruct_time is NULL)"
return mgotool.Find[*relation.ConversationModel](ctx, c.coll, bson.M{
"is_msg_destruct": 1,
"msg_destruct_time": bson.M{"$ne": 0},
"$or": []bson.M{
{
"$expr": bson.M{
"$gt": []any{
time.Now(),
bson.M{"$add": []any{"$msg_destruct_time", "$latest_msg_destruct_time"}},
},
},
},
{
"latest_msg_destruct_time": nil,
},
},
})
}
func (c *ConversationMgo) GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error) {
return mgotool.Find[string](ctx, c.coll, bson.M{"conversation_id": conversationID, "recv_msg_opt": bson.M{"$ne": constant.ReceiveMessage}}, options.Find().SetProjection(bson.M{"_id": 0, "owner_user_id": 1}))
}

@ -0,0 +1,169 @@
package newmgo
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo/mgotool"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
// FriendMgo implements FriendModelInterface using MongoDB as the storage backend.
type FriendMgo struct {
coll *mongo.Collection
}
// NewFriendMongo creates a new instance of FriendMgo with the provided MongoDB database.
func NewFriendMongo(db *mongo.Database) (relation.FriendModelInterface, error) {
return &FriendMgo{
coll: db.Collection(relation.FriendModelCollectionName),
}, nil
}
// Create inserts multiple friend records.
func (f *FriendMgo) Create(ctx context.Context, friends []*relation.FriendModel) error {
return mgotool.InsertMany(ctx, f.coll, friends)
}
// Delete removes specified friends of the owner user.
func (f *FriendMgo) Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) error {
filter := bson.M{
"owner_user_id": ownerUserID,
"friend_user_id": bson.M{"$in": friendUserIDs},
}
_, err := f.coll.DeleteMany(ctx, filter)
if err != nil {
return err
}
return nil
}
// UpdateByMap updates specific fields of a friend document using a map.
func (f *FriendMgo) UpdateByMap(ctx context.Context, ownerUserID string, friendUserID string, args map[string]interface{}) error {
if len(args) == 0 {
return nil
}
filter := bson.M{
"owner_user_id": ownerUserID,
"friend_user_id": friendUserID,
}
update := bson.M{"$set": args}
err := mgotool.UpdateOne(ctx, f.coll, filter, update, true)
if err != nil {
return err
}
return nil
}
// Update modifies multiple friend documents.
// func (f *FriendMgo) Update(ctx context.Context, friends []*relation.FriendModel) error {
// filter := bson.M{
// "owner_user_id": ownerUserID,
// "friend_user_id": friendUserID,
// }
// return mgotool.UpdateMany(ctx, f.coll, filter, friends)
// }
// UpdateRemark updates the remark for a specific friend.
func (f *FriendMgo) UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) error {
args := map[string]interface{}{"remark": remark}
return f.UpdateByMap(ctx, ownerUserID, friendUserID, args)
}
// Take retrieves a single friend document. Returns an error if not found.
func (f *FriendMgo) Take(ctx context.Context, ownerUserID, friendUserID string) (*relation.FriendModel, error) {
filter := bson.M{
"owner_user_id": ownerUserID,
"friend_user_id": friendUserID,
}
friend, err := mgotool.FindOne[*relation.FriendModel](ctx, f.coll, filter)
if err != nil {
return nil, err
}
return friend, nil
}
// FindUserState finds the friendship status between two users.
func (f *FriendMgo) FindUserState(ctx context.Context, userID1, userID2 string) ([]*relation.FriendModel, error) {
filter := bson.M{
"$or": []bson.M{
{"owner_user_id": userID1, "friend_user_id": userID2},
{"owner_user_id": userID2, "friend_user_id": userID1},
},
}
friends, err := mgotool.Find[*relation.FriendModel](ctx, f.coll, filter)
if err != nil {
return nil, err
}
return friends, nil
}
// FindFriends retrieves a list of friends for a given owner. Missing friends do not cause an error.
func (f *FriendMgo) FindFriends(ctx context.Context, ownerUserID string, friendUserIDs []string) ([]*relation.FriendModel, error) {
filter := bson.M{
"owner_user_id": ownerUserID,
"friend_user_id": bson.M{"$in": friendUserIDs},
}
friends, err := mgotool.Find[*relation.FriendModel](ctx, f.coll, filter)
if err != nil {
return nil, err
}
return friends, nil
}
// FindReversalFriends finds users who have added the specified user as a friend.
func (f *FriendMgo) FindReversalFriends(ctx context.Context, friendUserID string, ownerUserIDs []string) ([]*relation.FriendModel, error) {
filter := bson.M{
"owner_user_id": bson.M{"$in": ownerUserIDs},
"friend_user_id": friendUserID,
}
friends, err := mgotool.Find[*relation.FriendModel](ctx, f.coll, filter)
if err != nil {
return nil, err
}
return friends, nil
}
// FindOwnerFriends retrieves a paginated list of friends for a given owner.
func (f *FriendMgo) FindOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination, showNumber int32) ([]*relation.FriendModel, int64, error) {
filter := bson.M{"owner_user_id": ownerUserID}
count, friends, err := mgotool.FindPage[*relation.FriendModel](ctx, f.coll, filter, pagination)
if err != nil {
return nil, 0, err
}
return friends, count, nil
}
// FindInWhoseFriends finds users who have added the specified user as a friend, with pagination.
func (f *FriendMgo) FindInWhoseFriends(ctx context.Context, friendUserID string, pagination.Pagination, showNumber int32) ([]*relation.FriendModel, int64, error) {
filter := bson.M{"friend_user_id": friendUserID}
count, friends, err := mgotool.FindPage[*relation.FriendModel](ctx, f.coll, filter, pagination)
if err != nil {
return nil, 0, err
}
return friends, count, nil
}
// FindFriendUserIDs retrieves a list of friend user IDs for a given owner.
func (f *FriendMgo) FindFriendUserIDs(ctx context.Context, ownerUserID string) ([]string, error) {
filter := bson.M{"owner_user_id": ownerUserID}
friends := []*relation.FriendModel{}
friends, err := mgotool.Find[*relation.FriendModel](ctx, f.coll, filter)
if err != nil {
return nil, err
}
friendUserIDs := make([]string, len(friends))
for i, friend := range friends {
friendUserIDs[i] = friend.FriendUserID
}
return friendUserIDs, nil
}
// NewTx creates a new transaction.
func (f *FriendMgo) NewTx(tx any) relation.FriendModelInterface {
panic("not implemented")
return nil
}

@ -0,0 +1,48 @@
package newmgo
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo/mgotool"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
type FriendRequestMgo struct {
coll *mongo.Collection
}
func NewFriendRequestMongo(db *mongo.Database) (relation.FriendRequestModelInterface, error) {
return &FriendRequestMgo{
coll: db.Collection(relation.FriendRequestModelCollectionName),
}, nil
}
func (f *FriendRequestMgo) Create(ctx context.Context, friendRequests []*relation.FriendRequestModel) error {
return mgotool.InsertMany(ctx, f.coll, friendRequests)
}
func (f *FriendRequestMgo) Delete(ctx context.Context, fromUserID, toUserID string) (err error) {
return mgotool.Delete[*relation.FriendRequestModel](ctx, f.coll, bson.M{"from_user_id": fromUserID, "to_user_id": toUserID})
}
func (f *FriendRequestMgo) UpdateByMap(ctx context.Context, formUserID, toUserID string, args map[string]any) (err error) {
if len(args) == 0 {
return nil
}
return mgotool.UpdateOne(ctx, f.coll, bson.M{"from_user_id": formUserID, "to_user_id": toUserID}, bson.M{"$set": args}, true)
}
func (f *FriendRequestMgo) Update(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) {
return mgotool.UpdateOne(ctx, f.coll, bson.M{"_id": friendRequest.ID}, bson.M{"$set": friendRequest}, true)
}
func (f *FriendRequestMgo) Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *relation.FriendRequestModel, err error) {
return mgotool.FindOne[*relation.FriendRequestModel](ctx, f.coll, bson.M{"from_user_id": fromUserID, "to_user_id": toUserID})
}
func (f *FriendRequestMgo) Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *relation.FriendRequestModel, err error) {
return f.Find(ctx, fromUserID, toUserID)
}

@ -0,0 +1,60 @@
package newmgo
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo/mgotool"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"time"
)
func NewGroupMongo(db *mongo.Database) (relation.GroupModelInterface, error) {
return &GroupMgo{
coll: db.Collection("group"),
}, nil
}
type GroupMgo struct {
coll *mongo.Collection
}
func (g *GroupMgo) Create(ctx context.Context, groups []*relation.GroupModel) (err error) {
return mgotool.InsertMany(ctx, g.coll, groups)
}
func (g *GroupMgo) UpdateState(ctx context.Context, groupID string, state int32) (err error) {
return g.UpdateMap(ctx, groupID, map[string]any{"state": state})
}
func (g *GroupMgo) UpdateMap(ctx context.Context, groupID string, args map[string]any) (err error) {
if len(args) == 0 {
return nil
}
return mgotool.UpdateOne(ctx, g.coll, bson.M{"group_id": groupID}, bson.M{"$set": args}, true)
}
func (g *GroupMgo) Find(ctx context.Context, groupIDs []string) (groups []*relation.GroupModel, err error) {
return mgotool.Find[*relation.GroupModel](ctx, g.coll, bson.M{"group_id": bson.M{"$in": groupIDs}})
}
func (g *GroupMgo) Take(ctx context.Context, groupID string) (group *relation.GroupModel, err error) {
return mgotool.FindOne[*relation.GroupModel](ctx, g.coll, bson.M{"group_id": groupID})
}
func (g *GroupMgo) Search(ctx context.Context, keyword string, pagination pagination.Pagination) (total int64, groups []*relation.GroupModel, err error) {
return mgotool.FindPage[*relation.GroupModel](ctx, g.coll, bson.M{"group_name": bson.M{"$regex": keyword}}, pagination)
}
func (g *GroupMgo) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
if before == nil {
return mgotool.Count(ctx, g.coll, bson.M{})
}
return mgotool.Count(ctx, g.coll, bson.M{"create_time": bson.M{"$lt": before}})
}
func (g *GroupMgo) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
//TODO implement me
panic("implement me")
}

@ -0,0 +1,88 @@
package newmgo
import (
"context"
"github.com/OpenIMSDK/protocol/constant"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo/mgotool"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func NewGroupMember(db *mongo.Database) (relation.GroupMemberModelInterface, error) {
return &GroupMemberMgo{coll: db.Collection("group_member")}, nil
}
type GroupMemberMgo struct {
coll *mongo.Collection
}
func (g *GroupMemberMgo) Create(ctx context.Context, groupMembers []*relation.GroupMemberModel) (err error) {
return mgotool.InsertMany(ctx, g.coll, groupMembers)
}
func (g *GroupMemberMgo) Delete(ctx context.Context, groupID string, userIDs []string) (err error) {
return mgotool.DeleteMany(ctx, g.coll, bson.M{"group_id": groupID, "user_id": bson.M{"$in": userIDs}})
}
func (g *GroupMemberMgo) UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32) error {
return g.Update(ctx, groupID, userID, bson.M{"role_level": roleLevel})
}
func (g *GroupMemberMgo) Update(ctx context.Context, groupID string, userID string, data map[string]any) (err error) {
return mgotool.UpdateOne(ctx, g.coll, bson.M{"group_id": groupID, "user_id": userID}, bson.M{"$set": data}, true)
}
func (g *GroupMemberMgo) Find(ctx context.Context, groupIDs []string, userIDs []string, roleLevels []int32) (groupMembers []*relation.GroupMemberModel, err error) {
//TODO implement me
panic("implement me")
}
func (g *GroupMemberMgo) FindMemberUserID(ctx context.Context, groupID string) (userIDs []string, err error) {
return mgotool.Find[string](ctx, g.coll, bson.M{"group_id": groupID}, options.Find().SetProjection(bson.M{"_id": 0, "user_id": 1}))
}
func (g *GroupMemberMgo) Take(ctx context.Context, groupID string, userID string) (groupMember *relation.GroupMemberModel, err error) {
return mgotool.FindOne[*relation.GroupMemberModel](ctx, g.coll, bson.M{"group_id": groupID, "user_id": userID})
}
func (g *GroupMemberMgo) TakeOwner(ctx context.Context, groupID string) (groupMember *relation.GroupMemberModel, err error) {
return mgotool.FindOne[*relation.GroupMemberModel](ctx, g.coll, bson.M{"group_id": groupID, "role_level": constant.GroupOwner})
}
func (g *GroupMemberMgo) FindRoleLevelUserIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error) {
return mgotool.Find[string](ctx, g.coll, bson.M{"group_id": groupID, "role_level": roleLevel}, options.Find().SetProjection(bson.M{"_id": 0, "user_id": 1}))
}
func (g *GroupMemberMgo) SearchMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (total int64, groupList []*relation.GroupMemberModel, err error) {
//TODO implement me
panic("implement me")
}
func (g *GroupMemberMgo) FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
return mgotool.Find[string](ctx, g.coll, bson.M{"user_id": userID}, options.Find().SetProjection(bson.M{"_id": 0, "group_id": 1}))
}
func (g *GroupMemberMgo) TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error) {
return mgotool.Count(ctx, g.coll, bson.M{"group_id": groupID})
}
func (g *GroupMemberMgo) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
filter := bson.M{
"user_id": userID,
"role_level": bson.M{
"$in": []int{constant.GroupOwner, constant.GroupAdmin},
},
}
return mgotool.Find[string](ctx, g.coll, filter, options.Find().SetProjection(bson.M{"_id": 0, "group_id": 1}))
}
func (g *GroupMemberMgo) IsUpdateRoleLevel(data map[string]any) bool {
if len(data) == 0 {
return false
}
_, ok := data["role_level"]
return ok
}

@ -0,0 +1,46 @@
package newmgo
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo/mgotool"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
func NewGroupRequestMgo(db *mongo.Database) (relation.GroupRequestModelInterface, error) {
return &GroupRequestMgo{coll: db.Collection("group_request")}, nil
}
type GroupRequestMgo struct {
coll *mongo.Collection
}
func (g *GroupRequestMgo) Create(ctx context.Context, groupRequests []*relation.GroupRequestModel) (err error) {
return mgotool.InsertMany(ctx, g.coll, groupRequests)
}
func (g *GroupRequestMgo) Delete(ctx context.Context, groupID string, userID string) (err error) {
return mgotool.DeleteOne(ctx, g.coll, bson.M{"group_id": groupID, "user_id": userID})
}
func (g *GroupRequestMgo) UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error) {
return mgotool.UpdateOne(ctx, g.coll, bson.M{"group_id": groupID, "user_id": userID}, bson.M{"$set": bson.M{"handle_msg": handledMsg, "handle_result": handleResult}}, true)
}
func (g *GroupRequestMgo) Take(ctx context.Context, groupID string, userID string) (groupRequest *relation.GroupRequestModel, err error) {
return mgotool.FindOne[*relation.GroupRequestModel](ctx, g.coll, bson.M{"group_id": groupID, "user_id": userID})
}
func (g *GroupRequestMgo) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*relation.GroupRequestModel, error) {
return mgotool.Find[*relation.GroupRequestModel](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 []*relation.GroupRequestModel, err error) {
return mgotool.FindPage[*relation.GroupRequestModel](ctx, g.coll, bson.M{"user_id": userID}, pagination)
}
func (g *GroupRequestMgo) PageGroup(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (total int64, groups []*relation.GroupRequestModel, err error) {
return mgotool.FindPage[*relation.GroupRequestModel](ctx, g.coll, bson.M{"group_id": bson.M{"$in": groupIDs}}, pagination)
}

@ -0,0 +1,49 @@
package newmgo
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo/mgotool"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"time"
)
func NewLogMongo(db *mongo.Database) (relation.LogInterface, error) {
lm := &LogMgo{
coll: db.Collection("log"),
}
return lm, nil
}
type LogMgo struct {
coll *mongo.Collection
}
func (l *LogMgo) Create(ctx context.Context, log []*relation.Log) error {
return mgotool.InsertMany(ctx, l.coll, log)
}
func (l *LogMgo) Search(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*relation.Log, error) {
filter := bson.M{"create_time": bson.M{"$gte": start, "$lte": end}}
if keyword != "" {
filter["user_id"] = bson.M{"$regex": keyword}
}
return mgotool.FindPage[*relation.Log](ctx, l.coll, filter, pagination, options.Find().SetSort(bson.M{"create_time": -1}))
}
func (l *LogMgo) Delete(ctx context.Context, logID []string, userID string) error {
if userID == "" {
return mgotool.DeleteMany(ctx, l.coll, bson.M{"log_id": bson.M{"$in": logID}})
}
return mgotool.DeleteMany(ctx, l.coll, bson.M{"log_id": bson.M{"$in": logID}, "user_id": userID})
}
func (l *LogMgo) Get(ctx context.Context, logIDs []string, userID string) ([]*relation.Log, error) {
if userID == "" {
return mgotool.Find[*relation.Log](ctx, l.coll, bson.M{"log_id": bson.M{"$in": logIDs}})
}
return mgotool.Find[*relation.Log](ctx, l.coll, bson.M{"log_id": bson.M{"$in": logIDs}, "user_id": userID})
}

@ -0,0 +1,198 @@
package mgotool
import (
"context"
"github.com/OpenIMSDK/tools/errs"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func basic[T any]() bool {
var t T
switch any(t).(type) {
case int:
case int8:
case int16:
case int32:
case int64:
case uint:
case uint8:
case uint16:
case uint32:
case uint64:
case float32:
case float64:
case string:
case []byte:
default:
return false
}
return true
}
func anes[T any](ts []T) []any {
val := make([]any, len(ts))
for i := range ts {
val[i] = ts[i]
}
return val
}
func findOptionToCountOption(opts []*options.FindOptions) *options.CountOptions {
countOpt := options.Count()
for _, opt := range opts {
if opt.Skip != nil {
countOpt.SetSkip(*opt.Skip)
}
if opt.Limit != nil {
countOpt.SetLimit(*opt.Limit)
}
}
return countOpt
}
func InsertMany[T any](ctx context.Context, coll *mongo.Collection, val []T, opts ...*options.InsertManyOptions) error {
_, err := coll.InsertMany(ctx, anes(val), opts...)
if err != nil {
return errs.Wrap(err)
}
return nil
}
func UpdateOne(ctx context.Context, coll *mongo.Collection, filter any, update any, notMatchedErr bool, opts ...*options.UpdateOptions) error {
res, err := coll.UpdateOne(ctx, filter, update, opts...)
if err != nil {
return errs.Wrap(err)
}
if notMatchedErr && res.MatchedCount == 0 {
return errs.Wrap(mongo.ErrNoDocuments)
}
return nil
}
func UpdateMany(ctx context.Context, coll *mongo.Collection, filter any, update any, opts ...*options.UpdateOptions) (*mongo.UpdateResult, error) {
res, err := coll.UpdateMany(ctx, filter, update, opts...)
if err != nil {
return nil, errs.Wrap(err)
}
return res, nil
}
func Find[T any](ctx context.Context, coll *mongo.Collection, filter any, opts ...*options.FindOptions) ([]T, error) {
cur, err := coll.Find(ctx, filter, opts...)
if err != nil {
return nil, errs.Wrap(err)
}
defer cur.Close(ctx)
var res []T
if basic[T]() {
var temp []map[string]T
if err := cur.All(ctx, &temp); err != nil {
return nil, errs.Wrap(err)
}
res = make([]T, 0, len(temp))
for _, m := range temp {
if len(m) != 1 {
return nil, errs.ErrInternalServer.Wrap("mongo find result len(m) != 1")
}
for _, t := range m {
res = append(res, t)
}
}
} else {
if err := cur.All(ctx, &res); err != nil {
return nil, errs.Wrap(err)
}
}
return res, nil
}
func FindOne[T any](ctx context.Context, coll *mongo.Collection, filter any, opts ...*options.FindOneOptions) (res T, err error) {
cur := coll.FindOne(ctx, filter, opts...)
if err := cur.Err(); err != nil {
return res, errs.Wrap(err)
}
if err := cur.Decode(&res); err != nil {
return res, errs.Wrap(err)
}
return res, nil
}
func FindPage[T any](ctx context.Context, coll *mongo.Collection, filter any, pagination pagination.Pagination, opts ...*options.FindOptions) (int64, []T, error) {
count, err := Count(ctx, coll, filter, findOptionToCountOption(opts))
if err != nil {
return 0, nil, err
}
if count == 0 || pagination == nil {
return count, nil, nil
}
skip := int64(pagination.GetPageNumber()-1) * int64(pagination.GetShowNumber())
if skip < 0 || skip >= count || pagination.GetShowNumber() <= 0 {
return count, nil, nil
}
opt := options.Find().SetSkip(skip).SetLimit(int64(pagination.GetShowNumber()))
res, err := Find[T](ctx, coll, filter, append(opts, opt)...)
if err != nil {
return 0, nil, err
}
return count, res, nil
}
func FindPageOnly[T any](ctx context.Context, coll *mongo.Collection, filter any, pagination pagination.Pagination, opts ...*options.FindOptions) ([]T, error) {
skip := int64(pagination.GetPageNumber()-1) * int64(pagination.GetShowNumber())
if skip < 0 || pagination.GetShowNumber() <= 0 {
return nil, nil
}
opt := options.Find().SetSkip(skip).SetLimit(int64(pagination.GetShowNumber()))
return Find[T](ctx, coll, filter, append(opts, opt)...)
}
func Count(ctx context.Context, coll *mongo.Collection, filter any, opts ...*options.CountOptions) (int64, error) {
return coll.CountDocuments(ctx, filter, opts...)
}
func Exist(ctx context.Context, coll *mongo.Collection, filter any, opts ...*options.CountOptions) (bool, error) {
opts = append(opts, options.Count().SetLimit(1))
count, err := Count(ctx, coll, filter, opts...)
if err != nil {
return false, err
}
return count > 0, nil
}
func DeleteOne(ctx context.Context, coll *mongo.Collection, filter any, opts ...*options.DeleteOptions) error {
if _, err := coll.DeleteOne(ctx, filter, opts...); err != nil {
return errs.Wrap(err)
}
return nil
}
func DeleteMany(ctx context.Context, coll *mongo.Collection, filter any, opts ...*options.DeleteOptions) error {
if _, err := coll.DeleteMany(ctx, filter, opts...); err != nil {
return errs.Wrap(err)
}
return nil
}
// TODO
func Delete[T any](ctx context.Context, coll *mongo.Collection, filter any, opts ...*options.DeleteOptions) error {
if _, err := coll.DeleteMany(ctx, filter, opts...); err != nil {
return errs.Wrap(err)
}
return nil
}
func Aggregate[T any](ctx context.Context, coll *mongo.Collection, pipeline any, opts ...*options.AggregateOptions) ([]T, error) {
cur, err := coll.Aggregate(ctx, pipeline, opts...)
if err != nil {
return nil, err
}
var ts []T
if err := cur.All(ctx, &ts); err != nil {
return nil, err
}
return ts, nil
}

@ -0,0 +1,45 @@
package newmgo
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo/mgotool"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func NewS3Mongo(db *mongo.Database) (relation.ObjectInfoModelInterface, error) {
return &S3Mongo{
coll: db.Collection("s3"),
}, nil
}
type S3Mongo struct {
coll *mongo.Collection
}
func (o *S3Mongo) SetObject(ctx context.Context, obj *relation.ObjectModel) error {
filter := bson.M{"name": obj.Name, "engine": obj.Engine}
update := bson.M{
"name": obj.Name,
"engine": obj.Engine,
"key": obj.Key,
"size": obj.Size,
"content_type": obj.ContentType,
"group": obj.Group,
"create_time": obj.CreateTime,
}
return mgotool.UpdateOne(ctx, o.coll, filter, bson.M{"$set": update}, false, options.Update().SetUpsert(true))
}
func (o *S3Mongo) Take(ctx context.Context, engine string, name string) (*relation.ObjectModel, error) {
if engine == "" {
return mgotool.FindOne[*relation.ObjectModel](ctx, o.coll, bson.M{"name": name})
}
return mgotool.FindOne[*relation.ObjectModel](ctx, o.coll, bson.M{"name": name, "engine": engine})
}
func (o *S3Mongo) Delete(ctx context.Context, engine string, name string) error {
return mgotool.DeleteOne(ctx, o.coll, bson.M{"name": name, "engine": engine})
}

@ -0,0 +1,71 @@
package newmgo
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo/mgotool"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"time"
)
func NewUserMongo(db *mongo.Database) (relation.UserModelInterface, error) {
return &UserMgo{
coll: db.Collection("user"),
}, nil
}
type UserMgo struct {
coll *mongo.Collection
}
func (u *UserMgo) Create(ctx context.Context, users []*relation.UserModel) error {
return mgotool.InsertMany(ctx, u.coll, users)
}
func (u *UserMgo) UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error) {
if len(args) == 0 {
return nil
}
return mgotool.UpdateOne(ctx, u.coll, bson.M{"user_id": userID}, bson.M{"$set": args}, true)
}
func (u *UserMgo) Find(ctx context.Context, userIDs []string) (users []*relation.UserModel, err error) {
return mgotool.Find[*relation.UserModel](ctx, u.coll, bson.M{"user_id": bson.M{"$in": userIDs}})
}
func (u *UserMgo) Take(ctx context.Context, userID string) (user *relation.UserModel, err error) {
return mgotool.FindOne[*relation.UserModel](ctx, u.coll, bson.M{"user_id": userID})
}
func (u *UserMgo) Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*relation.UserModel, err error) {
return mgotool.FindPage[*relation.UserModel](ctx, u.coll, bson.M{}, pagination)
}
func (u *UserMgo) GetAllUserID(ctx context.Context, pagination pagination.Pagination) (int64, []string, error) {
return mgotool.FindPage[string](ctx, u.coll, bson.M{}, pagination, options.Find().SetProjection(bson.M{"user_id": 1}))
}
func (u *UserMgo) Exist(ctx context.Context, userID string) (exist bool, err error) {
return mgotool.Exist(ctx, u.coll, bson.M{"user_id": userID})
}
func (u *UserMgo) GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error) {
return mgotool.FindOne[int](ctx, u.coll, bson.M{"user_id": userID}, options.FindOne().SetProjection(bson.M{"global_recv_msg_opt": 1}))
}
func (u *UserMgo) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
return mgotool.Count(ctx, u.coll, bson.M{"create_time": bson.M{"$lt": before}})
}
func (u *UserMgo) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
//type Temp struct {
// CreateTime time.Time `bson:"create_time"`
// Number int64 `bson:"number"`
//}
//mgotool.Find(ctx, u.coll, bson.M{"create_time": bson.M{"$gte": start, "$lt": end}}, options.Find().SetProjection(bson.M{"create_time": 1}))
panic("implement me")
return nil, nil
}

@ -47,7 +47,7 @@ func (b *BlackGorm) Delete(ctx context.Context, blacks []*relation.BlackModel) (
func (b *BlackGorm) UpdateByMap( func (b *BlackGorm) UpdateByMap(
ctx context.Context, ctx context.Context,
ownerUserID, blockUserID string, ownerUserID, blockUserID string,
args map[string]interface{}, args map[string]any,
) (err error) { ) (err error) {
return utils.Wrap( return utils.Wrap(
b.db(ctx).Where("block_user_id = ? and block_user_id = ?", ownerUserID, blockUserID).Updates(args).Error, b.db(ctx).Where("block_user_id = ? and block_user_id = ?", ownerUserID, blockUserID).Updates(args).Error,
@ -63,9 +63,9 @@ func (b *BlackGorm) Find(
ctx context.Context, ctx context.Context,
blacks []*relation.BlackModel, blacks []*relation.BlackModel,
) (blackList []*relation.BlackModel, err error) { ) (blackList []*relation.BlackModel, err error) {
var where [][]interface{} var where [][]any
for _, black := range blacks { for _, black := range blacks {
where = append(where, []interface{}{black.OwnerUserID, black.BlockUserID}) where = append(where, []any{black.OwnerUserID, black.BlockUserID})
} }
return blackList, utils.Wrap( return blackList, utils.Wrap(
b.db(ctx).Where("(owner_user_id, block_user_id) in ?", where).Find(&blackList).Error, b.db(ctx).Where("(owner_user_id, block_user_id) in ?", where).Find(&blackList).Error,

@ -14,237 +14,231 @@
package relation package relation
import ( //
"context" //import (
// "context"
"github.com/OpenIMSDK/tools/errs" //
"gorm.io/gorm" // "github.com/OpenIMSDK/tools/errs"
// "gorm.io/gorm"
"github.com/OpenIMSDK/protocol/constant" //
"github.com/OpenIMSDK/tools/utils" // "github.com/OpenIMSDK/protocol/constant"
// "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 ConversationGorm struct { //
*MetaDB //type ConversationGorm struct {
} // *MetaDB
//}
func NewConversationGorm(db *gorm.DB) relation.ConversationModelInterface { //
return &ConversationGorm{NewMetaDB(db, &relation.ConversationModel{})} //func NewConversationGorm(db *gorm.DB) relation.ConversationModelInterface {
} // return &ConversationGorm{NewMetaDB(db, &relation.ConversationModel{})}
//}
func (c *ConversationGorm) NewTx(tx any) relation.ConversationModelInterface { //
return &ConversationGorm{NewMetaDB(tx.(*gorm.DB), &relation.ConversationModel{})} //func (c *ConversationGorm) NewTx(tx any) relation.ConversationModelInterface {
} // return &ConversationGorm{NewMetaDB(tx.(*gorm.DB), &relation.ConversationModel{})}
//}
func (c *ConversationGorm) Create(ctx context.Context, conversations []*relation.ConversationModel) (err error) { //
return utils.Wrap(c.db(ctx).Create(&conversations).Error, "") //func (c *ConversationGorm) Create(ctx context.Context, conversations []*relation.ConversationModel) (err error) {
} // return utils.Wrap(c.db(ctx).Create(&conversations).Error, "")
//}
func (c *ConversationGorm) Delete(ctx context.Context, groupIDs []string) (err error) { //
return utils.Wrap(c.db(ctx).Where("group_id in (?)", groupIDs).Delete(&relation.ConversationModel{}).Error, "") //func (c *ConversationGorm) Delete(ctx context.Context, groupIDs []string) (err error) {
} // return utils.Wrap(c.db(ctx).Where("group_id in (?)", groupIDs).Delete(&relation.ConversationModel{}).Error, "")
//}
func (c *ConversationGorm) UpdateByMap( //
ctx context.Context, //func (c *ConversationGorm) UpdateByMap(
userIDList []string, // ctx context.Context,
conversationID string, // userIDList []string,
args map[string]interface{}, // conversationID string,
) (rows int64, err error) { // args map[string]any,
result := c.db(ctx).Where("owner_user_id IN (?) and conversation_id=?", userIDList, conversationID).Updates(args) //) (rows int64, err error) {
return result.RowsAffected, utils.Wrap(result.Error, "") // result := c.db(ctx).Where("owner_user_id IN (?) and conversation_id=?", userIDList, conversationID).Updates(args)
} // return result.RowsAffected, utils.Wrap(result.Error, "")
//}
func (c *ConversationGorm) Update(ctx context.Context, conversation *relation.ConversationModel) (err error) { //
return utils.Wrap( //func (c *ConversationGorm) Update(ctx context.Context, conversation *relation.ConversationModel) (err error) {
c.db(ctx). // return utils.Wrap(
Where("owner_user_id = ? and conversation_id = ?", conversation.OwnerUserID, conversation.ConversationID). // c.db(ctx).
Updates(conversation). // Where("owner_user_id = ? and conversation_id = ?", conversation.OwnerUserID, conversation.ConversationID).
Error, // Updates(conversation).
"", // Error,
) // "",
} // )
//}
func (c *ConversationGorm) Find( //
ctx context.Context, //func (c *ConversationGorm) Find(
ownerUserID string, // ctx context.Context,
conversationIDs []string, // ownerUserID string,
) (conversations []*relation.ConversationModel, err error) { // conversationIDs []string,
err = utils.Wrap( //) (conversations []*relation.ConversationModel, err error) {
c.db(ctx). // err = utils.Wrap(
Where("owner_user_id=? and conversation_id IN (?)", ownerUserID, conversationIDs). // c.db(ctx).
Find(&conversations). // Where("owner_user_id=? and conversation_id IN (?)", ownerUserID, conversationIDs).
Error, // Find(&conversations).
"", // Error,
) // "",
return conversations, err // )
} // return conversations, err
//}
func (c *ConversationGorm) Take( //
ctx context.Context, //func (c *ConversationGorm) Take(
userID, conversationID string, // ctx context.Context,
) (conversation *relation.ConversationModel, err error) { // userID, conversationID string,
cc := &relation.ConversationModel{} //) (conversation *relation.ConversationModel, err error) {
return cc, utils.Wrap( // cc := &relation.ConversationModel{}
c.db(ctx).Where("conversation_id = ? And owner_user_id = ?", conversationID, userID).Take(cc).Error, // return cc, utils.Wrap(
"", // c.db(ctx).Where("conversation_id = ? And owner_user_id = ?", conversationID, userID).Take(cc).Error,
) // "",
} // )
//}
func (c *ConversationGorm) FindUserID( //
ctx context.Context, //func (c *ConversationGorm) FindUserID(
userIDs []string, // ctx context.Context,
conversationIDs []string, // userIDs []string,
) (existUserID []string, err error) { // conversationIDs []string,
return existUserID, utils.Wrap( //) (existUserID []string, err error) {
c.db(ctx). // return existUserID, utils.Wrap(
Where(" owner_user_id IN (?) and conversation_id in (?)", userIDs, conversationIDs). // c.db(ctx).
Pluck("owner_user_id", &existUserID). // Where(" owner_user_id IN (?) and conversation_id in (?)", userIDs, conversationIDs).
Error, // Pluck("owner_user_id", &existUserID).
"", // Error,
) // "",
} // )
//}
func (c *ConversationGorm) FindConversationID( //
ctx context.Context, //func (c *ConversationGorm) FindConversationID(
userID string, // ctx context.Context,
conversationIDList []string, // userID string,
) (existConversationID []string, err error) { // conversationIDList []string,
return existConversationID, utils.Wrap( //) (existConversationID []string, err error) {
c.db(ctx). // return existConversationID, utils.Wrap(
Where(" conversation_id IN (?) and owner_user_id=?", conversationIDList, userID). // c.db(ctx).
Pluck("conversation_id", &existConversationID). // Where(" conversation_id IN (?) and owner_user_id=?", conversationIDList, userID).
Error, // Pluck("conversation_id", &existConversationID).
"", // Error,
) // "",
} // )
//}
func (c *ConversationGorm) FindUserIDAllConversationID( //
ctx context.Context, //func (c *ConversationGorm) FindUserIDAllConversationID(
userID string, // ctx context.Context,
) (conversationIDList []string, err error) { // userID string,
return conversationIDList, utils.Wrap( //) (conversationIDList []string, err error) {
c.db(ctx).Where("owner_user_id=?", userID).Pluck("conversation_id", &conversationIDList).Error, // return conversationIDList, utils.Wrap(
"", // c.db(ctx).Where("owner_user_id=?", userID).Pluck("conversation_id", &conversationIDList).Error,
) // "",
} // )
//}
func (c *ConversationGorm) FindUserIDAllConversations( //
ctx context.Context, //func (c *ConversationGorm) FindUserIDAllConversations(
userID string, // ctx context.Context,
) (conversations []*relation.ConversationModel, err error) { // userID string,
return conversations, utils.Wrap(c.db(ctx).Where("owner_user_id=?", userID).Find(&conversations).Error, "") //) (conversations []*relation.ConversationModel, err error) {
} // return conversations, utils.Wrap(c.db(ctx).Where("owner_user_id=?", userID).Find(&conversations).Error, "")
//}
func (c *ConversationGorm) FindRecvMsgNotNotifyUserIDs( //
ctx context.Context, //func (c *ConversationGorm) FindRecvMsgNotNotifyUserIDs(
groupID string, // ctx context.Context,
) (userIDs []string, err error) { // groupID string,
return userIDs, utils.Wrap( //) (userIDs []string, err error) {
c.db(ctx). // return userIDs, utils.Wrap(
Where("group_id = ? and recv_msg_opt = ?", groupID, constant.ReceiveNotNotifyMessage). // c.db(ctx).
Pluck("owner_user_id", &userIDs). // Where("group_id = ? and recv_msg_opt = ?", groupID, constant.ReceiveNotNotifyMessage).
Error, // Pluck("owner_user_id", &userIDs).
"", // Error,
) // "",
} // )
//}
func (c *ConversationGorm) FindSuperGroupRecvMsgNotNotifyUserIDs( //
ctx context.Context, //func (c *ConversationGorm) FindSuperGroupRecvMsgNotNotifyUserIDs(
groupID string, // ctx context.Context,
) (userIDs []string, err error) { // groupID string,
return userIDs, utils.Wrap( //) (userIDs []string, err error) {
c.db(ctx). // return userIDs, utils.Wrap(
Where("group_id = ? and recv_msg_opt = ? and conversation_type = ?", groupID, constant.ReceiveNotNotifyMessage, constant.SuperGroupChatType). // c.db(ctx).
Pluck("owner_user_id", &userIDs). // Where("group_id = ? and recv_msg_opt = ? and conversation_type = ?", groupID, constant.ReceiveNotNotifyMessage, constant.SuperGroupChatType).
Error, // Pluck("owner_user_id", &userIDs).
"", // Error,
) // "",
} // )
//}
func (c *ConversationGorm) GetUserRecvMsgOpt( //
ctx context.Context, //func (c *ConversationGorm) GetUserRecvMsgOpt(
ownerUserID, conversationID string, // ctx context.Context,
) (opt int, err error) { // ownerUserID, conversationID string,
var conversation relation.ConversationModel //) (opt int, err error) {
return int( // var conversation relation.ConversationModel
conversation.RecvMsgOpt, // return int(
), utils.Wrap( // conversation.RecvMsgOpt,
c.db(ctx). // ), utils.Wrap(
Where("conversation_id = ? And owner_user_id = ?", conversationID, ownerUserID). // c.db(ctx).
Select("recv_msg_opt"). // Where("conversation_id = ? And owner_user_id = ?", conversationID, ownerUserID).
Find(&conversation). // Select("recv_msg_opt").
Error, // Find(&conversation).
"", // Error,
) // "",
} // )
//}
func (c *ConversationGorm) GetAllConversationIDs(ctx context.Context) (conversationIDs []string, err error) { //
return conversationIDs, utils.Wrap( //func (c *ConversationGorm) GetAllConversationIDs(ctx context.Context) (conversationIDs []string, err error) {
c.db(ctx).Distinct("conversation_id").Pluck("conversation_id", &conversationIDs).Error, // return conversationIDs, utils.Wrap(
"", // c.db(ctx).Distinct("conversation_id").Pluck("conversation_id", &conversationIDs).Error,
) // "",
} // )
//}
func (c *ConversationGorm) GetAllConversationIDsNumber(ctx context.Context) (int64, error) { //
var num int64 //func (c *ConversationGorm) GetAllConversationIDsNumber(ctx context.Context) (int64, error) {
err := c.db(ctx).Select("COUNT(DISTINCT conversation_id)").Model(&relation.ConversationModel{}).Count(&num).Error // var num int64
return num, errs.Wrap(err) // err := c.db(ctx).Select("COUNT(DISTINCT conversation_id)").Model(&relation.ConversationModel{}).Count(&num).Error
} // return num, errs.Wrap(err)
//}
func (c *ConversationGorm) PageConversationIDs(ctx context.Context, pageNumber, showNumber int32) (conversationIDs []string, err error) { //
err = c.db(ctx).Distinct("conversation_id").Limit(int(showNumber)).Offset(int((pageNumber-1)*showNumber)).Pluck("conversation_id", &conversationIDs).Error //func (c *ConversationGorm) PageConversationIDs(ctx context.Context, pageNumber, showNumber int32) (conversationIDs []string, err error) {
err = errs.Wrap(err) // err = c.db(ctx).Distinct("conversation_id").Limit(int(showNumber)).Offset(int((pageNumber-1)*showNumber)).Pluck("conversation_id", &conversationIDs).Error
return // err = errs.Wrap(err)
} // return
//}
func (c *ConversationGorm) GetUserAllHasReadSeqs( //
ctx context.Context, //func (c *ConversationGorm) GetConversationsByConversationID(
ownerUserID string, // ctx context.Context,
) (hasReadSeqs map[string]int64, err error) { // conversationIDs []string,
return nil, nil //) (conversations []*relation.ConversationModel, err error) {
} // return conversations, utils.Wrap(
// c.db(ctx).Where("conversation_id IN (?)", conversationIDs).Find(&conversations).Error,
func (c *ConversationGorm) GetConversationsByConversationID( // "",
ctx context.Context, // )
conversationIDs []string, //}
) (conversations []*relation.ConversationModel, err error) { //
return conversations, utils.Wrap( //func (c *ConversationGorm) GetConversationIDsNeedDestruct(
c.db(ctx).Where("conversation_id IN (?)", conversationIDs).Find(&conversations).Error, // ctx context.Context,
"", //) (conversations []*relation.ConversationModel, err error) {
) // return conversations, utils.Wrap(
} // c.db(ctx).
// Where("is_msg_destruct = 1 && msg_destruct_time != 0 && (UNIX_TIMESTAMP(NOW()) > (msg_destruct_time + UNIX_TIMESTAMP(latest_msg_destruct_time)) || latest_msg_destruct_time is NULL)").
func (c *ConversationGorm) GetConversationIDsNeedDestruct( // Find(&conversations).
ctx context.Context, // Error,
) (conversations []*relation.ConversationModel, err error) { // "",
return conversations, utils.Wrap( // )
c.db(ctx). //}
Where("is_msg_destruct = 1 && msg_destruct_time != 0 && (UNIX_TIMESTAMP(NOW()) > (msg_destruct_time + UNIX_TIMESTAMP(latest_msg_destruct_time)) || latest_msg_destruct_time is NULL)"). //
Find(&conversations). //func (c *ConversationGorm) GetConversationRecvMsgOpt(ctx context.Context, userID string, conversationID string) (int32, error) {
Error, // var recvMsgOpt int32
"", // return recvMsgOpt, errs.Wrap(
) // c.db(ctx).
} // Model(&relation.ConversationModel{}).
// Where("conversation_id = ? and owner_user_id in ?", conversationID, userID).
func (c *ConversationGorm) GetConversationRecvMsgOpt(ctx context.Context, userID string, conversationID string) (int32, error) { // Pluck("recv_msg_opt", &recvMsgOpt).
var recvMsgOpt int32 // Error,
return recvMsgOpt, errs.Wrap( // )
c.db(ctx). //}
Model(&relation.ConversationModel{}). //
Where("conversation_id = ? and owner_user_id in ?", conversationID, userID). //func (c *ConversationGorm) GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error) {
Pluck("recv_msg_opt", &recvMsgOpt). // var userIDs []string
Error, // return userIDs, errs.Wrap(
) // c.db(ctx).
} // Model(&relation.ConversationModel{}).
// Where("conversation_id = ? and recv_msg_opt <> ?", conversationID, constant.ReceiveMessage).
func (c *ConversationGorm) GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error) { // Pluck("owner_user_id", &userIDs).Error,
var userIDs []string // )
return userIDs, errs.Wrap( //}
c.db(ctx).
Model(&relation.ConversationModel{}).
Where("conversation_id = ? and recv_msg_opt <> ?", conversationID, constant.ReceiveMessage).
Pluck("owner_user_id", &userIDs).Error,
)
}

@ -58,7 +58,7 @@ func (f *FriendGorm) UpdateByMap(
ctx context.Context, ctx context.Context,
ownerUserID string, ownerUserID string,
friendUserID string, friendUserID string,
args map[string]interface{}, args map[string]any,
) (err error) { ) (err error) {
return utils.Wrap( return utils.Wrap(
f.db(ctx).Where("owner_user_id = ? AND friend_user_id = ? ", ownerUserID, friendUserID).Updates(args).Error, f.db(ctx).Where("owner_user_id = ? AND friend_user_id = ? ", ownerUserID, friendUserID).Updates(args).Error,
@ -82,7 +82,7 @@ func (f *FriendGorm) UpdateRemark(ctx context.Context, ownerUserID, friendUserID
"", "",
) )
} }
m := make(map[string]interface{}, 1) m := make(map[string]any, 1)
m["remark"] = "" m["remark"] = ""
return utils.Wrap(f.db(ctx).Where("owner_user_id = ?", ownerUserID).Updates(m).Error, "") return utils.Wrap(f.db(ctx).Where("owner_user_id = ?", ownerUserID).Updates(m).Error, "")
} }

@ -14,151 +14,141 @@
package relation package relation
import ( // type FriendRequestGorm struct {
"context" // *MetaDB
// }
"gorm.io/gorm"
// func NewFriendRequestGorm(db *gorm.DB) relation.FriendRequestModelInterface {
"github.com/OpenIMSDK/tools/utils" // return &FriendRequestGorm{NewMetaDB(db, &relation.FriendRequestModel{})}
// }
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
) // func (f *FriendRequestGorm) NewTx(tx any) relation.FriendRequestModelInterface {
// return &FriendRequestGorm{NewMetaDB(tx.(*gorm.DB), &relation.FriendRequestModel{})}
type FriendRequestGorm struct { // }
*MetaDB
} // // 插入多条记录.
// func (f *FriendRequestGorm) Create(ctx context.Context, friendRequests []*relation.FriendRequestModel) (err error) {
func NewFriendRequestGorm(db *gorm.DB) relation.FriendRequestModelInterface { // return utils.Wrap(f.db(ctx).Create(&friendRequests).Error, "")
return &FriendRequestGorm{NewMetaDB(db, &relation.FriendRequestModel{})} // }
}
// // 删除记录.
func (f *FriendRequestGorm) NewTx(tx any) relation.FriendRequestModelInterface { // func (f *FriendRequestGorm) Delete(ctx context.Context, fromUserID, toUserID string) (err error) {
return &FriendRequestGorm{NewMetaDB(tx.(*gorm.DB), &relation.FriendRequestModel{})} // return utils.Wrap(
} // f.db(ctx).
// Where("from_user_id = ? AND to_user_id = ?", fromUserID, toUserID).
// 插入多条记录. // Delete(&relation.FriendRequestModel{}).
func (f *FriendRequestGorm) Create(ctx context.Context, friendRequests []*relation.FriendRequestModel) (err error) { // Error,
return utils.Wrap(f.db(ctx).Create(&friendRequests).Error, "") // "",
} // )
// }
// 删除记录.
func (f *FriendRequestGorm) Delete(ctx context.Context, fromUserID, toUserID string) (err error) { // // 更新零值.
return utils.Wrap( // func (f *FriendRequestGorm) UpdateByMap(
f.db(ctx). // ctx context.Context,
Where("from_user_id = ? AND to_user_id = ?", fromUserID, toUserID). // fromUserID string,
Delete(&relation.FriendRequestModel{}). // toUserID string,
Error, // args map[string]any,
"", // ) (err error) {
) // return utils.Wrap(
} // f.db(ctx).
// Model(&relation.FriendRequestModel{}).
// 更新零值. // Where("from_user_id = ? AND to_user_id =?", fromUserID, toUserID).
func (f *FriendRequestGorm) UpdateByMap( // Updates(args).
ctx context.Context, // Error,
fromUserID string, // "",
toUserID string, // )
args map[string]interface{}, // }
) (err error) {
return utils.Wrap( // // 更新记录 (非零值).
f.db(ctx). // func (f *FriendRequestGorm) Update(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) {
Model(&relation.FriendRequestModel{}). // fr2 := *friendRequest
Where("from_user_id = ? AND to_user_id =?", fromUserID, toUserID). // fr2.FromUserID = ""
Updates(args). // fr2.ToUserID = ""
Error, // return utils.Wrap(
"", // f.db(ctx).
) // Where("from_user_id = ? AND to_user_id =?", friendRequest.FromUserID, friendRequest.ToUserID).
} // Updates(fr2).
// Error,
// 更新记录 (非零值). // "",
func (f *FriendRequestGorm) Update(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) { // )
fr2 := *friendRequest // }
fr2.FromUserID = ""
fr2.ToUserID = "" // // 获取来指定用户的好友申请 未找到 不返回错误.
return utils.Wrap( // func (f *FriendRequestGorm) Find(
f.db(ctx). // ctx context.Context,
Where("from_user_id = ? AND to_user_id =?", friendRequest.FromUserID, friendRequest.ToUserID). // fromUserID, toUserID string,
Updates(fr2). // ) (friendRequest *relation.FriendRequestModel, err error) {
Error, // friendRequest = &relation.FriendRequestModel{}
"", // err = utils.Wrap(
) // f.db(ctx).Where("from_user_id = ? and to_user_id = ?", fromUserID, toUserID).Find(friendRequest).Error,
} // "",
// )
// 获取来指定用户的好友申请 未找到 不返回错误. // return friendRequest, err
func (f *FriendRequestGorm) Find( // }
ctx context.Context,
fromUserID, toUserID string, // func (f *FriendRequestGorm) Take(
) (friendRequest *relation.FriendRequestModel, err error) { // ctx context.Context,
friendRequest = &relation.FriendRequestModel{} // fromUserID, toUserID string,
err = utils.Wrap( // ) (friendRequest *relation.FriendRequestModel, err error) {
f.db(ctx).Where("from_user_id = ? and to_user_id = ?", fromUserID, toUserID).Find(friendRequest).Error, // friendRequest = &relation.FriendRequestModel{}
"", // err = utils.Wrap(
) // f.db(ctx).Where("from_user_id = ? and to_user_id = ?", fromUserID, toUserID).Take(friendRequest).Error,
return friendRequest, err // "",
} // )
// return friendRequest, err
func (f *FriendRequestGorm) Take( // }
ctx context.Context,
fromUserID, toUserID string, // // 获取toUserID收到的好友申请列表.
) (friendRequest *relation.FriendRequestModel, err error) { // func (f *FriendRequestGorm) FindToUserID(
friendRequest = &relation.FriendRequestModel{} // ctx context.Context,
err = utils.Wrap( // toUserID string,
f.db(ctx).Where("from_user_id = ? and to_user_id = ?", fromUserID, toUserID).Take(friendRequest).Error, // pageNumber, showNumber int32,
"", // ) (friendRequests []*relation.FriendRequestModel, total int64, err error) {
) // err = f.db(ctx).Model(&relation.FriendRequestModel{}).Where("to_user_id = ? ", toUserID).Count(&total).Error
return friendRequest, err // if err != nil {
} // return nil, 0, utils.Wrap(err, "")
// }
// 获取toUserID收到的好友申请列表. // err = utils.Wrap(
func (f *FriendRequestGorm) FindToUserID( // f.db(ctx).
ctx context.Context, // Where("to_user_id = ? ", toUserID).
toUserID string, // Limit(int(showNumber)).
pageNumber, showNumber int32, // Offset(int(pageNumber-1)*int(showNumber)).
) (friendRequests []*relation.FriendRequestModel, total int64, err error) { // Find(&friendRequests).
err = f.db(ctx).Model(&relation.FriendRequestModel{}).Where("to_user_id = ? ", toUserID).Count(&total).Error // Error,
if err != nil { // "",
return nil, 0, utils.Wrap(err, "") // )
} // return
err = utils.Wrap( // }
f.db(ctx).
Where("to_user_id = ? ", toUserID). // // 获取fromUserID发出去的好友申请列表.
Limit(int(showNumber)). // func (f *FriendRequestGorm) FindFromUserID(
Offset(int(pageNumber-1)*int(showNumber)). // ctx context.Context,
Find(&friendRequests). // fromUserID string,
Error, // pageNumber, showNumber int32,
"", // ) (friendRequests []*relation.FriendRequestModel, total int64, err error) {
) // err = f.db(ctx).Model(&relation.FriendRequestModel{}).Where("from_user_id = ? ", fromUserID).Count(&total).Error
return // if err != nil {
} // return nil, 0, utils.Wrap(err, "")
// }
// 获取fromUserID发出去的好友申请列表. // err = utils.Wrap(
func (f *FriendRequestGorm) FindFromUserID( // f.db(ctx).
ctx context.Context, // Where("from_user_id = ? ", fromUserID).
fromUserID string, // Limit(int(showNumber)).
pageNumber, showNumber int32, // Offset(int(pageNumber-1)*int(showNumber)).
) (friendRequests []*relation.FriendRequestModel, total int64, err error) { // Find(&friendRequests).
err = f.db(ctx).Model(&relation.FriendRequestModel{}).Where("from_user_id = ? ", fromUserID).Count(&total).Error // Error,
if err != nil { // "",
return nil, 0, utils.Wrap(err, "") // )
} // return
err = utils.Wrap( // }
f.db(ctx).
Where("from_user_id = ? ", fromUserID). // func (f *FriendRequestGorm) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error) {
Limit(int(showNumber)). // err = utils.Wrap(
Offset(int(pageNumber-1)*int(showNumber)). // f.db(ctx).
Find(&friendRequests). // Where("(from_user_id = ? AND to_user_id = ?) OR (from_user_id = ? AND to_user_id = ?)", fromUserID, toUserID, toUserID, fromUserID).
Error, // Find(&friends).
"", // Error,
) // "",
return // )
} // return
// }
func (f *FriendRequestGorm) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error) {
err = utils.Wrap(
f.db(ctx).
Where("(from_user_id = ? AND to_user_id = ?) OR (from_user_id = ? AND to_user_id = ?)", fromUserID, toUserID, toUserID, fromUserID).
Find(&friends).
Error,
"",
)
return
}

@ -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,93 +14,93 @@
package relation package relation
import ( //import (
"context" // "context"
"time" // "time"
//
"github.com/OpenIMSDK/protocol/constant" // "github.com/OpenIMSDK/protocol/constant"
//
"gorm.io/gorm" // "gorm.io/gorm"
//
"github.com/OpenIMSDK/tools/errs" // "github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/ormutil" // "github.com/OpenIMSDK/tools/ormutil"
"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"
) //)
//
var _ relation.GroupModelInterface = (*GroupGorm)(nil) //var _ relation.GroupModelInterface = (*GroupGorm)(nil)
//
type GroupGorm struct { //type GroupGorm struct {
*MetaDB // *MetaDB
} //}
//
func NewGroupDB(db *gorm.DB) relation.GroupModelInterface { //func NewGroupDB(db *gorm.DB) relation.GroupModelInterface {
return &GroupGorm{NewMetaDB(db, &relation.GroupModel{})} // return &GroupGorm{NewMetaDB(db, &relation.GroupModel{})}
} //}
//
func (g *GroupGorm) NewTx(tx any) relation.GroupModelInterface { //func (g *GroupGorm) NewTx(tx any) relation.GroupModelInterface {
return &GroupGorm{NewMetaDB(tx.(*gorm.DB), &relation.GroupModel{})} // return &GroupGorm{NewMetaDB(tx.(*gorm.DB), &relation.GroupModel{})}
} //}
//
func (g *GroupGorm) Create(ctx context.Context, groups []*relation.GroupModel) (err error) { //func (g *GroupGorm) Create(ctx context.Context, groups []*relation.GroupModel) (err error) {
return utils.Wrap(g.DB.Create(&groups).Error, "") // return utils.Wrap(g.DB.Create(&groups).Error, "")
} //}
//
func (g *GroupGorm) UpdateMap(ctx context.Context, groupID string, args map[string]interface{}) (err error) { //func (g *GroupGorm) UpdateMap(ctx context.Context, groupID string, args map[string]any) (err error) {
return utils.Wrap(g.DB.Where("group_id = ?", groupID).Model(&relation.GroupModel{}).Updates(args).Error, "") // return utils.Wrap(g.DB.Where("group_id = ?", groupID).Model(&relation.GroupModel{}).Updates(args).Error, "")
} //}
//
func (g *GroupGorm) UpdateStatus(ctx context.Context, groupID string, status int32) (err error) { //func (g *GroupGorm) UpdateStatus(ctx context.Context, groupID string, status int32) (err error) {
return utils.Wrap(g.DB.Where("group_id = ?", groupID).Model(&relation.GroupModel{}).Updates(map[string]any{"status": status}).Error, "") // return utils.Wrap(g.DB.Where("group_id = ?", groupID).Model(&relation.GroupModel{}).Updates(map[string]any{"status": status}).Error, "")
} //}
//
func (g *GroupGorm) Find(ctx context.Context, groupIDs []string) (groups []*relation.GroupModel, err error) { //func (g *GroupGorm) Find(ctx context.Context, groupIDs []string) (groups []*relation.GroupModel, err error) {
return groups, utils.Wrap(g.DB.Where("group_id in (?)", groupIDs).Find(&groups).Error, "") // return groups, utils.Wrap(g.DB.Where("group_id in (?)", groupIDs).Find(&groups).Error, "")
} //}
//
func (g *GroupGorm) Take(ctx context.Context, groupID string) (group *relation.GroupModel, err error) { //func (g *GroupGorm) Take(ctx context.Context, groupID string) (group *relation.GroupModel, err error) {
group = &relation.GroupModel{} // group = &relation.GroupModel{}
return group, utils.Wrap(g.DB.Where("group_id = ?", groupID).Take(group).Error, "") // return group, utils.Wrap(g.DB.Where("group_id = ?", groupID).Take(group).Error, "")
} //}
//
func (g *GroupGorm) Search(ctx context.Context, keyword string, pageNumber, showNumber int32) (total uint32, groups []*relation.GroupModel, err error) { //func (g *GroupGorm) Search(ctx context.Context, keyword string, pageNumber, showNumber int32) (total uint32, groups []*relation.GroupModel, err error) {
db := g.DB // db := g.DB
db = db.WithContext(ctx).Where("status!=?", constant.GroupStatusDismissed) // db = db.WithContext(ctx).Where("status!=?", constant.GroupStatusDismissed)
return ormutil.GormSearch[relation.GroupModel](db, []string{"name"}, keyword, pageNumber, showNumber) // return ormutil.GormSearch[relation.GroupModel](db, []string{"name"}, keyword, pageNumber, showNumber)
} //}
//
func (g *GroupGorm) GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error) { //func (g *GroupGorm) GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error) {
return groupIDs, utils.Wrap(g.DB.Model(&relation.GroupModel{}).Where("group_type = ? ", groupType).Pluck("group_id", &groupIDs).Error, "") // return groupIDs, utils.Wrap(g.DB.Model(&relation.GroupModel{}).Where("group_type = ? ", groupType).Pluck("group_id", &groupIDs).Error, "")
} //}
//
func (g *GroupGorm) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) { //func (g *GroupGorm) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
db := g.db(ctx).Model(&relation.GroupModel{}) // db := g.db(ctx).Model(&relation.GroupModel{})
if before != nil { // if before != nil {
db = db.Where("create_time < ?", before) // db = db.Where("create_time < ?", before)
} // }
if err := db.Count(&count).Error; err != nil { // if err := db.Count(&count).Error; err != nil {
return 0, err // return 0, err
} // }
return count, nil // return count, nil
} //}
//
func (g *GroupGorm) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) { //func (g *GroupGorm) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
var res []struct { // var res []struct {
Date time.Time `gorm:"column:date"` // Date time.Time `gorm:"column:date"`
Count int64 `gorm:"column:count"` // Count int64 `gorm:"column:count"`
} // }
err := g.db(ctx).Model(&relation.GroupModel{}).Select("DATE(create_time) AS date, count(1) AS count").Where("create_time >= ? and create_time < ?", start, end).Group("date").Find(&res).Error // err := g.db(ctx).Model(&relation.GroupModel{}).Select("DATE(create_time) AS date, count(1) AS count").Where("create_time >= ? and create_time < ?", start, end).Group("date").Find(&res).Error
if err != nil { // if err != nil {
return nil, errs.Wrap(err) // return nil, errs.Wrap(err)
} // }
v := make(map[string]int64) // v := make(map[string]int64)
for _, r := range res { // for _, r := range res {
v[r.Date.Format("2006-01-02")] = r.Count // v[r.Date.Format("2006-01-02")] = r.Count
} // }
return v, nil // return v, nil
} //}
//
func (g *GroupGorm) FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*relation.GroupModel, err error) { //func (g *GroupGorm) FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*relation.GroupModel, err error) {
return groups, utils.Wrap(g.DB.Where("group_id in (?) and status != ?", groupIDs, constant.GroupStatusDismissed).Find(&groups).Error, "") // return groups, utils.Wrap(g.DB.Where("group_id in (?) and status != ?", groupIDs, constant.GroupStatusDismissed).Find(&groups).Error, "")
} //}

@ -14,105 +14,106 @@
package relation package relation
import ( //
"context" //import (
// "context"
"github.com/OpenIMSDK/tools/ormutil" //
// "github.com/OpenIMSDK/tools/ormutil"
"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 GroupRequestGorm struct { //
*MetaDB //type GroupRequestGorm struct {
} // *MetaDB
//}
func NewGroupRequest(db *gorm.DB) relation.GroupRequestModelInterface { //
return &GroupRequestGorm{ //func NewGroupRequest(db *gorm.DB) relation.GroupRequestModelInterface {
NewMetaDB(db, &relation.GroupRequestModel{}), // return &GroupRequestGorm{
} // NewMetaDB(db, &relation.GroupRequestModel{}),
} // }
//}
func (g *GroupRequestGorm) NewTx(tx any) relation.GroupRequestModelInterface { //
return &GroupRequestGorm{NewMetaDB(tx.(*gorm.DB), &relation.GroupRequestModel{})} //func (g *GroupRequestGorm) NewTx(tx any) relation.GroupRequestModelInterface {
} // return &GroupRequestGorm{NewMetaDB(tx.(*gorm.DB), &relation.GroupRequestModel{})}
//}
func (g *GroupRequestGorm) Create(ctx context.Context, groupRequests []*relation.GroupRequestModel) (err error) { //
return utils.Wrap(g.DB.WithContext(ctx).Create(&groupRequests).Error, utils.GetSelfFuncName()) //func (g *GroupRequestGorm) Create(ctx context.Context, groupRequests []*relation.GroupRequestModel) (err error) {
} // return utils.Wrap(g.DB.WithContext(ctx).Create(&groupRequests).Error, utils.GetSelfFuncName())
//}
func (g *GroupRequestGorm) Delete(ctx context.Context, groupID string, userID string) (err error) { //
return utils.Wrap( //func (g *GroupRequestGorm) Delete(ctx context.Context, groupID string, userID string) (err error) {
g.DB.WithContext(ctx). // return utils.Wrap(
Where("group_id = ? and user_id = ? ", groupID, userID). // g.DB.WithContext(ctx).
Delete(&relation.GroupRequestModel{}). // Where("group_id = ? and user_id = ? ", groupID, userID).
Error, // Delete(&relation.GroupRequestModel{}).
utils.GetSelfFuncName(), // Error,
) // utils.GetSelfFuncName(),
} // )
//}
func (g *GroupRequestGorm) UpdateHandler( //
ctx context.Context, //func (g *GroupRequestGorm) UpdateHandler(
groupID string, // ctx context.Context,
userID string, // groupID string,
handledMsg string, // userID string,
handleResult int32, // handledMsg string,
) (err error) { // handleResult int32,
return utils.Wrap( //) (err error) {
g.DB.WithContext(ctx). // return utils.Wrap(
Model(&relation.GroupRequestModel{}). // g.DB.WithContext(ctx).
Where("group_id = ? and user_id = ? ", groupID, userID). // Model(&relation.GroupRequestModel{}).
Updates(map[string]any{ // Where("group_id = ? and user_id = ? ", groupID, userID).
"handle_msg": handledMsg, // Updates(map[string]any{
"handle_result": handleResult, // "handle_msg": handledMsg,
}). // "handle_result": handleResult,
Error, // }).
utils.GetSelfFuncName(), // Error,
) // utils.GetSelfFuncName(),
} // )
//}
func (g *GroupRequestGorm) Take( //
ctx context.Context, //func (g *GroupRequestGorm) Take(
groupID string, // ctx context.Context,
userID string, // groupID string,
) (groupRequest *relation.GroupRequestModel, err error) { // userID string,
groupRequest = &relation.GroupRequestModel{} //) (groupRequest *relation.GroupRequestModel, err error) {
return groupRequest, utils.Wrap( // groupRequest = &relation.GroupRequestModel{}
g.DB.WithContext(ctx).Where("group_id = ? and user_id = ? ", groupID, userID).Take(groupRequest).Error, // return groupRequest, utils.Wrap(
utils.GetSelfFuncName(), // g.DB.WithContext(ctx).Where("group_id = ? and user_id = ? ", groupID, userID).Take(groupRequest).Error,
) // utils.GetSelfFuncName(),
} // )
//}
func (g *GroupRequestGorm) Page( //
ctx context.Context, //func (g *GroupRequestGorm) Page(
userID string, // ctx context.Context,
pageNumber, showNumber int32, // userID string,
) (total uint32, groups []*relation.GroupRequestModel, err error) { // pageNumber, showNumber int32,
return ormutil.GormSearch[relation.GroupRequestModel]( //) (total uint32, groups []*relation.GroupRequestModel, err error) {
g.DB.WithContext(ctx).Where("user_id = ?", userID), // return ormutil.GormSearch[relation.GroupRequestModel](
nil, // g.DB.WithContext(ctx).Where("user_id = ?", userID),
"", // nil,
pageNumber, // "",
showNumber, // pageNumber,
) // showNumber,
} // )
//}
func (g *GroupRequestGorm) PageGroup( //
ctx context.Context, //func (g *GroupRequestGorm) PageGroup(
groupIDs []string, // ctx context.Context,
pageNumber, showNumber int32, // groupIDs []string,
) (total uint32, groups []*relation.GroupRequestModel, err error) { // pageNumber, showNumber int32,
return ormutil.GormPage[relation.GroupRequestModel]( //) (total uint32, groups []*relation.GroupRequestModel, err error) {
g.DB.WithContext(ctx).Where("group_id in ?", groupIDs), // return ormutil.GormPage[relation.GroupRequestModel](
pageNumber, // g.DB.WithContext(ctx).Where("group_id in ?", groupIDs),
showNumber, // pageNumber,
) // showNumber,
} // )
//}
func (g *GroupRequestGorm) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (total int64, groupRequests []*relation.GroupRequestModel, err error) { //
err = g.DB.WithContext(ctx).Where("group_id = ? and user_id in ?", groupID, userIDs).Find(&groupRequests).Error //func (g *GroupRequestGorm) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (total int64, groupRequests []*relation.GroupRequestModel, err error) {
return int64(len(groupRequests)), groupRequests, utils.Wrap(err, utils.GetSelfFuncName()) // err = g.DB.WithContext(ctx).Where("group_id = ? and user_id in ?", groupID, userIDs).Find(&groupRequests).Error
} // return int64(len(groupRequests)), groupRequests, utils.Wrap(err, utils.GetSelfFuncName())
//}

@ -1,49 +1,49 @@
package relation package relation
import ( //import (
"context" // "context"
"time" // "time"
//
"github.com/OpenIMSDK/tools/errs" // "github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/ormutil" // "github.com/OpenIMSDK/tools/ormutil"
"gorm.io/gorm" // "gorm.io/gorm"
//
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" // relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
) //)
//
type LogGorm struct { //type LogGorm struct {
db *gorm.DB // db *gorm.DB
} //}
//
func (l *LogGorm) Create(ctx context.Context, log []*relationtb.Log) error { //func (l *LogGorm) Create(ctx context.Context, log []*relationtb.Log) error {
return errs.Wrap(l.db.WithContext(ctx).Create(log).Error) // return errs.Wrap(l.db.WithContext(ctx).Create(log).Error)
} //}
//
func (l *LogGorm) Search(ctx context.Context, keyword string, start time.Time, end time.Time, pageNumber int32, showNumber int32) (uint32, []*relationtb.Log, error) { //func (l *LogGorm) Search(ctx context.Context, keyword string, start time.Time, end time.Time, pageNumber int32, showNumber int32) (uint32, []*relationtb.Log, error) {
db := l.db.WithContext(ctx).Where("create_time >= ?", start) // db := l.db.WithContext(ctx).Where("create_time >= ?", start)
if end.UnixMilli() != 0 { // if end.UnixMilli() != 0 {
db = l.db.WithContext(ctx).Where("create_time <= ?", end) // db = l.db.WithContext(ctx).Where("create_time <= ?", end)
} // }
db = db.Order("create_time desc") // db = db.Order("create_time desc")
return ormutil.GormSearch[relationtb.Log](db, []string{"user_id"}, keyword, pageNumber, showNumber) // return ormutil.GormSearch[relationtb.Log](db, []string{"user_id"}, keyword, pageNumber, showNumber)
} //}
//
func (l *LogGorm) Delete(ctx context.Context, logIDs []string, userID string) error { //func (l *LogGorm) Delete(ctx context.Context, logIDs []string, userID string) error {
if userID == "" { // if userID == "" {
return errs.Wrap(l.db.WithContext(ctx).Where("log_id in ?", logIDs).Delete(&relationtb.Log{}).Error) // return errs.Wrap(l.db.WithContext(ctx).Where("log_id in ?", logIDs).Delete(&relationtb.Log{}).Error)
} // }
return errs.Wrap(l.db.WithContext(ctx).Where("log_id in ? and user_id=?", logIDs, userID).Delete(&relationtb.Log{}).Error) // return errs.Wrap(l.db.WithContext(ctx).Where("log_id in ? and user_id=?", logIDs, userID).Delete(&relationtb.Log{}).Error)
} //}
//
func (l *LogGorm) Get(ctx context.Context, logIDs []string, userID string) ([]*relationtb.Log, error) { //func (l *LogGorm) Get(ctx context.Context, logIDs []string, userID string) ([]*relationtb.Log, error) {
var logs []*relationtb.Log // var logs []*relationtb.Log
if userID == "" { // if userID == "" {
return logs, errs.Wrap(l.db.WithContext(ctx).Where("log_id in ?", logIDs).Find(&logs).Error) // return logs, errs.Wrap(l.db.WithContext(ctx).Where("log_id in ?", logIDs).Find(&logs).Error)
} // }
return logs, errs.Wrap(l.db.WithContext(ctx).Where("log_id in ? and user_id=?", logIDs, userID).Find(&logs).Error) // return logs, errs.Wrap(l.db.WithContext(ctx).Where("log_id in ? and user_id=?", logIDs, userID).Find(&logs).Error)
} //}
//
func NewLogGorm(db *gorm.DB) relationtb.LogInterface { //func NewLogGorm(db *gorm.DB) relationtb.LogInterface {
db.AutoMigrate(&relationtb.Log{}) // db.AutoMigrate(&relationtb.Log{})
return &LogGorm{db: db} // return &LogGorm{db: db}
} //}

@ -14,40 +14,41 @@
package relation package relation
import ( //
"context" //import (
// "context"
"gorm.io/gorm" //
// "gorm.io/gorm"
"github.com/OpenIMSDK/tools/errs" //
// "github.com/OpenIMSDK/tools/errs"
"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 ObjectInfoGorm struct { //
*MetaDB //type ObjectInfoGorm struct {
} // *MetaDB
//}
func NewObjectInfo(db *gorm.DB) relation.ObjectInfoModelInterface { //
return &ObjectInfoGorm{ //func NewObjectInfo(db *gorm.DB) relation.ObjectInfoModelInterface {
NewMetaDB(db, &relation.ObjectModel{}), // return &ObjectInfoGorm{
} // NewMetaDB(db, &relation.ObjectModel{}),
} // }
//}
func (o *ObjectInfoGorm) NewTx(tx any) relation.ObjectInfoModelInterface { //
return &ObjectInfoGorm{ //func (o *ObjectInfoGorm) NewTx(tx any) relation.ObjectInfoModelInterface {
NewMetaDB(tx.(*gorm.DB), &relation.ObjectModel{}), // return &ObjectInfoGorm{
} // NewMetaDB(tx.(*gorm.DB), &relation.ObjectModel{}),
} // }
//}
func (o *ObjectInfoGorm) SetObject(ctx context.Context, obj *relation.ObjectModel) (err error) { //
if err := o.DB.WithContext(ctx).Where("name = ?", obj.Name).FirstOrCreate(obj).Error; err != nil { //func (o *ObjectInfoGorm) SetObject(ctx context.Context, obj *relation.ObjectModel) (err error) {
return errs.Wrap(err) // if err := o.DB.WithContext(ctx).Where("name = ?", obj.Name).FirstOrCreate(obj).Error; err != nil {
} // return errs.Wrap(err)
return nil // }
} // return nil
//}
func (o *ObjectInfoGorm) Take(ctx context.Context, name string) (info *relation.ObjectModel, err error) { //
info = &relation.ObjectModel{} //func (o *ObjectInfoGorm) Take(ctx context.Context, name string) (info *relation.ObjectModel, err error) {
return info, errs.Wrap(o.DB.WithContext(ctx).Where("name = ?", name).Take(info).Error) // info = &relation.ObjectModel{}
} // return info, errs.Wrap(o.DB.WithContext(ctx).Where("name = ?", name).Take(info).Error)
//}

@ -14,123 +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 &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]interface{}) (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, "") //// 获取指定用户信息 不存在,也不返回错误.
return users, err //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, "")
// return users, err
// 获取某个用户信息 不存在,则返回错误. //}
func (u *UserGorm) Take(ctx context.Context, userID string) (user *relation.UserModel, err error) { //
user = &relation.UserModel{} //// 获取某个用户信息 不存在,则返回错误.
err = utils.Wrap(u.db(ctx).Where("user_id = ?", userID).Take(&user).Error, "") //func (u *UserGorm) Take(ctx context.Context, userID string) (user *relation.UserModel, err error) {
return user, err // user = &relation.UserModel{}
} // err = utils.Wrap(u.db(ctx).Where("user_id = ?", userID).Take(&user).Error, "")
// return user, err
// 获取用户信息 不存在,不返回错误. //}
func (u *UserGorm) Page( //
ctx context.Context, //// 获取用户信息 不存在,不返回错误.
pageNumber, showNumber int32, //func (u *UserGorm) Page(
) (users []*relation.UserModel, count int64, err error) { // ctx context.Context,
err = utils.Wrap(u.db(ctx).Count(&count).Error, "") // pageNumber, showNumber int32,
if err != nil { //) (users []*relation.UserModel, count int64, err error) {
return // err = utils.Wrap(u.db(ctx).Count(&count).Error, "")
} // if err != nil {
err = utils.Wrap( // return
u.db(ctx). // }
Limit(int(showNumber)). // err = utils.Wrap(
Offset(int((pageNumber-1)*showNumber)). // u.db(ctx).
Find(&users). // Limit(int(showNumber)).
Order("create_time DESC"). // Offset(int((pageNumber-1)*showNumber)).
Error, // Find(&users).
"", // Order("create_time DESC").
) // Error,
return // "",
} // )
// return
// 获取所有用户ID. //}
func (u *UserGorm) GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error) { //
if pageNumber == 0 || showNumber == 0 { //// 获取所有用户ID.
return userIDs, errs.Wrap(u.db(ctx).Pluck("user_id", &userIDs).Error) //func (u *UserGorm) GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error) {
} else { // if pageNumber == 0 || showNumber == 0 {
return userIDs, errs.Wrap(u.db(ctx).Limit(int(showNumber)).Offset(int((pageNumber-1)*showNumber)).Pluck("user_id", &userIDs).Error) // return userIDs, errs.Wrap(u.db(ctx).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 //
return opt, err //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
// return opt, err
func (u *UserGorm) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) { //}
db := u.db(ctx).Model(&relation.UserModel{}) //
if before != nil { //func (u *UserGorm) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
db = db.Where("create_time < ?", before) // db := u.db(ctx).Model(&relation.UserModel{})
} // if before != nil {
if err := db.Count(&count).Error; err != nil { // db = db.Where("create_time < ?", before)
return 0, err // }
} // if err := db.Count(&count).Error; err != nil {
return count, nil // return 0, err
} // }
// return count, nil
func (u *UserGorm) CountRangeEverydayTotal( //}
ctx context.Context, //
start time.Time, //func (u *UserGorm) CountRangeEverydayTotal(
end time.Time, // ctx context.Context,
) (map[string]int64, error) { // start time.Time,
var res []struct { // end time.Time,
Date time.Time `gorm:"column:date"` //) (map[string]int64, error) {
Count int64 `gorm:"column:count"` // var res []struct {
} // Date time.Time `gorm:"column:date"`
err := u.db(ctx). // Count int64 `gorm:"column:count"`
Model(&relation.UserModel{}). // }
Select("DATE(create_time) AS date, count(1) AS count"). // err := u.db(ctx).
Where("create_time >= ? and create_time < ?", start, end). // Model(&relation.UserModel{}).
Group("date"). // Select("DATE(create_time) AS date, count(1) AS count").
Find(&res). // Where("create_time >= ? and create_time < ?", start, end).
Error // Group("date").
if err != nil { // Find(&res).
return nil, errs.Wrap(err) // Error
} // if err != nil {
v := make(map[string]int64) // return nil, errs.Wrap(err)
for _, r := range res { // }
v[r.Date.Format("2006-01-02")] = r.Count // v := make(map[string]int64)
} // for _, r := range res {
return v, nil // v[r.Date.Format("2006-01-02")] = r.Count
} // }
// return v, nil
//}

@ -46,6 +46,10 @@ type Controller struct {
impl s3.Interface impl s3.Interface
} }
func (c *Controller) Engine() string {
return c.impl.Engine()
}
func (c *Controller) HashPath(md5 string) string { func (c *Controller) HashPath(md5 string) string {
return path.Join(hashPath, md5) return path.Join(hashPath, md5)
} }

@ -10,4 +10,4 @@ import (
) )
//go:linkname newRequest github.com/tencentyun/cos-go-sdk-v5.(*Client).newRequest //go:linkname newRequest github.com/tencentyun/cos-go-sdk-v5.(*Client).newRequest
func newRequest(c *cos.Client, ctx context.Context, baseURL *url.URL, uri, method string, body interface{}, optQuery interface{}, optHeader interface{}) (req *http.Request, err error) func newRequest(c *cos.Client, ctx context.Context, baseURL *url.URL, uri, method string, body any, optQuery any, optHeader any) (req *http.Request, err error)

@ -26,7 +26,7 @@ import (
func signHeader(c oss.Conn, req *http.Request, canonicalizedResource string) func signHeader(c oss.Conn, req *http.Request, canonicalizedResource string)
//go:linkname getURLParams github.com/aliyun/aliyun-oss-go-sdk/oss.Conn.getURLParams //go:linkname getURLParams github.com/aliyun/aliyun-oss-go-sdk/oss.Conn.getURLParams
func getURLParams(c oss.Conn, params map[string]interface{}) string func getURLParams(c oss.Conn, params map[string]any) string
//go:linkname getURL github.com/aliyun/aliyun-oss-go-sdk/oss.urlMaker.getURL //go:linkname getURL github.com/aliyun/aliyun-oss-go-sdk/oss.urlMaker.getURL
func getURL(um urlMaker, bucket, object, params string) *url.URL func getURL(um urlMaker, bucket, object, params string) *url.URL

@ -39,7 +39,7 @@ func (BlackModel) TableName() string {
type BlackModelInterface interface { type BlackModelInterface interface {
Create(ctx context.Context, blacks []*BlackModel) (err error) Create(ctx context.Context, blacks []*BlackModel) (err error)
Delete(ctx context.Context, blacks []*BlackModel) (err error) Delete(ctx context.Context, blacks []*BlackModel) (err error)
UpdateByMap(ctx context.Context, ownerUserID, blockUserID string, args map[string]interface{}) (err error) UpdateByMap(ctx context.Context, ownerUserID, blockUserID string, args map[string]any) (err error)
Update(ctx context.Context, blacks []*BlackModel) (err error) Update(ctx context.Context, blacks []*BlackModel) (err error)
Find(ctx context.Context, blacks []*BlackModel) (blackList []*BlackModel, err error) Find(ctx context.Context, blacks []*BlackModel) (blackList []*BlackModel, err error)
Take(ctx context.Context, ownerUserID, blockUserID string) (black *BlackModel, err error) Take(ctx context.Context, ownerUserID, blockUserID string) (black *BlackModel, err error)

@ -16,6 +16,7 @@ package relation
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time" "time"
) )
@ -23,25 +24,46 @@ const (
conversationModelTableName = "conversations" conversationModelTableName = "conversations"
) )
//type ConversationModel struct {
// OwnerUserID string `gorm:"column:owner_user_id;primary_key;type:char(128)" json:"OwnerUserID"`
// ConversationID string `gorm:"column:conversation_id;primary_key;type:char(128)" json:"conversationID"`
// ConversationType int32 `gorm:"column:conversation_type" json:"conversationType"`
// UserID string `gorm:"column:user_id;type:char(64)" json:"userID"`
// GroupID string `gorm:"column:group_id;type:char(128)" json:"groupID"`
// RecvMsgOpt int32 `gorm:"column:recv_msg_opt" json:"recvMsgOpt"`
// IsPinned bool `gorm:"column:is_pinned" json:"isPinned"`
// IsPrivateChat bool `gorm:"column:is_private_chat" json:"isPrivateChat"`
// BurnDuration int32 `gorm:"column:burn_duration;default:30" json:"burnDuration"`
// GroupAtType int32 `gorm:"column:group_at_type" json:"groupAtType"`
// AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
// Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
// MaxSeq int64 `gorm:"column:max_seq" json:"maxSeq"`
// MinSeq int64 `gorm:"column:min_seq" json:"minSeq"`
// CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"`
// IsMsgDestruct bool `gorm:"column:is_msg_destruct;default:false"`
// MsgDestructTime int64 `gorm:"column:msg_destruct_time;default:604800"`
// LatestMsgDestructTime time.Time `gorm:"column:latest_msg_destruct_time;autoCreateTime"`
//}
type ConversationModel struct { type ConversationModel struct {
OwnerUserID string `gorm:"column:owner_user_id;primary_key;type:char(128)" json:"OwnerUserID"` OwnerUserID string `bson:"owner_user_id"`
ConversationID string `gorm:"column:conversation_id;primary_key;type:char(128)" json:"conversationID"` ConversationID string `bson:"conversation_id"`
ConversationType int32 `gorm:"column:conversation_type" json:"conversationType"` ConversationType int32 `bson:"conversation_type"`
UserID string `gorm:"column:user_id;type:char(64)" json:"userID"` UserID string `bson:"user_id"`
GroupID string `gorm:"column:group_id;type:char(128)" json:"groupID"` GroupID string `bson:"group_id"`
RecvMsgOpt int32 `gorm:"column:recv_msg_opt" json:"recvMsgOpt"` RecvMsgOpt int32 `bson:"recv_msg_opt"`
IsPinned bool `gorm:"column:is_pinned" json:"isPinned"` IsPinned bool `bson:"is_pinned"`
IsPrivateChat bool `gorm:"column:is_private_chat" json:"isPrivateChat"` IsPrivateChat bool `bson:"is_private_chat"`
BurnDuration int32 `gorm:"column:burn_duration;default:30" json:"burnDuration"` BurnDuration int32 `bson:"burn_duration"`
GroupAtType int32 `gorm:"column:group_at_type" json:"groupAtType"` GroupAtType int32 `bson:"group_at_type"`
AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"` AttachedInfo string `bson:"attached_info"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"` Ex string `bson:"ex"`
MaxSeq int64 `gorm:"column:max_seq" json:"maxSeq"` MaxSeq int64 `bson:"max_seq"`
MinSeq int64 `gorm:"column:min_seq" json:"minSeq"` MinSeq int64 `bson:"min_seq"`
CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"` CreateTime time.Time `bson:"create_time"`
IsMsgDestruct bool `gorm:"column:is_msg_destruct;default:false"` IsMsgDestruct bool `bson:"is_msg_destruct"`
MsgDestructTime int64 `gorm:"column:msg_destruct_time;default:604800"` MsgDestructTime int64 `bson:"msg_destruct_time"`
LatestMsgDestructTime time.Time `gorm:"column:latest_msg_destruct_time;autoCreateTime"` LatestMsgDestructTime time.Time `bson:"latest_msg_destruct_time"`
} }
func (ConversationModel) TableName() string { func (ConversationModel) TableName() string {
@ -51,7 +73,7 @@ func (ConversationModel) TableName() string {
type ConversationModelInterface interface { type ConversationModelInterface interface {
Create(ctx context.Context, conversations []*ConversationModel) (err error) Create(ctx context.Context, conversations []*ConversationModel) (err error)
Delete(ctx context.Context, groupIDs []string) (err error) Delete(ctx context.Context, groupIDs []string) (err error)
UpdateByMap(ctx context.Context, userIDs []string, conversationID string, args map[string]interface{}) (rows int64, err error) UpdateByMap(ctx context.Context, userIDs []string, conversationID string, args map[string]any) (rows int64, err error)
Update(ctx context.Context, conversation *ConversationModel) (err error) Update(ctx context.Context, conversation *ConversationModel) (err error)
Find(ctx context.Context, ownerUserID string, conversationIDs []string) (conversations []*ConversationModel, err error) Find(ctx context.Context, ownerUserID string, conversationIDs []string) (conversations []*ConversationModel, err error)
FindUserID(ctx context.Context, userIDs []string, conversationIDs []string) ([]string, error) FindUserID(ctx context.Context, userIDs []string, conversationIDs []string) ([]string, error)
@ -61,13 +83,12 @@ type ConversationModelInterface interface {
FindUserIDAllConversations(ctx context.Context, userID string) (conversations []*ConversationModel, err error) FindUserIDAllConversations(ctx context.Context, userID string) (conversations []*ConversationModel, err error)
FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error) GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error)
FindSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error) //FindSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
GetAllConversationIDs(ctx context.Context) ([]string, error) GetAllConversationIDs(ctx context.Context) ([]string, error)
GetAllConversationIDsNumber(ctx context.Context) (int64, error) GetAllConversationIDsNumber(ctx context.Context) (int64, error)
PageConversationIDs(ctx context.Context, pageNumber, showNumber int32) (conversationIDs []string, err error) PageConversationIDs(ctx context.Context, pagination pagination.Pagination) (conversationIDs []string, err error)
GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (hashReadSeqs map[string]int64, err error) //GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (hashReadSeqs map[string]int64, err error)
GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*ConversationModel, error) GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*ConversationModel, error)
GetConversationIDsNeedDestruct(ctx context.Context) ([]*ConversationModel, error) GetConversationIDsNeedDestruct(ctx context.Context) ([]*ConversationModel, error)
GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error) GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)
NewTx(tx any) ConversationModelInterface
} }

@ -17,62 +17,65 @@ package relation
import ( import (
"context" "context"
"time" "time"
"go.mongodb.org/mongo-driver/bson/primitive"
) )
const ( const (
FriendModelTableName = "friends" FriendModelCollectionName = "friends"
) )
// OwnerUserID string `gorm:"column:owner_user_id;primary_key;size:64"`
// FriendUserID string `gorm:"column:friend_user_id;primary_key;size:64"`
// Remark string `gorm:"column:remark;size:255"`
// CreateTime time.Time `gorm:"column:create_time;autoCreateTime"`
// AddSource int32 `gorm:"column:add_source"`
// OperatorUserID string `gorm:"column:operator_user_id;size:64"`
// Ex string `gorm:"column:ex;size:1024"`
// FriendModel represents the data structure for a friend relationship in MongoDB.
type FriendModel struct { type FriendModel struct {
OwnerUserID string `gorm:"column:owner_user_id;primary_key;size:64"` ID primitive.ObjectID `bson:"_id,omitempty"`
FriendUserID string `gorm:"column:friend_user_id;primary_key;size:64"` OwnerUserID string `bson:"owner_user_id"`
Remark string `gorm:"column:remark;size:255"` FriendUserID string `bson:"friend_user_id"`
CreateTime time.Time `gorm:"column:create_time;autoCreateTime"` Remark string `bson:"remark"`
AddSource int32 `gorm:"column:add_source"` CreateTime time.Time `bson:"create_time"`
OperatorUserID string `gorm:"column:operator_user_id;size:64"` AddSource int32 `bson:"add_source"`
Ex string `gorm:"column:ex;size:1024"` OperatorUserID string `bson:"operator_user_id"`
Ex string `bson:"ex"`
} }
func (FriendModel) TableName() string { // CollectionName returns the name of the MongoDB collection.
return FriendModelTableName func (FriendModel) CollectionName() string {
return FriendModelCollectionName
} }
// FriendModelInterface defines the operations for managing friends in MongoDB.
type FriendModelInterface interface { type FriendModelInterface interface {
// 插入多条记录 // Create inserts multiple friend records.
Create(ctx context.Context, friends []*FriendModel) (err error) Create(ctx context.Context, friends []*FriendModel) (err error)
// 删除ownerUserID指定的好友 // Delete removes specified friends of the owner user.
Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error) Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error)
// 更新ownerUserID单个好友信息 更新零值 // UpdateByMap updates specific fields of a friend document using a map.
UpdateByMap(ctx context.Context, ownerUserID string, friendUserID string, args map[string]interface{}) (err error) UpdateByMap(ctx context.Context, ownerUserID string, friendUserID string, args map[string]any) (err error)
// 更新好友信息的非零值 // Update modifies multiple friend documents.
Update(ctx context.Context, friends []*FriendModel) (err error) // Update(ctx context.Context, friends []*FriendModel) (err error)
// 更新好友备注(也支持零值 // UpdateRemark updates the remark for a specific friend.
UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error) UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error)
// 获取单个好友信息,如没找到 返回错误 // Take retrieves a single friend document. Returns an error if not found.
Take(ctx context.Context, ownerUserID, friendUserID string) (friend *FriendModel, err error) Take(ctx context.Context, ownerUserID, friendUserID string) (friend *FriendModel, err error)
// 查找好友关系,如果是双向关系,则都返回 // FindUserState finds the friendship status between two users.
FindUserState(ctx context.Context, userID1, userID2 string) (friends []*FriendModel, err error) FindUserState(ctx context.Context, userID1, userID2 string) (friends []*FriendModel, err error)
// 获取 owner指定的好友列表 如果有friendUserIDs不存在也不返回错误 // FindFriends retrieves a list of friends for a given owner. Missing friends do not cause an error.
FindFriends(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*FriendModel, err error) FindFriends(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*FriendModel, err error)
// 获取哪些人添加了friendUserID 如果有ownerUserIDs不存在也不返回错误 // FindReversalFriends finds users who have added the specified user as a friend.
FindReversalFriends( FindReversalFriends(ctx context.Context, friendUserID string, ownerUserIDs []string) (friends []*FriendModel, err error)
ctx context.Context, // FindOwnerFriends retrieves a paginated list of friends for a given owner.
friendUserID string, FindOwnerFriends(ctx context.Context, ownerUserID string, pageNumber, showNumber int32) (friends []*FriendModel, total int64, err error)
ownerUserIDs []string, // FindInWhoseFriends finds users who have added the specified user as a friend, with pagination.
) (friends []*FriendModel, err error) FindInWhoseFriends(ctx context.Context, friendUserID string, pageNumber, showNumber int32) (friends []*FriendModel, total int64, err error)
// 获取ownerUserID好友列表 支持翻页 // FindFriendUserIDs retrieves a list of friend user IDs for a given owner.
FindOwnerFriends(
ctx context.Context,
ownerUserID string,
pageNumber, showNumber int32,
) (friends []*FriendModel, total int64, err error)
// 获取哪些人添加了friendUserID 支持翻页
FindInWhoseFriends(
ctx context.Context,
friendUserID string,
pageNumber, showNumber int32,
) (friends []*FriendModel, total int64, err error)
// 获取好友UserID列表
FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error) FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
// NewTx creates a new transaction.
NewTx(tx any) FriendModelInterface NewTx(tx any) FriendModelInterface
} }

@ -17,50 +17,47 @@ package relation
import ( import (
"context" "context"
"time" "time"
"go.mongodb.org/mongo-driver/bson/primitive"
) )
const FriendRequestModelTableName = "friend_requests" const FriendRequestModelCollectionName = "friend_requests"
type FriendRequestModel struct { type FriendRequestModel struct {
FromUserID string `gorm:"column:from_user_id;primary_key;size:64"` ID primitive.ObjectID `bson:"_id,omitempty"`
ToUserID string `gorm:"column:to_user_id;primary_key;size:64"` FromUserID string `bson:"from_user_id"`
HandleResult int32 `gorm:"column:handle_result"` ToUserID string `bson:"to_user_id"`
ReqMsg string `gorm:"column:req_msg;size:255"` HandleResult int32 `bson:"handle_result"`
CreateTime time.Time `gorm:"column:create_time; autoCreateTime"` ReqMsg string `bson:"req_msg"`
HandlerUserID string `gorm:"column:handler_user_id;size:64"` CreateTime time.Time `bson:"create_time"`
HandleMsg string `gorm:"column:handle_msg;size:255"` HandlerUserID string `bson:"handler_user_id"`
HandleTime time.Time `gorm:"column:handle_time"` HandleMsg string `bson:"handle_msg"`
Ex string `gorm:"column:ex;size:1024"` HandleTime time.Time `bson:"handle_time"`
Ex string `bson:"ex"`
} }
func (FriendRequestModel) TableName() string { func (FriendRequestModel) CollectionName() string {
return FriendRequestModelTableName return FriendRequestModelCollectionName
} }
type FriendRequestModelInterface interface { type FriendRequestModelInterface interface {
// 插入多条记录 // Insert multiple records
Create(ctx context.Context, friendRequests []*FriendRequestModel) (err error) Create(ctx context.Context, friendRequests []*FriendRequestModel) (err error)
// 删除记录 // Delete record
Delete(ctx context.Context, fromUserID, toUserID string) (err error) Delete(ctx context.Context, fromUserID, toUserID string) (err error)
// 更新零值 // Update with zero values
UpdateByMap(ctx context.Context, formUserID string, toUserID string, args map[string]interface{}) (err error) UpdateByMap(ctx context.Context, formUserID string, toUserID string, args map[string]any) (err error)
// 更新多条记录 (非零值) // Update multiple records (non-zero values)
Update(ctx context.Context, friendRequest *FriendRequestModel) (err error) Update(ctx context.Context, friendRequest *FriendRequestModel) (err error)
// 获取来指定用户的好友申请 未找到 不返回错误 // Get friend requests sent to a specific user, no error returned if not found
Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error) Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error)
Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error) Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error)
// 获取toUserID收到的好友申请列表 // Get list of friend requests received by toUserID
FindToUserID( FindToUserID(ctx context.Context,toUserID string,pageNumber, showNumber int32,) (friendRequests []*FriendRequestModel, total int64, err error)
ctx context.Context, // Get list of friend requests sent by fromUserID
toUserID string, FindFromUserID(ctx context.Context,fromUserID string,pageNumber, showNumber int32,) (friendRequests []*FriendRequestModel, total int64, err error)
pageNumber, showNumber int32,
) (friendRequests []*FriendRequestModel, total int64, err error)
// 获取fromUserID发出去的好友申请列表
FindFromUserID(
ctx context.Context,
fromUserID string,
pageNumber, showNumber int32,
) (friendRequests []*FriendRequestModel, total int64, err error)
FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*FriendRequestModel, err error) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*FriendRequestModel, err error)
NewTx(tx any) FriendRequestModelInterface NewTx(tx any) FriendRequestModelInterface
// Check if the record exists
Exist(ctx context.Context, userID string) (exist bool, err error)
} }

@ -16,6 +16,7 @@ package relation
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time" "time"
) )
@ -23,22 +24,40 @@ const (
GroupModelTableName = "groups" GroupModelTableName = "groups"
) )
//type GroupModel struct {
// GroupID string `gorm:"column:group_id;primary_key;size:64" json:"groupID" binding:"required"`
// GroupName string `gorm:"column:name;size:255" json:"groupName"`
// Notification string `gorm:"column:notification;size:255" json:"notification"`
// Introduction string `gorm:"column:introduction;size:255" json:"introduction"`
// FaceURL string `gorm:"column:face_url;size:255" json:"faceURL"`
// CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"`
// Ex string `gorm:"column:ex" json:"ex;size:1024"`
// Status int32 `gorm:"column:status"`
// CreatorUserID string `gorm:"column:creator_user_id;size:64"`
// GroupType int32 `gorm:"column:group_type"`
// NeedVerification int32 `gorm:"column:need_verification"`
// LookMemberInfo int32 `gorm:"column:look_member_info" json:"lookMemberInfo"`
// ApplyMemberFriend int32 `gorm:"column:apply_member_friend" json:"applyMemberFriend"`
// NotificationUpdateTime time.Time `gorm:"column:notification_update_time"`
// NotificationUserID string `gorm:"column:notification_user_id;size:64"`
//}
type GroupModel struct { type GroupModel struct {
GroupID string `gorm:"column:group_id;primary_key;size:64" json:"groupID" binding:"required"` GroupID string `bson:"group_id"`
GroupName string `gorm:"column:name;size:255" json:"groupName"` GroupName string `bson:"group_name"`
Notification string `gorm:"column:notification;size:255" json:"notification"` Notification string `bson:"notification"`
Introduction string `gorm:"column:introduction;size:255" json:"introduction"` Introduction string `bson:"introduction"`
FaceURL string `gorm:"column:face_url;size:255" json:"faceURL"` FaceURL string `bson:"face_url"`
CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"` CreateTime time.Time `bson:"create_time"`
Ex string `gorm:"column:ex" json:"ex;size:1024"` Ex string `bson:"ex"`
Status int32 `gorm:"column:status"` Status int32 `bson:"status"`
CreatorUserID string `gorm:"column:creator_user_id;size:64"` CreatorUserID string `bson:"creator_user_id"`
GroupType int32 `gorm:"column:group_type"` GroupType int32 `bson:"group_type"`
NeedVerification int32 `gorm:"column:need_verification"` NeedVerification int32 `bson:"need_verification"`
LookMemberInfo int32 `gorm:"column:look_member_info" json:"lookMemberInfo"` LookMemberInfo int32 `bson:"look_member_info"`
ApplyMemberFriend int32 `gorm:"column:apply_member_friend" json:"applyMemberFriend"` ApplyMemberFriend int32 `bson:"apply_member_friend"`
NotificationUpdateTime time.Time `gorm:"column:notification_update_time"` NotificationUpdateTime time.Time `bson:"notification_update_time"`
NotificationUserID string `gorm:"column:notification_user_id;size:64"` NotificationUserID string `bson:"notification_user_id"`
} }
func (GroupModel) TableName() string { func (GroupModel) TableName() string {
@ -46,19 +65,12 @@ func (GroupModel) TableName() string {
} }
type GroupModelInterface interface { type GroupModelInterface interface {
NewTx(tx any) GroupModelInterface
Create(ctx context.Context, groups []*GroupModel) (err error) Create(ctx context.Context, groups []*GroupModel) (err error)
UpdateMap(ctx context.Context, groupID string, args map[string]interface{}) (err error) UpdateMap(ctx context.Context, groupID string, args map[string]any) (err error)
UpdateStatus(ctx context.Context, groupID string, status int32) (err error) UpdateState(ctx context.Context, groupID string, state int32) (err error)
Find(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error) Find(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error)
FindNotDismissedGroup(ctx context.Context, groupIDs []string) (groups []*GroupModel, err error)
Take(ctx context.Context, groupID string) (group *GroupModel, err error) Take(ctx context.Context, groupID string) (group *GroupModel, err error)
Search( Search(ctx context.Context, keyword string, pagination pagination.Pagination) (total int64, groups []*GroupModel, err error)
ctx context.Context,
keyword string,
pageNumber, showNumber int32,
) (total uint32, groups []*GroupModel, err error)
GetGroupIDsByGroupType(ctx context.Context, groupType int) (groupIDs []string, err error)
// 获取群总数 // 获取群总数
CountTotal(ctx context.Context, before *time.Time) (count int64, err error) CountTotal(ctx context.Context, before *time.Time) (count int64, err error)
// 获取范围内群增量 // 获取范围内群增量

@ -16,6 +16,7 @@ package relation
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time" "time"
) )
@ -23,18 +24,32 @@ const (
GroupMemberModelTableName = "group_members" GroupMemberModelTableName = "group_members"
) )
//type GroupMemberModel struct {
// GroupID string `gorm:"column:group_id;primary_key;size:64"`
// UserID string `gorm:"column:user_id;primary_key;size:64"`
// Nickname string `gorm:"column:nickname;size:255"`
// FaceURL string `gorm:"column:user_group_face_url;size:255"`
// RoleLevel int32 `gorm:"column:role_level"`
// JoinTime time.Time `gorm:"column:join_time"`
// JoinSource int32 `gorm:"column:join_source"`
// InviterUserID string `gorm:"column:inviter_user_id;size:64"`
// OperatorUserID string `gorm:"column:operator_user_id;size:64"`
// MuteEndTime time.Time `gorm:"column:mute_end_time"`
// Ex string `gorm:"column:ex;size:1024"`
//}
type GroupMemberModel struct { type GroupMemberModel struct {
GroupID string `gorm:"column:group_id;primary_key;size:64"` GroupID string `bson:"group_id"`
UserID string `gorm:"column:user_id;primary_key;size:64"` UserID string `bson:"user_id"`
Nickname string `gorm:"column:nickname;size:255"` Nickname string `bson:"nickname"`
FaceURL string `gorm:"column:user_group_face_url;size:255"` FaceURL string `bson:"face_url"`
RoleLevel int32 `gorm:"column:role_level"` RoleLevel int32 `bson:"role_level"`
JoinTime time.Time `gorm:"column:join_time"` JoinTime time.Time `bson:"join_time"`
JoinSource int32 `gorm:"column:join_source"` JoinSource int32 `bson:"join_source"`
InviterUserID string `gorm:"column:inviter_user_id;size:64"` InviterUserID string `bson:"inviter_user_id"`
OperatorUserID string `gorm:"column:operator_user_id;size:64"` OperatorUserID string `bson:"operator_user_id"`
MuteEndTime time.Time `gorm:"column:mute_end_time"` MuteEndTime time.Time `bson:"mute_end_time"`
Ex string `gorm:"column:ex;size:1024"` Ex string `bson:"ex"`
} }
func (GroupMemberModel) TableName() string { func (GroupMemberModel) TableName() string {
@ -42,33 +57,22 @@ func (GroupMemberModel) TableName() string {
} }
type GroupMemberModelInterface interface { type GroupMemberModelInterface interface {
NewTx(tx any) GroupMemberModelInterface //NewTx(tx any) GroupMemberModelInterface
Create(ctx context.Context, groupMembers []*GroupMemberModel) (err error) Create(ctx context.Context, groupMembers []*GroupMemberModel) (err error)
Delete(ctx context.Context, groupID string, userIDs []string) (err error) Delete(ctx context.Context, groupID string, userIDs []string) (err error)
DeleteGroup(ctx context.Context, groupIDs []string) (err error) //DeleteGroup(ctx context.Context, groupIDs []string) (err error)
Update(ctx context.Context, groupID string, userID string, data map[string]any) (err error) Update(ctx context.Context, groupID string, userID string, data map[string]any) (err error)
UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32) (rowsAffected int64, err error) UpdateRoleLevel(ctx context.Context, groupID string, userID string, roleLevel int32) error
Find(
ctx context.Context,
groupIDs []string,
userIDs []string,
roleLevels []int32,
) (groupMembers []*GroupMemberModel, err error)
FindMemberUserID(ctx context.Context, groupID string) (userIDs []string, err error) FindMemberUserID(ctx context.Context, groupID string) (userIDs []string, err error)
Take(ctx context.Context, groupID string, userID string) (groupMember *GroupMemberModel, err error) Take(ctx context.Context, groupID string, userID string) (groupMember *GroupMemberModel, err error)
TakeOwner(ctx context.Context, groupID string) (groupMember *GroupMemberModel, err error) TakeOwner(ctx context.Context, groupID string) (groupMember *GroupMemberModel, err error)
SearchMember( SearchMember(ctx context.Context, keyword string, groupID string, pagination pagination.Pagination) (total int64, groupList []*GroupMemberModel, err error)
ctx context.Context, FindRoleLevelUserIDs(ctx context.Context, groupID string, roleLevel int32) ([]string, error)
keyword string, //MapGroupMemberNum(ctx context.Context, groupIDs []string) (count map[string]uint32, err error)
groupIDs []string, //FindJoinUserID(ctx context.Context, groupIDs []string) (groupUsers map[string][]string, err error)
userIDs []string,
roleLevels []int32,
pageNumber, showNumber int32,
) (total uint32, groupList []*GroupMemberModel, err error)
MapGroupMemberNum(ctx context.Context, groupIDs []string) (count map[string]uint32, err error)
FindJoinUserID(ctx context.Context, groupIDs []string) (groupUsers map[string][]string, err error)
FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) FindUserJoinedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error) TakeGroupMemberNum(ctx context.Context, groupID string) (count int64, err error)
FindUsersJoinedGroupID(ctx context.Context, userIDs []string) (map[string][]string, error) //FindUsersJoinedGroupID(ctx context.Context, userIDs []string) (map[string][]string, error)
FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error)
IsUpdateRoleLevel(data map[string]any) bool
} }

@ -16,6 +16,7 @@ package relation
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time" "time"
) )
@ -23,18 +24,32 @@ const (
GroupRequestModelTableName = "group_requests" GroupRequestModelTableName = "group_requests"
) )
//type GroupRequestModel struct {
// UserID string `gorm:"column:user_id;primary_key;size:64"`
// GroupID string `gorm:"column:group_id;primary_key;size:64"`
// HandleResult int32 `gorm:"column:handle_result"`
// ReqMsg string `gorm:"column:req_msg;size:1024"`
// HandledMsg string `gorm:"column:handle_msg;size:1024"`
// ReqTime time.Time `gorm:"column:req_time"`
// HandleUserID string `gorm:"column:handle_user_id;size:64"`
// HandledTime time.Time `gorm:"column:handle_time"`
// JoinSource int32 `gorm:"column:join_source"`
// InviterUserID string `gorm:"column:inviter_user_id;size:64"`
// Ex string `gorm:"column:ex;size:1024"`
//}
type GroupRequestModel struct { type GroupRequestModel struct {
UserID string `gorm:"column:user_id;primary_key;size:64"` UserID string `bson:"user_id"`
GroupID string `gorm:"column:group_id;primary_key;size:64"` GroupID string `bson:"group_id"`
HandleResult int32 `gorm:"column:handle_result"` HandleResult int32 `bson:"handle_result"`
ReqMsg string `gorm:"column:req_msg;size:1024"` ReqMsg string `bson:"req_msg"`
HandledMsg string `gorm:"column:handle_msg;size:1024"` HandledMsg string `bson:"handled_msg"`
ReqTime time.Time `gorm:"column:req_time"` ReqTime time.Time `bson:"req_time"`
HandleUserID string `gorm:"column:handle_user_id;size:64"` HandleUserID string `bson:"handle_user_id"`
HandledTime time.Time `gorm:"column:handle_time"` HandledTime time.Time `bson:"handled_time"`
JoinSource int32 `gorm:"column:join_source"` JoinSource int32 `bson:"join_source"`
InviterUserID string `gorm:"column:inviter_user_id;size:64"` InviterUserID string `bson:"inviter_user_id"`
Ex string `gorm:"column:ex;size:1024"` Ex string `bson:"ex"`
} }
func (GroupRequestModel) TableName() string { func (GroupRequestModel) TableName() string {
@ -42,20 +57,11 @@ func (GroupRequestModel) TableName() string {
} }
type GroupRequestModelInterface interface { type GroupRequestModelInterface interface {
NewTx(tx any) GroupRequestModelInterface
Create(ctx context.Context, groupRequests []*GroupRequestModel) (err error) Create(ctx context.Context, groupRequests []*GroupRequestModel) (err error)
Delete(ctx context.Context, groupID string, userID string) (err error) Delete(ctx context.Context, groupID string, userID string) (err error)
UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error) UpdateHandler(ctx context.Context, groupID string, userID string, handledMsg string, handleResult int32) (err error)
Take(ctx context.Context, groupID string, userID string) (groupRequest *GroupRequestModel, err error) Take(ctx context.Context, groupID string, userID string) (groupRequest *GroupRequestModel, err error)
FindGroupRequests(ctx context.Context, groupID string, userIDs []string) (int64, []*GroupRequestModel, error) FindGroupRequests(ctx context.Context, groupID string, userIDs []string) ([]*GroupRequestModel, error)
Page( Page(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, groups []*GroupRequestModel, err error)
ctx context.Context, PageGroup(ctx context.Context, groupIDs []string, pagination pagination.Pagination) (total int64, groups []*GroupRequestModel, err error)
userID string,
pageNumber, showNumber int32,
) (total uint32, groups []*GroupRequestModel, err error)
PageGroup(
ctx context.Context,
groupIDs []string,
pageNumber, showNumber int32,
) (total uint32, groups []*GroupRequestModel, err error)
} }

@ -2,24 +2,37 @@ package relation
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time" "time"
) )
//type Log struct {
// LogID string `gorm:"column:log_id;primary_key;type:char(64)"`
// Platform string `gorm:"column:platform;type:varchar(32)"`
// UserID string `gorm:"column:user_id;type:char(64)"`
// CreateTime time.Time `gorm:"index:,sort:desc"`
// Url string `gorm:"column:url;type varchar(255)"`
// FileName string `gorm:"column:filename;type varchar(255)"`
// SystemType string `gorm:"column:system_type;type varchar(255)"`
// Version string `gorm:"column:version;type varchar(255)"`
// Ex string `gorm:"column:ex;type varchar(255)"`
//}
type Log struct { type Log struct {
LogID string `gorm:"column:log_id;primary_key;type:char(64)"` LogID string `bson:"log_id"`
Platform string `gorm:"column:platform;type:varchar(32)"` Platform string `bson:"platform"`
UserID string `gorm:"column:user_id;type:char(64)"` UserID string `bson:"user_id"`
CreateTime time.Time `gorm:"index:,sort:desc"` CreateTime time.Time `bson:"create_time"`
Url string `gorm:"column:url;type varchar(255)"` Url string `bson:"url"`
FileName string `gorm:"column:filename;type varchar(255)"` FileName string `bson:"file_name"`
SystemType string `gorm:"column:system_type;type varchar(255)"` SystemType string `bson:"system_type"`
Version string `gorm:"column:version;type varchar(255)"` Version string `bson:"version"`
Ex string `gorm:"column:ex;type varchar(255)"` Ex string `bson:"ex"`
} }
type LogInterface interface { type LogInterface interface {
Create(ctx context.Context, log []*Log) error Create(ctx context.Context, log []*Log) error
Search(ctx context.Context, keyword string, start time.Time, end time.Time, pageNumber int32, showNumber int32) (uint32, []*Log, error) Search(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*Log, error)
Delete(ctx context.Context, logID []string, userID string) error Delete(ctx context.Context, logID []string, userID string) error
Get(ctx context.Context, logIDs []string, userID string) ([]*Log, error) Get(ctx context.Context, logIDs []string, userID string) ([]*Log, error)
} }

@ -24,22 +24,35 @@ const (
) )
type ObjectModel struct { type ObjectModel struct {
Name string `gorm:"column:name;primary_key"` Name string `bson:"name"`
UserID string `gorm:"column:user_id"` UserID string `bson:"user_id"`
Hash string `gorm:"column:hash"` Hash string `bson:"hash"`
Key string `gorm:"column:key"` Engine string `bson:"engine"`
Size int64 `gorm:"column:size"` Key string `bson:"key"`
ContentType string `gorm:"column:content_type"` Size int64 `bson:"size"`
Cause string `gorm:"column:cause"` ContentType string `bson:"content_type"`
CreateTime time.Time `gorm:"column:create_time"` Group string `bson:"group"`
CreateTime time.Time `bson:"create_time"`
} }
//type ObjectModel struct {
// Name string `gorm:"column:name;primary_key"`
// UserID string `gorm:"column:user_id"`
// Hash string `gorm:"column:hash"`
// Engine string `gorm:"column:engine"`
// Key string `gorm:"column:key"`
// Size int64 `gorm:"column:size"`
// ContentType string `gorm:"column:content_type"`
// Cause string `gorm:"column:cause"`
// CreateTime time.Time `gorm:"column:create_time"`
//}
func (ObjectModel) TableName() string { func (ObjectModel) TableName() string {
return ObjectInfoModelTableName return ObjectInfoModelTableName
} }
type ObjectInfoModelInterface interface { type ObjectInfoModelInterface interface {
NewTx(tx any) ObjectInfoModelInterface
SetObject(ctx context.Context, obj *ObjectModel) error SetObject(ctx context.Context, obj *ObjectModel) error
Take(ctx context.Context, name string) (*ObjectModel, error) Take(ctx context.Context, engine string, name string) (*ObjectModel, error)
Delete(ctx context.Context, engine string, name string) error
} }

@ -16,21 +16,18 @@ package relation
import ( import (
"context" "context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time" "time"
) )
const (
UserModelTableName = "users"
)
type UserModel struct { type UserModel struct {
UserID string `gorm:"column:user_id;primary_key;size:64"` UserID string `bson:"user_id"`
Nickname string `gorm:"column:name;size:255"` Nickname string `bson:"nickname"`
FaceURL string `gorm:"column:face_url;size:255"` FaceURL string `bson:"face_url"`
Ex string `gorm:"column:ex;size:1024"` Ex string `bson:"ex"`
CreateTime time.Time `gorm:"column:create_time;index:create_time;autoCreateTime"` AppMangerLevel int32 `bson:"app_manger_level"`
AppMangerLevel int32 `gorm:"column:app_manger_level;default:1"` GlobalRecvMsgOpt int32 `bson:"global_recv_msg_opt"`
GlobalRecvMsgOpt int32 `gorm:"column:global_recv_msg_opt"` CreateTime time.Time `bson:"create_time"`
} }
func (u *UserModel) GetNickname() string { func (u *UserModel) GetNickname() string {
@ -41,29 +38,22 @@ func (u *UserModel) GetFaceURL() string {
return u.FaceURL return u.FaceURL
} }
func (u *UserModel) GetUserID() string { func (u UserModel) GetUserID() string {
return u.UserID return u.UserID
} }
func (u *UserModel) GetEx() string { func (u UserModel) GetEx() string {
return u.Ex return u.Ex
} }
func (UserModel) TableName() string {
return UserModelTableName
}
type UserModelInterface interface { type UserModelInterface interface {
Create(ctx context.Context, users []*UserModel) (err error) Create(ctx context.Context, users []*UserModel) (err error)
UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) (err error) UpdateByMap(ctx context.Context, userID string, args map[string]any) (err error)
Update(ctx context.Context, user *UserModel) (err error)
// 获取指定用户信息 不存在,也不返回错误
Find(ctx context.Context, userIDs []string) (users []*UserModel, err error) Find(ctx context.Context, userIDs []string) (users []*UserModel, err error)
// 获取某个用户信息 不存在,则返回错误
Take(ctx context.Context, userID string) (user *UserModel, err error) Take(ctx context.Context, userID string) (user *UserModel, err error)
// 获取用户信息 不存在,不返回错误 Page(ctx context.Context, pagination pagination.Pagination) (count int64, users []*UserModel, err error)
Page(ctx context.Context, pageNumber, showNumber int32) (users []*UserModel, count int64, err error) Exist(ctx context.Context, userID string) (exist bool, err error)
GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error) GetAllUserID(ctx context.Context, pagination pagination.Pagination) (count int64, userIDs []string, err error)
GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error) GetUserGlobalRecvMsgOpt(ctx context.Context, userID string) (opt int, err error)
// 获取用户总数 // 获取用户总数
CountTotal(ctx context.Context, before *time.Time) (count int64, err error) CountTotal(ctx context.Context, before *time.Time) (count int64, err error)

@ -14,40 +14,40 @@
package unrelation package unrelation
import ( //import (
"context" // "context"
) //)
//
const ( //const (
CSuperGroup = "super_group" // CSuperGroup = "super_group"
CUserToSuperGroup = "user_to_super_group" // CUserToSuperGroup = "user_to_super_group"
) //)
//
type SuperGroupModel struct { //type SuperGroupModel struct {
GroupID string `bson:"group_id" json:"groupID"` // GroupID string `bson:"group_id" json:"groupID"`
MemberIDs []string `bson:"member_id_list" json:"memberIDList"` // MemberIDs []string `bson:"member_id_list" json:"memberIDList"`
} //}
//
func (SuperGroupModel) TableName() string { //func (SuperGroupModel) TableName() string {
return CSuperGroup // return CSuperGroup
} //}
//
type UserToSuperGroupModel struct { //type UserToSuperGroupModel struct {
UserID string `bson:"user_id" json:"userID"` // UserID string `bson:"user_id" json:"userID"`
GroupIDs []string `bson:"group_id_list" json:"groupIDList"` // GroupIDs []string `bson:"group_id_list" json:"groupIDList"`
} //}
//
func (UserToSuperGroupModel) TableName() string { //func (UserToSuperGroupModel) TableName() string {
return CUserToSuperGroup // return CUserToSuperGroup
} //}
//
type SuperGroupModelInterface interface { //type SuperGroupModelInterface interface {
CreateSuperGroup(ctx context.Context, groupID string, initMemberIDs []string) error // CreateSuperGroup(ctx context.Context, groupID string, initMemberIDs []string) error
TakeSuperGroup(ctx context.Context, groupID string) (group *SuperGroupModel, err error) // TakeSuperGroup(ctx context.Context, groupID string) (group *SuperGroupModel, err error)
FindSuperGroup(ctx context.Context, groupIDs []string) (groups []*SuperGroupModel, err error) // FindSuperGroup(ctx context.Context, groupIDs []string) (groups []*SuperGroupModel, err error)
AddUserToSuperGroup(ctx context.Context, groupID string, userIDs []string) error // AddUserToSuperGroup(ctx context.Context, groupID string, userIDs []string) error
RemoverUserFromSuperGroup(ctx context.Context, groupID string, userIDs []string) error // RemoverUserFromSuperGroup(ctx context.Context, groupID string, userIDs []string) error
GetSuperGroupByUserID(ctx context.Context, userID string) (*UserToSuperGroupModel, error) // GetSuperGroupByUserID(ctx context.Context, userID string) (*UserToSuperGroupModel, error)
DeleteSuperGroup(ctx context.Context, groupID string) error // DeleteSuperGroup(ctx context.Context, groupID string) error
RemoveGroupFromUser(ctx context.Context, groupID string, userIDs []string) error // RemoveGroupFromUser(ctx context.Context, groupID string, userIDs []string) error
} //}

@ -0,0 +1,19 @@
package tx
import (
"context"
"github.com/OpenIMSDK/tools/tx"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
func NewAuto(ctx context.Context, cli *mongo.Client) (tx.CtxTx, error) {
var res map[string]any
if err := cli.Database("admin").RunCommand(ctx, bson.M{"isMaster": 1}).Decode(&res); err != nil {
return nil, err
}
if _, ok := res["setName"]; ok {
return NewMongoTx(cli), nil
}
return NewInvalidTx(), nil
}

@ -0,0 +1,16 @@
package tx
import (
"context"
"github.com/OpenIMSDK/tools/tx"
)
func NewInvalidTx() tx.CtxTx {
return invalid{}
}
type invalid struct{}
func (m invalid) Transaction(ctx context.Context, fn func(ctx context.Context) error) error {
return fn(ctx)
}

@ -0,0 +1,28 @@
package tx
import (
"context"
"github.com/OpenIMSDK/tools/tx"
"go.mongodb.org/mongo-driver/mongo"
)
func NewMongoTx(client *mongo.Client) tx.CtxTx {
return &mongoTx{
client: client,
}
}
type mongoTx struct {
client *mongo.Client
}
func (m *mongoTx) Transaction(ctx context.Context, fn func(ctx context.Context) error) error {
sess, err := m.client.StartSession()
if err != nil {
return err
}
_, err = sess.WithTransaction(ctx, func(ctx mongo.SessionContext) (interface{}, error) {
return nil, fn(ctx)
})
return err
}

@ -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)

@ -48,7 +48,7 @@ func (m *MsgMongoDriver) ConvertMsgsDocLen(ctx context.Context, conversationIDs
log.ZError(ctx, "convertAll delete many failed", err, "conversationID", conversationID) log.ZError(ctx, "convertAll delete many failed", err, "conversationID", conversationID)
continue continue
} }
var newMsgDocs []interface{} var newMsgDocs []any
for _, msgDoc := range msgDocs { for _, msgDoc := range msgDocs {
if int64(len(msgDoc.Msg)) == m.model.GetSingleGocMsgNum() { if int64(len(msgDoc.Msg)) == m.model.GetSingleGocMsgNum() {
continue continue

@ -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, "")
//}

@ -58,7 +58,7 @@ func Get(url string) (response []byte, err error) {
return body, nil return body, nil
} }
func Post(ctx context.Context, url string, header map[string]string, data interface{}, timeout int) (content []byte, err error) { func Post(ctx context.Context, url string, header map[string]string, data any, timeout int) (content []byte, err error) {
if timeout > 0 { if timeout > 0 {
var cancel func() var cancel func()
ctx, cancel = context.WithTimeout(ctx, time.Second*time.Duration(timeout)) ctx, cancel = context.WithTimeout(ctx, time.Second*time.Duration(timeout))
@ -97,7 +97,7 @@ func Post(ctx context.Context, url string, header map[string]string, data interf
return result, nil return result, nil
} }
func PostReturn(ctx context.Context, url string, header map[string]string, input, output interface{}, timeOutSecond int) error { func PostReturn(ctx context.Context, url string, header map[string]string, input, output any, timeOutSecond int) error {
b, err := Post(ctx, url, header, input, timeOutSecond) b, err := Post(ctx, url, header, input, timeOutSecond)
if err != nil { if err != nil {
return err return err
@ -106,7 +106,7 @@ func PostReturn(ctx context.Context, url string, header map[string]string, input
return err return err
} }
func callBackPostReturn(ctx context.Context, url, command string, input interface{}, output callbackstruct.CallbackResp, callbackConfig config.CallBackConfig) error { func callBackPostReturn(ctx context.Context, url, command string, input any, output callbackstruct.CallbackResp, callbackConfig config.CallBackConfig) error {
defer log.ZDebug(ctx, "callback", "url", url, "command", command, "input", input, "callbackConfig", callbackConfig) defer log.ZDebug(ctx, "callback", "url", url, "command", command, "input", input, "callbackConfig", callbackConfig)
v := urllib.Values{} v := urllib.Values{}

@ -54,7 +54,7 @@ func TestPost(t *testing.T) {
ctx context.Context ctx context.Context
url string url string
header map[string]string header map[string]string
data interface{} data any
timeout int timeout int
} }
tests := []struct { tests := []struct {
@ -84,8 +84,8 @@ func TestPostReturn(t *testing.T) {
ctx context.Context ctx context.Context
url string url string
header map[string]string header map[string]string
input interface{} input any
output interface{} output any
timeOutSecond int timeOutSecond int
} }
tests := []struct { tests := []struct {
@ -109,7 +109,7 @@ func Test_callBackPostReturn(t *testing.T) {
ctx context.Context ctx context.Context
url string url string
command string command string
input interface{} input any
output callbackstruct.CallbackResp output callbackstruct.CallbackResp
callbackConfig config.CallBackConfig callbackConfig config.CallBackConfig
} }

@ -0,0 +1,6 @@
package pagination
type Pagination interface {
GetPageNumber() int32
GetShowNumber() int32
}

@ -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
}

@ -52,6 +52,41 @@ type GroupNotificationSender struct {
db controller.GroupDatabase db controller.GroupDatabase
} }
func (g *GroupNotificationSender) PopulateGroupMember(ctx context.Context, members ...*relation.GroupMemberModel) error {
if len(members) == 0 {
return nil
}
emptyUserIDs := make(map[string]struct{})
for _, member := range members {
if member.Nickname == "" || member.FaceURL == "" {
emptyUserIDs[member.UserID] = struct{}{}
}
}
if len(emptyUserIDs) > 0 {
users, err := g.getUsersInfo(ctx, utils.Keys(emptyUserIDs))
if err != nil {
return err
}
userMap := make(map[string]CommonUser)
for i, user := range users {
userMap[user.GetUserID()] = users[i]
}
for i, member := range members {
user, ok := userMap[member.UserID]
if !ok {
continue
}
if member.Nickname == "" {
members[i].Nickname = user.GetNickname()
}
if member.FaceURL == "" {
members[i].FaceURL = user.GetFaceURL()
}
}
}
return nil
}
func (g *GroupNotificationSender) getUser(ctx context.Context, userID string) (*sdkws.PublicUserInfo, error) { func (g *GroupNotificationSender) getUser(ctx context.Context, userID string) (*sdkws.PublicUserInfo, error) {
users, err := g.getUsersInfo(ctx, []string{userID}) users, err := g.getUsersInfo(ctx, []string{userID})
if err != nil { if err != nil {
@ -103,10 +138,13 @@ func (g *GroupNotificationSender) getGroupInfo(ctx context.Context, groupID stri
} }
func (g *GroupNotificationSender) getGroupMembers(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error) { func (g *GroupNotificationSender) getGroupMembers(ctx context.Context, groupID string, userIDs []string) ([]*sdkws.GroupMemberFullInfo, error) {
members, err := g.db.FindGroupMember(ctx, []string{groupID}, userIDs, nil) members, err := g.db.FindGroupMembers(ctx, groupID, userIDs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := g.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
log.ZDebug(ctx, "getGroupMembers", "members", members) log.ZDebug(ctx, "getGroupMembers", "members", members)
users, err := g.getUsersInfoMap(ctx, userIDs) users, err := g.getUsersInfoMap(ctx, userIDs)
if err != nil { if err != nil {
@ -125,17 +163,6 @@ func (g *GroupNotificationSender) getGroupMembers(ctx context.Context, groupID s
res = append(res, g.groupMemberDB2PB(member, user.AppMangerLevel)) res = append(res, g.groupMemberDB2PB(member, user.AppMangerLevel))
delete(users, member.UserID) delete(users, member.UserID)
} }
//for userID, info := range users {
// if info.AppMangerLevel == constant.AppAdmin {
// res = append(res, &sdkws.GroupMemberFullInfo{
// GroupID: groupID,
// UserID: userID,
// Nickname: info.Nickname,
// FaceURL: info.FaceURL,
// AppMangerLevel: info.AppMangerLevel,
// })
// }
//}
return res, nil return res, nil
} }
@ -163,10 +190,13 @@ func (g *GroupNotificationSender) getGroupMember(ctx context.Context, groupID st
} }
func (g *GroupNotificationSender) getGroupOwnerAndAdminUserID(ctx context.Context, groupID string) ([]string, error) { func (g *GroupNotificationSender) getGroupOwnerAndAdminUserID(ctx context.Context, groupID string) ([]string, error) {
members, err := g.db.FindGroupMember(ctx, []string{groupID}, nil, []int32{constant.GroupOwner, constant.GroupAdmin}) members, err := g.db.FindGroupMemberRoleLevels(ctx, groupID, []int32{constant.GroupOwner, constant.GroupAdmin})
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := g.PopulateGroupMember(ctx, members...); err != nil {
return nil, err
}
fn := func(e *relation.GroupMemberModel) string { return e.UserID } fn := func(e *relation.GroupMemberModel) string { return e.UserID }
return utils.Slice(members, fn), nil return utils.Slice(members, fn), nil
} }

@ -125,7 +125,7 @@ func RegisterUser(token, userID, nickname, faceURL string) error {
return err return err
} }
var respData map[string]interface{} var respData map[string]any
if err := json.Unmarshal(respBody, &respData); err != nil { if err := json.Unmarshal(respBody, &respData); err != nil {
return err return err
} }

@ -71,7 +71,7 @@ func GetUsers(token string, pageNumber, showNumber int) error {
} }
// sendPostRequestWithToken sends a POST request with a token in the header // sendPostRequestWithToken sends a POST request with a token in the header
func sendPostRequestWithToken(url, token string, body interface{}) error { func sendPostRequestWithToken(url, token string, body any) error {
reqBytes, err := json.Marshal(body) reqBytes, err := json.Marshal(body)
if err != nil { if err != nil {
return err return err
@ -98,7 +98,7 @@ func sendPostRequestWithToken(url, token string, body interface{}) error {
return err return err
} }
var respData map[string]interface{} var respData map[string]any
if err := json.Unmarshal(respBody, &respData); err != nil { if err := json.Unmarshal(respBody, &respData); err != nil {
return err return err
} }

@ -25,7 +25,7 @@ func main() {
// Verify the token // Verify the token
claims := &jwt.MapClaims{} claims := &jwt.MapClaims{}
parsedT, err := jwt.ParseWithClaims(rawJWT, claims, func(token *jwt.Token) (interface{}, error) { parsedT, err := jwt.ParseWithClaims(rawJWT, claims, func(token *jwt.Token) (any, error) {
// Validate the alg is HMAC signature // Validate the alg is HMAC signature
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])

@ -239,7 +239,7 @@ func dedup(errors []packages.Error) []string {
var outMu sync.Mutex var outMu sync.Mutex
func serialFprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { func serialFprintf(w io.Writer, format string, a ...any) (n int, err error) {
outMu.Lock() outMu.Lock()
defer outMu.Unlock() defer outMu.Unlock()
return fmt.Fprintf(w, format, a...) return fmt.Fprintf(w, format, a...)

@ -3,8 +3,8 @@ package conversion
import ( import (
"github.com/OpenIMSDK/protocol/constant" "github.com/OpenIMSDK/protocol/constant"
v3 "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
v2 "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v2" v2 "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v2"
v3 "github.com/openimsdk/open-im-server/v3/tools/data-conversion/openim/mysql/v3"
"github.com/openimsdk/open-im-server/v3/tools/data-conversion/utils" "github.com/openimsdk/open-im-server/v3/tools/data-conversion/utils"
) )

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save