tailly_clips/internal/service/like_service.go
admin 57eba68496
Some checks failed
continuous-integration/drone/push Build is failing
v.0.0.1 Создан сервис клипов
2025-09-02 11:58:10 +03:00

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
}