spark-server/internal/module/message/logic/send_perm.go
2026-09-18 14:50:41 +08:00

140 lines
3.4 KiB
Go

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
}