feat: incr sync version.

This commit is contained in:
Gordon
2024-06-24 17:48:33 +08:00
parent e8ccae6349
commit 88b8043224
308 changed files with 55952 additions and 59 deletions

View File

@@ -0,0 +1,131 @@
// Copyright © 2023 OpenIM SDK. 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 ccontext
import (
"context"
"github.com/openimsdk/openim-sdk-core/v3/open_im_sdk_callback"
"github.com/openimsdk/openim-sdk-core/v3/sdk_struct"
"github.com/openimsdk/tools/mcontext"
)
const (
Callback = "callback"
)
type GlobalConfig struct {
UserID string
Token string
sdk_struct.IMConfig
}
type ContextInfo interface {
UserID() string
Token() string
PlatformID() int32
ApiAddr() string
WsAddr() string
DataDir() string
LogLevel() uint32
OperationID() string
IsExternalExtensions() bool
}
func Info(ctx context.Context) ContextInfo {
conf := ctx.Value(GlobalConfigKey{}).(*GlobalConfig)
return &info{
conf: conf,
ctx: ctx,
}
}
func WithInfo(ctx context.Context, conf *GlobalConfig) context.Context {
return context.WithValue(ctx, GlobalConfigKey{}, conf)
}
func WithOperationID(ctx context.Context, operationID string) context.Context {
return mcontext.SetOperationID(ctx, operationID)
}
func WithSendMessageCallback(ctx context.Context, callback open_im_sdk_callback.SendMsgCallBack) context.Context {
return context.WithValue(ctx, Callback, callback)
}
func WithApiErrCode(ctx context.Context, cb ApiErrCodeCallback) context.Context {
return context.WithValue(ctx, apiErrCode{}, cb)
}
func GetApiErrCodeCallback(ctx context.Context) ApiErrCodeCallback {
fn, _ := ctx.Value(apiErrCode{}).(ApiErrCodeCallback)
if fn == nil {
return &emptyApiErrCodeCallback{}
}
return fn
}
type GlobalConfigKey struct{}
type info struct {
conf *GlobalConfig
ctx context.Context
}
func (i *info) UserID() string {
return i.conf.UserID
}
func (i *info) Token() string {
return i.conf.Token
}
func (i *info) PlatformID() int32 {
return i.conf.PlatformID
}
func (i *info) ApiAddr() string {
return i.conf.ApiAddr
}
func (i *info) WsAddr() string {
return i.conf.WsAddr
}
func (i *info) DataDir() string {
return i.conf.DataDir
}
func (i *info) LogLevel() uint32 {
return i.conf.LogLevel
}
func (i *info) OperationID() string {
return mcontext.GetOperationID(i.ctx)
}
func (i *info) IsExternalExtensions() bool {
return i.conf.IsExternalExtensions
}
type apiErrCode struct{}
type ApiErrCodeCallback interface {
OnError(ctx context.Context, err error)
}
type emptyApiErrCodeCallback struct{}
func (e *emptyApiErrCodeCallback) OnError(ctx context.Context, err error) {}

View File

@@ -0,0 +1,41 @@
// Copyright © 2023 OpenIM SDK. 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 ccontext
import (
"context"
"fmt"
"testing"
)
func TestName(t *testing.T) {
ctx := context.Background()
conf := GlobalConfig{
UserID: "uid123",
}
ctx = WithInfo(ctx, &conf)
operationID := "opid123"
ctx = WithOperationID(ctx, operationID)
fmt.Println("UserID:", Info(ctx).UserID())
fmt.Println("OperationID:", Info(ctx).OperationID())
if Info(ctx).UserID() != conf.UserID {
t.Fatal("UserID not match")
}
if Info(ctx).OperationID() != operationID {
t.Fatal("OperationID not match")
}
}

View File

@@ -0,0 +1,148 @@
// Copyright © 2023 OpenIM SDK. 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 common
import (
"encoding/json"
"github.com/openimsdk/openim-sdk-core/v3/open_im_sdk_callback"
"github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"runtime"
)
//var validate *validator.Validate
//funcation init() {
// validate = validator.New()
//}
func CheckAnyErrCallback(callback open_im_sdk_callback.Base, errCode int32, err error, operationID string) {
if err != nil {
errInfo := "operationID[" + operationID + "], " + "info[" + err.Error() + "]"
//log.NewError(operationID, "checkErr ", errInfo)
callback.OnError(errCode, errInfo)
runtime.Goexit()
}
}
func CheckConfigErrCallback(callback open_im_sdk_callback.Base, err error, operationID string) {
CheckAnyErrCallback(callback, sdkerrs.ArgsError, err, operationID)
}
//func CheckTokenErrCallback(callback open_im_sdk_callback.Base, err error, operationID string) {
// CheckAnyErrCallback(callback, sdkerrs.TokenInvalidError, err, operationID)
//}
func CheckDBErrCallback(callback open_im_sdk_callback.Base, err error, operationID string) {
CheckAnyErrCallback(callback, sdkerrs.SdkInternalError, err, operationID)
}
func CheckDataErrCallback(callback open_im_sdk_callback.Base, err error, operationID string) {
CheckAnyErrCallback(callback, sdkerrs.SdkInternalError, err, operationID)
}
func CheckArgsErrCallback(callback open_im_sdk_callback.Base, err error, operationID string) {
CheckAnyErrCallback(callback, sdkerrs.ArgsError, err, operationID)
}
//
//funcation CheckErrAndResp2(err error, resp []byte, output interface{}) error {
// if err != nil {
// return utils.Wrap(err, "api resp failed")
// }
// var c server_api_params.CommDataResp
// err = json.Unmarshal(resp, &c)
// if err == nil {
// if c.ErrCode != 0 {
// return utils.Wrap(errors.New(c.ErrMsg), "")
// }
// if output != nil {
// err = mapstructure.Decode(c.Data, output)
// if err != nil {
// goto one
// }
// return nil
// }
// return nil
// }
//
// unMarshaler := jsonpb.Unmarshaler{}
// unMarshaler.Unmarshal()
// s, _ := marshaler.MarshalToString(pb)
// out := make(map[string]interface{})
// json.Unmarshal([]byte(s), &out)
// if idFix {
// if _, ok := out["id"]; ok {
// out["_id"] = out["id"]
// delete(out, "id")
// }
// }
// return out
//
//one:
// var c2 server_api_params.CommDataRespOne
//
// err = json.Unmarshal(resp, &c2)
// if err != nil {
// return utils.Wrap(err, "")
// }
// if c2.ErrCode != 0 {
// return utils.Wrap(errors.New(c2.ErrMsg), "")
// }
// if output != nil {
// err = mapstructure.Decode(c2.Data, output)
// if err != nil {
// return utils.Wrap(err, "")
// }
// return nil
// }
// return nil
//}
func JsonUnmarshalAndArgsValidate(s string, args interface{}, callback open_im_sdk_callback.Base, operationID string) error {
err := json.Unmarshal([]byte(s), args)
if err != nil {
if callback != nil {
//log.NewError(operationID, "Unmarshal failed ", err.Error(), s)
callback.OnError(sdkerrs.ArgsError, err.Error())
runtime.Goexit()
} else {
return utils.Wrap(err, "json Unmarshal failed")
}
}
//err = validate.Struct(args)
//if err != nil {
// if callback != nil {
// log.NewError(operationID, "validate failed ", err.Error(), s)
// callback.OnError(constant.ErrArgs.ErrCode, constant.ErrArgs.ErrMsg)
// runtime.Goexit()
// }
//}
//return utils.Wrap(err, "args check failed")
return nil
}
func JsonUnmarshalCallback(s string, args interface{}, callback open_im_sdk_callback.Base, operationID string) error {
err := json.Unmarshal([]byte(s), args)
if err != nil {
if callback != nil {
//log.NewError(operationID, "Unmarshal failed ", err.Error(), s)
callback.OnError(sdkerrs.ArgsError, err.Error())
runtime.Goexit()
} else {
return utils.Wrap(err, "json Unmarshal failed")
}
}
return nil
}

View File

@@ -0,0 +1,217 @@
// Copyright © 2023 OpenIM SDK. 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 common
import (
"context"
"errors"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"github.com/openimsdk/openim-sdk-core/v3/sdk_struct"
"time"
"github.com/openimsdk/tools/log"
"github.com/openimsdk/protocol/sdkws"
)
func TriggerCmdJoinedSuperGroup(cmd sdk_struct.CmdJoinedSuperGroup, joinedSuperGroupCh chan Cmd2Value) error {
if joinedSuperGroupCh == nil {
return utils.Wrap(errors.New("ch == nil"), "")
}
c2v := Cmd2Value{Cmd: constant.CmdJoinedSuperGroup, Value: cmd}
return sendCmd(joinedSuperGroupCh, c2v, 100)
}
func TriggerCmdNewMsgCome(ctx context.Context, msg sdk_struct.CmdNewMsgComeToConversation, conversationCh chan Cmd2Value) error {
if conversationCh == nil {
return utils.Wrap(errors.New("ch == nil"), "")
}
c2v := Cmd2Value{Cmd: constant.CmdNewMsgCome, Value: msg, Ctx: ctx}
return sendCmd(conversationCh, c2v, 100)
}
func TriggerCmdSuperGroupMsgCome(msg sdk_struct.CmdNewMsgComeToConversation, conversationCh chan Cmd2Value) error {
if conversationCh == nil {
return utils.Wrap(errors.New("ch == nil"), "")
}
c2v := Cmd2Value{Cmd: constant.CmdSuperGroupMsgCome, Value: msg}
return sendCmd(conversationCh, c2v, 100)
}
func TriggerCmdNotification(ctx context.Context, msg sdk_struct.CmdNewMsgComeToConversation, conversationCh chan Cmd2Value) error {
if conversationCh == nil {
return utils.Wrap(errors.New("ch == nil"), "")
}
c2v := Cmd2Value{Cmd: constant.CmdNotification, Value: msg, Ctx: ctx}
return sendCmd(conversationCh, c2v, 100)
}
func TriggerCmdWakeUp(ch chan Cmd2Value) error {
if ch == nil {
return utils.Wrap(errors.New("ch == nil"), "")
}
c2v := Cmd2Value{Cmd: constant.CmdWakeUp, Value: nil}
return sendCmd(ch, c2v, 100)
}
func TriggerCmdSyncReactionExtensions(node SyncReactionExtensionsNode, conversationCh chan Cmd2Value) error {
if conversationCh == nil {
return utils.Wrap(errors.New("ch == nil"), "")
}
c2v := Cmd2Value{
Cmd: constant.CmSyncReactionExtensions,
Value: node,
}
return sendCmd(conversationCh, c2v, 100)
}
func TriggerCmdUpdateConversation(ctx context.Context, node UpdateConNode, conversationCh chan<- Cmd2Value) error {
c2v := Cmd2Value{
Cmd: constant.CmdUpdateConversation,
Value: node,
Ctx: ctx,
}
return sendCmd(conversationCh, c2v, 100)
}
func TriggerCmdUpdateMessage(ctx context.Context, node UpdateMessageNode, conversationCh chan Cmd2Value) error {
c2v := Cmd2Value{
Cmd: constant.CmdUpdateMessage,
Value: node,
Ctx: ctx,
}
return sendCmd(conversationCh, c2v, 100)
}
// Push message, msg for msgData slice
func TriggerCmdPushMsg(ctx context.Context, msg *sdkws.PushMessages, ch chan Cmd2Value) error {
if ch == nil {
return utils.Wrap(errors.New("ch == nil"), "")
}
c2v := Cmd2Value{Cmd: constant.CmdPushMsg, Value: msg, Ctx: ctx}
return sendCmd(ch, c2v, 100)
}
// seq trigger
func TriggerCmdMaxSeq(ctx context.Context, seq *sdk_struct.CmdMaxSeqToMsgSync, ch chan Cmd2Value) error {
if ch == nil {
return utils.Wrap(errors.New("ch == nil"), "")
}
c2v := Cmd2Value{Cmd: constant.CmdMaxSeq, Value: seq, Ctx: ctx}
return sendCmd(ch, c2v, 100)
}
func TriggerCmdLogOut(ctx context.Context, ch chan Cmd2Value) error {
if ch == nil {
return utils.Wrap(errors.New("ch == nil"), "")
}
c2v := Cmd2Value{Cmd: constant.CmdLogOut, Ctx: ctx}
return sendCmd(ch, c2v, 100)
}
// Connection success trigger
func TriggerCmdConnected(ctx context.Context, ch chan Cmd2Value) error {
if ch == nil {
return utils.Wrap(errors.New("ch == nil"), "")
}
c2v := Cmd2Value{Cmd: constant.CmdConnSuccesss, Value: nil, Ctx: ctx}
return sendCmd(ch, c2v, 100)
}
type DeleteConNode struct {
SourceID string
ConversationID string
SessionType int
}
type SyncReactionExtensionsNode struct {
OperationID string
Action int
Args interface{}
}
type UpdateConNode struct {
ConID string
Action int //1 Delete the conversation; 2 Update the latest news in the conversation or add a conversation; 3 Put a conversation on the top;
// 4 Cancel a conversation on the top, 5 Messages are not read and set to 0, 6 New conversations
Args interface{}
}
type UpdateMessageNode struct {
Action int
Args interface{}
}
type Cmd2Value struct {
Cmd string
Value interface{}
Ctx context.Context
}
type UpdateConInfo struct {
UserID string
GroupID string
}
type UpdateMessageInfo struct {
SessionType int32
UserID string
FaceURL string
Nickname string
GroupID string
}
type SourceIDAndSessionType struct {
SourceID string
SessionType int32
FaceURL string
Nickname string
}
func UnInitAll(conversationCh chan Cmd2Value) error {
c2v := Cmd2Value{Cmd: constant.CmdUnInit}
return sendCmd(conversationCh, c2v, 100)
}
type goroutine interface {
Work(cmd Cmd2Value)
GetCh() chan Cmd2Value
//GetContext() context.Context
}
func DoListener(Li goroutine, ctx context.Context) {
for {
select {
case cmd := <-Li.GetCh():
Li.Work(cmd)
case <-ctx.Done():
log.ZInfo(ctx, "conversation done sdk logout.....")
return
}
}
}
func sendCmd(ch chan<- Cmd2Value, value Cmd2Value, timeout int64) error {
select {
case ch <- value:
return nil
case <-time.After(time.Millisecond * time.Duration(timeout)):
return errors.New("send cmd timeout")
}
}

View File

@@ -0,0 +1,33 @@
// Copyright © 2023 OpenIM SDK. 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 common
//import (
// "github.com/mitchellh/mapstructure"
// "open_im_sdk/open_im_sdk_callback"
// "open_im_sdk/pkg/db"
// "open_im_sdk/pkg/db/model_struct"
//)
//
//funcation GetGroupMemberListByGroupID(callback open_im_sdk_callback.Base, operationID string, db *db.DataBase, groupID string) []*model_struct.LocalGroupMember {
// memberList, err := db.GetGroupMemberListByGroupID(groupID)
// CheckDBErrCallback(callback, err, operationID)
// return memberList
//}
//
//funcation MapstructureDecode(input interface{}, output interface{}, callback open_im_sdk_callback.Base, oprationID string) {
// err := mapstructure.Decode(input, output)
// CheckDataErrCallback(callback, err, oprationID)
//}

View File

@@ -0,0 +1,428 @@
// Copyright © 2023 OpenIM SDK. 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 constant
const (
CmdFriend = "001"
CmdBlackList = "002"
CmdNotification = "003"
CmdDeleteConversation = "004"
CmdNewMsgCome = "005"
CmdSuperGroupMsgCome = "006"
CmdUpdateConversation = "007"
CmSyncReactionExtensions = "008"
CmdFroceSyncBlackList = "009"
CmdForceSyncFriendApplication = "010"
CmdForceSyncMsg = "011"
CmdForceSyncLoginUerInfo = "012"
CmdReLogin = "013"
CmdUnInit = "014"
CmdAcceptFriend = "015"
CmdRefuseFriend = "016"
CmdAddFriend = "017"
CmdJoinedSuperGroup = "018"
CmdUpdateMessage = "019"
CmdReconnect = "020"
CmdInit = "021"
CmdMaxSeq = "maxSeq"
CmdPushMsg = "pushMsg"
CmdConnSuccesss = "connSuccess"
CmdWakeUp = "wakeUp"
CmdLogOut = "loginOut"
)
const (
//ContentType
Text = 101
Picture = 102
Sound = 103
Video = 104
File = 105
AtText = 106
Merger = 107
Card = 108
Location = 109
Custom = 110
Typing = 113
Quote = 114
Face = 115
AdvancedText = 117
CustomMsgNotTriggerConversation = 119
CustomMsgOnlineOnly = 120
ReactionMessageModifier = 121
ReactionMessageDeleter = 122
//////////////////////////////////////////
NotificationBegin = 1000
FriendNotificationBegin = 1200
FriendApplicationApprovedNotification = 1201 //add_friend_response
FriendApplicationRejectedNotification = 1202 //add_friend_response
FriendApplicationNotification = 1203 //add_friend
FriendAddedNotification = 1204
FriendDeletedNotification = 1205 //delete_friend
FriendRemarkSetNotification = 1206 //set_friend_remark?
BlackAddedNotification = 1207 //add_black
BlackDeletedNotification = 1208 //remove_black
FriendInfoUpdatedNotification = 1209
FriendsInfoUpdateNotification = 1210
FriendNotificationEnd = 1299
ConversationChangeNotification = 1300
UserNotificationBegin = 1301
UserInfoUpdatedNotification = 1303 //SetSelfInfoTip = 204
UserStatusChangeNotification = 1304
UserCommandAddNotification = 1305
UserCommandDeleteNotification = 1306
UserCommandUpdateNotification = 1307
UserNotificationEnd = 1399
OANotification = 1400
GroupNotificationBegin = 1500
GroupCreatedNotification = 1501
GroupInfoSetNotification = 1502
JoinGroupApplicationNotification = 1503
MemberQuitNotification = 1504
GroupApplicationAcceptedNotification = 1505
GroupApplicationRejectedNotification = 1506
GroupOwnerTransferredNotification = 1507
MemberKickedNotification = 1508
MemberInvitedNotification = 1509
MemberEnterNotification = 1510
GroupDismissedNotification = 1511
GroupMemberMutedNotification = 1512
GroupMemberCancelMutedNotification = 1513
GroupMutedNotification = 1514
GroupCancelMutedNotification = 1515
GroupMemberInfoSetNotification = 1516
GroupMemberSetToAdminNotification = 1517
GroupMemberSetToOrdinaryUserNotification = 1518
GroupInfoSetAnnouncementNotification = 1519
GroupInfoSetNameNotification = 1520
GroupNotificationEnd = 1599
SignalingNotificationBegin = 1600
SignalingNotification = 1601
SignalingNotificationEnd = 1649
SuperGroupNotificationBegin = 1650
SuperGroupUpdateNotification = 1651
MsgDeleteNotification = 1652
ReactionMessageModifierNotification = 1653
ReactionMessageDeleteNotification = 1654
SuperGroupNotificationEnd = 1699
ConversationPrivateChatNotification = 1701
ConversationUnreadNotification = 1702
WorkMomentNotificationBegin = 1900
WorkMomentNotification = 1901
BusinessNotificationBegin = 2000
BusinessNotification = 2001
BusinessNotificationEnd = 2099
RevokeNotification = 2101
HasReadReceiptNotification = 2150
GroupHasReadReceiptNotification = 2155
ClearConversationNotification = 2101
DeleteMsgsNotification = 2102
HasReadReceipt = 2200
NotificationEnd = 5000
////////////////////////////////////////
//MsgFrom
UserMsgType = 100
SysMsgType = 200
/////////////////////////////////////
//SessionType
SingleChatType = 1
GroupChatType = 2
SuperGroupChatType = 3
NotificationChatType = 4
//MsgStatus
MsgStatusDefault = 0
MsgStatusSending = 1
MsgStatusSendSuccess = 2
MsgStatusSendFailed = 3
MsgStatusHasDeleted = 4
MsgStatusFiltered = 5
//OptionsKey
IsHistory = "history"
IsPersistent = "persistent"
IsUnreadCount = "unreadCount"
IsConversationUpdate = "conversationUpdate"
IsOfflinePush = "offlinePush"
IsSenderSync = "senderSync"
IsNotPrivate = "notPrivate"
IsSenderConversationUpdate = "senderConversationUpdate"
//GroupStatus
GroupOk = 0
GroupBanChat = 1
GroupStatusDismissed = 2
GroupStatusMuted = 3
// workMoment permission
WorkMomentPublic = 0
WorkMomentPrivate = 1
WorkMomentPermissionCanSee = 2
WorkMomentPermissionCantSee = 3
// workMoment sdk notification type
WorkMomentCommentNotification = 0
WorkMomentLikeNotification = 1
WorkMomentAtUserNotification = 2
)
const (
ckWsInitConnection string = "ws-init-connection"
ckWsLoginConnection string = "ws-login-connection"
ckWsClose string = "ws-close"
ckWsKickOffLine string = "ws-kick-off-line"
ckTokenExpired string = "token-expired"
ckSelfInfoUpdate string = "self-info-update"
)
const (
BlackRelationship = 0
FriendRelationship = 1
)
// const (
//
// ErrCodeInitLogin = 1001
// ErrCodeFriend = 2001
// ErrCodeConversation = 3001
// ErrCodeUserInfo = 4001
// ErrCodeGroup = 5001
//
// )
const (
NormalGroup = 0
SuperGroup = 1
WorkingGroup = 2
SuperGroupTableName = "local_super_groups"
SuperGroupErrChatLogsTableNamePre = "local_sg_err_chat_logs_"
ChatLogsTableNamePre = "chat_logs_"
)
const (
SdkInit = 0
LoginSuccess = 101
Logining = 102
LoginFailed = 103
Logout = 201
TokenFailedExpired = 701
TokenFailedInvalid = 702
TokenFailedKickedOffline = 703
)
const (
DeFaultSuccessMsg = "ok"
)
const (
AddConOrUpLatMsg = 2
UnreadCountSetZero = 3
IncrUnread = 5
TotalUnreadMessageChanged = 6
UpdateConFaceUrlAndNickName = 7
UpdateLatestMessageChange = 8
ConChange = 9
NewCon = 10
ConChangeDirect = 11
NewConDirect = 12
ConversationLatestMsgHasRead = 13
UpdateMsgFaceUrlAndNickName = 14
SyncConversation = 15
SyncMessageListReactionExtensions = 16
SyncMessageListTypeKeyInfo = 17
UpdateUserCommand = 18
HasRead = 1
NotRead = 0
IsFilter = 1
NotFilter = 0
)
const (
GroupActionCreateGroup = 1
GroupActionApplyJoinGroup = 2
GroupActionQuitGroup = 3
GroupActionSetGroupInfo = 4
GroupActionKickGroupMember = 5
GroupActionTransferGroupOwner = 6
GroupActionInviteUserToGroup = 7
GroupActionAcceptGroupApplication = 8
GroupActionRefuseGroupApplication = 9
)
const ZoomScale = "200"
const MaxTotalMsgLen = 51200
// const MaxTotalMsgLen = 20480
const (
FriendAcceptTip = "You have successfully become friends, so start chatting"
TransferGroupTip = "The owner of the group is transferred!"
AcceptGroupTip = "%s join the group"
)
const (
GetNewestSeq = 1001
PullMsgBySeqList = 1002
SendMsg = 1003
SendSignalMsg = 1004
DelMsg = 1005
PushMsg = 2001
KickOnlineMsg = 2002
LogoutMsg = 2003
SetBackgroundStatus = 2004
WSDataError = 3001
)
// conversation
const (
//MsgReceiveOpt
ReceiveMessage = 0
NotReceiveMessage = 1
ReceiveNotNotifyMessage = 2
Online = 1
Offline = 0
//pinned
Pinned = 1
NotPinned = 0
//privateChat
IsPrivateChat = true
NotPrivateChat = false
)
const SuccessCallbackDefault = "" // Default value for success callback
const (
AppOrdinaryUsers = 1 // Application user type: ordinary user
AppAdmin = 2 // Application user type: administrator
GroupOwner = 100 // Group member type: owner
GroupAdmin = 60 // Group member type: administrator
GroupOrdinaryUsers = 20 // Group member type: ordinary user
GroupFilterAll = 0
GroupFilterOwner = 1
GroupFilterAdmin = 2
GroupFilterOrdinaryUsers = 3
GroupFilterAdminAndOrdinaryUsers = 4
GroupFilterOwnerAndAdmin = 5
GroupResponseAgree = 1 // Response to group application: agree
GroupResponseRefuse = -1 // Response to group application: refuse
FriendResponseAgree = 1 // Response to friend request: agree
FriendResponseRefuse = -1 // Response to friend request: refuse
FriendResponseDefault = 0
Male = 1 // Gender: male
Female = 2 // Gender: female
)
const (
AtAllString = "AtAllTag" // String for 'all people' mention tag
AtNormal = 0 // Mention mode: normal
AtMe = 1 // Mention mode: mention sender only
AtAll = 2 // Mention mode: mention all people
AtAllAtMe = 3 // Mention mode: mention all people and sender
)
const (
FieldRecvMsgOpt = 1 // Field type: message receiving options
FieldIsPinned = 2 // Field type: whether a message is pinned
FieldAttachedInfo = 3 // Field type: attached information
FieldIsPrivateChat = 4 // Field type: whether a message is from a private chat
FieldGroupAtType = 5 // Field type: group mention mode
FieldIsNotInGroup = 6 // Field type: whether a message is not in a group
FieldEx = 7 // Field type: extension field
FieldUnread = 8 // Field type: whether a message is unread
FieldBurnDuration = 9 // Field type: message burn duration
)
const (
SetMessageExtensions = 1 // Message extension operation type: set extension
AddMessageExtensions = 2 // Message extension operation type: add extension
)
const (
KeywordMatchOr = 0 // Keyword match mode: match any keyword
KeywordMatchAnd = 1 // Keyword match mode: match all keywords
)
const BigVersion = "v3"
const UpdateVersion = ".0.0"
const SdkVersion = "openim-sdk-core-"
const LogFileName = "sdk"
func GetSdkVersion() string {
return SdkVersion + BigVersion + UpdateVersion
}
var HeartbeatInterval = 5
const (
MsgSyncModelDefault = 0 //SyncFlag
MsgSyncModelLogin = 1 //SyncFlag
SyncOrderStartLatest = 101 //PullMsgOrder
MsgSyncBegin = 1001 //
MsgSyncProcessing = 1002 //
MsgSyncEnd = 1003 //
MsgSyncFailed = 1004
)
const (
JoinByInvitation = 2
JoinBySearch = 3
JoinByQRCode = 4
)
const (
SplitPullMsgNum = 100
PullMsgNumWhenLogin = 10000
PullMsgNumForReadDiffusion = 50
NormalMsgMinNumReadDiffusion = 100
)
const SplitGetGroupMemberNum = 1000
const UseHashGroupMemberNum = 1000
const (
Uninitialized = -1001
NoNetwork = 1 //有网络->无网络
NetworkAvailable = 2 //无网络->有网络
NetworkVariation = 3 //有网络,但状态有变化
)

View File

@@ -0,0 +1,112 @@
// Copyright © 2023 OpenIM SDK. 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 constant
// key = errCode, string = errMsg
//type ErrInfo struct {
// ErrCode int32
// ErrMsg string
//}
//
//var (
// OK = ErrInfo{0, ""}
//
// ErrParseToken = ErrInfo{200, ParseTokenMsg.Error()}
//
// ErrTencentCredential = ErrInfo{400, ThirdPartyMsg.Error()}
// ErrInBlackList = ErrInfo{ErrCode: 600, ErrMsg: InBlackList.Error()}
// ErrNotFriend = ErrInfo{ErrCode: 601, ErrMsg: NotFriend.Error()}
//
// ErrTokenExpired = ErrInfo{701, TokenExpiredMsg.Error()}
// ErrTokenInvalid = ErrInfo{702, TokenInvalidMsg.Error()}
// ErrTokenMalformed = ErrInfo{703, TokenMalformedMsg.Error()}
// ErrTokenNotValidYet = ErrInfo{704, TokenNotValidYetMsg.Error()}
// ErrTokenUnknown = ErrInfo{705, TokenUnknownMsg.Error()}
// ErrTokenKicked = ErrInfo{706, TokenUserKickedMsg.Error()}
//
// ErrAccess = ErrInfo{ErrCode: 801, ErrMsg: AccessMsg.Error()}
// ErrDB = ErrInfo{ErrCode: 802, ErrMsg: DBMsg.Error()}
// ErrArgs = ErrInfo{ErrCode: 803, ErrMsg: ArgsMsg.Error()}
// ErrApi = ErrInfo{ErrCode: 804, ErrMsg: ApiMsg.Error()}
// ErrData = ErrInfo{ErrCode: 805, ErrMsg: DataMsg.Error()}
// ErrLogin = ErrInfo{ErrCode: 806, ErrMsg: LoginMsg.Error()}
// ErrConfig = ErrInfo{ErrCode: 807, ErrMsg: ConfigMsg.Error()}
// ErrThirdParty = ErrInfo{ErrCode: 808, ErrMsg: ThirdPartyMsg.Error()}
// ErrServerReturn = ErrInfo{ErrCode: 809, ErrMsg: ServerReturn.Error()}
//
// ErrWsRecvConnDiff = ErrInfo{ErrCode: 901, ErrMsg: WsRecvConnDiff.Error()}
// ErrWsRecvConnSame = ErrInfo{ErrCode: 902, ErrMsg: WsRecvConnSame.Error()}
// ErrWsRecvCode = ErrInfo{ErrCode: 903, ErrMsg: WsRecvCode.Error()}
// ErrWsSendTimeout = ErrInfo{ErrCode: 904, ErrMsg: WsSendTimeout.Error()}
// ErrResourceLoadNotComplete = ErrInfo{ErrCode: 905, ErrMsg: ResourceLoadNotComplete.Error()}
// ErrNotSupportFunction = ErrInfo{ErrCode: 906, ErrMsg: NotSupportFunction.Error()}
//)
//
//var (
// ParseTokenMsg = errors.New("parse token failed")
// TokenExpiredMsg = errors.New("token is timed out, please log in again")
// TokenInvalidMsg = errors.New("token has been invalidated")
// TokenNotValidYetMsg = errors.New("token not active yet")
// TokenMalformedMsg = errors.New("that's not even a token")
// TokenUnknownMsg = errors.New("couldn't handle this token")
// TokenUserKickedMsg = errors.New("user has been kicked")
//
// AccessMsg = errors.New("no permission")
// DBMsg = errors.New("db failed")
// ArgsMsg = errors.New("args failed")
// ApiMsg = errors.New("api failed")
// DataMsg = errors.New("data failed ")
// LoginMsg = errors.New("you can only login once")
// ConfigMsg = errors.New("config failed")
//
// ThirdPartyMsg = errors.New("third party error")
// ServerReturn = errors.New("server return data err")
//
// WsRecvConnDiff = errors.New("recv timeout, conn diff")
// WsRecvConnSame = errors.New("recv timeout, conn same")
// WsRecvCode = errors.New("recv code err")
// WsSendTimeout = errors.New("send timeout")
// ResourceLoadNotComplete = errors.New("resource loading is not complete")
// NotSupportFunction = errors.New("unsupported function")
//
// NotFriend = errors.New("not friend")
// InBlackList = errors.New("in blackList")
//)
//
//funcation (e *ErrInfo) Error() string {
// return e.ErrMsg
//}
//
//const (
// StatusErrTokenExpired = 701
// StatusErrTokenInvalid = 702
// StatusErrTokenMalformed = 703
// StatusErrTokenNotValidYet = 704
// StatusErrTokenUnknown = 705
// StatusErrTokenKicked = 706
//)
//
//var statusText = map[int]*ErrInfo{
// StatusErrTokenExpired: &ErrTokenExpired,
// StatusErrTokenInvalid: &ErrTokenInvalid,
// StatusErrTokenMalformed: &ErrTokenMalformed,
// StatusErrTokenNotValidYet: &ErrTokenNotValidYet,
// StatusErrTokenUnknown: &ErrTokenUnknown,
// StatusErrTokenKicked: &ErrTokenKicked,
//}
//
//funcation StatusText(code int) *ErrInfo {
// return statusText[code]
//}

View File

@@ -0,0 +1,90 @@
// Copyright © 2023 OpenIM SDK. 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 constant
// fixme 1<--->IOS 2<--->Android 3<--->Windows
//fixme 4<--->OSX 5<--->Web 6<--->MiniWeb 7<--->Linux
const (
//Platform ID
IOSPlatformID = 1
AndroidPlatformID = 2
WindowsPlatformID = 3
OSXPlatformID = 4
WebPlatformID = 5
MiniWebPlatformID = 6
LinuxPlatformID = 7
AndroidPadPlatformID = 8
IPadPlatformID = 9
AdminPlatformID = 10
//Platform string match to Platform ID
IOSPlatformStr = "IOS"
AndroidPlatformStr = "Android"
WindowsPlatformStr = "Windows"
OSXPlatformStr = "OSX"
WebPlatformStr = "Web"
MiniWebPlatformStr = "MiniWeb"
LinuxPlatformStr = "Linux"
AndroidPadPlatformStr = "APad"
IPadPlatformStr = "IPad"
AdminPlatformStr = "Admin"
//terminal types
TerminalPC = "PC"
TerminalMobile = "Mobile"
)
var PlatformID2Name = map[int]string{
IOSPlatformID: IOSPlatformStr,
AndroidPlatformID: AndroidPlatformStr,
WindowsPlatformID: WindowsPlatformStr,
OSXPlatformID: OSXPlatformStr,
WebPlatformID: WebPlatformStr,
MiniWebPlatformID: MiniWebPlatformStr,
LinuxPlatformID: LinuxPlatformStr,
AndroidPadPlatformID: AndroidPadPlatformStr,
IPadPlatformID: IPadPlatformStr,
}
var PlatformName2ID = map[string]int{
IOSPlatformStr: IOSPlatformID,
AndroidPlatformStr: AndroidPlatformID,
WindowsPlatformStr: WindowsPlatformID,
OSXPlatformStr: OSXPlatformID,
WebPlatformStr: WebPlatformID,
MiniWebPlatformStr: MiniWebPlatformID,
LinuxPlatformStr: LinuxPlatformID,
AndroidPadPlatformStr: AndroidPadPlatformID,
IPadPlatformStr: IPadPlatformID,
}
var Platform2class = map[string]string{
IOSPlatformStr: TerminalMobile,
AndroidPlatformStr: TerminalMobile,
MiniWebPlatformStr: WebPlatformStr,
WebPlatformStr: WebPlatformStr,
WindowsPlatformStr: TerminalPC,
OSXPlatformStr: TerminalPC,
LinuxPlatformStr: TerminalPC,
}
func PlatformIDToName(num int) string {
return PlatformID2Name[num]
}
func PlatformNameToID(name string) int {
return PlatformName2ID[name]
}
func PlatformNameToClass(name string) string {
return Platform2class[name]
}

View File

@@ -0,0 +1,159 @@
// Copyright © 2023 OpenIM SDK. 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 constant
const (
GetSelfUserInfoRouter = "/user/get_self_user_info"
GetUsersInfoRouter = "/user/get_users_info"
UpdateSelfUserInfoRouter = "/user/update_user_info"
UpdateSelfUserInfoExRouter = "/user/update_user_info_ex"
SetGlobalRecvMessageOptRouter = "/user/set_global_msg_recv_opt"
ProcessUserCommandAdd = "/user/process_user_command_add"
ProcessUserCommandDelete = "/user/process_user_command_delete"
ProcessUserCommandUpdate = "/user/process_user_command_update"
ProcessUserCommandGet = "/user/process_user_command_get"
ProcessUserCommandGetAll = "/user/process_user_command_get_all"
GetUsersInfoFromCacheRouter = "/user/get_users_info_from_cache"
AccountCheck = "/user/account_check"
UserRegister = "/user/user_register"
SubscribeUsersStatusRouter = "/user/subscribe_users_status"
GetSubscribeUsersStatusRouter = "/user/get_subscribe_users_status"
GetUserStatusRouter = "/user/get_users_status"
AddFriendRouter = "/friend/add_friend"
DeleteFriendRouter = "/friend/delete_friend"
GetFriendApplicationListRouter = "/friend/get_friend_apply_list" //recv
GetSelfFriendApplicationListRouter = "/friend/get_self_friend_apply_list" //send
ImportFriendListRouter = "/friend/import_friend"
GetDesignatedFriendsApplyRouter = "/friend/get_designated_friend_apply"
GetFriendListRouter = "/friend/get_friend_list"
GetDesignatedFriendsRouter = "/friend/get_designated_friends"
AddFriendResponse = "/friend/add_friend_response"
SetFriendRemark = "/friend/set_friend_remark"
UpdateFriends = "/friend/update_friends"
GetIncrementalFriends = "/friend/get_incremental_friends"
GetFullFriendUserIDs = "/friend/get_full_friend_user_ids"
AddBlackRouter = "/friend/add_black"
RemoveBlackRouter = "/friend/remove_black"
GetBlackListRouter = "/friend/get_black_list"
PullUserMsgRouter = "/chat/pull_msg"
PullUserMsgBySeqRouter = "/chat/pull_msg_by_seq"
NewestSeqRouter = "/chat/newest_seq"
// msg
ClearConversationMsgRouter = RouterMsg + "/clear_conversation_msg" // Clear the message of the specified conversation
ClearAllMsgRouter = RouterMsg + "/user_clear_all_msg" // Clear all messages of the current user
DeleteMsgsRouter = RouterMsg + "/delete_msgs" // Delete the specified message
RevokeMsgRouter = RouterMsg + "/revoke_msg"
SetMessageReactionExtensionsRouter = RouterMsg + "/set_message_reaction_extensions"
AddMessageReactionExtensionsRouter = RouterMsg + "/add_message_reaction_extensions"
MarkMsgsAsReadRouter = RouterMsg + "/mark_msgs_as_read"
GetConversationsHasReadAndMaxSeqRouter = RouterMsg + "/get_conversations_has_read_and_max_seq"
MarkConversationAsRead = RouterMsg + "/mark_conversation_as_read"
MarkMsgsAsRead = RouterMsg + "/mark_msgs_as_read"
SetConversationHasReadSeq = RouterMsg + "/set_conversation_has_read_seq"
SendMsgRouter = RouterMsg + "/send_msg"
GetServerTimeRouter = RouterMsg + "/get_server_time"
GetMessageListReactionExtensionsRouter = RouterMsg + "/get_message_list_reaction_extensions"
DeleteMessageReactionExtensionsRouter = RouterMsg + "/delete_message_reaction_extensions"
TencentCloudStorageCredentialRouter = "/third/tencent_cloud_storage_credential"
AliOSSCredentialRouter = "/third/ali_oss_credential"
MinioStorageCredentialRouter = "/third/minio_storage_credential"
AwsStorageCredentialRouter = "/third/aws_storage_credential"
// group
CreateGroupRouter = RouterGroup + "/create_group"
SetGroupInfoRouter = RouterGroup + "/set_group_info"
JoinGroupRouter = RouterGroup + "/join_group"
QuitGroupRouter = RouterGroup + "/quit_group"
GetGroupsInfoRouter = RouterGroup + "/get_groups_info"
GetGroupMemberListRouter = RouterGroup + "/get_group_member_list"
GetGroupAllMemberListRouter = RouterGroup + "/get_group_all_member_list"
GetGroupMembersInfoRouter = RouterGroup + "/get_group_members_info"
InviteUserToGroupRouter = RouterGroup + "/invite_user_to_group"
GetJoinedGroupListRouter = RouterGroup + "/get_joined_group_list"
KickGroupMemberRouter = RouterGroup + "/kick_group"
TransferGroupRouter = RouterGroup + "/transfer_group"
GetRecvGroupApplicationListRouter = RouterGroup + "/get_recv_group_applicationList"
GetSendGroupApplicationListRouter = RouterGroup + "/get_user_req_group_applicationList"
AcceptGroupApplicationRouter = RouterGroup + "/group_application_response"
RefuseGroupApplicationRouter = RouterGroup + "/group_application_response"
DismissGroupRouter = RouterGroup + "/dismiss_group"
MuteGroupMemberRouter = RouterGroup + "/mute_group_member"
CancelMuteGroupMemberRouter = RouterGroup + "/cancel_mute_group_member"
MuteGroupRouter = RouterGroup + "/mute_group"
CancelMuteGroupRouter = RouterGroup + "/cancel_mute_group"
SetGroupMemberNicknameRouter = RouterGroup + "/set_group_member_nickname"
SetGroupMemberInfoRouter = RouterGroup + "/set_group_member_info"
GetGroupAbstractInfoRouter = RouterGroup + "/get_group_abstract_info"
//SearchGroupMember = RouterGroup + "/search_group_member"
GetIncrementalJoinGroup = RouterGroup + "/get_incremental_join_group"
GetIncrementalGroupMemberBatch = RouterGroup + "/get_incremental_group_member_batch"
GetFullJoinedGroupIDs = RouterGroup + "/get_full_join_group_ids"
GetFullGroupMemberUserIDs = RouterGroup + "/get_full_group_member_user_ids"
SetReceiveMessageOptRouter = "/conversation/set_receive_message_opt"
GetReceiveMessageOptRouter = "/conversation/get_receive_message_opt"
GetAllConversationMessageOptRouter = "/conversation/get_all_conversation_message_opt"
SetConversationOptRouter = ConversationGroup + "/set_conversation"
GetConversationsRouter = ConversationGroup + "/get_conversations"
GetAllConversationsRouter = ConversationGroup + "/get_all_conversations"
GetConversationRouter = ConversationGroup + "/get_conversation"
BatchSetConversationRouter = ConversationGroup + "/batch_set_conversation"
ModifyConversationFieldRouter = ConversationGroup + "/modify_conversation_field"
SetConversationsRouter = ConversationGroup + "/set_conversations"
// organization
GetSubDepartmentRouter = RouterOrganization + "/get_sub_department"
GetDepartmentMemberRouter = RouterOrganization + "/get_department_member"
ParseTokenRouter = RouterAuth + "/parse_token"
// super_group
GetJoinedSuperGroupListRouter = RouterSuperGroup + "/get_joined_group_list"
GetSuperGroupsInfoRouter = RouterSuperGroup + "/get_groups_info"
// third
FcmUpdateTokenRouter = RouterThird + "/fcm_update_token"
SetAppBadgeRouter = RouterThird + "/set_app_badge"
UploadLogsRouter = RouterThird + "/logs/upload"
// auth
GetUsersToken = RouterAuth + "/user_token"
)
const (
RouterGroup = "/group"
ConversationGroup = "/conversation"
RouterOrganization = "/organization"
RouterAuth = "/auth"
RouterSuperGroup = "/super_group"
RouterMsg = "/msg"
RouterThird = "/third"
)
const (
ObjectPartLimit = "/object/part_limit"
ObjectPartSize = "/object/part_size"
ObjectInitiateMultipartUpload = "/object/initiate_multipart_upload"
ObjectAuthSign = "/object/auth_sign"
ObjectCompleteMultipartUpload = "/object/complete_multipart_upload"
ObjectAccessURL = "/object/access_url"
)

View File

@@ -0,0 +1,62 @@
// Copyright © 2023 OpenIM SDK. 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 constant
//
//var (
// ErrServer = ErrInfo{500, "server error"}
//
// ErrTokenDifferentPlatformID = ErrInfo{707, TokenDifferentPlatformIDMsg.Error()}
// ErrTokenDifferentUserID = ErrInfo{708, TokenDifferentUserIDMsg.Error()}
//
// ErrStatus = ErrInfo{ErrCode: 804, ErrMsg: StatusMsg.Error()}
// ErrCallback = ErrInfo{ErrCode: 809, ErrMsg: CallBackMsg.Error()}
// ErrSendLimit = ErrInfo{ErrCode: 810, ErrMsg: "send msg limit, to many request, try again later"}
// ErrMessageHasReadDisable = ErrInfo{ErrCode: 811, ErrMsg: "message has read disable"}
// ErrInternal = ErrInfo{ErrCode: 812, ErrMsg: "internal error"}
//)
//
//var (
// TokenDifferentPlatformIDMsg = errors.New("different platformID")
// TokenDifferentUserIDMsg = errors.New("different userID")
//
// StatusMsg = errors.New("status is abnormal")
//
// CallBackMsg = errors.New("callback failed")
//)
//
//const (
// NoError = 0
// FormattingError = 10001
// HasRegistered = 10002
// NotRegistered = 10003
// PasswordErr = 10004
// GetIMTokenErr = 10005
// RepeatSendCode = 10006
// MailSendCodeErr = 10007
// SmsSendCodeErr = 10008
// CodeInvalidOrExpired = 10009
// RegisterFailed = 10010
// ResetPasswordFailed = 10011
// DatabaseError = 10002
// ServerError = 10004
// HttpError = 10005
// IoError = 10006
// IntentionalError = 10007
//)
//
//funcation (e *ErrInfo) Code() int32 {
// return e.ErrCode
//}

View File

@@ -0,0 +1,93 @@
package content_type
import (
"strings"
)
var ext = map[string]string{
"html": "text/html",
"htm": "text/html",
"css": "text/css",
"js": "application/javascript",
"json": "application/json",
"xml": "application/xml",
"png": "image/png",
"jpg": "image/jpeg",
"jpeg": "image/jpeg",
"gif": "image/gif",
"bmp": "image/bmp",
"tif": "image/tiff",
"tiff": "image/tiff",
"ico": "image/x-icon",
"svg": "image/svg+xml",
"webp": "image/webp",
"mp4": "video/mp4",
"avi": "video/x-msvideo",
"mkv": "video/x-matroska",
"mov": "video/quicktime",
"wmv": "video/x-ms-wmv",
"flv": "video/x-flv",
"webm": "video/webm",
"3gp": "video/3gpp",
"mp3": "audio/mpeg",
"wav": "audio/wav",
"ogg": "audio/ogg",
"aac": "audio/aac",
"wma": "audio/x-ms-wma",
"flac": "audio/flac",
"mid": "audio/midi",
"midi": "audio/midi",
"weba": "audio/webm",
"pdf": "application/pdf",
"doc": "application/msword",
"docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"xls": "application/vnd.ms-excel",
"xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"ppt": "application/vnd.ms-powerpoint",
"pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
"txt": "text/plain",
"csv": "text/csv",
"zip": "application/zip",
"rar": "application/x-rar-compressed",
"tar": "application/x-tar",
"gz": "application/gzip",
"exe": "application/x-msdownload",
"msi": "application/x-msi",
"deb": "application/x-debian-package",
"rpm": "application/x-redhat-package-manager",
"sh": "application/x-sh",
"bat": "application/bat",
"py": "application/x-python",
"java": "text/x-java-source",
"c": "text/x-csrc",
"cpp": "text/x-c++src",
"h": "text/x-chdr",
"hpp": "text/x-c++hdr",
"php": "application/x-php",
"asp": "application/x-asp",
"jsp": "application/x-jsp",
"dll": "application/x-msdownload",
"jar": "application/java-archive",
"war": "application/java-archive",
"ear": "application/java-archive",
}
func GetType(val ...string) string {
for _, s := range val {
if len(s) > 1 {
if i := strings.IndexByte(s, '/'); i > 0 && i < len(s)-1 {
return s
}
if strings.HasPrefix(s, ".") {
s = s[1:]
}
if val, ok := ext[s]; ok {
return val
}
if val, ok := ext[strings.ToLower(s)]; ok {
return val
}
}
}
return ""
}

View File

@@ -0,0 +1,98 @@
package datafetcher
import (
"context"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/db_interface"
"github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/utils/datautil"
)
// DataFetcher is a struct that handles data synchronization
type DataFetcher[T any] struct {
db db_interface.VersionSyncModel
TableName string
EntityID string
Key func(T) string
batchInsert func(ctx context.Context, servers []T) error
FetchFromLocal FetchDataFunc[T]
fetchFromServer FetchFromServerFunc[T]
}
// FetchDataFunc is a function type for fetching data
type FetchDataFunc[T any] func(ctx context.Context, uids []string) ([]T, error)
// FetchFromServerFunc is a function type for fetching data from server
type FetchFromServerFunc[T any] func(ctx context.Context, uids []string) ([]T, error)
// NewDataFetcher creates a new NewDataFetcher
func NewDataFetcher[T any](db db_interface.VersionSyncModel, tableName string, entityID string, key func(T) string,
batchInsert func(ctx context.Context, servers []T) error, fetchFromLocal FetchDataFunc[T], fetchFromServer FetchFromServerFunc[T]) *DataFetcher[T] {
return &DataFetcher[T]{
db: db,
TableName: tableName,
EntityID: entityID,
Key: key,
batchInsert: batchInsert,
FetchFromLocal: fetchFromLocal,
fetchFromServer: fetchFromServer,
}
}
// FetchWithPagination fetches data with pagination and fills missing data from server
func (ds *DataFetcher[T]) FetchWithPagination(ctx context.Context, offset, limit int) ([]T, error) {
versionInfo, err := ds.db.GetVersionSync(ctx, ds.TableName, ds.EntityID)
if err != nil {
return nil, err
}
if offset > len(versionInfo.UIDList) {
return nil, errs.New("offset exceeds the length of the UID list").Wrap()
}
end := offset + limit
if end > len(versionInfo.UIDList) {
end = len(versionInfo.UIDList)
}
paginatedUIDs := versionInfo.UIDList[offset:end]
localData, err := ds.FetchMissingAndFillLocal(ctx, paginatedUIDs)
if err != nil {
return nil, err
}
return localData, nil
}
// FetchMissingAndFillLocal fetches missing data from server and fills local database
func (ds *DataFetcher[T]) FetchMissingAndFillLocal(ctx context.Context, uids []string) ([]T, error) {
localData, err := ds.FetchFromLocal(ctx, uids)
if err != nil {
return nil, err
}
localUIDSet := datautil.SliceSetAny(localData, ds.Key)
var missingUIDs []string
for _, uid := range uids {
if _, found := localUIDSet[uid]; !found {
missingUIDs = append(missingUIDs, uid)
}
}
if len(missingUIDs) > 0 {
serverData, err := ds.fetchFromServer(ctx, missingUIDs)
if err != nil {
return nil, err
}
if err := ds.batchInsert(ctx, serverData); err != nil {
return nil, err
}
localData = append(localData, serverData...)
}
return localData, nil
}

View File

@@ -0,0 +1,59 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/tools/errs"
)
func (d *DataBase) InsertAdminGroupRequest(ctx context.Context, groupRequest *model_struct.LocalAdminGroupRequest) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Create(groupRequest).Error, "InsertAdminGroupRequest failed")
}
func (d *DataBase) DeleteAdminGroupRequest(ctx context.Context, groupID, userID string) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Where("group_id=? and user_id=?", groupID, userID).Delete(&model_struct.LocalAdminGroupRequest{}).Error, "DeleteAdminGroupRequest failed")
}
func (d *DataBase) UpdateAdminGroupRequest(ctx context.Context, groupRequest *model_struct.LocalAdminGroupRequest) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
t := d.conn.WithContext(ctx).Model(groupRequest).Select("*").Updates(*groupRequest)
if t.RowsAffected == 0 {
return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update")
}
return errs.Wrap(t.Error)
}
func (d *DataBase) GetAdminGroupApplication(ctx context.Context) ([]*model_struct.LocalAdminGroupRequest, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupRequestList []*model_struct.LocalAdminGroupRequest
err := errs.Wrap(d.conn.WithContext(ctx).Order("create_time DESC").Find(&groupRequestList).Error)
if err != nil {
return nil, errs.Wrap(err)
}
return groupRequestList, nil
}

View File

@@ -0,0 +1,34 @@
package db
import (
"context"
"github.com/openimsdk/tools/errs"
"gorm.io/gorm"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
)
func (d *DataBase) GetAppSDKVersion(ctx context.Context) (*model_struct.LocalAppSDKVersion, error) {
var appVersion model_struct.LocalAppSDKVersion
return &appVersion, errs.Wrap(d.conn.WithContext(ctx).Take(&appVersion).Error)
}
func (d *DataBase) SetAppSDKVersion(ctx context.Context, appVersion *model_struct.LocalAppSDKVersion) error {
var exist model_struct.LocalAppSDKVersion
err := d.conn.WithContext(ctx).First(&exist).Error
if err == gorm.ErrRecordNotFound {
if createErr := d.conn.WithContext(ctx).Create(appVersion).Error; createErr != nil {
return errs.Wrap(createErr)
}
return nil
} else if err != nil {
return errs.Wrap(err)
}
if updateErr := d.conn.WithContext(ctx).Model(&exist).Updates(appVersion).Error; updateErr != nil {
return errs.Wrap(updateErr)
}
return nil
}

View File

@@ -0,0 +1,79 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/tools/errs"
)
func (d *DataBase) GetBlackListDB(ctx context.Context) ([]*model_struct.LocalBlack, error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
var blackList []*model_struct.LocalBlack
return blackList, errs.Wrap(d.conn.WithContext(ctx).Find(&blackList).Error)
}
func (d *DataBase) GetBlackListUserID(ctx context.Context) (blackListUid []string, err error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
return blackListUid, errs.WrapMsg(d.conn.WithContext(ctx).Model(&model_struct.LocalBlack{}).Select("block_user_id").Find(&blackListUid).Error, "GetBlackList failed")
}
func (d *DataBase) GetBlackInfoByBlockUserID(ctx context.Context, blockUserID string) (*model_struct.LocalBlack, error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
var black model_struct.LocalBlack
return &black, errs.WrapMsg(d.conn.WithContext(ctx).Where("owner_user_id = ? AND block_user_id = ? ",
d.loginUserID, blockUserID).Take(&black).Error, "GetBlackInfoByBlockUserID failed")
}
func (d *DataBase) GetBlackInfoList(ctx context.Context, blockUserIDList []string) ([]*model_struct.LocalBlack, error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
var blackList []*model_struct.LocalBlack
if err := d.conn.WithContext(ctx).Where("block_user_id IN ? ", blockUserIDList).Find(&blackList).Error; err != nil {
return nil, errs.WrapMsg(err, "GetBlackInfoList failed")
}
return blackList, nil
}
func (d *DataBase) InsertBlack(ctx context.Context, black *model_struct.LocalBlack) error {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Create(black).Error, "InsertBlack failed")
}
func (d *DataBase) UpdateBlack(ctx context.Context, black *model_struct.LocalBlack) error {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
t := d.conn.WithContext(ctx).Updates(black)
if t.RowsAffected == 0 {
return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update")
}
return errs.WrapMsg(t.Error, "UpdateBlack failed")
}
func (d *DataBase) DeleteBlack(ctx context.Context, blockUserID string) error {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Where("owner_user_id=? and block_user_id=?", d.loginUserID, blockUserID).Delete(&model_struct.LocalBlack{}).Error, "DeleteBlack failed")
}

View File

@@ -0,0 +1,565 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"github.com/openimsdk/openim-sdk-core/v3/sdk_struct"
"gorm.io/gorm"
)
// funcation (d *DataBase) BatchInsertMessageList(ctx context.Context, MessageList []*model_struct.LocalChatLog) error {
// if MessageList == nil {
// return nil
// }
// d.mRWMutex.Lock()
// defer d.mRWMutex.Unlock()
// return utils.Wrap(d.conn.WithContext(ctx).Create(MessageList).Error, "BatchInsertMessageList failed")
// }
//funcation (d *DataBase) BatchInsertMessageListController(ctx context.Context, MessageList []*model_struct.LocalChatLog) error {
// if len(MessageList) == 0 {
// return nil
// }
// switch MessageList[len(MessageList)-1].SessionType {
// case constant.SuperGroupChatType:
// return d.SuperGroupBatchInsertMessageList(ctx, MessageList, MessageList[len(MessageList)-1].RecvID)
// default:
// return d.BatchInsertMessageList(ctx, MessageList)
// }
//}
// funcation (d *DataBase) InsertMessage(ctx context.Context, Message *model_struct.LocalChatLog) error {
// d.mRWMutex.Lock()
// defer d.mRWMutex.Unlock()
// return utils.Wrap(d.conn.WithContext(ctx).Create(Message).Error, "InsertMessage failed")
// }
//
// funcation (d *DataBase) InsertMessageController(ctx context.Context, message *model_struct.LocalChatLog) error {
// switch message.SessionType {
// case constant.SuperGroupChatType:
// return d.SuperGroupInsertMessage(ctx, message, message.RecvID)
// default:
// return d.InsertMessage(ctx, message)
// }
// }
//funcation (d *DataBase) SearchMessageByKeyword(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error) {
// var messageList []model_struct.LocalChatLog
// var condition string
// var subCondition string
// if keywordListMatchType == constant.KeywordMatchOr {
// for i := 0; i < len(keywordList); i++ {
// if i == 0 {
// subCondition += "And ("
// }
// if i+1 >= len(keywordList) {
// subCondition += "content like " + "'%" + keywordList[i] + "%') "
// } else {
// subCondition += "content like " + "'%" + keywordList[i] + "%' " + "or "
//
// }
// }
// } else {
// for i := 0; i < len(keywordList); i++ {
// if i == 0 {
// subCondition += "And ("
// }
// if i+1 >= len(keywordList) {
// subCondition += "content like " + "'%" + keywordList[i] + "%') "
// } else {
// subCondition += "content like " + "'%" + keywordList[i] + "%' " + "and "
// }
// }
// }
// switch sessionType {
// case constant.SingleChatType, constant.NotificationChatType:
// condition = fmt.Sprintf("session_type==%d And (send_id==%q OR recv_id==%q) And send_time between %d and %d AND status <=%d And content_type IN ? ", constant.SingleChatType, sourceID, sourceID, startTime, endTime, constant.MsgStatusSendFailed)
// case constant.GroupChatType:
// condition = fmt.Sprintf("session_type==%d And recv_id==%q And send_time between %d and %d AND status <=%d And content_type IN ? ", constant.GroupChatType, sourceID, startTime, endTime, constant.MsgStatusSendFailed)
// default:
// //condition = fmt.Sprintf("(send_id==%q OR recv_id==%q) And send_time between %d and %d AND status <=%d And content_type == %d And content like %q", sourceID, sourceID, startTime, endTime, constant.MsgStatusSendFailed, constant.Text, "%"+keyword+"%")
// return nil, err
// }
// condition += subCondition
// err = utils.Wrap(d.conn.WithContext(ctx).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&messageList).Error, "InsertMessage failed")
//
// for _, v := range messageList {
// v1 := v
// result = append(result, &v1)
// }
// return result, err
//}
//funcation (d *DataBase) SearchMessageByKeywordController(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error) {
// switch sessionType {
// case constant.SuperGroupChatType:
// return d.SuperGroupSearchMessageByKeyword(ctx, contentType, keywordList, keywordListMatchType, sourceID, startTime, endTime, sessionType, offset, count)
// default:
// return d.SearchMessageByKeyword(ctx, contentType, keywordList, keywordListMatchType, sourceID, startTime, endTime, sessionType, offset, count)
// }
//}
//funcation (d *DataBase) SearchMessageByContentType(ctx context.Context, contentType []int,conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error) {
// var messageList []model_struct.LocalChatLog
// var condition string
// switch sessionType {
// case constant.SingleChatType, constant.NotificationChatType:
// condition = fmt.Sprintf("session_type==%d And (send_id==%q OR recv_id==%q) And send_time between %d and %d AND status <=%d And content_type IN ?", constant.SingleChatType, sourceID, sourceID, startTime, endTime, constant.MsgStatusSendFailed)
// case constant.GroupChatType:
// condition = fmt.Sprintf("session_type==%d And recv_id==%q And send_time between %d and %d AND status <=%d And content_type IN ?", constant.GroupChatType, sourceID, startTime, endTime, constant.MsgStatusSendFailed)
// default:
// return nil, err
// }
// err = utils.Wrap(d.conn.WithContext(ctx).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&messageList).Error, "SearchMessage failed")
// for _, v := range messageList {
// v1 := v
// result = append(result, &v1)
// }
// return result, err
//}
//funcation (d *DataBase) SearchMessageByContentTypeController(ctx context.Context, contentType []int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error) {
// switch sessionType {
// case constant.SuperGroupChatType:
// return d.SuperGroupSearchMessageByContentType(ctx, contentType, sourceID, startTime, endTime, sessionType, offset, count)
// default:
// return d.SearchMessageByContentType(ctx, contentType, conversationID, startTime, endTime, offset, count)
// }
//}
//funcation (d *DataBase) SearchMessageByContentTypeAndKeyword(ctx context.Context, contentType []int, conversationID string,keywordList []string, keywordListMatchType int, startTime, endTime int64) (result []*model_struct.LocalChatLog, err error) {
// var messageList []model_struct.LocalChatLog
// var condition string
// var subCondition string
// if keywordListMatchType == constant.KeywordMatchOr {
// for i := 0; i < len(keywordList); i++ {
// if i == 0 {
// subCondition += "And ("
// }
// if i+1 >= len(keywordList) {
// subCondition += "content like " + "'%" + keywordList[i] + "%') "
// } else {
// subCondition += "content like " + "'%" + keywordList[i] + "%' " + "or "
//
// }
// }
// } else {
// for i := 0; i < len(keywordList); i++ {
// if i == 0 {
// subCondition += "And ("
// }
// if i+1 >= len(keywordList) {
// subCondition += "content like " + "'%" + keywordList[i] + "%') "
// } else {
// subCondition += "content like " + "'%" + keywordList[i] + "%' " + "and "
// }
// }
// }
// condition = fmt.Sprintf("send_time between %d and %d AND status <=%d And content_type IN ? ", startTime, endTime, constant.MsgStatusSendFailed)
// condition += subCondition
// log.Info("key owrd", condition)
// err = utils.Wrap(d.conn.WithContext(ctx).Where(condition, contentType).Order("send_time DESC").Find(&messageList).Error, "SearchMessage failed")
// for _, v := range messageList {
// v1 := v
// result = append(result, &v1)
// }
// return result, err
//}
//funcation (d *DataBase) BatchUpdateMessageList(ctx context.Context, MessageList []*model_struct.LocalChatLog) error {
// if MessageList == nil {
// return nil
// }
//
// for _, v := range MessageList {
// v1 := new(model_struct.LocalChatLog)
// v1.ClientMsgID = v.ClientMsgID
// v1.Seq = v.Seq
// v1.Status = v.Status
// v1.RecvID = v.RecvID
// v1.SessionType = v.SessionType
// v1.ServerMsgID = v.ServerMsgID
// err := d.UpdateMessageController(ctx, v1)
// if err != nil {
// return utils.Wrap(err, "BatchUpdateMessageList failed")
// }
//
// }
// return nil
//}
//funcation (d *DataBase) BatchSpecialUpdateMessageList(ctx context.Context, MessageList []*model_struct.LocalChatLog) error {
// if MessageList == nil {
// return nil
// }
//
// for _, v := range MessageList {
// v1 := new(model_struct.LocalChatLog)
// v1.ClientMsgID = v.ClientMsgID
// v1.ServerMsgID = v.ServerMsgID
// v1.SendID = v.SendID
// v1.RecvID = v.RecvID
// v1.SenderPlatformID = v.SenderPlatformID
// v1.SenderNickname = v.SenderNickname
// v1.SenderFaceURL = v.SenderFaceURL
// v1.SessionType = v.SessionType
// v1.MsgFrom = v.MsgFrom
// v1.ContentType = v.ContentType
// v1.Content = v.Content
// v1.Seq = v.Seq
// v1.SendTime = v.SendTime
// v1.CreateTime = v.CreateTime
// v1.AttachedInfo = v.AttachedInfo
// v1.Ex = v.Ex
// err := d.UpdateMessageController(ctx, v1)
// if err != nil {
// log.Error("", "update single message failed", *v)
// return utils.Wrap(err, "BatchUpdateMessageList failed")
// }
//
// }
// return nil
//}
func (d *DataBase) MessageIfExists(ctx context.Context, ClientMsgID string) (bool, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var count int64
t := d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Where("client_msg_id = ?",
ClientMsgID).Count(&count)
if t.Error != nil {
return false, utils.Wrap(t.Error, "MessageIfExists get failed")
}
if count != 1 {
return false, nil
} else {
return true, nil
}
}
func (d *DataBase) IsExistsInErrChatLogBySeq(ctx context.Context, seq int64) bool {
return true
}
func (d *DataBase) MessageIfExistsBySeq(ctx context.Context, seq int64) (bool, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var count int64
t := d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Where("seq = ?",
seq).Count(&count)
if t.Error != nil {
return false, utils.Wrap(t.Error, "MessageIfExistsBySeq get failed")
}
if count != 1 {
return false, nil
} else {
return true, nil
}
}
// funcation (d *DataBase) GetMessage(ctx context.Context, ClientMsgID string) (*model_struct.LocalChatLog, error) {
// var c model_struct.LocalChatLog
// return &c, utils.Wrap(d.conn.WithContext(ctx).Where("client_msg_id = ?",
// ClientMsgID).Take(&c).Error, "GetMessage failed")
// }
//funcation (d *DataBase) GetMessageController(ctx context.Context, msg *sdk_struct.MsgStruct) (*model_struct.LocalChatLog, error) {
// switch msg.SessionType {
// case constant.SuperGroupChatType:
// return d.SuperGroupGetMessage(ctx, msg)
// default:
// return d.GetMessage(ctx, msg.ClientMsgID)
// }
//}
func (d *DataBase) GetAllUnDeleteMessageSeqList(ctx context.Context) ([]uint32, error) {
var seqList []uint32
return seqList, utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Where("status != ?", constant.MsgStatusHasDeleted).Select("seq").Find(&seqList).Error, "")
}
func (d *DataBase) UpdateColumnsMessageList(ctx context.Context, clientMsgIDList []string, args map[string]interface{}) error {
c := model_struct.LocalChatLog{}
t := d.conn.WithContext(ctx).Model(&c).Where("client_msg_id IN", clientMsgIDList).Updates(args)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "UpdateColumnsConversation failed")
}
//funcation (d *DataBase) UpdateColumnsMessageController(ctx context.Context, ClientMsgID string, groupID string, sessionType int32, args map[string]interface{}) error {
// switch sessionType {
// case constant.SuperGroupChatType:
// return utils.Wrap(d.SuperGroupUpdateColumnsMessage(ctx, ClientMsgID, groupID, args), "")
// default:
// return utils.Wrap(d.UpdateColumnsMessage(ctx, ClientMsgID, args), "")
// }
//}
// funcation (d *DataBase) UpdateMessage(ctx context.Context, c *model_struct.LocalChatLog) error {
// t := d.conn.WithContext(ctx).Updates(c)
// if t.RowsAffected == 0 {
// return utils.Wrap(errors.New("RowsAffected == 0"), "no update ")
// }
// return utils.Wrap(t.Error, "UpdateMessage failed")
// }
//funcation (d *DataBase) UpdateMessageController(ctx context.Context, c *model_struct.LocalChatLog) error {
// switch c.SessionType {
// case constant.SuperGroupChatType:
// return utils.Wrap(d.SuperGroupUpdateMessage(ctx, c), "")
// default:
// return utils.Wrap(d.UpdateMessage(ctx, c), "")
// }
//}
func (d *DataBase) DeleteAllMessage(ctx context.Context) error {
m := model_struct.LocalChatLog{Status: constant.MsgStatusHasDeleted, Content: ""}
err := d.conn.WithContext(ctx).Session(&gorm.Session{AllowGlobalUpdate: true}).Select("status", "content").Updates(m).Error
return utils.Wrap(err, "delete all message error")
}
func (d *DataBase) UpdateMessageStatusBySourceID(ctx context.Context, sourceID string, status, sessionType int32) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var condition string
if sourceID == d.loginUserID && sessionType == constant.SingleChatType {
condition = "send_id=? And recv_id=? AND session_type=?"
} else {
condition = "(send_id=? or recv_id=?)AND session_type=?"
}
t := d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where(condition, sourceID, sourceID, sessionType).Updates(model_struct.LocalChatLog{Status: status})
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "UpdateMessageStatusBySourceID failed")
}
func (d *DataBase) UpdateMessageStatusBySourceIDController(ctx context.Context, sourceID string, status, sessionType int32) error {
switch sessionType {
case constant.SuperGroupChatType:
return d.SuperGroupUpdateMessageStatusBySourceID(ctx, sourceID, status, sessionType)
default:
return d.UpdateMessageStatusBySourceID(ctx, sourceID, status, sessionType)
}
}
// funcation (d *DataBase) UpdateMessageTimeAndStatus(ctx context.Context, clientMsgID string, serverMsgID string, sendTime int64, status int32) error {
// d.mRWMutex.Lock()
// defer d.mRWMutex.Unlock()
// return utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where("client_msg_id=? And seq=?", clientMsgID, 0).
// Updates(model_struct.LocalChatLog{Status: status, SendTime: sendTime, ServerMsgID: serverMsgID}).Error, "UpdateMessageStatusBySourceID failed")
//
// }
//funcation (d *DataBase) UpdateMessageTimeAndStatusController(ctx context.Context, msg *sdk_struct.MsgStruct) error {
// switch msg.SessionType {
// case constant.SuperGroupChatType:
// return d.SuperGroupUpdateMessageTimeAndStatus(ctx, msg)
// default:
// return d.UpdateMessageTimeAndStatus(ctx, msg.ClientMsgID, msg.ServerMsgID, msg.SendTime, msg.Status)
// }
//}
//funcation (d *DataBase) UpdateMessageAttachedInfo(ctx context.Context, msg *sdk_struct.MsgStruct) error {
// info, err := json.Marshal(msg.AttachedInfoElem)
// if err != nil {
// return err
// }
// d.mRWMutex.Lock()
// defer d.mRWMutex.Unlock()
// switch msg.SessionType {
// case constant.SuperGroupChatType:
// t := d.conn.WithContext(ctx).Table(utils.GetSuperGroupTableName(msg.GroupID)).Where("client_msg_id=?", msg.ClientMsgID).Updates(map[string]any{"attached_info": string(info)})
// if t.RowsAffected == 0 {
// return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
// }
// return utils.Wrap(t.Error, "SuperGroupUpdateMessageTimeAndStatus failed")
// default:
// return utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where("client_msg_id=?", msg.ClientMsgID).Updates(map[string]any{"attached_info": string(info)}).Error, "")
// }
//}
// group ,index_recv_id and index_send_time only one can be used,when index_recv_id be used,temp B tree use for order by,Query speed decrease
//funcation (d *DataBase) GetMessageList(ctx context.Context, sourceID string, sessionType, count int, startTime int64, isReverse bool) (result []*model_struct.LocalChatLog, err error) {
// d.mRWMutex.Lock()
// defer d.mRWMutex.Unlock()
// var messageList []model_struct.LocalChatLog
// var condition, timeOrder, timeSymbol string
// if isReverse {
// timeOrder = "send_time ASC"
// timeSymbol = ">"
// } else {
// timeOrder = "send_time DESC"
// timeSymbol = "<"
// }
// if sessionType == constant.SingleChatType && sourceID == d.loginUserID {
// condition = "send_id = ? And recv_id = ? AND status <=? And session_type = ? And send_time " + timeSymbol + " ?"
// } else {
// condition = "(send_id = ? OR recv_id = ?) AND status <=? And session_type = ? And send_time " + timeSymbol + " ?"
// }
// err = utils.Wrap(d.conn.WithContext(ctx).Where(condition, sourceID, sourceID, constant.MsgStatusSendFailed, sessionType, startTime).
// Order(timeOrder).Offset(0).Limit(count).Find(&messageList).Error, "GetMessageList failed")
// for _, v := range messageList {
// v1 := v
// result = append(result, &v1)
// }
// return result, err
//}
func (d *DataBase) GetAllMessageForTest(ctx context.Context) (result []*model_struct.LocalChatLog, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var messageList []model_struct.LocalChatLog
err = utils.Wrap(d.conn.WithContext(ctx).Find(&messageList).Error, "GetMessageList failed")
for _, v := range messageList {
v1 := v
result = append(result, &v1)
}
return result, err
}
//funcation (d *DataBase) GetMessageListController(ctx context.Context, sourceID string, sessionType, count int, startTime int64, isReverse bool) (result []*model_struct.LocalChatLog, err error) {
// switch sessionType {
// case constant.SuperGroupChatType:
// return d.SuperGroupGetMessageList(ctx, sourceID, sessionType, count, startTime, isReverse)
// default:
// return d.GetMessageList(ctx, sourceID, sessionType, count, startTime, isReverse)
// }
//}
//funcation (d *DataBase) GetMessageListNoTime(ctx context.Context, sourceID string, sessionType, count int, isReverse bool) (result []*model_struct.LocalChatLog, err error) {
// d.mRWMutex.Lock()
// defer d.mRWMutex.Unlock()
// var messageList []model_struct.LocalChatLog
// var condition, timeOrder string
// if isReverse {
// timeOrder = "send_time ASC"
// } else {
// timeOrder = "send_time DESC"
// }
// switch sessionType {
// case constant.SingleChatType:
// if sourceID == d.loginUserID {
// condition = "send_id = ? And recv_id = ? AND status <=? And session_type = ?"
// } else {
// condition = "(send_id = ? OR recv_id = ?) AND status <=? And session_type = ? "
// }
// err = utils.Wrap(d.conn.WithContext(ctx).Where(condition, sourceID, sourceID, constant.MsgStatusSendFailed, sessionType).
// Order(timeOrder).Offset(0).Limit(count).Find(&messageList).Error, "GetMessageList failed")
// case constant.GroupChatType:
// condition = " recv_id = ? AND status <=? And session_type = ? "
// err = utils.Wrap(d.conn.WithContext(ctx).Where(condition, sourceID, constant.MsgStatusSendFailed, sessionType).
// Order(timeOrder).Offset(0).Limit(count).Find(&messageList).Error, "GetMessageList failed")
// default:
// condition = "(send_id = ? OR recv_id = ?) AND status <=? And session_type = ? "
// err = utils.Wrap(d.conn.WithContext(ctx).Where(condition, sourceID, sourceID, constant.MsgStatusSendFailed, sessionType).
// Order(timeOrder).Offset(0).Limit(count).Find(&messageList).Error, "GetMessageList failed")
// }
//
// for _, v := range messageList {
// v1 := v
// result = append(result, &v1)
// }
// return result, err
//}
//funcation (d *DataBase) GetMessageListNoTimeController(ctx context.Context, sourceID string, sessionType, count int, isReverse bool) (result []*model_struct.LocalChatLog, err error) {
// switch sessionType {
// case constant.SuperGroupChatType:
// return d.SuperGroupGetMessageListNoTime(ctx, sourceID, sessionType, count, isReverse)
// default:
// return d.GetMessageListNoTime(ctx, sourceID, sessionType, count, isReverse)
// }
//}
func (d *DataBase) GetTestMessage(ctx context.Context, seq uint32) (*model_struct.LocalChatLog, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var c model_struct.LocalChatLog
return &c, utils.Wrap(d.conn.WithContext(ctx).Where("seq = ?",
seq).Find(&c).Error, "GetTestMessage failed")
}
func (d *DataBase) UpdateMsgSenderNickname(ctx context.Context, sendID, nickname string, sType int) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where(
"send_id = ? and session_type = ? and sender_nick_name != ? ", sendID, sType, nickname).Updates(
map[string]interface{}{"sender_nick_name": nickname}).Error, utils.GetSelfFuncName()+" failed")
}
func (d *DataBase) UpdateMsgSenderFaceURL(ctx context.Context, sendID, faceURL string, sType int) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where(
"send_id = ? and session_type = ? and sender_face_url != ? ", sendID, sType, faceURL).Updates(
map[string]interface{}{"sender_face_url": faceURL}).Error, utils.GetSelfFuncName()+" failed")
}
//funcation (d *DataBase) UpdateMsgSenderFaceURLAndSenderNicknameController(ctx context.Context, sendID, faceURL, nickname string, sessionType int, groupID string) error {
// switch sessionType {
// case constant.SuperGroupChatType:
// return d.SuperGroupUpdateMsgSenderFaceURLAndSenderNickname(ctx, sendID, faceURL, nickname, sessionType, groupID)
// default:
// return d.UpdateMsgSenderFaceURLAndSenderNickname(ctx, sendID, faceURL, nickname, sessionType)
// }
//}
//funcation (d *DataBase) UpdateMsgSenderFaceURLAndSenderNickname(ctx context.Context, sendID, faceURL, nickname string, sessionType int) error {
// d.mRWMutex.Lock()
// defer d.mRWMutex.Unlock()
// return utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where(
// "send_id = ? and session_type = ?", sendID, sessionType).Updates(
// map[string]interface{}{"sender_face_url": faceURL, "sender_nick_name": nickname}).Error, utils.GetSelfFuncName()+" failed")
//}
func (d *DataBase) GetMsgSeqByClientMsgID(ctx context.Context, clientMsgID string) (uint32, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var seq uint32
err := utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("client_msg_id=?", clientMsgID).First(&seq).Error, utils.GetSelfFuncName()+" failed")
return seq, err
}
func (d *DataBase) GetMsgSeqByClientMsgIDController(ctx context.Context, m *sdk_struct.MsgStruct) (uint32, error) {
switch m.SessionType {
case constant.SuperGroupChatType:
return d.SuperGroupGetMsgSeqByClientMsgID(ctx, m.ClientMsgID, m.GroupID)
default:
return d.GetMsgSeqByClientMsgID(ctx, m.ClientMsgID)
}
}
func (d *DataBase) GetMsgSeqListByGroupID(ctx context.Context, groupID string) ([]uint32, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var seqList []uint32
err := utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=?", groupID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed")
return seqList, err
}
func (d *DataBase) GetMsgSeqListByPeerUserID(ctx context.Context, userID string) ([]uint32, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var seqList []uint32
err := utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=? or send_id=?", userID, userID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed")
return seqList, err
}
func (d *DataBase) GetMsgSeqListBySelfUserID(ctx context.Context, userID string) ([]uint32, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var seqList []uint32
err := utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=? and send_id=?", userID, userID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed")
return seqList, err
}

View File

@@ -0,0 +1,341 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"fmt"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"github.com/openimsdk/openim-sdk-core/v3/sdk_struct"
"github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/log"
)
func (d *DataBase) initChatLog(ctx context.Context, conversationID string) {
if !d.conn.Migrator().HasTable(utils.GetTableName(conversationID)) {
d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).AutoMigrate(&model_struct.LocalChatLog{})
result := d.conn.Exec(fmt.Sprintf("CREATE INDEX %s ON %s (seq)", "index_seq_"+conversationID,
utils.GetTableName(conversationID)))
if result.Error != nil {
log.ZError(ctx, "create table seq index failed", result.Error, "conversationID", conversationID)
}
result = d.conn.Exec(fmt.Sprintf("CREATE INDEX %s ON %s (send_time)", "index_send_time_"+conversationID,
utils.GetTableName(conversationID)))
if result.Error != nil {
log.ZError(ctx, "create table send_time index failed", result.Error, "conversationID", conversationID)
}
}
}
func (d *DataBase) UpdateMessage(ctx context.Context, conversationID string, c *model_struct.LocalChatLog) error {
t := d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Updates(c)
if t.RowsAffected == 0 {
return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update ")
}
return errs.WrapMsg(t.Error, "UpdateMessage failed")
}
func (d *DataBase) UpdateMessageBySeq(ctx context.Context, conversationID string, c *model_struct.LocalChatLog) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("seq=?", c.Seq).Updates(c).Error, "UpdateMessage failed")
}
func (d *DataBase) BatchInsertMessageList(ctx context.Context, conversationID string, MessageList []*model_struct.LocalChatLog) error {
if MessageList == nil {
return nil
}
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Create(MessageList).Error, "BatchInsertMessageList failed")
}
func (d *DataBase) InsertMessage(ctx context.Context, conversationID string, Message *model_struct.LocalChatLog) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Create(Message).Error, "InsertMessage failed")
}
func (d *DataBase) GetMessage(ctx context.Context, conversationID string, clientMsgID string) (*model_struct.LocalChatLog, error) {
d.initChatLog(ctx, conversationID)
var c model_struct.LocalChatLog
return &c, errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("client_msg_id = ?",
clientMsgID).Take(&c).Error, "GetMessage failed")
}
func (d *DataBase) GetMessageBySeq(ctx context.Context, conversationID string, seq int64) (*model_struct.LocalChatLog, error) {
d.initChatLog(ctx, conversationID)
var c model_struct.LocalChatLog
return &c, errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("seq = ?",
seq).Take(&c).Error, "GetMessage failed")
}
func (d *DataBase) UpdateMessageTimeAndStatus(ctx context.Context, conversationID, clientMsgID string, serverMsgID string, sendTime int64, status int32) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Model(model_struct.LocalChatLog{}).Where("client_msg_id=? And seq=?", clientMsgID, 0).
Updates(model_struct.LocalChatLog{Status: status, SendTime: sendTime, ServerMsgID: serverMsgID}).Error, "UpdateMessageStatusBySourceID failed")
}
func (d *DataBase) GetMessageListNoTime(ctx context.Context, conversationID string,
count int, isReverse bool) (result []*model_struct.LocalChatLog, err error) {
d.initChatLog(ctx, conversationID)
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var timeOrder string
if isReverse {
timeOrder = "send_time ASC"
} else {
timeOrder = "send_time DESC"
}
err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Order(timeOrder).Offset(0).Limit(count).Find(&result).Error, "GetMessageList failed")
if err != nil {
return nil, err
}
return result, err
}
func (d *DataBase) GetMessageList(ctx context.Context, conversationID string, count int, startTime int64, isReverse bool) (result []*model_struct.LocalChatLog, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var condition, timeOrder, timeSymbol string
if isReverse {
timeOrder = "send_time ASC"
timeSymbol = ">"
} else {
timeOrder = "send_time DESC"
timeSymbol = "<"
}
condition = "send_time " + timeSymbol + " ?"
err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition, startTime).
Order(timeOrder).Offset(0).Limit(count).Find(&result).Error, "GetMessageList failed")
if err != nil {
return nil, err
}
return result, err
}
func (d *DataBase) DeleteConversationAllMessages(ctx context.Context, conversationID string) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("1 = 1").Delete(model_struct.LocalChatLog{}).Error, "DeleteConversationAllMessages failed")
}
func (d *DataBase) MarkDeleteConversationAllMessages(ctx context.Context, conversationID string) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("1 = 1").Updates(model_struct.LocalChatLog{Status: constant.MsgStatusHasDeleted}).Error, "DeleteConversationAllMessages failed")
}
func (d *DataBase) DeleteConversationMsgs(ctx context.Context, conversationID string, msgIDs []string) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("client_msg_id IN ?", msgIDs).Delete(model_struct.LocalChatLog{}).Error, "DeleteConversationMsgs failed")
}
func (d *DataBase) DeleteConversationMsgsBySeqs(ctx context.Context, conversationID string, seqs []int64) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where("seq IN ?", seqs).Delete(model_struct.LocalChatLog{}).Error, "DeleteConversationMsgs failed")
}
func (d *DataBase) SearchMessageByContentType(ctx context.Context, contentType []int, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error) {
condition := fmt.Sprintf("send_time between %d and %d AND status <=%d And content_type IN ?", startTime, endTime, constant.MsgStatusSendFailed)
err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&result).Error, "SearchMessage failed")
return result, err
}
func (d *DataBase) SearchMessageByKeyword(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error) {
var condition string
var subCondition string
if keywordListMatchType == constant.KeywordMatchOr {
for i := 0; i < len(keywordList); i++ {
if i == 0 {
subCondition += "And ("
}
if i+1 >= len(keywordList) {
subCondition += "content like " + "'%" + keywordList[i] + "%') "
} else {
subCondition += "content like " + "'%" + keywordList[i] + "%' " + "or "
}
}
} else {
for i := 0; i < len(keywordList); i++ {
if i == 0 {
subCondition += "And ("
}
if i+1 >= len(keywordList) {
subCondition += "content like " + "'%" + keywordList[i] + "%') "
} else {
subCondition += "content like " + "'%" + keywordList[i] + "%' " + "and "
}
}
}
condition = fmt.Sprintf(" send_time between %d and %d AND status <=%d And content_type IN ? ", startTime, endTime, constant.MsgStatusSendFailed)
condition += subCondition
err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&result).Error, "InsertMessage failed")
return result, err
} // SearchMessageByContentTypeAndKeyword searches for messages in the database that match specified content types and keywords within a given time range.
func (d *DataBase) SearchMessageByContentTypeAndKeyword(ctx context.Context, contentType []int, conversationID string, keywordList []string, keywordListMatchType int, startTime, endTime int64) (result []*model_struct.LocalChatLog, err error) {
var condition string
var subCondition string
// Construct a sub-condition for SQL query based on keyword list and match type
if keywordListMatchType == constant.KeywordMatchOr {
// Use OR logic if keywordListMatchType is KeywordMatchOr
for i := 0; i < len(keywordList); i++ {
if i == 0 {
subCondition += "And ("
}
if i+1 >= len(keywordList) {
subCondition += "content like " + "'%" + keywordList[i] + "%') "
} else {
subCondition += "content like " + "'%" + keywordList[i] + "%' " + "or "
}
}
} else {
// Use AND logic for other keywordListMatchType
for i := 0; i < len(keywordList); i++ {
if i == 0 {
subCondition += "And ("
}
if i+1 >= len(keywordList) {
subCondition += "content like " + "'%" + keywordList[i] + "%') "
} else {
subCondition += "content like " + "'%" + keywordList[i] + "%' " + "and "
}
}
}
// Construct the main SQL condition string
condition = fmt.Sprintf("send_time between %d and %d AND status <=%d And content_type IN ? ", startTime, endTime, constant.MsgStatusSendFailed)
condition += subCondition
// Execute the query using the constructed condition and handle errors
err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Where(condition, contentType).Order("send_time DESC").Find(&result).Error, "SearchMessage failed")
return result, err
}
func (d *DataBase) UpdateMsgSenderFaceURLAndSenderNickname(ctx context.Context, conversationID, sendID, faceURL, nickname string) error {
return errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Model(model_struct.LocalChatLog{}).Where(
"send_id = ?", sendID).Updates(
map[string]interface{}{"sender_face_url": faceURL, "sender_nick_name": nickname}).Error, utils.GetSelfFuncName()+" failed")
}
func (d *DataBase) GetAlreadyExistSeqList(ctx context.Context, conversationID string, lostSeqList []int64) (seqList []int64, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("seq IN ?", lostSeqList).Pluck("seq", &seqList).Error, utils.GetSelfFuncName()+" failed")
if err != nil {
return nil, err
}
return seqList, nil
}
func (d *DataBase) UpdateColumnsMessage(ctx context.Context, conversationID, ClientMsgID string, args map[string]interface{}) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
c := model_struct.LocalChatLog{ClientMsgID: ClientMsgID}
t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Model(&c).Updates(args)
if t.RowsAffected == 0 {
return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update")
}
return errs.WrapMsg(t.Error, "UpdateColumnsConversation failed")
}
func (d *DataBase) SearchAllMessageByContentType(ctx context.Context, conversationID string, contentType int) (result []*model_struct.LocalChatLog, err error) {
err = d.conn.WithContext(ctx).Table(utils.GetTableName(conversationID)).Model(&model_struct.LocalChatLog{}).Where("content_type = ?", contentType).Find(&result).Error
return result, err
}
func (d *DataBase) GetUnreadMessage(ctx context.Context, conversationID string) (msgs []*model_struct.LocalChatLog, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Debug().Where("send_id != ? AND is_read = ?", d.loginUserID, constant.NotRead).Find(&msgs).Error, "GetMessageList failed")
return msgs, err
}
func (d *DataBase) MarkConversationMessageAsReadBySeqs(ctx context.Context, conversationID string, seqs []int64) (rowsAffected int64, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("seq in ? AND send_id != ?", seqs, d.loginUserID).Update("is_read", constant.HasRead)
if t.RowsAffected == 0 {
return 0, errs.WrapMsg(errors.New("RowsAffected == 0"), "no update")
}
return t.RowsAffected, errs.WrapMsg(t.Error, "UpdateMessageStatusBySourceID failed")
}
func (d *DataBase) MarkConversationMessageAsReadDB(ctx context.Context, conversationID string, msgIDs []string) (rowsAffected int64, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var msgs []*model_struct.LocalChatLog
if err := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("client_msg_id in ? AND send_id != ?", msgIDs, d.loginUserID).Find(&msgs).Error; err != nil {
return 0, errs.WrapMsg(err, "MarkConversationMessageAsReadDB failed")
}
for _, msg := range msgs {
var attachedInfo sdk_struct.AttachedInfoElem
utils.JsonStringToStruct(msg.AttachedInfo, &attachedInfo)
attachedInfo.HasReadTime = utils.GetCurrentTimestampByMill()
msg.IsRead = true
msg.AttachedInfo = utils.StructToJsonString(attachedInfo)
if err := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("client_msg_id = ?", msg.ClientMsgID).Updates(msg).Error; err != nil {
log.ZError(ctx, "MarkConversationMessageAsReadDB failed", err, "msg", msg)
} else {
rowsAffected++
}
}
// t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("client_msg_id in ? AND send_id != ?", msgIDs, d.loginUserID).Update("is_read", constant.HasRead)
// if t.RowsAffected == 0 {
// return 0, errs.WrapMsg(errors.New("RowsAffected == 0"), "no update")
// }
return rowsAffected, nil
}
func (d *DataBase) MarkConversationAllMessageAsRead(ctx context.Context, conversationID string) (rowsAffected int64, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("send_id != ? AND is_read == ?", d.loginUserID, false).Update("is_read", constant.HasRead)
if t.RowsAffected == 0 {
return 0, errs.WrapMsg(errors.New("RowsAffected == 0"), "no update")
}
return t.RowsAffected, errs.WrapMsg(t.Error, "UpdateMessageStatusBySourceID failed")
}
func (d *DataBase) GetMessagesByClientMsgIDs(ctx context.Context, conversationID string, msgIDs []string) (msgs []*model_struct.LocalChatLog, err error) {
err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("client_msg_id IN ?", msgIDs).Order("send_time DESC").Find(&msgs).Error, "GetMessagesByClientMsgIDs error")
return msgs, err
}
func (d *DataBase) GetMessagesBySeqs(ctx context.Context, conversationID string, seqs []int64) (msgs []*model_struct.LocalChatLog, err error) {
err = errs.WrapMsg(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Where("seq IN ?", seqs).Order("send_time DESC").Find(&msgs).Error, "GetMessagesBySeqs error")
return msgs, err
}
func (d *DataBase) GetConversationNormalMsgSeq(ctx context.Context, conversationID string) (int64, error) {
d.initChatLog(ctx, conversationID)
var seq int64
err := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Select("IFNULL(max(seq),0)").Find(&seq).Error
return seq, errs.WrapMsg(err, "GetConversationNormalMsgSeq")
}
func (d *DataBase) GetConversationPeerNormalMsgSeq(ctx context.Context, conversationID string) (int64, error) {
var seq int64
err := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(conversationID)).Select("IFNULL(max(seq),0)").Where("send_id != ?", d.loginUserID).Find(&seq).Error
return seq, errs.WrapMsg(err, "GetConversationPeerNormalMsgSeq")
}

View File

@@ -0,0 +1,120 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
)
func (d *DataBase) GetMessageReactionExtension(ctx context.Context, msgID string) (result *model_struct.LocalChatLogReactionExtensions, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var l model_struct.LocalChatLogReactionExtensions
return &l, utils.Wrap(d.conn.WithContext(ctx).Where("client_msg_id = ?",
msgID).Take(&l).Error, "GetMessageReactionExtension failed")
}
func (d *DataBase) InsertMessageReactionExtension(ctx context.Context, messageReactionExtension *model_struct.LocalChatLogReactionExtensions) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Create(messageReactionExtension).Error, "InsertMessageReactionExtension failed")
}
func (d *DataBase) UpdateMessageReactionExtension(ctx context.Context, c *model_struct.LocalChatLogReactionExtensions) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
t := d.conn.WithContext(ctx).Updates(c)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "UpdateConversation failed")
}
// func (d *DataBase) GetAndUpdateMessageReactionExtension(ctx context.Context, msgID string, m map[string]*sdkws.KeyValue) error {
// d.mRWMutex.Lock()
// defer d.mRWMutex.Unlock()
// var temp model_struct.LocalChatLogReactionExtensions
// err := d.conn.WithContext(ctx).Where("client_msg_id = ?",
// msgID).Take(&temp).Error
// if err != nil {
// temp.ClientMsgID = msgID
// temp.LocalReactionExtensions = []byte(utils.StructToJsonString(m))
// return d.conn.WithContext(ctx).Create(&temp).Error
// } else {
// oldKeyValue := make(map[string]*sdkws.KeyValue)
// err = json.Unmarshal(temp.LocalReactionExtensions, &oldKeyValue)
// if err != nil {
// log.Error("special handle", err.Error())
// }
// log.Warn("special handle", oldKeyValue)
// for k, newValue := range m {
// oldKeyValue[k] = newValue
// }
// temp.LocalReactionExtensions = []byte(utils.StructToJsonString(oldKeyValue))
// t := d.conn.WithContext(ctx).Updates(temp)
// if t.RowsAffected == 0 {
// return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
// }
// }
// return nil
// }
func (d *DataBase) DeleteMessageReactionExtension(ctx context.Context, msgID string) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
temp := model_struct.LocalChatLogReactionExtensions{ClientMsgID: msgID}
return d.conn.WithContext(ctx).Delete(&temp).Error
}
// func (d *DataBase) DeleteAndUpdateMessageReactionExtension(ctx context.Context, msgID string, m map[string]*sdkws.KeyValue) error {
// d.mRWMutex.Lock()
// defer d.mRWMutex.Unlock()
// var temp model_struct.LocalChatLogReactionExtensions
// err := d.conn.WithContext(ctx).Where("client_msg_id = ?",
// msgID).Take(&temp).Error
// if err != nil {
// return err
// } else {
// oldKeyValue := make(map[string]*server_api_params.KeyValue)
// _ = json.Unmarshal(temp.LocalReactionExtensions, &oldKeyValue)
// for k := range m {
// if _, ok := oldKeyValue[k]; ok {
// delete(oldKeyValue, k)
// }
// }
// temp.LocalReactionExtensions = []byte(utils.StructToJsonString(oldKeyValue))
// t := d.conn.WithContext(ctx).Updates(temp)
// if t.RowsAffected == 0 {
// return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
// }
// }
// return nil
// }
// func (d *DataBase) GetMultipleMessageReactionExtension(ctx context.Context, msgIDList []string) (result []*model_struct.LocalChatLogReactionExtensions, err error) {
// d.mRWMutex.Lock()
// defer d.mRWMutex.Unlock()
// var messageList []model_struct.LocalChatLogReactionExtensions
// err = utils.Wrap(d.conn.WithContext(ctx).Where("client_msg_id IN ?", msgIDList).Find(&messageList).Error, "GetMultipleMessageReactionExtension failed")
// for _, v := range messageList {
// v1 := v
// result = append(result, &v1)
// }
// return result, err
// }

View File

@@ -0,0 +1,383 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"fmt"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/log"
"gorm.io/gorm"
)
func (d *DataBase) GetConversationByUserID(ctx context.Context, userID string) (*model_struct.LocalConversation, error) {
var conversation model_struct.LocalConversation
err := utils.Wrap(d.conn.WithContext(ctx).Where("user_id=?", userID).Find(&conversation).Error, "GetConversationByUserID error")
return &conversation, err
}
func (d *DataBase) GetAllConversationListDB(ctx context.Context) ([]*model_struct.LocalConversation, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var conversationList []*model_struct.LocalConversation
err := utils.Wrap(d.conn.WithContext(ctx).Where("latest_msg_send_time > ?", 0).Order("case when is_pinned=1 then 0 else 1 end,max(latest_msg_send_time,draft_text_time) DESC").Find(&conversationList).Error,
"GetAllConversationList failed")
if err != nil {
return nil, err
}
return conversationList, err
}
func (d *DataBase) FindAllConversationConversationID(ctx context.Context) (conversationIDs []string, err error) {
return conversationIDs, utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalConversation{}).Where("latest_msg_send_time > ?", 0).Pluck("conversation_id", &conversationIDs).Error, "")
}
func (d *DataBase) GetHiddenConversationList(ctx context.Context) ([]*model_struct.LocalConversation, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var conversationList []model_struct.LocalConversation
err := utils.Wrap(d.conn.WithContext(ctx).Where("latest_msg_send_time = ?", 0).Find(&conversationList).Error,
"GetHiddenConversationList failed")
var transfer []*model_struct.LocalConversation
for _, v := range conversationList {
v1 := v
transfer = append(transfer, &v1)
}
return transfer, err
}
func (d *DataBase) GetAllConversations(ctx context.Context) ([]*model_struct.LocalConversation, error) {
var conversationList []*model_struct.LocalConversation
err := utils.Wrap(d.conn.WithContext(ctx).Find(&conversationList).Error, "GetAllConversations failed")
return conversationList, err
}
func (d *DataBase) GetAllConversationIDList(ctx context.Context) (result []string, err error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var c model_struct.LocalConversation
err = d.conn.WithContext(ctx).Model(&c).Pluck("conversation_id", &result).Error
return result, utils.Wrap(err, "GetAllConversationIDList failed ")
}
func (d *DataBase) GetAllSingleConversationIDList(ctx context.Context) (result []string, err error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var c model_struct.LocalConversation
err = d.conn.WithContext(ctx).Model(&c).Where("conversation_type = ?", constant.SingleChatType).Pluck("conversation_id", &result).Error
return result, utils.Wrap(err, "GetAllConversationIDList failed ")
}
func (d *DataBase) GetConversationListSplitDB(ctx context.Context, offset, count int) ([]*model_struct.LocalConversation, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var conversationList []model_struct.LocalConversation
err := utils.Wrap(d.conn.WithContext(ctx).Where("latest_msg_send_time > ?", 0).Order("case when is_pinned=1 then 0 else 1 end,max(latest_msg_send_time,draft_text_time) DESC").Offset(offset).Limit(count).Find(&conversationList).Error,
"GetFriendList failed")
var transfer []*model_struct.LocalConversation
for _, v := range conversationList {
v1 := v
transfer = append(transfer, &v1)
}
return transfer, err
}
func (d *DataBase) BatchInsertConversationList(ctx context.Context, conversationList []*model_struct.LocalConversation) error {
if conversationList == nil {
return nil
}
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Create(conversationList).Error, "BatchInsertConversationList failed")
}
func (d *DataBase) UpdateOrCreateConversations(ctx context.Context, conversationList []*model_struct.LocalConversation) error {
var conversationIDs []string
if err := d.conn.WithContext(ctx).Model(&model_struct.LocalConversation{}).Pluck("conversation_id", &conversationIDs).Error; err != nil {
return err
}
var notExistConversations []*model_struct.LocalConversation
var existConversations []*model_struct.LocalConversation
for i, v := range conversationList {
if utils.IsContain(v.ConversationID, conversationIDs) {
existConversations = append(existConversations, v)
continue
} else {
notExistConversations = append(notExistConversations, conversationList[i])
}
}
if len(notExistConversations) > 0 {
if err := d.conn.WithContext(ctx).Create(notExistConversations).Error; err != nil {
return err
}
}
for _, v := range existConversations {
if err := d.conn.WithContext(ctx).Model(&model_struct.LocalConversation{}).Where("conversation_id = ?", v.ConversationID).Updates(map[string]interface{}{"unread_count": v.UnreadCount}).Error; err != nil {
return err
}
}
return nil
}
func (d *DataBase) InsertConversation(ctx context.Context, conversationList *model_struct.LocalConversation) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Create(conversationList).Error, "InsertConversation failed")
}
func (d *DataBase) DeleteConversation(ctx context.Context, conversationID string) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Where("conversation_id = ?", conversationID).Delete(&model_struct.LocalConversation{}).Error, "DeleteConversation failed")
}
func (d *DataBase) GetConversation(ctx context.Context, conversationID string) (*model_struct.LocalConversation, error) {
var c model_struct.LocalConversation
return &c, utils.Wrap(d.conn.WithContext(ctx).Where("conversation_id = ?",
conversationID).Take(&c).Error, "GetConversation failed, conversationID: "+conversationID)
}
func (d *DataBase) UpdateConversation(ctx context.Context, c *model_struct.LocalConversation) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
d.conn.WithContext(ctx).Logger.LogMode(6)
t := d.conn.WithContext(ctx).Updates(c)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "UpdateConversation failed")
}
func (d *DataBase) UpdateConversationForSync(ctx context.Context, c *model_struct.LocalConversation) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
t := d.conn.WithContext(ctx).Model(&model_struct.LocalConversation{}).Where("conversation_id = ?", c.ConversationID).
Updates(map[string]interface{}{"recv_msg_opt": c.RecvMsgOpt, "is_pinned": c.IsPinned, "is_private_chat": c.IsPrivateChat,
"group_at_type": c.GroupAtType, "is_not_in_group": c.IsNotInGroup, "update_unread_count_time": c.UpdateUnreadCountTime, "ex": c.Ex, "attached_info": c.AttachedInfo,
"burn_duration": c.BurnDuration, "msg_destruct_time": c.MsgDestructTime, "is_msg_destruct": c.IsMsgDestruct})
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "UpdateConversation failed")
}
func (d *DataBase) BatchUpdateConversationList(ctx context.Context, conversationList []*model_struct.LocalConversation) error {
for _, v := range conversationList {
err := d.UpdateConversation(ctx, v)
if err != nil {
return utils.Wrap(err, "BatchUpdateConversationList failed")
}
}
return nil
}
func (d *DataBase) ConversationIfExists(ctx context.Context, conversationID string) (bool, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var count int64
t := d.conn.WithContext(ctx).Model(&model_struct.LocalConversation{}).Where("conversation_id = ?",
conversationID).Count(&count)
if t.Error != nil {
return false, utils.Wrap(t.Error, "ConversationIfExists get failed")
}
if count != 1 {
return false, nil
} else {
return true, nil
}
}
// Reset the conversation is equivalent to deleting the conversation,
// and the GetAllConversation or GetConversationListSplit interface will no longer be obtained.
func (d *DataBase) ResetConversation(ctx context.Context, conversationID string) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
c := model_struct.LocalConversation{ConversationID: conversationID, UnreadCount: 0, LatestMsg: "", LatestMsgSendTime: 0, DraftText: "", DraftTextTime: 0}
t := d.conn.WithContext(ctx).Select("unread_count", "latest_msg", "latest_msg_send_time", "draft_text", "draft_text_time").Updates(c)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "ResetConversation failed")
}
// ResetAllConversation Reset ALL conversation is equivalent to deleting the conversation,
// and the GetAllConversation or GetConversationListSplit interface will no longer be obtained.
func (d *DataBase) ResetAllConversation(ctx context.Context) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
c := model_struct.LocalConversation{UnreadCount: 0, LatestMsg: "", LatestMsgSendTime: 0, DraftText: "", DraftTextTime: 0}
t := d.conn.WithContext(ctx).Session(&gorm.Session{AllowGlobalUpdate: true}).Select("unread_count", "latest_msg", "latest_msg_send_time", "draft_text", "draft_text_time").Updates(c)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "ResetConversation failed")
}
// Clear the conversation, which is used to delete the conversation history message and clear the conversation at the same time.
// The GetAllConversation or GetConversationListSplit interface can still be obtained,
// but there is no latest message.
func (d *DataBase) ClearConversation(ctx context.Context, conversationID string) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
c := model_struct.LocalConversation{ConversationID: conversationID, UnreadCount: 0, LatestMsg: "", DraftText: "", DraftTextTime: 0}
t := d.conn.WithContext(ctx).Select("unread_count", "latest_msg", "draft_text", "draft_text_time").Updates(c)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "ClearConversation failed")
}
func (d *DataBase) SetConversationDraftDB(ctx context.Context, conversationID, draftText string) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
nowTime := utils.GetCurrentTimestampByMill()
t := d.conn.WithContext(ctx).Exec("update local_conversations set draft_text=?,draft_text_time=?,latest_msg_send_time=case when latest_msg_send_time=? then ? else latest_msg_send_time end where conversation_id=?",
draftText, nowTime, 0, nowTime, conversationID)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "SetConversationDraft failed")
}
func (d *DataBase) RemoveConversationDraft(ctx context.Context, conversationID, draftText string) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
c := model_struct.LocalConversation{ConversationID: conversationID, DraftText: draftText, DraftTextTime: 0}
t := d.conn.WithContext(ctx).Select("draft_text", "draft_text_time").Updates(c)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "RemoveConversationDraft failed")
}
func (d *DataBase) UnPinConversation(ctx context.Context, conversationID string, isPinned int) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
t := d.conn.WithContext(ctx).Exec("update local_conversations set is_pinned=?,draft_text_time=case when draft_text=? then ? else draft_text_time end where conversation_id=?",
isPinned, "", 0, conversationID)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "UnPinConversation failed")
}
func (d *DataBase) UpdateColumnsConversation(ctx context.Context, conversationID string, args map[string]interface{}) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
t := d.conn.WithContext(ctx).Model(model_struct.LocalConversation{ConversationID: conversationID}).Updates(args)
if t.RowsAffected == 0 {
return utils.Wrap(errs.ErrRecordNotFound, "no update")
}
return utils.Wrap(t.Error, "UpdateColumnsConversation failed")
}
func (d *DataBase) UpdateAllConversation(ctx context.Context, conversation *model_struct.LocalConversation) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
if conversation.ConversationID != "" {
return utils.Wrap(errors.New("not update all conversation"), "UpdateAllConversation failed")
}
t := d.conn.WithContext(ctx).Model(conversation).Updates(conversation)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "UpdateColumnsConversation failed")
}
func (d *DataBase) IncrConversationUnreadCount(ctx context.Context, conversationID string) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
c := model_struct.LocalConversation{ConversationID: conversationID}
t := d.conn.WithContext(ctx).Model(&c).Update("unread_count", gorm.Expr("unread_count+?", 1))
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "IncrConversationUnreadCount failed")
}
func (d *DataBase) GetTotalUnreadMsgCountDB(ctx context.Context) (totalUnreadCount int32, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var result []int64
err = d.conn.WithContext(ctx).Model(&model_struct.LocalConversation{}).Where("recv_msg_opt < ? and latest_msg_send_time > ?", constant.ReceiveNotNotifyMessage, 0).Pluck("unread_count", &result).Error
if err != nil {
return totalUnreadCount, utils.Wrap(errors.New("GetTotalUnreadMsgCount err"), "GetTotalUnreadMsgCount err")
}
for _, v := range result {
totalUnreadCount += int32(v)
}
return totalUnreadCount, nil
}
func (d *DataBase) SetMultipleConversationRecvMsgOpt(ctx context.Context, conversationIDList []string, opt int) (err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
t := d.conn.WithContext(ctx).Model(&model_struct.LocalConversation{}).Where("conversation_id IN ?", conversationIDList).Updates(map[string]interface{}{"recv_msg_opt": opt})
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "SetMultipleConversationRecvMsgOpt failed")
}
func (d *DataBase) GetMultipleConversationDB(ctx context.Context, conversationIDList []string) (result []*model_struct.LocalConversation, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var conversationList []model_struct.LocalConversation
err = utils.Wrap(d.conn.WithContext(ctx).Where("conversation_id IN ?", conversationIDList).Find(&conversationList).Error, "GetMultipleConversation failed")
for _, v := range conversationList {
v1 := v
result = append(result, &v1)
}
return result, err
}
func (d *DataBase) DecrConversationUnreadCount(ctx context.Context, conversationID string, count int64) (err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
tx := d.conn.WithContext(ctx).Begin()
c := model_struct.LocalConversation{ConversationID: conversationID}
t := tx.Model(&c).Update("unread_count", gorm.Expr("unread_count-?", count))
if t.Error != nil {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
if err := tx.Where("conversation_id = ?",
conversationID).Take(&c).Error; err != nil {
tx.Rollback()
return utils.Wrap(errors.New("get conversation err"), "")
}
if c.UnreadCount < 0 {
log.ZWarn(ctx, "decr unread count < 0", nil, "conversationID", conversationID, "count", count)
if t = tx.Model(&c).Update("unread_count", 0); t.Error != nil {
tx.Rollback()
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
}
tx.Commit()
return nil
}
func (d *DataBase) SearchConversations(ctx context.Context, searchParam string) ([]*model_struct.LocalConversation, error) {
// Define the search condition based on the searchParam
condition := fmt.Sprintf("show_name like %q ", "%"+searchParam+"%")
var conversationList []model_struct.LocalConversation
err := d.conn.WithContext(ctx).Where(condition).Order("latest_msg_send_time DESC").Find(&conversationList).Error
var transfer []*model_struct.LocalConversation
for _, v := range conversationList {
v1 := v // Create a copy to avoid referencing the loop variable
transfer = append(transfer, &v1)
}
return transfer, utils.Wrap(err, "SearchConversation failed ")
}

View File

@@ -0,0 +1,38 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
)
func (d *DataBase) BatchInsertConversationUnreadMessageList(ctx context.Context, messageList []*model_struct.LocalConversationUnreadMessage) error {
if messageList == nil {
return nil
}
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Create(messageList).Error, "BatchInsertConversationUnreadMessageList failed")
}
func (d *DataBase) DeleteConversationUnreadMessageList(ctx context.Context, conversationID string, sendTime int64) int64 {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return d.conn.WithContext(ctx).Where("conversation_id = ? and send_time <= ?", conversationID, sendTime).Delete(&model_struct.LocalConversationUnreadMessage{}).RowsAffected
}

View File

@@ -0,0 +1,200 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"path/filepath"
"sync"
"time"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"github.com/openimsdk/openim-sdk-core/v3/version"
"github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/log"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type DataBase struct {
loginUserID string
dbDir string
conn *gorm.DB
mRWMutex sync.RWMutex
groupMtx sync.RWMutex
friendMtx sync.RWMutex
userMtx sync.RWMutex
versionMtx sync.RWMutex
superGroupMtx sync.RWMutex
}
func (d *DataBase) GetMultipleMessageReactionExtension(ctx context.Context, msgIDList []string) (result []*model_struct.LocalChatLogReactionExtensions, err error) {
// TODO implement me
panic("implement me")
}
func (d *DataBase) InitSuperLocalErrChatLog(ctx context.Context, groupID string) {
panic("implement me")
}
func (d *DataBase) InitSuperLocalChatLog(ctx context.Context, groupID string) {
panic("implement me")
}
func (d *DataBase) SetChatLogFailedStatus(ctx context.Context) {
panic("implement me")
}
func (d *DataBase) InitDB(ctx context.Context, userID string, dataDir string) error {
panic("implement me")
}
func (d *DataBase) Close(ctx context.Context) error {
dbConn, err := d.conn.WithContext(ctx).DB()
if err != nil {
return err
} else {
if dbConn != nil {
err := dbConn.Close()
if err != nil {
return err
}
}
}
return nil
}
func NewDataBase(ctx context.Context, loginUserID string, dbDir string, logLevel int) (*DataBase, error) {
dataBase := &DataBase{loginUserID: loginUserID, dbDir: dbDir}
err := dataBase.initDB(ctx, logLevel)
if err != nil {
return dataBase, utils.Wrap(err, "initDB failed "+dbDir)
}
return dataBase, nil
}
func (d *DataBase) initDB(ctx context.Context, logLevel int) error {
var zLogLevel logger.LogLevel
if d.loginUserID == "" {
return errors.New("no uid")
}
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
path := d.dbDir + "/OpenIM_" + constant.BigVersion + "_" + d.loginUserID + ".db"
dbFileName, err := filepath.Abs(path)
if err != nil {
return err
}
log.ZInfo(ctx, "sqlite", "path", dbFileName)
// slowThreshold := 500
// sqlLogger := log.NewSqlLogger(logger.LogLevel(sdk_struct.SvrConf.LogLevel), true, time.Duration(slowThreshold)*time.Millisecond)
if logLevel > 5 {
zLogLevel = logger.Info
} else {
zLogLevel = logger.Silent
}
db, err := gorm.Open(sqlite.Open(dbFileName), &gorm.Config{Logger: log.NewSqlLogger(zLogLevel, false, time.Millisecond*200)})
if err != nil {
return utils.Wrap(err, "open db failed "+dbFileName)
}
log.ZDebug(ctx, "open db success", "db", db, "dbFileName", dbFileName)
sqlDB, err := db.DB()
if err != nil {
return utils.Wrap(err, "get sql db failed")
}
sqlDB.SetConnMaxLifetime(time.Hour * 1)
sqlDB.SetMaxOpenConns(3)
sqlDB.SetMaxIdleConns(2)
sqlDB.SetConnMaxIdleTime(time.Minute * 10)
d.conn = db
// base
if err = db.AutoMigrate(&model_struct.LocalAppSDKVersion{}); err != nil {
return err
}
if err = d.versionDataMigrate(ctx); err != nil {
return err
}
//if err := db.Table(constant.SuperGroupTableName).AutoMigrate(superGroup); err != nil {
// return err
//}
return nil
}
func (d *DataBase) versionDataMigrate(ctx context.Context) error {
verModel, err := d.GetAppSDKVersion(ctx)
if errs.Unwrap(err) == gorm.ErrRecordNotFound {
err = d.conn.AutoMigrate(
&model_struct.LocalAppSDKVersion{},
&model_struct.LocalFriend{},
&model_struct.LocalFriendRequest{},
&model_struct.LocalGroup{},
&model_struct.LocalGroupMember{},
&model_struct.LocalGroupRequest{},
&model_struct.LocalErrChatLog{},
&model_struct.LocalUser{},
&model_struct.LocalBlack{},
&model_struct.LocalConversation{},
&model_struct.NotificationSeqs{},
&model_struct.LocalChatLog{},
&model_struct.LocalAdminGroupRequest{},
&model_struct.LocalWorkMomentsNotification{},
&model_struct.LocalWorkMomentsNotificationUnreadCount{},
&model_struct.TempCacheLocalChatLog{},
&model_struct.LocalChatLogReactionExtensions{},
&model_struct.LocalUpload{},
&model_struct.LocalStranger{},
&model_struct.LocalSendingMessages{},
&model_struct.LocalUserCommand{},
&model_struct.LocalVersionSync{},
)
if err != nil {
return err
}
err = d.SetAppSDKVersion(ctx, &model_struct.LocalAppSDKVersion{Version: version.Version})
if err != nil {
return err
}
return nil
} else if err != nil {
return err
}
if verModel.Version != version.Version {
switch version.Version {
case "3.8.0":
d.conn.AutoMigrate(&model_struct.LocalAppSDKVersion{})
}
err = d.SetAppSDKVersion(ctx, &model_struct.LocalAppSDKVersion{Version: version.Version})
if err != nil {
return err
}
}
return nil
}

View File

@@ -0,0 +1,304 @@
// Copyright © 2023 OpenIM SDK. 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 db_interface
import (
"context"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/sdk_struct"
)
type GroupModel interface {
InsertGroup(ctx context.Context, groupInfo *model_struct.LocalGroup) error
DeleteGroup(ctx context.Context, groupID string) error
UpdateGroup(ctx context.Context, groupInfo *model_struct.LocalGroup) error
BatchInsertGroup(ctx context.Context, groupList []*model_struct.LocalGroup) error
DeleteAllGroup(ctx context.Context) error
GetJoinedGroupListDB(ctx context.Context) ([]*model_struct.LocalGroup, error)
GetGroups(ctx context.Context, groupIDs []string) ([]*model_struct.LocalGroup, error)
GetGroupInfoByGroupID(ctx context.Context, groupID string) (*model_struct.LocalGroup, error)
GetAllGroupInfoByGroupIDOrGroupName(ctx context.Context, keyword string, isSearchGroupID bool, isSearchGroupName bool) ([]*model_struct.LocalGroup, error)
AddMemberCount(ctx context.Context, groupID string) error
SubtractMemberCount(ctx context.Context, groupID string) error
GetJoinedWorkingGroupIDList(ctx context.Context) ([]string, error)
GetJoinedWorkingGroupList(ctx context.Context) ([]*model_struct.LocalGroup, error)
GetUserJoinedGroupIDs(ctx context.Context, userID string) ([]string, error)
InsertAdminGroupRequest(ctx context.Context, groupRequest *model_struct.LocalAdminGroupRequest) error
DeleteAdminGroupRequest(ctx context.Context, groupID, userID string) error
UpdateAdminGroupRequest(ctx context.Context, groupRequest *model_struct.LocalAdminGroupRequest) error
GetAdminGroupApplication(ctx context.Context) ([]*model_struct.LocalAdminGroupRequest, error)
InsertGroupRequest(ctx context.Context, groupRequest *model_struct.LocalGroupRequest) error
DeleteGroupRequest(ctx context.Context, groupID, userID string) error
UpdateGroupRequest(ctx context.Context, groupRequest *model_struct.LocalGroupRequest) error
GetSendGroupApplication(ctx context.Context) ([]*model_struct.LocalGroupRequest, error)
InsertSuperGroup(ctx context.Context, groupInfo *model_struct.LocalGroup) error
DeleteAllSuperGroup(ctx context.Context) error
GetSuperGroupInfoByGroupID(ctx context.Context, groupID string) (*model_struct.LocalGroup, error)
UpdateSuperGroup(ctx context.Context, groupInfo *model_struct.LocalGroup) error
DeleteSuperGroup(ctx context.Context, groupID string) error
GetGroupMemberInfoByGroupIDUserID(ctx context.Context, groupID, userID string) (*model_struct.LocalGroupMember, error)
GetAllGroupMemberList(ctx context.Context) ([]model_struct.LocalGroupMember, error)
GetAllGroupMemberUserIDList(ctx context.Context) ([]model_struct.LocalGroupMember, error)
GetGroupMemberCount(ctx context.Context, groupID string) (int32, error)
GetGroupSomeMemberInfo(ctx context.Context, groupID string, userIDList []string) ([]*model_struct.LocalGroupMember, error)
GetGroupAdminID(ctx context.Context, groupID string) ([]string, error)
GetGroupMemberListByGroupID(ctx context.Context, groupID string) ([]*model_struct.LocalGroupMember, error)
GetGroupMemberListSplit(ctx context.Context, groupID string, filter int32, offset, count int) ([]*model_struct.LocalGroupMember, error)
GetGroupMemberListByUserIDs(ctx context.Context, groupID string, filter int32, userIDs []string) ([]*model_struct.LocalGroupMember, error)
GetGroupMemberOwnerAndAdminDB(ctx context.Context, groupID string) ([]*model_struct.LocalGroupMember, error)
GetGroupMemberOwner(ctx context.Context, groupID string) (*model_struct.LocalGroupMember, error)
GetGroupMemberListSplitByJoinTimeFilter(ctx context.Context, groupID string, offset, count int, joinTimeBegin, joinTimeEnd int64, userIDList []string) ([]*model_struct.LocalGroupMember, error)
GetGroupOwnerAndAdminByGroupID(ctx context.Context, groupID string) ([]*model_struct.LocalGroupMember, error)
GetGroupMemberUIDListByGroupID(ctx context.Context, groupID string) (result []string, err error)
GetGroupMemberAllGroupIDs(ctx context.Context) ([]string, error)
InsertGroupMember(ctx context.Context, groupMember *model_struct.LocalGroupMember) error
BatchInsertGroupMember(ctx context.Context, groupMemberList []*model_struct.LocalGroupMember) error
DeleteGroupMember(ctx context.Context, groupID, userID string) error
DeleteGroupAllMembers(ctx context.Context, groupID string) error
UpdateGroupMember(ctx context.Context, groupMember *model_struct.LocalGroupMember) error
UpdateGroupMemberField(ctx context.Context, groupID, userID string, args map[string]interface{}) error
GetGroupMemberInfoIfOwnerOrAdmin(ctx context.Context) ([]*model_struct.LocalGroupMember, error)
SearchGroupMembersDB(ctx context.Context, keyword string, groupID string, isSearchMemberNickname, isSearchUserID bool, offset, count int) (result []*model_struct.LocalGroupMember, err error)
}
type MessageModel interface {
BatchInsertMessageList(ctx context.Context, conversationID string, MessageList []*model_struct.LocalChatLog) error
// BatchInsertMessageListController(ctx context.Context, MessageList []*model_struct.LocalChatLog) error
InsertMessage(ctx context.Context, conversationID string, Message *model_struct.LocalChatLog) error
// InsertMessageController(ctx context.Context, message *model_struct.LocalChatLog) error
SearchMessageByKeyword(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error)
// SearchMessageByKeywordController(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error)
SearchMessageByContentType(ctx context.Context, contentType []int, conversationID string, startTime, endTime int64, offset, count int) (result []*model_struct.LocalChatLog, err error)
// SearchMessageByContentTypeController(ctx context.Context, contentType []int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error)
SearchMessageByContentTypeAndKeyword(ctx context.Context, contentType []int, conversationID string, keywordList []string, keywordListMatchType int, startTime, endTime int64) (result []*model_struct.LocalChatLog, err error)
MessageIfExists(ctx context.Context, ClientMsgID string) (bool, error)
IsExistsInErrChatLogBySeq(ctx context.Context, seq int64) bool
MessageIfExistsBySeq(ctx context.Context, seq int64) (bool, error)
GetMessage(ctx context.Context, conversationID, clientMsgID string) (*model_struct.LocalChatLog, error)
GetMessageBySeq(ctx context.Context, conversationID string, seq int64) (*model_struct.LocalChatLog, error)
// GetMessageController(ctx context.Context, conversationID, clientMsgID string) (*model_struct.LocalChatLog, error)
UpdateColumnsMessageList(ctx context.Context, clientMsgIDList []string, args map[string]interface{}) error
UpdateColumnsMessage(ctx context.Context, conversationID string, ClientMsgID string, args map[string]interface{}) error
// UpdateColumnsMessageController(ctx context.Context, ClientMsgID string, groupID string, sessionType int32, args map[string]interface{}) error
UpdateMessage(ctx context.Context, conversationID string, c *model_struct.LocalChatLog) error
UpdateMessageBySeq(ctx context.Context, conversationID string, c *model_struct.LocalChatLog) error
// UpdateMessageController(ctx context.Context, c *model_struct.LocalChatLog) error
DeleteAllMessage(ctx context.Context) error
UpdateMessageStatusBySourceID(ctx context.Context, sourceID string, status, sessionType int32) error
// UpdateMessageStatusBySourceIDController(ctx context.Context, sourceID string, status, sessionType int32) error
UpdateMessageTimeAndStatus(ctx context.Context, conversationID, clientMsgID string, serverMsgID string, sendTime int64, status int32) error
// UpdateMessageTimeAndStatusController(ctx context.Context, msg *sdk_struct.MsgStruct) error
GetMessageList(ctx context.Context, conversationID string, count int, startTime int64, isReverse bool) (result []*model_struct.LocalChatLog, err error)
// GetMessageListController(ctx context.Context, sourceID string, sessionType, count int, startTime int64, isReverse bool) (result []*model_struct.LocalChatLog, err error)
GetMessageListNoTime(ctx context.Context, conversationID string, count int, isReverse bool) (result []*model_struct.LocalChatLog, err error)
// GetMessageListNoTimeController(ctx context.Context, sourceID string, sessionType, count int, isReverse bool) (result []*model_struct.LocalChatLog, err error)
MarkConversationMessageAsReadDB(ctx context.Context, conversationID string, msgIDs []string) (rowsAffected int64, err error)
MarkConversationMessageAsReadBySeqs(ctx context.Context, conversationID string, seqs []int64) (rowsAffected int64, err error)
GetUnreadMessage(ctx context.Context, conversationID string) (result []*model_struct.LocalChatLog, err error)
MarkConversationAllMessageAsRead(ctx context.Context, conversationID string) (rowsAffected int64, err error)
GetMessagesByClientMsgIDs(ctx context.Context, conversationID string, msgIDs []string) (result []*model_struct.LocalChatLog, err error)
GetMessagesBySeqs(ctx context.Context, conversationID string, seqs []int64) (result []*model_struct.LocalChatLog, err error)
GetConversationNormalMsgSeq(ctx context.Context, conversationID string) (int64, error)
GetConversationPeerNormalMsgSeq(ctx context.Context, conversationID string) (int64, error)
GetTestMessage(ctx context.Context, seq uint32) (*model_struct.LocalChatLog, error)
UpdateMsgSenderNickname(ctx context.Context, sendID, nickname string, sType int) error
UpdateMsgSenderFaceURL(ctx context.Context, sendID, faceURL string, sType int) error
// UpdateMsgSenderFaceURLAndSenderNicknameController(ctx context.Context, sendID, faceURL, nickname string, sessionType int) error
UpdateMsgSenderFaceURLAndSenderNickname(ctx context.Context, conversationID, sendID, faceURL, nickname string) error
GetMsgSeqByClientMsgID(ctx context.Context, clientMsgID string) (uint32, error)
// GetMsgSeqByClientMsgIDController(ctx context.Context, m *sdk_struct.MsgStruct) (uint32, error)
GetMsgSeqListByGroupID(ctx context.Context, groupID string) ([]uint32, error)
GetMsgSeqListByPeerUserID(ctx context.Context, userID string) ([]uint32, error)
GetMsgSeqListBySelfUserID(ctx context.Context, userID string) ([]uint32, error)
InitSuperLocalErrChatLog(ctx context.Context, groupID string)
SuperBatchInsertExceptionMsg(ctx context.Context, MessageList []*model_struct.LocalErrChatLog, groupID string) error
GetAbnormalMsgSeq(ctx context.Context) (int64, error)
GetAbnormalMsgSeqList(ctx context.Context) ([]int64, error)
BatchInsertExceptionMsg(ctx context.Context, MessageList []*model_struct.LocalErrChatLog) error
GetConversationAbnormalMsgSeq(ctx context.Context, groupID string) (int64, error)
BatchInsertTempCacheMessageList(ctx context.Context, MessageList []*model_struct.TempCacheLocalChatLog) error
InsertTempCacheMessage(ctx context.Context, Message *model_struct.TempCacheLocalChatLog) error
InitSuperLocalChatLog(ctx context.Context, groupID string)
SuperGroupBatchInsertMessageList(ctx context.Context, MessageList []*model_struct.LocalChatLog, groupID string) error
SuperGroupInsertMessage(ctx context.Context, Message *model_struct.LocalChatLog, groupID string) error
SuperGroupDeleteAllMessage(ctx context.Context, groupID string) error
DeleteConversationAllMessages(ctx context.Context, conversationID string) error
MarkDeleteConversationAllMessages(ctx context.Context, conversationID string) error
SuperGroupSearchMessageByKeyword(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error)
// SuperGroupSearchMessageByContentType(ctx context.Context, contentType []int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error)
SuperGroupSearchMessageByContentTypeAndKeyword(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, startTime, endTime int64, groupID string) (result []*model_struct.LocalChatLog, err error)
SuperGroupBatchUpdateMessageList(ctx context.Context, MessageList []*model_struct.LocalChatLog) error
SuperGroupMessageIfExists(ctx context.Context, ClientMsgID string) (bool, error)
SuperGroupIsExistsInErrChatLogBySeq(ctx context.Context, seq int64) bool
SuperGroupMessageIfExistsBySeq(ctx context.Context, seq int64) (bool, error)
SuperGroupGetMessage(ctx context.Context, msg *sdk_struct.MsgStruct) (*model_struct.LocalChatLog, error)
SuperGroupGetAllUnDeleteMessageSeqList(ctx context.Context) ([]uint32, error)
SuperGroupUpdateColumnsMessage(ctx context.Context, ClientMsgID, groupID string, args map[string]interface{}) error
SuperGroupUpdateMessage(ctx context.Context, c *model_struct.LocalChatLog) error
SuperGroupUpdateMessageStatusBySourceID(ctx context.Context, sourceID string, status, sessionType int32) error
SuperGroupUpdateMessageTimeAndStatus(ctx context.Context, msg *sdk_struct.MsgStruct) error
SuperGroupGetMessageList(ctx context.Context, sourceID string, sessionType, count int, startTime int64, isReverse bool) (result []*model_struct.LocalChatLog, err error)
SuperGroupGetMessageListNoTime(ctx context.Context, sourceID string, sessionType, count int, isReverse bool) (result []*model_struct.LocalChatLog, err error)
SuperGroupGetSendingMessageList(ctx context.Context, groupID string) (result []*model_struct.LocalChatLog, err error)
SuperGroupUpdateGroupMessageHasRead(ctx context.Context, msgIDList []string, groupID string) error
// SuperGroupUpdateGroupMessageFields(ctx context.Context, msgIDList []string, groupID string, args map[string]interface{}) error
SuperGroupUpdateMsgSenderNickname(ctx context.Context, sendID, nickname string, sType int) error
SuperGroupUpdateMsgSenderFaceURL(ctx context.Context, sendID, faceURL string, sType int) error
SuperGroupUpdateMsgSenderFaceURLAndSenderNickname(ctx context.Context, sendID, faceURL, nickname string, sessionType int, groupID string) error
SuperGroupGetMsgSeqByClientMsgID(ctx context.Context, clientMsgID string, groupID string) (uint32, error)
SuperGroupGetMsgSeqListByGroupID(ctx context.Context, groupID string) ([]uint32, error)
SuperGroupGetMsgSeqListByPeerUserID(ctx context.Context, userID string) ([]uint32, error)
SuperGroupGetMsgSeqListBySelfUserID(ctx context.Context, userID string) ([]uint32, error)
GetAlreadyExistSeqList(ctx context.Context, conversationID string, lostSeqList []int64) (seqList []int64, err error)
BatchInsertConversationUnreadMessageList(ctx context.Context, messageList []*model_struct.LocalConversationUnreadMessage) error
DeleteConversationUnreadMessageList(ctx context.Context, conversationID string, sendTime int64) int64
DeleteConversationMsgs(ctx context.Context, conversationID string, msgIDs []string) error
// DeleteConversationMsgsBySeqs(ctx context.Context, conversationID string, seqs []int64) error
SetNotificationSeq(ctx context.Context, conversationID string, seq int64) error
GetNotificationAllSeqs(ctx context.Context) ([]*model_struct.NotificationSeqs, error)
}
type ConversationModel interface {
GetConversationByUserID(ctx context.Context, userID string) (*model_struct.LocalConversation, error)
GetAllConversationListDB(ctx context.Context) ([]*model_struct.LocalConversation, error)
GetHiddenConversationList(ctx context.Context) ([]*model_struct.LocalConversation, error)
GetAllConversations(ctx context.Context) ([]*model_struct.LocalConversation, error)
GetAllSingleConversationIDList(ctx context.Context) (result []string, err error)
GetAllConversationIDList(ctx context.Context) (result []string, err error)
GetConversationListSplitDB(ctx context.Context, offset, count int) ([]*model_struct.LocalConversation, error)
BatchInsertConversationList(ctx context.Context, conversationList []*model_struct.LocalConversation) error
UpdateOrCreateConversations(ctx context.Context, conversationList []*model_struct.LocalConversation) error
InsertConversation(ctx context.Context, conversationList *model_struct.LocalConversation) error
DeleteConversation(ctx context.Context, conversationID string) error
GetConversation(ctx context.Context, conversationID string) (*model_struct.LocalConversation, error)
UpdateConversation(ctx context.Context, c *model_struct.LocalConversation) error
UpdateConversationForSync(ctx context.Context, c *model_struct.LocalConversation) error
BatchUpdateConversationList(ctx context.Context, conversationList []*model_struct.LocalConversation) error
ConversationIfExists(ctx context.Context, conversationID string) (bool, error)
ResetConversation(ctx context.Context, conversationID string) error
ResetAllConversation(ctx context.Context) error
ClearConversation(ctx context.Context, conversationID string) error
SetConversationDraftDB(ctx context.Context, conversationID, draftText string) error
RemoveConversationDraft(ctx context.Context, conversationID, draftText string) error
UnPinConversation(ctx context.Context, conversationID string, isPinned int) error
UpdateColumnsConversation(ctx context.Context, conversationID string, args map[string]interface{}) error
UpdateAllConversation(ctx context.Context, conversation *model_struct.LocalConversation) error
IncrConversationUnreadCount(ctx context.Context, conversationID string) error
DecrConversationUnreadCount(ctx context.Context, conversationID string, count int64) (err error)
GetTotalUnreadMsgCountDB(ctx context.Context) (totalUnreadCount int32, err error)
SetMultipleConversationRecvMsgOpt(ctx context.Context, conversationIDList []string, opt int) (err error)
GetMultipleConversationDB(ctx context.Context, conversationIDList []string) (result []*model_struct.LocalConversation, err error)
SearchAllMessageByContentType(ctx context.Context, conversationID string, contentType int) ([]*model_struct.LocalChatLog, error)
SuperGroupSearchAllMessageByContentType(ctx context.Context, superGroupID string, contentType int32) ([]*model_struct.LocalChatLog, error)
SearchConversations(ctx context.Context, searchParam string) ([]*model_struct.LocalConversation, error)
}
type UserModel interface {
GetLoginUser(ctx context.Context, userID string) (*model_struct.LocalUser, error)
UpdateLoginUser(ctx context.Context, user *model_struct.LocalUser) error
UpdateLoginUserByMap(ctx context.Context, user *model_struct.LocalUser, args map[string]interface{}) error
InsertLoginUser(ctx context.Context, user *model_struct.LocalUser) error
GetStrangerInfo(ctx context.Context, userIDs []string) ([]*model_struct.LocalStranger, error)
SetStrangerInfo(ctx context.Context, localStrangerList []*model_struct.LocalStranger) error
ProcessUserCommandAdd(ctx context.Context, command *model_struct.LocalUserCommand) error
ProcessUserCommandUpdate(ctx context.Context, command *model_struct.LocalUserCommand) error
ProcessUserCommandDelete(ctx context.Context, command *model_struct.LocalUserCommand) error
ProcessUserCommandGetAll(ctx context.Context) ([]*model_struct.LocalUserCommand, error)
}
type FriendModel interface {
InsertFriend(ctx context.Context, friend *model_struct.LocalFriend) error
DeleteFriendDB(ctx context.Context, friendUserID string) error
GetFriendListCount(ctx context.Context) (int64, error)
UpdateFriend(ctx context.Context, friend *model_struct.LocalFriend) error
GetAllFriendList(ctx context.Context) ([]*model_struct.LocalFriend, error)
GetPageFriendList(ctx context.Context, offset, count int) ([]*model_struct.LocalFriend, error)
BatchInsertFriend(ctx context.Context, friendList []*model_struct.LocalFriend) error
DeleteAllFriend(ctx context.Context) error
SearchFriendList(ctx context.Context, keyword string, isSearchUserID, isSearchNickname, isSearchRemark bool) ([]*model_struct.LocalFriend, error)
GetFriendInfoByFriendUserID(ctx context.Context, FriendUserID string) (*model_struct.LocalFriend, error)
GetFriendInfoList(ctx context.Context, friendUserIDList []string) ([]*model_struct.LocalFriend, error)
InsertFriendRequest(ctx context.Context, friendRequest *model_struct.LocalFriendRequest) error
DeleteFriendRequestBothUserID(ctx context.Context, fromUserID, toUserID string) error
UpdateFriendRequest(ctx context.Context, friendRequest *model_struct.LocalFriendRequest) error
GetRecvFriendApplication(ctx context.Context) ([]*model_struct.LocalFriendRequest, error)
GetSendFriendApplication(ctx context.Context) ([]*model_struct.LocalFriendRequest, error)
GetFriendApplicationByBothID(ctx context.Context, fromUserID, toUserID string) (*model_struct.LocalFriendRequest, error)
GetBothFriendReq(ctx context.Context, fromUserID, toUserID string) ([]*model_struct.LocalFriendRequest, error)
UpdateColumnsFriend(ctx context.Context, friendIDs []string, args map[string]interface{}) error
GetBlackListDB(ctx context.Context) ([]*model_struct.LocalBlack, error)
GetBlackListUserID(ctx context.Context) (blackListUid []string, err error)
GetBlackInfoByBlockUserID(ctx context.Context, blockUserID string) (*model_struct.LocalBlack, error)
GetBlackInfoList(ctx context.Context, blockUserIDList []string) ([]*model_struct.LocalBlack, error)
InsertBlack(ctx context.Context, black *model_struct.LocalBlack) error
UpdateBlack(ctx context.Context, black *model_struct.LocalBlack) error
DeleteBlack(ctx context.Context, blockUserID string) error
}
type ReactionModel interface {
GetMessageReactionExtension(ctx context.Context, msgID string) (result *model_struct.LocalChatLogReactionExtensions, err error)
InsertMessageReactionExtension(ctx context.Context, messageReactionExtension *model_struct.LocalChatLogReactionExtensions) error
UpdateMessageReactionExtension(ctx context.Context, c *model_struct.LocalChatLogReactionExtensions) error
// GetAndUpdateMessageReactionExtension(ctx context.Context, msgID string, m map[string]*sdkws.KeyValue) error
// DeleteAndUpdateMessageReactionExtension(ctx context.Context, msgID string, m map[string]*sdkws.KeyValue) error
GetMultipleMessageReactionExtension(ctx context.Context, msgIDList []string) (result []*model_struct.LocalChatLogReactionExtensions, err error)
DeleteMessageReactionExtension(ctx context.Context, msgID string) error
}
type S3Model interface {
GetUpload(ctx context.Context, partHash string) (*model_struct.LocalUpload, error)
InsertUpload(ctx context.Context, upload *model_struct.LocalUpload) error
DeleteUpload(ctx context.Context, partHash string) error
UpdateUpload(ctx context.Context, upload *model_struct.LocalUpload) error
DeleteExpireUpload(ctx context.Context) error
}
type SendingMessagesModel interface {
InsertSendingMessage(ctx context.Context, message *model_struct.LocalSendingMessages) error
DeleteSendingMessage(ctx context.Context, conversationID, clientMsgID string) error
GetAllSendingMessages(ctx context.Context) (friendRequests []*model_struct.LocalSendingMessages, err error)
}
type VersionSyncModel interface {
GetVersionSync(ctx context.Context, tableName, entityID string) (*model_struct.LocalVersionSync, error)
SetVersionSync(ctx context.Context, version *model_struct.LocalVersionSync) error
DeleteVersionSync(ctx context.Context, tableName, entityID string) error
}
type AppSDKVersion interface {
GetAppSDKVersion(ctx context.Context) (*model_struct.LocalAppSDKVersion, error)
SetAppSDKVersion(ctx context.Context, version *model_struct.LocalAppSDKVersion) error
}
type DataBase interface {
Close(ctx context.Context) error
InitDB(ctx context.Context, userID string, dataDir string) error
GroupModel
MessageModel
ConversationModel
UserModel
FriendModel
ReactionModel
S3Model
SendingMessagesModel
VersionSyncModel
AppSDKVersion
}

View File

@@ -0,0 +1,87 @@
// Copyright © 2023 OpenIM SDK. 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 db
import (
"context"
"errors"
"github.com/openimsdk/openim-sdk-core/v3/wasm/exec"
"github.com/openimsdk/openim-sdk-core/v3/wasm/indexdb"
)
var ErrType = errors.New("from javascript data type err")
type IndexDB struct {
*indexdb.LocalUsers
*indexdb.LocalConversations
*indexdb.LocalChatLogs
*indexdb.LocalSuperGroupChatLogs
*indexdb.LocalSuperGroup
*indexdb.LocalConversationUnreadMessages
*indexdb.LocalGroups
*indexdb.LocalGroupMember
*indexdb.LocalCacheMessage
*indexdb.FriendRequest
*indexdb.Black
*indexdb.Friend
*indexdb.LocalGroupRequest
*indexdb.LocalChatLogReactionExtensions
*indexdb.NotificationSeqs
*indexdb.LocalUpload
*indexdb.LocalStrangers
*indexdb.LocalSendingMessages
*indexdb.LocalUserCommand
loginUserID string
}
func (i IndexDB) Close(ctx context.Context) error {
_, err := exec.Exec()
return err
}
func (i IndexDB) InitDB(ctx context.Context, userID string, dataDir string) error {
_, err := exec.Exec(userID, dataDir)
return err
}
func NewDataBase(ctx context.Context, loginUserID string, dbDir string, logLevel int) (*IndexDB, error) {
i := &IndexDB{
LocalUsers: indexdb.NewLocalUsers(),
LocalConversations: indexdb.NewLocalConversations(),
LocalChatLogs: indexdb.NewLocalChatLogs(loginUserID),
LocalSuperGroupChatLogs: indexdb.NewLocalSuperGroupChatLogs(),
LocalSuperGroup: indexdb.NewLocalSuperGroup(),
LocalConversationUnreadMessages: indexdb.NewLocalConversationUnreadMessages(),
LocalGroups: indexdb.NewLocalGroups(),
LocalGroupMember: indexdb.NewLocalGroupMember(),
LocalCacheMessage: indexdb.NewLocalCacheMessage(),
FriendRequest: indexdb.NewFriendRequest(loginUserID),
Black: indexdb.NewBlack(loginUserID),
Friend: indexdb.NewFriend(loginUserID),
LocalGroupRequest: indexdb.NewLocalGroupRequest(),
LocalChatLogReactionExtensions: indexdb.NewLocalChatLogReactionExtensions(),
NotificationSeqs: indexdb.NewNotificationSeqs(),
LocalUpload: indexdb.NewLocalUpload(),
LocalStrangers: indexdb.NewLocalStrangers(),
LocalSendingMessages: indexdb.NewLocalSendingMessages(),
LocalUserCommand: indexdb.NewLocalUserCommand(),
loginUserID: loginUserID,
}
err := i.InitDB(ctx, loginUserID, dbDir)
if err != nil {
return nil, err
}
return i, nil
}

View File

@@ -0,0 +1,77 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
)
func (d *DataBase) initSuperLocalErrChatLog(ctx context.Context, groupID string) {
if !d.conn.WithContext(ctx).Migrator().HasTable(utils.GetErrTableName(groupID)) {
d.conn.WithContext(ctx).Table(utils.GetErrTableName(groupID)).AutoMigrate(&model_struct.LocalErrChatLog{})
}
}
func (d *DataBase) SuperBatchInsertExceptionMsg(ctx context.Context, MessageList []*model_struct.LocalErrChatLog, groupID string) error {
if MessageList == nil {
return nil
}
d.initSuperLocalErrChatLog(ctx, groupID)
return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Create(MessageList).Error, "BatchInsertMessageList failed")
}
func (d *DataBase) GetAbnormalMsgSeq(ctx context.Context) (int64, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var seq int64
err := d.conn.WithContext(ctx).Model(model_struct.LocalErrChatLog{}).Select("IFNULL(max(seq),0)").Find(&seq).Error
return seq, utils.Wrap(err, "GetAbnormalMsgSeq")
}
func (d *DataBase) GetAbnormalMsgSeqList(ctx context.Context) ([]int64, error) {
var seqList []int64
err := d.conn.WithContext(ctx).Model(model_struct.LocalErrChatLog{}).Select("seq").Find(&seqList).Error
return seqList, utils.Wrap(err, "GetAbnormalMsgSeqList")
}
func (d *DataBase) BatchInsertExceptionMsg(ctx context.Context, messageList []*model_struct.LocalErrChatLog) error {
if messageList == nil {
return nil
}
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Create(messageList).Error, "BatchInsertMessageList failed")
}
func (d *DataBase) BatchInsertExceptionMsgController(ctx context.Context, messageList []*model_struct.LocalErrChatLog) error {
if len(messageList) == 0 {
return nil
}
switch messageList[len(messageList)-1].SessionType {
case constant.SuperGroupChatType:
return d.SuperBatchInsertExceptionMsg(ctx, messageList, messageList[len(messageList)-1].RecvID)
default:
return d.BatchInsertExceptionMsg(ctx, messageList)
}
}
func (d *DataBase) GetConversationAbnormalMsgSeq(ctx context.Context, conversationID string) (int64, error) {
var seq int64
if !d.conn.WithContext(ctx).Migrator().HasTable(utils.GetErrTableName(conversationID)) {
return 0, nil
}
err := d.conn.WithContext(ctx).Table(utils.GetErrTableName(conversationID)).Select("IFNULL(max(seq),0)").Find(&seq).Error
return seq, utils.Wrap(err, "GetConversationNormalMsgSeq")
}

View File

@@ -0,0 +1,139 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"fmt"
"gorm.io/gorm"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/tools/errs"
)
func (d *DataBase) InsertFriend(ctx context.Context, friend *model_struct.LocalFriend) error {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Create(friend).Error, "InsertFriend failed")
}
func (d *DataBase) DeleteFriendDB(ctx context.Context, friendUserID string) error {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Where("owner_user_id=? and friend_user_id=?", d.loginUserID, friendUserID).Delete(&model_struct.LocalFriend{}).Error, "DeleteFriend failed")
}
func (d *DataBase) GetFriendListCount(ctx context.Context) (int64, error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
var count int64
return count, errs.WrapMsg(d.conn.WithContext(ctx).Model(&model_struct.LocalFriend{}).Count(&count).Error, "GetFriendListCount failed")
}
func (d *DataBase) UpdateFriend(ctx context.Context, friend *model_struct.LocalFriend) error {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
t := d.conn.WithContext(ctx).Model(friend).Select("*").Updates(*friend)
if t.RowsAffected == 0 {
return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update")
}
return errs.Wrap(t.Error)
}
func (d *DataBase) GetAllFriendList(ctx context.Context) ([]*model_struct.LocalFriend, error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
var friendList []*model_struct.LocalFriend
return friendList, errs.WrapMsg(d.conn.WithContext(ctx).Where("owner_user_id = ?", d.loginUserID).Find(&friendList).Error,
"GetFriendList failed")
}
func (d *DataBase) GetPageFriendList(ctx context.Context, offset, count int) ([]*model_struct.LocalFriend, error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
var friendList []*model_struct.LocalFriend
err := errs.WrapMsg(d.conn.WithContext(ctx).Where("owner_user_id = ?", d.loginUserID).Offset(offset).Limit(count).Order("name").Find(&friendList).Error,
"GetFriendList failed")
return friendList, err
}
func (d *DataBase) BatchInsertFriend(ctx context.Context, friendList []*model_struct.LocalFriend) error {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
if friendList == nil {
return errs.New("nil").Wrap()
}
return errs.WrapMsg(d.conn.WithContext(ctx).Create(friendList).Error, "BatchInsertFriendList failed")
}
func (d *DataBase) DeleteAllFriend(ctx context.Context) error {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&model_struct.LocalFriend{}).Error, "DeleteAllFriend failed")
}
func (d *DataBase) SearchFriendList(ctx context.Context, keyword string, isSearchUserID, isSearchNickname, isSearchRemark bool) ([]*model_struct.LocalFriend, error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
var count int
var friendList []*model_struct.LocalFriend
var condition string
if isSearchUserID {
condition = fmt.Sprintf("friend_user_id like %q ", "%"+keyword+"%")
count++
}
if isSearchNickname {
if count > 0 {
condition += "or "
}
condition += fmt.Sprintf("name like %q ", "%"+keyword+"%")
count++
}
if isSearchRemark {
if count > 0 {
condition += "or "
}
condition += fmt.Sprintf("remark like %q ", "%"+keyword+"%")
}
err := d.conn.WithContext(ctx).Where(condition).Order("create_time DESC").Find(&friendList).Error
return friendList, errs.WrapMsg(err, "SearchFriendList failed")
}
func (d *DataBase) GetFriendInfoByFriendUserID(ctx context.Context, FriendUserID string) (*model_struct.LocalFriend, error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
var friend model_struct.LocalFriend
return &friend, errs.WrapMsg(d.conn.WithContext(ctx).Where("owner_user_id = ? AND friend_user_id = ?",
d.loginUserID, FriendUserID).Take(&friend).Error, "GetFriendInfoByFriendUserID failed")
}
func (d *DataBase) GetFriendInfoList(ctx context.Context, friendUserIDList []string) ([]*model_struct.LocalFriend, error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
var friendList []*model_struct.LocalFriend
err := errs.WrapMsg(d.conn.WithContext(ctx).Where("friend_user_id IN ?", friendUserIDList).Find(&friendList).Error, "GetFriendInfoListByFriendUserID failed")
return friendList, err
}
func (d *DataBase) UpdateColumnsFriend(ctx context.Context, friendIDs []string, args map[string]interface{}) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Model(&model_struct.LocalFriend{}).Where("friend_user_id IN ?", friendIDs).Updates(args).Error, "UpdateColumnsFriend failed")
}

View File

@@ -0,0 +1,76 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/tools/errs"
)
func (d *DataBase) InsertFriendRequest(ctx context.Context, friendRequest *model_struct.LocalFriendRequest) error {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Create(friendRequest).Error, "InsertFriendRequest failed")
}
func (d *DataBase) DeleteFriendRequestBothUserID(ctx context.Context, fromUserID, toUserID string) error {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Where("from_user_id=? and to_user_id=?", fromUserID, toUserID).Delete(&model_struct.LocalFriendRequest{}).Error, "DeleteFriendRequestBothUserID failed")
}
func (d *DataBase) UpdateFriendRequest(ctx context.Context, friendRequest *model_struct.LocalFriendRequest) error {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
t := d.conn.WithContext(ctx).Model(friendRequest).Select("*").Updates(*friendRequest)
if t.RowsAffected == 0 {
return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update")
}
return errs.Wrap(t.Error)
}
func (d *DataBase) GetRecvFriendApplication(ctx context.Context) ([]*model_struct.LocalFriendRequest, error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
var friendRequestList []*model_struct.LocalFriendRequest
return friendRequestList, errs.WrapMsg(d.conn.WithContext(ctx).Where("to_user_id = ?", d.loginUserID).Order("create_time DESC").Find(&friendRequestList).Error, "GetRecvFriendApplication failed")
}
func (d *DataBase) GetSendFriendApplication(ctx context.Context) ([]*model_struct.LocalFriendRequest, error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
var friendRequestList []*model_struct.LocalFriendRequest
return friendRequestList, errs.WrapMsg(d.conn.WithContext(ctx).Where("from_user_id = ?", d.loginUserID).Order("create_time DESC").Find(&friendRequestList).Error, "GetSendFriendApplication failed")
}
func (d *DataBase) GetFriendApplicationByBothID(ctx context.Context, fromUserID, toUserID string) (*model_struct.LocalFriendRequest, error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
var friendRequest model_struct.LocalFriendRequest
return &friendRequest, errs.WrapMsg(d.conn.WithContext(ctx).Where("from_user_id = ? AND to_user_id = ?", fromUserID, toUserID).Take(&friendRequest).Error, "GetFriendApplicationByBothID failed")
}
func (d *DataBase) GetBothFriendReq(ctx context.Context, fromUserID, toUserID string) (friendRequests []*model_struct.LocalFriendRequest, err error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
return friendRequests, errs.WrapMsg(d.conn.WithContext(ctx).Where("(from_user_id = ? AND to_user_id = ?) OR (from_user_id = ? AND to_user_id = ?)", fromUserID, toUserID, toUserID, fromUserID).Find(&friendRequests).Error, "GetFriendApplicationByBothID failed")
}

View File

@@ -0,0 +1,307 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"fmt"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/tools/errs"
)
func (d *DataBase) GetGroupMemberInfoByGroupIDUserID(ctx context.Context, groupID, userID string) (*model_struct.LocalGroupMember, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupMember model_struct.LocalGroupMember
return &groupMember, errs.WrapMsg(d.conn.WithContext(ctx).Where("group_id = ? AND user_id = ?",
groupID, userID).Take(&groupMember).Error, "GetGroupMemberInfoByGroupIDUserID failed")
}
func (d *DataBase) GetAllGroupMemberList(ctx context.Context) ([]model_struct.LocalGroupMember, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupMemberList []model_struct.LocalGroupMember
return groupMemberList, errs.WrapMsg(d.conn.WithContext(ctx).Find(&groupMemberList).Error, "GetAllGroupMemberList failed")
}
func (d *DataBase) GetAllGroupMemberUserIDList(ctx context.Context) ([]model_struct.LocalGroupMember, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupMemberList []model_struct.LocalGroupMember
return groupMemberList, errs.WrapMsg(d.conn.WithContext(ctx).Find(&groupMemberList).Error, "GetAllGroupMemberList failed")
}
func (d *DataBase) GetGroupMemberCount(ctx context.Context, groupID string) (int32, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var count int64
err := d.conn.WithContext(ctx).Model(&model_struct.LocalGroupMember{}).Where("group_id = ? ", groupID).Count(&count).Error
return int32(count), errs.WrapMsg(err, "GetGroupMemberCount failed")
}
func (d *DataBase) GetGroupSomeMemberInfo(ctx context.Context, groupID string, userIDList []string) ([]*model_struct.LocalGroupMember, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupMemberList []*model_struct.LocalGroupMember
err := d.conn.WithContext(ctx).Where("group_id = ? And user_id IN ? ", groupID, userIDList).Find(&groupMemberList).Error
return groupMemberList, errs.WrapMsg(err, "GetGroupMemberListByGroupID failed ")
}
func (d *DataBase) GetGroupAdminID(ctx context.Context, groupID string) ([]string, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var adminIDList []string
return adminIDList, errs.WrapMsg(d.conn.WithContext(ctx).Model(&model_struct.LocalGroupMember{}).Select("user_id").Where("group_id = ? And role_level = ?", groupID, constant.GroupAdmin).Find(&adminIDList).Error, "")
}
func (d *DataBase) GetGroupMemberListByGroupID(ctx context.Context, groupID string) ([]*model_struct.LocalGroupMember, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupMemberList []*model_struct.LocalGroupMember
err := d.conn.WithContext(ctx).Where("group_id = ? ", groupID).Find(&groupMemberList).Error
return groupMemberList, errs.WrapMsg(err, "GetGroupMemberListByGroupID failed ")
}
func (d *DataBase) GetGroupMemberListByUserIDs(ctx context.Context, groupID string, filter int32, userIDs []string) ([]*model_struct.LocalGroupMember, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupMemberList []*model_struct.LocalGroupMember
var err error
switch filter {
case constant.GroupFilterAll:
err = d.conn.WithContext(ctx).Where("group_id = ? AND user_id IN ?", groupID, userIDs).Order("role_level DESC, join_time ASC").Find(&groupMemberList).Error
case constant.GroupFilterOwner:
err = d.conn.WithContext(ctx).Where("group_id = ? AND role_level = ? AND user_id IN ?", groupID, constant.GroupOwner, userIDs).Find(&groupMemberList).Error
case constant.GroupFilterAdmin:
err = d.conn.WithContext(ctx).Where("group_id = ? AND role_level = ? AND user_id IN ?", groupID, constant.GroupAdmin, userIDs).Find(&groupMemberList).Error
case constant.GroupFilterOrdinaryUsers:
err = d.conn.WithContext(ctx).Where("group_id = ? AND role_level = ? AND user_id IN ?", groupID, constant.GroupOrdinaryUsers, userIDs).Find(&groupMemberList).Error
case constant.GroupFilterAdminAndOrdinaryUsers:
err = d.conn.WithContext(ctx).Where("group_id = ? AND (role_level = ? OR role_level = ?) AND user_id IN ?", groupID, constant.GroupAdmin, constant.GroupOrdinaryUsers, userIDs).Find(&groupMemberList).Error
case constant.GroupFilterOwnerAndAdmin:
err = d.conn.WithContext(ctx).Where("group_id = ? AND (role_level = ? OR role_level = ?) AND user_id IN ?", groupID, constant.GroupOwner, constant.GroupAdmin, userIDs).Find(&groupMemberList).Error
default:
return nil, errs.New("filter args failed.", "filter", filter).Wrap()
}
return groupMemberList, errs.Wrap(err)
}
func (d *DataBase) GetGroupMemberListSplit(ctx context.Context, groupID string, filter int32, offset, count int) ([]*model_struct.LocalGroupMember, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupMemberList []*model_struct.LocalGroupMember
var err error
switch filter {
case constant.GroupFilterAll:
err = d.conn.WithContext(ctx).Where("group_id = ?", groupID).Order("role_level DESC,join_time ASC").Offset(offset).Limit(count).Find(&groupMemberList).Error
case constant.GroupFilterOwner:
err = d.conn.WithContext(ctx).Where("group_id = ? And role_level = ?", groupID, constant.GroupOwner).Offset(offset).Limit(count).Find(&groupMemberList).Error
case constant.GroupFilterAdmin:
err = d.conn.WithContext(ctx).Where("group_id = ? And role_level = ?", groupID, constant.GroupAdmin).Order("join_time ASC").Offset(offset).Limit(count).Find(&groupMemberList).Error
case constant.GroupFilterOrdinaryUsers:
err = d.conn.WithContext(ctx).Where("group_id = ? And role_level = ?", groupID, constant.GroupOrdinaryUsers).Order("join_time ASC").Offset(offset).Limit(count).Find(&groupMemberList).Error
case constant.GroupFilterAdminAndOrdinaryUsers:
err = d.conn.WithContext(ctx).Where("group_id = ? And (role_level = ? or role_level = ?)", groupID, constant.GroupAdmin, constant.GroupOrdinaryUsers).Order("role_level DESC,join_time ASC").Offset(offset).Limit(count).Find(&groupMemberList).Error
case constant.GroupFilterOwnerAndAdmin:
err = d.conn.WithContext(ctx).Where("group_id = ? And (role_level = ? or role_level = ?)", groupID, constant.GroupOwner, constant.GroupAdmin).Order("role_level DESC,join_time ASC").Offset(offset).Limit(count).Find(&groupMemberList).Error
default:
return nil, errs.New("filter args failed", "filter", filter).Wrap()
}
return groupMemberList, errs.WrapMsg(err, "GetGroupMemberListSplit failed ")
}
func (d *DataBase) GetGroupMemberOwnerAndAdminDB(ctx context.Context, groupID string) ([]*model_struct.LocalGroupMember, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupMemberList []*model_struct.LocalGroupMember
err := d.conn.WithContext(ctx).Where("group_id = ? And (role_level = ? OR role_level = ?)", groupID, constant.GroupOwner, constant.GroupAdmin).Order("join_time DESC").Find(&groupMemberList).Error
return groupMemberList, errs.WrapMsg(err, "GetGroupMemberListSplit failed ")
}
func (d *DataBase) GetGroupMemberOwner(ctx context.Context, groupID string) (*model_struct.LocalGroupMember, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupMember model_struct.LocalGroupMember
err := d.conn.WithContext(ctx).Where("group_id = ? And role_level = ?", groupID, constant.GroupOwner).Find(&groupMember).Error
return &groupMember, errs.WrapMsg(err, "GetGroupMemberListSplit failed ")
}
func (d *DataBase) GetGroupMemberListSplitByJoinTimeFilter(ctx context.Context, groupID string, offset, count int, joinTimeBegin, joinTimeEnd int64, userIDList []string) ([]*model_struct.LocalGroupMember, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupMemberList []*model_struct.LocalGroupMember
var err error
if len(userIDList) == 0 {
err = d.conn.WithContext(ctx).Where("group_id = ? And join_time between ? and ? ", groupID, joinTimeBegin, joinTimeEnd).Order("join_time DESC").Offset(offset).Limit(count).Find(&groupMemberList).Error
} else {
err = d.conn.WithContext(ctx).Where("group_id = ? And join_time between ? and ? And user_id NOT IN ?", groupID, joinTimeBegin, joinTimeEnd, userIDList).Order("join_time DESC").Offset(offset).Limit(count).Find(&groupMemberList).Error
}
return groupMemberList, errs.WrapMsg(err, "GetGroupMemberListSplitByJoinTimeFilter failed ")
}
func (d *DataBase) GetGroupOwnerAndAdminByGroupID(ctx context.Context, groupID string) ([]*model_struct.LocalGroupMember, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupMemberList []*model_struct.LocalGroupMember
err := d.conn.WithContext(ctx).Where("group_id = ? AND (role_level = ? Or role_level = ?)", groupID, constant.GroupOwner, constant.GroupAdmin).Find(&groupMemberList).Error
return groupMemberList, errs.WrapMsg(err, "GetGroupMemberListByGroupID failed ")
}
func (d *DataBase) GetGroupMemberUIDListByGroupID(ctx context.Context, groupID string) (result []string, err error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var g model_struct.LocalGroupMember
g.GroupID = groupID
err = d.conn.WithContext(ctx).Model(&g).Where("group_id = ?", groupID).Pluck("user_id", &result).Error
return result, errs.WrapMsg(err, "GetGroupMemberListByGroupID failed ")
}
func (d *DataBase) InsertGroupMember(ctx context.Context, groupMember *model_struct.LocalGroupMember) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Create(groupMember).Error, "")
}
//funcation (d *DataBase) BatchInsertMessageList(ctx context.Context, MessageList []*model_struct.LocalChatLog) error {
// if MessageList == nil {
// return nil
// }
// d.mRWMutex.Lock()
// defer d.mRWMutex.Unlock()
// return errs.WrapMsg(d.conn.WithContext(ctx).Create(MessageList).Error, "BatchInsertMessageList failed")
//}
func (d *DataBase) BatchInsertGroupMember(ctx context.Context, groupMemberList []*model_struct.LocalGroupMember) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
if groupMemberList == nil {
return errors.New("nil")
}
return errs.WrapMsg(d.conn.WithContext(ctx).Create(groupMemberList).Error, "BatchInsertMessageList failed")
}
func (d *DataBase) DeleteGroupMember(ctx context.Context, groupID, userID string) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupMember model_struct.LocalGroupMember
return d.conn.WithContext(ctx).Where("group_id=? and user_id=?", groupID, userID).Delete(&groupMember).Error
}
func (d *DataBase) DeleteGroupAllMembers(ctx context.Context, groupID string) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupMember model_struct.LocalGroupMember
return d.conn.WithContext(ctx).Where("group_id=? ", groupID).Delete(&groupMember).Error
}
func (d *DataBase) UpdateGroupMember(ctx context.Context, groupMember *model_struct.LocalGroupMember) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
t := d.conn.WithContext(ctx).Model(groupMember).Select("*").Updates(*groupMember)
if t.RowsAffected == 0 {
return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update")
}
return errs.WrapMsg(t.Error, "")
}
func (d *DataBase) UpdateGroupMemberField(ctx context.Context, groupID, userID string, args map[string]interface{}) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
c := model_struct.LocalGroupMember{GroupID: groupID, UserID: userID}
t := d.conn.WithContext(ctx).Model(&c).Updates(args)
if t.RowsAffected == 0 {
return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update")
}
return errs.WrapMsg(t.Error, "UpdateGroupMemberField failed")
}
func (d *DataBase) GetGroupMemberInfoIfOwnerOrAdmin(ctx context.Context) ([]*model_struct.LocalGroupMember, error) {
var ownerAndAdminList []*model_struct.LocalGroupMember
groupList, err := d.GetJoinedGroupListDB(ctx)
if err != nil {
return nil, errs.Wrap(err)
}
for _, v := range groupList {
memberList, err := d.GetGroupOwnerAndAdminByGroupID(ctx, v.GroupID)
if err != nil {
return nil, errs.Wrap(err)
}
ownerAndAdminList = append(ownerAndAdminList, memberList...)
}
return ownerAndAdminList, nil
}
func (d *DataBase) SearchGroupMembersDB(ctx context.Context, keyword string, groupID string, isSearchMemberNickname, isSearchUserID bool, offset, count int) (result []*model_struct.LocalGroupMember, err error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
if !isSearchMemberNickname && !isSearchUserID {
return nil, errors.New("args failed")
}
var countCon int
var condition string
if isSearchUserID {
condition = fmt.Sprintf("user_id like %q ", "%"+keyword+"%")
countCon++
}
if isSearchMemberNickname {
if countCon > 0 {
condition += "or "
}
condition += fmt.Sprintf("nickname like %q ", "%"+keyword+"%")
}
var groupMemberList []model_struct.LocalGroupMember
if groupID != "" {
condition = "( " + condition + " ) "
condition += " and group_id IN ? "
err = d.conn.WithContext(ctx).Where(condition, []string{groupID}).Order("role_level DESC,join_time ASC").Offset(offset).Limit(count).Find(&groupMemberList).Error
} else {
err = d.conn.WithContext(ctx).Where(condition).Order("role_level DESC,join_time ASC").Offset(offset).Limit(count).Find(&groupMemberList).Error
}
for _, v := range groupMemberList {
v1 := v
result = append(result, &v1)
}
return result, err
}
func (d *DataBase) GetGroupMemberAllGroupIDs(ctx context.Context) ([]string, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
// SELECT DISTINCT group_id FROM local_group_members;
var groupIDs []string
err := d.conn.WithContext(ctx).Select("DISTINCT group_id").Model(&model_struct.LocalGroupMember{}).Pluck("group_id", &groupIDs).Error
if err != nil {
return nil, err
}
return groupIDs, nil
}
func (d *DataBase) GetUserJoinedGroupIDs(ctx context.Context, userID string) (groupIDs []string, err error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
return groupIDs, d.conn.WithContext(ctx).Model(&model_struct.LocalGroupMember{}).Where("user_id = ?", userID).Pluck("group_id", &groupIDs).Error
}

View File

@@ -0,0 +1,117 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"fmt"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/tools/errs"
"gorm.io/gorm"
)
func (d *DataBase) InsertGroup(ctx context.Context, groupInfo *model_struct.LocalGroup) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Create(groupInfo).Error, "InsertGroup failed")
}
func (d *DataBase) DeleteGroup(ctx context.Context, groupID string) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
localGroup := model_struct.LocalGroup{GroupID: groupID}
return errs.WrapMsg(d.conn.WithContext(ctx).Delete(&localGroup).Error, "DeleteGroup failed")
}
func (d *DataBase) UpdateGroup(ctx context.Context, groupInfo *model_struct.LocalGroup) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
t := d.conn.WithContext(ctx).Model(groupInfo).Select("*").Updates(*groupInfo)
if t.RowsAffected == 0 {
return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update")
}
return errs.Wrap(t.Error)
}
func (d *DataBase) BatchInsertGroup(ctx context.Context, groupList []*model_struct.LocalGroup) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Create(groupList).Error, "BatchInsertGroup failed")
}
func (d *DataBase) DeleteAllGroup(ctx context.Context) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&model_struct.LocalGroup{}).Error, "DeleteAllGroup failed")
}
func (d *DataBase) GetJoinedGroupListDB(ctx context.Context) ([]*model_struct.LocalGroup, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupList []*model_struct.LocalGroup
err := d.conn.WithContext(ctx).Find(&groupList).Error
return groupList, errs.WrapMsg(err, "GetJoinedGroupList failed ")
}
func (d *DataBase) GetGroups(ctx context.Context, groupIDs []string) ([]*model_struct.LocalGroup, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupList []*model_struct.LocalGroup
err := d.conn.WithContext(ctx).Where("group_id in (?)", groupIDs).Find(&groupList).Error
return groupList, errs.WrapMsg(err, "GetGroups failed ")
}
func (d *DataBase) GetGroupInfoByGroupID(ctx context.Context, groupID string) (*model_struct.LocalGroup, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var g model_struct.LocalGroup
return &g, errs.WrapMsg(d.conn.WithContext(ctx).Where("group_id = ?", groupID).Take(&g).Error, "GetGroupList failed")
}
func (d *DataBase) GetAllGroupInfoByGroupIDOrGroupName(ctx context.Context, keyword string, isSearchGroupID bool, isSearchGroupName bool) ([]*model_struct.LocalGroup, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupList []*model_struct.LocalGroup
var condition string
if isSearchGroupID {
if isSearchGroupName {
condition = fmt.Sprintf("group_id like %q or name like %q", "%"+keyword+"%", "%"+keyword+"%")
} else {
condition = fmt.Sprintf("group_id like %q ", "%"+keyword+"%")
}
} else {
condition = fmt.Sprintf("name like %q ", "%"+keyword+"%")
}
err := d.conn.WithContext(ctx).Where(condition).Order("create_time DESC").Find(&groupList).Error
return groupList, errs.WrapMsg(err, "GetAllGroupInfoByGroupIDOrGroupName failed ")
}
func (d *DataBase) AddMemberCount(ctx context.Context, groupID string) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
group := model_struct.LocalGroup{GroupID: groupID}
return errs.WrapMsg(d.conn.WithContext(ctx).Model(&group).Updates(map[string]interface{}{"member_count": gorm.Expr("member_count+1")}).Error, "")
}
func (d *DataBase) SubtractMemberCount(ctx context.Context, groupID string) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
group := model_struct.LocalGroup{GroupID: groupID}
return errs.WrapMsg(d.conn.WithContext(ctx).Model(&group).Updates(map[string]interface{}{"member_count": gorm.Expr("member_count-1")}).Error, "")
}

View File

@@ -0,0 +1,53 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/tools/errs"
)
func (d *DataBase) InsertGroupRequest(ctx context.Context, groupRequest *model_struct.LocalGroupRequest) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Create(groupRequest).Error, "InsertGroupRequest failed")
}
func (d *DataBase) DeleteGroupRequest(ctx context.Context, groupID, userID string) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
return errs.WrapMsg(d.conn.WithContext(ctx).Where("group_id=? and user_id=?", groupID, userID).Delete(&model_struct.LocalGroupRequest{}).Error, "DeleteGroupRequest failed")
}
func (d *DataBase) UpdateGroupRequest(ctx context.Context, groupRequest *model_struct.LocalGroupRequest) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
t := d.conn.WithContext(ctx).Model(groupRequest).Select("*").Updates(*groupRequest)
if t.RowsAffected == 0 {
return errs.WrapMsg(errors.New("RowsAffected == 0"), "no update")
}
return errs.Wrap(t.Error)
}
func (d *DataBase) GetSendGroupApplication(ctx context.Context) ([]*model_struct.LocalGroupRequest, error) {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
var groupRequestList []*model_struct.LocalGroupRequest
return groupRequestList, errs.Wrap(d.conn.WithContext(ctx).Order("create_time DESC").Find(&groupRequestList).Error)
}

View File

@@ -0,0 +1,587 @@
// Copyright © 2023 OpenIM SDK. 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 model_struct
import (
"database/sql/driver"
"encoding/json"
"github.com/openimsdk/tools/errs"
)
//
//message FriendInfo{
//string OwnerUserID = 1;
//string Remark = 2;
//int64 CreateTime = 3;
//UserInfo FriendUser = 4;
//int32 AddSource = 5;
//string OperatorUserID = 6;
//string Ex = 7;
//}
//open_im_sdk.FriendInfo(FriendUser) != imdb.Friend(FriendUserID)
// table = ` CREATE TABLE IF NOT EXISTS friends(
// owner_user_id CHAR (64) NOT NULL,
// friend_user_id CHAR (64) NOT NULL ,
// name varchar(64) DEFAULT NULL ,
// face_url varchar(100) DEFAULT NULL ,
// remark varchar(255) DEFAULT NULL,
// gender int DEFAULT NULL ,
// phone_number varchar(32) DEFAULT NULL ,
// birth INTEGER DEFAULT NULL ,
// email varchar(64) DEFAULT NULL ,
// create_time INTEGER DEFAULT NULL ,
// add_source int DEFAULT NULL ,
// operator_user_id CHAR(64) DEFAULT NULL,
// ex varchar(1024) DEFAULT NULL,
// PRIMARY KEY (owner_user_id,friend_user_id)
// )`
type LocalFriend struct {
OwnerUserID string `gorm:"column:owner_user_id;primary_key;type:varchar(64)" json:"ownerUserID"`
FriendUserID string `gorm:"column:friend_user_id;primary_key;type:varchar(64)" json:"userID"`
Remark string `gorm:"column:remark;type:varchar(255)" json:"remark"`
CreateTime int64 `gorm:"column:create_time" json:"createTime"`
AddSource int32 `gorm:"column:add_source" json:"addSource"`
OperatorUserID string `gorm:"column:operator_user_id;type:varchar(64)" json:"operatorUserID"`
Nickname string `gorm:"column:name;type:varchar;type:varchar(255)" json:"nickname"`
FaceURL string `gorm:"column:face_url;type:varchar;type:varchar(255)" json:"faceURL"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
IsPinned bool `gorm:"column:is_pinned;" json:"isPinned"`
}
func (LocalFriend) TableName() string {
return "local_friends"
}
// message FriendRequest{
// string FromUserID = 1;
// string ToUserID = 2;
// int32 HandleResult = 3;
// string ReqMsg = 4;
// int64 CreateTime = 5;
// string HandlerUserID = 6;
// string HandleMsg = 7;
// int64 HandleTime = 8;
// string Ex = 9;
// }
// open_im_sdk.FriendRequest == imdb.FriendRequest
type LocalFriendRequest struct {
FromUserID string `gorm:"column:from_user_id;primary_key;type:varchar(64)" json:"fromUserID"`
FromNickname string `gorm:"column:from_nickname;type:varchar;type:varchar(255)" json:"fromNickname"`
FromFaceURL string `gorm:"column:from_face_url;type:varchar;type:varchar(255)" json:"fromFaceURL"`
// FromGender int32 `gorm:"column:from_gender" json:"fromGender"`
ToUserID string `gorm:"column:to_user_id;primary_key;type:varchar(64)" json:"toUserID"`
ToNickname string `gorm:"column:to_nickname;type:varchar;type:varchar(255)" json:"toNickname"`
ToFaceURL string `gorm:"column:to_face_url;type:varchar;type:varchar(255)" json:"toFaceURL"`
// ToGender int32 `gorm:"column:to_gender" json:"toGender"`
HandleResult int32 `gorm:"column:handle_result" json:"handleResult"`
ReqMsg string `gorm:"column:req_msg;type:varchar(255)" json:"reqMsg"`
CreateTime int64 `gorm:"column:create_time" json:"createTime"`
HandlerUserID string `gorm:"column:handler_user_id;type:varchar(64)" json:"handlerUserID"`
HandleMsg string `gorm:"column:handle_msg;type:varchar(255)" json:"handleMsg"`
HandleTime int64 `gorm:"column:handle_time" json:"handleTime"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
}
//message GroupInfo{
// string GroupID = 1;
// string GroupName = 2;
// string NotificationCmd = 3;
// string Introduction = 4;
// string FaceUrl = 5;
// string OwnerUserID = 6;
// uint32 MemberCount = 8;
// int64 CreateTime = 7;
// string Ex = 9;
// int32 Status = 10;
// string CreatorUserID = 11;
// int32 GroupType = 12;
//}
// open_im_sdk.GroupInfo (OwnerUserID , MemberCount )> imdb.Group
// group_id char(64) NOT NULL,
// name varchar(64) DEFAULT NULL ,
// introduction varchar(255) DEFAULT NULL,
// notification varchar(255) DEFAULT NULL,
// face_url varchar(100) DEFAULT NULL,
// group_type int DEFAULT NULL,
// status int DEFAULT NULL,
// creator_user_id char(64) DEFAULT NULL,
// create_time INTEGER DEFAULT NULL,
// ex varchar(1024) DEFAULT NULL,
// PRIMARY KEY (group_id)
// )`
type LocalGroup struct {
GroupID string `gorm:"column:group_id;primary_key;type:varchar(64)" json:"groupID" binding:"required"`
GroupName string `gorm:"column:name;size:255" json:"groupName"`
Notification string `gorm:"column:notification;type:varchar(255)" json:"notification"`
Introduction string `gorm:"column:introduction;type:varchar(255)" json:"introduction"`
FaceURL string `gorm:"column:face_url;type:varchar(255)" json:"faceURL"`
CreateTime int64 `gorm:"column:create_time" json:"createTime"`
Status int32 `gorm:"column:status" json:"status"`
CreatorUserID string `gorm:"column:creator_user_id;type:varchar(64)" json:"creatorUserID"`
GroupType int32 `gorm:"column:group_type" json:"groupType"`
OwnerUserID string `gorm:"column:owner_user_id;type:varchar(64)" json:"ownerUserID"`
MemberCount int32 `gorm:"column:member_count" json:"memberCount"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
NeedVerification int32 `gorm:"column:need_verification" json:"needVerification"`
LookMemberInfo int32 `gorm:"column:look_member_info" json:"lookMemberInfo"`
ApplyMemberFriend int32 `gorm:"column:apply_member_friend" json:"applyMemberFriend"`
NotificationUpdateTime int64 `gorm:"column:notification_update_time" json:"notificationUpdateTime"`
NotificationUserID string `gorm:"column:notification_user_id;size:64" json:"notificationUserID"`
}
func (LocalGroup) TableName() string {
return "local_groups"
}
//message GroupMemberFullInfo {
//string GroupID = 1 ;
//string UserID = 2 ;
//int32 roleLevel = 3;
//int64 JoinTime = 4;
//string NickName = 5;
//string FaceUrl = 6;
//int32 JoinSource = 8;
//string OperatorUserID = 9;
//string Ex = 10;
//int32 AppMangerLevel = 7; //if >0
//} open_im_sdk.GroupMemberFullInfo(AppMangerLevel) > imdb.GroupMember
// group_id char(64) NOT NULL,
// user_id char(64) NOT NULL,
// nickname varchar(64) DEFAULT NULL,
// user_group_face_url varchar(64) DEFAULT NULL,
// role_level int DEFAULT NULL,
// join_time INTEGER DEFAULT NULL,
// join_source int DEFAULT NULL,
// operator_user_id char(64) NOT NULL,
type LocalGroupMember struct {
GroupID string `gorm:"column:group_id;primary_key;type:varchar(64)" json:"groupID"`
UserID string `gorm:"column:user_id;primary_key;type:varchar(64)" json:"userID"`
Nickname string `gorm:"column:nickname;type:varchar(255)" json:"nickname"`
FaceURL string `gorm:"column:user_group_face_url;type:varchar(255)" json:"faceURL"`
RoleLevel int32 `gorm:"column:role_level;index:index_role_level;" json:"roleLevel"`
JoinTime int64 `gorm:"column:join_time;index:index_join_time;" json:"joinTime"`
JoinSource int32 `gorm:"column:join_source" json:"joinSource"`
InviterUserID string `gorm:"column:inviter_user_id;size:64" json:"inviterUserID"`
MuteEndTime int64 `gorm:"column:mute_end_time;default:0" json:"muteEndTime"`
OperatorUserID string `gorm:"column:operator_user_id;type:varchar(64)" json:"operatorUserID"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
}
func (LocalGroupMember) TableName() string {
return "local_group_members"
}
// message GroupRequest{
// string UserID = 1;
// string GroupID = 2;
// string HandleResult = 3;
// string ReqMsg = 4;
// string HandleMsg = 5;
// int64 ReqTime = 6;
// string HandleUserID = 7;
// int64 HandleTime = 8;
// string Ex = 9;
// }open_im_sdk.GroupRequest == imdb.GroupRequest
type LocalGroupRequest struct {
GroupID string `gorm:"column:group_id;primary_key;type:varchar(64)" json:"groupID"`
GroupName string `gorm:"column:group_name;size:255" json:"groupName"`
Notification string `gorm:"column:notification;type:varchar(255)" json:"notification"`
Introduction string `gorm:"column:introduction;type:varchar(255)" json:"introduction"`
GroupFaceURL string `gorm:"column:face_url;type:varchar(255)" json:"groupFaceURL"`
CreateTime int64 `gorm:"column:create_time" json:"createTime"`
Status int32 `gorm:"column:status" json:"status"`
CreatorUserID string `gorm:"column:creator_user_id;type:varchar(64)" json:"creatorUserID"`
GroupType int32 `gorm:"column:group_type" json:"groupType"`
OwnerUserID string `gorm:"column:owner_user_id;type:varchar(64)" json:"ownerUserID"`
MemberCount int32 `gorm:"column:member_count" json:"memberCount"`
UserID string `gorm:"column:user_id;primary_key;type:varchar(64)" json:"userID"`
Nickname string `gorm:"column:nickname;type:varchar(255)" json:"nickname"`
UserFaceURL string `gorm:"column:user_face_url;type:varchar(255)" json:"userFaceURL"`
// Gender int32 `gorm:"column:gender" json:"gender"`
HandleResult int32 `gorm:"column:handle_result" json:"handleResult"`
ReqMsg string `gorm:"column:req_msg;type:varchar(255)" json:"reqMsg"`
HandledMsg string `gorm:"column:handle_msg;type:varchar(255)" json:"handledMsg"`
ReqTime int64 `gorm:"column:req_time" json:"reqTime"`
HandleUserID string `gorm:"column:handle_user_id;type:varchar(64)" json:"handleUserID"`
HandledTime int64 `gorm:"column:handle_time" json:"handledTime"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
JoinSource int32 `gorm:"column:join_source" json:"joinSource"`
InviterUserID string `gorm:"column:inviter_user_id;size:64" json:"inviterUserID"`
}
// string UserID = 1;
// string Nickname = 2;
// string FaceUrl = 3;
// int32 Gender = 4;
// string PhoneNumber = 5;
// string Birth = 6;
// string Email = 7;
// string Ex = 8;
// int64 CreateTime = 9;
// int32 AppMangerLevel = 10;
// open_im_sdk.User == imdb.User
type LocalUser struct {
UserID string `gorm:"column:user_id;primary_key;type:varchar(64)" json:"userID"`
Nickname string `gorm:"column:name;type:varchar(255)" json:"nickname"`
FaceURL string `gorm:"column:face_url;type:varchar(255)" json:"faceURL"`
CreateTime int64 `gorm:"column:create_time" json:"createTime"`
AppMangerLevel int32 `gorm:"column:app_manger_level" json:"-"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
GlobalRecvMsgOpt int32 `gorm:"column:global_recv_msg_opt" json:"globalRecvMsgOpt"`
}
// message BlackInfo{
// string OwnerUserID = 1;
// int64 CreateTime = 2;
// PublicUserInfo BlackUserInfo = 4;
// int32 AddSource = 5;
// string OperatorUserID = 6;
// string Ex = 7;
// }
// open_im_sdk.BlackInfo(BlackUserInfo) != imdb.Black (BlockUserID)
type LocalBlack struct {
OwnerUserID string `gorm:"column:owner_user_id;primary_key;type:varchar(64)" json:"ownerUserID"`
BlockUserID string `gorm:"column:block_user_id;primary_key;type:varchar(64)" json:"userID"`
Nickname string `gorm:"column:nickname;type:varchar(255)" json:"nickname"`
FaceURL string `gorm:"column:face_url;type:varchar(255)" json:"faceURL"`
// Gender int32 `gorm:"column:gender" json:"gender"`
CreateTime int64 `gorm:"column:create_time" json:"createTime"`
AddSource int32 `gorm:"column:add_source" json:"addSource"`
OperatorUserID string `gorm:"column:operator_user_id;type:varchar(64)" json:"operatorUserID"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
}
type LocalSeqData struct {
UserID string `gorm:"column:user_id;primary_key;type:varchar(64)"`
Seq uint32 `gorm:"column:seq"`
}
type LocalSeq struct {
ID string `gorm:"column:id;primary_key;type:varchar(64)"`
MinSeq uint32 `gorm:"column:min_seq"`
}
// `create table if not exists chat_log (
//
// client_msg_id char(64) NOT NULL,
// server_msg_id char(64) DEFAULT NULL,
// send_id char(64) NOT NULL ,
// is_read int NOT NULL ,
// seq INTEGER DEFAULT NULL ,
// status int NOT NULL ,
// session_type int NOT NULL ,
// recv_id char(64) NOT NULL ,
// content_type int NOT NULL ,
// sender_face_url varchar(100) DEFAULT NULL,
// sender_nick_name varchar(64) DEFAULT NULL,
// msg_from int NOT NULL ,
// content varchar(1000) NOT NULL ,
// sender_platform_id int NOT NULL ,
// send_time INTEGER DEFAULT NULL ,
// create_time INTEGER DEFAULT NULL,
// ex varchar(1024) DEFAULT NULL,
// PRIMARY KEY (client_msg_id)
// )`
// 删除会话,可能会话没有
// 确认删除,告诉会话 ID
// 清空聊天记录的发,会话有,但是聊天记录没有
// DeleteMlessageFromlocalAndSvr
// db
// 不同的会话本地有一个单独的表,其中单聊的话也是这样,有一个单聊的表
// 删除的话,先删除表,在删除本地的 seq ,最后清楚这个表。
// 删除所有的消息的话,全部都是服务器来做,调用接口,然后客户端收到回调,然后删除本地的所有的信息。
// 删除一条信息,删除最新的话,会话上有一条最新的消息,删除这条消息,会话上就没有消息了,此时显示的是第二条。
// 和微信一样,我们 Go get error 分支,然后调用最新的 APi
type LocalChatLog struct {
ClientMsgID string `gorm:"column:client_msg_id;primary_key;type:char(64)" json:"clientMsgID"`
ServerMsgID string `gorm:"column:server_msg_id;type:char(64)" json:"serverMsgID"`
SendID string `gorm:"column:send_id;type:char(64)" json:"sendID"`
RecvID string `gorm:"column:recv_id;index:index_recv_id;type:char(64)" 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" json:"sessionType"`
MsgFrom int32 `gorm:"column:msg_from" json:"msgFrom"`
ContentType int32 `gorm:"column:content_type;index:content_type_alone" json:"contentType"`
Content string `gorm:"column:content;type:varchar(1000)" json:"content"`
IsRead bool `gorm:"column:is_read" json:"isRead"`
Status int32 `gorm:"column:status" json:"status"`
Seq int64 `gorm:"column:seq;index:index_seq;default:0" json:"seq"`
SendTime int64 `gorm:"column:send_time;index:index_send_time;" json:"sendTime"`
CreateTime int64 `gorm:"column:create_time" json:"createTime"`
AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
LocalEx string `gorm:"column:local_ex;type:varchar(1024)" json:"localEx"`
IsReact bool `gorm:"column:is_react" json:"isReact"`
IsExternalExtensions bool `gorm:"column:is_external_extensions" json:"isExternalExtensions"`
MsgFirstModifyTime int64 `gorm:"column:msg_first_modify_time" json:"msgFirstModifyTime"`
}
type LocalErrChatLog struct {
Seq int64 `gorm:"column:seq;primary_key" json:"seq"`
ClientMsgID string `gorm:"column:client_msg_id;type:char(64)" json:"clientMsgID"`
ServerMsgID string `gorm:"column:server_msg_id;type:char(64)" json:"serverMsgID"`
SendID string `gorm:"column:send_id;type:char(64)" json:"sendID"`
RecvID string `gorm:"column:recv_id;type:char(64)" 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" json:"sessionType"`
MsgFrom int32 `gorm:"column:msg_from" json:"msgFrom"`
ContentType int32 `gorm:"column:content_type" json:"contentType"`
Content string `gorm:"column:content;type:varchar(1000)" json:"content"`
IsRead bool `gorm:"column:is_read" json:"isRead"`
Status int32 `gorm:"column:status" json:"status"`
SendTime int64 `gorm:"column:send_time" json:"sendTime"`
CreateTime int64 `gorm:"column:create_time" json:"createTime"`
AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
}
type TempCacheLocalChatLog struct {
ClientMsgID string `gorm:"column:client_msg_id;primary_key;type:char(64)" json:"clientMsgID"`
ServerMsgID string `gorm:"column:server_msg_id;type:char(64)" json:"serverMsgID"`
SendID string `gorm:"column:send_id;type:char(64)" json:"sendID"`
RecvID string `gorm:"column:recv_id;type:char(64)" 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" json:"sessionType"`
MsgFrom int32 `gorm:"column:msg_from" json:"msgFrom"`
ContentType int32 `gorm:"column:content_type" json:"contentType"`
Content string `gorm:"column:content;type:varchar(1000)" json:"content"`
IsRead bool `gorm:"column:is_read" json:"isRead"`
Status int32 `gorm:"column:status" json:"status"`
Seq int64 `gorm:"column:seq;default:0" json:"seq"`
SendTime int64 `gorm:"column:send_time;" json:"sendTime"`
CreateTime int64 `gorm:"column:create_time" json:"createTime"`
AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
}
// `create table if not exists conversation (
//
// conversation_id char(128) NOT NULL,
// conversation_type int(11) NOT NULL,
// user_id varchar(128) DEFAULT NULL,
// group_id varchar(128) DEFAULT NULL,
// show_name varchar(128) NOT NULL,
// face_url varchar(128) NOT NULL,
// recv_msg_opt int(11) NOT NULL ,
// unread_count int(11) NOT NULL ,
// latest_msg varchar(255) NOT NULL ,
// latest_msg_send_time INTEGER(255) NOT NULL ,
// draft_text varchar(255) DEFAULT NULL ,
// draft_timestamp INTEGER(255) DEFAULT NULL ,
// is_pinned int(10) NOT NULL ,
// PRIMARY KEY (conversation_id)
//
// )
type LocalConversation struct {
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"`
ShowName string `gorm:"column:show_name;type:varchar(255)" json:"showName"`
FaceURL string `gorm:"column:face_url;type:varchar(255)" json:"faceURL"`
RecvMsgOpt int32 `gorm:"column:recv_msg_opt" json:"recvMsgOpt"`
UnreadCount int32 `gorm:"column:unread_count" json:"unreadCount"`
GroupAtType int32 `gorm:"column:group_at_type" json:"groupAtType"`
LatestMsg string `gorm:"column:latest_msg;type:varchar(1000)" json:"latestMsg"`
LatestMsgSendTime int64 `gorm:"column:latest_msg_send_time;index:index_latest_msg_send_time" json:"latestMsgSendTime"`
DraftText string `gorm:"column:draft_text" json:"draftText"`
DraftTextTime int64 `gorm:"column:draft_text_time" json:"draftTextTime"`
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"`
IsNotInGroup bool `gorm:"column:is_not_in_group" json:"isNotInGroup"`
UpdateUnreadCountTime int64 `gorm:"column:update_unread_count_time" json:"updateUnreadCountTime"`
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"`
HasReadSeq int64 `gorm:"column:has_read_seq" json:"hasReadSeq"`
MsgDestructTime int64 `gorm:"column:msg_destruct_time;default:604800" json:"msgDestructTime"`
IsMsgDestruct bool `gorm:"column:is_msg_destruct;default:false" json:"isMsgDestruct"`
}
type LocalConversationUnreadMessage struct {
ConversationID string `gorm:"column:conversation_id;primary_key;type:char(128)" json:"conversationID"`
ClientMsgID string `gorm:"column:client_msg_id;primary_key;type:char(64)" json:"clientMsgID"`
SendTime int64 `gorm:"column:send_time" json:"sendTime"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
}
// message GroupRequest{
// string UserID = 1;
// string GroupID = 2;
// string HandleResult = 3;
// string ReqMsg = 4;
// string HandleMsg = 5;
// int64 ReqTime = 6;
// string HandleUserID = 7;
// int64 HandleTime = 8;
// string Ex = 9;
// }open_im_sdk.GroupRequest == imdb.GroupRequest
type LocalAdminGroupRequest struct {
LocalGroupRequest
}
type LocalChatLogReactionExtensions struct {
ClientMsgID string `gorm:"column:client_msg_id;primary_key;type:char(64)" json:"clientMsgID"`
LocalReactionExtensions []byte `gorm:"column:local_reaction_extensions" json:"localReactionExtensions"`
}
type LocalWorkMomentsNotification struct {
JsonDetail string `gorm:"column:json_detail"`
CreateTime int64 `gorm:"create_time"`
}
type WorkMomentNotificationMsg struct {
NotificationMsgType int32 `json:"notificationMsgType"`
ReplyUserName string `json:"replyUserName"`
ReplyUserID string `json:"replyUserID"`
Content string `json:"content"`
ContentID string `json:"contentID"`
WorkMomentID string `json:"workMomentID"`
UserID string `json:"userID"`
UserName string `json:"userName"`
FaceURL string `json:"faceURL"`
WorkMomentContent string `json:"workMomentContent"`
CreateTime int32 `json:"createTime"`
}
func (LocalWorkMomentsNotification) TableName() string {
return "local_work_moments_notification"
}
type LocalWorkMomentsNotificationUnreadCount struct {
UnreadCount int `gorm:"unread_count" json:"unreadCount"`
}
func (LocalWorkMomentsNotificationUnreadCount) TableName() string {
return "local_work_moments_notification_unread_count"
}
type NotificationSeqs struct {
ConversationID string `gorm:"column:conversation_id;primary_key;type:char(128)" json:"conversationID"`
Seq int64 `gorm:"column:seq" json:"seq"`
}
func (NotificationSeqs) TableName() string {
return "local_notification_seqs"
}
type LocalUpload struct {
PartHash string `gorm:"column:part_hash;primary_key" json:"partHash"`
UploadID string `gorm:"column:upload_id;type:varchar(1000)" json:"uploadID"`
UploadInfo string `gorm:"column:upload_info;type:varchar(2000)" json:"uploadInfo"`
ExpireTime int64 `gorm:"column:expire_time" json:"expireTime"`
CreateTime int64 `gorm:"column:create_time" json:"createTime"`
}
func (LocalUpload) TableName() string {
return "local_uploads"
}
type LocalStranger struct {
UserID string `gorm:"column:user_id;primary_key;type:varchar(64)" json:"userID"`
Nickname string `gorm:"column:name;type:varchar(255)" json:"nickname"`
FaceURL string `gorm:"column:face_url;type:varchar(255)" json:"faceURL"`
CreateTime int64 `gorm:"column:create_time" json:"createTime"`
AppMangerLevel int32 `gorm:"column:app_manger_level" json:"-"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
AttachedInfo string `gorm:"column:attached_info;type:varchar(1024)" json:"attachedInfo"`
GlobalRecvMsgOpt int32 `gorm:"column:global_recv_msg_opt" json:"globalRecvMsgOpt"`
}
func (LocalStranger) TableName() string {
return "local_stranger"
}
type LocalSendingMessages struct {
ConversationID string `gorm:"column:conversation_id;primary_key;type:char(128)" json:"conversationID"`
ClientMsgID string `gorm:"column:client_msg_id;primary_key;type:char(64)" json:"clientMsgID"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
}
func (LocalSendingMessages) TableName() string {
return "local_sending_messages"
}
type LocalUserCommand struct {
UserID string `gorm:"column:user_id;type:char(128);primary_key" json:"userID"`
Type int32 `gorm:"column:type;primary_key" json:"type"`
Uuid string `gorm:"column:uuid;type:varchar(255);primary_key" json:"uuid"`
CreateTime int64 `gorm:"column:create_time" json:"createTime"`
Value string `gorm:"column:value;type:varchar(255)" json:"value"`
Ex string `gorm:"column:ex;type:varchar(1024)" json:"ex"`
}
func (LocalUserCommand) TableName() string {
return "local_user_command"
}
type StringArray []string
func (a StringArray) Value() (driver.Value, error) {
return json.Marshal(a)
}
func (a *StringArray) Scan(value interface{}) error {
b, ok := value.([]byte)
if !ok {
return errs.New("type assertion to []byte failed").Wrap()
}
return json.Unmarshal(b, &a)
}
type LocalVersionSync struct {
Table string `gorm:"column:table;type:varchar(255);primary_key" json:"table"`
EntityID string `gorm:"column:entity_id;type:varchar(255);primary_key" json:"entityID"`
VersionID string `gorm:"column:version_id" json:"versionID"`
Version uint64 `gorm:"column:version" json:"version"`
CreateTime int64 `gorm:"column:create_time" json:"createTime"`
UIDList StringArray `gorm:"column:id_list;type:text" json:"uidList"`
}
func (LocalVersionSync) TableName() string {
return "local_sync_version"
}
type LocalAppSDKVersion struct {
Version string `gorm:"column:version;type:varchar(255);primary_key" json:"version"`
}
func (LocalAppSDKVersion) TableName() string {
return "local_app_sdk_version"
}

View File

@@ -0,0 +1,44 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
)
func (d *DataBase) SetNotificationSeq(ctx context.Context, conversationID string, seq int64) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
cursor := d.conn.WithContext(ctx).Model(&model_struct.NotificationSeqs{}).Where("conversation_id = ?", conversationID).Updates(map[string]interface{}{"seq": seq})
if cursor.Error != nil {
return utils.Wrap(cursor.Error, "Updates failed")
}
if cursor.RowsAffected == 0 {
return utils.Wrap(d.conn.WithContext(ctx).Create(&model_struct.NotificationSeqs{ConversationID: conversationID, Seq: seq}).Error, "Create failed")
}
return nil
}
func (d *DataBase) GetNotificationAllSeqs(ctx context.Context) ([]*model_struct.NotificationSeqs, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var seqs []*model_struct.NotificationSeqs
return seqs, utils.Wrap(d.conn.WithContext(ctx).Where("1=1").Find(&seqs).Error, "GetNotificationAllSeqs failed")
}

View File

@@ -0,0 +1,43 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
)
func (d *DataBase) InsertSendingMessage(ctx context.Context, message *model_struct.LocalSendingMessages) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Create(message).Error, "InsertSendingMessage failed")
}
func (d *DataBase) DeleteSendingMessage(ctx context.Context, conversationID, clientMsgID string) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
localSendingMessage := model_struct.LocalSendingMessages{ConversationID: conversationID, ClientMsgID: clientMsgID}
return utils.Wrap(d.conn.WithContext(ctx).Delete(&localSendingMessage).Error, "DeleteSendingMessage failed")
}
func (d *DataBase) GetAllSendingMessages(ctx context.Context) (friendRequests []*model_struct.LocalSendingMessages, err error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
err = utils.Wrap(d.conn.WithContext(ctx).Find(&friendRequests).Error, "GetAllSendingMessages failed")
return friendRequests, utils.Wrap(err, "GetAllSendingMessages failed")
}

View File

@@ -0,0 +1,47 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
)
func (d *DataBase) GetMinSeq(ctx context.Context, ID string) (uint32, error) {
var seqData model_struct.LocalSeq
return seqData.MinSeq, utils.Wrap(d.conn.WithContext(ctx).First(&seqData).Error, "GetMinSeq failed")
}
func (d *DataBase) SetMinSeq(ctx context.Context, ID string, minSeq uint32) error {
seqData := model_struct.LocalSeq{ID: ID, MinSeq: minSeq}
t := d.conn.WithContext(ctx).Updates(&seqData)
if t.RowsAffected == 0 {
return utils.Wrap(d.conn.WithContext(ctx).Create(seqData).Error, "Updates failed")
} else {
return utils.Wrap(t.Error, "SetMinSeq failed")
}
}
func (d *DataBase) GetUserMinSeq(ctx context.Context) (uint32, error) {
return 0, nil
}
func (d *DataBase) GetGroupMinSeq(ctx context.Context, groupID string) (uint32, error) {
return 0, nil
}

View File

@@ -0,0 +1,58 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"gorm.io/gorm"
)
func (d *DataBase) GetStrangerInfo(ctx context.Context, userIDs []string) ([]*model_struct.LocalStranger, error) {
d.friendMtx.Lock()
defer d.friendMtx.Unlock()
var friendList []model_struct.LocalStranger
err := utils.Wrap(d.conn.WithContext(ctx).Where("user_id IN ?", userIDs).Find(&friendList).Error, "GetFriendInfoListByFriendUserID failed")
var transfer []*model_struct.LocalStranger
for _, v := range friendList {
v1 := v
transfer = append(transfer, &v1)
}
return transfer, err
}
func (d *DataBase) SetStrangerInfo(ctx context.Context, localStrangerList []*model_struct.LocalStranger) error {
//TODO Can be optimized into two chan batch update or insert operations
for _, existingData := range localStrangerList {
result := d.conn.First(&existingData, "user_id = ?", existingData.UserID)
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
// Data does not exist, perform insert operation
err := d.conn.Create(&existingData).Error
return err
} else if result.Error != nil {
return result.Error
}
err := d.conn.Save(&existingData).Error
if err != nil {
return err
}
}
return nil
}

View File

@@ -0,0 +1,423 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"fmt"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"github.com/openimsdk/openim-sdk-core/v3/sdk_struct"
"gorm.io/gorm"
)
func (d *DataBase) initSuperLocalChatLog(ctx context.Context, groupID string) {
if !d.conn.WithContext(ctx).Migrator().HasTable(utils.GetConversationTableName(groupID)) {
d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).AutoMigrate(&model_struct.LocalChatLog{})
}
}
func (d *DataBase) SuperGroupBatchInsertMessageList(ctx context.Context, MessageList []*model_struct.LocalChatLog, groupID string) error {
if MessageList == nil {
return nil
}
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Create(MessageList).Error, "SuperGroupBatchInsertMessageList failed")
}
func (d *DataBase) SuperGroupInsertMessage(ctx context.Context, Message *model_struct.LocalChatLog, groupID string) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Create(Message).Error, "SuperGroupInsertMessage failed")
}
func (d *DataBase) SuperGroupDeleteAllMessage(ctx context.Context, groupID string) error {
return utils.Wrap(d.conn.WithContext(ctx).Session(&gorm.Session{AllowGlobalUpdate: true}).Table(utils.GetConversationTableName(groupID)).Delete(&model_struct.LocalChatLog{}).Error, "SuperGroupDeleteAllMessage failed")
}
func (d *DataBase) SuperGroupSearchMessageByKeyword(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var messageList []model_struct.LocalChatLog
var condition string
var subCondition string
if keywordListMatchType == constant.KeywordMatchOr {
for i := 0; i < len(keywordList); i++ {
if i == 0 {
subCondition += "And ("
}
if i+1 >= len(keywordList) {
subCondition += "content like " + "'%" + keywordList[i] + "%') "
} else {
subCondition += "content like " + "'%" + keywordList[i] + "%' " + "or "
}
}
} else {
for i := 0; i < len(keywordList); i++ {
if i == 0 {
subCondition += "And ("
}
if i+1 >= len(keywordList) {
subCondition += "content like " + "'%" + keywordList[i] + "%') "
} else {
subCondition += "content like " + "'%" + keywordList[i] + "%' " + "and "
}
}
}
condition = fmt.Sprintf("recv_id=%q And send_time between %d and %d AND status <=%d And content_type IN ? ", sourceID, startTime, endTime, constant.MsgStatusSendFailed)
condition += subCondition
err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(sourceID)).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&messageList).Error, "InsertMessage failed")
for _, v := range messageList {
v1 := v
result = append(result, &v1)
}
return result, err
}
func (d *DataBase) SuperGroupSearchAllMessageByContentType(ctx context.Context, groupID string, contentType int32) (result []*model_struct.LocalChatLog, err error) {
err = d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where("content_type = ?", contentType).Find(&result).Error
return result, err
}
func (d *DataBase) SuperGroupSearchMessageByContentType(ctx context.Context, contentType []int, sourceID string, startTime, endTime int64, sessionType, offset, count int) (result []*model_struct.LocalChatLog, err error) {
var messageList []model_struct.LocalChatLog
var condition string
condition = fmt.Sprintf("session_type=%d And recv_id==%q And send_time between %d and %d AND status <=%d And content_type IN ?", sessionType, sourceID, startTime, endTime, constant.MsgStatusSendFailed)
err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(sourceID)).Where(condition, contentType).Order("send_time DESC").Offset(offset).Limit(count).Find(&messageList).Error, "SearchMessage failed")
for _, v := range messageList {
v1 := v
result = append(result, &v1)
}
return result, err
}
func (d *DataBase) SuperGroupSearchMessageByContentTypeAndKeyword(ctx context.Context, contentType []int, keywordList []string, keywordListMatchType int, startTime, endTime int64, groupID string) (result []*model_struct.LocalChatLog, err error) {
var messageList []model_struct.LocalChatLog
var condition string
var subCondition string
if keywordListMatchType == constant.KeywordMatchOr {
for i := 0; i < len(keywordList); i++ {
if i == 0 {
subCondition += "And ("
}
if i+1 >= len(keywordList) {
subCondition += "content like " + "'%" + keywordList[i] + "%') "
} else {
subCondition += "content like " + "'%" + keywordList[i] + "%' " + "or "
}
}
} else {
for i := 0; i < len(keywordList); i++ {
if i == 0 {
subCondition += "And ("
}
if i+1 >= len(keywordList) {
subCondition += "content like " + "'%" + keywordList[i] + "%') "
} else {
subCondition += "content like " + "'%" + keywordList[i] + "%' " + "and "
}
}
}
condition = fmt.Sprintf("send_time between %d and %d AND status <=%d And content_type IN ? ", startTime, endTime, constant.MsgStatusSendFailed)
condition += subCondition
err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where(condition, contentType).Order("send_time DESC").Find(&messageList).Error, "SearchMessage failed")
for _, v := range messageList {
v1 := v
result = append(result, &v1)
}
return result, err
}
func (d *DataBase) SuperGroupBatchUpdateMessageList(ctx context.Context, MessageList []*model_struct.LocalChatLog) error {
if MessageList == nil {
return nil
}
for _, v := range MessageList {
v1 := new(model_struct.LocalChatLog)
v1.ClientMsgID = v.ClientMsgID
v1.Seq = v.Seq
v1.Status = v.Status
err := d.SuperGroupUpdateMessage(ctx, v1)
if err != nil {
return utils.Wrap(err, "BatchUpdateMessageList failed")
}
}
return nil
}
func (d *DataBase) SuperGroupMessageIfExists(ctx context.Context, ClientMsgID string) (bool, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var count int64
t := d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Where("client_msg_id = ?",
ClientMsgID).Count(&count)
if t.Error != nil {
return false, utils.Wrap(t.Error, "MessageIfExists get failed")
}
if count != 1 {
return false, nil
} else {
return true, nil
}
}
func (d *DataBase) SuperGroupIsExistsInErrChatLogBySeq(ctx context.Context, seq int64) bool {
return true
}
func (d *DataBase) SuperGroupMessageIfExistsBySeq(ctx context.Context, seq int64) (bool, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var count int64
t := d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Where("seq = ?",
seq).Count(&count)
if t.Error != nil {
return false, utils.Wrap(t.Error, "MessageIfExistsBySeq get failed")
}
if count != 1 {
return false, nil
} else {
return true, nil
}
}
func (d *DataBase) SuperGroupGetMessage(ctx context.Context, msg *sdk_struct.MsgStruct) (*model_struct.LocalChatLog, error) {
d.initSuperLocalChatLog(ctx, msg.GroupID)
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var c model_struct.LocalChatLog
return &c, utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(msg.GroupID)).Where("client_msg_id = ?",
msg.ClientMsgID).Take(&c).Error, "GetMessage failed")
}
func (d *DataBase) SuperGroupGetAllUnDeleteMessageSeqList(ctx context.Context) ([]uint32, error) {
var seqList []uint32
return seqList, utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Where("status != 4").Select("seq").Find(&seqList).Error, "")
}
func (d *DataBase) SuperGroupUpdateColumnsMessage(ctx context.Context, ClientMsgID, groupID string, args map[string]interface{}) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where(
"client_msg_id = ? ", ClientMsgID).Updates(args)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "UpdateColumnsConversation failed")
}
func (d *DataBase) SuperGroupUpdateMessage(ctx context.Context, c *model_struct.LocalChatLog) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(c.RecvID)).Updates(c)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "UpdateMessage failed")
}
func (d *DataBase) SuperGroupUpdateSpecificContentTypeMessage(ctx context.Context, contentType int, groupID string, args map[string]interface{}) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where("content_type = ?", contentType).Updates(args)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "UpdateMessage failed")
}
//funcation (d *DataBase) SuperGroupDeleteAllMessage(ctx context.Context, ) error {
// d.mRWMutex.Lock()
// defer d.mRWMutex.Unlock()
// err := d.conn.WithContext(ctx).Model(&model_struct.LocalChatLog{}).Exec("update local_chat_logs set status = ?,content = ? ", constant.MsgStatusHasDeleted, "").Error
// return utils.Wrap(err, "delete all message error")
//}
func (d *DataBase) SuperGroupUpdateMessageStatusBySourceID(ctx context.Context, sourceID string, status, sessionType int32) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var condition string
if sourceID == d.loginUserID && sessionType == constant.SingleChatType {
condition = "send_id=? And recv_id=? AND session_type=?"
} else {
condition = "(send_id=? or recv_id=?)AND session_type=?"
}
t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(sourceID)).Where(condition, sourceID, sourceID, sessionType).Updates(model_struct.LocalChatLog{Status: status})
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "UpdateMessageStatusBySourceID failed")
}
func (d *DataBase) SuperGroupUpdateMessageTimeAndStatus(ctx context.Context, msg *sdk_struct.MsgStruct) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(msg.GroupID)).Where("client_msg_id=? And seq=?", msg.ClientMsgID, 0).Updates(model_struct.LocalChatLog{Status: msg.Status, SendTime: msg.SendTime, ServerMsgID: msg.ServerMsgID})
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "SuperGroupUpdateMessageTimeAndStatus failed")
}
func (d *DataBase) SuperGroupGetMessageList(ctx context.Context, sourceID string, sessionType, count int, startTime int64, isReverse bool) (result []*model_struct.LocalChatLog, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var messageList []model_struct.LocalChatLog
var condition, timeOrder, timeSymbol string
if isReverse {
timeOrder = "send_time ASC"
timeSymbol = ">"
} else {
timeOrder = "send_time DESC"
timeSymbol = "<"
}
condition = " recv_id = ? AND status <=? And session_type = ? And send_time " + timeSymbol + " ?"
err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(sourceID)).Where(condition, sourceID, constant.MsgStatusSendFailed, sessionType, startTime).
Order(timeOrder).Offset(0).Limit(count).Find(&messageList).Error, "GetMessageList failed")
for _, v := range messageList {
v1 := v
result = append(result, &v1)
}
return result, err
}
func (d *DataBase) SuperGroupGetMessageListNoTime(ctx context.Context, sourceID string, sessionType, count int, isReverse bool) (result []*model_struct.LocalChatLog, err error) {
d.initSuperLocalChatLog(ctx, sourceID)
var messageList []model_struct.LocalChatLog
var condition, timeOrder string
if isReverse {
timeOrder = "send_time ASC"
} else {
timeOrder = "send_time DESC"
}
condition = "recv_id = ? AND status <=? And session_type = ? "
err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(sourceID)).Where(condition, sourceID, constant.MsgStatusSendFailed, sessionType).
Order(timeOrder).Offset(0).Limit(count).Find(&messageList).Error, "GetMessageList failed")
for _, v := range messageList {
v1 := v
result = append(result, &v1)
}
return result, err
}
func (d *DataBase) SuperGroupGetSendingMessageList(ctx context.Context, groupID string) (result []*model_struct.LocalChatLog, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var messageList []model_struct.LocalChatLog
err = utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where("status = ?", constant.MsgStatusSending).Find(&messageList).Error, "GetMessageList failed")
for _, v := range messageList {
v1 := v
result = append(result, &v1)
}
return result, err
}
func (d *DataBase) SuperGroupUpdateGroupMessageHasRead(ctx context.Context, msgIDList []string, groupID string) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where(" client_msg_id in ?", msgIDList).Update("is_read", constant.HasRead)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "UpdateMessageStatusBySourceID failed")
}
func (d *DataBase) SuperGroupUpdateGroupMessageFields(ctx context.Context, msgIDList []string, groupID string, args map[string]interface{}) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
t := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where(" client_msg_id in ?", msgIDList).Updates(args)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "UpdateMessageStatusBySourceID failed")
}
func (d *DataBase) SuperGroupGetNormalMsgSeq(ctx context.Context) (int64, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var seq int64
err := d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("IFNULL(max(seq),0)").Find(&seq).Error
return seq, utils.Wrap(err, "GetNormalMsgSeq")
}
func (d *DataBase) SuperGroupGetNormalMinSeq(ctx context.Context, groupID string) (int64, error) {
var seq int64
err := d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Select("IFNULL(min(seq),0)").Where("seq >?", 0).Find(&seq).Error
return seq, utils.Wrap(err, "SuperGroupGetNormalMinSeq")
}
func (d *DataBase) SuperGroupGetTestMessage(ctx context.Context, seq int64) (*model_struct.LocalChatLog, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var c model_struct.LocalChatLog
return &c, utils.Wrap(d.conn.WithContext(ctx).Where("seq = ?",
seq).Find(&c).Error, "GetTestMessage failed")
}
func (d *DataBase) SuperGroupUpdateMsgSenderNickname(ctx context.Context, sendID, nickname string, sType int) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where(
"send_id = ? and session_type = ? and sender_nick_name != ? ", sendID, sType, nickname).Updates(
map[string]interface{}{"sender_nick_name": nickname}).Error, utils.GetSelfFuncName()+" failed")
}
func (d *DataBase) SuperGroupUpdateMsgSenderFaceURL(ctx context.Context, sendID, faceURL string, sType int) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Where(
"send_id = ? and session_type = ? and sender_face_url != ? ", sendID, sType, faceURL).Updates(
map[string]interface{}{"sender_face_url": faceURL}).Error, utils.GetSelfFuncName()+" failed")
}
func (d *DataBase) SuperGroupUpdateMsgSenderFaceURLAndSenderNickname(ctx context.Context, sendID, faceURL, nickname string, sessionType int, groupID string) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Where(
"send_id = ? and session_type = ?", sendID, sessionType).Updates(
map[string]interface{}{"sender_face_url": faceURL, "sender_nick_name": nickname}).Error, utils.GetSelfFuncName()+" failed")
}
func (d *DataBase) SuperGroupGetMsgSeqByClientMsgID(ctx context.Context, clientMsgID string, groupID string) (uint32, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var seq uint32
err := utils.Wrap(d.conn.WithContext(ctx).Table(utils.GetConversationTableName(groupID)).Select("seq").Where("client_msg_id=?", clientMsgID).Take(&seq).Error, utils.GetSelfFuncName()+" failed")
return seq, err
}
func (d *DataBase) SuperGroupGetMsgSeqListByGroupID(ctx context.Context, groupID string) ([]uint32, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var seqList []uint32
err := utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=?", groupID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed")
return seqList, err
}
func (d *DataBase) SuperGroupGetMsgSeqListByPeerUserID(ctx context.Context, userID string) ([]uint32, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var seqList []uint32
err := utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=? or send_id=?", userID, userID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed")
return seqList, err
}
func (d *DataBase) SuperGroupGetMsgSeqListBySelfUserID(ctx context.Context, userID string) ([]uint32, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var seqList []uint32
err := utils.Wrap(d.conn.WithContext(ctx).Model(model_struct.LocalChatLog{}).Select("seq").Where("recv_id=? and send_id=?", userID, userID).Find(&seqList).Error, utils.GetSelfFuncName()+" failed")
return seqList, err
}

View File

@@ -0,0 +1,63 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
)
func (d *DataBase) InsertSuperGroup(ctx context.Context, groupInfo *model_struct.LocalGroup) error {
d.superGroupMtx.Lock()
defer d.superGroupMtx.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Table(constant.SuperGroupTableName).Create(groupInfo).Error, "InsertSuperGroup failed")
}
func (d *DataBase) DeleteAllSuperGroup(ctx context.Context) error {
d.superGroupMtx.Lock()
defer d.superGroupMtx.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Table(constant.SuperGroupTableName).Delete(&model_struct.LocalGroup{}).Error, "DeleteAllSuperGroup failed")
}
func (d *DataBase) GetSuperGroupInfoByGroupID(ctx context.Context, groupID string) (*model_struct.LocalGroup, error) {
d.superGroupMtx.Lock()
defer d.superGroupMtx.Unlock()
var g model_struct.LocalGroup
return &g, utils.Wrap(d.conn.WithContext(ctx).Table(constant.SuperGroupTableName).Where("group_id = ?", groupID).Take(&g).Error, "GetGroupList failed")
}
func (d *DataBase) UpdateSuperGroup(ctx context.Context, groupInfo *model_struct.LocalGroup) error {
d.superGroupMtx.Lock()
defer d.superGroupMtx.Unlock()
t := d.conn.WithContext(ctx).Table(constant.SuperGroupTableName).Select("*").Updates(*groupInfo)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "")
}
func (d *DataBase) DeleteSuperGroup(ctx context.Context, groupID string) error {
d.superGroupMtx.Lock()
defer d.superGroupMtx.Unlock()
localGroup := model_struct.LocalGroup{GroupID: groupID}
return utils.Wrap(d.conn.WithContext(ctx).Table(constant.SuperGroupTableName).Delete(&localGroup).Error, "DeleteSuperGroup failed")
}

View File

@@ -0,0 +1,36 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
)
func (d *DataBase) BatchInsertTempCacheMessageList(ctx context.Context, MessageList []*model_struct.TempCacheLocalChatLog) error {
if MessageList == nil {
return nil
}
return utils.Wrap(d.conn.WithContext(ctx).Create(MessageList).Error, "BatchInsertTempCacheMessageList failed")
}
func (d *DataBase) InsertTempCacheMessage(ctx context.Context, Message *model_struct.TempCacheLocalChatLog) error {
return utils.Wrap(d.conn.WithContext(ctx).Create(Message).Error, "InsertTempCacheMessage failed")
}

View File

@@ -0,0 +1,75 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"time"
"github.com/openimsdk/tools/errs"
)
func (d *DataBase) GetUpload(ctx context.Context, partHash string) (*model_struct.LocalUpload, error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var upload model_struct.LocalUpload
err := d.conn.WithContext(ctx).Where("part_hash = ?", partHash).Take(&upload).Error
if err != nil {
return nil, errs.Wrap(err)
}
return &upload, nil
}
func (d *DataBase) InsertUpload(ctx context.Context, upload *model_struct.LocalUpload) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return errs.Wrap(d.conn.WithContext(ctx).Create(upload).Error)
}
func (d *DataBase) deleteUpload(ctx context.Context, partHash string) error {
return errs.Wrap(d.conn.WithContext(ctx).Where("part_hash = ?", partHash).Delete(&model_struct.LocalUpload{}).Error)
}
func (d *DataBase) UpdateUpload(ctx context.Context, upload *model_struct.LocalUpload) error {
d.groupMtx.Lock()
defer d.groupMtx.Unlock()
return errs.Wrap(d.conn.WithContext(ctx).Updates(upload).Error)
}
func (d *DataBase) DeleteUpload(ctx context.Context, partHash string) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return d.deleteUpload(ctx, partHash)
}
func (d *DataBase) DeleteExpireUpload(ctx context.Context) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
var uploads []*model_struct.LocalUpload
err := d.conn.WithContext(ctx).Where("expire_time <= ?", time.Now().UnixMilli()).Find(&uploads).Error
if err != nil {
return errs.Wrap(err)
}
for _, upload := range uploads {
if err := d.deleteUpload(ctx, upload.PartHash); err != nil {
return err
}
}
return nil
}

View File

@@ -0,0 +1,74 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"github.com/pkg/errors"
)
// ProcessUserCommandAdd adds a new user command to the database.
func (d *DataBase) ProcessUserCommandAdd(ctx context.Context, command *model_struct.LocalUserCommand) error {
d.userMtx.Lock()
defer d.userMtx.Unlock()
userCommand := model_struct.LocalUserCommand{
UserID: command.UserID,
CreateTime: command.CreateTime,
Type: command.Type,
Uuid: command.Uuid,
Value: command.Value,
Ex: command.Ex,
}
return utils.Wrap(d.conn.WithContext(ctx).Create(&userCommand).Error, "ProcessUserCommandAdd failed")
}
// ProcessUserCommandUpdate updates an existing user command in the database.
func (d *DataBase) ProcessUserCommandUpdate(ctx context.Context, command *model_struct.LocalUserCommand) error {
d.userMtx.Lock()
defer d.userMtx.Unlock()
t := d.conn.WithContext(ctx).Model(command).Select("*").Updates(*command)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "")
}
// ProcessUserCommandDelete deletes a user command from the database.
func (d *DataBase) ProcessUserCommandDelete(ctx context.Context, command *model_struct.LocalUserCommand) error {
d.userMtx.Lock()
defer d.userMtx.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Where("type = ? AND uuid = ?", command.Type, command.Uuid).Delete(&model_struct.LocalUserCommand{}).Error,
"ProcessUserCommandDelete failed")
}
// ProcessUserCommandGetAll retrieves user commands from the database.
func (d *DataBase) ProcessUserCommandGetAll(ctx context.Context) ([]*model_struct.LocalUserCommand, error) {
d.userMtx.RLock()
defer d.userMtx.RUnlock()
var commands []*model_struct.LocalUserCommand
err := d.conn.WithContext(ctx).Find(&commands).Error
return commands, utils.Wrap(err, "ProcessUserCommandGetAll failed")
}

View File

@@ -0,0 +1,56 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
)
func (d *DataBase) GetLoginUser(ctx context.Context, userID string) (*model_struct.LocalUser, error) {
d.userMtx.RLock()
defer d.userMtx.RUnlock()
var user model_struct.LocalUser
return &user, utils.Wrap(d.conn.WithContext(ctx).Where("user_id = ? ", userID).Take(&user).Error, "GetLoginUserInfo failed")
}
func (d *DataBase) UpdateLoginUser(ctx context.Context, user *model_struct.LocalUser) error {
d.userMtx.Lock()
defer d.userMtx.Unlock()
t := d.conn.WithContext(ctx).Model(user).Select("*").Updates(user)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "UpdateLoginUser failed")
}
func (d *DataBase) UpdateLoginUserByMap(ctx context.Context, user *model_struct.LocalUser, args map[string]interface{}) error {
d.userMtx.Lock()
defer d.userMtx.Unlock()
t := d.conn.WithContext(ctx).Model(&user).Updates(args)
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "UpdateColumnsConversation failed")
}
func (d *DataBase) InsertLoginUser(ctx context.Context, user *model_struct.LocalUser) error {
d.userMtx.Lock()
defer d.userMtx.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Create(user).Error, "InsertLoginUser failed")
}

View File

@@ -0,0 +1,45 @@
package db
import (
"context"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/tools/errs"
"gorm.io/gorm"
)
func (d *DataBase) GetVersionSync(ctx context.Context, tableName, entityID string) (*model_struct.LocalVersionSync, error) {
d.versionMtx.RLock()
defer d.versionMtx.RUnlock()
var res model_struct.LocalVersionSync
return &res, errs.Wrap(d.conn.WithContext(ctx).Where("`table` = ? and `entity_id` = ?", tableName, entityID).Take(&res).Error)
}
func (d *DataBase) SetVersionSync(ctx context.Context, lv *model_struct.LocalVersionSync) error {
d.versionMtx.Lock()
defer d.versionMtx.Unlock()
var existing model_struct.LocalVersionSync
err := d.conn.WithContext(ctx).Where("`table` = ? AND `entity_id` = ?", lv.Table, lv.EntityID).First(&existing).Error
if err == gorm.ErrRecordNotFound {
if createErr := d.conn.WithContext(ctx).Create(lv).Error; createErr != nil {
return errs.Wrap(createErr)
}
return nil
} else if err != nil {
return errs.Wrap(err)
}
if updateErr := d.conn.WithContext(ctx).Model(&existing).Updates(lv).Error; updateErr != nil {
return errs.Wrap(updateErr)
}
return nil
}
func (d *DataBase) DeleteVersionSync(ctx context.Context, tableName, entityID string) error {
d.versionMtx.Lock()
defer d.versionMtx.Unlock()
localVersionSync := model_struct.LocalVersionSync{Table: tableName, EntityID: entityID}
return errs.WrapMsg(d.conn.WithContext(ctx).Delete(&localVersionSync).Error, "DeleteVersionSync failed")
}

View File

@@ -0,0 +1,96 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"errors"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"gorm.io/gorm"
"time"
)
func (d *DataBase) InsertWorkMomentsNotification(ctx context.Context, jsonDetail string) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
workMomentsNotification := model_struct.LocalWorkMomentsNotification{
JsonDetail: jsonDetail,
CreateTime: time.Now().Unix(),
}
return utils.Wrap(d.conn.WithContext(ctx).Create(workMomentsNotification).Error, "")
}
func (d *DataBase) GetWorkMomentsNotification(ctx context.Context, offset, count int) (WorkMomentsNotifications []*model_struct.LocalWorkMomentsNotification, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
WorkMomentsNotifications = []*model_struct.LocalWorkMomentsNotification{}
err = utils.Wrap(d.conn.WithContext(ctx).Table("local_work_moments_notification").Order("create_time DESC").Offset(offset).Limit(count).Find(&WorkMomentsNotifications).Error, "")
return WorkMomentsNotifications, err
}
func (d *DataBase) GetWorkMomentsNotificationLimit(ctx context.Context, pageNumber, showNumber int) (WorkMomentsNotifications []*model_struct.LocalWorkMomentsNotification, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
WorkMomentsNotifications = []*model_struct.LocalWorkMomentsNotification{}
err = utils.Wrap(d.conn.WithContext(ctx).Table("local_work_moments_notification").Select("json_detail").Find(WorkMomentsNotifications).Error, "")
return WorkMomentsNotifications, err
}
func (d *DataBase) InitWorkMomentsNotificationUnreadCount(ctx context.Context) error {
var n int64
err := utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalWorkMomentsNotificationUnreadCount{}).Count(&n).Error, "")
if err == nil {
if n == 0 {
c := model_struct.LocalWorkMomentsNotificationUnreadCount{UnreadCount: 0}
return utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalWorkMomentsNotificationUnreadCount{}).Create(c).Error, "IncrConversationUnreadCount failed")
}
}
return err
}
func (d *DataBase) IncrWorkMomentsNotificationUnreadCount(ctx context.Context) error {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
c := model_struct.LocalWorkMomentsNotificationUnreadCount{}
t := d.conn.WithContext(ctx).Model(&c).Where("1=1").Update("unread_count", gorm.Expr("unread_count+?", 1))
if t.RowsAffected == 0 {
return utils.Wrap(errors.New("RowsAffected == 0"), "no update")
}
return utils.Wrap(t.Error, "IncrConversationUnreadCount failed")
}
func (d *DataBase) MarkAllWorkMomentsNotificationAsRead(ctx context.Context) (err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalWorkMomentsNotificationUnreadCount{}).Where("1=1").Updates(map[string]interface{}{"unread_count": 0}).Error, "")
}
func (d *DataBase) GetWorkMomentsUnReadCount(ctx context.Context) (workMomentsNotificationUnReadCount model_struct.LocalWorkMomentsNotificationUnreadCount, err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
workMomentsNotificationUnReadCount = model_struct.LocalWorkMomentsNotificationUnreadCount{}
err = utils.Wrap(d.conn.WithContext(ctx).Model(&model_struct.LocalWorkMomentsNotificationUnreadCount{}).First(&workMomentsNotificationUnReadCount).Error, "")
return workMomentsNotificationUnReadCount, err
}
func (d *DataBase) ClearWorkMomentsNotification(ctx context.Context) (err error) {
d.mRWMutex.Lock()
defer d.mRWMutex.Unlock()
return utils.Wrap(d.conn.WithContext(ctx).Table("local_work_moments_notification").Where("1=1").Delete(&model_struct.LocalWorkMomentsNotification{}).Error, "")
}

View File

@@ -0,0 +1,50 @@
// Copyright © 2023 OpenIM SDK. 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.
//go:build !js
// +build !js
package db
import (
"context"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
)
func (d *DataBase) GetJoinedWorkingGroupIDList(ctx context.Context) ([]string, error) {
groupList, err := d.GetJoinedGroupListDB(ctx)
if err != nil {
return nil, utils.Wrap(err, "")
}
var groupIDList []string
for _, v := range groupList {
if v.GroupType == constant.WorkingGroup {
groupIDList = append(groupIDList, v.GroupID)
}
}
return groupIDList, nil
}
func (d *DataBase) GetJoinedWorkingGroupList(ctx context.Context) ([]*model_struct.LocalGroup, error) {
groupList, err := d.GetJoinedGroupListDB(ctx)
var transfer []*model_struct.LocalGroup
for _, v := range groupList {
if v.GroupType == constant.WorkingGroup {
transfer = append(transfer, v)
}
}
return transfer, utils.Wrap(err, "GetJoinedSuperGroupList failed ")
}

View File

@@ -0,0 +1,103 @@
// Copyright © 2023 OpenIM SDK. 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 network
import (
"bytes"
"encoding/json"
"errors"
"net"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"io/ioutil"
"net/http"
"time"
)
func get(url string) (response []byte, err error) {
client := http.Client{Timeout: 5 * time.Second}
resp, err := client.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return body, nil
}
func retry(url string, data interface{}, token string, attempts int, sleep time.Duration, fn func(string, interface{}, string) ([]byte, error)) ([]byte, error) {
b, err := fn(url, data, token)
if err != nil {
if attempts--; attempts > 0 {
time.Sleep(sleep)
return retry(url, data, token, attempts, 2*sleep, fn)
}
return nil, err
}
return b, nil
}
// application/json; charset=utf-8
func Post2Api(url string, data interface{}, token string) (content []byte, err error) {
c, err := postLogic(url, data, token)
return c, utils.Wrap(err, " post")
return retry(url, data, token, 1, 10*time.Second, postLogic)
}
func Post2ApiForRead(url string, data interface{}, token string) (content []byte, err error) {
return retry(url, data, token, 3, 10*time.Second, postLogic)
}
func postLogic(url string, data interface{}, token string) (content []byte, err error) {
jsonStr, err := json.Marshal(data)
if err != nil {
return nil, utils.Wrap(err, "marshal failed, url")
}
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
if err != nil {
return nil, utils.Wrap(err, "newRequest failed, url")
}
req.Close = true
req.Header.Add("content-type", "application/json")
req.Header.Add("token", token)
req.Header.Add("OperationID", utils.OperationIDGenerator())
tp := &http.Transport{
DialContext: (&net.Dialer{
KeepAlive: 10 * time.Minute,
}).DialContext,
ResponseHeaderTimeout: 60 * time.Second,
MaxIdleConnsPerHost: 100,
IdleConnTimeout: 60 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
}
client := &http.Client{Timeout: 60 * time.Second, Transport: tp}
resp, err := client.Do(req)
if err != nil {
return nil, utils.Wrap(err, "client.Do failed, url")
}
if resp.StatusCode != 200 {
return nil, utils.Wrap(errors.New(resp.Status), "status code failed "+url)
}
defer resp.Body.Close()
result, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, utils.Wrap(err, "ioutil.ReadAll failed, url")
}
// fmt.Println(url, "Marshal data: ", string(jsonStr), string(result))
return result, nil
}

View File

@@ -0,0 +1,165 @@
// Copyright © 2023 OpenIM SDK. 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 network
import (
"bytes"
"encoding/json"
"errors"
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
"io/ioutil"
"net/http"
"net/url"
"time"
"unsafe"
)
type HttpCli struct {
httpClient *http.Client
httpRequest *http.Request
Error error
}
func newHttpClient() *http.Client {
return &http.Client{Timeout: 30 * time.Second}
}
func PostWithTimeOut(url string, data interface{}, token string, timeout time.Duration) (content []byte, err error) {
return Post(url).BodyWithJson(data).SetTimeOut(timeout).SetHeader("token", token).ToBytes()
}
func Get(url string) *HttpCli {
request, err := http.NewRequest("GET", url, nil)
return &HttpCli{
httpClient: newHttpClient(),
httpRequest: request,
Error: err,
}
}
func Post(url string) *HttpCli {
request, err := http.NewRequest("POST", url, nil)
return &HttpCli{
httpClient: newHttpClient(),
httpRequest: request,
Error: utils.Wrap(err, "newRequest failed, url"),
}
}
func (c *HttpCli) SetTimeOut(timeout time.Duration) *HttpCli {
c.httpClient.Timeout = timeout
return c
}
func (c *HttpCli) SetHeader(key, value string) *HttpCli {
c.httpRequest.Header.Set(key, value)
return c
}
func (c *HttpCli) BodyWithJson(obj interface{}) *HttpCli {
if c.Error != nil {
return c
}
buf, err := json.Marshal(obj)
if err != nil {
c.Error = utils.Wrap(err, "marshal failed, url")
return c
}
c.httpRequest.Body = ioutil.NopCloser(bytes.NewReader(buf))
c.httpRequest.ContentLength = int64(len(buf))
c.httpRequest.Header.Set("Content-Type", "application/json")
return c
}
func (c *HttpCli) BodyWithBytes(buf []byte) *HttpCli {
if c.Error != nil {
return c
}
c.httpRequest.Body = ioutil.NopCloser(bytes.NewReader(buf))
c.httpRequest.ContentLength = int64(len(buf))
return c
}
func (c *HttpCli) BodyWithForm(form map[string]string) *HttpCli {
if c.Error != nil {
return c
}
var value url.Values = make(map[string][]string, len(form))
for k, v := range form {
value.Add(k, v)
}
buf := Str2bytes(value.Encode())
c.httpRequest.Body = ioutil.NopCloser(bytes.NewReader(buf))
c.httpRequest.ContentLength = int64(len(buf))
c.httpRequest.Header.Add("Content-Type", "application/x-www-form-urlencoded")
return c
}
func Str2bytes(s string) []byte {
x := (*[2]uintptr)(unsafe.Pointer(&s))
h := [3]uintptr{x[0], x[1], x[1]}
return *(*[]byte)(unsafe.Pointer(&h))
}
func (c *HttpCli) ToBytes() (content []byte, err error) {
if c.Error != nil {
return nil, c.Error
}
resp, err := c.httpClient.Do(c.httpRequest)
if err != nil {
return nil, utils.Wrap(err, "client.Do failed, url")
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, utils.Wrap(errors.New(resp.Status), "status code failed ")
}
buf, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, utils.Wrap(err, "ioutil.ReadAll failed, url")
}
return buf, nil
}
func (c *HttpCli) ToJson(obj interface{}) error {
if c.Error != nil {
return c.Error
}
resp, err := c.httpClient.Do(c.httpRequest)
if err != nil {
return utils.Wrap(err, "client.Do failed, url")
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return utils.Wrap(errors.New(resp.Status), "status code failed ")
}
buf, err := ioutil.ReadAll(resp.Body)
if err != nil {
return utils.Wrap(err, "ioutil.ReadAll failed, url")
}
err = json.Unmarshal(buf, obj)
if err != nil {
return utils.Wrap(err, "marshal failed, url")
}
return nil
}

View File

@@ -0,0 +1,7 @@
package page
import "github.com/openimsdk/protocol/sdkws"
type PageReq interface {
GetPagination() *sdkws.RequestPagination
}

View File

@@ -0,0 +1,120 @@
// Copyright © 2023 OpenIM SDK. 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 sdk_params_callback
import (
"github.com/openimsdk/openim-sdk-core/v3/pkg/server_api_params"
"github.com/openimsdk/openim-sdk-core/v3/sdk_struct"
)
type FindMessageListParams []*ConversationArgs
type ConversationArgs struct {
ConversationID string `json:"conversationID"`
ClientMsgIDList []string `json:"clientMsgIDList"`
}
type FindMessageListCallback struct {
TotalCount int `json:"totalCount"`
FindResultItems []*SearchByConversationResult `json:"findResultItems"`
}
type GetHistoryMessageListParams struct {
UserID string `json:"userID"`
GroupID string `json:"groupID"`
ConversationID string `json:"conversationID"`
StartClientMsgID string `json:"startClientMsgID"`
Count int `json:"count"`
}
type GetHistoryMessageListCallback []*sdk_struct.MsgStruct
type GetAdvancedHistoryMessageListParams struct {
LastMinSeq int64 `json:"lastMinSeq"`
ConversationID string `json:"conversationID"`
StartClientMsgID string `json:"startClientMsgID"`
Count int `json:"count"`
}
type GetAdvancedHistoryMessageListCallback struct {
MessageList []*sdk_struct.MsgStruct `json:"messageList"`
LastMinSeq int64 `json:"lastMinSeq"`
IsEnd bool `json:"isEnd"`
ErrCode int32 `json:"errCode"`
ErrMsg string `json:"errMsg"`
}
type SetConversationStatusParams struct {
UserId string `json:"userID" validate:"required"`
Status int `json:"status" validate:"required"`
}
type SearchLocalMessagesParams struct {
ConversationID string `json:"conversationID"`
KeywordList []string `json:"keywordList"`
KeywordListMatchType int `json:"keywordListMatchType"`
SenderUserIDList []string `json:"senderUserIDList"`
MessageTypeList []int `json:"messageTypeList"`
SearchTimePosition int64 `json:"searchTimePosition"`
SearchTimePeriod int64 `json:"searchTimePeriod"`
PageIndex int `json:"pageIndex"`
Count int `json:"count"`
}
type SearchLocalMessagesCallback struct {
TotalCount int `json:"totalCount"`
SearchResultItems []*SearchByConversationResult `json:"searchResultItems"`
}
type SearchByConversationResult struct {
ConversationID string `json:"conversationID"`
ConversationType int32 `json:"conversationType"`
ShowName string `json:"showName"`
FaceURL string `json:"faceURL"`
LatestMsgSendTime int64 `json:"latestMsgSendTime,omitempty"`
MessageCount int `json:"messageCount"`
MessageList []*sdk_struct.MsgStruct `json:"messageList"`
}
type SetMessageReactionExtensionsParams []*server_api_params.KeyValue
type SetMessageReactionExtensionsCallback struct {
Key string `json:"key" validate:"required"`
Value string `json:"value" validate:"required"`
ErrCode int32 `json:"errCode"`
ErrMsg string `json:"errMsg"`
}
type AddMessageReactionExtensionsParams []*server_api_params.KeyValue
type AddMessageReactionExtensionsCallback struct {
Key string `json:"key" validate:"required"`
Value string `json:"value" validate:"required"`
ErrCode int32 `json:"errCode"`
ErrMsg string `json:"errMsg"`
}
type DeleteMessageReactionExtensionsParams []string
type GetTypekeyListResp struct {
TypeKeyInfoList []*SingleTypeKeyInfoSum `json:"TypeKeyListInfo"`
}
type SingleTypeKeyInfoSum struct {
TypeKey string `json:"typeKey"`
Counter int64 `json:"counter"`
InfoList []*Info `json:"infoList"`
IsContainSelf bool `json:"isContainSelf"`
}
type SingleTypeKeyInfo struct {
TypeKey string `json:"typeKey"`
Counter int64 `json:"counter"`
IsCanRepeat bool `json:"isCanRepeat"`
Index int `json:"index"`
InfoList map[string]*Info `json:"infoList"`
}
type Info struct {
UserID string `json:"userID"`
Ex string `json:"ex"`
}

View File

@@ -0,0 +1,109 @@
// Copyright © 2023 OpenIM SDK. 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 sdk_params_callback
import (
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/server_api_params"
"github.com/openimsdk/protocol/wrapperspb"
)
// 1
type GetDesignatedFriendsInfoParams []string
type GetDesignatedFriendsInfoCallback []server_api_params.FullUserInfo
// 1
type AddFriendParams struct {
ToUserID string `json:"toUserID" validate:"required"`
ReqMsg string `json:"reqMsg"`
}
const AddFriendCallback = constant.SuccessCallbackDefault
// 1
// type GetRecvFriendApplicationListParams struct{}
type GetRecvFriendApplicationListCallback []*model_struct.LocalFriendRequest
// 1
// type GetSendFriendApplicationListParams struct{}
type GetSendFriendApplicationListCallback []*model_struct.LocalFriendRequest
// 1
type ProcessFriendApplicationParams struct {
ToUserID string `json:"toUserID" validate:"required"`
HandleMsg string `json:"handleMsg"`
}
const ProcessFriendApplicationCallback = constant.SuccessCallbackDefault
// 1
type CheckFriendParams []string
type CheckFriendCallback []server_api_params.UserIDResult
// 1
type DeleteFriendParams string
// type DeleteFriendCallback struct{}
const DeleteFriendCallback = constant.SuccessCallbackDefault
// 1
// type GetFriendListParams struct{}
type GetFriendListCallback []server_api_params.FullUserInfo
type SearchFriendsParam struct {
KeywordList []string `json:"keywordList"`
IsSearchUserID bool `json:"isSearchUserID"`
IsSearchNickname bool `json:"isSearchNickname"`
IsSearchRemark bool `json:"isSearchRemark"`
}
type GetFriendListPage struct {
}
type SearchFriendsCallback []*SearchFriendItem
type SearchFriendItem struct {
model_struct.LocalFriend
Relationship int `json:"relationship"`
}
// 1
type SetFriendRemarkParams struct {
ToUserID string `json:"toUserID" validate:"required"`
Remark string `json:"remark" validate:"required"`
}
type SetFriendPinParams struct {
ToUserIDs []string `json:"toUserIDs" validate:"required"`
IsPinned *wrapperspb.BoolValue `json:"isPinned" validate:"required"`
}
// type SetFriendRemarkCallback struct{}
const SetFriendRemarkCallback = constant.SuccessCallbackDefault
// 1
type AddBlackParams string
// type AddBlackCallback struct{}
const AddBlackCallback = constant.SuccessCallbackDefault
// 1
// type GetBlackListParams struct{}
type GetBlackListCallback []server_api_params.FullUserInfo
// 1
type RemoveBlackParams string
// type DeleteBlackCallback struct{}
const RemoveBlackCallback = constant.SuccessCallbackDefault

View File

@@ -0,0 +1,113 @@
// Copyright © 2023 OpenIM SDK. 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 sdk_params_callback
import (
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/server_api_params"
)
type CreateGroupBaseInfoParam struct {
GroupType int32 `json:"groupType"`
SetGroupInfoParam
}
type CreateGroupMemberRoleParam []*server_api_params.GroupAddMemberInfo
type CreateGroupCallback map[string]interface{}
// param groupID reqMsg
const JoinGroupCallback = constant.SuccessCallbackDefault
// type QuitGroupParam // groupID
const QuitGroupCallback = constant.SuccessCallbackDefault
const DismissGroupCallback = constant.SuccessCallbackDefault
const GroupMuteChangeCallback = constant.SuccessCallbackDefault
const GroupMemberMuteChangeCallback = constant.SuccessCallbackDefault
const SetGroupMemberNicknameCallback = constant.SuccessCallbackDefault
// type GetJoinedGroupListParam null
type GetJoinedGroupListCallback []*model_struct.LocalGroup
type GetGroupsInfoParam []string
type GetGroupsInfoCallback []*model_struct.LocalGroup
type SearchGroupsParam struct {
KeywordList []string `json:"keywordList"`
IsSearchGroupID bool `json:"isSearchGroupID"`
IsSearchGroupName bool `json:"isSearchGroupName"`
}
type SearchGroupsCallback []*model_struct.LocalGroup
type SearchGroupMembersParam struct {
GroupID string `json:"groupID"`
KeywordList []string `json:"keywordList"`
IsSearchUserID bool `json:"isSearchUserID"`
IsSearchMemberNickname bool `json:"isSearchMemberNickname"`
//offset, count int
Offset int `json:"offset"`
Count int `json:"count"`
PageNumber int `json:"pageNumber"`
}
type SearchGroupMembersCallback []*model_struct.LocalGroupMember
type SetGroupInfoParam struct {
GroupName string `json:"groupName"`
Notification string `json:"notification"`
Introduction string `json:"introduction"`
FaceURL string `json:"faceURL"`
Ex string `json:"ex"`
NeedVerification *int32 `json:"needVerification" binding:"oneof=0 1 2"`
}
type SetGroupMemberInfoParam struct {
GroupID string `json:"groupID"`
UserID string `json:"userID"`
Ex *string `json:"ex"`
}
const SetGroupMemberInfoCallback = constant.SuccessCallbackDefault
const SetGroupInfoCallback = constant.SuccessCallbackDefault
// type GetGroupMemberListParam groupID ...
type GetGroupMemberListCallback []*model_struct.LocalGroupMember
type GetGroupMembersInfoParam []string
type GetGroupMembersInfoCallback []*model_struct.LocalGroupMember
type KickGroupMemberParam []string
type KickGroupMemberCallback []*server_api_params.UserIDResult
// type TransferGroupOwnerParam
const TransferGroupOwnerCallback = constant.SuccessCallbackDefault
type InviteUserToGroupParam []string
type InviteUserToGroupCallback []*server_api_params.UserIDResult
// type GetGroupApplicationListParam
type GetGroupApplicationListCallback []*model_struct.LocalAdminGroupRequest
type GetSendGroupApplicationListCallback []*model_struct.LocalGroupRequest
// type AcceptGroupApplicationParam
const AcceptGroupApplicationCallback = constant.SuccessCallbackDefault
// type RefuseGroupApplicationParam
const RefuseGroupApplicationCallback = constant.SuccessCallbackDefault

View File

@@ -0,0 +1,68 @@
// Copyright © 2023 OpenIM SDK. 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 sdk_params_callback
import (
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
)
// //////////////////////////////friend////////////////////////////////////
type FriendApplicationAddedCallback model_struct.LocalFriendRequest
type FriendApplicationAcceptCallback model_struct.LocalFriendRequest
type FriendApplicationRejectCallback model_struct.LocalFriendRequest
type FriendApplicationDeletedCallback model_struct.LocalFriendRequest
type FriendAddedCallback model_struct.LocalFriend
type FriendDeletedCallback model_struct.LocalFriend
type FriendInfoChangedCallback model_struct.LocalFriend
type BlackAddCallback model_struct.LocalBlack
type BlackDeletedCallback model_struct.LocalBlack
////////////////////////////////group////////////////////////////////////
type JoinedGroupAddedCallback model_struct.LocalGroup
type JoinedGroupDeletedCallback model_struct.LocalGroup
type GroupMemberAddedCallback model_struct.LocalGroupMember
type GroupMemberDeletedCallback model_struct.LocalGroupMember
type GroupApplicationAddedCallback model_struct.LocalAdminGroupRequest
type GroupApplicationDeletedCallback model_struct.LocalAdminGroupRequest
type GroupApplicationAcceptCallback model_struct.LocalAdminGroupRequest
type GroupApplicationRejectCallback model_struct.LocalAdminGroupRequest
type GroupInfoChangedCallback model_struct.LocalGroup
type GroupMemberInfoChangedCallback model_struct.LocalGroupMember
// ////////////////////////////user////////////////////////////////////////
type SelfInfoUpdatedCallback model_struct.LocalUser
// ////////////////////////////user////////////////////////////////////////
type ConversationUpdateCallback model_struct.LocalConversation
type ConversationDeleteCallback model_struct.LocalConversation
// ///////////////////////////signaling/////////////////////////////////////
type InvitationInfo struct {
InviterUserID string
InviteeUserIDList []string
CustomData string
GroupID string
}
//type ReceiveNewInvitationCallback sdkws.SignalInviteReq
//
//type InviteeAcceptedCallback sdkws.SignalAcceptReq
//
//type InviteeRejectedCallback sdkws.SignalRejectReq
//
//type InvitationCancelledCallback sdkws.SignalCancelReq
//
//type InvitationTimeoutCallback sdkws.SignalInviteReq

View File

@@ -0,0 +1,27 @@
// Copyright © 2023 OpenIM SDK. 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 sdk_params_callback
import (
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
)
const UpdateFcmTokenCallback = constant.SuccessCallbackDefault
const SetAppBadgeCallback = constant.SuccessCallbackDefault
type UploadLogParams struct {
SystemType string `json:"system_type"`
Ex string `json:"ex"`
}

View File

@@ -0,0 +1,32 @@
// Copyright © 2023 OpenIM SDK. 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 sdk_params_callback
import (
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
"github.com/openimsdk/openim-sdk-core/v3/pkg/server_api_params"
)
// other user
type GetUsersInfoParam []string
type GetUsersInfoCallback []server_api_params.FullUserInfo
// type GetSelfUserInfoParam string
type GetSelfUserInfoCallback *model_struct.LocalUser
type SetSelfUserInfoParam server_api_params.ApiUserInfo
const SetSelfUserInfoCallback = constant.SuccessCallbackDefault

View File

@@ -0,0 +1,52 @@
// Copyright © 2023 OpenIM SDK. 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 sdkerrs
// 通用错误码
const (
NetworkError = 10000
NetworkTimeoutError = 10001
ArgsError = 10002 //输入参数错误
CtxDeadlineExceededError = 10003 //上下文超时
ResourceLoadNotCompleteError = 10004 //资源初始化未完成
UnknownCode = 10005 //没有解析到code
SdkInternalError = 10006 //SDK内部错误
NoUpdateError = 10007 //没有更新
UserIDNotFoundError = 10100 //UserID不存在 或未注册
LoginOutError = 10101 //用户已经退出登录
LoginRepeatError = 10102 //用户重复登录
//消息相关
FileNotFoundError = 10200 //记录不存在
MsgDeCompressionError = 10201 //消息解压失败
MsgDecodeBinaryWsError = 10202 //消息解码失败
MsgBinaryTypeNotSupportError = 10203 //消息类型不支持
MsgRepeatError = 10204 //消息重复发送
MsgContentTypeNotSupportError = 10205 //消息类型不支持
MsgHasNoSeqError = 10206 //消息没有seq
//会话相关
NotSupportOptError = 10301 //不支持的操作
NotSupportTypeError = 10302 //not support type
UnreadCountError = 10303 //unread count has zero
//群组相关
GroupIDNotFoundError = 10400 //GroupID不存在
GroupTypeErr = 10401 //群组类型错误
)

View File

@@ -0,0 +1,26 @@
// Copyright © 2023 OpenIM SDK. 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 sdkerrs
import "github.com/openimsdk/tools/errs"
func New(code int, msg string, dtl string) errs.CodeError {
return errs.NewCodeError(code, msg).WithDetail(dtl)
}
var (
Wrap = errs.Wrap
WrapMsg = errs.WrapMsg
)

View File

@@ -0,0 +1,50 @@
// Copyright © 2023 OpenIM SDK. 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 sdkerrs
import "github.com/openimsdk/tools/errs"
var (
ErrArgs = errs.NewCodeError(ArgsError, "ArgsError")
ErrCtxDeadline = errs.NewCodeError(CtxDeadlineExceededError, "CtxDeadlineExceededError")
ErrSdkInternal = errs.NewCodeError(SdkInternalError, "SdkInternalError")
ErrNetwork = errs.NewCodeError(NetworkError, "NetworkError")
ErrNetworkTimeOut = errs.NewCodeError(NetworkTimeoutError, "NetworkTimeoutError")
ErrGroupIDNotFound = errs.NewCodeError(GroupIDNotFoundError, "GroupIDNotFoundError")
ErrUserIDNotFound = errs.NewCodeError(UserIDNotFoundError, "UserIDNotFoundError")
ErrResourceLoad = errs.NewCodeError(ResourceLoadNotCompleteError, "ResourceLoadNotCompleteError")
//消息相关
ErrFileNotFound = errs.NewCodeError(FileNotFoundError, "RecordNotFoundError")
ErrMsgDecodeBinaryWs = errs.NewCodeError(MsgDecodeBinaryWsError, "MsgDecodeBinaryWsError")
ErrMsgDeCompression = errs.NewCodeError(MsgDeCompressionError, "MsgDeCompressionError")
ErrMsgBinaryTypeNotSupport = errs.NewCodeError(MsgBinaryTypeNotSupportError, "MsgTypeNotSupportError")
ErrMsgRepeated = errs.NewCodeError(MsgRepeatError, "only failed message can be repeatedly send")
ErrMsgContentTypeNotSupport = errs.NewCodeError(MsgContentTypeNotSupportError, "contentType not support currently") // msg // msg
ErrMsgHasNoSeq = errs.NewCodeError(MsgHasNoSeqError, "msg has no seq") // msg // msg
//会话相关
ErrNotSupportOpt = errs.NewCodeError(NotSupportOptError, "super group not support this opt")
ErrNotSupportType = errs.NewCodeError(NotSupportTypeError, "only support super group type type")
ErrUnreadCount = errs.NewCodeError(UnreadCountError, "unread count has zero")
//群组相关
ErrGroupType = errs.NewCodeError(GroupTypeErr, "group type error")
ErrLoginOut = errs.NewCodeError(LoginOutError, "LoginOutError")
ErrLoginRepeat = errs.NewCodeError(LoginRepeatError, "LoginRepeatError")
)

View File

@@ -0,0 +1,68 @@
// Copyright © 2023 OpenIM SDK. 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 server_api_params
import "github.com/openimsdk/protocol/sdkws"
//UserID string `protobuf:"bytes,1,opt,name=UserID" json:"UserID,omitempty"`
// Nickname string `protobuf:"bytes,2,opt,name=Nickname" json:"Nickname,omitempty"`
// FaceUrl string `protobuf:"bytes,3,opt,name=FaceUrl" json:"FaceUrl,omitempty"`
// Gender int32 `protobuf:"varint,4,opt,name=Gender" json:"Gender,omitempty"`
// PhoneNumber string `protobuf:"bytes,5,opt,name=PhoneNumber" json:"PhoneNumber,omitempty"`
// Birth string `protobuf:"bytes,6,opt,name=Birth" json:"Birth,omitempty"`
// Email string `protobuf:"bytes,7,opt,name=Email" json:"Email,omitempty"`
// Ex string `protobuf:"bytes,8,opt,name=Ex" json:"Ex,omitempty"`
type UserRegisterReq struct {
Secret string `json:"secret" binding:"required,max=32"`
Platform int32 `json:"platform" binding:"required,min=1,max=7"`
sdkws.UserInfo
OperationID string `json:"operationID" binding:"required"`
}
type UserTokenInfo struct {
UserID string `json:"userID"`
Token string `json:"token"`
ExpiredTime int64 `json:"expiredTime"`
}
type UserRegisterResp struct {
CommResp
UserToken UserTokenInfo `json:"data"`
}
type UserTokenReq struct {
Secret string `json:"secret" binding:"required,max=32"`
Platform int32 `json:"platformID" binding:"required,min=1,max=8"`
UserID string `json:"userID" binding:"required,min=1,max=64"`
OperationID string `json:"operationID" binding:"required"`
}
type UserTokenResp struct {
CommResp
UserToken UserTokenInfo `json:"data"`
}
type ParseTokenReq struct {
OperationID string `json:"operationID" binding:"required"`
}
type ExpireTime struct {
ExpireTimeSeconds uint32 `json:"expireTimeSeconds" `
}
type ParseTokenResp struct {
CommResp
ExpireTime ExpireTime `json:"expireTime"`
}

View File

@@ -0,0 +1,29 @@
// Copyright © 2023 OpenIM SDK. 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 server_api_params
type AwsStorageCredentialReq struct {
OperationID string `json:"operationID"`
}
type AwsStorageCredentialResp struct {
CommResp
AccessKeyId string `json:"accessKeyID"`
SecretAccessKey string `json:"secretAccessKey"`
SessionToken string `json:"sessionToken"`
RegionID string `json:"regionId"`
Bucket string `json:"bucket"`
FinalHost string `json:"FinalHost"`
}

View File

@@ -0,0 +1,184 @@
// Copyright © 2023 OpenIM SDK. 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 server_api_params
type DeleteMsgReq struct {
OpUserID string `json:"opUserID"`
UserID string `json:"userID"`
SeqList []int64 `json:"seqList"`
OperationID string `json:"operationID"`
}
type DeleteMsgResp struct {
}
type CleanUpMsgReq struct {
UserID string `json:"userID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
}
type CleanUpMsgResp struct {
CommResp
}
type DelSuperGroupMsgReq struct {
UserID string `json:"userID,omitempty" binding:"required"`
GroupID string `json:"groupID,omitempty" binding:"required"`
SeqList []int64 `json:"seqList,omitempty"`
IsAllDelete bool `json:"isAllDelete"`
OperationID string `json:"operationID,omitempty" binding:"required"`
}
type DelSuperGroupMsgResp struct {
CommResp
}
type MsgDeleteNotificationElem struct {
GroupID string `json:"groupID"`
IsAllDelete bool `json:"isAllDelete"`
SeqList []int64 `json:"seqList"`
}
type SetMessageReactionExtensionsReq struct {
OperationID string `json:"operationID" validate:"required"`
ClientMsgID string `json:"clientMsgID" validate:"required"`
SourceID string `json:"sourceID" validate:"required"`
SessionType int32 `json:"sessionType" validate:"required"`
ReactionExtensionList map[string]*KeyValue `json:"reactionExtensionList"`
IsReact bool `json:"isReact,omitempty"`
IsExternalExtensions bool `json:"isExternalExtensions,omitempty"`
MsgFirstModifyTime int64 `json:"msgFirstModifyTime,omitempty"`
}
type AddMessageReactionExtensionsReq struct {
OperationID string `json:"operationID" validate:"required"`
ClientMsgID string `json:"clientMsgID" validate:"required"`
SourceID string `json:"sourceID" validate:"required"`
SessionType int32 `json:"sessionType" validate:"required"`
ReactionExtensionList map[string]*KeyValue `json:"reactionExtensionList"`
IsReact bool `json:"isReact,omitempty"`
IsExternalExtensions bool `json:"isExternalExtensions,omitempty"`
MsgFirstModifyTime int64 `json:"msgFirstModifyTime,omitempty"`
Seq int64 `json:"seq"`
}
type DeleteMessageReactionExtensionsReq struct {
OperationID string `json:"operationID" binding:"required"`
SourceID string `json:"sourceID" binding:"required"`
SessionType int32 `json:"sessionType" binding:"required"`
ClientMsgID string `json:"clientMsgID" binding:"required"`
IsExternalExtensions bool `json:"isExternalExtensions"`
MsgFirstModifyTime int64 `json:"msgFirstModifyTime" binding:"required"`
ReactionExtensionList []*KeyValue `json:"reactionExtensionList" binding:"required"`
}
type DeleteMessageReactionExtensionsResp struct {
CommResp
Result []*ExtensionResult
Data map[string]interface{} `json:"data"`
}
type KeyValue struct {
TypeKey string `json:"typeKey" validate:"required"`
Value string `json:"value" validate:"required"`
LatestUpdateTime int64 `json:"latestUpdateTime"`
}
type ApiResult struct {
Result []*ExtensionResult `json:"result"`
MsgFirstModifyTime int64 `json:"msgFirstModifyTime"`
IsReact bool `json:"isReact"`
}
type SetMessageReactionExtensionsResp struct {
CommResp
ApiResult struct {
Result []*ExtensionResult `json:"result"`
MsgFirstModifyTime int64 `json:"msgFirstModifyTime"`
IsReact bool `json:"isReact"`
}
Data map[string]interface{} `json:"data"`
}
type AddMessageReactionExtensionsResp struct {
CommResp
ApiResult struct {
Result []*ExtensionResult `json:"result"`
MsgFirstModifyTime int64 `json:"msgFirstModifyTime"`
IsReact bool `json:"isReact"`
}
Data map[string]interface{} `json:"data"`
}
type ExtensionResult struct {
CommResp
KeyValue
}
type GetMessageListReactionExtensionsReq struct {
OperationID string `json:"operationID" binding:"required"`
SourceID string `json:"sourceID" binding:"required"`
SessionType int32 `json:"sessionType" binding:"required"`
IsExternalExtensions bool `json:"isExternalExtensions"`
TypeKeyList []string `json:"typeKeyList"`
MessageReactionKeyList []OperateMessageListReactionExtensionsReq `json:"messageReactionKeyList" binding:"required"`
}
type KeyValueResp struct {
KeyValue *KeyValue `protobuf:"bytes,1,opt,name=keyValue" json:"keyValue,omitempty"`
ErrCode int32 `protobuf:"varint,2,opt,name=errCode" json:"errCode,omitempty"`
ErrMsg string `protobuf:"bytes,3,opt,name=errMsg" json:"errMsg,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
//type ExtendMsg struct {
// ReactionExtensionList map[string]*KeyValueResp `protobuf:"bytes,1,rep,name=reactionExtensionList" json:"reactionExtensionList,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
// ClientMsgID string `protobuf:"bytes,2,opt,name=clientMsgID" json:"clientMsgID,omitempty"`
// MsgFirstModifyTime int64 `protobuf:"varint,3,opt,name=msgFirstModifyTime" json:"msgFirstModifyTime,omitempty"`
// AttachedInfo string `protobuf:"bytes,4,opt,name=attachedInfo" json:"attachedInfo,omitempty"`
// Ex string `protobuf:"bytes,5,opt,name=ex" json:"ex,omitempty"`
//}
//
//type ExtendMsgResp struct {
// ExtendMsg *ExtendMsg `protobuf:"bytes,1,opt,name=extendMsg" json:"extendMsg,omitempty"`
// ErrCode int32 `protobuf:"varint,2,opt,name=errCode" json:"errCode,omitempty"`
// ErrMsg string `protobuf:"bytes,3,opt,name=errMsg" json:"errMsg,omitempty"`
//}
type GetMessageListReactionExtensionsResp []*SingleMessageExtensionResult
type OperateMessageListReactionExtensionsReq struct {
ClientMsgID string `json:"clientMsgID"`
MsgFirstModifyTime int64 `json:"msgFirstModifyTime"`
}
type ReactionMessageModifierNotification struct {
Operation int `json:"operation" binding:"required"`
SourceID string `json:"sourceID" binding:"required"`
OpUserID string `json:"opUserID" binding:"required"`
SessionType int32 `json:"sessionType" binding:"required"`
// SuccessReactionExtensionList map[string]*sdkws.KeyValue `json:"reactionExtensionList,omitempty" binding:"required"`
ClientMsgID string `json:"clientMsgID" binding:"required"`
IsReact bool `json:"isReact"`
IsExternalExtensions bool `json:"isExternalExtensions"`
MsgFirstModifyTime int64 `json:"msgFirstModifyTime"`
Seq uint32 `json:"seq"`
}
type SingleMessageExtensionResult struct {
ErrCode int32 `protobuf:"varint,1,opt,name=errCode" json:"errCode,omitempty"`
ErrMsg string `protobuf:"bytes,2,opt,name=errMsg" json:"errMsg,omitempty"`
// ReactionExtensionList map[string]*sdkws.KeyValue `protobuf:"bytes,3,rep,name=reactionExtensionList" json:"reactionExtensionList,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
ClientMsgID string `protobuf:"bytes,4,opt,name=clientMsgID" json:"clientMsgID,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
type ReactionMessageDeleteNotification struct {
SourceID string `json:"sourceID" binding:"required"`
OpUserID string `json:"opUserID" binding:"required"`
SessionType int32 `json:"sessionType" binding:"required"`
// SuccessReactionExtensionList map[string]*sdkws.KeyValue `json:"reactionExtensionList,omitempty" binding:"required"`
ClientMsgID string `json:"clientMsgID" binding:"required"`
MsgFirstModifyTime int64 `json:"msgFirstModifyTime"`
}

View File

@@ -0,0 +1,98 @@
// Copyright © 2023 OpenIM SDK. 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 server_api_params
type Conversation struct {
OwnerUserID string `json:"ownerUserID" binding:"required"`
ConversationID string `json:"conversationID" binding:"required"`
ConversationType int32 `json:"conversationType" binding:"required"`
UserID string `json:"userID"`
GroupID string `json:"groupID"`
RecvMsgOpt int32 `json:"recvMsgOpt"`
UnreadCount int32 `json:"unreadCount"`
DraftTextTime int64 `json:"draftTextTime"`
IsPinned bool `json:"isPinned"`
IsPrivateChat bool `json:"isPrivateChat"`
BurnDuration int32 `json:"burnDuration"`
GroupAtType int32 `json:"groupAtType"`
IsNotInGroup bool `json:"isNotInGroup"`
UpdateUnreadCountTime int64 ` json:"updateUnreadCountTime"`
AttachedInfo string `json:"attachedInfo"`
Ex string `json:"ex"`
}
type SetConversationReq struct {
Conversation
NotificationType int `json:"notificationType"`
OperationID string `json:"operationID" binding:"required"`
}
type SetConversationResp struct {
}
type ModifyConversationFieldReq struct {
Conversation
FieldType int32 `json:"fieldType" binding:"required"`
UserIDList []string `json:"userIDList" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
}
type ModifyConversationFieldResp struct {
CommResp
}
type BatchSetConversationsReq struct {
Conversations []Conversation `json:"conversations" binding:"required"`
OwnerUserID string `json:"ownerUserID" binding:"required"`
NotificationType int `json:"notificationType"`
OperationID string `json:"operationID" binding:"required"`
}
type BatchSetConversationsResp struct {
Success []string `json:"success"`
Failed []string `json:"failed"`
}
type GetConversationReq struct {
ConversationID string `json:"conversationID" binding:"required"`
OwnerUserID string `json:"ownerUserID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
}
type GetConversationResp struct {
Conversation Conversation `json:"data"`
}
type GetAllConversationsReq struct {
OwnerUserID string `json:"ownerUserID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
}
type GetAllConversationsResp struct {
Conversations []Conversation `json:"data"`
}
type GetConversationsReq struct {
ConversationIDs []string `json:"conversationIDs" binding:"required"`
OwnerUserID string `json:"ownerUserID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
}
type GetConversationsResp struct {
CommResp
Conversations []Conversation `json:"data"`
}
type GetConversationRecvMessageOptResp struct {
ConversationID string `json:"conversationID"`
Result *int32 `json:"result"`
}

View File

@@ -0,0 +1,150 @@
// Copyright © 2023 OpenIM SDK. 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 server_api_params
import "github.com/openimsdk/protocol/sdkws"
type ParamsCommFriend struct {
OperationID string `json:"operationID" binding:"required"`
ToUserID string `json:"toUserID" binding:"required"`
FromUserID string `json:"fromUserID" binding:"required"`
}
type AddBlacklistReq struct {
ParamsCommFriend
}
type AddBlacklistResp struct {
CommResp
}
type ImportFriendReq struct {
FriendUserIDList []string `json:"friendUserIDList" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
FromUserID string `json:"fromUserID" binding:"required"`
}
type UserIDResult struct {
UserID string `json:"userID""`
Result int32 `json:"result"`
}
type ImportFriendResp struct {
CommResp
UserIDResultList []UserIDResult `json:"data"`
}
type AddFriendReq struct {
ParamsCommFriend
ReqMsg string `json:"reqMsg"`
}
type AddFriendResp struct {
CommResp
}
type AddFriendResponseReq struct {
ParamsCommFriend
Flag int32 `json:"flag" binding:"required,oneof=-1 0 1"`
HandleMsg string `json:"handleMsg"`
}
type AddFriendResponseResp struct {
CommResp
}
type DeleteFriendReq struct {
ParamsCommFriend
}
type DeleteFriendResp struct {
CommResp
}
type GetBlackListReq struct {
OperationID string `json:"operationID" binding:"required"`
FromUserID string `json:"fromUserID" binding:"required"`
}
type GetBlackListResp struct {
CommResp
BlackUserInfoList []*sdkws.PublicUserInfo
Data []map[string]interface{} `json:"data"`
}
//type PublicUserInfo struct {
// UserID string `json:"userID"`
// Nickname string `json:"nickname"`
// FaceUrl string `json:"faceUrl"`
// Gender int32 `json:"gender"`
//}
type SetFriendRemarkReq struct {
ParamsCommFriend
Remark string `json:"remark" binding:"required"`
}
type SetFriendRemarkResp struct {
CommResp
}
type RemoveBlackListReq struct {
ParamsCommFriend
}
type RemoveBlackListResp struct {
CommResp
}
type IsFriendReq struct {
ParamsCommFriend
}
type Response struct {
Friend bool `json:"isFriend"`
}
type IsFriendResp struct {
CommResp
Response Response `json:"data"`
}
type GetFriendsInfoReq struct {
ParamsCommFriend
}
type GetFriendsInfoResp struct {
CommResp
FriendInfoList []*sdkws.FriendInfo
Data []map[string]interface{} `json:"data"`
}
type GetFriendListReq struct {
OperationID string `json:"operationID" binding:"required"`
FromUserID string `json:"fromUserID" binding:"required"`
}
type GetFriendListResp struct {
CommResp
FriendInfoList []*sdkws.FriendInfo
Data []map[string]interface{} `json:"data"`
}
type GetFriendApplyListReq struct {
OperationID string `json:"operationID" binding:"required"`
FromUserID string `json:"fromUserID" binding:"required"`
}
type GetFriendApplyListResp struct {
CommResp
FriendRequestList []*sdkws.FriendRequest
Data []map[string]interface{} `json:"data"`
}
type GetSelfFriendApplyListReq struct {
OperationID string `json:"operationID" binding:"required"`
FromUserID string `json:"fromUserID" binding:"required"`
}
type GetSelfFriendApplyListResp struct {
CommResp
FriendRequestList []*sdkws.FriendRequest
Data []map[string]interface{} `json:"data"`
}

View File

@@ -0,0 +1,315 @@
// Copyright © 2023 OpenIM SDK. 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 server_api_params
import "github.com/openimsdk/protocol/sdkws"
type CommResp struct {
ErrCode int32 `json:"errCode"`
ErrMsg string `json:"errMsg"`
ErrDlt string `json:"errDlt"`
}
type CommDataResp struct {
CommResp
Data []map[string]interface{} `json:"data"`
}
type CommDataRespOne struct {
CommResp
Data map[string]interface{} `json:"data"`
}
type KickGroupMemberReq struct {
GroupID string `json:"groupID" binding:"required"`
KickedUserIDList []string `json:"kickedUserIDList" binding:"required"`
Reason string `json:"reason"`
OperationID string `json:"operationID" binding:"required"`
}
type KickGroupMemberResp struct {
CommResp
UserIDResultList []*UserIDResult `json:"data"`
}
type GetGroupMembersInfoReq struct {
GroupID string `json:"groupID" binding:"required"`
MemberList []string `json:"memberList" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
}
type GetGroupMembersInfoResp struct {
CommResp
MemberList []*sdkws.GroupMemberFullInfo `json:"-"`
Data []map[string]interface{} `json:"data"`
}
type InviteUserToGroupReq struct {
GroupID string `json:"groupID" binding:"required"`
InvitedUserIDList []string `json:"invitedUserIDList" binding:"required"`
Reason string `json:"reason"`
OperationID string `json:"operationID" binding:"required"`
}
type InviteUserToGroupResp struct {
CommResp
UserIDResultList []*UserIDResult `json:"data"`
}
type GetJoinedGroupListReq struct {
OperationID string `json:"operationID" binding:"required"`
FromUserID string `json:"fromUserID" binding:"required"`
}
type GetJoinedGroupListResp struct {
CommResp
GroupInfoList []*sdkws.GroupInfo
Data []map[string]interface{} `json:"data"`
}
type GetGroupMemberListReq struct {
GroupID string `json:"groupID"`
Filter int32 `json:"filter"`
NextSeq int32 `json:"nextSeq"`
OperationID string `json:"operationID"`
}
type GetGroupMemberListResp struct {
CommResp
NextSeq int32 `json:"nextSeq"`
MemberList []*sdkws.GroupMemberFullInfo
Data []map[string]interface{} `json:"data"`
}
type GetGroupAllMemberReq struct {
GroupID string `json:"groupID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
Offset int32 `json:"offset"`
Count int32 `json:"count"`
}
type GetGroupAllMemberResp struct {
CommResp
MemberList []*sdkws.GroupMemberFullInfo `json:"-"`
Data []map[string]interface{} `json:"data"`
}
type CreateGroupReq struct {
MemberList []*GroupAddMemberInfo `json:"memberList" binding:"required"`
OwnerUserID string `json:"ownerUserID" binding:"required"`
GroupType int32 `json:"groupType"`
GroupName string `json:"groupName"`
Notification string `json:"notification"`
Introduction string `json:"introduction"`
FaceURL string `json:"faceURL"`
Ex string `json:"ex"`
OperationID string `json:"operationID" binding:"required"`
}
type CreateGroupResp struct {
CommResp
GroupInfo sdkws.GroupInfo
Data map[string]interface{} `json:"data"`
}
type GetGroupApplicationListReq struct {
OperationID string `json:"operationID" binding:"required"`
FromUserID string `json:"fromUserID" binding:"required"` //作为管理员或群主收到的 进群申请
}
type GetGroupApplicationListResp struct {
CommResp
GroupRequestList []*sdkws.GroupRequest
Data []map[string]interface{} `json:"data"`
}
type GetUserReqGroupApplicationListReq struct {
OperationID string `json:"operationID" binding:"required"`
UserID string `json:"userID" binding:"required"`
}
type GetUserRespGroupApplicationResp struct {
CommResp
GroupRequestList []*sdkws.GroupRequest `json:"-"`
}
type GetGroupInfoReq struct {
GroupIDList []string `json:"groupIDList" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
}
type GetGroupInfoResp struct {
CommResp
GroupInfoList []*sdkws.GroupInfo `json:"-"`
Data []map[string]interface{} `json:"data"`
}
//type GroupInfoAlias struct {
// GroupID string `protobuf:"bytes,1,opt,name=groupID" json:"groupID,omitempty"`
// GroupName string `protobuf:"bytes,2,opt,name=groupName" json:"groupName,omitempty"`
// NotificationCmd string `protobuf:"bytes,3,opt,name=notification" json:"notification,omitempty"`
// Introduction string `protobuf:"bytes,4,opt,name=introduction" json:"introduction,omitempty"`
// FaceURL string `protobuf:"bytes,5,opt,name=faceURL" json:"faceURL,omitempty"`
// OwnerUserID string `protobuf:"bytes,6,opt,name=ownerUserID" json:"ownerUserID,omitempty"`
// CreateTime uint32 `protobuf:"varint,7,opt,name=createTime" json:"createTime,omitempty"`
// MemberCount uint32 `protobuf:"varint,8,opt,name=memberCount" json:"memberCount,omitempty"`
// Ex string `protobuf:"bytes,9,opt,name=ex" json:"ex,omitempty"`
// Status int32 `protobuf:"varint,10,opt,name=status" json:"status,omitempty"`
// CreatorUserID string `protobuf:"bytes,11,opt,name=creatorUserID" json:"creatorUserID,omitempty"`
// GroupType int32 `protobuf:"varint,12,opt,name=groupType" json:"groupType,omitempty"`
// NeedVerification int32 `protobuf:"bytes,13,opt,name=needVerification" json:"needVerification,omitempty"`
//}
//type GroupInfoAlias struct {
// GroupInfo
// NeedVerification int32 `protobuf:"bytes,13,opt,name=needVerification" json:"needVerification,omitempty"`
//}
type ApplicationGroupResponseReq struct {
OperationID string `json:"operationID" binding:"required"`
GroupID string `json:"groupID" binding:"required"`
FromUserID string `json:"fromUserID" binding:"required"` //application from FromUserID
HandledMsg string `json:"handledMsg"`
HandleResult int32 `json:"handleResult" binding:"required,oneof=-1 1"`
}
type ApplicationGroupResponseResp struct {
CommResp
}
type JoinGroupReq struct {
GroupID string `json:"groupID" binding:"required"`
ReqMessage string `json:"reqMessage"`
OperationID string `json:"operationID" binding:"required"`
JoinSource int32 `json:"joinSource"`
InviterUserID string `json:"inviterUserID"`
}
type JoinGroupResp struct {
CommResp
}
type QuitGroupReq struct {
GroupID string `json:"groupID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
}
type QuitGroupResp struct {
CommResp
}
type SetGroupInfoReq struct {
GroupID string `json:"groupID" binding:"required"`
GroupName string `json:"groupName"`
Notification string `json:"notification"`
Introduction string `json:"introduction"`
FaceURL string `json:"faceURL"`
Ex string `json:"ex"`
OperationID string `json:"operationID" binding:"required"`
NeedVerification *int32 `json:"needVerification" binding:"oneof=0 1 2"`
LookMemberInfo *int32 `json:"lookMemberInfo" binding:"oneof=0 1"`
ApplyMemberFriend *int32 `json:"applyMemberFriend" binding:"oneof=0 1"`
}
type SetGroupInfoResp struct {
CommResp
}
type TransferGroupOwnerReq struct {
GroupID string `json:"groupID" binding:"required"`
OldOwnerUserID string `json:"oldOwnerUserID" binding:"required"`
NewOwnerUserID string `json:"newOwnerUserID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
}
type TransferGroupOwnerResp struct {
CommResp
}
type DismissGroupReq struct {
GroupID string `json:"groupID" binding:"required"`
OperationID string `json:"operationID" binding:"required"`
}
type DismissGroupResp struct {
CommResp
}
type MuteGroupMemberReq struct {
OperationID string `json:"operationID" binding:"required"`
GroupID string `json:"groupID" binding:"required"`
UserID string `json:"userID" binding:"required"`
MutedSeconds uint32 `json:"mutedSeconds" binding:"required"`
}
type MuteGroupMemberResp struct {
CommResp
}
type CancelMuteGroupMemberReq struct {
OperationID string `json:"operationID" binding:"required"`
GroupID string `json:"groupID" binding:"required"`
UserID string `json:"userID" binding:"required"`
}
type CancelMuteGroupMemberResp struct {
CommResp
}
type MuteGroupReq struct {
OperationID string `json:"operationID" binding:"required"`
GroupID string `json:"groupID" binding:"required"`
}
type MuteGroupResp struct {
CommResp
}
type CancelMuteGroupReq struct {
OperationID string `json:"operationID" binding:"required"`
GroupID string `json:"groupID" binding:"required"`
}
type CancelMuteGroupResp struct {
CommResp
}
type SetGroupMemberNicknameReq struct {
OperationID string `json:"operationID" binding:"required"`
GroupID string `json:"groupID" binding:"required"`
UserID string `json:"userID" binding:"required"`
Nickname string `json:"nickname"`
}
type SetGroupMemberNicknameResp struct {
CommResp
}
type SetGroupMemberBaseInfoReq struct {
OperationID string `json:"operationID" binding:"required"`
GroupID string `json:"groupID" binding:"required"`
UserID string `json:"userID" binding:"required"`
}
type SetGroupMemberInfoReq struct {
OperationID string `json:"operationID" binding:"required"`
GroupID string `json:"groupID" binding:"required"`
UserID string `json:"userID" binding:"required"`
Nickname *string `json:"nickname"`
FaceURL *string `json:"userGroupFaceUrl"`
RoleLevel *int32 `json:"roleLevel" validate:"gte=1,lte=3"`
Ex *string `json:"ex"`
}
type SetGroupMemberRoleLevelReq struct {
SetGroupMemberBaseInfoReq
RoleLevel int `json:"roleLevel"`
}
type SetGroupMemberRoleLevelResp struct {
CommResp
}
type GetGroupAbstractInfoReq struct {
OperationID string `json:"operationID" binding:"required"`
GroupID string `json:"groupID" binding:"required"`
}
type GetGroupAbstractInfoResp struct {
CommResp
GroupMemberNumber int32 `json:"groupMemberNumber"`
GroupMemberListHash uint64 `json:"groupMemberListHash"`
}

View File

@@ -0,0 +1,74 @@
// Copyright © 2023 OpenIM SDK. 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 server_api_params
type DeleteUsersReq struct {
OperationID string `json:"operationID" binding:"required"`
DeleteUserIDList []string `json:"deleteUserIDList" binding:"required"`
}
type DeleteUsersResp struct {
CommResp
FailedUserIDList []string `json:"data"`
}
type GetAllUsersUidReq struct {
OperationID string `json:"operationID" binding:"required"`
}
type GetAllUsersUidResp struct {
CommResp
UserIDList []string `json:"data"`
}
type GetUsersOnlineStatusReq struct {
OperationID string `json:"operationID" binding:"required"`
UserIDList []string `json:"userIDList" binding:"required,lte=200"`
}
type GetUsersOnlineStatusResp struct {
CommResp
SuccessResult []GetusersonlinestatusrespSuccessresult `json:"data"`
}
type AccountCheckReq struct {
OperationID string `json:"operationID" binding:"required"`
CheckUserIDList []string `json:"checkUserIDList" binding:"required,lte=100"`
}
type AccountCheckResp struct {
CommResp
Results []*AccountCheckResp_SingleUserStatus `json:"data"`
}
type AccountCheckResp_SingleUserStatus struct {
UserID string `protobuf:"bytes,1,opt,name=userID" json:"userID,omitempty"`
AccountStatus string `protobuf:"bytes,2,opt,name=accountStatus" json:"accountStatus,omitempty"`
}
type GetusersonlinestatusrespSuccessdetail struct {
Platform string `protobuf:"bytes,1,opt,name=platform" json:"platform,omitempty"`
Status string `protobuf:"bytes,2,opt,name=status" json:"status,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
type GetusersonlinestatusrespSuccessresult struct {
UserID string `protobuf:"bytes,1,opt,name=userID" json:"userID,omitempty"`
Status string `protobuf:"bytes,2,opt,name=status" json:"status,omitempty"`
DetailPlatformStatus []*GetusersonlinestatusrespSuccessdetail `protobuf:"bytes,3,rep,name=detailPlatformStatus" json:"detailPlatformStatus,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
type AccountcheckrespSingleuserstatus struct {
UserID string `protobuf:"bytes,1,opt,name=userID" json:"userID,omitempty"`
AccountStatus string `protobuf:"bytes,2,opt,name=accountStatus" json:"accountStatus,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}

View File

@@ -0,0 +1,30 @@
// Copyright © 2023 OpenIM SDK. 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 server_api_params
type MinioStorageCredentialReq struct {
OperationID string `json:"operationID"`
}
type MinioStorageCredentialResp struct {
CommResp
SecretAccessKey string `json:"secretAccessKey"`
AccessKeyID string `json:"accessKeyID"`
SessionToken string `json:"sessionToken"`
SignerType int `json:"signerType"`
BucketName string `json:"bucketName"`
StsEndpointURL string `json:"stsEndpointURL"`
StorageTime int `json:"storageTime"`
}

View File

@@ -0,0 +1,36 @@
// Copyright © 2023 OpenIM SDK. 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 server_api_params
type OSSCredentialReq struct {
OperationID string `json:"operationID"`
Filename string `json:"filename"`
FileType string `json:"file_type"`
}
type OSSCredentialRespData struct {
Endpoint string `json:"endpoint"`
AccessKeyId string `json:"access_key_id"`
AccessKeySecret string `json:"access_key_secret"`
Token string `json:"token"`
Bucket string `json:"bucket"`
FinalHost string `json:"final_host"`
}
type OSSCredentialResp struct {
CommResp
OssData OSSCredentialRespData `json:"-"`
Data map[string]interface{} `json:"data"`
}

View File

@@ -0,0 +1,150 @@
// Copyright © 2023 OpenIM SDK. 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 server_api_params
import (
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
)
type ApiUserInfo struct {
UserID string `json:"userID" binding:"required,min=1,max=64"`
Nickname string `json:"nickname" binding:"omitempty,min=1,max=64"`
FaceURL string `json:"faceURL" binding:"omitempty,max=1024"`
GlobalRecvMsgOpt int32 `json:"globalRecvMsgOpt" binding:"omitempty,oneof=0 1 2"`
Ex string `json:"ex" binding:"omitempty,max=1024"`
}
type GroupAddMemberInfo struct {
UserID string `json:"userID" validate:"required"`
RoleLevel int32 `json:"roleLevel" validate:"required"`
}
type PublicUser struct {
UserID string `json:"userID"`
Nickname string `json:"nickname"`
FaceURL string `json:"faceURL"`
Ex string `json:"ex"`
CreateTime int64 `json:"createTime"`
}
type FullUserInfo struct {
PublicInfo *PublicUser `json:"publicInfo"`
FriendInfo *model_struct.LocalFriend `json:"friendInfo"`
BlackInfo *model_struct.LocalBlack `json:"blackInfo"`
}
type FullUserInfoWithCache struct {
PublicInfo *PublicUser `json:"publicInfo"`
FriendInfo *model_struct.LocalFriend `json:"friendInfo"`
BlackInfo *model_struct.LocalBlack `json:"blackInfo"`
GroupMemberInfo *model_struct.LocalGroupMember `json:"groupMemberInfo"`
}
//GroupName string `json:"groupName"`
// Introduction string `json:"introduction"`
// NotificationCmd string `json:"notification"`
// FaceUrl string `json:"faceUrl"`
// OperationID string `json:"operationID" binding:"required"`
// GroupType int32 `json:"groupType"`
// Ex string `json:"ex"`
//type GroupInfo struct {
// GroupID string `json:"groupID"`
// GroupName string `json:"groupName"`
// NotificationCmd string `json:"notification"`
// Introduction string `json:"introduction"`
// FaceUrl string `json:"faceUrl"`
// OwnerUserID string `json:"ownerUserID"`
// Ex string `json:"ex"`
// GroupType int32 `json:"groupType"`
//}
//type GroupMemberFullInfo struct {
// GroupID string `json:"groupID"`
// UserID string `json:"userID"`
// RoleLevel int32 `json:"roleLevel"`
// JoinTime uint64 `json:"joinTime"`
// Nickname string `json:"nickname"`
// FaceUrl string `json:"faceUrl"`
// FriendRemark string `json:"friendRemark"`
// AppMangerLevel int32 `json:"appMangerLevel"`
// JoinSource int32 `json:"joinSource"`
// OperatorUserID string `json:"operatorUserID"`
// Ex string `json:"ex"`
//}
//
//type PublicUserInfo struct {
// UserID string `json:"userID"`
// Nickname string `json:"nickname"`
// FaceUrl string `json:"faceUrl"`
// Gender int32 `json:"gender"`
//}
//
//type UserInfo struct {
// UserID string `json:"userID"`
// Nickname string `json:"nickname"`
// FaceUrl string `json:"faceUrl"`
// Gender int32 `json:"gender"`
// Mobile string `json:"mobile"`
// Birth string `json:"birth"`
// Email string `json:"email"`
// Ex string `json:"ex"`
//}
//
//type FriendInfo struct {
// OwnerUserID string `json:"ownerUserID"`
// Remark string `json:"remark"`
// CreateTime int64 `json:"createTime"`
// FriendUser UserInfo `json:"friendUser"`
// AddSource int32 `json:"addSource"`
// OperatorUserID string `json:"operatorUserID"`
// Ex string `json:"ex"`
//}
//
//type BlackInfo struct {
// OwnerUserID string `json:"ownerUserID"`
// CreateTime int64 `json:"createTime"`
// BlackUser PublicUserInfo `json:"friendUser"`
// AddSource int32 `json:"addSource"`
// OperatorUserID string `json:"operatorUserID"`
// Ex string `json:"ex"`
//}
//
//type GroupRequest struct {
// UserID string `json:"userID"`
// GroupID string `json:"groupID"`
// HandleResult string `json:"handleResult"`
// ReqMsg string `json:"reqMsg"`
// HandleMsg string `json:"handleMsg"`
// ReqTime int64 `json:"reqTime"`
// HandleUserID string `json:"handleUserID"`
// HandleTime int64 `json:"handleTime"`
// Ex string `json:"ex"`
//}
//
//type FriendRequest struct {
// FromUserID string `json:"fromUserID"`
// ToUserID string `json:"toUserID"`
// HandleResult int32 `json:"handleResult"`
// ReqMessage string `json:"reqMessage"`
// CreateTime int64 `json:"createTime"`
// HandlerUserID string `json:"handlerUserID"`
// HandleMsg string `json:"handleMsg"`
// HandleTime int64 `json:"handleTime"`
// Ex string `json:"ex"`
//}
//
//
//

View File

@@ -0,0 +1,30 @@
// Copyright © 2023 OpenIM SDK. 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 server_api_params
type GetJoinedSuperGroupReq struct {
GetJoinedGroupListReq
}
type GetJoinedSuperGroupResp struct {
GetJoinedGroupListResp
}
type GetSuperGroupsInfoReq struct {
GetGroupInfoReq
}
type GetSuperGroupsInfoResp struct {
GetGroupInfoResp
}

View File

@@ -0,0 +1,35 @@
// Copyright © 2023 OpenIM SDK. 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 server_api_params
type FcmUpdateTokenReq struct {
OperationID string `json:"operationID" binding:"required"`
Platform int `json:"platform" binding:"required,min=1,max=2"` //only for ios + android
FcmToken string `json:"fcmToken" binding:"required"`
}
type FcmUpdateTokenResp struct {
CommResp
}
type SetAppBadgeReq struct {
OperationID string `json:"operationID" binding:"required"`
FromUserID string `json:"fromUserID" binding:"required"`
AppUnreadCount int32 `json:"appUnreadCount" binding:"required"`
}
type SetAppBadgeResp struct {
CommResp
}

View File

@@ -0,0 +1,54 @@
// Copyright © 2023 OpenIM SDK. 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 server_api_params
import (
"github.com/openimsdk/protocol/sdkws"
)
type GetUsersInfoReq struct {
OperationID string `json:"operationID" binding:"required"`
UserIDList []string `json:"userIDList" binding:"required"`
}
type GetUsersInfoResp struct {
CommResp
UserInfoList []*sdkws.PublicUserInfo
Data []map[string]interface{} `json:"data"`
}
type UpdateSelfUserInfoReq struct {
ApiUserInfo
OperationID string `json:"operationID" binding:"required"`
}
type UpdateUserInfoResp struct {
CommResp
}
type SetGlobalRecvMessageOptReq struct {
OperationID string `json:"operationID" binding:"required"`
GlobalRecvMsgOpt *int32 `json:"globalRecvMsgOpt" binding:"omitempty,oneof=0 1 2"`
}
type SetGlobalRecvMessageOptResp struct {
CommResp
}
type GetSelfUserInfoReq struct {
OperationID string `json:"operationID" binding:"required"`
UserID string `json:"userID" binding:"required"`
}
type GetSelfUserInfoResp struct {
CommResp
UserInfo *sdkws.UserInfo `json:"-"`
Data map[string]interface{} `json:"data"`
}

View File

@@ -0,0 +1,22 @@
// Copyright © 2023 OpenIM SDK. 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 syncer
const (
Unchanged = 0
Insert = 1
Update = 2
Delete = 3
)

View File

@@ -0,0 +1,358 @@
// Copyright © 2023 OpenIM SDK. 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 syncer
import (
"context"
"github.com/google/go-cmp/cmp"
"github.com/openimsdk/openim-sdk-core/v3/internal/util"
"github.com/openimsdk/openim-sdk-core/v3/pkg/page"
"github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/utils/datautil"
"reflect"
"github.com/openimsdk/tools/log"
)
// New creates a new Syncer instance with the provided synchronization functions.
// This function requires several callback functions to handle different aspects of data synchronization:
// - insert: A function to insert new data.
// - delete: A function to delete existing data.
// - update: A function to update existing data.
// - uuid: A function to generate a unique identifier for each data item.
// - equal: A function to check if two data items are equal.
// - notice: A function to handle notifications during the sync process.
// Panics if insert, delete, update, or uuid functions are not provided.
func New[T, RESP any, V comparable](
insert func(ctx context.Context, value T) error,
delete func(ctx context.Context, value T) error,
update func(ctx context.Context, server T, local T) error,
uuid func(value T) V,
equal func(a T, b T) bool,
notice func(ctx context.Context, state int, server, local T) error,
) *Syncer[T, RESP, V] {
if insert == nil || update == nil || delete == nil || uuid == nil {
panic("invalid params")
}
// Determine the type of T and remove pointer indirection if necessary.
var t T
tof := reflect.TypeOf(&t)
for tof.Kind() == reflect.Ptr {
tof = tof.Elem()
}
// Return a new Syncer instance with the provided functions and the type as a string.
return &Syncer[T, RESP, V]{
insert: insert,
update: update,
delete: delete,
uuid: uuid,
equal: equal,
notice: notice,
ts: tof.String(),
}
}
// Syncer is a struct that holds functions for synchronizing data.
// It includes functions for inserting, updating, deleting, and notifying,
// as well as functions for generating unique IDs and checking equality of data items.
type Syncer[T, RESP any, V comparable] struct {
insert func(ctx context.Context, server T) error
update func(ctx context.Context, server T, local T) error
delete func(ctx context.Context, local T) error
batchInsert func(ctx context.Context, servers []T) error
deleteAll func(ctx context.Context, entityID string) error
notice func(ctx context.Context, state int, server, local T) error
equal func(server T, local T) bool
uuid func(value T) V
batchPageReq func(entityID string) page.PageReq
batchPageRespConvertFunc func(resp *RESP) []T
reqApiRouter string
ts string // Represents the type of T as a string.
}
type NoResp struct{}
func New2[T, RESP any, V comparable](opts ...Option[T, RESP, V]) *Syncer[T, RESP, V] {
// Create a new Syncer instance.
s := &Syncer[T, RESP, V]{}
// Apply the options to the Syncer.
for _, opt := range opts {
opt(s)
}
// Check required functions.
if s.insert == nil || s.update == nil || s.delete == nil || s.uuid == nil {
panic("invalid params")
}
// Determine the type of T and remove pointer indirection if necessary.
var t T
tof := reflect.TypeOf(&t)
for tof.Kind() == reflect.Ptr {
tof = tof.Elem()
}
// Set the type string.
s.ts = tof.String()
return s
}
// Option is a function that configures a Syncer.
type Option[T, RESP any, V comparable] func(*Syncer[T, RESP, V])
// WithInsert sets the insert function for the Syncer.
func WithInsert[T, RESP any, V comparable](f func(ctx context.Context, value T) error) Option[T, RESP, V] {
return func(s *Syncer[T, RESP, V]) {
s.insert = f
}
}
// WithUpdate sets the update function for the Syncer.
func WithUpdate[T, RESP any, V comparable](f func(ctx context.Context, server T, local T) error) Option[T, RESP, V] {
return func(s *Syncer[T, RESP, V]) {
s.update = f
}
}
// WithDelete sets the delete function for the Syncer.
func WithDelete[T, RESP any, V comparable](f func(ctx context.Context, local T) error) Option[T, RESP, V] {
return func(s *Syncer[T, RESP, V]) {
s.delete = f
}
}
// WithBatchInsert sets the batchInsert function for the Syncer.
func WithBatchInsert[T, RESP any, V comparable](f func(ctx context.Context, values []T) error) Option[T, RESP, V] {
return func(s *Syncer[T, RESP, V]) {
s.batchInsert = f
}
}
// WithDeleteAll sets the deleteAll function for the Syncer.
func WithDeleteAll[T, RESP any, V comparable](f func(ctx context.Context, entityID string) error) Option[T, RESP, V] {
return func(s *Syncer[T, RESP, V]) {
s.deleteAll = f
}
}
// WithUUID sets the uuid function for the Syncer.
func WithUUID[T, RESP any, V comparable](f func(value T) V) Option[T, RESP, V] {
return func(s *Syncer[T, RESP, V]) {
s.uuid = f
}
}
// WithEqual sets the equal function for the Syncer.
func WithEqual[T, RESP any, V comparable](f func(a T, b T) bool) Option[T, RESP, V] {
return func(s *Syncer[T, RESP, V]) {
s.equal = f
}
}
// WithNotice sets the notice function for the Syncer.
func WithNotice[T, RESP any, V comparable](f func(ctx context.Context, state int, server, local T) error) Option[T, RESP, V] {
return func(s *Syncer[T, RESP, V]) {
s.notice = f
}
}
// WithBatchPageReq sets the batchPageReq for the Syncer.
func WithBatchPageReq[T, RESP any, V comparable](f func(entityID string) page.PageReq) Option[T, RESP, V] {
return func(s *Syncer[T, RESP, V]) {
s.batchPageReq = f
}
}
// WithBatchPageRespConvertFunc sets the batchPageRespConvertFunc function for the Syncer.
func WithBatchPageRespConvertFunc[T, RESP any, V comparable](f func(resp *RESP) []T) Option[T, RESP, V] {
return func(s *Syncer[T, RESP, V]) {
s.batchPageRespConvertFunc = f
}
}
// WithReqApiRouter sets the reqApiRouter for the Syncer.
func WithReqApiRouter[T, RESP any, V comparable](router string) Option[T, RESP, V] {
return func(s *Syncer[T, RESP, V]) {
s.reqApiRouter = router
}
}
// NewSyncer creates a new Syncer with the provided options.
func NewSyncer[T, RESP any, V comparable](opts ...Option[T, RESP, V]) *Syncer[T, RESP, V] {
syncer := &Syncer[T, RESP, V]{}
for _, opt := range opts {
opt(syncer)
}
return syncer
}
// eq is a helper function to check equality of two data items.
// It uses the equal function if provided; otherwise, it falls back to the cmp.Equal function.
func (s *Syncer[T, RESP, V]) eq(server T, local T) bool {
if s.equal != nil {
return s.equal(server, local)
}
return cmp.Equal(server, local)
}
// onNotice is a helper function to handle notifications.
// It calls the Syncer's notice function and the provided notice function in sequence if they are not nil.
func (s *Syncer[T, RESP, V]) onNotice(ctx context.Context, state int, server, local T, fn func(ctx context.Context, state int, server, local T) error) error {
if s.notice != nil {
if err := s.notice(ctx, state, server, local); err != nil {
return err
}
}
if fn != nil {
if err := fn(ctx, state, server, local); err != nil {
return err
}
}
return nil
}
// Sync synchronizes server data with local data.
// Sync synchronizes the data between the server and local storage.
// It takes a context, two slices of data (serverData and localData),
// a notice function to handle notifications during the sync process,
// and a variadic parameter skipDeletion to control deletion behavior.
func (s *Syncer[T, RESP, V]) Sync(ctx context.Context, serverData []T, localData []T, notice func(ctx context.Context, state int, server, local T) error, skipDeletionAndNotice ...bool) (err error) {
defer func() {
// Log the outcome of the synchronization process.
if err == nil {
log.ZDebug(ctx, "sync success", "type", s.ts)
} else {
log.ZError(ctx, "sync failed", err, "type", s.ts)
}
}()
skipDeletion := false
if len(skipDeletionAndNotice) > 0 {
skipDeletion = skipDeletionAndNotice[0]
}
// If both server and local data are empty, log and return.
if len(serverData) == 0 && len(localData) == 0 {
log.ZDebug(ctx, "sync both the server and client are empty", "type", s.ts)
return nil
}
// Convert local data into a map for easier lookup.
localMap := datautil.SliceToMap(localData, func(item T) V {
return s.uuid(item)
})
// Iterate through server data to sync with local data.
for i := range serverData {
server := serverData[i]
id := s.uuid(server)
local, ok := localMap[id]
// If the item doesn't exist locally, insert it.
if !ok {
log.ZDebug(ctx, "sync insert", "type", s.ts, "server", server)
if err := s.insert(ctx, server); err != nil {
log.ZError(ctx, "sync insert failed", err, "type", s.ts, "server", server, "local", local)
return err
}
if err := s.onNotice(ctx, Insert, server, local, notice); err != nil {
log.ZError(ctx, "sync notice insert failed", err, "type", s.ts, "server", server, "local", local)
return err
}
continue
}
// Remove the item from the local map as it's found.
delete(localMap, id)
// If the local and server items are equal, notify and continue.
if s.eq(server, local) {
if err := s.onNotice(ctx, Unchanged, local, server, notice); err != nil {
log.ZError(ctx, "sync notice unchanged failed", err, "type", s.ts, "server", server, "local", local)
return err
}
continue
}
log.ZDebug(ctx, "sync update", "type", s.ts, "server", server, "local", local)
// Update the local item with server data.
if err := s.update(ctx, server, local); err != nil {
log.ZError(ctx, "sync update failed", err, "type", s.ts, "server", server, "local", local)
return err
}
if err := s.onNotice(ctx, Update, server, local, notice); err != nil {
log.ZError(ctx, "sync notice update failed", err, "type", s.ts, "server", server, "local", local)
return err
}
}
// Check the skipDeletion flag; if set, skip deletion.
if skipDeletion {
return nil
}
log.ZDebug(ctx, "sync delete", "type", s.ts, "localMap", localMap)
// Delete any local items not present in server data.
for id := range localMap {
local := localMap[id]
if err := s.delete(ctx, local); err != nil {
log.ZError(ctx, "sync delete failed", err, "type", s.ts, "local", local)
return err
}
var server T
if err := s.onNotice(ctx, Delete, server, local, notice); err != nil {
log.ZError(ctx, "sync notice delete failed", err, "type", s.ts, "local", local)
return err
}
}
return nil
}
func (s *Syncer[T, RESP, V]) FullSync(ctx context.Context, entityID string) (err error) {
defer func() {
// Log the outcome of the synchronization process.
if err == nil {
log.ZDebug(ctx, "full sync success", "type", s.ts)
} else {
log.ZError(ctx, "full sync failed", err, "type", s.ts)
}
}()
//// If server data is empty, log and return
//if len(serverData) == 0 {
// log.ZDebug(ctx, "full sync server data is empty", "type", s.ts)
// return nil
//}
// Clear local table data
if err = s.deleteAll(ctx, entityID); err != nil {
return errs.New("full sync delete all failed", "err", err.Error(), "type", s.ts)
}
// Get batch req
batchReq := s.batchPageReq(entityID)
// Batch page pull data and insert server data
if err = util.FetchAndInsertPagedData(ctx, s.reqApiRouter, batchReq, s.batchPageRespConvertFunc,
s.batchInsert, s.insert, 100); err != nil {
return errs.New("full sync batch insert failed", "err", err.Error(), "type", s.ts)
}
return nil
}

View File

@@ -0,0 +1,61 @@
// Copyright © 2023 OpenIM SDK. 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 utils
import (
"bytes"
"crypto/aes"
"crypto/cipher"
)
func PKCS5Padding(plaintext []byte, blockSize int) []byte {
padding := blockSize - len(plaintext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(plaintext, padtext...)
}
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
func AesEncrypt(origData, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
origData = PKCS5Padding(origData, blockSize)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
crypted := make([]byte, len(origData))
blockMode.CryptBlocks(crypted, origData)
return crypted, nil
}
func AesDecrypt(crypted, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) //初始向量的长度必须等于块block的长度16字节
origData := make([]byte, len(crypted))
blockMode.CryptBlocks(origData, crypted)
origData = PKCS5UnPadding(origData)
return origData, nil
}

View File

@@ -0,0 +1,56 @@
// Copyright © 2023 OpenIM SDK. 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 utils
import (
"io"
"os"
"path"
)
func CopyFile(srcName string, dstName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
return
}
dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
return
}
defer func() {
if src != nil {
src.Close()
}
if dst != nil {
dst.Close()
}
}()
return io.Copy(dst, src)
}
func FileTmpPath(fullPath, dbPrefix string) string {
suffix := path.Ext(fullPath)
if len(suffix) == 0 {
sdkLog("suffix err:")
}
return dbPrefix + Md5(fullPath) + suffix //a->b
}
func FileExist(filename string) bool {
_, err := os.Stat(filename)
return err == nil || os.IsExist(err)
}

View File

@@ -0,0 +1,555 @@
// Copyright © 2023 OpenIM SDK. 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 utils
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
"github.com/openimsdk/openim-sdk-core/v3/sdk_struct"
"sort"
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"
"reflect"
"github.com/pkg/errors"
"math/rand"
"runtime"
"strconv"
"strings"
"time"
)
func OperationIDGenerator() string {
return strconv.FormatInt(time.Now().UnixNano()+int64(rand.Uint32()), 10)
}
func GetMsgID(sendID string) string {
t := Int64ToString(GetCurrentTimestampByNano())
return Md5(t + sendID + Int64ToString(rand.Int63n(GetCurrentTimestampByNano())))
}
func Md5(s string) string {
h := md5.New()
h.Write([]byte(s))
cipher := h.Sum(nil)
return hex.EncodeToString(cipher)
}
//Get the current timestamp by Second
func GetCurrentTimestampBySecond() int64 {
return time.Now().Unix()
}
// Get the current timestamp by Mill
func GetCurrentTimestampByMill() int64 {
return time.Now().UnixNano() / 1e6
}
// Convert nano timestamp to time.Time type
func UnixNanoSecondToTime(nanoSecond int64) time.Time {
return time.Unix(0, nanoSecond)
}
// Get the current timestamp by Nano
func GetCurrentTimestampByNano() int64 {
return time.Now().UnixNano()
}
func StructToJsonString(param interface{}) string {
dataType, err := json.Marshal(param)
if err != nil {
panic(err)
}
dataString := string(dataType)
return dataString
}
func StructToJsonStringDefault(param interface{}) string {
if reflect.TypeOf(param).Kind() == reflect.Slice && reflect.ValueOf(param).Len() == 0 {
return "[]"
}
return StructToJsonString(param)
}
// The incoming parameter must be a pointer
func JsonStringToStruct(s string, args interface{}) error {
return Wrap(json.Unmarshal([]byte(s), args), "json Unmarshal failed")
}
func FirstLower(s string) string {
if s == "" {
return ""
}
return strings.ToLower(s[:1]) + s[1:]
}
//Convert timestamp to time.Time type
func UnixSecondToTime(second int64) time.Time {
return time.Unix(second, 0)
}
func IntToString(i int) string {
return strconv.FormatInt(int64(i), 10)
}
func Int32ToString(i int32) string {
return strconv.FormatInt(int64(i), 10)
}
func Int64ToString(i int64) string {
return strconv.FormatInt(i, 10)
}
func StringToInt64(i string) int64 {
j, _ := strconv.ParseInt(i, 10, 64)
return j
}
func StringToInt(i string) int {
j, _ := strconv.Atoi(i)
return j
}
func RunFuncName() string {
pc, _, _, _ := runtime.Caller(2)
return CleanUpfuncName(runtime.FuncForPC(pc).Name())
}
func LogBegin(v ...interface{}) {
//if constant.SdkLogFlag == 1 {
// return
//}
//if open_im_sdk.logger != nil {
// log2.NewInfo("", v...)
// return
//}
//pc, b, c, _ := runtime.Caller(1)
//fname := runtime.FuncForPC(pc).Name()
//i := strings.LastIndex(b, "/")
//if i != -1 {
// sLog.Println(" [", b[i+1:len(b)], ":", c, "]", cleanUpfuncName(fname), "call funcation begin, args: ", v)
//}
}
func LogEnd(v ...interface{}) {
//if constant.SdkLogFlag == 1 {
// return
//}
//if open_im_sdk.logger != nil {
// log2.NewInfo("", v...)
// return
//}
//pc, b, c, _ := runtime.Caller(1)
//fname := runtime.FuncForPC(pc).Name()
//i := strings.LastIndex(b, "/")
//if i != -1 {
// sLog.Println(" [", b[i+1:len(b)], ":", c, "]", cleanUpfuncName(fname), "call funcation end, args: ", v)
//}
}
func LogStart(v ...interface{}) {
//if constant.SdkLogFlag == 1 {
// return
//}
//if open_im_sdk.logger != nil {
// log2.NewInfo("", v...)
// return
//}
//pc, b, c, _ := runtime.Caller(1)
//fname := runtime.FuncForPC(pc).Name()
//i := strings.LastIndex(b, "/")
//if i != -1 {
// sLog.Println(" [", b[i+1:len(b)], ":", c, "]", cleanUpfuncName(fname), "funcation start, args: ", v)
//}
}
func LogFReturn(v ...interface{}) {
//if constant.SdkLogFlag == 1 {
// return
//}
//if open_im_sdk.logger != nil {
// log2.NewInfo("", v...)
// return
//}
//pc, b, c, _ := runtime.Caller(1)
//fname := runtime.FuncForPC(pc).Name()
//i := strings.LastIndex(b, "/")
//if i != -1 {
// sLog.Println("[", b[i+1:len(b)], ":", c, "]", cleanUpfuncName(fname), "failed return args(info): ", v)
//}
}
func LogSReturn(v ...interface{}) {
//if constant.SdkLogFlag == 1 {
// return
//}
//if open_im_sdk.logger != nil {
// log2.NewInfo("", v...)
// return
//}
//pc, b, c, _ := runtime.Caller(1)
//fname := runtime.FuncForPC(pc).Name()
//i := strings.LastIndex(b, "/")
//if i != -1 {
// sLog.Println("[", b[i+1:len(b)], ":", c, "]", cleanUpfuncName(fname), "success return args(info): ", v)
//}
}
func sdkLog(v ...interface{}) {
//if constant.SdkLogFlag == 1 {
// return
//}
//if open_im_sdk.logger != nil {
// log2.NewInfo("", v...)
// return
//}
//_, b, c, _ := runtime.Caller(1)
//i := strings.LastIndex(b, "/")
//if i != -1 {
// sLog.Println("[", b[i+1:len(b)], ":", c, "]", v)
//}
}
type LogInfo struct {
Info string `json:"info"`
}
// judge a string whether in the string list
func IsContain(target string, List []string) bool {
for _, element := range List {
if target == element {
return true
}
}
return false
}
func IsContainInt(target int, List []int) bool {
for _, element := range List {
if target == element {
return true
}
}
return false
}
func IsContainUInt32(target uint32, List []uint32) bool {
for _, element := range List {
if target == element {
return true
}
}
return false
}
func GetSwitchFromOptions(Options map[string]bool, key string) (result bool) {
if flag, ok := Options[key]; !ok || flag {
return true
}
return false
}
func SetSwitchFromOptions(Options map[string]bool, key string, value bool) {
Options[key] = value
}
func Wrap(err error, message string) error {
return errors.Wrap(err, "==> "+printCallerNameAndLine()+message)
}
func Unwrap(err error) error {
for err != nil {
unwrap, ok := err.(interface {
Unwrap() error
})
if !ok {
break
}
err = unwrap.Unwrap()
}
return err
}
func WithMessage(err error, message string) error {
return errors.WithMessage(err, "==> "+printCallerNameAndLine()+message)
}
func GetSelfFuncName() string {
pc, _, _, _ := runtime.Caller(1)
return CleanUpfuncName(runtime.FuncForPC(pc).Name())
}
func CleanUpfuncName(funcName string) string {
end := strings.LastIndex(funcName, ".")
if end == -1 {
return ""
}
return funcName[end+1:]
}
func printCallerNameAndLine() string {
pc, _, line, _ := runtime.Caller(2)
return runtime.FuncForPC(pc).Name() + "()@" + strconv.Itoa(line) + ": "
}
func StructToMap(user interface{}) map[string]interface{} {
data, _ := json.Marshal(user)
m := make(map[string]interface{})
json.Unmarshal(data, &m)
return m
}
// funcation GetConversationIDBySessionType(sourceID string, sessionType int) string {
// switch sessionType {
// case constant.SingleChatType:
// return "single_" + sourceID
// case constant.GroupChatType:
// return "group_" + sourceID
// case constant.SuperGroupChatType:
// return "super_group_" + sourceID
// case constant.NotificationChatType:
// return "notification_" + sourceID
// }
// return ""
// }
func GetConversationIDByMsg(msg *sdk_struct.MsgStruct) string {
switch msg.SessionType {
case constant.SingleChatType:
l := []string{msg.SendID, msg.RecvID}
sort.Strings(l)
return "si_" + strings.Join(l, "_") // single chat
case constant.GroupChatType:
return "g_" + msg.GroupID // group chat
case constant.SuperGroupChatType:
return "sg_" + msg.GroupID // super group chat
case constant.NotificationChatType:
return "sn_" + msg.SendID + "_" + msg.RecvID // server notification chat
}
return ""
}
func GetConversationIDByGroupID(groupID string) string {
return "sg_" + groupID
}
func GetConversationTableName(conversationID string) string {
return constant.ChatLogsTableNamePre + conversationID
}
func GetTableName(conversationID string) string {
return constant.ChatLogsTableNamePre + conversationID
}
func GetErrTableName(conversationID string) string {
return constant.SuperGroupErrChatLogsTableNamePre + conversationID
}
type Comparable interface {
~int | ~string | ~float64 | ~int32
}
func RemoveRepeatedElementsInList[T Comparable](slc []T) []T {
var result []T
tempMap := map[T]struct{}{}
for _, e := range slc {
if _, found := tempMap[e]; !found {
tempMap[e] = struct{}{}
result = append(result, e)
}
}
return result
}
func RemoveOneInList[T comparable](slice []T, val T) []T {
for i, v := range slice {
if v == val {
return append(slice[:i], slice[i+1:]...)
}
}
return slice
}
/*
*
KMP
*
*/
func KMP(rMainString string, rSubString string) (isInMainString bool) {
mainString := strings.ToLower(rMainString)
subString := strings.ToLower(rSubString)
mainIdx := 0
subIdx := 0
mainLen := len(mainString)
subLen := len(subString)
next := computeNextArray(subString)
for {
if mainIdx >= mainLen || subIdx >= subLen {
break
}
if mainString[mainIdx] == subString[subIdx] {
mainIdx++
subIdx++
} else {
if subIdx != 0 {
subIdx = next[subIdx-1]
} else {
mainIdx++
}
}
}
if subIdx >= subLen {
if mainIdx-subLen >= 0 {
return true
}
}
return false
}
func computeNextArray(subString string) []int {
next := make([]int, len(subString))
index := 0
i := 1
for i < len(subString) {
if subString[i] == subString[index] {
next[i] = index + 1
i++
index++
} else {
if index != 0 {
index = next[index-1]
} else {
i++
}
}
}
return next
}
func TrimStringList(list []string) (result []string) {
for _, v := range list {
if len(strings.Trim(v, " ")) != 0 {
result = append(result, v)
}
}
return result
}
// Get the intersection of two slices
func Intersect(slice1, slice2 []int64) []int64 {
m := make(map[int64]bool)
n := make([]int64, 0)
for _, v := range slice1 {
m[v] = true
}
for _, v := range slice2 {
flag, _ := m[v]
if flag {
n = append(n, v)
}
}
return n
}
// Get the diff of two slices
func DifferenceSubset(mainSlice, subSlice []int64) []int64 {
m := make(map[int64]bool)
n := make([]int64, 0)
for _, v := range subSlice {
m[v] = true
}
for _, v := range mainSlice {
if !m[v] {
n = append(n, v)
}
}
return n
}
func DifferenceSubsetString(mainSlice, subSlice []string) []string {
m := make(map[string]bool)
n := make([]string, 0)
for _, v := range subSlice {
m[v] = true
}
for _, v := range mainSlice {
if !m[v] {
n = append(n, v)
}
}
return n
}
func JsonDataOne(pb proto.Message) map[string]interface{} {
return ProtoToMap(pb, false)
}
func ProtoToMap(pb proto.Message, idFix bool) map[string]interface{} {
marshaler := jsonpb.Marshaler{
OrigName: true,
EnumsAsInts: false,
EmitDefaults: true,
}
s, _ := marshaler.MarshalToString(pb)
out := make(map[string]interface{})
json.Unmarshal([]byte(s), &out)
if idFix {
if _, ok := out["id"]; ok {
out["_id"] = out["id"]
delete(out, "id")
}
}
return out
}
func GetUserIDForMinSeq(userID string) string {
return "u_" + userID
}
func GetGroupIDForMinSeq(groupID string) string {
return "g_" + groupID
}
func TimeStringToTime(timeString string) (time.Time, error) {
t, err := time.Parse("2006-01-02", timeString)
return t, err
}
func TimeToString(t time.Time) string {
return t.Format("2006-01-02")
}
func Uint32ListConvert(list []uint32) []int64 {
var result []int64
for _, v := range list {
result = append(result, int64(v))
}
return result
}
func UnmarshalNotificationElem(bytes []byte, t interface{}) error {
var n sdk_struct.NotificationElem
err := JsonStringToStruct(string(bytes), &n)
if err != nil {
return err
}
err = JsonStringToStruct(n.Detail, t)
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,57 @@
# OpenIM SDK Version Management
OpenIM SDK uses a unique approach to version management by integrating principles from the Kubernetes project version management design.
## Versioning Methodology:
Whenever you run the server CTL via the `go build` command, the system will automatically obtain the current `git commit hash`. This commit hash is then set as the version number and written to the `pkg/version/version.go` file.
This approach ensures that each build is distinct and can be traced back to the specific commit hash from which it was built. It is a transparent and easy way to track changes and modifications across different versions of the SDK.
## How to Check Version:
- **Server Version**: Use the command `imctl version`.
- **Client Version**: Execute the command `go run main.go version`.
## SDK Versioning:
1. **Traditional SDK Versioning**: The standard method of versioning that uses Major, Minor, and Patch numbers.
2. **Client-Represented Versioning**: This is primarily managed through the Go versioning system. It helps in understanding the compatibility and dependencies.
## Code for Version Management:
### Utility to Compare Version Strings:
This function compares two version strings that follow the OpenIM versioning pattern.
```
goCopy codefunc CompareOpenIMAwareVersionStrings(v1, v2 string) int {
...
}
```
### Information Structure for Version:
This struct contains various version-related information, making it easy to understand and process the build details.
```
goCopy codetype Info struct {
...
}
func (info Info) String() string {
...
}
func Get() Info {
...
}
```
## Conclusion:
Effective version management is crucial for the growth and stability of any SDK. With OpenIM SDK's approach, users can be confident about the build's origin and its compatibility. The code snippets provided above can be utilized to integrate this versioning mechanism into any project seamlessly.
------
Hope this helps!

View File

@@ -0,0 +1,47 @@
package version
// Base version information.
//
// This is the fallback data used when version information from git is not
// provided via go ldflags. It provides an approximation of the OpenIM
// version for ad-hoc builds (e.g. `go build`) that cannot get the version
// information from git.
//
// If you are looking at these fields in the git tree, they look
// strange. They are modified on the fly by the build process. The
// in-tree values are dummy values used for "git archive", which also
// works for GitHub tar downloads.
//
// When releasing a new OpenIM version, this file is updated by
// build/mark_new_version.sh to reflect the new version, and then a
// git annotated tag (using format vX.Y where X == Major version and Y
// == Minor version) is created to point to the commit that updates
// pkg/version/base.go.
var (
// TODO: Deprecate gitMajor and gitMinor, use only gitVersion
// instead. First step in deprecation, keep the fields but make
// them irrelevant. (Next we'll take it out, which may muck with
// scripts consuming the imctl version output - but most of
// these should be looking at gitVersion already anyways.)
gitMajor string = "" // major version, always numeric
gitMinor string = "" // minor version, numeric possibly followed by "+"
// semantic version, derived by build scripts (see
// https://git.k8s.io/community/contributors/design-proposals/release/versioning.md
// for a detailed discussion of this field)
//
// TODO: This field is still called "gitVersion" for legacy
// reasons. For prerelease versions, the build metadata on the
// semantic version is a git hash, but the version itself is no
// longer the direct output of "git describe", but a slight
// translation to be semver compliant.
// NOTE: The $Format strings are replaced during 'git archive' thanks to the
// companion .gitattributes file containing 'export-subst' in this same
// directory. See also https://git-scm.com/docs/gitattributes
gitVersion string = "v0.0.0-main+$Format:%h$"
gitCommit string = "$Format:%H$" // sha1 from git, output of $(git rev-parse HEAD)
gitTreeState string = "" // state of git tree, either "clean" or "dirty"
buildDate string = "1970-01-01T00:00:00Z" // build date in ISO8601 format, output of $(date -u +'%Y-%m-%dT%H:%M:%SZ')
)

View File

@@ -0,0 +1,72 @@
package version
import (
"regexp"
"strconv"
"strings"
)
type versionType int
const (
// Bigger the version type number, higher priority it is
versionTypeAlpha versionType = iota
versionTypeBeta
versionTypeGA
)
var OpenIMVersionRegex = regexp.MustCompile("^v([\\d]+)(?:(alpha|beta)([\\d]+))?$")
func parseOpenIMVersion(v string) (majorVersion int, vType versionType, minorVersion int, ok bool) {
var err error
submatches := OpenIMVersionRegex.FindStringSubmatch(v)
if len(submatches) != 4 {
return 0, 0, 0, false
}
switch submatches[2] {
case "alpha":
vType = versionTypeAlpha
case "beta":
vType = versionTypeBeta
case "":
vType = versionTypeGA
default:
return 0, 0, 0, false
}
if majorVersion, err = strconv.Atoi(submatches[1]); err != nil {
return 0, 0, 0, false
}
if vType != versionTypeGA {
if minorVersion, err = strconv.Atoi(submatches[3]); err != nil {
return 0, 0, 0, false
}
}
return majorVersion, vType, minorVersion, true
}
// CompareOpenIMAwareVersionStrings compares two OpenIM-like version strings.
// OpenIM-like version strings are starting with a v, followed by a major version, optional "alpha" or "beta" strings
// followed by a minor version (e.g. v1, v2beta1). Versions will be sorted based on GA/alpha/beta first and then major
// and minor versions. e.g. v2, v1, v1beta2, v1beta1, v1alpha1.
func CompareOpenIMAwareVersionStrings(v1, v2 string) int {
if v1 == v2 {
return 0
}
v1major, v1type, v1minor, ok1 := parseOpenIMVersion(v1)
v2major, v2type, v2minor, ok2 := parseOpenIMVersion(v2)
switch {
case !ok1 && !ok2:
return strings.Compare(v2, v1)
case !ok1 && ok2:
return -1
case ok1 && !ok2:
return 1
}
if v1type != v2type {
return int(v1type) - int(v2type)
}
if v1major != v2major {
return v1major - v2major
}
return v1minor - v2minor
}

View File

@@ -0,0 +1,105 @@
package version
import (
"testing"
)
func TestCompareOpenIMAwareVersionStrings(t *testing.T) {
tests := []*struct {
v1, v2 string
expectedGreater bool
}{
{"v1", "v2", false},
{"v2", "v1", true},
{"v10", "v2", true},
{"v1", "v2alpha1", true},
{"v1", "v2beta1", true},
{"v1alpha2", "v1alpha1", true},
{"v1beta1", "v2alpha3", true},
{"v1alpha10", "v1alpha2", true},
{"v1beta10", "v1beta2", true},
{"foo", "v1beta2", false},
{"bar", "foo", true},
{"version1", "version2", true}, // Non OpenIM-like versions are sorted alphabetically
{"version1", "version10", true}, // Non OpenIM-like versions are sorted alphabetically
}
for _, tc := range tests {
if e, a := tc.expectedGreater, CompareOpenIMAwareVersionStrings(tc.v1, tc.v2) > 0; e != a {
if e {
t.Errorf("expected %s to be greater than %s", tc.v1, tc.v2)
} else {
t.Errorf("expected %s to be less than %s", tc.v1, tc.v2)
}
}
}
}
func Test_parseOpenIMVersion(t *testing.T) {
tests := []struct {
name string
v string
wantMajorVersion int
wantVType versionType
wantMinorVersion int
wantOk bool
}{
{
name: "invaild version for ga",
v: "v1.1",
wantMajorVersion: 0,
wantVType: 0,
wantMinorVersion: 0,
wantOk: false,
},
{
name: "invaild version for alpha",
v: "v1alpha1.1",
wantMajorVersion: 0,
wantVType: 0,
wantMinorVersion: 0,
wantOk: false,
},
{
name: "alpha version",
v: "v1alpha1",
wantMajorVersion: 1,
wantVType: 0,
wantMinorVersion: 1,
wantOk: true,
},
{
name: "beta version",
v: "v2beta10",
wantMajorVersion: 2,
wantVType: 1,
wantMinorVersion: 10,
wantOk: true,
},
{
name: "ga version",
v: "v3",
wantMajorVersion: 3,
wantVType: 2,
wantMinorVersion: 0,
wantOk: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotMajorVersion, gotVType, gotMinorVersion, gotOk := parseOpenIMVersion(tt.v)
if gotMajorVersion != tt.wantMajorVersion {
t.Errorf("parseOpenIMVersion() gotMajorVersion = %v, want %v", gotMajorVersion, tt.wantMajorVersion)
}
if gotVType != tt.wantVType {
t.Errorf("parseOpenIMVersion() gotVType = %v, want %v", gotVType, tt.wantVType)
}
if gotMinorVersion != tt.wantMinorVersion {
t.Errorf("parseOpenIMVersion() gotMinorVersion = %v, want %v", gotMinorVersion, tt.wantMinorVersion)
}
if gotOk != tt.wantOk {
t.Errorf("parseOpenIMVersion() gotOk = %v, want %v", gotOk, tt.wantOk)
}
})
}
}

View File

@@ -0,0 +1,21 @@
package version
// Info contains versioning information.
// TODO: Add []string of api versions supported? It's still unclear
// how we'll want to distribute that information.
type Info struct {
Major string `json:"major"`
Minor string `json:"minor"`
GitVersion string `json:"gitVersion"`
GitCommit string `json:"gitCommit"`
GitTreeState string `json:"gitTreeState"`
BuildDate string `json:"buildDate"`
GoVersion string `json:"goVersion"`
Compiler string `json:"compiler"`
Platform string `json:"platform"`
}
// String returns info as a human-friendly version string.
func (info Info) String() string {
return info.GitVersion
}

View File

@@ -0,0 +1,24 @@
package version
import (
"fmt"
"runtime"
)
// Get returns the overall codebase version. It's for detecting
// what code a binary was built from.
func Get() Info {
// These variables typically come from -ldflags settings and in
// their absence fallback to the settings in pkg/version/base.go
return Info{
Major: gitMajor,
Minor: gitMinor,
GitVersion: gitVersion,
GitCommit: gitCommit,
GitTreeState: gitTreeState,
BuildDate: buildDate,
GoVersion: runtime.Version(),
Compiler: runtime.Compiler,
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
}
}