140 lines
3.4 KiB
Go
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
|
|
}
|