pull/1450/head
withchao 2 years ago
parent df7bfc67b6
commit 768e6bc758

@ -38,7 +38,7 @@ require github.com/google/uuid v1.3.1
require (
github.com/IBM/sarama v1.41.3
github.com/OpenIMSDK/protocol v0.0.31
github.com/OpenIMSDK/tools v0.0.17
github.com/OpenIMSDK/tools v0.0.18
github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible
github.com/go-redis/redis v6.15.9+incompatible
github.com/go-sql-driver/mysql v1.7.1

@ -17,21 +17,20 @@ package msgtransfer
import (
"errors"
"fmt"
"log"
"net/http"
"sync"
"github.com/OpenIMSDK/tools/mw"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors"
"github.com/prometheus/client_golang/prometheus/promhttp"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"log"
"net/http"
"sync"
"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/relation"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
kdisc "github.com/openimsdk/open-im-server/v3/pkg/common/discoveryregister"
"github.com/openimsdk/open-im-server/v3/pkg/common/prommetrics"
@ -39,20 +38,12 @@ import (
)
type MsgTransfer struct {
persistentCH *PersistentConsumerHandler // 聊天记录持久化到mysql的消费者 订阅的topic: ws2ms_chat
historyCH *OnlineHistoryRedisConsumerHandler // 这个消费者聚合消息, 订阅的topicws2ms_chat, 修改通知发往msg_to_modify topic, 消息存入redis后Incr Redis, 再发消息到ms2pschat topic推送 发消息到msg_to_mongo topic持久化
historyMongoCH *OnlineHistoryMongoConsumerHandler // mongoDB批量插入, 成功后删除redis中消息以及处理删除通知消息删除的 订阅的topic: msg_to_mongo
// modifyCH *ModifyMsgConsumerHandler // 负责消费修改消息通知的consumer, 订阅的topic: msg_to_modify
}
func StartTransfer(prometheusPort int) error {
db, err := relation.NewGormDB()
if err != nil {
return err
}
if err := db.AutoMigrate(&relationtb.ChatLogModel{}); err != nil {
fmt.Printf("gorm: AutoMigrate ChatLogModel err: %v\n", err)
}
rdb, err := cache.NewRedis()
if err != nil {
return err
@ -78,21 +69,16 @@ func StartTransfer(prometheusPort int) error {
client.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
msgModel := cache.NewMsgCacheModel(rdb)
msgDocModel := unrelation.NewMsgMongoDriver(mongo.GetDatabase())
msgMysModel := relation.NewChatLogGorm(db)
chatLogDatabase := controller.NewChatLogDatabase(msgMysModel)
msgDatabase := controller.NewCommonMsgDatabase(msgDocModel, msgModel)
conversationRpcClient := rpcclient.NewConversationRpcClient(client)
groupRpcClient := rpcclient.NewGroupRpcClient(client)
msgTransfer := NewMsgTransfer(chatLogDatabase, msgDatabase, &conversationRpcClient, &groupRpcClient)
msgTransfer := NewMsgTransfer(msgDatabase, &conversationRpcClient, &groupRpcClient)
return msgTransfer.Start(prometheusPort)
}
func NewMsgTransfer(chatLogDatabase controller.ChatLogDatabase,
msgDatabase controller.CommonMsgDatabase,
conversationRpcClient *rpcclient.ConversationRpcClient, groupRpcClient *rpcclient.GroupRpcClient,
) *MsgTransfer {
func NewMsgTransfer(msgDatabase controller.CommonMsgDatabase, conversationRpcClient *rpcclient.ConversationRpcClient, groupRpcClient *rpcclient.GroupRpcClient) *MsgTransfer {
return &MsgTransfer{
persistentCH: NewPersistentConsumerHandler(chatLogDatabase), historyCH: NewOnlineHistoryRedisConsumerHandler(msgDatabase, conversationRpcClient, groupRpcClient),
historyCH: NewOnlineHistoryRedisConsumerHandler(msgDatabase, conversationRpcClient, groupRpcClient),
historyMongoCH: NewOnlineHistoryMongoConsumerHandler(msgDatabase),
}
}

@ -1,119 +0,0 @@
// 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 msgtransfer
import (
"context"
"github.com/OpenIMSDK/protocol/constant"
pbmsg "github.com/OpenIMSDK/protocol/msg"
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/controller"
kfk "github.com/openimsdk/open-im-server/v3/pkg/common/kafka"
"github.com/IBM/sarama"
"google.golang.org/protobuf/proto"
)
type PersistentConsumerHandler struct {
persistentConsumerGroup *kfk.MConsumerGroup
chatLogDatabase controller.ChatLogDatabase
}
func NewPersistentConsumerHandler(database controller.ChatLogDatabase) *PersistentConsumerHandler {
return &PersistentConsumerHandler{
persistentConsumerGroup: kfk.NewMConsumerGroup(&kfk.MConsumerGroupConfig{
KafkaVersion: sarama.V2_0_0_0,
OffsetsInitial: sarama.OffsetNewest, IsReturnErr: false,
}, []string{config.Config.Kafka.LatestMsgToRedis.Topic},
config.Config.Kafka.Addr, config.Config.Kafka.ConsumerGroupID.MsgToMySql),
chatLogDatabase: database,
}
}
func (pc *PersistentConsumerHandler) handleChatWs2Mysql(
ctx context.Context,
cMsg *sarama.ConsumerMessage,
msgKey string,
_ sarama.ConsumerGroupSession,
) {
msg := cMsg.Value
var tag bool
msgFromMQ := pbmsg.MsgDataToMQ{}
err := proto.Unmarshal(msg, &msgFromMQ)
if err != nil {
log.ZError(ctx, "msg_transfer Unmarshal msg err", err)
return
}
log.ZDebug(ctx, "handleChatWs2Mysql", "msg", msgFromMQ.MsgData)
// Control whether to store history messages (mysql)
isPersist := utils.GetSwitchFromOptions(msgFromMQ.MsgData.Options, constant.IsPersistent)
// Only process receiver data
if isPersist {
switch msgFromMQ.MsgData.SessionType {
case constant.SingleChatType, constant.NotificationChatType:
if msgKey == msgFromMQ.MsgData.RecvID {
tag = true
}
case constant.GroupChatType:
if msgKey == msgFromMQ.MsgData.SendID {
tag = true
}
case constant.SuperGroupChatType:
tag = true
}
if tag {
log.ZInfo(ctx, "msg_transfer msg persisting", "msg", string(msg))
if err = pc.chatLogDatabase.CreateChatLog(&msgFromMQ); err != nil {
log.ZError(ctx, "Message insert failed", err, "msg", msgFromMQ.String())
return
}
}
}
}
func (PersistentConsumerHandler) Setup(_ sarama.ConsumerGroupSession) error { return nil }
func (PersistentConsumerHandler) Cleanup(_ sarama.ConsumerGroupSession) error { return nil }
func (pc *PersistentConsumerHandler) ConsumeClaim(
sess sarama.ConsumerGroupSession,
claim sarama.ConsumerGroupClaim,
) error {
for msg := range claim.Messages() {
ctx := pc.persistentConsumerGroup.GetContextFromMsg(msg)
log.ZDebug(
ctx,
"kafka get info to mysql",
"msgTopic",
msg.Topic,
"msgPartition",
msg.Partition,
"msg",
string(msg.Value),
"key",
string(msg.Key),
)
if len(msg.Value) != 0 {
pc.handleChatWs2Mysql(ctx, msg, string(msg.Key), sess)
} else {
log.ZError(ctx, "msg get from kafka but is nil", nil, "key", msg.Key)
}
sess.MarkMessage(msg, "")
}
return nil
}

@ -17,8 +17,10 @@ package conversation
import (
"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/tools/tx"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
"google.golang.org/grpc"
@ -53,11 +55,7 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
if err != nil {
return err
}
tx, err := tx2.NewAuto(context.Background(), mongo.GetClient())
if err != nil {
return err
}
conversationDB, err := newmgo.NewConversationMongo(mongo.GetDatabase())
conversationDB, err := mgo.NewConversationMongo(mongo.GetDatabase())
if err != nil {
return err
}
@ -66,7 +64,7 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
pbconversation.RegisterConversationServer(server, &conversationServer{
conversationNotificationSender: notification.NewConversationNotificationSender(&msgRpcClient),
groupRpcClient: &groupRpcClient,
conversationDatabase: controller.NewConversationDatabase(conversationDB, cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), conversationDB), tx),
conversationDatabase: controller.NewConversationDatabase(conversationDB, cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), conversationDB), tx.NewMongo(mongo.GetClient())),
})
return nil
}

@ -27,19 +27,11 @@ import (
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
func (s *friendServer) GetPaginationBlacks(
ctx context.Context,
req *pbfriend.GetPaginationBlacksReq,
) (resp *pbfriend.GetPaginationBlacksResp, err error) {
func (s *friendServer) GetPaginationBlacks(ctx context.Context, req *pbfriend.GetPaginationBlacksReq) (resp *pbfriend.GetPaginationBlacksResp, err error) {
if err := s.userRpcClient.Access(ctx, req.UserID); err != nil {
return nil, err
}
var pageNumber, showNumber int32
if req.Pagination != nil {
pageNumber = req.Pagination.PageNumber
showNumber = req.Pagination.ShowNumber
}
blacks, total, err := s.blackDatabase.FindOwnerBlacks(ctx, req.UserID, pageNumber, showNumber)
total, blacks, err := s.blackDatabase.FindOwnerBlacks(ctx, req.UserID, req.Pagination)
if err != nil {
return nil, err
}
@ -63,10 +55,7 @@ func (s *friendServer) IsBlack(ctx context.Context, req *pbfriend.IsBlackReq) (*
return resp, nil
}
func (s *friendServer) RemoveBlack(
ctx context.Context,
req *pbfriend.RemoveBlackReq,
) (*pbfriend.RemoveBlackResp, error) {
func (s *friendServer) RemoveBlack(ctx context.Context, req *pbfriend.RemoveBlackReq) (*pbfriend.RemoveBlackResp, error) {
if err := s.userRpcClient.Access(ctx, req.OwnerUserID); err != nil {
return nil, err
}
@ -74,9 +63,6 @@ func (s *friendServer) RemoveBlack(
return nil, err
}
s.notificationSender.BlackDeletedNotification(ctx, req)
if err := CallbackAfterRemoveBlack(ctx, req); err != nil {
return nil, err
}
return &pbfriend.RemoveBlackResp{}, nil
}
@ -88,9 +74,6 @@ func (s *friendServer) AddBlack(ctx context.Context, req *pbfriend.AddBlackReq)
if err != nil {
return nil, err
}
if err := CallbackBeforeAddBlack(ctx, req); err != nil {
return nil, err
}
black := relation.BlackModel{
OwnerUserID: req.OwnerUserID,
BlockUserID: req.BlackUserID,

@ -17,6 +17,8 @@ package friend
import (
"context"
"github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
@ -32,12 +34,11 @@ import (
pbfriend "github.com/OpenIMSDK/protocol/friend"
registry "github.com/OpenIMSDK/tools/discoveryregistry"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/tx"
"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/controller"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/newmgo"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
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"
@ -65,17 +66,17 @@ func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
return err
}
friendMongoDB, err := newmgo.NewFriendMongo(mongo.GetDatabase())
friendMongoDB, err := mgo.NewFriendMongo(mongo.GetDatabase())
if err != nil {
return err
}
friendRequestMongoDB, err := newmgo.NewFriendRequestMongo(mongo.GetDatabase())
friendRequestMongoDB, err := mgo.NewFriendRequestMongo(mongo.GetDatabase())
if err != nil {
return err
}
blackMongoDB, err := newmgo.NewBlackMongo(mongo.GetDatabase())
blackMongoDB, err := mgo.NewBlackMongo(mongo.GetDatabase())
if err != nil {
return err
}
@ -89,7 +90,6 @@ func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
&msgRpcClient,
notification.WithRpcFunc(userRpcClient.GetUsersInfo),
)
// Register Friend server with refactored MongoDB and Redis integrations
pbfriend.RegisterFriendServer(server, &friendServer{
friendDatabase: controller.NewFriendDatabase(
@ -311,15 +311,12 @@ func (s *friendServer) GetDesignatedFriendsApply(ctx context.Context,
}
// ok 获取接收到的好友申请(即别人主动申请的).
func (s *friendServer) GetPaginationFriendsApplyTo(
ctx context.Context,
req *pbfriend.GetPaginationFriendsApplyToReq,
) (resp *pbfriend.GetPaginationFriendsApplyToResp, err error) {
func (s *friendServer) GetPaginationFriendsApplyTo(ctx context.Context, req *pbfriend.GetPaginationFriendsApplyToReq) (resp *pbfriend.GetPaginationFriendsApplyToResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
if err := s.userRpcClient.Access(ctx, req.UserID); err != nil {
return nil, err
}
friendRequests, total, err := s.friendDatabase.PageFriendRequestToMe(ctx, req.UserID, req.Pagination.PageNumber, req.Pagination.ShowNumber)
total, friendRequests, err := s.friendDatabase.PageFriendRequestToMe(ctx, req.UserID, req.Pagination)
if err != nil {
return nil, err
}
@ -333,16 +330,13 @@ func (s *friendServer) GetPaginationFriendsApplyTo(
}
// ok 获取主动发出去的好友申请列表.
func (s *friendServer) GetPaginationFriendsApplyFrom(
ctx context.Context,
req *pbfriend.GetPaginationFriendsApplyFromReq,
) (resp *pbfriend.GetPaginationFriendsApplyFromResp, err error) {
func (s *friendServer) GetPaginationFriendsApplyFrom(ctx context.Context, req *pbfriend.GetPaginationFriendsApplyFromReq) (resp *pbfriend.GetPaginationFriendsApplyFromResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
resp = &pbfriend.GetPaginationFriendsApplyFromResp{}
if err := s.userRpcClient.Access(ctx, req.UserID); err != nil {
return nil, err
}
friendRequests, total, err := s.friendDatabase.PageFriendRequestFromMe(ctx, req.UserID, req.Pagination.PageNumber, req.Pagination.ShowNumber)
total, friendRequests, err := s.friendDatabase.PageFriendRequestFromMe(ctx, req.UserID, req.Pagination)
if err != nil {
return nil, err
}
@ -355,10 +349,7 @@ func (s *friendServer) GetPaginationFriendsApplyFrom(
}
// ok.
func (s *friendServer) IsFriend(
ctx context.Context,
req *pbfriend.IsFriendReq,
) (resp *pbfriend.IsFriendResp, err error) {
func (s *friendServer) IsFriend(ctx context.Context, req *pbfriend.IsFriendReq) (resp *pbfriend.IsFriendResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
resp = &pbfriend.IsFriendResp{}
resp.InUser1Friends, resp.InUser2Friends, err = s.friendDatabase.CheckIn(ctx, req.UserID1, req.UserID2)
@ -368,15 +359,12 @@ func (s *friendServer) IsFriend(
return resp, nil
}
func (s *friendServer) GetPaginationFriends(
ctx context.Context,
req *pbfriend.GetPaginationFriendsReq,
) (resp *pbfriend.GetPaginationFriendsResp, err error) {
func (s *friendServer) GetPaginationFriends(ctx context.Context, req *pbfriend.GetPaginationFriendsReq) (resp *pbfriend.GetPaginationFriendsResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
if err := s.userRpcClient.Access(ctx, req.UserID); err != nil {
return nil, err
}
friends, total, err := s.friendDatabase.PageOwnerFriends(ctx, req.UserID, req.Pagination.PageNumber, req.Pagination.ShowNumber)
total, friends, err := s.friendDatabase.PageOwnerFriends(ctx, req.UserID, req.Pagination)
if err != nil {
return nil, err
}
@ -389,10 +377,7 @@ func (s *friendServer) GetPaginationFriends(
return resp, nil
}
func (s *friendServer) GetFriendIDs(
ctx context.Context,
req *pbfriend.GetFriendIDsReq,
) (resp *pbfriend.GetFriendIDsResp, err error) {
func (s *friendServer) GetFriendIDs(ctx context.Context, req *pbfriend.GetFriendIDsReq) (resp *pbfriend.GetFriendIDsResp, err error) {
defer log.ZInfo(ctx, utils.GetFuncName()+" Return")
if err := s.userRpcClient.Access(ctx, req.UserID); err != nil {
return nil, err

@ -17,18 +17,19 @@ package group
import (
"context"
"fmt"
pbconversation "github.com/OpenIMSDK/protocol/conversation"
"github.com/OpenIMSDK/protocol/wrapperspb"
"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/rpcclient/grouphash"
"github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
"math/big"
"math/rand"
"strconv"
"strings"
"time"
"github.com/openimsdk/open-im-server/v3/pkg/callbackstruct"
pbconversation "github.com/OpenIMSDK/protocol/conversation"
"github.com/OpenIMSDK/protocol/wrapperspb"
"github.com/OpenIMSDK/tools/tx"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
"github.com/openimsdk/open-im-server/v3/pkg/rpcclient/grouphash"
"github.com/openimsdk/open-im-server/v3/pkg/authverify"
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
@ -53,19 +54,11 @@ import (
"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/relation"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
)
func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) error {
db, err := relation.NewGormDB()
if err != nil {
return err
}
if err := db.AutoMigrate(&relationtb.GroupModel{}, &relationtb.GroupMemberModel{}, &relationtb.GroupRequestModel{}); err != nil {
return err
}
mongo, err := unrelation.NewMongo()
if err != nil {
return err
@ -74,27 +67,23 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
if err != nil {
return err
}
groupDB, err := newmgo.NewGroupMongo(mongo.GetDatabase())
groupDB, err := mgo.NewGroupMongo(mongo.GetDatabase())
if err != nil {
return err
}
groupMemberDB, err := newmgo.NewGroupMember(mongo.GetDatabase())
groupMemberDB, err := mgo.NewGroupMember(mongo.GetDatabase())
if err != nil {
return err
}
groupRequestDB, err := newmgo.NewGroupRequestMgo(mongo.GetDatabase())
groupRequestDB, err := mgo.NewGroupRequestMgo(mongo.GetDatabase())
if err != nil {
return err
}
userRpcClient := rpcclient.NewUserRpcClient(client)
msgRpcClient := rpcclient.NewMessageRpcClient(client)
conversationRpcClient := rpcclient.NewConversationRpcClient(client)
tx, err := tx2.NewAuto(context.Background(), mongo.GetClient())
if err != nil {
return err
}
var gs groupServer
database := controller.NewGroupDatabase(rdb, groupDB, groupMemberDB, groupRequestDB, tx, grouphash.NewGroupHashFromGroupServer(&gs))
database := controller.NewGroupDatabase(rdb, groupDB, groupMemberDB, groupRequestDB, tx.NewMongo(mongo.GetClient()), grouphash.NewGroupHashFromGroupServer(&gs))
gs.db = database
gs.User = userRpcClient
gs.Notification = notification.NewGroupNotificationSender(database, &msgRpcClient, &userRpcClient, func(ctx context.Context, userIDs []string) ([]notification.CommonUser, error) {

@ -32,11 +32,11 @@ func genLogID() string {
}
func (t *thirdServer) UploadLogs(ctx context.Context, req *third.UploadLogsReq) (*third.UploadLogsResp, error) {
var DBlogs []*relationtb.Log
var DBlogs []*relationtb.LogModel
userID := ctx.Value(constant.OpUserID).(string)
platform := constant.PlatformID2Name[int(req.Platform)]
for _, fileURL := range req.FileURLs {
log := relationtb.Log{
log := relationtb.LogModel{
Version: req.Version,
SystemType: req.SystemType,
Platform: platform,
@ -57,7 +57,7 @@ func (t *thirdServer) UploadLogs(ctx context.Context, req *third.UploadLogsReq)
}
}
if log.LogID == "" {
return nil, errs.ErrData.Wrap("Log id gen error")
return nil, errs.ErrData.Wrap("LogModel id gen error")
}
DBlogs = append(DBlogs, &log)
}
@ -92,8 +92,8 @@ func (t *thirdServer) DeleteLogs(ctx context.Context, req *third.DeleteLogsReq)
return &third.DeleteLogsResp{}, nil
}
func dbToPbLogInfos(logs []*relationtb.Log) []*third.LogInfo {
db2pbForLogInfo := func(log *relationtb.Log) *third.LogInfo {
func dbToPbLogInfos(logs []*relationtb.LogModel) []*third.LogInfo {
db2pbForLogInfo := func(log *relationtb.LogModel) *third.LogInfo {
return &third.LogInfo{
Filename: log.FileName,
UserID: log.UserID,

@ -17,17 +17,17 @@ package third
import (
"context"
"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"
"time"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/unrelation"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/s3"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/s3/cos"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/s3/kodo"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/s3/minio"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/s3/oss"
"google.golang.org/grpc"
"github.com/OpenIMSDK/protocol/third"
@ -44,11 +44,11 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
if err != nil {
return err
}
logdb, err := newmgo.NewLogMongo(mongo.GetDatabase())
logdb, err := mgo.NewLogMongo(mongo.GetDatabase())
if err != nil {
return err
}
s3db, err := newmgo.NewS3Mongo(mongo.GetDatabase())
s3db, err := mgo.NewS3Mongo(mongo.GetDatabase())
if err != nil {
return err
}
@ -77,8 +77,6 @@ func Start(client discoveryregistry.SvcDiscoveryRegistry, server *grpc.Server) e
o, err = cos.NewCos()
case "oss":
o, err = oss.NewOSS()
case "kodo":
o, err = kodo.NewKodo()
default:
err = fmt.Errorf("invalid object enable: %s", enable)
}

@ -17,11 +17,13 @@ package user
import (
"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"
"strings"
"time"
"github.com/OpenIMSDK/tools/tx"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/errs"
@ -70,17 +72,13 @@ func Start(client registry.SvcDiscoveryRegistry, server *grpc.Server) error {
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(mongo.GetDatabase())
if err != nil {
return err
}
tx, err := tx2.NewAuto(context.Background(), mongo.GetClient())
userDB, err := mgo.NewUserMongo(mongo.GetDatabase())
if err != nil {
return err
}
cache := cache.NewUserCacheRedis(rdb, userDB, cache.GetDefaultOpt())
userMongoDB := unrelation.NewUserMongoDriver(mongo.GetDatabase())
database := controller.NewUserDatabase(userDB, cache, tx, userMongoDB)
database := controller.NewUserDatabase(userDB, cache, tx.NewMongo(mongo.GetClient()), userMongoDB)
friendRpcClient := rpcclient.NewFriendRpcClient(client)
groupRpcClient := rpcclient.NewGroupRpcClient(client)
msgRpcClient := rpcclient.NewMessageRpcClient(client)

@ -17,11 +17,13 @@ package tools
import (
"context"
"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"
"github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/tx"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/mgo"
"github.com/redis/go-redis/v9"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
@ -78,43 +80,40 @@ func InitMsgTool() (*MsgTool, error) {
return nil, err
}
discov.AddOption(mw.GrpcClient(), grpc.WithTransportCredentials(insecure.NewCredentials()))
userDB, err := newmgo.NewUserMongo(mongo.GetDatabase())
if err != nil {
return nil, err
}
tx, err := tx2.NewAuto(context.Background(), mongo.GetClient())
userDB, err := mgo.NewUserMongo(mongo.GetDatabase())
if err != nil {
return nil, err
}
msgDatabase := controller.InitCommonMsgDatabase(rdb, mongo.GetDatabase())
userMongoDB := unrelation.NewUserMongoDriver(mongo.GetDatabase())
ctxTx := tx.NewMongo(mongo.GetClient())
userDatabase := controller.NewUserDatabase(
userDB,
cache.NewUserCacheRedis(rdb, userDB, cache.GetDefaultOpt()),
tx,
ctxTx,
userMongoDB,
)
groupDB, err := newmgo.NewGroupMongo(mongo.GetDatabase())
groupDB, err := mgo.NewGroupMongo(mongo.GetDatabase())
if err != nil {
return nil, err
}
groupMemberDB, err := newmgo.NewGroupMember(mongo.GetDatabase())
groupMemberDB, err := mgo.NewGroupMember(mongo.GetDatabase())
if err != nil {
return nil, err
}
groupRequestDB, err := newmgo.NewGroupRequestMgo(mongo.GetDatabase())
groupRequestDB, err := mgo.NewGroupRequestMgo(mongo.GetDatabase())
if err != nil {
return nil, err
}
conversationDB, err := newmgo.NewConversationMongo(mongo.GetDatabase())
conversationDB, err := mgo.NewConversationMongo(mongo.GetDatabase())
if err != nil {
return nil, err
}
groupDatabase := controller.NewGroupDatabase(rdb, groupDB, groupMemberDB, groupRequestDB, tx, nil)
groupDatabase := controller.NewGroupDatabase(rdb, groupDB, groupMemberDB, groupRequestDB, ctxTx, nil)
conversationDatabase := controller.NewConversationDatabase(
conversationDB,
cache.NewConversationRedis(rdb, cache.GetDefaultOpt(), conversationDB),
tx,
ctxTx,
)
msgRpcClient := rpcclient.NewMessageRpcClient(discov)
msgNotificationSender := notification.NewMsgNotificationSender(rpcclient.WithRpcClient(&msgRpcClient))

@ -17,11 +17,12 @@ package cache
import (
"context"
"fmt"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/errs"
"strconv"
"time"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
"github.com/dtm-labs/rockscache"
@ -318,7 +319,12 @@ func (g *GroupCacheRedis) GetGroupMembersInfo(ctx context.Context, groupID strin
})
}
func (g *GroupCacheRedis) GetGroupMembersPage(ctx context.Context, groupID string, userIDs []string, showNumber, pageNumber int32) (total uint32, groupMembers []*relationtb.GroupMemberModel, err error) {
func (g *GroupCacheRedis) GetGroupMembersPage(
ctx context.Context,
groupID string,
userIDs []string,
showNumber, pageNumber int32,
) (total uint32, groupMembers []*relationtb.GroupMemberModel, err error) {
groupMemberIDs, err := g.GetGroupMemberIDs(ctx, groupID)
if err != nil {
return 0, nil, err

@ -173,20 +173,7 @@ func (c *msgCache) getSeqs(ctx context.Context, items []string, getkey func(s st
}
func (c *msgCache) SetMaxSeq(ctx context.Context, conversationID string, maxSeq int64) error {
var retErr error
for {
select {
case <-ctx.Done():
return errs.Wrap(retErr, "SetMaxSeq redis retry too many amount")
default:
retErr = c.setSeq(ctx, conversationID, maxSeq, c.getMaxSeqKey)
if retErr != nil {
time.Sleep(time.Second * 2)
continue
}
return nil
}
}
return c.setSeq(ctx, conversationID, maxSeq, c.getMaxSeqKey)
}
func (c *msgCache) GetMaxSeqs(ctx context.Context, conversationIDs []string) (m map[string]int64, err error) {
@ -194,21 +181,7 @@ func (c *msgCache) GetMaxSeqs(ctx context.Context, conversationIDs []string) (m
}
func (c *msgCache) GetMaxSeq(ctx context.Context, conversationID string) (int64, error) {
var retErr error
var retData int64
for {
select {
case <-ctx.Done():
return -1, errs.Wrap(retErr, "GetMaxSeq redis retry too many amount")
default:
retData, retErr = c.getSeq(ctx, conversationID, c.getMaxSeqKey)
if retErr != nil && errs.Unwrap(retErr) != redis.Nil {
time.Sleep(time.Second * 2)
continue
}
return retData, retErr
}
}
return c.getSeq(ctx, conversationID, c.getMaxSeqKey)
}
func (c *msgCache) SetMinSeq(ctx context.Context, conversationID string, minSeq int64) error {
@ -672,36 +645,20 @@ func (c *msgCache) PipeDeleteMessages(ctx context.Context, conversationID string
}
func (c *msgCache) CleanUpOneConversationAllMsg(ctx context.Context, conversationID string) error {
var (
cursor uint64
keys []string
err error
key = c.allMessageCacheKey(conversationID)
)
for {
// scan up to 10000 at a time, the count (10000) param refers to the number of scans on redis server.
// if the count is too small, needs to be run scan on redis frequently.
var limit int64 = 10000
keys, cursor, err = c.rdb.Scan(ctx, cursor, key, limit).Result()
vals, err := c.rdb.Keys(ctx, c.allMessageCacheKey(conversationID)).Result()
if errors.Is(err, redis.Nil) {
return nil
}
if err != nil {
return errs.Wrap(err)
}
for _, key := range keys {
err := c.rdb.Del(ctx, key).Err()
if err != nil {
for _, v := range vals {
if err := c.rdb.Del(ctx, v).Err(); err != nil {
return errs.Wrap(err)
}
}
// scan end
if cursor == 0 {
return nil
}
}
}
func (c *msgCache) DelMsgFromCache(ctx context.Context, userID string, seqs []int64) error {
for _, seq := range seqs {

@ -385,50 +385,3 @@ func testParallelDeleteMessagesMix(t *testing.T, cid string, seqs []int64, input
assert.EqualValues(t, 1, val) // exists
}
}
func TestCleanUpOneConversationAllMsg(t *testing.T) {
rdb := redis.NewClient(&redis.Options{})
defer rdb.Close()
cacher := msgCache{rdb: rdb}
count := 1000
prefix := fmt.Sprintf("%v", rand.Int63())
ids := []string{}
for i := 0; i < count; i++ {
id := fmt.Sprintf("%v-cid-%v", prefix, rand.Int63())
ids = append(ids, id)
key := cacher.allMessageCacheKey(id)
rdb.Set(context.Background(), key, "openim", 0)
}
// delete 100 keys with scan.
for i := 0; i < 100; i++ {
pickedKey := ids[i]
err := cacher.CleanUpOneConversationAllMsg(context.Background(), pickedKey)
assert.Nil(t, err)
ls, err := rdb.Keys(context.Background(), pickedKey).Result()
assert.Nil(t, err)
assert.Equal(t, 0, len(ls))
rcode, err := rdb.Exists(context.Background(), pickedKey).Result()
assert.Nil(t, err)
assert.EqualValues(t, 0, rcode) // non-exists
}
sid := fmt.Sprintf("%v-cid-*", prefix)
ls, err := rdb.Keys(context.Background(), cacher.allMessageCacheKey(sid)).Result()
assert.Nil(t, err)
assert.Equal(t, count-100, len(ls))
// delete fuzzy matching keys.
err = cacher.CleanUpOneConversationAllMsg(context.Background(), sid)
assert.Nil(t, err)
// don't contains keys matched `{prefix}-cid-{random}` on redis
ls, err = rdb.Keys(context.Background(), cacher.allMessageCacheKey(sid)).Result()
assert.Nil(t, err)
assert.Equal(t, 0, len(ls))
}

@ -18,11 +18,12 @@ import (
"context"
"encoding/json"
"errors"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"hash/crc32"
"strconv"
"time"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/protocol/constant"

@ -17,6 +17,8 @@ package controller
import (
"context"
"github.com/OpenIMSDK/tools/pagination"
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/utils"
@ -30,12 +32,7 @@ type BlackDatabase interface {
// Delete 删除黑名单
Delete(ctx context.Context, blacks []*relation.BlackModel) (err error)
// FindOwnerBlacks 获取黑名单列表
FindOwnerBlacks(
ctx context.Context,
ownerUserID string,
pageNumber, showNumber int32,
) (blacks []*relation.BlackModel, total int64, err error)
FindBlackIDs(ctx context.Context, ownerUserID string) (blackIDs []string, err error)
FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*relation.BlackModel, err error)
FindBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*relation.BlackModel, err error)
// CheckIn 检查user2是否在user1的黑名单列表中(inUser1Blacks==true) 检查user1是否在user2的黑名单列表中(inUser2Blacks==true)
CheckIn(ctx context.Context, userID1, userID2 string) (inUser1Blacks bool, inUser2Blacks bool, err error)
@ -75,12 +72,8 @@ func (b *blackDatabase) deleteBlackIDsCache(ctx context.Context, blacks []*relat
}
// FindOwnerBlacks 获取黑名单列表.
func (b *blackDatabase) FindOwnerBlacks(
ctx context.Context,
ownerUserID string,
pageNumber, showNumber int32,
) (blacks []*relation.BlackModel, total int64, err error) {
return b.black.FindOwnerBlacks(ctx, ownerUserID, pageNumber, showNumber)
func (b *blackDatabase) FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*relation.BlackModel, err error) {
return b.black.FindOwnerBlacks(ctx, ownerUserID, pagination)
}
// CheckIn 检查user2是否在user1的黑名单列表中(inUser1Blacks==true) 检查user1是否在user2的黑名单列表中(inUser2Blacks==true).

@ -1,37 +0,0 @@
// 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 controller
import (
pbmsg "github.com/OpenIMSDK/protocol/msg"
relationtb "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
type ChatLogDatabase interface {
CreateChatLog(msg *pbmsg.MsgDataToMQ) error
}
func NewChatLogDatabase(chatLogModelInterface relationtb.ChatLogModelInterface) ChatLogDatabase {
return &chatLogDatabase{chatLogModel: chatLogModelInterface}
}
type chatLogDatabase struct {
chatLogModel relationtb.ChatLogModelInterface
}
func (c *chatLogDatabase) CreateChatLog(msg *pbmsg.MsgDataToMQ) error {
return c.chatLogModel.Create(msg)
}

@ -16,9 +16,10 @@ package controller
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time"
"github.com/OpenIMSDK/tools/pagination"
"github.com/openimsdk/open-im-server/v3/pkg/msgprocessor"
"github.com/OpenIMSDK/protocol/constant"
@ -237,7 +238,9 @@ func (c *conversationDatabase) SetUserConversations(ctx context.Context, ownerUs
if err != nil {
return err
}
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 cache.ExecDel(ctx)
})

@ -18,7 +18,7 @@ import (
"context"
"time"
"gorm.io/gorm"
"github.com/OpenIMSDK/tools/pagination"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/errs"
@ -47,35 +47,15 @@ type FriendDatabase interface {
// 更新好友备注
UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error)
// 获取ownerUserID的好友列表
PageOwnerFriends(
ctx context.Context,
ownerUserID string,
pageNumber, showNumber int32,
) (friends []*relation.FriendModel, total int64, err error)
PageOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error)
// friendUserID在哪些人的好友列表中
PageInWhoseFriends(
ctx context.Context,
friendUserID string,
pageNumber, showNumber int32,
) (friends []*relation.FriendModel, total int64, err error)
PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error)
// 获取我发出去的好友申请
PageFriendRequestFromMe(
ctx context.Context,
userID string,
pageNumber, showNumber int32,
) (friends []*relation.FriendRequestModel, total int64, err error)
PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error)
// 获取我收到的的好友申请
PageFriendRequestToMe(
ctx context.Context,
userID string,
pageNumber, showNumber int32,
) (friends []*relation.FriendRequestModel, total int64, err error)
PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error)
// 获取某人指定好友的信息
FindFriendsWithError(
ctx context.Context,
ownerUserID string,
friendUserIDs []string,
) (friends []*relation.FriendModel, err error)
FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*relation.FriendModel, err error)
FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error)
}
@ -83,24 +63,16 @@ type FriendDatabase interface {
type friendDatabase struct {
friend relation.FriendModelInterface
friendRequest relation.FriendRequestModelInterface
tx tx.Tx
tx tx.CtxTx
cache cache.FriendCache
}
func NewFriendDatabase(
friend relation.FriendModelInterface,
friendRequest relation.FriendRequestModelInterface,
cache cache.FriendCache,
tx tx.Tx,
) FriendDatabase {
func NewFriendDatabase(friend relation.FriendModelInterface, friendRequest relation.FriendRequestModelInterface, cache cache.FriendCache, tx tx.CtxTx) FriendDatabase {
return &friendDatabase{friend: friend, friendRequest: friendRequest, cache: cache, tx: tx}
}
// ok 检查user2是否在user1的好友列表中(inUser1Friends==true) 检查user1是否在user2的好友列表中(inUser2Friends==true).
func (f *friendDatabase) CheckIn(
ctx context.Context,
userID1, userID2 string,
) (inUser1Friends bool, inUser2Friends bool, err error) {
func (f *friendDatabase) CheckIn(ctx context.Context, userID1, userID2 string) (inUser1Friends bool, inUser2Friends bool, err error) {
userID1FriendIDs, err := f.cache.GetFriendIDs(ctx, userID1)
if err != nil {
return
@ -113,50 +85,35 @@ func (f *friendDatabase) CheckIn(
}
// 增加或者更新好友申请 如果之前有记录则更新,没有记录则新增.
func (f *friendDatabase) AddFriendRequest(
ctx context.Context,
fromUserID, toUserID string,
reqMsg string,
ex string,
) (err error) {
return f.tx.Transaction(func(tx any) error {
_, err := f.friendRequest.NewTx(tx).Take(ctx, fromUserID, toUserID)
// 有db错误
if err != nil && errs.Unwrap(err) != gorm.ErrRecordNotFound {
return err
}
// 无错误 则更新
if err == nil {
func (f *friendDatabase) AddFriendRequest(ctx context.Context, fromUserID, toUserID string, reqMsg string, ex string) (err error) {
return f.tx.Transaction(ctx, func(ctx context.Context) error {
_, err := f.friendRequest.Take(ctx, fromUserID, toUserID)
switch {
case err == nil:
m := make(map[string]any, 1)
m["handle_result"] = 0
m["handle_msg"] = ""
m["req_msg"] = reqMsg
m["ex"] = ex
m["create_time"] = time.Now()
if err := f.friendRequest.NewTx(tx).UpdateByMap(ctx, fromUserID, toUserID, m); err != nil {
return err
}
return nil
}
// gorm.ErrRecordNotFound 错误,则新增
if err := f.friendRequest.NewTx(tx).Create(ctx, []*relation.FriendRequestModel{{FromUserID: fromUserID, ToUserID: toUserID, ReqMsg: reqMsg, Ex: ex, CreateTime: time.Now(), HandleTime: time.Unix(0, 0)}}); err != nil {
return f.friendRequest.UpdateByMap(ctx, fromUserID, toUserID, m)
case relation.IsNotFound(err):
return f.friendRequest.Create(
ctx,
[]*relation.FriendRequestModel{{FromUserID: fromUserID, ToUserID: toUserID, ReqMsg: reqMsg, Ex: ex, CreateTime: time.Now(), HandleTime: time.Unix(0, 0)}},
)
default:
return err
}
return nil
})
}
// (1)先判断是否在好友表 (在不在都不返回错误) (2)对于不在好友列表的 插入即可.
func (f *friendDatabase) BecomeFriends(
ctx context.Context,
ownerUserID string,
friendUserIDs []string,
addSource int32,
) (err error) {
func (f *friendDatabase) BecomeFriends(ctx context.Context, ownerUserID string, friendUserIDs []string, addSource int32) (err error) {
return f.tx.Transaction(ctx, func(ctx context.Context) error {
cache := f.cache.NewCache()
if err := f.tx.Transaction(func(tx any) error {
// 先find 找出重复的 去掉重复的
fs1, err := f.friend.NewTx(tx).FindFriends(ctx, ownerUserID, friendUserIDs)
fs1, err := f.friend.FindFriends(ctx, ownerUserID, friendUserIDs)
if err != nil {
return err
}
@ -168,11 +125,11 @@ func (f *friendDatabase) BecomeFriends(
return e.FriendUserID
})
err = f.friend.NewTx(tx).Create(ctx, fs11)
err = f.friend.Create(ctx, fs11)
if err != nil {
return err
}
fs2, err := f.friend.NewTx(tx).FindReversalFriends(ctx, ownerUserID, friendUserIDs)
fs2, err := f.friend.FindReversalFriends(ctx, ownerUserID, friendUserIDs)
if err != nil {
return err
}
@ -184,24 +141,19 @@ func (f *friendDatabase) BecomeFriends(
fs22 := utils.DistinctAny(fs2, func(e *relation.FriendModel) string {
return e.OwnerUserID
})
err = f.friend.NewTx(tx).Create(ctx, fs22)
err = f.friend.Create(ctx, fs22)
if err != nil {
return err
}
newFriendIDs = append(newFriendIDs, ownerUserID)
cache = cache.DelFriendIDs(newFriendIDs...)
return nil
}); err != nil {
return nil
}
return cache.ExecDel(ctx)
})
}
// 拒绝好友申请 (1)检查是否有申请记录且为未处理状态 (没有记录返回错误) (2)修改申请记录 已拒绝.
func (f *friendDatabase) RefuseFriendRequest(
ctx context.Context,
friendRequest *relation.FriendRequestModel,
) (err error) {
func (f *friendDatabase) RefuseFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) {
fr, err := f.friendRequest.Take(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
if err != nil {
return err
@ -220,14 +172,11 @@ func (f *friendDatabase) RefuseFriendRequest(
}
// AgreeFriendRequest 同意好友申请 (1)检查是否有申请记录且为未处理状态 (没有记录返回错误) (2)检查是否好友(不返回错误) (3) 建立双向好友关系(存在的忽略).
func (f *friendDatabase) AgreeFriendRequest(
ctx context.Context,
friendRequest *relation.FriendRequestModel,
) (err error) {
return f.tx.Transaction(func(tx any) error {
func (f *friendDatabase) AgreeFriendRequest(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) {
return f.tx.Transaction(ctx, func(ctx context.Context) error {
defer log.ZDebug(ctx, "return line")
now := time.Now()
fr, err := f.friendRequest.NewTx(tx).Take(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
fr, err := f.friendRequest.Take(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
if err != nil {
return err
}
@ -237,25 +186,25 @@ func (f *friendDatabase) AgreeFriendRequest(
friendRequest.HandlerUserID = mcontext.GetOpUserID(ctx)
friendRequest.HandleResult = constant.FriendResponseAgree
friendRequest.HandleTime = now
err = f.friendRequest.NewTx(tx).Update(ctx, friendRequest)
err = f.friendRequest.Update(ctx, friendRequest)
if err != nil {
return err
}
fr2, err := f.friendRequest.NewTx(tx).Take(ctx, friendRequest.ToUserID, friendRequest.FromUserID)
fr2, err := f.friendRequest.Take(ctx, friendRequest.ToUserID, friendRequest.FromUserID)
if err == nil && fr2.HandleResult == constant.FriendResponseNotHandle {
fr2.HandlerUserID = mcontext.GetOpUserID(ctx)
fr2.HandleResult = constant.FriendResponseAgree
fr2.HandleTime = now
err = f.friendRequest.NewTx(tx).Update(ctx, fr2)
err = f.friendRequest.Update(ctx, fr2)
if err != nil {
return err
}
} else if err != nil && errs.Unwrap(err) != gorm.ErrRecordNotFound {
} else if err != nil && (!relation.IsNotFound(err)) {
return err
}
exists, err := f.friend.NewTx(tx).FindUserState(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
exists, err := f.friend.FindUserState(ctx, friendRequest.FromUserID, friendRequest.ToUserID)
if err != nil {
return err
}
@ -286,7 +235,7 @@ func (f *friendDatabase) AgreeFriendRequest(
)
}
if len(adds) > 0 {
if err := f.friend.NewTx(tx).Create(ctx, adds); err != nil {
if err := f.friend.Create(ctx, adds); err != nil {
return err
}
}
@ -311,47 +260,27 @@ func (f *friendDatabase) UpdateRemark(ctx context.Context, ownerUserID, friendUs
}
// 获取ownerUserID的好友列表 无结果不返回错误.
func (f *friendDatabase) PageOwnerFriends(
ctx context.Context,
ownerUserID string,
pageNumber, showNumber int32,
) (friends []*relation.FriendModel, total int64, err error) {
return f.friend.FindOwnerFriends(ctx, ownerUserID, pageNumber, showNumber)
func (f *friendDatabase) PageOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error) {
return f.friend.FindOwnerFriends(ctx, ownerUserID, pagination)
}
// friendUserID在哪些人的好友列表中.
func (f *friendDatabase) PageInWhoseFriends(
ctx context.Context,
friendUserID string,
pageNumber, showNumber int32,
) (friends []*relation.FriendModel, total int64, err error) {
return f.friend.FindInWhoseFriends(ctx, friendUserID, pageNumber, showNumber)
func (f *friendDatabase) PageInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendModel, err error) {
return f.friend.FindInWhoseFriends(ctx, friendUserID, pagination)
}
// 获取我发出去的好友申请 无结果不返回错误.
func (f *friendDatabase) PageFriendRequestFromMe(
ctx context.Context,
userID string,
pageNumber, showNumber int32,
) (friends []*relation.FriendRequestModel, total int64, err error) {
return f.friendRequest.FindFromUserID(ctx, userID, pageNumber, showNumber)
func (f *friendDatabase) PageFriendRequestFromMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error) {
return f.friendRequest.FindFromUserID(ctx, userID, pagination)
}
// 获取我收到的的好友申请 无结果不返回错误.
func (f *friendDatabase) PageFriendRequestToMe(
ctx context.Context,
userID string,
pageNumber, showNumber int32,
) (friends []*relation.FriendRequestModel, total int64, err error) {
return f.friendRequest.FindToUserID(ctx, userID, pageNumber, showNumber)
func (f *friendDatabase) PageFriendRequestToMe(ctx context.Context, userID string, pagination pagination.Pagination) (total int64, friends []*relation.FriendRequestModel, err error) {
return f.friendRequest.FindToUserID(ctx, userID, pagination)
}
// 获取某人指定好友的信息 如果有好友不存在,也返回错误.
func (f *friendDatabase) FindFriendsWithError(
ctx context.Context,
ownerUserID string,
friendUserIDs []string,
) (friends []*relation.FriendModel, err error) {
func (f *friendDatabase) FindFriendsWithError(ctx context.Context, ownerUserID string, friendUserIDs []string) (friends []*relation.FriendModel, err error) {
friends, err = f.friend.FindFriends(ctx, ownerUserID, friendUserIDs)
if err != nil {
return
@ -362,10 +291,7 @@ func (f *friendDatabase) FindFriendsWithError(
return
}
func (f *friendDatabase) FindFriendUserIDs(
ctx context.Context,
ownerUserID string,
) (friendUserIDs []string, err error) {
func (f *friendDatabase) FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error) {
return f.cache.GetFriendIDs(ctx, ownerUserID)
}

@ -16,10 +16,11 @@ package controller
import (
"context"
"github.com/dtm-labs/rockscache"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time"
"github.com/OpenIMSDK/tools/pagination"
"github.com/dtm-labs/rockscache"
"github.com/OpenIMSDK/protocol/constant"
"github.com/OpenIMSDK/tools/tx"
"github.com/OpenIMSDK/tools/utils"
@ -74,7 +75,14 @@ type GroupDatabase interface {
DeleteGroupMemberHash(ctx context.Context, groupIDs []string) error
}
func NewGroupDatabase(rdb redis.UniversalClient, groupDB relationtb.GroupModelInterface, groupMemberDB relationtb.GroupMemberModelInterface, groupRequestDB relationtb.GroupRequestModelInterface, ctxTx tx.CtxTx, groupHash cache.GroupHash) GroupDatabase {
func NewGroupDatabase(
rdb redis.UniversalClient,
groupDB relationtb.GroupModelInterface,
groupMemberDB relationtb.GroupMemberModelInterface,
groupRequestDB relationtb.GroupRequestModelInterface,
ctxTx tx.CtxTx,
groupHash cache.GroupHash,
) GroupDatabase {
rcOptions := rockscache.NewDefaultOptions()
rcOptions.StrongConsistency = true
rcOptions.RandomExpireAdjustment = 0.2

@ -357,9 +357,7 @@ func (db *commonMsgDatabase) DelUserDeleteMsgsList(ctx context.Context, conversa
}
func (db *commonMsgDatabase) BatchInsertChat2Cache(ctx context.Context, conversationID string, msgs []*sdkws.MsgData) (seq int64, isNew bool, err error) {
cancelCtx, cancel := context.WithTimeout(ctx, 1*time.Minute)
defer cancel()
currentMaxSeq, err := db.cache.GetMaxSeq(cancelCtx, conversationID)
currentMaxSeq, err := db.cache.GetMaxSeq(ctx, conversationID)
if err != nil && errs.Unwrap(err) != redis.Nil {
log.ZError(ctx, "db.cache.GetMaxSeq", err)
return 0, false, err
@ -386,21 +384,19 @@ func (db *commonMsgDatabase) BatchInsertChat2Cache(ctx context.Context, conversa
prommetrics.MsgInsertRedisFailedCounter.Add(float64(failedNum))
log.ZError(ctx, "setMessageToCache error", err, "len", len(msgs), "conversationID", conversationID)
} else {
prommetrics.MsgInsertRedisSuccessCounter.Add(float64(len(msgs)))
prommetrics.MsgInsertRedisSuccessCounter.Inc()
}
cancelCtx, cancel = context.WithTimeout(ctx, 1*time.Minute)
defer cancel()
err = db.cache.SetMaxSeq(cancelCtx, conversationID, currentMaxSeq)
err = db.cache.SetMaxSeq(ctx, conversationID, currentMaxSeq)
if err != nil {
log.ZError(ctx, "db.cache.SetMaxSeq error", err, "conversationID", conversationID)
prommetrics.SeqSetFailedCounter.Inc()
}
err2 := db.cache.SetHasReadSeqs(ctx, conversationID, userSeqMap)
if err2 != nil {
if err != nil {
log.ZError(ctx, "SetHasReadSeqs error", err2, "userSeqMap", userSeqMap, "conversationID", conversationID)
prommetrics.SeqSetFailedCounter.Inc()
}
return lastMaxSeq, isNew, errs.Wrap(err, "redis SetMaxSeq error")
return lastMaxSeq, isNew, utils.Wrap(err, "")
}
func (db *commonMsgDatabase) getMsgBySeqs(ctx context.Context, userID, conversationID string, seqs []int64) (totalMsgs []*sdkws.MsgData, err error) {
@ -658,27 +654,17 @@ func (db *commonMsgDatabase) GetMsgBySeqsRange(ctx context.Context, userID strin
func (db *commonMsgDatabase) GetMsgBySeqs(ctx context.Context, userID string, conversationID string, seqs []int64) (int64, int64, []*sdkws.MsgData, error) {
userMinSeq, err := db.cache.GetConversationUserMinSeq(ctx, conversationID, userID)
if err != nil {
log.ZError(ctx, "cache.GetConversationUserMinSeq error", err)
if errs.Unwrap(err) != redis.Nil {
if err != nil && errs.Unwrap(err) != redis.Nil {
return 0, 0, nil, err
}
}
minSeq, err := db.cache.GetMinSeq(ctx, conversationID)
if err != nil {
log.ZError(ctx, "cache.GetMinSeq error", err)
if errs.Unwrap(err) != redis.Nil {
if err != nil && errs.Unwrap(err) != redis.Nil {
return 0, 0, nil, err
}
}
maxSeq, err := db.cache.GetMaxSeq(ctx, conversationID)
if err != nil {
log.ZError(ctx, "cache.GetMaxSeq error", err)
if errs.Unwrap(err) != redis.Nil {
if err != nil && errs.Unwrap(err) != redis.Nil {
return 0, 0, nil, err
}
}
if userMinSeq < minSeq {
minSeq = userMinSeq
}
@ -690,16 +676,34 @@ func (db *commonMsgDatabase) GetMsgBySeqs(ctx context.Context, userID string, co
}
successMsgs, failedSeqs, err := db.cache.GetMessagesBySeq(ctx, conversationID, newSeqs)
if err != nil {
if err != redis.Nil {
log.ZError(ctx, "get message from redis exception", err, "failedSeqs", failedSeqs, "conversationID", conversationID)
}
log.ZInfo(ctx, "db.cache.GetMessagesBySeq", "userID", userID, "conversationID", conversationID, "seqs", seqs, "successMsgs",
len(successMsgs), "failedSeqs", failedSeqs, "conversationID", conversationID)
}
log.ZInfo(
ctx,
"db.cache.GetMessagesBySeq",
"userID",
userID,
"conversationID",
conversationID,
"seqs",
seqs,
"successMsgs",
len(successMsgs),
"failedSeqs",
failedSeqs,
"conversationID",
conversationID,
)
if len(failedSeqs) > 0 {
mongoMsgs, err := db.getMsgBySeqs(ctx, userID, conversationID, failedSeqs)
if err != nil {
return 0, 0, nil, err
}
successMsgs = append(successMsgs, mongoMsgs...)
}
return minSeq, maxSeq, successMsgs, nil

@ -16,9 +16,10 @@ package controller
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time"
"github.com/OpenIMSDK/tools/pagination"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/cache"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
@ -27,10 +28,10 @@ type ThirdDatabase interface {
FcmUpdateToken(ctx context.Context, account string, platformID int, fcmToken string, expireTime int64) error
SetAppBadge(ctx context.Context, userID string, value int) error
// about log for debug
UploadLogs(ctx context.Context, logs []*relation.Log) error
UploadLogs(ctx context.Context, logs []*relation.LogModel) error
DeleteLogs(ctx context.Context, logID []string, userID string) 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)
SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*relation.LogModel, error)
GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*relation.LogModel, error)
}
type thirdDatabase struct {
@ -44,17 +45,17 @@ func (t *thirdDatabase) DeleteLogs(ctx context.Context, logID []string, userID s
}
// GetLogs implements ThirdDatabase.
func (t *thirdDatabase) GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*relation.Log, error) {
func (t *thirdDatabase) GetLogs(ctx context.Context, LogIDs []string, userID string) ([]*relation.LogModel, error) {
return t.logdb.Get(ctx, LogIDs, userID)
}
// SearchLogs implements ThirdDatabase.
func (t *thirdDatabase) SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*relation.Log, error) {
func (t *thirdDatabase) SearchLogs(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*relation.LogModel, error) {
return t.logdb.Search(ctx, keyword, start, end, pagination)
}
// UploadLogs implements ThirdDatabase.
func (t *thirdDatabase) UploadLogs(ctx context.Context, logs []*relation.Log) error {
func (t *thirdDatabase) UploadLogs(ctx context.Context, logs []*relation.LogModel) error {
return t.logdb.Create(ctx, logs)
}

@ -16,10 +16,12 @@ package controller
import (
"context"
"time"
"github.com/OpenIMSDK/tools/pagination"
"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"
"github.com/OpenIMSDK/protocol/user"
@ -79,7 +81,6 @@ func NewUserDatabase(userDB relation.UserModelInterface, cache cache.UserCache,
return &userDatabase{userDB: userDB, cache: cache, tx: tx, mongoDB: mongoDB}
}
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 {
@ -107,7 +108,6 @@ func (u *userDatabase) InitOnce(ctx context.Context, users []*relation.UserModel
return nil
}
// 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) {
users, err = u.cache.GetUsersInfo(ctx, userIDs)

@ -0,0 +1,91 @@
package mgo
import (
"context"
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
func NewBlackMongo(db *mongo.Database) (relation.BlackModelInterface, error) {
coll := db.Collection("black")
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
Keys: bson.D{
{Key: "owner_user_id", Value: 1},
{Key: "block_user_id", Value: 1},
},
Options: options.Index().SetUnique(true),
})
if err != nil {
return nil, err
}
return &BlackMgo{coll: coll}, nil
}
type BlackMgo struct {
coll *mongo.Collection
}
func (b *BlackMgo) blackFilter(ownerUserID, blockUserID string) bson.M {
return bson.M{
"owner_user_id": ownerUserID,
"block_user_id": blockUserID,
}
}
func (b *BlackMgo) blacksFilter(blacks []*relation.BlackModel) bson.M {
if len(blacks) == 0 {
return nil
}
or := make(bson.A, 0, len(blacks))
for _, black := range blacks {
or = append(or, b.blackFilter(black.OwnerUserID, black.BlockUserID))
}
return bson.M{"$or": or}
}
func (b *BlackMgo) Create(ctx context.Context, blacks []*relation.BlackModel) (err error) {
return mgoutil.InsertMany(ctx, b.coll, blacks)
}
func (b *BlackMgo) Delete(ctx context.Context, blacks []*relation.BlackModel) (err error) {
if len(blacks) == 0 {
return nil
}
return mgoutil.DeleteMany(ctx, b.coll, b.blacksFilter(blacks))
}
func (b *BlackMgo) UpdateByMap(ctx context.Context, ownerUserID, blockUserID string, args map[string]any) (err error) {
if len(args) == 0 {
return nil
}
return mgoutil.UpdateOne(ctx, b.coll, b.blackFilter(ownerUserID, blockUserID), bson.M{"$set": args}, false)
}
func (b *BlackMgo) Find(ctx context.Context, blacks []*relation.BlackModel) (blackList []*relation.BlackModel, err error) {
return mgoutil.Find[*relation.BlackModel](ctx, b.coll, b.blacksFilter(blacks))
}
func (b *BlackMgo) Take(ctx context.Context, ownerUserID, blockUserID string) (black *relation.BlackModel, err error) {
return mgoutil.FindOne[*relation.BlackModel](ctx, b.coll, b.blackFilter(ownerUserID, blockUserID))
}
func (b *BlackMgo) FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*relation.BlackModel, err error) {
return mgoutil.FindPage[*relation.BlackModel](ctx, b.coll, bson.M{"owner_user_id": ownerUserID}, pagination)
}
func (b *BlackMgo) FindOwnerBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*relation.BlackModel, err error) {
if len(userIDs) == 0 {
return mgoutil.Find[*relation.BlackModel](ctx, b.coll, bson.M{"owner_user_id": ownerUserID})
}
return mgoutil.Find[*relation.BlackModel](ctx, b.coll, bson.M{"owner_user_id": ownerUserID, "block_user_id": bson.M{"$in": userIDs}})
}
func (b *BlackMgo) FindBlackUserIDs(ctx context.Context, ownerUserID string) (blackUserIDs []string, err error) {
return mgoutil.Find[string](ctx, b.coll, bson.M{"owner_user_id": ownerUserID}, options.Find().SetProjection(bson.M{"_id": 0, "block_user_id": 1}))
}

@ -1,21 +1,32 @@
package newmgo
package mgo
import (
"context"
"time"
"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"
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"time"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
func NewConversationMongo(db *mongo.Database) (*ConversationMgo, error) {
return &ConversationMgo{
coll: db.Collection("conversation"),
}, nil
coll := db.Collection("conversation")
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
Keys: bson.D{
{Key: "owner_user_id", Value: 1},
{Key: "conversation_id", Value: 1},
},
Options: options.Index().SetUnique(true),
})
if err != nil {
return nil, err
}
return &ConversationMgo{coll: coll}, nil
}
type ConversationMgo struct {
@ -23,15 +34,15 @@ type ConversationMgo struct {
}
func (c *ConversationMgo) Create(ctx context.Context, conversations []*relation.ConversationModel) (err error) {
return mgotool.InsertMany(ctx, c.coll, conversations)
return mgoutil.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}})
return mgoutil.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})
res, err := mgoutil.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
}
@ -39,50 +50,55 @@ func (c *ConversationMgo) UpdateByMap(ctx context.Context, userIDs []string, con
}
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)
return mgoutil.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}})
return mgoutil.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}))
return mgoutil.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}))
return mgoutil.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})
return mgoutil.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}))
return mgoutil.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})
return mgoutil.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}))
return mgoutil.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}))
return mgoutil.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{
return mgoutil.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{
counts, err := mgoutil.Aggregate[int64](ctx, c.coll, []bson.M{
{"$group": bson.M{"_id": "$conversation_id"}},
{"$project": bson.M{"_id": 0, "conversation_id": "$_id"}},
})
@ -96,16 +112,16 @@ func (c *ConversationMgo) GetAllConversationIDsNumber(ctx context.Context) (int6
}
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}))
return mgoutil.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}})
return mgoutil.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{
return mgoutil.Find[*relation.ConversationModel](ctx, c.coll, bson.M{
"is_msg_destruct": 1,
"msg_destruct_time": bson.M{"$ne": 0},
"$or": []bson.M{
@ -125,5 +141,10 @@ func (c *ConversationMgo) GetConversationIDsNeedDestruct(ctx context.Context) ([
}
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}))
return mgoutil.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}),
)
}

@ -1,13 +1,16 @@
package newmgo
package mgo
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"
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
// FriendMgo implements FriendModelInterface using MongoDB as the storage backend.
@ -17,14 +20,23 @@ type FriendMgo struct {
// 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
coll := db.Collection("friend")
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
Keys: bson.D{
{Key: "owner_user_id", Value: 1},
{Key: "friend_user_id", Value: 1},
},
Options: options.Index().SetUnique(true),
})
if err != nil {
return nil, err
}
return &FriendMgo{coll: coll}, nil
}
// Create inserts multiple friend records.
func (f *FriendMgo) Create(ctx context.Context, friends []*relation.FriendModel) error {
return mgotool.InsertMany(ctx, f.coll, friends)
return mgoutil.InsertMany(ctx, f.coll, friends)
}
// Delete removes specified friends of the owner user.
@ -33,11 +45,7 @@ func (f *FriendMgo) Delete(ctx context.Context, ownerUserID string, friendUserID
"owner_user_id": ownerUserID,
"friend_user_id": bson.M{"$in": friendUserIDs},
}
_, err := f.coll.DeleteMany(ctx, filter)
if err != nil {
return err
}
return nil
return mgoutil.DeleteOne(ctx, f.coll, filter)
}
// UpdateByMap updates specific fields of a friend document using a map.
@ -49,12 +57,7 @@ func (f *FriendMgo) UpdateByMap(ctx context.Context, ownerUserID string, friendU
"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
return mgoutil.UpdateOne(ctx, f.coll, filter, bson.M{"$set": args}, true)
}
// Update modifies multiple friend documents.
@ -68,8 +71,7 @@ func (f *FriendMgo) UpdateByMap(ctx context.Context, ownerUserID string, friendU
// 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)
return f.UpdateByMap(ctx, ownerUserID, friendUserID, map[string]any{"remark": remark})
}
// Take retrieves a single friend document. Returns an error if not found.
@ -78,11 +80,7 @@ func (f *FriendMgo) Take(ctx context.Context, ownerUserID, friendUserID string)
"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
return mgoutil.FindOne[*relation.FriendModel](ctx, f.coll, filter)
}
// FindUserState finds the friendship status between two users.
@ -93,11 +91,7 @@ func (f *FriendMgo) FindUserState(ctx context.Context, userID1, userID2 string)
{"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
return mgoutil.Find[*relation.FriendModel](ctx, f.coll, filter)
}
// FindFriends retrieves a list of friends for a given owner. Missing friends do not cause an error.
@ -106,11 +100,7 @@ func (f *FriendMgo) FindFriends(ctx context.Context, ownerUserID string, friendU
"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
return mgoutil.Find[*relation.FriendModel](ctx, f.coll, filter)
}
// FindReversalFriends finds users who have added the specified user as a friend.
@ -119,51 +109,23 @@ func (f *FriendMgo) FindReversalFriends(ctx context.Context, friendUserID string
"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
return mgoutil.Find[*relation.FriendModel](ctx, f.coll, filter)
}
// 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) {
func (f *FriendMgo) FindOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (int64, []*relation.FriendModel, 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
return mgoutil.FindPage[*relation.FriendModel](ctx, f.coll, filter, pagination)
}
// 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) {
func (f *FriendMgo) FindInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (int64, []*relation.FriendModel, 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
return mgoutil.FindPage[*relation.FriendModel](ctx, f.coll, filter, pagination)
}
// 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
return mgoutil.Find[string](ctx, f.coll, filter, options.Find().SetProjection(bson.M{"_id": 0, "friend_user_id": 1}))
}

@ -0,0 +1,99 @@
package mgo
import (
"context"
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
func NewFriendRequestMongo(db *mongo.Database) (relation.FriendRequestModelInterface, error) {
coll := db.Collection("friend_request")
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
Keys: bson.D{
{Key: "from_user_id", Value: 1},
{Key: "to_user_id", Value: 1},
},
Options: options.Index().SetUnique(true),
})
if err != nil {
return nil, err
}
return &FriendRequestMgo{coll: coll}, nil
}
type FriendRequestMgo struct {
coll *mongo.Collection
}
func (f *FriendRequestMgo) FindToUserID(ctx context.Context, toUserID string, pagination pagination.Pagination) (total int64, friendRequests []*relation.FriendRequestModel, err error) {
return mgoutil.FindPage[*relation.FriendRequestModel](ctx, f.coll, bson.M{"to_user_id": toUserID}, pagination)
}
func (f *FriendRequestMgo) FindFromUserID(ctx context.Context, fromUserID string, pagination pagination.Pagination) (total int64, friendRequests []*relation.FriendRequestModel, err error) {
return mgoutil.FindPage[*relation.FriendRequestModel](ctx, f.coll, bson.M{"from_user_id": fromUserID}, pagination)
}
func (f *FriendRequestMgo) FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*relation.FriendRequestModel, err error) {
filter := bson.M{"$or": []bson.M{
{"from_user_id": fromUserID, "to_user_id": toUserID},
{"from_user_id": toUserID, "to_user_id": fromUserID},
}}
return mgoutil.Find[*relation.FriendRequestModel](ctx, f.coll, filter)
}
func (f *FriendRequestMgo) Create(ctx context.Context, friendRequests []*relation.FriendRequestModel) error {
return mgoutil.InsertMany(ctx, f.coll, friendRequests)
}
func (f *FriendRequestMgo) Delete(ctx context.Context, fromUserID, toUserID string) (err error) {
return mgoutil.DeleteOne(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 mgoutil.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) {
updater := bson.M{}
if friendRequest.HandleResult != 0 {
updater["handle_result"] = friendRequest.HandleResult
}
if friendRequest.ReqMsg != "" {
updater["req_msg"] = friendRequest.ReqMsg
}
if friendRequest.HandlerUserID != "" {
updater["handler_user_id"] = friendRequest.HandlerUserID
}
if friendRequest.HandleMsg != "" {
updater["handle_msg"] = friendRequest.HandleMsg
}
if !friendRequest.HandleTime.IsZero() {
updater["handle_time"] = friendRequest.HandleTime
}
if friendRequest.Ex != "" {
updater["ex"] = friendRequest.Ex
}
if len(updater) == 0 {
return nil
}
filter := bson.M{"from_user_id": friendRequest.FromUserID, "to_user_id": friendRequest.ToUserID}
return mgoutil.UpdateOne(ctx, f.coll, filter, bson.M{"$set": updater}, true)
}
func (f *FriendRequestMgo) Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *relation.FriendRequestModel, err error) {
return mgoutil.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)
}

@ -1,19 +1,30 @@
package newmgo
package mgo
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"
"time"
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"time"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
func NewGroupMongo(db *mongo.Database) (relation.GroupModelInterface, error) {
return &GroupMgo{
coll: db.Collection("group"),
}, nil
coll := db.Collection("group")
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
Keys: bson.D{
{Key: "group_id", Value: 1},
},
Options: options.Index().SetUnique(true),
})
if err != nil {
return nil, err
}
return &GroupMgo{coll: coll}, nil
}
type GroupMgo struct {
@ -21,7 +32,7 @@ type GroupMgo struct {
}
func (g *GroupMgo) Create(ctx context.Context, groups []*relation.GroupModel) (err error) {
return mgotool.InsertMany(ctx, g.coll, groups)
return mgoutil.InsertMany(ctx, g.coll, groups)
}
func (g *GroupMgo) UpdateState(ctx context.Context, groupID string, state int32) (err error) {
@ -32,29 +43,63 @@ func (g *GroupMgo) UpdateMap(ctx context.Context, groupID string, args map[strin
if len(args) == 0 {
return nil
}
return mgotool.UpdateOne(ctx, g.coll, bson.M{"group_id": groupID}, bson.M{"$set": args}, true)
return mgoutil.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}})
return mgoutil.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})
return mgoutil.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)
return mgoutil.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 mgoutil.Count(ctx, g.coll, bson.M{})
}
return mgotool.Count(ctx, g.coll, bson.M{"create_time": bson.M{"$lt": before}})
return mgoutil.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")
pipeline := bson.A{
bson.M{
"$match": bson.M{
"create_time": bson.M{
"$gte": start,
"$lt": end,
},
},
},
bson.M{
"$group": bson.M{
"_id": bson.M{
"$dateToString": bson.M{
"format": "%Y-%m-%d",
"date": "$create_time",
},
},
"count": bson.M{
"$sum": 1,
},
},
},
}
type Item struct {
Date string `bson:"_id"`
Count int64 `bson:"count"`
}
items, err := mgoutil.Aggregate[Item](ctx, g.coll, pipeline)
if err != nil {
return nil, err
}
res := make(map[string]int64, len(items))
for _, item := range items {
res[item.Date] = item.Count
}
return res, nil
}

@ -1,18 +1,31 @@
package newmgo
package mgo
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"
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
func NewGroupMember(db *mongo.Database) (relation.GroupMemberModelInterface, error) {
return &GroupMemberMgo{coll: db.Collection("group_member")}, nil
coll := db.Collection("group_member")
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
Keys: bson.D{
{Key: "group_id", Value: 1},
{Key: "user_id", Value: 1},
},
Options: options.Index().SetUnique(true),
})
if err != nil {
return nil, err
}
return &GroupMemberMgo{coll: coll}, nil
}
type GroupMemberMgo struct {
@ -20,11 +33,11 @@ type GroupMemberMgo struct {
}
func (g *GroupMemberMgo) Create(ctx context.Context, groupMembers []*relation.GroupMemberModel) (err error) {
return mgotool.InsertMany(ctx, g.coll, groupMembers)
return mgoutil.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}})
return mgoutil.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 {
@ -32,7 +45,7 @@ func (g *GroupMemberMgo) UpdateRoleLevel(ctx context.Context, groupID string, us
}
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)
return mgoutil.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) {
@ -41,19 +54,19 @@ func (g *GroupMemberMgo) Find(ctx context.Context, groupIDs []string, userIDs []
}
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}))
return mgoutil.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})
return mgoutil.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})
return mgoutil.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}))
return mgoutil.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) {
@ -62,11 +75,11 @@ func (g *GroupMemberMgo) SearchMember(ctx context.Context, keyword string, group
}
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}))
return mgoutil.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})
return mgoutil.Count(ctx, g.coll, bson.M{"group_id": groupID})
}
func (g *GroupMemberMgo) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
@ -76,7 +89,7 @@ func (g *GroupMemberMgo) FindUserManagedGroupID(ctx context.Context, userID stri
"$in": []int{constant.GroupOwner, constant.GroupAdmin},
},
}
return mgotool.Find[string](ctx, g.coll, filter, options.Find().SetProjection(bson.M{"_id": 0, "group_id": 1}))
return mgoutil.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 {

@ -1,16 +1,30 @@
package newmgo
package mgo
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"
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
func NewGroupRequestMgo(db *mongo.Database) (relation.GroupRequestModelInterface, error) {
return &GroupRequestMgo{coll: db.Collection("group_request")}, nil
coll := db.Collection("group_request")
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
Keys: bson.D{
{Key: "group_id", Value: 1},
{Key: "user_id", Value: 1},
},
Options: options.Index().SetUnique(true),
})
if err != nil {
return nil, err
}
return &GroupRequestMgo{coll: coll}, nil
}
type GroupRequestMgo struct {
@ -18,29 +32,29 @@ type GroupRequestMgo struct {
}
func (g *GroupRequestMgo) Create(ctx context.Context, groupRequests []*relation.GroupRequestModel) (err error) {
return mgotool.InsertMany(ctx, g.coll, groupRequests)
return mgoutil.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})
return mgoutil.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)
return mgoutil.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})
return mgoutil.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}})
return mgoutil.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)
return mgoutil.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)
return mgoutil.FindPage[*relation.GroupRequestModel](ctx, g.coll, bson.M{"group_id": bson.M{"$in": groupIDs}}, pagination)
}

@ -0,0 +1,70 @@
package mgo
import (
"context"
"time"
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
func NewLogMongo(db *mongo.Database) (relation.LogInterface, error) {
coll := db.Collection("log")
_, err := coll.Indexes().CreateMany(context.Background(), []mongo.IndexModel{
{
Keys: bson.D{
{Key: "log_id", Value: 1},
},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{
{Key: "user_id", Value: 1},
},
},
{
Keys: bson.D{
{Key: "create_time", Value: -1},
},
},
})
if err != nil {
return nil, err
}
return &LogMgo{coll: coll}, nil
}
type LogMgo struct {
coll *mongo.Collection
}
func (l *LogMgo) Create(ctx context.Context, log []*relation.LogModel) error {
return mgoutil.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.LogModel, error) {
filter := bson.M{"create_time": bson.M{"$gte": start, "$lte": end}}
if keyword != "" {
filter["user_id"] = bson.M{"$regex": keyword}
}
return mgoutil.FindPage[*relation.LogModel](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 mgoutil.DeleteMany(ctx, l.coll, bson.M{"log_id": bson.M{"$in": logID}})
}
return mgoutil.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.LogModel, error) {
if userID == "" {
return mgoutil.Find[*relation.LogModel](ctx, l.coll, bson.M{"log_id": bson.M{"$in": logIDs}})
}
return mgoutil.Find[*relation.LogModel](ctx, l.coll, bson.M{"log_id": bson.M{"$in": logIDs}, "user_id": userID})
}

@ -1,18 +1,28 @@
package newmgo
package mgo
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/tools/mgoutil"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
func NewS3Mongo(db *mongo.Database) (relation.ObjectInfoModelInterface, error) {
return &S3Mongo{
coll: db.Collection("s3"),
}, nil
coll := db.Collection("s3")
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
Keys: bson.D{
{Key: "name", Value: 1},
},
Options: options.Index().SetUnique(true),
})
if err != nil {
return nil, err
}
return &S3Mongo{coll: coll}, nil
}
type S3Mongo struct {
@ -30,16 +40,16 @@ func (o *S3Mongo) SetObject(ctx context.Context, obj *relation.ObjectModel) erro
"group": obj.Group,
"create_time": obj.CreateTime,
}
return mgotool.UpdateOne(ctx, o.coll, filter, bson.M{"$set": update}, false, options.Update().SetUpsert(true))
return mgoutil.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 mgoutil.FindOne[*relation.ObjectModel](ctx, o.coll, bson.M{"name": name})
}
return mgotool.FindOne[*relation.ObjectModel](ctx, o.coll, bson.M{"name": name, "engine": engine})
return mgoutil.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})
return mgoutil.DeleteOne(ctx, o.coll, bson.M{"name": name, "engine": engine})
}

@ -1,20 +1,30 @@
package newmgo
package mgo
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"
"time"
"github.com/OpenIMSDK/tools/mgoutil"
"github.com/OpenIMSDK/tools/pagination"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"time"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
func NewUserMongo(db *mongo.Database) (relation.UserModelInterface, error) {
return &UserMgo{
coll: db.Collection("user"),
}, nil
coll := db.Collection("user")
_, err := coll.Indexes().CreateOne(context.Background(), mongo.IndexModel{
Keys: bson.D{
{Key: "user_id", Value: 1},
},
Options: options.Index().SetUnique(true),
})
if err != nil {
return nil, err
}
return &UserMgo{coll: coll}, nil
}
type UserMgo struct {
@ -22,50 +32,82 @@ type UserMgo struct {
}
func (u *UserMgo) Create(ctx context.Context, users []*relation.UserModel) error {
return mgotool.InsertMany(ctx, u.coll, users)
return mgoutil.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)
return mgoutil.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}})
return mgoutil.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})
return mgoutil.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)
return mgoutil.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}))
return mgoutil.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})
return mgoutil.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}))
return mgoutil.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}})
if before == nil {
return mgoutil.Count(ctx, u.coll, bson.M{})
}
return mgoutil.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
pipeline := bson.A{
bson.M{
"$match": bson.M{
"create_time": bson.M{
"$gte": start,
"$lt": end,
},
},
},
bson.M{
"$group": bson.M{
"_id": bson.M{
"$dateToString": bson.M{
"format": "%Y-%m-%d",
"date": "$create_time",
},
},
"count": bson.M{
"$sum": 1,
},
},
},
}
type Item struct {
Date string `bson:"_id"`
Count int64 `bson:"count"`
}
items, err := mgoutil.Aggregate[Item](ctx, u.coll, pipeline)
if err != nil {
return nil, err
}
res := make(map[string]int64, len(items))
for _, item := range items {
res[item.Date] = item.Count
}
return res, nil
}

@ -1,48 +0,0 @@
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)
}

@ -1,49 +0,0 @@
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})
}

@ -1,198 +0,0 @@
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
}

@ -1,111 +0,0 @@
// 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 relation
import (
"context"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/ormutil"
"gorm.io/gorm"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
type BlackGorm struct {
*MetaDB
}
func NewBlackGorm(db *gorm.DB) relation.BlackModelInterface {
return &BlackGorm{NewMetaDB(db, &relation.BlackModel{})}
}
func (b *BlackGorm) Create(ctx context.Context, blacks []*relation.BlackModel) (err error) {
return utils.Wrap(b.db(ctx).Create(&blacks).Error, "")
}
func (b *BlackGorm) Delete(ctx context.Context, blacks []*relation.BlackModel) (err error) {
return utils.Wrap(b.db(ctx).Delete(blacks).Error, "")
}
func (b *BlackGorm) UpdateByMap(
ctx context.Context,
ownerUserID, blockUserID string,
args map[string]any,
) (err error) {
return utils.Wrap(
b.db(ctx).Where("block_user_id = ? and block_user_id = ?", ownerUserID, blockUserID).Updates(args).Error,
"",
)
}
func (b *BlackGorm) Update(ctx context.Context, blacks []*relation.BlackModel) (err error) {
return utils.Wrap(b.db(ctx).Updates(&blacks).Error, "")
}
func (b *BlackGorm) Find(
ctx context.Context,
blacks []*relation.BlackModel,
) (blackList []*relation.BlackModel, err error) {
var where [][]any
for _, black := range blacks {
where = append(where, []any{black.OwnerUserID, black.BlockUserID})
}
return blackList, utils.Wrap(
b.db(ctx).Where("(owner_user_id, block_user_id) in ?", where).Find(&blackList).Error,
"",
)
}
func (b *BlackGorm) Take(ctx context.Context, ownerUserID, blockUserID string) (black *relation.BlackModel, err error) {
black = &relation.BlackModel{}
return black, utils.Wrap(
b.db(ctx).Where("owner_user_id = ? and block_user_id = ?", ownerUserID, blockUserID).Take(black).Error,
"",
)
}
func (b *BlackGorm) FindOwnerBlacks(
ctx context.Context,
ownerUserID string,
pageNumber, showNumber int32,
) (blacks []*relation.BlackModel, total int64, err error) {
err = b.db(ctx).Count(&total).Error
if err != nil {
return nil, 0, utils.Wrap(err, "")
}
totalUint32, blacks, err := ormutil.GormPage[relation.BlackModel](
b.db(ctx).Where("owner_user_id = ?", ownerUserID),
pageNumber,
showNumber,
)
total = int64(totalUint32)
return
}
func (b *BlackGorm) FindBlackUserIDs(ctx context.Context, ownerUserID string) (blackUserIDs []string, err error) {
return blackUserIDs, utils.Wrap(
b.db(ctx).Where("owner_user_id = ?", ownerUserID).Pluck("block_user_id", &blackUserIDs).Error,
"",
)
}
func (b *BlackGorm) FindOwnerBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*relation.BlackModel, err error) {
return blacks, errs.Wrap(b.db(ctx).Where("owner_user_id = ? and block_user_id in ?", ownerUserID, userIDs).Find(&blacks).Error)
}

@ -1,63 +0,0 @@
// 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 relation
import (
"github.com/golang/protobuf/jsonpb"
"github.com/jinzhu/copier"
"google.golang.org/protobuf/proto"
"gorm.io/gorm"
"github.com/OpenIMSDK/protocol/constant"
pbmsg "github.com/OpenIMSDK/protocol/msg"
sdkws "github.com/OpenIMSDK/protocol/sdkws"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
type ChatLogGorm struct {
*MetaDB
}
func NewChatLogGorm(db *gorm.DB) relation.ChatLogModelInterface {
return &ChatLogGorm{NewMetaDB(db, &relation.ChatLogModel{})}
}
func (c *ChatLogGorm) Create(msg *pbmsg.MsgDataToMQ) error {
chatLog := new(relation.ChatLogModel)
copier.Copy(chatLog, msg.MsgData)
switch msg.MsgData.SessionType {
case constant.GroupChatType, constant.SuperGroupChatType:
chatLog.RecvID = msg.MsgData.GroupID
case constant.SingleChatType:
chatLog.RecvID = msg.MsgData.RecvID
}
if msg.MsgData.ContentType >= constant.NotificationBegin && msg.MsgData.ContentType <= constant.NotificationEnd {
var tips sdkws.TipsComm
_ = proto.Unmarshal(msg.MsgData.Content, &tips)
marshaler := jsonpb.Marshaler{
OrigName: true,
EnumsAsInts: false,
EmitDefaults: false,
}
chatLog.Content, _ = marshaler.MarshalToString(&tips)
} else {
chatLog.Content = string(msg.MsgData.Content)
}
chatLog.CreateTime = utils.UnixMillSecondToTime(msg.MsgData.CreateTime)
chatLog.SendTime = utils.UnixMillSecondToTime(msg.MsgData.SendTime)
return c.DB.Create(chatLog).Error
}

@ -1,244 +0,0 @@
// 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 relation
//
//import (
// "context"
//
// "github.com/OpenIMSDK/tools/errs"
// "gorm.io/gorm"
//
// "github.com/OpenIMSDK/protocol/constant"
// "github.com/OpenIMSDK/tools/utils"
//
// "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
//)
//
//type ConversationGorm struct {
// *MetaDB
//}
//
//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) 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) UpdateByMap(
// ctx context.Context,
// userIDList []string,
// conversationID string,
// args map[string]any,
//) (rows int64, err 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(
// c.db(ctx).
// Where("owner_user_id = ? and conversation_id = ?", conversation.OwnerUserID, conversation.ConversationID).
// Updates(conversation).
// Error,
// "",
// )
//}
//
//func (c *ConversationGorm) Find(
// ctx context.Context,
// ownerUserID string,
// conversationIDs []string,
//) (conversations []*relation.ConversationModel, err error) {
// err = utils.Wrap(
// c.db(ctx).
// Where("owner_user_id=? and conversation_id IN (?)", ownerUserID, conversationIDs).
// Find(&conversations).
// Error,
// "",
// )
// return conversations, err
//}
//
//func (c *ConversationGorm) Take(
// ctx context.Context,
// userID, conversationID string,
//) (conversation *relation.ConversationModel, err error) {
// cc := &relation.ConversationModel{}
// 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,
// userIDs []string,
// conversationIDs []string,
//) (existUserID []string, err error) {
// return existUserID, utils.Wrap(
// c.db(ctx).
// Where(" owner_user_id IN (?) and conversation_id in (?)", userIDs, conversationIDs).
// Pluck("owner_user_id", &existUserID).
// Error,
// "",
// )
//}
//
//func (c *ConversationGorm) FindConversationID(
// ctx context.Context,
// userID string,
// conversationIDList []string,
//) (existConversationID []string, err error) {
// return existConversationID, utils.Wrap(
// c.db(ctx).
// Where(" conversation_id IN (?) and owner_user_id=?", conversationIDList, userID).
// Pluck("conversation_id", &existConversationID).
// Error,
// "",
// )
//}
//
//func (c *ConversationGorm) FindUserIDAllConversationID(
// ctx context.Context,
// userID string,
//) (conversationIDList []string, err 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,
// userID string,
//) (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,
// groupID string,
//) (userIDs []string, err error) {
// return userIDs, utils.Wrap(
// c.db(ctx).
// Where("group_id = ? and recv_msg_opt = ?", groupID, constant.ReceiveNotNotifyMessage).
// Pluck("owner_user_id", &userIDs).
// Error,
// "",
// )
//}
//
//func (c *ConversationGorm) FindSuperGroupRecvMsgNotNotifyUserIDs(
// ctx context.Context,
// groupID string,
//) (userIDs []string, err error) {
// return userIDs, utils.Wrap(
// c.db(ctx).
// Where("group_id = ? and recv_msg_opt = ? and conversation_type = ?", groupID, constant.ReceiveNotNotifyMessage, constant.SuperGroupChatType).
// Pluck("owner_user_id", &userIDs).
// Error,
// "",
// )
//}
//
//func (c *ConversationGorm) GetUserRecvMsgOpt(
// ctx context.Context,
// ownerUserID, conversationID string,
//) (opt int, err error) {
// var conversation relation.ConversationModel
// return int(
// conversation.RecvMsgOpt,
// ), utils.Wrap(
// c.db(ctx).
// Where("conversation_id = ? And owner_user_id = ?", conversationID, ownerUserID).
// Select("recv_msg_opt").
// Find(&conversation).
// Error,
// "",
// )
//}
//
//func (c *ConversationGorm) GetAllConversationIDs(ctx context.Context) (conversationIDs []string, err 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
// 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
// err = errs.Wrap(err)
// return
//}
//
//func (c *ConversationGorm) GetConversationsByConversationID(
// ctx context.Context,
// conversationIDs []string,
//) (conversations []*relation.ConversationModel, err error) {
// return conversations, utils.Wrap(
// c.db(ctx).Where("conversation_id IN (?)", conversationIDs).Find(&conversations).Error,
// "",
// )
//}
//
//func (c *ConversationGorm) GetConversationIDsNeedDestruct(
// 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)").
// Find(&conversations).
// Error,
// "",
// )
//}
//
//func (c *ConversationGorm) GetConversationRecvMsgOpt(ctx context.Context, userID string, conversationID string) (int32, error) {
// var recvMsgOpt int32
// return recvMsgOpt, errs.Wrap(
// c.db(ctx).
// Model(&relation.ConversationModel{}).
// Where("conversation_id = ? and owner_user_id in ?", conversationID, userID).
// Pluck("recv_msg_opt", &recvMsgOpt).
// Error,
// )
//}
//
//func (c *ConversationGorm) GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, 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,
// )
//}

@ -1,15 +0,0 @@
// 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 relation // import "github.com/openimsdk/open-im-server/v3/pkg/common/db/relation"

@ -1,193 +0,0 @@
// 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 relation
import (
"context"
"gorm.io/gorm"
"github.com/OpenIMSDK/tools/utils"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
)
type FriendGorm struct {
*MetaDB
}
func NewFriendGorm(db *gorm.DB) relation.FriendModelInterface {
return &FriendGorm{NewMetaDB(db, &relation.FriendModel{})}
}
func (f *FriendGorm) NewTx(tx any) relation.FriendModelInterface {
return &FriendGorm{NewMetaDB(tx.(*gorm.DB), &relation.FriendModel{})}
}
// 插入多条记录.
func (f *FriendGorm) Create(ctx context.Context, friends []*relation.FriendModel) (err error) {
return utils.Wrap(f.db(ctx).Create(&friends).Error, "")
}
// 删除ownerUserID指定的好友.
func (f *FriendGorm) Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error) {
err = utils.Wrap(
f.db(ctx).
Where("owner_user_id = ? AND friend_user_id in ( ?)", ownerUserID, friendUserIDs).
Delete(&relation.FriendModel{}).
Error,
"",
)
return err
}
// 更新ownerUserID单个好友信息 更新零值.
func (f *FriendGorm) UpdateByMap(
ctx context.Context,
ownerUserID string,
friendUserID string,
args map[string]any,
) (err error) {
return utils.Wrap(
f.db(ctx).Where("owner_user_id = ? AND friend_user_id = ? ", ownerUserID, friendUserID).Updates(args).Error,
"",
)
}
// 更新好友信息的非零值.
func (f *FriendGorm) Update(ctx context.Context, friends []*relation.FriendModel) (err error) {
return utils.Wrap(f.db(ctx).Updates(&friends).Error, "")
}
// 更新好友备注(也支持零值 .
func (f *FriendGorm) UpdateRemark(ctx context.Context, ownerUserID, friendUserID, remark string) (err error) {
if remark != "" {
return utils.Wrap(
f.db(ctx).
Where("owner_user_id = ? and friend_user_id = ?", ownerUserID, friendUserID).
Update("remark", remark).
Error,
"",
)
}
m := make(map[string]any, 1)
m["remark"] = ""
return utils.Wrap(f.db(ctx).Where("owner_user_id = ?", ownerUserID).Updates(m).Error, "")
}
// 获取单个好友信息,如没找到 返回错误.
func (f *FriendGorm) Take(
ctx context.Context,
ownerUserID, friendUserID string,
) (friend *relation.FriendModel, err error) {
friend = &relation.FriendModel{}
return friend, utils.Wrap(
f.db(ctx).Where("owner_user_id = ? and friend_user_id", ownerUserID, friendUserID).Take(friend).Error,
"",
)
}
// 查找好友关系,如果是双向关系,则都返回.
func (f *FriendGorm) FindUserState(
ctx context.Context,
userID1, userID2 string,
) (friends []*relation.FriendModel, err error) {
return friends, utils.Wrap(
f.db(ctx).
Where("(owner_user_id = ? and friend_user_id = ?) or (owner_user_id = ? and friend_user_id = ?)", userID1, userID2, userID2, userID1).
Find(&friends).
Error,
"",
)
}
// 获取 owner指定的好友列表 如果有friendUserIDs不存在也不返回错误.
func (f *FriendGorm) FindFriends(
ctx context.Context,
ownerUserID string,
friendUserIDs []string,
) (friends []*relation.FriendModel, err error) {
return friends, utils.Wrap(
f.db(ctx).Where("owner_user_id = ? AND friend_user_id in (?)", ownerUserID, friendUserIDs).Find(&friends).Error,
"",
)
}
// 获取哪些人添加了friendUserID 如果有ownerUserIDs不存在也不返回错误.
func (f *FriendGorm) FindReversalFriends(
ctx context.Context,
friendUserID string,
ownerUserIDs []string,
) (friends []*relation.FriendModel, err error) {
return friends, utils.Wrap(
f.db(ctx).Where("friend_user_id = ? AND owner_user_id in (?)", friendUserID, ownerUserIDs).Find(&friends).Error,
"",
)
}
// 获取ownerUserID好友列表 支持翻页.
func (f *FriendGorm) FindOwnerFriends(
ctx context.Context,
ownerUserID string,
pageNumber, showNumber int32,
) (friends []*relation.FriendModel, total int64, err error) {
err = f.DB.Model(&relation.FriendModel{}).Where("owner_user_id = ? ", ownerUserID).Count(&total).Error
if err != nil {
return nil, 0, utils.Wrap(err, "")
}
err = utils.Wrap(
f.db(ctx).
Where("owner_user_id = ? ", ownerUserID).
Limit(int(showNumber)).
Offset(int((pageNumber-1)*showNumber)).
Find(&friends).
Error,
"",
)
return
}
// 获取哪些人添加了friendUserID 支持翻页.
func (f *FriendGorm) FindInWhoseFriends(
ctx context.Context,
friendUserID string,
pageNumber, showNumber int32,
) (friends []*relation.FriendModel, total int64, err error) {
err = f.DB.Model(&relation.FriendModel{}).Where("friend_user_id = ? ", friendUserID).Count(&total).Error
if err != nil {
return nil, 0, utils.Wrap(err, "")
}
err = utils.Wrap(
f.db(ctx).
Where("friend_user_id = ? ", friendUserID).
Limit(int(showNumber)).
Offset(int((pageNumber-1)*showNumber)).
Find(&friends).
Error,
"",
)
return
}
func (f *FriendGorm) FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error) {
return friendUserIDs, utils.Wrap(
f.db(ctx).
Model(&relation.FriendModel{}).
Where("owner_user_id = ? ", ownerUserID).
Pluck("friend_user_id", &friendUserIDs).
Error,
"",
)
}

@ -1,154 +0,0 @@
// 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 relation
// type FriendRequestGorm struct {
// *MetaDB
// }
// func NewFriendRequestGorm(db *gorm.DB) relation.FriendRequestModelInterface {
// return &FriendRequestGorm{NewMetaDB(db, &relation.FriendRequestModel{})}
// }
// func (f *FriendRequestGorm) NewTx(tx any) relation.FriendRequestModelInterface {
// return &FriendRequestGorm{NewMetaDB(tx.(*gorm.DB), &relation.FriendRequestModel{})}
// }
// // 插入多条记录.
// func (f *FriendRequestGorm) Create(ctx context.Context, friendRequests []*relation.FriendRequestModel) (err 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(
// f.db(ctx).
// Where("from_user_id = ? AND to_user_id = ?", fromUserID, toUserID).
// Delete(&relation.FriendRequestModel{}).
// Error,
// "",
// )
// }
// // 更新零值.
// func (f *FriendRequestGorm) UpdateByMap(
// ctx context.Context,
// fromUserID string,
// toUserID string,
// 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).
// Updates(args).
// Error,
// "",
// )
// }
// // 更新记录 (非零值).
// func (f *FriendRequestGorm) Update(ctx context.Context, friendRequest *relation.FriendRequestModel) (err error) {
// fr2 := *friendRequest
// fr2.FromUserID = ""
// fr2.ToUserID = ""
// return utils.Wrap(
// f.db(ctx).
// Where("from_user_id = ? AND to_user_id =?", friendRequest.FromUserID, friendRequest.ToUserID).
// Updates(fr2).
// Error,
// "",
// )
// }
// // 获取来指定用户的好友申请 未找到 不返回错误.
// func (f *FriendRequestGorm) Find(
// ctx context.Context,
// fromUserID, toUserID string,
// ) (friendRequest *relation.FriendRequestModel, err 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) Take(
// ctx context.Context,
// fromUserID, toUserID string,
// ) (friendRequest *relation.FriendRequestModel, err 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
// }
// // 获取toUserID收到的好友申请列表.
// func (f *FriendRequestGorm) FindToUserID(
// ctx context.Context,
// toUserID string,
// 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
// if err != nil {
// return nil, 0, utils.Wrap(err, "")
// }
// err = utils.Wrap(
// f.db(ctx).
// Where("to_user_id = ? ", toUserID).
// Limit(int(showNumber)).
// Offset(int(pageNumber-1)*int(showNumber)).
// Find(&friendRequests).
// Error,
// "",
// )
// return
// }
// // 获取fromUserID发出去的好友申请列表.
// func (f *FriendRequestGorm) FindFromUserID(
// ctx context.Context,
// fromUserID string,
// 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
// if err != nil {
// return nil, 0, utils.Wrap(err, "")
// }
// err = utils.Wrap(
// f.db(ctx).
// Where("from_user_id = ? ", fromUserID).
// Limit(int(showNumber)).
// Offset(int(pageNumber-1)*int(showNumber)).
// Find(&friendRequests).
// Error,
// "",
// )
// 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
// }

@ -1,198 +0,0 @@
// 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 relation
//
//import (
// "context"
//
// "gorm.io/gorm"
//
// "github.com/OpenIMSDK/protocol/constant"
// "github.com/OpenIMSDK/tools/ormutil"
// "github.com/OpenIMSDK/tools/utils"
//
// "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
//)
//
//var _ relation.GroupMemberModelInterface = (*GroupMemberGorm)(nil)
//
//type GroupMemberGorm struct {
// *MetaDB
//}
//
//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) 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(
// 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) 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,
// groupID string,
// userID string,
// roleLevel int32,
//) (rowsAffected int64, err error) {
// 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, "")
//}
//
//func (g *GroupMemberGorm) Find(
// ctx context.Context,
// groupIDs []string,
// userIDs []string,
// roleLevels []int32,
//) (groupMembers []*relation.GroupMemberModel, err error) {
// db := g.db(ctx)
// if len(groupIDs) > 0 {
// db = db.Where("group_id in (?)", groupIDs)
// }
// if len(userIDs) > 0 {
// db = db.Where("user_id in (?)", userIDs)
// }
// if len(roleLevels) > 0 {
// db = db.Where("role_level in (?)", roleLevels)
// }
// return groupMembers, utils.Wrap(db.Find(&groupMembers).Error, "")
//}
//
//func (g *GroupMemberGorm) Take(
// ctx context.Context,
// groupID string,
// userID string,
//) (groupMember *relation.GroupMemberModel, err error) {
// groupMember = &relation.GroupMemberModel{}
// 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,
// groupID string,
//) (groupMember *relation.GroupMemberModel, err error) {
// groupMember = &relation.GroupMemberModel{}
// 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,
// keyword string,
// groupIDs []string,
// userIDs []string,
// roleLevels []int32,
// pageNumber, showNumber int32,
//) (total uint32, groupList []*relation.GroupMemberModel, err error) {
// db := g.db(ctx)
// ormutil.GormIn(&db, "group_id", groupIDs)
// ormutil.GormIn(&db, "user_id", userIDs)
// ormutil.GormIn(&db, "role_level", roleLevels)
// return ormutil.GormSearch[relation.GroupMemberModel](db, []string{"nickname"}, keyword, pageNumber, showNumber)
//}
//
//func (g *GroupMemberGorm) MapGroupMemberNum(
// ctx context.Context,
// groupIDs []string,
//) (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,
// groupIDs []string,
//) (groupUsers map[string][]string, err error) {
// var groupMembers []*relation.GroupMemberModel
// 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 {
// v, ok := groupUsers[item.GroupID]
// if !ok {
// groupUsers[item.GroupID] = []string{item.UserID}
// } else {
// groupUsers[item.GroupID] = append(v, item.UserID)
// }
// }
// 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) 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) FindUsersJoinedGroupID(ctx context.Context, userIDs []string) (map[string][]string, error) {
// var groupMembers []*relation.GroupMemberModel
// err := g.db(ctx).Select("group_id, user_id").Where("user_id IN (?)", userIDs).Find(&groupMembers).Error
// if err != nil {
// return nil, err
// }
// result := make(map[string][]string)
// for _, groupMember := range groupMembers {
// v, ok := result[groupMember.UserID]
// if !ok {
// result[groupMember.UserID] = []string{groupMember.GroupID}
// } else {
// result[groupMember.UserID] = append(v, groupMember.GroupID)
// }
// }
// return result, nil
//}
//
//func (g *GroupMemberGorm) FindUserManagedGroupID(ctx context.Context, userID string) (groupIDs []string, err error) {
// return groupIDs, utils.Wrap(
// g.db(ctx).
// Model(&relation.GroupMemberModel{}).
// Where("user_id = ? and (role_level = ? or role_level = ?)", userID, constant.GroupOwner, constant.GroupAdmin).
// Pluck("group_id", &groupIDs).
// Error,
// "",
// )
//}

@ -1,106 +0,0 @@
// 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 relation
//import (
// "context"
// "time"
//
// "github.com/OpenIMSDK/protocol/constant"
//
// "gorm.io/gorm"
//
// "github.com/OpenIMSDK/tools/errs"
// "github.com/OpenIMSDK/tools/ormutil"
// "github.com/OpenIMSDK/tools/utils"
//
// "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
//)
//
//var _ relation.GroupModelInterface = (*GroupGorm)(nil)
//
//type GroupGorm struct {
// *MetaDB
//}
//
//func NewGroupDB(db *gorm.DB) relation.GroupModelInterface {
// return &GroupGorm{NewMetaDB(db, &relation.GroupModel{})}
//}
//
//func (g *GroupGorm) NewTx(tx any) relation.GroupModelInterface {
// return &GroupGorm{NewMetaDB(tx.(*gorm.DB), &relation.GroupModel{})}
//}
//
//func (g *GroupGorm) Create(ctx context.Context, groups []*relation.GroupModel) (err error) {
// return utils.Wrap(g.DB.Create(&groups).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, "")
//}
//
//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, "")
//}
//
//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, "")
//}
//
//func (g *GroupGorm) Take(ctx context.Context, groupID string) (group *relation.GroupModel, err error) {
// group = &relation.GroupModel{}
// 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) {
// db := g.DB
// db = db.WithContext(ctx).Where("status!=?", constant.GroupStatusDismissed)
// return ormutil.GormSearch[relation.GroupModel](db, []string{"name"}, keyword, pageNumber, showNumber)
//}
//
//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, "")
//}
//
//func (g *GroupGorm) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
// db := g.db(ctx).Model(&relation.GroupModel{})
// if before != nil {
// db = db.Where("create_time < ?", before)
// }
// if err := db.Count(&count).Error; err != nil {
// return 0, err
// }
// return count, nil
//}
//
//func (g *GroupGorm) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) {
// var res []struct {
// Date time.Time `gorm:"column:date"`
// 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
// if err != nil {
// return nil, errs.Wrap(err)
// }
// v := make(map[string]int64)
// for _, r := range res {
// v[r.Date.Format("2006-01-02")] = r.Count
// }
// return v, nil
//}
//
//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, "")
//}

@ -1,119 +0,0 @@
// 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 relation
//
//import (
// "context"
//
// "github.com/OpenIMSDK/tools/ormutil"
//
// "gorm.io/gorm"
//
// "github.com/OpenIMSDK/tools/utils"
//
// "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
//)
//
//type GroupRequestGorm struct {
// *MetaDB
//}
//
//func NewGroupRequest(db *gorm.DB) relation.GroupRequestModelInterface {
// 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) 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(
// g.DB.WithContext(ctx).
// Where("group_id = ? and user_id = ? ", groupID, userID).
// Delete(&relation.GroupRequestModel{}).
// Error,
// utils.GetSelfFuncName(),
// )
//}
//
//func (g *GroupRequestGorm) UpdateHandler(
// ctx context.Context,
// groupID string,
// userID string,
// handledMsg string,
// handleResult int32,
//) (err error) {
// return utils.Wrap(
// g.DB.WithContext(ctx).
// Model(&relation.GroupRequestModel{}).
// Where("group_id = ? and user_id = ? ", groupID, userID).
// Updates(map[string]any{
// "handle_msg": handledMsg,
// "handle_result": handleResult,
// }).
// Error,
// utils.GetSelfFuncName(),
// )
//}
//
//func (g *GroupRequestGorm) Take(
// ctx context.Context,
// groupID string,
// userID string,
//) (groupRequest *relation.GroupRequestModel, err error) {
// groupRequest = &relation.GroupRequestModel{}
// return groupRequest, utils.Wrap(
// g.DB.WithContext(ctx).Where("group_id = ? and user_id = ? ", groupID, userID).Take(groupRequest).Error,
// utils.GetSelfFuncName(),
// )
//}
//
//func (g *GroupRequestGorm) Page(
// ctx context.Context,
// userID string,
// pageNumber, showNumber int32,
//) (total uint32, groups []*relation.GroupRequestModel, err error) {
// return ormutil.GormSearch[relation.GroupRequestModel](
// g.DB.WithContext(ctx).Where("user_id = ?", userID),
// nil,
// "",
// pageNumber,
// showNumber,
// )
//}
//
//func (g *GroupRequestGorm) PageGroup(
// ctx context.Context,
// groupIDs []string,
// pageNumber, showNumber int32,
//) (total uint32, groups []*relation.GroupRequestModel, err error) {
// return ormutil.GormPage[relation.GroupRequestModel](
// g.DB.WithContext(ctx).Where("group_id in ?", groupIDs),
// 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
// return int64(len(groupRequests)), groupRequests, utils.Wrap(err, utils.GetSelfFuncName())
//}

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

@ -1,38 +0,0 @@
// 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 relation
import (
"context"
"gorm.io/gorm"
)
type MetaDB struct {
DB *gorm.DB
table any
}
func NewMetaDB(db *gorm.DB, table any) *MetaDB {
return &MetaDB{
DB: db,
table: table,
}
}
func (g *MetaDB) db(ctx context.Context) *gorm.DB {
db := g.DB.WithContext(ctx).Model(g.table)
return db
}

@ -1,157 +0,0 @@
// 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 relation
import (
"fmt"
"time"
"github.com/OpenIMSDK/tools/errs"
"github.com/OpenIMSDK/tools/log"
"github.com/OpenIMSDK/tools/mw/specialerror"
mysqldriver "github.com/go-sql-driver/mysql"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
)
const (
maxRetry = 100 // number of retries
)
type option struct {
Username string
Password string
Address []string
Database string
LogLevel int
SlowThreshold int
MaxLifeTime int
MaxOpenConn int
MaxIdleConn int
Connect func(dsn string, maxRetry int) (*gorm.DB, error)
}
// newMysqlGormDB Initialize the database connection.
func newMysqlGormDB(o *option) (*gorm.DB, error) {
err := maybeCreateTable(o)
if err != nil {
return nil, err
}
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true&loc=Local",
o.Username, o.Password, o.Address[0], o.Database)
sqlLogger := log.NewSqlLogger(
logger.LogLevel(o.LogLevel),
true,
time.Duration(o.SlowThreshold)*time.Millisecond,
)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: sqlLogger,
})
if err != nil {
return nil, err
}
sqlDB, err := db.DB()
if err != nil {
return nil, err
}
sqlDB.SetConnMaxLifetime(time.Second * time.Duration(o.MaxLifeTime))
sqlDB.SetMaxOpenConns(o.MaxOpenConn)
sqlDB.SetMaxIdleConns(o.MaxIdleConn)
return db, nil
}
// maybeCreateTable creates a database if it does not exists.
func maybeCreateTable(o *option) error {
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true&loc=Local",
o.Username, o.Password, o.Address[0], "mysql")
var db *gorm.DB
var err error
if f := o.Connect; f != nil {
db, err = f(dsn, maxRetry)
} else {
db, err = connectToDatabase(dsn, maxRetry)
}
if err != nil {
panic(err.Error() + " Open failed " + dsn)
}
sqlDB, err := db.DB()
if err != nil {
return err
}
defer sqlDB.Close()
sql := fmt.Sprintf(
"CREATE DATABASE IF NOT EXISTS `%s` default charset utf8mb4 COLLATE utf8mb4_unicode_ci",
o.Database,
)
err = db.Exec(sql).Error
if err != nil {
return fmt.Errorf("init db %w", err)
}
return nil
}
// connectToDatabase Connection retry for mysql.
func connectToDatabase(dsn string, maxRetry int) (*gorm.DB, error) {
var db *gorm.DB
var err error
for i := 0; i <= maxRetry; i++ {
db, err = gorm.Open(mysql.Open(dsn), nil)
if err == nil {
return db, nil
}
if mysqlErr, ok := err.(*mysqldriver.MySQLError); ok && mysqlErr.Number == 1045 {
return nil, err
}
time.Sleep(time.Duration(1) * time.Second)
}
return nil, err
}
// NewGormDB gorm mysql.
func NewGormDB() (*gorm.DB, error) {
specialerror.AddReplace(gorm.ErrRecordNotFound, errs.ErrRecordNotFound)
specialerror.AddErrHandler(replaceDuplicateKey)
return newMysqlGormDB(&option{
Username: config.Config.Mysql.Username,
Password: config.Config.Mysql.Password,
Address: config.Config.Mysql.Address,
Database: config.Config.Mysql.Database,
LogLevel: config.Config.Mysql.LogLevel,
SlowThreshold: config.Config.Mysql.SlowThreshold,
MaxLifeTime: config.Config.Mysql.MaxLifeTime,
MaxOpenConn: config.Config.Mysql.MaxOpenConn,
MaxIdleConn: config.Config.Mysql.MaxIdleConn,
})
}
func replaceDuplicateKey(err error) errs.CodeError {
if IsMysqlDuplicateKey(err) {
return errs.ErrDuplicateKey
}
return nil
}
func IsMysqlDuplicateKey(err error) bool {
if mysqlErr, ok := err.(*mysqldriver.MySQLError); ok {
return mysqlErr.Number == 1062
}
return false
}

@ -1,121 +0,0 @@
package relation
import (
"context"
"database/sql"
"database/sql/driver"
"errors"
"fmt"
"reflect"
"testing"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
func TestMaybeCreateTable(t *testing.T) {
t.Run("normal", func(t *testing.T) {
err := maybeCreateTable(&option{
Username: "root",
Password: "openIM123",
Address: []string{"172.28.0.1:13306"},
Database: "openIM_v3",
LogLevel: 4,
SlowThreshold: 500,
MaxOpenConn: 1000,
MaxIdleConn: 100,
MaxLifeTime: 60,
Connect: connect(expectExec{
query: "CREATE DATABASE IF NOT EXISTS `openIM_v3` default charset utf8mb4 COLLATE utf8mb4_unicode_ci",
args: nil,
}),
})
if err != nil {
t.Fatal(err)
}
})
t.Run("im-db", func(t *testing.T) {
err := maybeCreateTable(&option{
Username: "root",
Password: "openIM123",
Address: []string{"172.28.0.1:13306"},
Database: "im-db",
LogLevel: 4,
SlowThreshold: 500,
MaxOpenConn: 1000,
MaxIdleConn: 100,
MaxLifeTime: 60,
Connect: connect(expectExec{
query: "CREATE DATABASE IF NOT EXISTS `im-db` default charset utf8mb4 COLLATE utf8mb4_unicode_ci",
args: nil,
}),
})
if err != nil {
t.Fatal(err)
}
})
t.Run("err", func(t *testing.T) {
e := errors.New("e")
err := maybeCreateTable(&option{
Username: "root",
Password: "openIM123",
Address: []string{"172.28.0.1:13306"},
Database: "openIM_v3",
LogLevel: 4,
SlowThreshold: 500,
MaxOpenConn: 1000,
MaxIdleConn: 100,
MaxLifeTime: 60,
Connect: connect(expectExec{
err: e,
}),
})
if !errors.Is(err, e) {
t.Fatalf("err not is e: %v", err)
}
})
}
func connect(e expectExec) func(string, int) (*gorm.DB, error) {
return func(string, int) (*gorm.DB, error) {
return gorm.Open(mysql.New(mysql.Config{
SkipInitializeWithVersion: true,
Conn: sql.OpenDB(e),
}), &gorm.Config{
Logger: logger.Discard,
})
}
}
type expectExec struct {
err error
query string
args []driver.NamedValue
}
func (c expectExec) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
if c.err != nil {
return nil, c.err
}
if query != c.query {
return nil, fmt.Errorf("query mismatch. expect: %s, got: %s", c.query, query)
}
if reflect.DeepEqual(args, c.args) {
return nil, fmt.Errorf("args mismatch. expect: %v, got: %v", c.args, args)
}
return noEffectResult{}, nil
}
func (e expectExec) Connect(context.Context) (driver.Conn, error) { return e, nil }
func (expectExec) Driver() driver.Driver { panic("not implemented") }
func (expectExec) Prepare(query string) (driver.Stmt, error) { panic("not implemented") }
func (expectExec) Close() (e error) { return }
func (expectExec) Begin() (driver.Tx, error) { panic("not implemented") }
type noEffectResult struct{}
func (noEffectResult) LastInsertId() (i int64, e error) { return }
func (noEffectResult) RowsAffected() (i int64, e error) { return }

@ -1,54 +0,0 @@
// 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 relation
//
//import (
// "context"
//
// "gorm.io/gorm"
//
// "github.com/OpenIMSDK/tools/errs"
//
// "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
//)
//
//type ObjectInfoGorm struct {
// *MetaDB
//}
//
//func NewObjectInfo(db *gorm.DB) relation.ObjectInfoModelInterface {
// return &ObjectInfoGorm{
// NewMetaDB(db, &relation.ObjectModel{}),
// }
//}
//
//func (o *ObjectInfoGorm) NewTx(tx any) relation.ObjectInfoModelInterface {
// 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 {
// return errs.Wrap(err)
// }
// return nil
//}
//
//func (o *ObjectInfoGorm) Take(ctx context.Context, name string) (info *relation.ObjectModel, err error) {
// info = &relation.ObjectModel{}
// return info, errs.Wrap(o.DB.WithContext(ctx).Where("name = ?", name).Take(info).Error)
//}

@ -1,138 +0,0 @@
// 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 relation
//
//import (
// "context"
// "time"
//
// "github.com/OpenIMSDK/tools/errs"
//
// "gorm.io/gorm"
//
// "github.com/OpenIMSDK/tools/utils"
//
// "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"
//)
//
//type UserGorm struct {
// *MetaDB
//}
//
//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) 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) 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, "")
// return user, err
//}
//
//// 获取用户信息 不存在,不返回错误.
//func (u *UserGorm) Page(
// ctx context.Context,
// pageNumber, showNumber int32,
//) (users []*relation.UserModel, count int64, err error) {
// err = utils.Wrap(u.db(ctx).Count(&count).Error, "")
// if err != nil {
// return
// }
// err = utils.Wrap(
// u.db(ctx).
// Limit(int(showNumber)).
// Offset(int((pageNumber-1)*showNumber)).
// Find(&users).
// Order("create_time DESC").
// Error,
// "",
// )
// return
//}
//
//// 获取所有用户ID.
//func (u *UserGorm) GetAllUserID(ctx context.Context, pageNumber, showNumber int32) (userIDs []string, err error) {
// if pageNumber == 0 || showNumber == 0 {
// 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) CountTotal(ctx context.Context, before *time.Time) (count int64, err error) {
// db := u.db(ctx).Model(&relation.UserModel{})
// if before != nil {
// db = db.Where("create_time < ?", before)
// }
// if err := db.Count(&count).Error; err != nil {
// return 0, err
// }
// return count, nil
//}
//
//func (u *UserGorm) CountRangeEverydayTotal(
// ctx context.Context,
// start time.Time,
// end time.Time,
//) (map[string]int64, error) {
// var res []struct {
// Date time.Time `gorm:"column:date"`
// Count int64 `gorm:"column:count"`
// }
// err := u.db(ctx).
// Model(&relation.UserModel{}).
// 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 {
// return nil, errs.Wrap(err)
// }
// v := make(map[string]int64)
// for _, r := range res {
// v[r.Date.Format("2006-01-02")] = r.Count
// }
// return v, nil
//}

@ -1,323 +0,0 @@
package kodo
import (
"context"
"errors"
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
awss3config "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
awss3 "github.com/aws/aws-sdk-go-v2/service/s3"
awss3types "github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/openimsdk/open-im-server/v3/pkg/common/config"
"github.com/openimsdk/open-im-server/v3/pkg/common/db/s3"
"github.com/qiniu/go-sdk/v7/auth"
"github.com/qiniu/go-sdk/v7/storage"
)
const (
minPartSize = 1024 * 1024 * 1 // 1MB
maxPartSize = 1024 * 1024 * 1024 * 5 // 5GB
maxNumSize = 10000
)
type Kodo struct {
AccessKey string
SecretKey string
Region string
Token string
Endpoint string
BucketURL string
Auth *auth.Credentials
Client *awss3.Client
PresignClient *awss3.PresignClient
}
func NewKodo() (s3.Interface, error) {
conf := config.Config.Object.Kodo
//init client
cfg, err := awss3config.LoadDefaultConfig(context.TODO(),
awss3config.WithRegion(conf.Bucket),
awss3config.WithEndpointResolverWithOptions(
aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
return aws.Endpoint{URL: conf.Endpoint}, nil
})),
awss3config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(
conf.AccessKeyID,
conf.AccessKeySecret,
conf.SessionToken),
),
)
if err != nil {
panic(err)
}
client := awss3.NewFromConfig(cfg)
presignClient := awss3.NewPresignClient(client)
return &Kodo{
AccessKey: conf.AccessKeyID,
SecretKey: conf.AccessKeySecret,
Region: conf.Bucket,
BucketURL: conf.BucketURL,
Auth: auth.New(conf.AccessKeyID, conf.AccessKeySecret),
Client: client,
PresignClient: presignClient,
}, nil
}
func (k Kodo) Engine() string {
return "kodo"
}
func (k Kodo) PartLimit() *s3.PartLimit {
return &s3.PartLimit{
MinPartSize: minPartSize,
MaxPartSize: maxPartSize,
MaxNumSize: maxNumSize,
}
}
func (k Kodo) InitiateMultipartUpload(ctx context.Context, name string) (*s3.InitiateMultipartUploadResult, error) {
result, err := k.Client.CreateMultipartUpload(ctx, &awss3.CreateMultipartUploadInput{
Bucket: aws.String(k.Region),
Key: aws.String(name),
})
if err != nil {
return nil, err
}
return &s3.InitiateMultipartUploadResult{
UploadID: aws.ToString(result.UploadId),
Bucket: aws.ToString(result.Bucket),
Key: aws.ToString(result.Key),
}, nil
}
func (k Kodo) CompleteMultipartUpload(ctx context.Context, uploadID string, name string, parts []s3.Part) (*s3.CompleteMultipartUploadResult, error) {
kodoParts := make([]awss3types.CompletedPart, len(parts))
for i, part := range parts {
kodoParts[i] = awss3types.CompletedPart{
PartNumber: aws.Int32(int32(part.PartNumber)),
ETag: aws.String(part.ETag),
}
}
result, err := k.Client.CompleteMultipartUpload(ctx, &awss3.CompleteMultipartUploadInput{
Bucket: aws.String(k.Region),
Key: aws.String(name),
UploadId: aws.String(uploadID),
MultipartUpload: &awss3types.CompletedMultipartUpload{Parts: kodoParts},
})
if err != nil {
return nil, err
}
return &s3.CompleteMultipartUploadResult{
Location: aws.ToString(result.Location),
Bucket: aws.ToString(result.Bucket),
Key: aws.ToString(result.Key),
ETag: strings.ToLower(strings.ReplaceAll(aws.ToString(result.ETag), `"`, ``)),
}, nil
}
func (k Kodo) PartSize(ctx context.Context, size int64) (int64, error) {
if size <= 0 {
return 0, errors.New("size must be greater than 0")
}
if size > maxPartSize*maxNumSize {
return 0, fmt.Errorf("size must be less than %db", maxPartSize*maxNumSize)
}
if size <= minPartSize*maxNumSize {
return minPartSize, nil
}
partSize := size / maxNumSize
if size%maxNumSize != 0 {
partSize++
}
return partSize, nil
}
func (k Kodo) AuthSign(ctx context.Context, uploadID string, name string, expire time.Duration, partNumbers []int) (*s3.AuthSignResult, error) {
result := s3.AuthSignResult{
URL: k.BucketURL + "/" + name,
Query: url.Values{"uploadId": {uploadID}},
Header: make(http.Header),
Parts: make([]s3.SignPart, len(partNumbers)),
}
for i, partNumber := range partNumbers {
part, _ := k.PresignClient.PresignUploadPart(ctx, &awss3.UploadPartInput{
Bucket: aws.String(k.Region),
UploadId: aws.String(uploadID),
Key: aws.String(name),
PartNumber: aws.Int32(int32(partNumber)),
})
result.Parts[i] = s3.SignPart{
PartNumber: partNumber,
URL: part.URL,
Header: part.SignedHeader,
}
}
return &result, nil
}
func (k Kodo) PresignedPutObject(ctx context.Context, name string, expire time.Duration) (string, error) {
object, err := k.PresignClient.PresignPutObject(ctx, &awss3.PutObjectInput{
Bucket: aws.String(k.Region),
Key: aws.String(name),
}, func(po *awss3.PresignOptions) {
po.Expires = expire
})
return object.URL, err
}
func (k Kodo) DeleteObject(ctx context.Context, name string) error {
_, err := k.Client.DeleteObject(ctx, &awss3.DeleteObjectInput{
Bucket: aws.String(k.Region),
Key: aws.String(name),
})
return err
}
func (k Kodo) CopyObject(ctx context.Context, src string, dst string) (*s3.CopyObjectInfo, error) {
result, err := k.Client.CopyObject(ctx, &awss3.CopyObjectInput{
Bucket: aws.String(k.Region),
CopySource: aws.String(k.Region + "/" + src),
Key: aws.String(dst),
})
if err != nil {
return nil, err
}
return &s3.CopyObjectInfo{
Key: dst,
ETag: strings.ToLower(strings.ReplaceAll(aws.ToString(result.CopyObjectResult.ETag), `"`, ``)),
}, nil
}
func (k Kodo) StatObject(ctx context.Context, name string) (*s3.ObjectInfo, error) {
info, err := k.Client.HeadObject(ctx, &awss3.HeadObjectInput{
Bucket: aws.String(k.Region),
Key: aws.String(name),
})
if err != nil {
return nil, err
}
res := &s3.ObjectInfo{Key: name}
res.Size = aws.ToInt64(info.ContentLength)
res.ETag = strings.ToLower(strings.ReplaceAll(aws.ToString(info.ETag), `"`, ``))
return res, nil
}
func (k Kodo) IsNotFound(err error) bool {
return true
}
func (k Kodo) AbortMultipartUpload(ctx context.Context, uploadID string, name string) error {
_, err := k.Client.AbortMultipartUpload(ctx, &awss3.AbortMultipartUploadInput{
UploadId: aws.String(uploadID),
Bucket: aws.String(k.Region),
Key: aws.String(name),
})
return err
}
func (k Kodo) ListUploadedParts(ctx context.Context, uploadID string, name string, partNumberMarker int, maxParts int) (*s3.ListUploadedPartsResult, error) {
result, err := k.Client.ListParts(ctx, &awss3.ListPartsInput{
Key: aws.String(name),
UploadId: aws.String(uploadID),
Bucket: aws.String(k.Region),
MaxParts: aws.Int32(int32(maxParts)),
PartNumberMarker: aws.String(strconv.Itoa(partNumberMarker)),
})
if err != nil {
return nil, err
}
res := &s3.ListUploadedPartsResult{
Key: aws.ToString(result.Key),
UploadID: aws.ToString(result.UploadId),
MaxParts: int(aws.ToInt32(result.MaxParts)),
UploadedParts: make([]s3.UploadedPart, len(result.Parts)),
}
// int to string
NextPartNumberMarker, err := strconv.Atoi(aws.ToString(result.NextPartNumberMarker))
if err != nil {
return nil, err
}
res.NextPartNumberMarker = NextPartNumberMarker
for i, part := range result.Parts {
res.UploadedParts[i] = s3.UploadedPart{
PartNumber: int(aws.ToInt32(part.PartNumber)),
LastModified: aws.ToTime(part.LastModified),
ETag: aws.ToString(part.ETag),
Size: aws.ToInt64(part.Size),
}
}
return res, nil
}
func (k Kodo) AccessURL(ctx context.Context, name string, expire time.Duration, opt *s3.AccessURLOption) (string, error) {
//get object head
info, err := k.Client.HeadObject(ctx, &awss3.HeadObjectInput{
Bucket: aws.String(k.Region),
Key: aws.String(name),
})
if err != nil {
return "", errors.New("AccessURL object not found")
}
if opt != nil {
if opt.ContentType != aws.ToString(info.ContentType) {
//修改文件类型
err := k.SetObjectContentType(ctx, name, opt.ContentType)
if err != nil {
return "", errors.New("AccessURL setContentType error")
}
}
}
imageMogr := ""
//image dispose
if opt != nil {
if opt.Image != nil {
//https://developer.qiniu.com/dora/8255/the-zoom
process := ""
if opt.Image.Width > 0 {
process += strconv.Itoa(opt.Image.Width) + "x"
}
if opt.Image.Height > 0 {
if opt.Image.Width > 0 {
process += strconv.Itoa(opt.Image.Height)
} else {
process += "x" + strconv.Itoa(opt.Image.Height)
}
}
imageMogr = "imageMogr2/thumbnail/" + process
}
}
//expire
deadline := time.Now().Add(time.Second * expire).Unix()
domain := k.BucketURL
query := url.Values{}
if opt != nil && opt.Filename != "" {
query.Add("attname", opt.Filename)
}
privateURL := storage.MakePrivateURLv2WithQuery(k.Auth, domain, name, query, deadline)
if imageMogr != "" {
privateURL += "&" + imageMogr
}
return privateURL, nil
}
func (k *Kodo) SetObjectContentType(ctx context.Context, name string, contentType string) error {
//set object content-type
_, err := k.Client.CopyObject(ctx, &awss3.CopyObjectInput{
Bucket: aws.String(k.Region),
CopySource: aws.String(k.Region + "/" + name),
Key: aws.String(name),
ContentType: aws.String(contentType),
MetadataDirective: awss3types.MetadataDirectiveReplace,
})
return err
}

@ -17,33 +17,27 @@ package relation
import (
"context"
"time"
)
const (
BlackModelTableName = "blacks"
"github.com/OpenIMSDK/tools/pagination"
)
type BlackModel struct {
OwnerUserID string `gorm:"column:owner_user_id;primary_key;size:64"`
BlockUserID string `gorm:"column:block_user_id;primary_key;size:64"`
CreateTime time.Time `gorm:"column:create_time"`
AddSource int32 `gorm:"column:add_source"`
OperatorUserID string `gorm:"column:operator_user_id;size:64"`
Ex string `gorm:"column:ex;size:1024"`
}
func (BlackModel) TableName() string {
return BlackModelTableName
OwnerUserID string `bson:"owner_user_id"`
BlockUserID string `bson:"block_user_id"`
CreateTime time.Time `bson:"create_time"`
AddSource int32 `bson:"add_source"`
OperatorUserID string `bson:"operator_user_id"`
Ex string `bson:"ex"`
}
type BlackModelInterface interface {
Create(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]any) (err error)
Update(ctx context.Context, blacks []*BlackModel) (err error)
//UpdateByMap(ctx context.Context, ownerUserID, blockUserID string, args map[string]any) (err error)
//Update(ctx context.Context, blacks []*BlackModel) (err error)
Find(ctx context.Context, blacks []*BlackModel) (blackList []*BlackModel, err error)
Take(ctx context.Context, ownerUserID, blockUserID string) (black *BlackModel, err error)
FindOwnerBlacks(ctx context.Context, ownerUserID string, pageNumber, showNumber int32) (blacks []*BlackModel, total int64, err error)
FindOwnerBlacks(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, blacks []*BlackModel, err error)
FindOwnerBlackInfos(ctx context.Context, ownerUserID string, userIDs []string) (blacks []*BlackModel, err error)
FindBlackUserIDs(ctx context.Context, ownerUserID string) (blackUserIDs []string, err error)
}

@ -1,51 +0,0 @@
// 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 relation
import (
"time"
pbmsg "github.com/OpenIMSDK/protocol/msg"
)
const (
ChatLogModelTableName = "chat_logs"
)
type ChatLogModel struct {
ServerMsgID string `gorm:"column:server_msg_id;primary_key;type:char(64)" json:"serverMsgID"`
ClientMsgID string `gorm:"column:client_msg_id;type:char(64)" json:"clientMsgID"`
SendID string `gorm:"column:send_id;type:char(64);index:send_id,priority:2" json:"sendID"`
RecvID string `gorm:"column:recv_id;type:char(64);index:recv_id,priority:2" json:"recvID"`
SenderPlatformID int32 `gorm:"column:sender_platform_id" json:"senderPlatformID"`
SenderNickname string `gorm:"column:sender_nick_name;type:varchar(255)" json:"senderNickname"`
SenderFaceURL string `gorm:"column:sender_face_url;type:varchar(255);" json:"senderFaceURL"`
SessionType int32 `gorm:"column:session_type;index:session_type,priority:2;index:session_type_alone" json:"sessionType"`
MsgFrom int32 `gorm:"column:msg_from" json:"msgFrom"`
ContentType int32 `gorm:"column:content_type;index:content_type,priority:2;index:content_type_alone" json:"contentType"`
Content string `gorm:"column:content;type:varchar(3000)" json:"content"`
Status int32 `gorm:"column:status" json:"status"`
SendTime time.Time `gorm:"column:send_time;index:sendTime;index:content_type,priority:1;index:session_type,priority:1;index:recv_id,priority:1;index:send_id,priority:1" json:"sendTime"`
CreateTime time.Time `gorm:"column:create_time" json:"createTime"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
}
func (ChatLogModel) TableName() string {
return ChatLogModelTableName
}
type ChatLogModelInterface interface {
Create(msg *pbmsg.MsgDataToMQ) error
}

@ -16,35 +16,11 @@ package relation
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time"
)
const (
conversationModelTableName = "conversations"
"github.com/OpenIMSDK/tools/pagination"
)
//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 {
OwnerUserID string `bson:"owner_user_id"`
ConversationID string `bson:"conversation_id"`
@ -66,10 +42,6 @@ type ConversationModel struct {
LatestMsgDestructTime time.Time `bson:"latest_msg_destruct_time"`
}
func (ConversationModel) TableName() string {
return conversationModelTableName
}
type ConversationModelInterface interface {
Create(ctx context.Context, conversations []*ConversationModel) (err error)
Delete(ctx context.Context, groupIDs []string) (err error)
@ -83,11 +55,9 @@ type ConversationModelInterface interface {
FindUserIDAllConversations(ctx context.Context, userID string) (conversations []*ConversationModel, err error)
FindRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
GetUserRecvMsgOpt(ctx context.Context, ownerUserID, conversationID string) (opt int, err error)
//FindSuperGroupRecvMsgNotNotifyUserIDs(ctx context.Context, groupID string) ([]string, error)
GetAllConversationIDs(ctx context.Context) ([]string, error)
GetAllConversationIDsNumber(ctx context.Context) (int64, error)
PageConversationIDs(ctx context.Context, pagination pagination.Pagination) (conversationIDs []string, err error)
//GetUserAllHasReadSeqs(ctx context.Context, ownerUserID string) (hashReadSeqs map[string]int64, err error)
GetConversationsByConversationID(ctx context.Context, conversationIDs []string) ([]*ConversationModel, error)
GetConversationIDsNeedDestruct(ctx context.Context) ([]*ConversationModel, error)
GetConversationNotReceiveMessageUserIDs(ctx context.Context, conversationID string) ([]string, error)

@ -1,15 +0,0 @@
// 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 relation // import "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation"

@ -18,24 +18,11 @@ import (
"context"
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
"github.com/OpenIMSDK/tools/pagination"
)
const (
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 {
ID primitive.ObjectID `bson:"_id,omitempty"`
OwnerUserID string `bson:"owner_user_id"`
FriendUserID string `bson:"friend_user_id"`
Remark string `bson:"remark"`
@ -45,11 +32,6 @@ type FriendModel struct {
Ex string `bson:"ex"`
}
// CollectionName returns the name of the MongoDB collection.
func (FriendModel) CollectionName() string {
return FriendModelCollectionName
}
// FriendModelInterface defines the operations for managing friends in MongoDB.
type FriendModelInterface interface {
// Create inserts multiple friend records.
@ -58,9 +40,7 @@ type FriendModelInterface interface {
Delete(ctx context.Context, ownerUserID string, friendUserIDs []string) (err error)
// UpdateByMap updates specific fields of a friend document using a map.
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)
// UpdateRemark updates the remark for a specific friend.
// UpdateRemark modify remarks.
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)
@ -71,11 +51,9 @@ type FriendModelInterface interface {
// FindReversalFriends finds users who have added the specified user as a friend.
FindReversalFriends(ctx context.Context, friendUserID string, ownerUserIDs []string) (friends []*FriendModel, err error)
// FindOwnerFriends retrieves a paginated list of friends for a given owner.
FindOwnerFriends(ctx context.Context, ownerUserID string, pageNumber, showNumber int32) (friends []*FriendModel, total int64, err error)
FindOwnerFriends(ctx context.Context, ownerUserID string, pagination pagination.Pagination) (total int64, friends []*FriendModel, err error)
// FindInWhoseFriends finds users who have added the specified user as a friend, with pagination.
FindInWhoseFriends(ctx context.Context, friendUserID string, pageNumber, showNumber int32) (friends []*FriendModel, total int64, err error)
FindInWhoseFriends(ctx context.Context, friendUserID string, pagination pagination.Pagination) (total int64, friends []*FriendModel, err error)
// FindFriendUserIDs retrieves a list of friend user IDs for a given owner.
FindFriendUserIDs(ctx context.Context, ownerUserID string) (friendUserIDs []string, err error)
// NewTx creates a new transaction.
NewTx(tx any) FriendModelInterface
}

@ -18,13 +18,10 @@ import (
"context"
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
"github.com/OpenIMSDK/tools/pagination"
)
const FriendRequestModelCollectionName = "friend_requests"
type FriendRequestModel struct {
ID primitive.ObjectID `bson:"_id,omitempty"`
FromUserID string `bson:"from_user_id"`
ToUserID string `bson:"to_user_id"`
HandleResult int32 `bson:"handle_result"`
@ -36,10 +33,6 @@ type FriendRequestModel struct {
Ex string `bson:"ex"`
}
func (FriendRequestModel) CollectionName() string {
return FriendRequestModelCollectionName
}
type FriendRequestModelInterface interface {
// Insert multiple records
Create(ctx context.Context, friendRequests []*FriendRequestModel) (err error)
@ -53,11 +46,8 @@ type FriendRequestModelInterface interface {
Find(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error)
Take(ctx context.Context, fromUserID, toUserID string) (friendRequest *FriendRequestModel, err error)
// Get list of friend requests received by toUserID
FindToUserID(ctx context.Context,toUserID string,pageNumber, showNumber int32,) (friendRequests []*FriendRequestModel, total int64, err error)
FindToUserID(ctx context.Context, toUserID string, pagination pagination.Pagination) (total int64, friendRequests []*FriendRequestModel, err error)
// Get list of friend requests sent by fromUserID
FindFromUserID(ctx context.Context,fromUserID string,pageNumber, showNumber int32,) (friendRequests []*FriendRequestModel, total int64, err error)
FindFromUserID(ctx context.Context, fromUserID string, pagination pagination.Pagination) (total int64, friendRequests []*FriendRequestModel, err error)
FindBothFriendRequests(ctx context.Context, fromUserID, toUserID string) (friends []*FriendRequestModel, err error)
NewTx(tx any) FriendRequestModelInterface
// Check if the record exists
Exist(ctx context.Context, userID string) (exist bool, err error)
}

@ -16,32 +16,11 @@ package relation
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time"
)
const (
GroupModelTableName = "groups"
"github.com/OpenIMSDK/tools/pagination"
)
//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 {
GroupID string `bson:"group_id"`
GroupName string `bson:"group_name"`
@ -60,10 +39,6 @@ type GroupModel struct {
NotificationUserID string `bson:"notification_user_id"`
}
func (GroupModel) TableName() string {
return GroupModelTableName
}
type GroupModelInterface interface {
Create(ctx context.Context, groups []*GroupModel) (err error)
UpdateMap(ctx context.Context, groupID string, args map[string]any) (err error)

@ -16,28 +16,11 @@ package relation
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time"
)
const (
GroupMemberModelTableName = "group_members"
"github.com/OpenIMSDK/tools/pagination"
)
//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 {
GroupID string `bson:"group_id"`
UserID string `bson:"user_id"`
@ -52,10 +35,6 @@ type GroupMemberModel struct {
Ex string `bson:"ex"`
}
func (GroupMemberModel) TableName() string {
return GroupMemberModelTableName
}
type GroupMemberModelInterface interface {
//NewTx(tx any) GroupMemberModelInterface
Create(ctx context.Context, groupMembers []*GroupMemberModel) (err error)

@ -16,28 +16,11 @@ package relation
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time"
)
const (
GroupRequestModelTableName = "group_requests"
"github.com/OpenIMSDK/tools/pagination"
)
//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 {
UserID string `bson:"user_id"`
GroupID string `bson:"group_id"`
@ -52,10 +35,6 @@ type GroupRequestModel struct {
Ex string `bson:"ex"`
}
func (GroupRequestModel) TableName() string {
return GroupRequestModelTableName
}
type GroupRequestModelInterface interface {
Create(ctx context.Context, groupRequests []*GroupRequestModel) (err error)
Delete(ctx context.Context, groupID string, userID string) (err error)

@ -2,23 +2,12 @@ package relation
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"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)"`
//}
"github.com/OpenIMSDK/tools/pagination"
)
type Log struct {
type LogModel struct {
LogID string `bson:"log_id"`
Platform string `bson:"platform"`
UserID string `bson:"user_id"`
@ -31,8 +20,8 @@ type Log struct {
}
type LogInterface interface {
Create(ctx context.Context, log []*Log) error
Search(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*Log, error)
Create(ctx context.Context, log []*LogModel) error
Search(ctx context.Context, keyword string, start time.Time, end time.Time, pagination pagination.Pagination) (int64, []*LogModel, 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) ([]*LogModel, error)
}

@ -19,10 +19,6 @@ import (
"time"
)
const (
ObjectInfoModelTableName = "object"
)
type ObjectModel struct {
Name string `bson:"name"`
UserID string `bson:"user_id"`
@ -35,22 +31,6 @@ type ObjectModel struct {
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 {
return ObjectInfoModelTableName
}
type ObjectInfoModelInterface interface {
SetObject(ctx context.Context, obj *ObjectModel) error
Take(ctx context.Context, engine string, name string) (*ObjectModel, error)

@ -16,8 +16,9 @@ package relation
import (
"context"
"github.com/openimsdk/open-im-server/v3/pkg/common/pagination"
"time"
"github.com/OpenIMSDK/tools/pagination"
)
type UserModel struct {

@ -15,9 +15,8 @@
package relation
import (
"gorm.io/gorm"
"github.com/OpenIMSDK/tools/utils"
"go.mongodb.org/mongo-driver/mongo"
)
type BatchUpdateGroupMember struct {
@ -32,5 +31,5 @@ type GroupSimpleUserID struct {
}
func IsNotFound(err error) bool {
return utils.Unwrap(err) == gorm.ErrRecordNotFound
return utils.Unwrap(err) == mongo.ErrNoDocuments
}

@ -1,19 +0,0 @@
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
}

@ -1,16 +0,0 @@
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)
}

@ -1,28 +0,0 @@
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
}
Loading…
Cancel
Save