package friend import ( "context" svc "gim/internal/business/comm/service" "gim/internal/business/comm/utils" "gim/internal/logic/domain/message/repo" "gim/internal/logic/proxy" "gim/pkg/db" "gim/pkg/gerrors" "gim/pkg/grpclib" "gim/pkg/pb" "gim/pkg/rpc" "google.golang.org/protobuf/proto" "time" ) type friendService struct{} var FriendService = new(friendService) // List 获取好友列表 func (s *friendService) List(ctx context.Context, userId int64) ([]*pb.Friend, error) { friends, err := FriendRepo.List(userId, FriendStatusAgree) if err != nil { return nil, err } userIds := make(map[int64]int32, len(friends)) for i := range friends { userIds[friends[i].FriendId] = 0 } resp, err := rpc.GetBusinessIntClient().GetUsers(ctx, &pb.GetUsersReq{UserIds: userIds}) if err != nil { return nil, err } var infos = make([]*pb.Friend, len(friends)) for i := range friends { friend := pb.Friend{ UserId: friends[i].FriendId, Remarks: friends[i].Remarks, Extra: friends[i].Extra, } user, ok := resp.Users[friends[i].FriendId] if ok { friend.Nickname = user.Nickname friend.Sex = user.Sex friend.AvatarUrl = user.AvatarUrl friend.UserExtra = user.Extra } infos[i] = &friend } return infos, nil } // DeleteFriend 删除好友 func (*friendService) DeleteFriend(ctx context.Context, userId, friendId int64) error { err := FriendRepo.Delete(userId, friendId) if err != nil { return err } return nil } // AddFriend 添加好友 func (*friendService) AddFriend(ctx context.Context, userId, friendId int64, remarks, description string) error { masterId, _ := grpclib.GetCtxMasterId(ctx) isAutoAddFriends := svc.SysCfgGet(masterId, "is_auto_add_friends") friend, err := FriendRepo.Get(userId, friendId) if err != nil { return err } if friend != nil { if friend.Status == FriendStatusApply { if isAutoAddFriends != "1" { return nil } //TODO::防止第一次加好友失败 db.DB.Where("user_id = ? and friend_id = ?", userId, friendId).Delete(&friend) } if friend.Status == FriendStatusAgree { return gerrors.ErrAlreadyIsFriend } } now := time.Now() err = FriendRepo.Save(&Friend{ UserId: userId, FriendId: friendId, Remarks: remarks, Status: FriendStatusApply, CreateTime: now, UpdateTime: now, }) if err != nil { return err } resp, err := rpc.GetBusinessIntClient().GetUser(ctx, &pb.GetUserReq{UserId: userId}) if err != nil { return err } err = proxy.MessageProxy.PushToUser(ctx, friendId, pb.PushCode_PC_ADD_FRIEND, &pb.AddFriendPush{ FriendId: userId, Nickname: resp.User.Nickname, AvatarUrl: resp.User.AvatarUrl, Description: description, }, true) if err != nil { return err } //TODO::判断是否需要`自动添加好友` //if isAutoAddFriends == "1" && resp.User.IsAutoAddedFriends == 1 { if isAutoAddFriends == "1" { respFriend, err := rpc.GetBusinessIntClient().GetUser(ctx, &pb.GetUserReq{UserId: friendId}) if err != nil { return err } utils.FilePutContents("addFriend", utils.SerializeStr(map[string]interface{}{ "is_auto_add_friends": isAutoAddFriends, "user": resp.User, })) if description == "社交人脉圈添加好友" { return FriendService.AgreeAddFriend(ctx, friendId, userId, description) } else if description == "客服自动添加" { return FriendService.AgreeAddFriend(ctx, friendId, userId, "客服") } else { if respFriend.User.IsAutoAddedFriends == 1 { return FriendService.AgreeAddFriend(ctx, friendId, userId, "系统自动添加") } } } return nil } // AgreeAddFriend 同意添加好友 func (*friendService) AgreeAddFriend(ctx context.Context, userId, friendId int64, remarks string) error { friend, err := FriendRepo.Get(friendId, userId) if err != nil { return err } if friend == nil { utils.FilePutContents("AgreeAddFriend", utils.SerializeStr(map[string]interface{}{ "userId": userId, "friendId": friendId, })) return gerrors.ErrBadRequest } if friend.Status == FriendStatusAgree { return nil } friend.Status = FriendStatusAgree err = FriendRepo.Save(friend) if err != nil { return err } newFriend, err := FriendRepo.Get(userId, friendId) if newFriend != nil && newFriend.Status != FriendStatusAgree { newFriend.Status = FriendStatusAgree err = FriendRepo.Save(newFriend) } else { now := time.Now() err = FriendRepo.Save(&Friend{ UserId: userId, FriendId: friendId, Remarks: remarks, Status: FriendStatusAgree, CreateTime: now, UpdateTime: now, }) } if err != nil { return err } resp, err := rpc.GetBusinessIntClient().GetUser(ctx, &pb.GetUserReq{UserId: userId}) if err != nil { return err } err = proxy.MessageProxy.PushToUser(ctx, friendId, pb.PushCode_PC_AGREE_ADD_FRIEND, &pb.AgreeAddFriendPush{ FriendId: userId, Nickname: resp.User.Nickname, AvatarUrl: resp.User.AvatarUrl, }, true) utils.FilePutContents("push_AgreeAddFriend", utils.SerializeStr(map[string]interface{}{ "friend_id": userId, "friend_nick_name": resp.User.Nickname, "friend_avatar_url": resp.User.AvatarUrl, "err": err, })) if err != nil { return err } return nil } // SendToFriend 消息发送至好友 func (*friendService) SendToFriend(ctx context.Context, sender *pb.Sender, req *pb.SendMessageReq) (int64, error) { //TODO::判断是否为好友 friend, err := FriendRepo.Get(sender.SenderId, req.ReceiverId) if err != nil { return 0, err } if friend == nil || friend.Status != FriendStatusAgree { return 0, gerrors.ErrNotIsFriend } //utils.FilePutContents("sendToFriend", utils.SerializeStr(map[string]interface{}{ // "send": sender, // "req": req, //})) // 发给发送者 seq, err := proxy.MessageProxy.SendToUser(ctx, sender, sender.SenderId, req) if err != nil { return 0, err } // 发给接收者 _, err = proxy.MessageProxy.SendToUser(ctx, sender, req.ReceiverId, req) if err != nil { return 0, err } return seq, nil } // RecallMessageSendToFriend 撤回消息发送至好友 func (*friendService) RecallMessageSendToFriend(ctx context.Context, sender *pb.Sender, req *pb.RecallMessageReq) (int64, error) { //TODO::判断是否为好友 friend, err := FriendRepo.Get(sender.SenderId, req.ReceiverId) if err != nil { return 0, err } if friend == nil || friend.Status != FriendStatusAgree { return 0, gerrors.ErrNotIsFriend } utils.FilePutContents("RecallMessageSendToFriend", utils.SerializeStr(map[string]interface{}{ "send": sender, "req": req, })) //查询到对应seq的消息 msg := &pb.RECALL{} err = proto.Unmarshal(req.MessageContent, msg) if err != nil { return 0, err } message, err := repo.MessageRepo.GetMessage(sender.SenderId, msg.RecallSeq) if err != nil { return 0, err } // 发给发送者 seq, err := proxy.MessageProxy.RecallMessageSendToUser(ctx, sender, sender.SenderId, req, message.SendTime) if err != nil { return 0, err } // 发给接收者 _, err = proxy.MessageProxy.RecallMessageSendToUser(ctx, sender, req.ReceiverId, req, message.SendTime) if err != nil { return 0, err } return seq, nil } // RedPackageMessageSendToFriend 红包发送至好友 func (*friendService) RedPackageMessageSendToFriend(ctx context.Context, sender *pb.Sender, req *pb.SendRedPacketReq) (int64, error) { //TODO::判断是否为好友 friend, err := FriendRepo.Get(sender.SenderId, req.ReceiverId) if err != nil { return 0, err } if friend == nil || friend.Status != FriendStatusAgree { return 0, gerrors.ErrNotIsFriend } utils.FilePutContents("RedPackageMessageSendToFriend", utils.SerializeStr(map[string]interface{}{ "send": sender, "req": req, })) // 发给发送者 seq, err := proxy.MessageProxy.SendRedPackageToUser(ctx, sender, sender.SenderId, req) if err != nil { return 0, err } // 发给接收者 _, err = proxy.MessageProxy.SendRedPackageToUser(ctx, sender, req.ReceiverId, req) if err != nil { return 0, err } return seq, nil }