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) // Новые методы для уведомлений GetLikeNotifications(ctx context.Context, userID int, unreadOnly bool, limit, offset int) ([]*domain.LikeNotification, int, int, error) MarkLikeNotificationAsRead(ctx context.Context, notificationID, userID int) error MarkAllLikeNotificationsAsRead(ctx context.Context, userID int) error } // Реализация сервиса лайков type likeService struct { likeRepo repository.LikeRepository postRepo repository.PostRepository userRepo repository.UserRepository // Добавляем для получения информации о пользователях } // Конструктор сервиса func NewLikeService(likeRepo repository.LikeRepository, postRepo repository.PostRepository, userRepo repository.UserRepository) LikeService { return &likeService{ likeRepo: likeRepo, postRepo: postRepo, userRepo: userRepo, } } // Поставить лайк посту func (s *likeService) LikePost(ctx context.Context, userID, postID int) (*domain.Like, error) { // Проверяем существование поста post, err := s.postRepo.GetByID(ctx, postID) if 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") } // Проверяем, что пользователь не лайкает свой собственный пост if post.AuthorID == userID { return nil, errors.New("cannot like your own post") } like := &domain.Like{ PostID: postID, UserID: userID, CreatedAt: time.Now(), IsRead: false, NotifiedAt: 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 } 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 } // Новые методы для уведомлений func (s *likeService) GetLikeNotifications(ctx context.Context, userID int, unreadOnly bool, limit, offset int) ([]*domain.LikeNotification, int, int, error) { var notifications []*domain.LikeNotification var err error if unreadOnly { notifications, err = s.likeRepo.GetUnreadLikeNotifications(ctx, userID, limit, offset) } else { notifications, err = s.likeRepo.GetAllLikeNotifications(ctx, userID, limit, offset) } if err != nil { return nil, 0, 0, err } totalCount, unreadCount, err := s.likeRepo.GetLikeNotificationCounts(ctx, userID) if err != nil { return nil, 0, 0, err } return notifications, totalCount, unreadCount, nil } func (s *likeService) MarkLikeNotificationAsRead(ctx context.Context, notificationID, userID int) error { return s.likeRepo.MarkLikeNotificationAsRead(ctx, notificationID, userID) } func (s *likeService) MarkAllLikeNotificationsAsRead(ctx context.Context, userID int) error { return s.likeRepo.MarkAllLikeNotificationsAsRead(ctx, userID) }