package logic import ( "context" "errors" "time" "spark-server/internal/module/square/entity" "spark-server/internal/pkg/errs" ) func (s *Service) Like(ctx context.Context, userID, postID int64, channel entity.Channel) (*View, error) { post, err := s.visiblePost(ctx, userID, postID, channel) if err != nil { return nil, err } if !s.allowInteract(ctx, userID) { return nil, errs.ErrRateLimited } created, err := s.repo.AddLike(ctx, &entity.Like{PostID: postID, UserID: userID, CreatedAtMS: time.Now().UnixMilli()}) if err != nil { return nil, err } if created { _ = s.notify(ctx, []*entity.Notice{s.newNotice(post.UserID, userID, entity.NoticeLike, post.Channel, postID, 0)}) } return s.Get(ctx, userID, postID, channel) } func (s *Service) Unlike(ctx context.Context, userID, postID int64, channel entity.Channel) (*View, error) { if _, err := s.visiblePost(ctx, userID, postID, channel); err != nil { return nil, err } if err := s.repo.RemoveLike(ctx, postID, userID); err != nil && !errors.Is(err, errs.ErrNotFound) { return nil, err } return s.Get(ctx, userID, postID, channel) } func (s *Service) visiblePost(ctx context.Context, viewerID, postID int64, channel entity.Channel) (*entity.Post, error) { if !s.ready() || viewerID <= 0 { return nil, errs.ErrUnauthorized } if postID <= 0 { return nil, errs.ErrInvalidArgument } channel = normalizeChannel(channel) post, err := s.repo.GetPost(ctx, postID) if err != nil { return nil, err } if normalizeChannel(post.Channel) != channel { return nil, errs.ErrNotFound } vis, err := s.visFor(ctx, viewerID, []*entity.Post{post}) if err != nil { return nil, err } if !vis.canSee(post) { return nil, errs.ErrNotFound } return post, nil }