package repository import ( "context" "database/sql" "errors" "tailly_back_v2/internal/domain" ) var ( ErrLikeNotFound = errors.New("like not found") ErrLikeAlreadyExists = errors.New("like already exists") ) type LikeRepository interface { Create(ctx context.Context, like *domain.Like) error GetByID(ctx context.Context, id int) (*domain.Like, error) GetByPostID(ctx context.Context, postID int) ([]*domain.Like, error) GetByUserAndPost(ctx context.Context, userID, postID int) (*domain.Like, error) Delete(ctx context.Context, id int) error DeleteByUserAndPost(ctx context.Context, userID, postID int) error } type likeRepository struct { db *sql.DB } func (r *likeRepository) GetByID(ctx context.Context, id int) (*domain.Like, error) { //TODO implement me panic("implement me") } func (r *likeRepository) Delete(ctx context.Context, id int) error { //TODO implement me panic("implement me") } func NewLikeRepository(db *sql.DB) *likeRepository { return &likeRepository{db: db} } func (r *likeRepository) Create(ctx context.Context, like *domain.Like) error { // Проверяем, существует ли уже лайк _, err := r.GetByUserAndPost(ctx, like.UserID, like.PostID) if err == nil { return ErrLikeAlreadyExists } else if err != ErrLikeNotFound { return err } query := ` INSERT INTO likes (post_id, user_id, created_at) VALUES ($1, $2, $3) RETURNING id ` err = r.db.QueryRowContext(ctx, query, like.PostID, like.UserID, like.CreatedAt, ).Scan(&like.ID) return err } func (r *likeRepository) GetByPostID(ctx context.Context, postID int) ([]*domain.Like, error) { query := ` SELECT id, post_id, user_id, created_at FROM likes WHERE post_id = $1 ORDER BY created_at DESC ` rows, err := r.db.QueryContext(ctx, query, postID) if err != nil { return nil, err } defer rows.Close() var likes []*domain.Like for rows.Next() { like := &domain.Like{} err := rows.Scan( &like.ID, &like.PostID, &like.UserID, &like.CreatedAt, ) if err != nil { return nil, err } likes = append(likes, like) } return likes, nil } func (r *likeRepository) DeleteByUserAndPost(ctx context.Context, userID, postID int) error { query := ` DELETE FROM likes WHERE user_id = $1 AND post_id = $2 ` _, err := r.db.ExecContext(ctx, query, userID, postID) return err } func (r *likeRepository) GetByUserAndPost(ctx context.Context, userID, postID int) (*domain.Like, error) { query := ` SELECT id, post_id, user_id, created_at FROM likes WHERE user_id = $1 AND post_id = $2 LIMIT 1 ` like := &domain.Like{} err := r.db.QueryRowContext(ctx, query, userID, postID).Scan( &like.ID, &like.PostID, &like.UserID, &like.CreatedAt, ) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, ErrLikeNotFound } return nil, err } return like, nil }