feat: incr sync version.
This commit is contained in:
71
go/chao-sdk-core/internal/friend/conversion.go
Normal file
71
go/chao-sdk-core/internal/friend/conversion.go
Normal file
@@ -0,0 +1,71 @@
|
||||
// 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 friend
|
||||
|
||||
import (
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
)
|
||||
|
||||
func ServerFriendRequestToLocalFriendRequest(info *sdkws.FriendRequest) *model_struct.LocalFriendRequest {
|
||||
return &model_struct.LocalFriendRequest{
|
||||
FromUserID: info.FromUserID,
|
||||
FromNickname: info.FromNickname,
|
||||
FromFaceURL: info.FromFaceURL,
|
||||
//FromGender: info.FromGender,
|
||||
ToUserID: info.ToUserID,
|
||||
ToNickname: info.ToNickname,
|
||||
ToFaceURL: info.ToFaceURL,
|
||||
//ToGender: info.ToGender,
|
||||
HandleResult: info.HandleResult,
|
||||
ReqMsg: info.ReqMsg,
|
||||
CreateTime: info.CreateTime,
|
||||
HandlerUserID: info.HandlerUserID,
|
||||
HandleMsg: info.HandleMsg,
|
||||
HandleTime: info.HandleTime,
|
||||
Ex: info.Ex,
|
||||
//AttachedInfo: info.AttachedInfo,
|
||||
}
|
||||
}
|
||||
|
||||
func ServerFriendToLocalFriend(info *sdkws.FriendInfo) *model_struct.LocalFriend {
|
||||
return &model_struct.LocalFriend{
|
||||
OwnerUserID: info.OwnerUserID,
|
||||
FriendUserID: info.FriendUser.UserID,
|
||||
Remark: info.Remark,
|
||||
CreateTime: info.CreateTime,
|
||||
AddSource: info.AddSource,
|
||||
OperatorUserID: info.OperatorUserID,
|
||||
Nickname: info.FriendUser.Nickname,
|
||||
FaceURL: info.FriendUser.FaceURL,
|
||||
Ex: info.Ex,
|
||||
//AttachedInfo: info.FriendUser.AttachedInfo,
|
||||
IsPinned: info.IsPinned,
|
||||
}
|
||||
}
|
||||
|
||||
func ServerBlackToLocalBlack(info *sdkws.BlackInfo) *model_struct.LocalBlack {
|
||||
return &model_struct.LocalBlack{
|
||||
OwnerUserID: info.OwnerUserID,
|
||||
BlockUserID: info.BlackUserInfo.UserID,
|
||||
CreateTime: info.CreateTime,
|
||||
AddSource: info.AddSource,
|
||||
OperatorUserID: info.OperatorUserID,
|
||||
Nickname: info.BlackUserInfo.Nickname,
|
||||
FaceURL: info.BlackUserInfo.FaceURL,
|
||||
Ex: info.Ex,
|
||||
//AttachedInfo: info.FriendUser.AttachedInfo,
|
||||
}
|
||||
}
|
||||
199
go/chao-sdk-core/internal/friend/friend.go
Normal file
199
go/chao-sdk-core/internal/friend/friend.go
Normal file
@@ -0,0 +1,199 @@
|
||||
// Copyright 2021 OpenIM Corporation
|
||||
//
|
||||
// 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 friend
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/openimsdk/openim-sdk-core/v3/internal/user"
|
||||
"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/db/db_interface"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/page"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/syncer"
|
||||
friend "github.com/openimsdk/protocol/relation"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/tools/log"
|
||||
)
|
||||
|
||||
func NewFriend(loginUserID string, db db_interface.DataBase, user *user.User, conversationCh chan common.Cmd2Value) *Friend {
|
||||
f := &Friend{loginUserID: loginUserID, db: db, user: user, conversationCh: conversationCh}
|
||||
f.initSyncer()
|
||||
return f
|
||||
}
|
||||
|
||||
type Friend struct {
|
||||
friendListener open_im_sdk_callback.OnFriendshipListenerSdk
|
||||
loginUserID string
|
||||
db db_interface.DataBase
|
||||
user *user.User
|
||||
friendSyncer *syncer.Syncer[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string]
|
||||
blockSyncer *syncer.Syncer[*model_struct.LocalBlack, syncer.NoResp, [2]string]
|
||||
requestRecvSyncer *syncer.Syncer[*model_struct.LocalFriendRequest, syncer.NoResp, [2]string]
|
||||
requestSendSyncer *syncer.Syncer[*model_struct.LocalFriendRequest, syncer.NoResp, [2]string]
|
||||
conversationCh chan common.Cmd2Value
|
||||
listenerForService open_im_sdk_callback.OnListenerForService
|
||||
}
|
||||
|
||||
func (f *Friend) initSyncer() {
|
||||
f.friendSyncer = syncer.New2[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](
|
||||
syncer.WithInsert[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(ctx context.Context, value *model_struct.LocalFriend) error {
|
||||
return f.db.InsertFriend(ctx, value)
|
||||
}),
|
||||
syncer.WithDelete[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(ctx context.Context, value *model_struct.LocalFriend) error {
|
||||
return f.db.DeleteFriendDB(ctx, value.FriendUserID)
|
||||
}),
|
||||
syncer.WithUpdate[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(ctx context.Context, server, local *model_struct.LocalFriend) error {
|
||||
return f.db.UpdateFriend(ctx, server)
|
||||
}),
|
||||
syncer.WithUUID[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(value *model_struct.LocalFriend) [2]string {
|
||||
return [...]string{value.OwnerUserID, value.FriendUserID}
|
||||
}),
|
||||
syncer.WithNotice[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(ctx context.Context, state int, server, local *model_struct.LocalFriend) error {
|
||||
switch state {
|
||||
case syncer.Insert:
|
||||
f.friendListener.OnFriendAdded(*server)
|
||||
case syncer.Delete:
|
||||
log.ZDebug(ctx, "syncer OnFriendDeleted", "local", local)
|
||||
f.friendListener.OnFriendDeleted(*local)
|
||||
case syncer.Update:
|
||||
f.friendListener.OnFriendInfoChanged(*server)
|
||||
if local.Nickname != server.Nickname || local.FaceURL != server.FaceURL || local.Remark != server.Remark {
|
||||
if server.Remark != "" {
|
||||
server.Nickname = server.Remark
|
||||
}
|
||||
_ = common.TriggerCmdUpdateConversation(ctx, common.UpdateConNode{
|
||||
Action: constant.UpdateConFaceUrlAndNickName,
|
||||
Args: common.SourceIDAndSessionType{
|
||||
SourceID: server.FriendUserID,
|
||||
SessionType: constant.SingleChatType,
|
||||
FaceURL: server.FaceURL,
|
||||
Nickname: server.Nickname,
|
||||
},
|
||||
}, f.conversationCh)
|
||||
_ = common.TriggerCmdUpdateMessage(ctx, common.UpdateMessageNode{
|
||||
Action: constant.UpdateMsgFaceUrlAndNickName,
|
||||
Args: common.UpdateMessageInfo{
|
||||
SessionType: constant.SingleChatType,
|
||||
UserID: server.FriendUserID,
|
||||
FaceURL: server.FaceURL,
|
||||
Nickname: server.Nickname,
|
||||
},
|
||||
}, f.conversationCh)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
syncer.WithBatchInsert[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(ctx context.Context, values []*model_struct.LocalFriend) error {
|
||||
log.ZDebug(ctx, "BatchInsertFriend", "length", len(values))
|
||||
return f.db.BatchInsertFriend(ctx, values)
|
||||
}),
|
||||
syncer.WithDeleteAll[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(ctx context.Context, _ string) error {
|
||||
return f.db.DeleteAllFriend(ctx)
|
||||
}),
|
||||
syncer.WithBatchPageReq[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(entityID string) page.PageReq {
|
||||
return &friend.GetPaginationFriendsReq{UserID: entityID,
|
||||
Pagination: &sdkws.RequestPagination{ShowNumber: 100}}
|
||||
}),
|
||||
syncer.WithBatchPageRespConvertFunc[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](func(resp *friend.GetPaginationFriendsResp) []*model_struct.LocalFriend {
|
||||
return datautil.Batch(ServerFriendToLocalFriend, resp.FriendsInfo)
|
||||
}),
|
||||
syncer.WithReqApiRouter[*model_struct.LocalFriend, friend.GetPaginationFriendsResp, [2]string](constant.GetFriendListRouter),
|
||||
)
|
||||
|
||||
f.blockSyncer = syncer.New[*model_struct.LocalBlack, syncer.NoResp, [2]string](func(ctx context.Context, value *model_struct.LocalBlack) error {
|
||||
return f.db.InsertBlack(ctx, value)
|
||||
}, func(ctx context.Context, value *model_struct.LocalBlack) error {
|
||||
return f.db.DeleteBlack(ctx, value.BlockUserID)
|
||||
}, func(ctx context.Context, server *model_struct.LocalBlack, local *model_struct.LocalBlack) error {
|
||||
return f.db.UpdateBlack(ctx, server)
|
||||
}, func(value *model_struct.LocalBlack) [2]string {
|
||||
return [...]string{value.OwnerUserID, value.BlockUserID}
|
||||
}, nil, func(ctx context.Context, state int, server, local *model_struct.LocalBlack) error {
|
||||
switch state {
|
||||
case syncer.Insert:
|
||||
f.friendListener.OnBlackAdded(*server)
|
||||
case syncer.Delete:
|
||||
f.friendListener.OnBlackDeleted(*local)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
f.requestRecvSyncer = syncer.New[*model_struct.LocalFriendRequest, syncer.NoResp, [2]string](func(ctx context.Context, value *model_struct.LocalFriendRequest) error {
|
||||
return f.db.InsertFriendRequest(ctx, value)
|
||||
}, func(ctx context.Context, value *model_struct.LocalFriendRequest) error {
|
||||
return f.db.DeleteFriendRequestBothUserID(ctx, value.FromUserID, value.ToUserID)
|
||||
}, func(ctx context.Context, server *model_struct.LocalFriendRequest, local *model_struct.LocalFriendRequest) error {
|
||||
return f.db.UpdateFriendRequest(ctx, server)
|
||||
}, func(value *model_struct.LocalFriendRequest) [2]string {
|
||||
return [...]string{value.FromUserID, value.ToUserID}
|
||||
}, nil, func(ctx context.Context, state int, server, local *model_struct.LocalFriendRequest) error {
|
||||
switch state {
|
||||
case syncer.Insert:
|
||||
f.friendListener.OnFriendApplicationAdded(*server)
|
||||
case syncer.Delete:
|
||||
f.friendListener.OnFriendApplicationDeleted(*local)
|
||||
case syncer.Update:
|
||||
switch server.HandleResult {
|
||||
case constant.FriendResponseAgree:
|
||||
f.friendListener.OnFriendApplicationAccepted(*server)
|
||||
case constant.FriendResponseRefuse:
|
||||
f.friendListener.OnFriendApplicationRejected(*server)
|
||||
case constant.FriendResponseDefault:
|
||||
f.friendListener.OnFriendApplicationAdded(*server)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
f.requestSendSyncer = syncer.New[*model_struct.LocalFriendRequest, syncer.NoResp, [2]string](func(ctx context.Context, value *model_struct.LocalFriendRequest) error {
|
||||
return f.db.InsertFriendRequest(ctx, value)
|
||||
}, func(ctx context.Context, value *model_struct.LocalFriendRequest) error {
|
||||
return f.db.DeleteFriendRequestBothUserID(ctx, value.FromUserID, value.ToUserID)
|
||||
}, func(ctx context.Context, server *model_struct.LocalFriendRequest, local *model_struct.LocalFriendRequest) error {
|
||||
return f.db.UpdateFriendRequest(ctx, server)
|
||||
}, func(value *model_struct.LocalFriendRequest) [2]string {
|
||||
return [...]string{value.FromUserID, value.ToUserID}
|
||||
}, nil, func(ctx context.Context, state int, server, local *model_struct.LocalFriendRequest) error {
|
||||
switch state {
|
||||
case syncer.Insert:
|
||||
f.friendListener.OnFriendApplicationAdded(*server)
|
||||
case syncer.Delete:
|
||||
f.friendListener.OnFriendApplicationDeleted(*local)
|
||||
case syncer.Update:
|
||||
switch server.HandleResult {
|
||||
case constant.FriendResponseAgree:
|
||||
f.friendListener.OnFriendApplicationAccepted(*server)
|
||||
case constant.FriendResponseRefuse:
|
||||
f.friendListener.OnFriendApplicationRejected(*server)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (f *Friend) Db() db_interface.DataBase {
|
||||
return f.db
|
||||
}
|
||||
|
||||
func (f *Friend) SetListener(listener func() open_im_sdk_callback.OnFriendshipListener) {
|
||||
f.friendListener = open_im_sdk_callback.NewOnFriendshipListenerSdk(listener)
|
||||
}
|
||||
|
||||
func (f *Friend) SetListenerForService(listener open_im_sdk_callback.OnListenerForService) {
|
||||
f.listenerForService = listener
|
||||
}
|
||||
33
go/chao-sdk-core/internal/friend/hash.go
Normal file
33
go/chao-sdk-core/internal/friend/hash.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package friend
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/binary"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
|
||||
"github.com/openimsdk/protocol/constant"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (f *Friend) CalculateHash(friends []*model_struct.LocalFriend) uint64 {
|
||||
datautil.SortAny(friends, func(a, b *model_struct.LocalFriend) bool {
|
||||
return a.CreateTime > b.CreateTime
|
||||
})
|
||||
if len(friends) > constant.MaxSyncPullNumber {
|
||||
friends = friends[:constant.MaxSyncPullNumber]
|
||||
}
|
||||
hashStr := strings.Join(datautil.Slice(friends, func(f *model_struct.LocalFriend) string {
|
||||
return strings.Join([]string{
|
||||
f.FriendUserID,
|
||||
f.Remark,
|
||||
strconv.FormatInt(f.CreateTime, 10),
|
||||
strconv.Itoa(int(f.AddSource)),
|
||||
f.OperatorUserID,
|
||||
f.Ex,
|
||||
strconv.FormatBool(f.IsPinned),
|
||||
}, ",")
|
||||
}), ";")
|
||||
sum := md5.Sum([]byte(hashStr))
|
||||
return binary.BigEndian.Uint64(sum[:])
|
||||
}
|
||||
136
go/chao-sdk-core/internal/friend/notification.go
Normal file
136
go/chao-sdk-core/internal/friend/notification.go
Normal file
@@ -0,0 +1,136 @@
|
||||
// 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 friend
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/utils"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/tools/log"
|
||||
)
|
||||
|
||||
func (f *Friend) DoNotification(ctx context.Context, msg *sdkws.MsgData) {
|
||||
go func() {
|
||||
if err := f.doNotification(ctx, msg); err != nil {
|
||||
log.ZError(ctx, "doNotification error", err, "msg", msg)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (f *Friend) doNotification(ctx context.Context, msg *sdkws.MsgData) error {
|
||||
switch msg.ContentType {
|
||||
case constant.FriendApplicationNotification:
|
||||
tips := sdkws.FriendApplicationTips{}
|
||||
if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil {
|
||||
return err
|
||||
}
|
||||
return f.SyncBothFriendRequest(ctx,
|
||||
tips.FromToUserID.FromUserID, tips.FromToUserID.ToUserID)
|
||||
case constant.FriendApplicationApprovedNotification:
|
||||
var tips sdkws.FriendApplicationApprovedTips
|
||||
err := utils.UnmarshalNotificationElem(msg.Content, &tips)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if tips.FromToUserID.FromUserID == f.loginUserID {
|
||||
err = f.SyncFriends(ctx, []string{tips.FromToUserID.ToUserID})
|
||||
} else if tips.FromToUserID.ToUserID == f.loginUserID {
|
||||
err = f.SyncFriends(ctx, []string{tips.FromToUserID.FromUserID})
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f.SyncBothFriendRequest(ctx, tips.FromToUserID.FromUserID, tips.FromToUserID.ToUserID)
|
||||
case constant.FriendApplicationRejectedNotification:
|
||||
var tips sdkws.FriendApplicationRejectedTips
|
||||
if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil {
|
||||
return err
|
||||
}
|
||||
return f.SyncBothFriendRequest(ctx, tips.FromToUserID.FromUserID, tips.FromToUserID.ToUserID)
|
||||
case constant.FriendAddedNotification:
|
||||
var tips sdkws.FriendAddedTips
|
||||
if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil {
|
||||
return err
|
||||
}
|
||||
if tips.Friend != nil && tips.Friend.FriendUser != nil {
|
||||
if tips.Friend.FriendUser.UserID == f.loginUserID {
|
||||
return f.SyncFriends(ctx, []string{tips.Friend.OwnerUserID})
|
||||
} else if tips.Friend.OwnerUserID == f.loginUserID {
|
||||
return f.SyncFriends(ctx, []string{tips.Friend.FriendUser.UserID})
|
||||
}
|
||||
}
|
||||
case constant.FriendDeletedNotification:
|
||||
var tips sdkws.FriendDeletedTips
|
||||
if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil {
|
||||
return err
|
||||
}
|
||||
if tips.FromToUserID != nil {
|
||||
if tips.FromToUserID.FromUserID == f.loginUserID {
|
||||
return f.deleteFriend(ctx, tips.FromToUserID.ToUserID)
|
||||
}
|
||||
}
|
||||
case constant.FriendRemarkSetNotification:
|
||||
var tips sdkws.FriendInfoChangedTips
|
||||
if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil {
|
||||
return err
|
||||
}
|
||||
if tips.FromToUserID != nil {
|
||||
if tips.FromToUserID.FromUserID == f.loginUserID {
|
||||
return f.SyncFriends(ctx, []string{tips.FromToUserID.ToUserID})
|
||||
}
|
||||
}
|
||||
case constant.FriendInfoUpdatedNotification:
|
||||
var tips sdkws.UserInfoUpdatedTips
|
||||
if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil {
|
||||
return err
|
||||
}
|
||||
if tips.UserID != f.loginUserID {
|
||||
return f.SyncFriends(ctx, []string{tips.UserID})
|
||||
}
|
||||
case constant.BlackAddedNotification:
|
||||
var tips sdkws.BlackAddedTips
|
||||
if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil {
|
||||
return err
|
||||
}
|
||||
if tips.FromToUserID.FromUserID == f.loginUserID {
|
||||
return f.SyncAllBlackList(ctx)
|
||||
}
|
||||
case constant.BlackDeletedNotification:
|
||||
var tips sdkws.BlackDeletedTips
|
||||
if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil {
|
||||
return err
|
||||
}
|
||||
if tips.FromToUserID.FromUserID == f.loginUserID {
|
||||
return f.SyncAllBlackList(ctx)
|
||||
}
|
||||
case constant.FriendsInfoUpdateNotification:
|
||||
|
||||
var tips sdkws.FriendsInfoUpdateTips
|
||||
|
||||
if err := utils.UnmarshalNotificationElem(msg.Content, &tips); err != nil {
|
||||
return err
|
||||
}
|
||||
if tips.FromToUserID.ToUserID == f.loginUserID {
|
||||
return f.SyncFriends(ctx, tips.FriendIDs)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("type failed %d", msg.ContentType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
344
go/chao-sdk-core/internal/friend/sdk.go
Normal file
344
go/chao-sdk-core/internal/friend/sdk.go
Normal file
@@ -0,0 +1,344 @@
|
||||
// Copyright 2021 OpenIM Corporation
|
||||
//
|
||||
// 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 friend
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
friend "github.com/openimsdk/protocol/relation"
|
||||
"github.com/openimsdk/protocol/wrapperspb"
|
||||
"github.com/openimsdk/tools/errs"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
|
||||
"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/datafetcher"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/db/model_struct"
|
||||
sdk "github.com/openimsdk/openim-sdk-core/v3/pkg/sdk_params_callback"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/sdkerrs"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/server_api_params"
|
||||
|
||||
"github.com/openimsdk/tools/log"
|
||||
)
|
||||
|
||||
func (f *Friend) GetSpecifiedFriendsInfo(ctx context.Context, friendUserIDList []string) ([]*server_api_params.FullUserInfo, error) {
|
||||
datafetcher := datafetcher.NewDataFetcher(
|
||||
f.db,
|
||||
f.friendListTableName(),
|
||||
f.loginUserID,
|
||||
func(localFriend *model_struct.LocalFriend) string {
|
||||
return localFriend.FriendUserID
|
||||
},
|
||||
func(ctx context.Context, values []*model_struct.LocalFriend) error {
|
||||
return f.db.BatchInsertFriend(ctx, values)
|
||||
},
|
||||
func(ctx context.Context, userIDs []string) ([]*model_struct.LocalFriend, error) {
|
||||
return f.db.GetFriendInfoList(ctx, userIDs)
|
||||
},
|
||||
func(ctx context.Context, userIDs []string) ([]*model_struct.LocalFriend, error) {
|
||||
serverFriend, err := f.GetDesignatedFriends(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return datautil.Batch(ServerFriendToLocalFriend, serverFriend), nil
|
||||
},
|
||||
)
|
||||
localFriendList, err := datafetcher.FetchMissingAndFillLocal(ctx, friendUserIDList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.ZDebug(ctx, "GetDesignatedFriendsInfo", "localFriendList", localFriendList)
|
||||
blackList, err := f.db.GetBlackInfoList(ctx, friendUserIDList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.ZDebug(ctx, "GetDesignatedFriendsInfo", "blackList", blackList)
|
||||
m := make(map[string]*model_struct.LocalBlack)
|
||||
for i, black := range blackList {
|
||||
m[black.BlockUserID] = blackList[i]
|
||||
}
|
||||
res := make([]*server_api_params.FullUserInfo, 0, len(localFriendList))
|
||||
for _, localFriend := range localFriendList {
|
||||
res = append(res, &server_api_params.FullUserInfo{
|
||||
PublicInfo: nil,
|
||||
FriendInfo: localFriend,
|
||||
BlackInfo: m[localFriend.FriendUserID],
|
||||
})
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (f *Friend) AddFriend(ctx context.Context, userIDReqMsg *friend.ApplyToAddFriendReq) error {
|
||||
if userIDReqMsg.FromUserID == "" {
|
||||
userIDReqMsg.FromUserID = f.loginUserID
|
||||
}
|
||||
if err := util.ApiPost(ctx, constant.AddFriendRouter, userIDReqMsg, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return f.SyncAllFriendApplication(ctx)
|
||||
}
|
||||
|
||||
func (f *Friend) GetFriendApplicationListAsRecipient(ctx context.Context) ([]*model_struct.LocalFriendRequest, error) {
|
||||
return f.db.GetRecvFriendApplication(ctx)
|
||||
}
|
||||
|
||||
func (f *Friend) GetFriendApplicationListAsApplicant(ctx context.Context) ([]*model_struct.LocalFriendRequest, error) {
|
||||
return f.db.GetSendFriendApplication(ctx)
|
||||
}
|
||||
|
||||
func (f *Friend) AcceptFriendApplication(ctx context.Context, userIDHandleMsg *sdk.ProcessFriendApplicationParams) error {
|
||||
return f.RespondFriendApply(ctx, &friend.RespondFriendApplyReq{FromUserID: userIDHandleMsg.ToUserID, ToUserID: f.loginUserID, HandleResult: constant.FriendResponseAgree, HandleMsg: userIDHandleMsg.HandleMsg})
|
||||
}
|
||||
|
||||
func (f *Friend) RefuseFriendApplication(ctx context.Context, userIDHandleMsg *sdk.ProcessFriendApplicationParams) error {
|
||||
return f.RespondFriendApply(ctx, &friend.RespondFriendApplyReq{FromUserID: userIDHandleMsg.ToUserID, ToUserID: f.loginUserID, HandleResult: constant.FriendResponseRefuse, HandleMsg: userIDHandleMsg.HandleMsg})
|
||||
}
|
||||
|
||||
func (f *Friend) RespondFriendApply(ctx context.Context, req *friend.RespondFriendApplyReq) error {
|
||||
if req.ToUserID == "" {
|
||||
req.ToUserID = f.loginUserID
|
||||
}
|
||||
if err := util.ApiPost(ctx, constant.AddFriendResponse, req, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
if req.HandleResult == constant.FriendResponseAgree {
|
||||
_ = f.SyncFriends(ctx, []string{req.FromUserID})
|
||||
}
|
||||
_ = f.SyncAllFriendApplication(ctx)
|
||||
return nil
|
||||
// return f.SyncFriendApplication(ctx)
|
||||
}
|
||||
|
||||
func (f *Friend) CheckFriend(ctx context.Context, friendUserIDList []string) ([]*server_api_params.UserIDResult, error) {
|
||||
friendList, err := f.db.GetFriendInfoList(ctx, friendUserIDList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blackList, err := f.db.GetBlackInfoList(ctx, friendUserIDList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res := make([]*server_api_params.UserIDResult, 0, len(friendUserIDList))
|
||||
for _, v := range friendUserIDList {
|
||||
var r server_api_params.UserIDResult
|
||||
isBlack := false
|
||||
isFriend := false
|
||||
for _, b := range blackList {
|
||||
if v == b.BlockUserID {
|
||||
isBlack = true
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, f := range friendList {
|
||||
if v == f.FriendUserID {
|
||||
isFriend = true
|
||||
break
|
||||
}
|
||||
}
|
||||
r.UserID = v
|
||||
if isFriend && !isBlack {
|
||||
r.Result = 1
|
||||
} else {
|
||||
r.Result = 0
|
||||
}
|
||||
res = append(res, &r)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (f *Friend) DeleteFriend(ctx context.Context, friendUserID string) error {
|
||||
if err := util.ApiPost(ctx, constant.DeleteFriendRouter, &friend.DeleteFriendReq{OwnerUserID: f.loginUserID, FriendUserID: friendUserID}, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return f.deleteFriend(ctx, friendUserID)
|
||||
}
|
||||
|
||||
func (f *Friend) GetFriendList(ctx context.Context) ([]*server_api_params.FullUserInfo, error) {
|
||||
localFriendList, err := f.db.GetAllFriendList(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
localBlackList, err := f.db.GetBlackListDB(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[string]*model_struct.LocalBlack)
|
||||
for i, black := range localBlackList {
|
||||
m[black.BlockUserID] = localBlackList[i]
|
||||
}
|
||||
res := make([]*server_api_params.FullUserInfo, 0, len(localFriendList))
|
||||
for _, localFriend := range localFriendList {
|
||||
res = append(res, &server_api_params.FullUserInfo{
|
||||
PublicInfo: nil,
|
||||
FriendInfo: localFriend,
|
||||
BlackInfo: m[localFriend.FriendUserID],
|
||||
})
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (f *Friend) GetFriendListPage(ctx context.Context, offset, count int32) ([]*server_api_params.FullUserInfo, error) {
|
||||
dataFetcher := datafetcher.NewDataFetcher(
|
||||
f.db,
|
||||
f.friendListTableName(),
|
||||
f.loginUserID,
|
||||
func(localFriend *model_struct.LocalFriend) string {
|
||||
return localFriend.FriendUserID
|
||||
},
|
||||
func(ctx context.Context, values []*model_struct.LocalFriend) error {
|
||||
return f.db.BatchInsertFriend(ctx, values)
|
||||
},
|
||||
func(ctx context.Context, userIDs []string) ([]*model_struct.LocalFriend, error) {
|
||||
return f.db.GetFriendInfoList(ctx, userIDs)
|
||||
},
|
||||
func(ctx context.Context, userIDs []string) ([]*model_struct.LocalFriend, error) {
|
||||
serverFriend, err := f.GetDesignatedFriends(ctx, userIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return datautil.Batch(ServerFriendToLocalFriend, serverFriend), nil
|
||||
},
|
||||
)
|
||||
|
||||
localFriendList, err := dataFetcher.FetchWithPagination(ctx, int(offset), int(count))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// don't need extra handle. only full pull.
|
||||
localBlackList, err := f.db.GetBlackListDB(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[string]*model_struct.LocalBlack)
|
||||
for i, black := range localBlackList {
|
||||
m[black.BlockUserID] = localBlackList[i]
|
||||
}
|
||||
res := make([]*server_api_params.FullUserInfo, 0, len(localFriendList))
|
||||
for _, localFriend := range localFriendList {
|
||||
res = append(res, &server_api_params.FullUserInfo{
|
||||
PublicInfo: nil,
|
||||
FriendInfo: localFriend,
|
||||
BlackInfo: m[localFriend.FriendUserID],
|
||||
})
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (f *Friend) SearchFriends(ctx context.Context, param *sdk.SearchFriendsParam) ([]*sdk.SearchFriendItem, error) {
|
||||
if len(param.KeywordList) == 0 || (!param.IsSearchNickname && !param.IsSearchUserID && !param.IsSearchRemark) {
|
||||
return nil, sdkerrs.ErrArgs.WrapMsg("keyword is null or search field all false")
|
||||
}
|
||||
localFriendList, err := f.db.SearchFriendList(ctx, param.KeywordList[0], param.IsSearchUserID, param.IsSearchNickname, param.IsSearchRemark)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
localBlackList, err := f.db.GetBlackListDB(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[string]struct{})
|
||||
for _, black := range localBlackList {
|
||||
m[black.BlockUserID] = struct{}{}
|
||||
}
|
||||
res := make([]*sdk.SearchFriendItem, 0, len(localFriendList))
|
||||
for i, localFriend := range localFriendList {
|
||||
var relationship int
|
||||
if _, ok := m[localFriend.FriendUserID]; ok {
|
||||
relationship = constant.BlackRelationship
|
||||
} else {
|
||||
relationship = constant.FriendRelationship
|
||||
}
|
||||
res = append(res, &sdk.SearchFriendItem{
|
||||
LocalFriend: *localFriendList[i],
|
||||
Relationship: relationship,
|
||||
})
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (f *Friend) SetFriendRemark(ctx context.Context, userIDRemark *sdk.SetFriendRemarkParams) error {
|
||||
if err := util.ApiPost(ctx, constant.SetFriendRemark, &friend.SetFriendRemarkReq{OwnerUserID: f.loginUserID, FriendUserID: userIDRemark.ToUserID, Remark: userIDRemark.Remark}, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return f.SyncFriends(ctx, []string{userIDRemark.ToUserID})
|
||||
}
|
||||
|
||||
func (f *Friend) PinFriends(ctx context.Context, friends *sdk.SetFriendPinParams) error {
|
||||
if err := util.ApiPost(ctx, constant.UpdateFriends, &friend.UpdateFriendsReq{OwnerUserID: f.loginUserID, FriendUserIDs: friends.ToUserIDs, IsPinned: friends.IsPinned}, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return f.SyncFriends(ctx, friends.ToUserIDs)
|
||||
}
|
||||
|
||||
func (f *Friend) AddBlack(ctx context.Context, blackUserID string, ex string) error {
|
||||
if err := util.ApiPost(ctx, constant.AddBlackRouter, &friend.AddBlackReq{OwnerUserID: f.loginUserID, BlackUserID: blackUserID, Ex: ex}, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return f.SyncAllBlackList(ctx)
|
||||
}
|
||||
|
||||
func (f *Friend) RemoveBlack(ctx context.Context, blackUserID string) error {
|
||||
if err := util.ApiPost(ctx, constant.RemoveBlackRouter, &friend.RemoveBlackReq{OwnerUserID: f.loginUserID, BlackUserID: blackUserID}, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return f.SyncAllBlackList(ctx)
|
||||
}
|
||||
|
||||
func (f *Friend) GetBlackList(ctx context.Context) ([]*model_struct.LocalBlack, error) {
|
||||
return f.db.GetBlackListDB(ctx)
|
||||
}
|
||||
|
||||
func (f *Friend) SetFriendsEx(ctx context.Context, friendIDs []string, ex string) error {
|
||||
if err := util.ApiPost(ctx, constant.UpdateFriends, &friend.UpdateFriendsReq{OwnerUserID: f.loginUserID, FriendUserIDs: friendIDs, Ex: &wrapperspb.StringValue{
|
||||
Value: ex,
|
||||
}}, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
// Check if the specified ID is a friend
|
||||
friendResults, err := f.CheckFriend(ctx, friendIDs)
|
||||
if err != nil {
|
||||
return errs.WrapMsg(err, "Error checking friend status")
|
||||
}
|
||||
|
||||
// Determine if friendID is indeed a friend
|
||||
// Iterate over each friendID
|
||||
for _, friendID := range friendIDs {
|
||||
isFriend := false
|
||||
|
||||
// Check if this friendID is in the friendResults
|
||||
for _, result := range friendResults {
|
||||
if result.UserID == friendID && result.Result == 1 { // Assuming result 1 means they are friends
|
||||
isFriend = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If this friendID is not a friend, return an error
|
||||
if !isFriend {
|
||||
return errs.ErrRecordNotFound.WrapMsg("Not friend")
|
||||
}
|
||||
}
|
||||
|
||||
// If the code reaches here, all friendIDs are confirmed as friends
|
||||
// Update friend information if they are friends
|
||||
|
||||
updateErr := f.db.UpdateColumnsFriend(ctx, friendIDs, map[string]interface{}{"Ex": ex})
|
||||
if updateErr != nil {
|
||||
return errs.WrapMsg(updateErr, "Error updating friend information")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
180
go/chao-sdk-core/internal/friend/sync.go
Normal file
180
go/chao-sdk-core/internal/friend/sync.go
Normal file
@@ -0,0 +1,180 @@
|
||||
// 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 friend
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
"time"
|
||||
|
||||
"github.com/openimsdk/openim-sdk-core/v3/internal/util"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/pkg/constant"
|
||||
friend "github.com/openimsdk/protocol/relation"
|
||||
"github.com/openimsdk/protocol/sdkws"
|
||||
"github.com/openimsdk/tools/log"
|
||||
)
|
||||
|
||||
func (f *Friend) SyncBothFriendRequest(ctx context.Context, fromUserID, toUserID string) error {
|
||||
var resp friend.GetDesignatedFriendsApplyResp
|
||||
if err := util.ApiPost(ctx, constant.GetDesignatedFriendsApplyRouter, &friend.GetDesignatedFriendsApplyReq{FromUserID: fromUserID, ToUserID: toUserID}, &resp); err != nil {
|
||||
return nil
|
||||
}
|
||||
localData, err := f.db.GetBothFriendReq(ctx, fromUserID, toUserID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if toUserID == f.loginUserID {
|
||||
return f.requestRecvSyncer.Sync(ctx, datautil.Batch(ServerFriendRequestToLocalFriendRequest, resp.FriendRequests), localData, nil)
|
||||
} else if fromUserID == f.loginUserID {
|
||||
return f.requestSendSyncer.Sync(ctx, datautil.Batch(ServerFriendRequestToLocalFriendRequest, resp.FriendRequests), localData, nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// send
|
||||
func (f *Friend) SyncAllSelfFriendApplication(ctx context.Context) error {
|
||||
req := &friend.GetPaginationFriendsApplyFromReq{UserID: f.loginUserID, Pagination: &sdkws.RequestPagination{}}
|
||||
fn := func(resp *friend.GetPaginationFriendsApplyFromResp) []*sdkws.FriendRequest {
|
||||
return resp.FriendRequests
|
||||
}
|
||||
requests, err := util.GetPageAll(ctx, constant.GetSelfFriendApplicationListRouter, req, fn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
localData, err := f.db.GetSendFriendApplication(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f.requestSendSyncer.Sync(ctx, datautil.Batch(ServerFriendRequestToLocalFriendRequest, requests), localData, nil)
|
||||
}
|
||||
|
||||
// recv
|
||||
func (f *Friend) SyncAllFriendApplication(ctx context.Context) error {
|
||||
req := &friend.GetPaginationFriendsApplyToReq{UserID: f.loginUserID, Pagination: &sdkws.RequestPagination{}}
|
||||
fn := func(resp *friend.GetPaginationFriendsApplyToResp) []*sdkws.FriendRequest { return resp.FriendRequests }
|
||||
requests, err := util.GetPageAll(ctx, constant.GetFriendApplicationListRouter, req, fn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
localData, err := f.db.GetRecvFriendApplication(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f.requestRecvSyncer.Sync(ctx, datautil.Batch(ServerFriendRequestToLocalFriendRequest, requests), localData, nil)
|
||||
}
|
||||
|
||||
func (f *Friend) SyncAllFriendList(ctx context.Context) error {
|
||||
t := time.Now()
|
||||
defer func(start time.Time) {
|
||||
|
||||
elapsed := time.Since(start).Milliseconds()
|
||||
log.ZDebug(ctx, "SyncAllFriendList fn call end", "cost time", fmt.Sprintf("%d ms", elapsed))
|
||||
|
||||
}(t)
|
||||
return f.IncrSyncFriends(ctx)
|
||||
//req := &friend.GetPaginationFriendsReq{UserID: f.loginUserID, Pagination: &sdkws.RequestPagination{}}
|
||||
//fn := func(resp *friend.GetPaginationFriendsResp) []*sdkws.FriendInfo { return resp.FriendsInfo }
|
||||
//friends, err := util.GetPageAll(ctx, constant.GetFriendListRouter, req, fn)
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
//localData, err := f.db.GetAllFriendList(ctx)
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
//log.ZDebug(ctx, "sync friend", "data from server", friends, "data from local", localData)
|
||||
//return f.friendSyncer.Sync(ctx, util.Batch(ServerFriendToLocalFriend, friends), localData, nil)
|
||||
}
|
||||
|
||||
func (f *Friend) deleteFriend(ctx context.Context, friendUserID string) error {
|
||||
return f.IncrSyncFriends(ctx)
|
||||
//friends, err := f.db.GetFriendInfoList(ctx, []string{friendUserID})
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
//if len(friends) == 0 {
|
||||
// return sdkerrs.ErrUserIDNotFound.WrapMsg("friendUserID not found")
|
||||
//}
|
||||
//if err := f.db.DeleteFriendDB(ctx, friendUserID); err != nil {
|
||||
// return err
|
||||
//}
|
||||
//f.friendListener.OnFriendDeleted(*friends[0])
|
||||
//return nil
|
||||
}
|
||||
|
||||
func (f *Friend) SyncFriends(ctx context.Context, friendIDs []string) error {
|
||||
return f.IncrSyncFriends(ctx)
|
||||
//var resp friend.GetDesignatedFriendsResp
|
||||
//if err := util.ApiPost(ctx, constant.GetDesignatedFriendsRouter, &friend.GetDesignatedFriendsReq{OwnerUserID: f.loginUserID, FriendUserIDs: friendIDs}, &resp); err != nil {
|
||||
// return err
|
||||
//}
|
||||
//localData, err := f.db.GetFriendInfoList(ctx, friendIDs)
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
//log.ZDebug(ctx, "sync friend", "data from server", resp.FriendsInfo, "data from local", localData)
|
||||
//return f.friendSyncer.Sync(ctx, util.Batch(ServerFriendToLocalFriend, resp.FriendsInfo), localData, nil)
|
||||
}
|
||||
|
||||
//func (f *Friend) SyncFriendPart(ctx context.Context) error {
|
||||
// hashResp, err := util.CallApi[friend.GetFriendHashResp](ctx, constant.GetFriendHash, &friend.GetFriendHashReq{UserID: f.loginUserID})
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// friends, err := f.db.GetAllFriendList(ctx)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// hashCode := f.CalculateHash(friends)
|
||||
// log.ZDebug(ctx, "SyncFriendPart", "serverHash", hashResp.Hash, "serverTotal", hashResp.Total, "localHash", hashCode, "localTotal", len(friends))
|
||||
// if hashCode == hashResp.Hash {
|
||||
// return nil
|
||||
// }
|
||||
// req := &friend.GetPaginationFriendsReq{
|
||||
// UserID: f.loginUserID,
|
||||
// Pagination: &sdkws.RequestPagination{PageNumber: pconstant.FirstPageNumber, ShowNumber: pconstant.MaxSyncPullNumber},
|
||||
// }
|
||||
// resp, err := util.CallApi[friend.GetPaginationFriendsResp](ctx, constant.GetFriendListRouter, req)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// serverFriends := util.Batch(ServerFriendToLocalFriend, resp.FriendsInfo)
|
||||
// return f.friendSyncer.Sync(ctx, serverFriends, friends, nil)
|
||||
//}
|
||||
|
||||
func (f *Friend) SyncAllBlackList(ctx context.Context) error {
|
||||
req := &friend.GetPaginationBlacksReq{UserID: f.loginUserID, Pagination: &sdkws.RequestPagination{}}
|
||||
fn := func(resp *friend.GetPaginationBlacksResp) []*sdkws.BlackInfo { return resp.Blacks }
|
||||
serverData, err := util.GetPageAll(ctx, constant.GetBlackListRouter, req, fn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.ZDebug(ctx, "black from server", "data", serverData)
|
||||
localData, err := f.db.GetBlackListDB(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.ZDebug(ctx, "black from local", "data", localData)
|
||||
return f.blockSyncer.Sync(ctx, datautil.Batch(ServerBlackToLocalBlack, serverData), localData, nil)
|
||||
}
|
||||
|
||||
func (f *Friend) GetDesignatedFriends(ctx context.Context, friendIDs []string) ([]*sdkws.FriendInfo, error) {
|
||||
resp := &friend.GetDesignatedFriendsResp{}
|
||||
if err := util.ApiPost(ctx, constant.GetDesignatedFriendsRouter, &friend.GetDesignatedFriendsReq{OwnerUserID: f.loginUserID, FriendUserIDs: friendIDs}, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.FriendsInfo, nil
|
||||
}
|
||||
72
go/chao-sdk-core/internal/friend/sync2.go
Normal file
72
go/chao-sdk-core/internal/friend/sync2.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package friend
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/openimsdk/openim-sdk-core/v3/internal/incrversion"
|
||||
"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"
|
||||
friend "github.com/openimsdk/protocol/relation"
|
||||
"github.com/openimsdk/tools/utils/datautil"
|
||||
)
|
||||
|
||||
const (
|
||||
LocalFriendSyncMaxNum = 1000
|
||||
)
|
||||
|
||||
func (f *Friend) IncrSyncFriends(ctx context.Context) error {
|
||||
friendSyncer := incrversion.VersionSynchronizer[*model_struct.LocalFriend, *friend.GetIncrementalFriendsResp]{
|
||||
Ctx: ctx,
|
||||
DB: f.db,
|
||||
TableName: f.friendListTableName(),
|
||||
EntityID: f.loginUserID,
|
||||
Key: func(localFriend *model_struct.LocalFriend) string {
|
||||
return localFriend.FriendUserID
|
||||
},
|
||||
Local: func() ([]*model_struct.LocalFriend, error) {
|
||||
return f.db.GetAllFriendList(ctx)
|
||||
},
|
||||
Server: func(version *model_struct.LocalVersionSync) (*friend.GetIncrementalFriendsResp, error) {
|
||||
return util.CallApi[friend.GetIncrementalFriendsResp](ctx, constant.GetIncrementalFriends, &friend.GetIncrementalFriendsReq{
|
||||
UserID: f.loginUserID,
|
||||
Version: version.Version,
|
||||
VersionID: version.VersionID,
|
||||
})
|
||||
},
|
||||
Full: func(resp *friend.GetIncrementalFriendsResp) bool {
|
||||
return resp.Full
|
||||
},
|
||||
Version: func(resp *friend.GetIncrementalFriendsResp) (string, uint64) {
|
||||
return resp.VersionID, resp.Version
|
||||
},
|
||||
Delete: func(resp *friend.GetIncrementalFriendsResp) []string {
|
||||
return resp.Delete
|
||||
},
|
||||
Update: func(resp *friend.GetIncrementalFriendsResp) []*model_struct.LocalFriend {
|
||||
return datautil.Batch(ServerFriendToLocalFriend, resp.Update)
|
||||
},
|
||||
Insert: func(resp *friend.GetIncrementalFriendsResp) []*model_struct.LocalFriend {
|
||||
return datautil.Batch(ServerFriendToLocalFriend, resp.Insert)
|
||||
},
|
||||
Syncer: func(server, local []*model_struct.LocalFriend) error {
|
||||
return f.friendSyncer.Sync(ctx, server, local, nil)
|
||||
},
|
||||
FullSyncer: func(ctx context.Context) error {
|
||||
return f.friendSyncer.FullSync(ctx, f.loginUserID)
|
||||
},
|
||||
FullID: func(ctx context.Context) ([]string, error) {
|
||||
resp, err := util.CallApi[friend.GetFullFriendUserIDsResp](ctx, constant.GetFullFriendUserIDs, &friend.GetFullFriendUserIDsReq{
|
||||
UserID: f.loginUserID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.UserIDs, nil
|
||||
},
|
||||
}
|
||||
return friendSyncer.Sync()
|
||||
}
|
||||
|
||||
func (f *Friend) friendListTableName() string {
|
||||
return model_struct.LocalFriend{}.TableName()
|
||||
}
|
||||
13
go/chao-sdk-core/internal/friend/sync2_test.go
Normal file
13
go/chao-sdk-core/internal/friend/sync2_test.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package friend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_main(t *testing.T) {
|
||||
a := []int{1, 2, 3, 4, 5}
|
||||
fmt.Println(a[:3])
|
||||
fmt.Println(a[3:])
|
||||
fmt.Println(a[2:4])
|
||||
}
|
||||
Reference in New Issue
Block a user