112 lines
3.4 KiB
Go
112 lines
3.4 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"tailly_clips/internal/domain"
|
|
"tailly_clips/internal/repository"
|
|
"time"
|
|
)
|
|
|
|
type LikeService interface {
|
|
LikeClip(ctx context.Context, clipID, userID int) (*domain.ClipLike, error)
|
|
UnlikeClip(ctx context.Context, clipID, userID int) error
|
|
GetClipLikes(ctx context.Context, clipID, limit, offset int) ([]*domain.ClipLike, int, error)
|
|
CheckIfLiked(ctx context.Context, clipID, userID int) (bool, error)
|
|
}
|
|
|
|
type likeService struct {
|
|
likeRepo repository.LikeRepository
|
|
clipRepo repository.ClipRepository
|
|
}
|
|
|
|
func NewLikeService(likeRepo repository.LikeRepository, clipRepo repository.ClipRepository) LikeService {
|
|
return &likeService{
|
|
likeRepo: likeRepo,
|
|
clipRepo: clipRepo,
|
|
}
|
|
}
|
|
|
|
func (s *likeService) LikeClip(ctx context.Context, clipID, userID int) (*domain.ClipLike, error) {
|
|
// Проверяем существование клипа
|
|
if _, err := s.clipRepo.GetByID(ctx, clipID); err != nil {
|
|
return nil, fmt.Errorf("clip not found: %w", err)
|
|
}
|
|
|
|
// Проверяем не лайкнул ли уже пользователь
|
|
alreadyLiked, err := s.likeRepo.CheckExists(ctx, clipID, userID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to check like existence: %w", err)
|
|
}
|
|
if alreadyLiked {
|
|
return nil, fmt.Errorf("user already liked this clip")
|
|
}
|
|
|
|
// Создаем лайк
|
|
like := &domain.ClipLike{
|
|
ClipID: clipID,
|
|
UserID: userID,
|
|
CreatedAt: time.Now(),
|
|
}
|
|
|
|
if err := s.likeRepo.Create(ctx, like); err != nil {
|
|
return nil, fmt.Errorf("failed to create like: %w", err)
|
|
}
|
|
|
|
// Увеличиваем счетчик лайков
|
|
if err := s.clipRepo.IncrementLikesCount(ctx, clipID); err != nil {
|
|
// Откатываем создание лайка при ошибке
|
|
s.likeRepo.Delete(ctx, clipID, userID)
|
|
return nil, fmt.Errorf("failed to increment likes count: %w", err)
|
|
}
|
|
|
|
return like, nil
|
|
}
|
|
|
|
func (s *likeService) UnlikeClip(ctx context.Context, clipID, userID int) error {
|
|
// Проверяем существование клипа
|
|
if _, err := s.clipRepo.GetByID(ctx, clipID); err != nil {
|
|
return fmt.Errorf("clip not found: %w", err)
|
|
}
|
|
|
|
// Удаляем лайк
|
|
if err := s.likeRepo.Delete(ctx, clipID, userID); err != nil {
|
|
return fmt.Errorf("failed to delete like: %w", err)
|
|
}
|
|
|
|
// Уменьшаем счетчик лайков
|
|
if err := s.clipRepo.DecrementLikesCount(ctx, clipID); err != nil {
|
|
return fmt.Errorf("failed to decrement likes count: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *likeService) GetClipLikes(ctx context.Context, clipID, limit, offset int) ([]*domain.ClipLike, int, error) {
|
|
// Проверяем существование клипа
|
|
if _, err := s.clipRepo.GetByID(ctx, clipID); err != nil {
|
|
return nil, 0, fmt.Errorf("clip not found: %w", err)
|
|
}
|
|
|
|
likes, totalCount, err := s.likeRepo.GetByClipID(ctx, clipID, limit, offset)
|
|
if err != nil {
|
|
return nil, 0, fmt.Errorf("failed to get clip likes: %w", err)
|
|
}
|
|
|
|
return likes, totalCount, nil
|
|
}
|
|
|
|
func (s *likeService) CheckIfLiked(ctx context.Context, clipID, userID int) (bool, error) {
|
|
// Проверяем существование клипа
|
|
if _, err := s.clipRepo.GetByID(ctx, clipID); err != nil {
|
|
return false, fmt.Errorf("clip not found: %w", err)
|
|
}
|
|
|
|
isLiked, err := s.likeRepo.CheckExists(ctx, clipID, userID)
|
|
if err != nil {
|
|
return false, fmt.Errorf("failed to check like status: %w", err)
|
|
}
|
|
|
|
return isLiked, nil
|
|
}
|