You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
openim-sdk-cpp/go/chao-sdk-core/internal/friend/sdk.go

344 lines
12 KiB

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