127 lines
3.6 KiB
Go
127 lines
3.6 KiB
Go
package service
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"tailly_back_v2/internal/domain"
|
||
"tailly_back_v2/internal/repository"
|
||
"time"
|
||
)
|
||
|
||
// Интерфейс сервиса лайков
|
||
type LikeService interface {
|
||
LikePost(ctx context.Context, userID, postID int) (*domain.Like, error)
|
||
UnlikePost(ctx context.Context, userID, postID int) error
|
||
GetByPostID(ctx context.Context, postID int) ([]*domain.Like, error)
|
||
GetCountForPost(ctx context.Context, postID int) (int, error)
|
||
CheckIfLiked(ctx context.Context, userID, postID int) (bool, error)
|
||
}
|
||
|
||
// Реализация сервиса лайков
|
||
type likeService struct {
|
||
likeRepo repository.LikeRepository
|
||
postRepo repository.PostRepository // Для проверки существования поста
|
||
}
|
||
|
||
// Конструктор сервиса
|
||
func NewLikeService(likeRepo repository.LikeRepository, postRepo repository.PostRepository) LikeService {
|
||
return &likeService{
|
||
likeRepo: likeRepo,
|
||
postRepo: postRepo,
|
||
}
|
||
}
|
||
|
||
// Поставить лайк посту
|
||
func (s *likeService) LikePost(ctx context.Context, userID, postID int) (*domain.Like, error) {
|
||
// Проверяем существование поста
|
||
if _, err := s.postRepo.GetByID(ctx, postID); err != nil {
|
||
if errors.Is(err, repository.ErrPostNotFound) {
|
||
return nil, errors.New("post not found")
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
// Проверяем, не поставил ли пользователь уже лайк
|
||
if liked, err := s.CheckIfLiked(ctx, userID, postID); err != nil {
|
||
return nil, err
|
||
} else if liked {
|
||
return nil, errors.New("you have already liked this post")
|
||
}
|
||
|
||
like := &domain.Like{
|
||
PostID: postID,
|
||
UserID: userID,
|
||
CreatedAt: time.Now(),
|
||
}
|
||
|
||
if err := s.likeRepo.Create(ctx, like); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return like, nil
|
||
}
|
||
|
||
// Убрать лайк с поста
|
||
func (s *likeService) UnlikePost(ctx context.Context, userID, postID int) error {
|
||
// Проверяем существование поста
|
||
if _, err := s.postRepo.GetByID(ctx, postID); err != nil {
|
||
if errors.Is(err, repository.ErrPostNotFound) {
|
||
return errors.New("post not found")
|
||
}
|
||
return err
|
||
}
|
||
|
||
// Проверяем, ставил ли пользователь лайк
|
||
if liked, err := s.CheckIfLiked(ctx, userID, postID); err != nil {
|
||
return err
|
||
} else if !liked {
|
||
return errors.New("you haven't liked this post yet")
|
||
}
|
||
|
||
return s.likeRepo.DeleteByUserAndPost(ctx, userID, postID)
|
||
}
|
||
|
||
// Получить все лайки для поста
|
||
func (s *likeService) GetByPostID(ctx context.Context, postID int) ([]*domain.Like, error) {
|
||
// Проверяем существование поста
|
||
if _, err := s.postRepo.GetByID(ctx, postID); err != nil {
|
||
if errors.Is(err, repository.ErrPostNotFound) {
|
||
return nil, errors.New("post not found")
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
likes, err := s.likeRepo.GetByPostID(ctx, postID)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// Возвращаем пустой слайс вместо nil
|
||
if likes == nil {
|
||
return []*domain.Like{}, nil
|
||
}
|
||
|
||
return likes, nil
|
||
}
|
||
|
||
// Получить количество лайков для поста
|
||
func (s *likeService) GetCountForPost(ctx context.Context, postID int) (int, error) {
|
||
likes, err := s.GetByPostID(ctx, postID)
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
return len(likes), nil
|
||
}
|
||
|
||
// Проверить, поставил ли пользователь лайк
|
||
func (s *likeService) CheckIfLiked(ctx context.Context, userID, postID int) (bool, error) {
|
||
_, err := s.likeRepo.GetByUserAndPost(ctx, userID, postID)
|
||
if err != nil {
|
||
if errors.Is(err, repository.ErrLikeNotFound) {
|
||
return false, nil
|
||
}
|
||
return false, err
|
||
}
|
||
return true, nil
|
||
}
|