package logic import ( "context" "errors" conventity "spark-server/internal/module/conversation/entity" "spark-server/internal/module/message/entity" "spark-server/internal/pkg/errs" ) func (s *Service) prepareSend(ctx context.Context, userID int64, in *SendInput) (*conventity.Conversation, []int64, error) { if in.ConversationID <= 0 && in.PeerID <= 0 { return nil, nil, errs.ErrInvalidArgument } convID := in.ConversationID if convID <= 0 { if s.p2p == nil || s.friends == nil || in.PeerID <= 0 { return nil, nil, errs.ErrForbidden } if err := s.friends.CanSend(ctx, userID, in.PeerID); err != nil { return nil, nil, err } id, err := s.p2p.EnsureP2P(ctx, userID, in.PeerID) if err != nil { return nil, nil, err } convID = id } if _, err := s.chats.GetMember(ctx, convID, userID); err != nil { if errors.Is(err, errs.ErrNotFound) { return nil, nil, errs.ErrForbidden } return nil, nil, err } conv, err := s.chats.Get(ctx, convID) if err != nil { return nil, nil, err } memberIDs, err := s.recipientIDs(ctx, userID, conv) if err != nil { return nil, nil, err } return conv, memberIDs, nil } func (s *Service) stampTargets(ctx context.Context, userID int64, conv *conventity.Conversation, memberIDs []int64, msg *entity.Message) error { if conv == nil || msg == nil { return nil } switch conv.Type { case conventity.TypeP2P: msg.ReceiverID = otherMember(userID, memberIDs) case conventity.TypeGroup: if s.groups == nil { return errs.ErrForbidden } gid, err := s.groups.IDByConversation(ctx, conv.ID) if err != nil { return err } msg.GroupID = gid } return nil } func kindOfConv(conv *conventity.Conversation) entity.Kind { if conv != nil && conv.Type == conventity.TypeGroup { return entity.KindGroup } return entity.KindPrivate } func (s *Service) recipientIDs(ctx context.Context, userID int64, conv *conventity.Conversation) ([]int64, error) { switch conv.Type { case conventity.TypeP2P: ids, err := s.chats.ListMemberIDs(ctx, conv.ID) if err != nil { return nil, err } peer := otherMember(userID, ids) if peer <= 0 || s.friends == nil { return nil, errs.ErrForbidden } if err := s.friends.CanSend(ctx, userID, peer); err != nil { return nil, err } return ids, nil case conventity.TypeGroup: if s.groups == nil { return nil, errs.ErrForbidden } if err := s.groups.CanSend(ctx, userID, conv.ID); err != nil { return nil, err } return s.groups.MemberIDs(ctx, conv.ID) default: return nil, errs.ErrForbidden } } func (s *Service) checkReplyTo(ctx context.Context, convID, replyTo int64) error { if replyTo == 0 { return nil } target, err := s.repo.GetByID(ctx, replyTo) if err != nil { if errors.Is(err, errs.ErrNotFound) { return errs.ErrInvalidArgument } return err } if target.ConversationID != convID { return errs.ErrInvalidArgument } return nil } func (s *Service) checkMentions(ctx context.Context, userID int64, conv *conventity.Conversation, content *entity.Content) error { if content == nil || (!content.AtAll && len(content.AtUIDs) == 0) { return nil } if conv == nil || conv.Type != conventity.TypeGroup { return errs.ErrInvalidArgument } if s.groups == nil { return errs.ErrForbidden } return s.groups.CheckMentions(ctx, userID, conv.ID, content.AtAll, content.AtUIDs) } func otherMember(self int64, ids []int64) int64 { for _, id := range ids { if id != self { return id } } return 0 }