2023-07-04 11:15:20 +08:00
// Copyright © 2023 OpenIM. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2023-06-30 09:45:02 +08:00
package controller
import (
"context"
2025-05-26 10:06:35 +08:00
"time"
2026-01-22 16:34:00 +08:00
"github.com/openimsdk/open-im-server/v3/pkg/common/servererrs"
2024-05-27 11:58:36 +08:00
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/database/mgo"
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/model"
2023-06-30 09:45:02 +08:00
2024-05-27 11:58:36 +08:00
"github.com/openimsdk/open-im-server/v3/pkg/common/storage/cache"
2024-04-19 22:23:08 +08:00
"github.com/openimsdk/protocol/constant"
"github.com/openimsdk/tools/db/pagination"
"github.com/openimsdk/tools/db/tx"
"github.com/openimsdk/tools/errs"
"github.com/openimsdk/tools/log"
"github.com/openimsdk/tools/mcontext"
"github.com/openimsdk/tools/utils/datautil"
2023-06-30 09:45:02 +08:00
)
type FriendDatabase interface {
2023-12-28 14:45:27 +08:00
// CheckIn checks if user2 is in user1's friend list (inUser1Friends==true) and if user1 is in user2's friend list (inUser2Friends==true)
2023-06-30 09:45:02 +08:00
CheckIn ( ctx context . Context , user1 , user2 string ) ( inUser1Friends bool , inUser2Friends bool , err error )
2023-12-28 14:45:27 +08:00
// AddFriendRequest adds or updates a friend request
2023-06-30 09:45:02 +08:00
AddFriendRequest ( ctx context . Context , fromUserID , toUserID string , reqMsg string , ex string ) ( err error )
2023-12-28 14:45:27 +08:00
2024-05-27 11:58:36 +08:00
// BecomeFriends first checks if the users are already in the friends model; if not, it inserts them as friends
2023-06-30 09:45:02 +08:00
BecomeFriends ( ctx context . Context , ownerUserID string , friendUserIDs [ ] string , addSource int32 ) ( err error )
2023-12-28 14:45:27 +08:00
// RefuseFriendRequest refuses a friend request
2024-05-27 11:58:36 +08:00
RefuseFriendRequest ( ctx context . Context , friendRequest * model . FriendRequest ) ( err error )
2023-12-28 14:45:27 +08:00
// AgreeFriendRequest accepts a friend request
2024-05-27 11:58:36 +08:00
AgreeFriendRequest ( ctx context . Context , friendRequest * model . FriendRequest ) ( err error )
2023-12-28 14:45:27 +08:00
// Delete removes a friend or friends from the owner's friend list
2023-06-30 09:45:02 +08:00
Delete ( ctx context . Context , ownerUserID string , friendUserIDs [ ] string ) ( err error )
2023-12-28 14:45:27 +08:00
// UpdateRemark updates the remark for a friend
2023-06-30 09:45:02 +08:00
UpdateRemark ( ctx context . Context , ownerUserID , friendUserID , remark string ) ( err error )
2023-12-28 14:45:27 +08:00
// PageOwnerFriends retrieves the friend list of ownerUserID with pagination
2024-05-27 11:58:36 +08:00
PageOwnerFriends ( ctx context . Context , ownerUserID string , pagination pagination . Pagination ) ( total int64 , friends [ ] * model . Friend , err error )
2023-12-28 14:45:27 +08:00
// PageInWhoseFriends finds the users who have friendUserID in their friend list with pagination
2024-05-27 11:58:36 +08:00
PageInWhoseFriends ( ctx context . Context , friendUserID string , pagination pagination . Pagination ) ( total int64 , friends [ ] * model . Friend , err error )
2023-12-28 14:45:27 +08:00
// PageFriendRequestFromMe retrieves the friend requests sent by the user with pagination
2025-05-26 10:06:35 +08:00
PageFriendRequestFromMe ( ctx context . Context , userID string , handleResults [ ] int , pagination pagination . Pagination ) ( total int64 , friends [ ] * model . FriendRequest , err error )
2023-12-28 14:45:27 +08:00
// PageFriendRequestToMe retrieves the friend requests received by the user with pagination
2025-05-26 10:06:35 +08:00
PageFriendRequestToMe ( ctx context . Context , userID string , handleResults [ ] int , pagination pagination . Pagination ) ( total int64 , friends [ ] * model . FriendRequest , err error )
2023-12-28 14:45:27 +08:00
// FindFriendsWithError fetches specified friends of a user and returns an error if any do not exist
2024-05-27 11:58:36 +08:00
FindFriendsWithError ( ctx context . Context , ownerUserID string , friendUserIDs [ ] string ) ( friends [ ] * model . Friend , err error )
2023-12-28 14:45:27 +08:00
// FindFriendUserIDs retrieves the friend IDs of a user
2023-06-30 09:45:02 +08:00
FindFriendUserIDs ( ctx context . Context , ownerUserID string ) ( friendUserIDs [ ] string , err error )
2023-12-28 14:45:27 +08:00
// FindBothFriendRequests finds friend requests sent and received
2024-05-27 11:58:36 +08:00
FindBothFriendRequests ( ctx context . Context , fromUserID , toUserID string ) ( friends [ ] * model . FriendRequest , err error )
2023-12-28 14:45:27 +08:00
2024-01-10 10:27:03 +08:00
// UpdateFriends updates fields for friends
UpdateFriends ( ctx context . Context , ownerUserID string , friendUserIDs [ ] string , val map [ string ] any ) ( err error )
2024-07-01 17:38:14 +08:00
//FindSortFriendUserIDs(ctx context.Context, ownerUserID string) ([]string, error)
FindFriendIncrVersion ( ctx context . Context , ownerUserID string , version uint , limit int ) ( * model . VersionLog , error )
FindMaxFriendVersionCache ( ctx context . Context , ownerUserID string ) ( * model . VersionLog , error )
FindFriendUserID ( ctx context . Context , friendUserID string ) ( [ ] string , error )
OwnerIncrVersion ( ctx context . Context , ownerUserID string , friendUserIDs [ ] string , state int32 ) error
2025-05-26 10:06:35 +08:00
GetUnhandledCount ( ctx context . Context , userID string , ts int64 ) ( int64 , error )
2023-06-30 09:45:02 +08:00
}
type friendDatabase struct {
2024-05-27 11:58:36 +08:00
friend database . Friend
friendRequest database . FriendRequest
2024-04-19 22:23:08 +08:00
tx tx . Tx
2023-06-30 09:45:02 +08:00
cache cache . FriendCache
}
2024-05-27 11:58:36 +08:00
func NewFriendDatabase ( friend database . Friend , friendRequest database . FriendRequest , cache cache . FriendCache , tx tx . Tx ) FriendDatabase {
2023-06-30 09:45:02 +08:00
return & friendDatabase { friend : friend , friendRequest : friendRequest , cache : cache , tx : tx }
}
2024-03-04 12:12:14 +08:00
// CheckIn verifies if user2 is in user1's friend list (inUser1Friends returns true) and
// if user1 is in user2's friend list (inUser2Friends returns true).
2023-12-05 20:53:02 +08:00
func ( f * friendDatabase ) CheckIn ( ctx context . Context , userID1 , userID2 string ) ( inUser1Friends bool , inUser2Friends bool , err error ) {
2024-03-04 12:12:14 +08:00
// Retrieve friend IDs of userID1 from the cache
2023-06-30 09:45:02 +08:00
userID1FriendIDs , err := f . cache . GetFriendIDs ( ctx , userID1 )
if err != nil {
2026-01-22 16:34:00 +08:00
return false , false , err
2023-06-30 09:45:02 +08:00
}
2024-03-04 12:12:14 +08:00
// Retrieve friend IDs of userID2 from the cache
2023-06-30 09:45:02 +08:00
userID2FriendIDs , err := f . cache . GetFriendIDs ( ctx , userID2 )
if err != nil {
2026-01-22 16:34:00 +08:00
return false , false , err
2023-06-30 09:45:02 +08:00
}
2024-03-04 12:12:14 +08:00
// Check if userID2 is in userID1's friend list and vice versa
2024-04-19 22:23:08 +08:00
inUser1Friends = datautil . Contain ( userID2 , userID1FriendIDs ... )
inUser2Friends = datautil . Contain ( userID1 , userID2FriendIDs ... )
2024-03-04 12:12:14 +08:00
return inUser1Friends , inUser2Friends , nil
2023-06-30 09:45:02 +08:00
}
2024-03-04 12:12:14 +08:00
// AddFriendRequest adds or updates a friend request.
2023-12-05 20:53:02 +08:00
func ( f * friendDatabase ) AddFriendRequest ( ctx context . Context , fromUserID , toUserID string , reqMsg string , ex string ) ( err error ) {
return f . tx . Transaction ( ctx , func ( ctx context . Context ) error {
_ , err := f . friendRequest . Take ( ctx , fromUserID , toUserID )
switch {
case err == nil :
m := make ( map [ string ] any , 1 )
2023-06-30 09:45:02 +08:00
m [ "handle_result" ] = 0
m [ "handle_msg" ] = ""
m [ "req_msg" ] = reqMsg
m [ "ex" ] = ex
m [ "create_time" ] = time . Now ( )
2023-12-05 20:53:02 +08:00
return f . friendRequest . UpdateByMap ( ctx , fromUserID , toUserID , m )
2024-05-27 11:58:36 +08:00
case mgo . IsNotFound ( err ) :
2023-12-05 20:53:02 +08:00
return f . friendRequest . Create (
ctx ,
2024-05-27 11:58:36 +08:00
[ ] * model . FriendRequest { { FromUserID : fromUserID , ToUserID : toUserID , ReqMsg : reqMsg , Ex : ex , CreateTime : time . Now ( ) , HandleTime : time . Unix ( 0 , 0 ) } } ,
2023-12-05 20:53:02 +08:00
)
default :
2023-06-30 09:45:02 +08:00
return err
}
} )
}
2024-03-04 12:12:14 +08:00
// (1) First determine whether it is in the friends list (in or out does not return an error) (2) for not in the friends list can be inserted.
2023-12-05 20:53:02 +08:00
func ( f * friendDatabase ) BecomeFriends ( ctx context . Context , ownerUserID string , friendUserIDs [ ] string , addSource int32 ) ( err error ) {
return f . tx . Transaction ( ctx , func ( ctx context . Context ) error {
2024-05-27 11:58:36 +08:00
cache := f . cache . CloneFriendCache ( )
2024-04-19 22:23:08 +08:00
// user find friends
2024-07-29 16:53:26 +08:00
myFriends , err := f . friend . FindFriends ( ctx , ownerUserID , friendUserIDs )
2023-10-24 20:28:22 +08:00
if err != nil {
return err
2023-06-30 09:45:02 +08:00
}
2024-07-29 16:53:26 +08:00
addOwners , err := f . friend . FindReversalFriends ( ctx , ownerUserID , friendUserIDs )
2023-10-24 20:28:22 +08:00
if err != nil {
return err
2023-06-30 09:45:02 +08:00
}
2024-08-29 15:18:23 +08:00
opUserID := mcontext . GetOpUserID ( ctx )
2024-07-29 16:53:26 +08:00
friends := make ( [ ] * model . Friend , 0 , len ( friendUserIDs ) * 2 )
myFriendsSet := datautil . SliceSetAny ( myFriends , func ( friend * model . Friend ) string {
return friend . FriendUserID
} )
addOwnersSet := datautil . SliceSetAny ( addOwners , func ( friend * model . Friend ) string {
return friend . OwnerUserID
} )
newMyFriendIDs := make ( [ ] string , 0 , len ( friendUserIDs ) )
newMyOwnerIDs := make ( [ ] string , 0 , len ( friendUserIDs ) )
for _ , userID := range friendUserIDs {
if ownerUserID == userID {
continue
}
if _ , ok := myFriendsSet [ userID ] ; ! ok {
myFriendsSet [ userID ] = struct { } { }
newMyFriendIDs = append ( newMyFriendIDs , userID )
friends = append ( friends , & model . Friend { OwnerUserID : ownerUserID , FriendUserID : userID , AddSource : addSource , OperatorUserID : opUserID } )
}
if _ , ok := addOwnersSet [ userID ] ; ! ok {
addOwnersSet [ userID ] = struct { } { }
newMyOwnerIDs = append ( newMyOwnerIDs , userID )
friends = append ( friends , & model . Friend { OwnerUserID : userID , FriendUserID : ownerUserID , AddSource : addSource , OperatorUserID : opUserID } )
}
2023-06-30 09:45:02 +08:00
}
2024-07-29 16:53:26 +08:00
if len ( friends ) == 0 {
return nil
2023-06-30 09:45:02 +08:00
}
2024-07-29 16:53:26 +08:00
err = f . friend . Create ( ctx , friends )
2023-10-24 20:28:22 +08:00
if err != nil {
return err
2023-06-30 09:45:02 +08:00
}
2024-08-08 15:20:01 +08:00
cache = cache . DelFriendIDs ( ownerUserID ) . DelMaxFriendVersion ( ownerUserID )
2024-07-29 16:53:26 +08:00
if len ( newMyFriendIDs ) > 0 {
cache = cache . DelFriendIDs ( newMyFriendIDs ... )
cache = cache . DelFriends ( ownerUserID , newMyFriendIDs ) . DelMaxFriendVersion ( newMyFriendIDs ... )
}
if len ( newMyOwnerIDs ) > 0 {
cache = cache . DelFriendIDs ( newMyOwnerIDs ... )
cache = cache . DelOwner ( ownerUserID , newMyOwnerIDs ) . DelMaxFriendVersion ( newMyOwnerIDs ... )
}
2024-05-27 11:58:36 +08:00
return cache . ChainExecDel ( ctx )
2023-12-05 20:53:02 +08:00
} )
2023-06-30 09:45:02 +08:00
}
2024-03-04 12:12:14 +08:00
// RefuseFriendRequest rejects a friend request. It first checks for an existing, unprocessed request.
// If no such request exists, it returns an error. Otherwise, it marks the request as refused.
2024-05-27 11:58:36 +08:00
func ( f * friendDatabase ) RefuseFriendRequest ( ctx context . Context , friendRequest * model . FriendRequest ) error {
2024-03-04 12:12:14 +08:00
// Attempt to retrieve the friend request from the database.
2023-06-30 09:45:02 +08:00
fr , err := f . friendRequest . Take ( ctx , friendRequest . FromUserID , friendRequest . ToUserID )
if err != nil {
2026-01-22 16:34:00 +08:00
return err
2023-06-30 09:45:02 +08:00
}
2024-03-04 12:12:14 +08:00
// Check if the friend request has already been handled.
2023-06-30 09:45:02 +08:00
if fr . HandleResult != 0 {
2026-01-22 16:34:00 +08:00
return servererrs . ErrFriendRequestHandled . WrapMsg ( "friend request has already been processed" , "from" , friendRequest . FromUserID , "to" , friendRequest . ToUserID )
2023-06-30 09:45:02 +08:00
}
2024-03-04 12:12:14 +08:00
// Log the action of refusing the friend request for debugging and auditing purposes.
log . ZDebug ( ctx , "Refusing friend request" , map [ string ] interface { } {
"DB_FriendRequest" : fr ,
"Arg_FriendRequest" : friendRequest ,
} )
// Mark the friend request as refused and update the handle time.
2023-06-30 09:45:02 +08:00
friendRequest . HandleResult = constant . FriendResponseRefuse
friendRequest . HandleTime = time . Now ( )
2024-03-04 12:12:14 +08:00
if err := f . friendRequest . Update ( ctx , friendRequest ) ; err != nil {
2026-01-22 16:34:00 +08:00
return err
2023-06-30 09:45:02 +08:00
}
2024-03-04 12:12:14 +08:00
2023-06-30 09:45:02 +08:00
return nil
}
2024-03-04 12:12:14 +08:00
// AgreeFriendRequest accepts a friend request. It first checks for an existing, unprocessed request.
2024-05-27 11:58:36 +08:00
func ( f * friendDatabase ) AgreeFriendRequest ( ctx context . Context , friendRequest * model . FriendRequest ) ( err error ) {
2023-12-05 20:53:02 +08:00
return f . tx . Transaction ( ctx , func ( ctx context . Context ) error {
2023-07-13 15:26:25 +08:00
now := time . Now ( )
2023-12-05 20:53:02 +08:00
fr , err := f . friendRequest . Take ( ctx , friendRequest . FromUserID , friendRequest . ToUserID )
2023-06-30 09:45:02 +08:00
if err != nil {
return err
}
if fr . HandleResult != 0 {
2024-04-19 22:23:08 +08:00
return errs . ErrArgs . WrapMsg ( "the friend request has been processed" )
2023-06-30 09:45:02 +08:00
}
friendRequest . HandlerUserID = mcontext . GetOpUserID ( ctx )
friendRequest . HandleResult = constant . FriendResponseAgree
2023-07-13 15:26:25 +08:00
friendRequest . HandleTime = now
2023-12-05 20:53:02 +08:00
err = f . friendRequest . Update ( ctx , friendRequest )
2023-06-30 09:45:02 +08:00
if err != nil {
return err
}
2023-07-13 15:26:25 +08:00
2023-12-05 20:53:02 +08:00
fr2 , err := f . friendRequest . Take ( ctx , friendRequest . ToUserID , friendRequest . FromUserID )
2023-07-13 15:26:25 +08:00
if err == nil && fr2 . HandleResult == constant . FriendResponseNotHandle {
fr2 . HandlerUserID = mcontext . GetOpUserID ( ctx )
fr2 . HandleResult = constant . FriendResponseAgree
fr2 . HandleTime = now
2023-12-05 20:53:02 +08:00
err = f . friendRequest . Update ( ctx , fr2 )
2023-07-13 15:26:25 +08:00
if err != nil {
return err
}
2024-05-27 11:58:36 +08:00
} else if err != nil && ( ! mgo . IsNotFound ( err ) ) {
2023-07-13 15:26:25 +08:00
return err
}
2023-12-05 20:53:02 +08:00
exists , err := f . friend . FindUserState ( ctx , friendRequest . FromUserID , friendRequest . ToUserID )
2023-06-30 09:45:02 +08:00
if err != nil {
return err
}
2024-05-27 11:58:36 +08:00
existsMap := datautil . SliceSet ( datautil . Slice ( exists , func ( friend * model . Friend ) [ 2 ] string {
2024-03-04 12:12:14 +08:00
return [ ... ] string { friend . OwnerUserID , friend . FriendUserID } // My - Friend
2023-06-30 09:45:02 +08:00
} ) )
2024-05-27 11:58:36 +08:00
var adds [ ] * model . Friend
2024-03-04 12:12:14 +08:00
if _ , ok := existsMap [ [ ... ] string { friendRequest . ToUserID , friendRequest . FromUserID } ] ; ! ok { // My - Friend
2023-07-03 16:29:22 +08:00
adds = append (
adds ,
2024-05-27 11:58:36 +08:00
& model . Friend {
2023-07-03 16:29:22 +08:00
OwnerUserID : friendRequest . ToUserID ,
FriendUserID : friendRequest . FromUserID ,
AddSource : int32 ( constant . BecomeFriendByApply ) ,
OperatorUserID : friendRequest . FromUserID ,
} ,
)
2023-06-30 09:45:02 +08:00
}
2024-03-04 12:12:14 +08:00
if _ , ok := existsMap [ [ ... ] string { friendRequest . FromUserID , friendRequest . ToUserID } ] ; ! ok { // My - Friend
2023-07-03 16:29:22 +08:00
adds = append (
adds ,
2024-05-27 11:58:36 +08:00
& model . Friend {
2023-07-03 16:29:22 +08:00
OwnerUserID : friendRequest . FromUserID ,
FriendUserID : friendRequest . ToUserID ,
AddSource : int32 ( constant . BecomeFriendByApply ) ,
OperatorUserID : friendRequest . FromUserID ,
} ,
)
2023-06-30 09:45:02 +08:00
}
if len ( adds ) > 0 {
2023-12-05 20:53:02 +08:00
if err := f . friend . Create ( ctx , adds ) ; err != nil {
2023-06-30 09:45:02 +08:00
return err
}
}
2024-07-01 17:38:14 +08:00
return f . cache . DelFriendIDs ( friendRequest . ToUserID , friendRequest . FromUserID ) . DelMaxFriendVersion ( friendRequest . ToUserID , friendRequest . FromUserID ) . ChainExecDel ( ctx )
2023-06-30 09:45:02 +08:00
} )
}
2024-03-04 12:12:14 +08:00
// Delete removes a friend relationship. It is assumed that the external caller has verified the friendship status.
2023-06-30 09:45:02 +08:00
func ( f * friendDatabase ) Delete ( ctx context . Context , ownerUserID string , friendUserIDs [ ] string ) ( err error ) {
if err := f . friend . Delete ( ctx , ownerUserID , friendUserIDs ) ; err != nil {
return err
}
2024-07-01 17:38:14 +08:00
userIds := append ( friendUserIDs , ownerUserID )
return f . cache . DelFriendIDs ( userIds ... ) . DelMaxFriendVersion ( userIds ... ) . ChainExecDel ( ctx )
2023-06-30 09:45:02 +08:00
}
2024-03-04 12:12:14 +08:00
// UpdateRemark updates the remark for a friend. Zero value for remark is also supported.
2023-06-30 09:45:02 +08:00
func ( f * friendDatabase ) UpdateRemark ( ctx context . Context , ownerUserID , friendUserID , remark string ) ( err error ) {
if err := f . friend . UpdateRemark ( ctx , ownerUserID , friendUserID , remark ) ; err != nil {
return err
}
2024-07-01 17:38:14 +08:00
return f . cache . DelFriend ( ownerUserID , friendUserID ) . DelMaxFriendVersion ( ownerUserID ) . ChainExecDel ( ctx )
2023-06-30 09:45:02 +08:00
}
2024-03-04 12:12:14 +08:00
// PageOwnerFriends retrieves the list of friends for the ownerUserID. It does not return an error if the result is empty.
2024-05-27 11:58:36 +08:00
func ( f * friendDatabase ) PageOwnerFriends ( ctx context . Context , ownerUserID string , pagination pagination . Pagination ) ( total int64 , friends [ ] * model . Friend , err error ) {
2023-12-05 20:53:02 +08:00
return f . friend . FindOwnerFriends ( ctx , ownerUserID , pagination )
2023-06-30 09:45:02 +08:00
}
2024-03-04 12:12:14 +08:00
// PageInWhoseFriends identifies in whose friend lists the friendUserID appears.
2024-05-27 11:58:36 +08:00
func ( f * friendDatabase ) PageInWhoseFriends ( ctx context . Context , friendUserID string , pagination pagination . Pagination ) ( total int64 , friends [ ] * model . Friend , err error ) {
2023-12-05 20:53:02 +08:00
return f . friend . FindInWhoseFriends ( ctx , friendUserID , pagination )
2023-06-30 09:45:02 +08:00
}
2024-03-04 12:12:14 +08:00
// PageFriendRequestFromMe retrieves friend requests sent by me. It does not return an error if the result is empty.
2025-05-26 10:06:35 +08:00
func ( f * friendDatabase ) PageFriendRequestFromMe ( ctx context . Context , userID string , handleResults [ ] int , pagination pagination . Pagination ) ( total int64 , friends [ ] * model . FriendRequest , err error ) {
return f . friendRequest . FindFromUserID ( ctx , userID , handleResults , pagination )
2023-06-30 09:45:02 +08:00
}
2024-03-04 12:12:14 +08:00
// PageFriendRequestToMe retrieves friend requests received by me. It does not return an error if the result is empty.
2025-05-26 10:06:35 +08:00
func ( f * friendDatabase ) PageFriendRequestToMe ( ctx context . Context , userID string , handleResults [ ] int , pagination pagination . Pagination ) ( total int64 , friends [ ] * model . FriendRequest , err error ) {
return f . friendRequest . FindToUserID ( ctx , userID , handleResults , pagination )
2023-06-30 09:45:02 +08:00
}
2024-03-04 12:12:14 +08:00
// FindFriendsWithError retrieves specified friends' information for ownerUserID. Returns an error if any friend does not exist.
2024-05-27 11:58:36 +08:00
func ( f * friendDatabase ) FindFriendsWithError ( ctx context . Context , ownerUserID string , friendUserIDs [ ] string ) ( friends [ ] * model . Friend , err error ) {
2023-06-30 09:45:02 +08:00
friends , err = f . friend . FindFriends ( ctx , ownerUserID , friendUserIDs )
if err != nil {
2026-01-22 16:34:00 +08:00
return nil , err
2023-06-30 09:45:02 +08:00
}
2026-01-22 16:34:00 +08:00
return friends , nil
2023-06-30 09:45:02 +08:00
}
2023-12-05 20:53:02 +08:00
func ( f * friendDatabase ) FindFriendUserIDs ( ctx context . Context , ownerUserID string ) ( friendUserIDs [ ] string , err error ) {
2023-06-30 09:45:02 +08:00
return f . cache . GetFriendIDs ( ctx , ownerUserID )
}
2023-07-27 12:32:08 +08:00
2024-05-27 11:58:36 +08:00
func ( f * friendDatabase ) FindBothFriendRequests ( ctx context . Context , fromUserID , toUserID string ) ( friends [ ] * model . FriendRequest , err error ) {
2023-07-27 12:32:08 +08:00
return f . friendRequest . FindBothFriendRequests ( ctx , fromUserID , toUserID )
}
2024-01-10 10:27:03 +08:00
func ( f * friendDatabase ) UpdateFriends ( ctx context . Context , ownerUserID string , friendUserIDs [ ] string , val map [ string ] any ) ( err error ) {
if len ( val ) == 0 {
return nil
2023-12-18 18:39:58 +08:00
}
2024-07-01 17:38:14 +08:00
return f . tx . Transaction ( ctx , func ( ctx context . Context ) error {
if err := f . friend . UpdateFriends ( ctx , ownerUserID , friendUserIDs , val ) ; err != nil {
return err
}
return f . cache . DelFriends ( ownerUserID , friendUserIDs ) . DelMaxFriendVersion ( ownerUserID ) . ChainExecDel ( ctx )
} )
}
//func (f *friendDatabase) FindSortFriendUserIDs(ctx context.Context, ownerUserID string) ([]string, error) {
// return f.cache.FindSortFriendUserIDs(ctx, ownerUserID)
//}
func ( f * friendDatabase ) FindFriendIncrVersion ( ctx context . Context , ownerUserID string , version uint , limit int ) ( * model . VersionLog , error ) {
return f . friend . FindIncrVersion ( ctx , ownerUserID , version , limit )
}
func ( f * friendDatabase ) FindMaxFriendVersionCache ( ctx context . Context , ownerUserID string ) ( * model . VersionLog , error ) {
return f . cache . FindMaxFriendVersion ( ctx , ownerUserID )
}
func ( f * friendDatabase ) FindFriendUserID ( ctx context . Context , friendUserID string ) ( [ ] string , error ) {
return f . friend . FindFriendUserID ( ctx , friendUserID )
}
//func (f *friendDatabase) SearchFriend(ctx context.Context, ownerUserID, keyword string, pagination pagination.Pagination) (int64, []*model.Friend, error) {
// return f.friend.SearchFriend(ctx, ownerUserID, keyword, pagination)
//}
func ( f * friendDatabase ) OwnerIncrVersion ( ctx context . Context , ownerUserID string , friendUserIDs [ ] string , state int32 ) error {
if err := f . friend . IncrVersion ( ctx , ownerUserID , friendUserIDs , state ) ; err != nil {
2023-12-28 14:45:27 +08:00
return err
}
2024-07-01 17:38:14 +08:00
return f . cache . DelMaxFriendVersion ( ownerUserID ) . ChainExecDel ( ctx )
2023-12-28 14:45:27 +08:00
}
2025-05-26 10:06:35 +08:00
func ( f * friendDatabase ) GetUnhandledCount ( ctx context . Context , userID string , ts int64 ) ( int64 , error ) {
return f . friendRequest . GetUnhandledCount ( ctx , userID , ts )
}