feat: incr sync version.
This commit is contained in:
43
go/chao-sdk-core/internal/user/convert.go
Normal file
43
go/chao-sdk-core/internal/user/convert.go
Normal 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.
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
|
||||
"github.com/openimsdk/protocol/user"
|
||||
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
)
|
||||
|
||||
func ServerUserToLocalUser(user *sdkws.UserInfo) *model_struct.LocalUser {
|
||||
return &model_struct.LocalUser{
|
||||
UserID: user.UserID,
|
||||
Nickname: user.Nickname,
|
||||
FaceURL: user.FaceURL,
|
||||
CreateTime: user.CreateTime,
|
||||
Ex: user.Ex,
|
||||
//AppMangerLevel: user.AppMangerLevel,
|
||||
GlobalRecvMsgOpt: user.GlobalRecvMsgOpt,
|
||||
//AttachedInfo: user.AttachedInfo,
|
||||
}
|
||||
}
|
||||
func ServerCommandToLocalCommand(data *user.AllCommandInfoResp) *model_struct.LocalUserCommand {
|
||||
return &model_struct.LocalUserCommand{
|
||||
Type: data.Type,
|
||||
CreateTime: data.CreateTime,
|
||||
Uuid: data.Uuid,
|
||||
Value: data.Value,
|
||||
}
|
||||
}
|
||||
89
go/chao-sdk-core/internal/user/sdk.go
Normal file
89
go/chao-sdk-core/internal/user/sdk.go
Normal file
@@ -0,0 +1,89 @@
|
||||
// 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 user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/internal/util"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
|
||||
pbUser "github.com/openimsdk/protocol/user"
|
||||
userPb "github.com/openimsdk/protocol/user"
|
||||
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
)
|
||||
|
||||
func (u *User) GetUsersInfo(ctx context.Context, userIDs []string) ([]*model_struct.LocalUser, error) {
|
||||
return u.GetUsersInfoFromSvr(ctx, userIDs)
|
||||
}
|
||||
|
||||
func (u *User) GetSelfUserInfo(ctx context.Context) (*model_struct.LocalUser, error) {
|
||||
return u.getSelfUserInfo(ctx)
|
||||
}
|
||||
|
||||
// Deprecated: user SetSelfInfoEx instead
|
||||
func (u *User) SetSelfInfo(ctx context.Context, userInfo *sdkws.UserInfo) error {
|
||||
return u.updateSelfUserInfo(ctx, userInfo)
|
||||
}
|
||||
func (u *User) SetSelfInfoEx(ctx context.Context, userInfo *sdkws.UserInfoWithEx) error {
|
||||
return u.updateSelfUserInfoEx(ctx, userInfo)
|
||||
}
|
||||
func (u *User) SetGlobalRecvMessageOpt(ctx context.Context, opt int) error {
|
||||
if err := util.ApiPost(ctx, constant.SetGlobalRecvMessageOptRouter,
|
||||
&pbUser.SetGlobalRecvMessageOptReq{UserID: u.loginUserID, GlobalRecvMsgOpt: int32(opt)}, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
u.SyncLoginUserInfo(ctx)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) UpdateMsgSenderInfo(ctx context.Context, nickname, faceURL string) (err error) {
|
||||
if nickname != "" {
|
||||
if err = u.DataBase.UpdateMsgSenderNickname(ctx, u.loginUserID, nickname, constant.SingleChatType); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if faceURL != "" {
|
||||
if err = u.DataBase.UpdateMsgSenderFaceURL(ctx, u.loginUserID, faceURL, constant.SingleChatType); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) SubscribeUsersStatus(ctx context.Context, userIDs []string) ([]*userPb.OnlineStatus, error) {
|
||||
userStatus, err := u.subscribeUsersStatus(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
u.OnlineStatusCache.DeleteAll()
|
||||
u.OnlineStatusCache.StoreAll(func(value *userPb.OnlineStatus) string {
|
||||
return value.UserID
|
||||
}, userStatus)
|
||||
return userStatus, nil
|
||||
}
|
||||
|
||||
func (u *User) UnsubscribeUsersStatus(ctx context.Context, userIDs []string) error {
|
||||
u.OnlineStatusCache.DeleteAll()
|
||||
return u.unsubscribeUsersStatus(ctx, userIDs)
|
||||
}
|
||||
|
||||
func (u *User) GetSubscribeUsersStatus(ctx context.Context) ([]*userPb.OnlineStatus, error) {
|
||||
return u.getSubscribeUsersStatus(ctx)
|
||||
}
|
||||
|
||||
func (u *User) GetUserStatus(ctx context.Context, userIDs []string) ([]*userPb.OnlineStatus, error) {
|
||||
return u.getUserStatus(ctx, userIDs)
|
||||
}
|
||||
97
go/chao-sdk-core/internal/user/sync.go
Normal file
97
go/chao-sdk-core/internal/user/sync.go
Normal file
@@ -0,0 +1,97 @@
|
||||
// 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 user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/internal/util"
|
||||
"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"
|
||||
userPb "github.com/openimsdk/protocol/user"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func (u *User) SyncLoginUserInfo(ctx context.Context) error {
|
||||
remoteUser, err := u.GetSingleUserFromSvr(ctx, u.loginUserID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
localUser, err := u.GetLoginUser(ctx, u.loginUserID)
|
||||
if err != nil && errs.Unwrap(err) != gorm.ErrRecordNotFound {
|
||||
log.ZError(ctx, "SyncLoginUserInfo", err)
|
||||
}
|
||||
var localUsers []*model_struct.LocalUser
|
||||
if err == nil {
|
||||
localUsers = []*model_struct.LocalUser{localUser}
|
||||
}
|
||||
log.ZDebug(ctx, "SyncLoginUserInfo", "remoteUser", remoteUser, "localUser", localUser)
|
||||
return u.userSyncer.Sync(ctx, []*model_struct.LocalUser{remoteUser}, localUsers, nil)
|
||||
}
|
||||
|
||||
func (u *User) SyncUserStatus(ctx context.Context, fromUserID string, status int32, platformID int32) {
|
||||
userOnlineStatus := userPb.OnlineStatus{
|
||||
UserID: fromUserID,
|
||||
Status: status,
|
||||
PlatformIDs: []int32{platformID},
|
||||
}
|
||||
if v, ok := u.OnlineStatusCache.Load(fromUserID); ok {
|
||||
if status == constant.Online {
|
||||
v.PlatformIDs = utils.RemoveRepeatedElementsInList(append(v.PlatformIDs, platformID))
|
||||
u.OnlineStatusCache.Store(fromUserID, v)
|
||||
} else {
|
||||
v.PlatformIDs = utils.RemoveOneInList(v.PlatformIDs, platformID)
|
||||
if len(v.PlatformIDs) == 0 {
|
||||
v.Status = constant.Offline
|
||||
v.PlatformIDs = []int32{}
|
||||
u.OnlineStatusCache.Delete(fromUserID)
|
||||
}
|
||||
}
|
||||
u.listener().OnUserStatusChanged(utils.StructToJsonString(v))
|
||||
} else {
|
||||
if status == constant.Online {
|
||||
u.OnlineStatusCache.Store(fromUserID, &userOnlineStatus)
|
||||
u.listener().OnUserStatusChanged(utils.StructToJsonString(userOnlineStatus))
|
||||
} else {
|
||||
log.ZWarn(ctx, "exception", errors.New("user not exist"), "fromUserID", fromUserID,
|
||||
"status", status, "platformID", platformID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type CommandInfoResponse struct {
|
||||
CommandResp []*userPb.AllCommandInfoResp `json:"CommandResp"`
|
||||
}
|
||||
|
||||
func (u *User) SyncAllCommand(ctx context.Context) error {
|
||||
var serverData CommandInfoResponse
|
||||
err := util.ApiPost(ctx, constant.ProcessUserCommandGetAll, userPb.ProcessUserCommandGetAllReq{
|
||||
UserID: u.loginUserID,
|
||||
}, &serverData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
localData, err := u.DataBase.ProcessUserCommandGetAll(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.ZDebug(ctx, "sync command", "data from server", serverData, "data from local", localData)
|
||||
return u.commandSyncer.Sync(ctx, datautil.Batch(ServerCommandToLocalCommand, serverData.CommandResp), localData, nil)
|
||||
}
|
||||
427
go/chao-sdk-core/internal/user/user.go
Normal file
427
go/chao-sdk-core/internal/user/user.go
Normal file
@@ -0,0 +1,427 @@
|
||||
// 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 user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/internal/cache"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/internal/util"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/db_interface"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/syncer"
|
||||
authPb "github.com/openimsdk/protocol/auth"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
userPb "github.com/openimsdk/protocol/user"
|
||||
"github.com/openimsdk/tools/log"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
|
||||
"github.com/openimsdk/openim-sdk-core/v3/open_im_sdk_callback"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/common"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
|
||||
PbConstant "github.com/openimsdk/protocol/constant"
|
||||
)
|
||||
|
||||
type BasicInfo struct {
|
||||
Nickname string
|
||||
FaceURL string
|
||||
}
|
||||
|
||||
// User is a struct that represents a user in the system.
|
||||
type User struct {
|
||||
db_interface.DataBase
|
||||
loginUserID string
|
||||
listener func() open_im_sdk_callback.OnUserListener
|
||||
userSyncer *syncer.Syncer[*model_struct.LocalUser, syncer.NoResp, string]
|
||||
commandSyncer *syncer.Syncer[*model_struct.LocalUserCommand, syncer.NoResp, string]
|
||||
conversationCh chan common.Cmd2Value
|
||||
UserBasicCache *cache.Cache[string, *BasicInfo]
|
||||
OnlineStatusCache *cache.Cache[string, *userPb.OnlineStatus]
|
||||
}
|
||||
|
||||
// SetListener sets the user's listener.
|
||||
func (u *User) SetListener(listener func() open_im_sdk_callback.OnUserListener) {
|
||||
u.listener = listener
|
||||
}
|
||||
|
||||
// NewUser creates a new User object.
|
||||
func NewUser(dataBase db_interface.DataBase, loginUserID string, conversationCh chan common.Cmd2Value) *User {
|
||||
user := &User{DataBase: dataBase, loginUserID: loginUserID, conversationCh: conversationCh}
|
||||
user.initSyncer()
|
||||
user.UserBasicCache = cache.NewCache[string, *BasicInfo]()
|
||||
user.OnlineStatusCache = cache.NewCache[string, *userPb.OnlineStatus]()
|
||||
return user
|
||||
}
|
||||
|
||||
func (u *User) initSyncer() {
|
||||
u.userSyncer = syncer.New[*model_struct.LocalUser, syncer.NoResp, string](
|
||||
func(ctx context.Context, value *model_struct.LocalUser) error {
|
||||
return u.InsertLoginUser(ctx, value)
|
||||
},
|
||||
func(ctx context.Context, value *model_struct.LocalUser) error {
|
||||
return fmt.Errorf("not support delete user %s", value.UserID)
|
||||
},
|
||||
func(ctx context.Context, serverUser, localUser *model_struct.LocalUser) error {
|
||||
return u.DataBase.UpdateLoginUser(context.Background(), serverUser)
|
||||
},
|
||||
func(user *model_struct.LocalUser) string {
|
||||
return user.UserID
|
||||
},
|
||||
nil,
|
||||
func(ctx context.Context, state int, server, local *model_struct.LocalUser) error {
|
||||
switch state {
|
||||
case syncer.Update:
|
||||
u.listener().OnSelfInfoUpdated(utils.StructToJsonString(server))
|
||||
if server.Nickname != local.Nickname || server.FaceURL != local.FaceURL {
|
||||
_ = common.TriggerCmdUpdateMessage(ctx, common.UpdateMessageNode{Action: constant.UpdateMsgFaceUrlAndNickName,
|
||||
Args: common.UpdateMessageInfo{SessionType: constant.SingleChatType, UserID: server.UserID, FaceURL: server.FaceURL, Nickname: server.Nickname}}, u.conversationCh)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
u.commandSyncer = syncer.New[*model_struct.LocalUserCommand, syncer.NoResp, string](
|
||||
func(ctx context.Context, command *model_struct.LocalUserCommand) error {
|
||||
// Logic to insert a command
|
||||
return u.DataBase.ProcessUserCommandAdd(ctx, command)
|
||||
},
|
||||
func(ctx context.Context, command *model_struct.LocalUserCommand) error {
|
||||
// Logic to delete a command
|
||||
return u.DataBase.ProcessUserCommandDelete(ctx, command)
|
||||
},
|
||||
func(ctx context.Context, serverCommand *model_struct.LocalUserCommand, localCommand *model_struct.LocalUserCommand) error {
|
||||
// Logic to update a command
|
||||
if serverCommand == nil || localCommand == nil {
|
||||
return fmt.Errorf("nil command reference")
|
||||
}
|
||||
return u.DataBase.ProcessUserCommandUpdate(ctx, serverCommand)
|
||||
},
|
||||
func(command *model_struct.LocalUserCommand) string {
|
||||
// Return a unique identifier for the command
|
||||
if command == nil {
|
||||
return ""
|
||||
}
|
||||
return command.Uuid
|
||||
},
|
||||
func(a *model_struct.LocalUserCommand, b *model_struct.LocalUserCommand) bool {
|
||||
// Compare two commands to check if they are equal
|
||||
if a == nil || b == nil {
|
||||
return false
|
||||
}
|
||||
return a.Uuid == b.Uuid && a.Type == b.Type && a.Value == b.Value
|
||||
},
|
||||
func(ctx context.Context, state int, serverCommand *model_struct.LocalUserCommand, localCommand *model_struct.LocalUserCommand) error {
|
||||
if u.listener == nil {
|
||||
return nil
|
||||
}
|
||||
switch state {
|
||||
case syncer.Delete:
|
||||
u.listener().OnUserCommandDelete(utils.StructToJsonString(serverCommand))
|
||||
case syncer.Update:
|
||||
u.listener().OnUserCommandUpdate(utils.StructToJsonString(serverCommand))
|
||||
case syncer.Insert:
|
||||
u.listener().OnUserCommandAdd(utils.StructToJsonString(serverCommand))
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
//func (u *User) equal(a, b *model_struct.LocalUser) bool {
|
||||
// if a.CreateTime != b.CreateTime {
|
||||
// log.ZDebug(context.Background(), "user equal", "a", a.CreateTime, "b", b.CreateTime)
|
||||
// }
|
||||
// if a.UserID != b.UserID {
|
||||
// log.ZDebug(context.Background(), "user equal", "a", a.UserID, "b", b.UserID)
|
||||
// }
|
||||
// if a.Ex != b.Ex {
|
||||
// log.ZDebug(context.Background(), "user equal", "a", a.Ex, "b", b.Ex)
|
||||
// }
|
||||
//
|
||||
// if a.Nickname != b.Nickname {
|
||||
// log.ZDebug(context.Background(), "user equal", "a", a.Nickname, "b", b.Nickname)
|
||||
// }
|
||||
// if a.FaceURL != b.FaceURL {
|
||||
// log.ZDebug(context.Background(), "user equal", "a", a.FaceURL, "b", b.FaceURL)
|
||||
// }
|
||||
// if a.AttachedInfo != b.AttachedInfo {
|
||||
// log.ZDebug(context.Background(), "user equal", "a", a.AttachedInfo, "b", b.AttachedInfo)
|
||||
// }
|
||||
// if a.GlobalRecvMsgOpt != b.GlobalRecvMsgOpt {
|
||||
// log.ZDebug(context.Background(), "user equal", "a", a.GlobalRecvMsgOpt, "b", b.GlobalRecvMsgOpt)
|
||||
// }
|
||||
// if a.AppMangerLevel != b.AppMangerLevel {
|
||||
// log.ZDebug(context.Background(), "user equal", "a", a.AppMangerLevel, "b", b.AppMangerLevel)
|
||||
// }
|
||||
// return a.UserID == b.UserID && a.Nickname == b.Nickname && a.FaceURL == b.FaceURL &&
|
||||
// a.CreateTime == b.CreateTime && a.AttachedInfo == b.AttachedInfo &&
|
||||
// a.Ex == b.Ex && a.GlobalRecvMsgOpt == b.GlobalRecvMsgOpt && a.AppMangerLevel == b.AppMangerLevel
|
||||
//}
|
||||
|
||||
// DoNotification handles incoming notifications for the user.
|
||||
func (u *User) DoNotification(ctx context.Context, msg *sdkws.MsgData) {
|
||||
log.ZDebug(ctx, "user notification", "msg", *msg)
|
||||
go func() {
|
||||
switch msg.ContentType {
|
||||
case constant.UserInfoUpdatedNotification:
|
||||
u.userInfoUpdatedNotification(ctx, msg)
|
||||
case constant.UserStatusChangeNotification:
|
||||
u.userStatusChangeNotification(ctx, msg)
|
||||
case constant.UserCommandAddNotification:
|
||||
u.userCommandAddNotification(ctx, msg)
|
||||
case constant.UserCommandDeleteNotification:
|
||||
u.userCommandDeleteNotification(ctx, msg)
|
||||
case constant.UserCommandUpdateNotification:
|
||||
u.userCommandUpdateNotification(ctx, msg)
|
||||
default:
|
||||
// log.Error(operationID, "type failed ", msg.ClientMsgID, msg.ServerMsgID, msg.ContentType)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// userInfoUpdatedNotification handles notifications about updated user information.
|
||||
func (u *User) userInfoUpdatedNotification(ctx context.Context, msg *sdkws.MsgData) {
|
||||
log.ZDebug(ctx, "userInfoUpdatedNotification", "msg", *msg)
|
||||
tips := sdkws.UserInfoUpdatedTips{}
|
||||
if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil {
|
||||
log.ZError(ctx, "comm.UnmarshalTips failed", err, "msg", msg.Content)
|
||||
return
|
||||
}
|
||||
|
||||
if tips.UserID == u.loginUserID {
|
||||
u.SyncLoginUserInfo(ctx)
|
||||
} else {
|
||||
log.ZDebug(ctx, "detail.UserID != u.loginUserID, do nothing", "detail.UserID", tips.UserID, "u.loginUserID", u.loginUserID)
|
||||
}
|
||||
}
|
||||
|
||||
// userStatusChangeNotification get subscriber status change callback
|
||||
func (u *User) userStatusChangeNotification(ctx context.Context, msg *sdkws.MsgData) {
|
||||
log.ZDebug(ctx, "userStatusChangeNotification", "msg", *msg)
|
||||
tips := sdkws.UserStatusChangeTips{}
|
||||
if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil {
|
||||
log.ZError(ctx, "comm.UnmarshalTips failed", err, "msg", msg.Content)
|
||||
return
|
||||
}
|
||||
if tips.FromUserID == u.loginUserID {
|
||||
log.ZDebug(ctx, "self terminal login", "tips", tips)
|
||||
return
|
||||
}
|
||||
u.SyncUserStatus(ctx, tips.FromUserID, tips.Status, tips.PlatformID)
|
||||
}
|
||||
|
||||
// userCommandAddNotification handle notification when user add favorite
|
||||
func (u *User) userCommandAddNotification(ctx context.Context, msg *sdkws.MsgData) {
|
||||
log.ZDebug(ctx, "userCommandAddNotification", "msg", *msg)
|
||||
tip := sdkws.UserCommandAddTips{}
|
||||
if tip.ToUserID == u.loginUserID {
|
||||
u.SyncAllCommand(ctx)
|
||||
} else {
|
||||
log.ZDebug(ctx, "ToUserID != u.loginUserID, do nothing", "detail.UserID", tip.ToUserID, "u.loginUserID", u.loginUserID)
|
||||
}
|
||||
}
|
||||
|
||||
// userCommandDeleteNotification handle notification when user delete favorite
|
||||
func (u *User) userCommandDeleteNotification(ctx context.Context, msg *sdkws.MsgData) {
|
||||
log.ZDebug(ctx, "userCommandAddNotification", "msg", *msg)
|
||||
tip := sdkws.UserCommandDeleteTips{}
|
||||
if tip.ToUserID == u.loginUserID {
|
||||
u.SyncAllCommand(ctx)
|
||||
} else {
|
||||
log.ZDebug(ctx, "ToUserID != u.loginUserID, do nothing", "detail.UserID", tip.ToUserID, "u.loginUserID", u.loginUserID)
|
||||
}
|
||||
}
|
||||
|
||||
// userCommandUpdateNotification handle notification when user update favorite
|
||||
func (u *User) userCommandUpdateNotification(ctx context.Context, msg *sdkws.MsgData) {
|
||||
log.ZDebug(ctx, "userCommandAddNotification", "msg", *msg)
|
||||
tip := sdkws.UserCommandUpdateTips{}
|
||||
if tip.ToUserID == u.loginUserID {
|
||||
u.SyncAllCommand(ctx)
|
||||
} else {
|
||||
log.ZDebug(ctx, "ToUserID != u.loginUserID, do nothing", "detail.UserID", tip.ToUserID, "u.loginUserID", u.loginUserID)
|
||||
}
|
||||
}
|
||||
|
||||
// GetUsersInfoFromSvr retrieves user information from the server.
|
||||
func (u *User) GetUsersInfoFromSvr(ctx context.Context, userIDs []string) ([]*model_struct.LocalUser, error) {
|
||||
resp, err := util.CallApi[userPb.GetDesignateUsersResp](ctx, constant.GetUsersInfoRouter, userPb.GetDesignateUsersReq{UserIDs: userIDs})
|
||||
if err != nil {
|
||||
return nil, sdkerrs.WrapMsg(err, "GetUsersInfoFromSvr failed")
|
||||
}
|
||||
return datautil.Batch(ServerUserToLocalUser, resp.UsersInfo), nil
|
||||
}
|
||||
|
||||
// GetSingleUserFromSvr retrieves user information from the server.
|
||||
func (u *User) GetSingleUserFromSvr(ctx context.Context, userID string) (*model_struct.LocalUser, error) {
|
||||
users, err := u.GetUsersInfoFromSvr(ctx, []string{userID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(users) > 0 {
|
||||
return users[0], nil
|
||||
}
|
||||
return nil, sdkerrs.ErrUserIDNotFound.WrapMsg(fmt.Sprintf("getSelfUserInfo failed, userID: %s not exist", userID))
|
||||
}
|
||||
|
||||
// getSelfUserInfo retrieves the user's information.
|
||||
func (u *User) getSelfUserInfo(ctx context.Context) (*model_struct.LocalUser, error) {
|
||||
userInfo, errLocal := u.GetLoginUser(ctx, u.loginUserID)
|
||||
if errLocal != nil {
|
||||
srvUserInfo, errServer := u.GetServerUserInfo(ctx, []string{u.loginUserID})
|
||||
if errServer != nil {
|
||||
return nil, errServer
|
||||
}
|
||||
if len(srvUserInfo) == 0 {
|
||||
return nil, sdkerrs.ErrUserIDNotFound
|
||||
}
|
||||
userInfo = ServerUserToLocalUser(srvUserInfo[0])
|
||||
_ = u.InsertLoginUser(ctx, userInfo)
|
||||
}
|
||||
return userInfo, nil
|
||||
}
|
||||
|
||||
// updateSelfUserInfo updates the user's information.
|
||||
func (u *User) updateSelfUserInfo(ctx context.Context, userInfo *sdkws.UserInfo) error {
|
||||
userInfo.UserID = u.loginUserID
|
||||
if err := util.ApiPost(ctx, constant.UpdateSelfUserInfoRouter, userPb.UpdateUserInfoReq{UserInfo: userInfo}, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = u.SyncLoginUserInfo(ctx)
|
||||
return nil
|
||||
}
|
||||
|
||||
// updateSelfUserInfoEx updates the user's information with Ex field.
|
||||
func (u *User) updateSelfUserInfoEx(ctx context.Context, userInfo *sdkws.UserInfoWithEx) error {
|
||||
userInfo.UserID = u.loginUserID
|
||||
if err := util.ApiPost(ctx, constant.UpdateSelfUserInfoExRouter, userPb.UpdateUserInfoExReq{UserInfo: userInfo}, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = u.SyncLoginUserInfo(ctx)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CRUD user command
|
||||
func (u *User) ProcessUserCommandAdd(ctx context.Context, userCommand *userPb.ProcessUserCommandAddReq) error {
|
||||
if err := util.ApiPost(ctx, constant.ProcessUserCommandAdd, userPb.ProcessUserCommandAddReq{UserID: u.loginUserID, Type: userCommand.Type, Uuid: userCommand.Uuid, Value: userCommand.Value}, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return u.SyncAllCommand(ctx)
|
||||
|
||||
}
|
||||
|
||||
// ProcessUserCommandDelete delete user's choice
|
||||
func (u *User) ProcessUserCommandDelete(ctx context.Context, userCommand *userPb.ProcessUserCommandDeleteReq) error {
|
||||
if err := util.ApiPost(ctx, constant.ProcessUserCommandDelete, userPb.ProcessUserCommandDeleteReq{UserID: u.loginUserID,
|
||||
Type: userCommand.Type, Uuid: userCommand.Uuid}, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return u.SyncAllCommand(ctx)
|
||||
}
|
||||
|
||||
// ProcessUserCommandUpdate update user's choice
|
||||
func (u *User) ProcessUserCommandUpdate(ctx context.Context, userCommand *userPb.ProcessUserCommandUpdateReq) error {
|
||||
if err := util.ApiPost(ctx, constant.ProcessUserCommandUpdate, userPb.ProcessUserCommandUpdateReq{UserID: u.loginUserID,
|
||||
Type: userCommand.Type, Uuid: userCommand.Uuid, Value: userCommand.Value}, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return u.SyncAllCommand(ctx)
|
||||
}
|
||||
|
||||
// ProcessUserCommandGet get user's choice
|
||||
func (u *User) ProcessUserCommandGetAll(ctx context.Context) ([]*userPb.CommandInfoResp, error) {
|
||||
localCommands, err := u.DataBase.ProcessUserCommandGetAll(ctx)
|
||||
if err != nil {
|
||||
return nil, err // Handle the error appropriately
|
||||
}
|
||||
|
||||
var result []*userPb.CommandInfoResp
|
||||
for _, localCommand := range localCommands {
|
||||
result = append(result, &userPb.CommandInfoResp{
|
||||
Type: localCommand.Type,
|
||||
CreateTime: localCommand.CreateTime,
|
||||
Uuid: localCommand.Uuid,
|
||||
Value: localCommand.Value,
|
||||
})
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ParseTokenFromSvr parses a token from the server.
|
||||
func (u *User) ParseTokenFromSvr(ctx context.Context) (int64, error) {
|
||||
resp, err := util.CallApi[authPb.ParseTokenResp](ctx, constant.ParseTokenRouter, authPb.ParseTokenReq{})
|
||||
return resp.ExpireTimeSeconds, err
|
||||
}
|
||||
|
||||
// GetServerUserInfo retrieves user information from the server.
|
||||
func (u *User) GetServerUserInfo(ctx context.Context, userIDs []string) ([]*sdkws.UserInfo, error) {
|
||||
resp, err := util.CallApi[userPb.GetDesignateUsersResp](ctx, constant.GetUsersInfoRouter, &userPb.GetDesignateUsersReq{UserIDs: userIDs})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.UsersInfo, nil
|
||||
}
|
||||
|
||||
// subscribeUsersStatus Presence status of subscribed users.
|
||||
func (u *User) subscribeUsersStatus(ctx context.Context, userIDs []string) ([]*userPb.OnlineStatus, error) {
|
||||
resp, err := util.CallApi[userPb.SubscribeOrCancelUsersStatusResp](ctx, constant.SubscribeUsersStatusRouter, &userPb.SubscribeOrCancelUsersStatusReq{
|
||||
UserID: u.loginUserID,
|
||||
UserIDs: userIDs,
|
||||
Genre: PbConstant.SubscriberUser,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.StatusList, nil
|
||||
}
|
||||
|
||||
// unsubscribeUsersStatus Unsubscribe a user's presence.
|
||||
func (u *User) unsubscribeUsersStatus(ctx context.Context, userIDs []string) error {
|
||||
_, err := util.CallApi[userPb.SubscribeOrCancelUsersStatusResp](ctx, constant.SubscribeUsersStatusRouter, &userPb.SubscribeOrCancelUsersStatusReq{
|
||||
UserID: u.loginUserID,
|
||||
UserIDs: userIDs,
|
||||
Genre: PbConstant.Unsubscribe,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getSubscribeUsersStatus Get the online status of subscribers.
|
||||
func (u *User) getSubscribeUsersStatus(ctx context.Context) ([]*userPb.OnlineStatus, error) {
|
||||
resp, err := util.CallApi[userPb.GetSubscribeUsersStatusResp](ctx, constant.GetSubscribeUsersStatusRouter, &userPb.GetSubscribeUsersStatusReq{
|
||||
UserID: u.loginUserID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.StatusList, nil
|
||||
}
|
||||
|
||||
// getUserStatus Get the online status of users.
|
||||
func (u *User) getUserStatus(ctx context.Context, userIDs []string) ([]*userPb.OnlineStatus, error) {
|
||||
resp, err := util.CallApi[userPb.GetUserStatusResp](ctx, constant.GetUserStatusRouter, &userPb.GetUserStatusReq{
|
||||
UserID: u.loginUserID,
|
||||
UserIDs: userIDs,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.StatusList, nil
|
||||
}
|
||||
Reference in New Issue
Block a user