tailly_clips/internal/repository/comment_repository.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

263 lines
6.4 KiB
Go

package repository
import (
"context"
"database/sql"
"errors"
"fmt"
"tailly_clips/internal/domain"
"time"
)
var (
ErrCommentNotFound = errors.New("comment not found")
)
type CommentRepository interface {
Create(ctx context.Context, comment *domain.ClipComment) error
GetByID(ctx context.Context, id int) (*domain.ClipComment, error)
GetByClipID(ctx context.Context, clipID, limit, offset int) ([]*domain.ClipComment, int, error)
GetByAuthorID(ctx context.Context, authorID, limit, offset int) ([]*domain.ClipComment, int, error)
Update(ctx context.Context, comment *domain.ClipComment) error
Delete(ctx context.Context, id int) error
DeleteByClipID(ctx context.Context, clipID int) error
DeleteByAuthorID(ctx context.Context, authorID int) error
}
type commentRepository struct {
db *sql.DB
}
func NewCommentRepository(db *sql.DB) CommentRepository {
return &commentRepository{db: db}
}
func (r *commentRepository) Create(ctx context.Context, comment *domain.ClipComment) error {
query := `
INSERT INTO clip_comments (clip_id, author_id, content, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5)
RETURNING id
`
err := r.db.QueryRowContext(ctx, query,
comment.ClipID,
comment.AuthorID,
comment.Content,
comment.CreatedAt,
comment.UpdatedAt,
).Scan(&comment.ID)
if err != nil {
return fmt.Errorf("failed to create comment: %w", err)
}
return nil
}
func (r *commentRepository) GetByID(ctx context.Context, id int) (*domain.ClipComment, error) {
query := `
SELECT id, clip_id, author_id, content, created_at, updated_at
FROM clip_comments
WHERE id = $1 AND deleted_at IS NULL
`
comment := &domain.ClipComment{}
err := r.db.QueryRowContext(ctx, query, id).Scan(
&comment.ID,
&comment.ClipID,
&comment.AuthorID,
&comment.Content,
&comment.CreatedAt,
&comment.UpdatedAt,
)
if err == sql.ErrNoRows {
return nil, ErrCommentNotFound
}
if err != nil {
return nil, fmt.Errorf("failed to get comment: %w", err)
}
return comment, nil
}
func (r *commentRepository) GetByClipID(ctx context.Context, clipID, limit, offset int) ([]*domain.ClipComment, int, error) {
// Получаем общее количество
countQuery := `SELECT COUNT(*) FROM clip_comments WHERE clip_id = $1 AND deleted_at IS NULL`
var totalCount int
err := r.db.QueryRowContext(ctx, countQuery, clipID).Scan(&totalCount)
if err != nil {
return nil, 0, fmt.Errorf("failed to get total count: %w", err)
}
// Получаем комментарии
query := `
SELECT id, clip_id, author_id, content, created_at, updated_at
FROM clip_comments
WHERE clip_id = $1 AND deleted_at IS NULL
ORDER BY created_at ASC
LIMIT $2 OFFSET $3
`
rows, err := r.db.QueryContext(ctx, query, clipID, limit, offset)
if err != nil {
return nil, 0, fmt.Errorf("failed to get comments: %w", err)
}
defer rows.Close()
var comments []*domain.ClipComment
for rows.Next() {
comment := &domain.ClipComment{}
err := rows.Scan(
&comment.ID,
&comment.ClipID,
&comment.AuthorID,
&comment.Content,
&comment.CreatedAt,
&comment.UpdatedAt,
)
if err != nil {
return nil, 0, fmt.Errorf("failed to scan comment: %w", err)
}
comments = append(comments, comment)
}
if err = rows.Err(); err != nil {
return nil, 0, fmt.Errorf("rows error: %w", err)
}
return comments, totalCount, nil
}
func (r *commentRepository) GetByAuthorID(ctx context.Context, authorID, limit, offset int) ([]*domain.ClipComment, int, error) {
// Получаем общее количество
countQuery := `SELECT COUNT(*) FROM clip_comments WHERE author_id = $1 AND deleted_at IS NULL`
var totalCount int
err := r.db.QueryRowContext(ctx, countQuery, authorID).Scan(&totalCount)
if err != nil {
return nil, 0, fmt.Errorf("failed to get total count: %w", err)
}
// Получаем комментарии
query := `
SELECT id, clip_id, author_id, content, created_at, updated_at
FROM clip_comments
WHERE author_id = $1 AND deleted_at IS NULL
ORDER BY created_at DESC
LIMIT $2 OFFSET $3
`
rows, err := r.db.QueryContext(ctx, query, authorID, limit, offset)
if err != nil {
return nil, 0, fmt.Errorf("failed to get comments: %w", err)
}
defer rows.Close()
var comments []*domain.ClipComment
for rows.Next() {
comment := &domain.ClipComment{}
err := rows.Scan(
&comment.ID,
&comment.ClipID,
&comment.AuthorID,
&comment.Content,
&comment.CreatedAt,
&comment.UpdatedAt,
)
if err != nil {
return nil, 0, fmt.Errorf("failed to scan comment: %w", err)
}
comments = append(comments, comment)
}
if err = rows.Err(); err != nil {
return nil, 0, fmt.Errorf("rows error: %w", err)
}
return comments, totalCount, nil
}
func (r *commentRepository) Update(ctx context.Context, comment *domain.ClipComment) error {
query := `
UPDATE clip_comments
SET content = $1, updated_at = $2
WHERE id = $3 AND deleted_at IS NULL
`
result, err := r.db.ExecContext(ctx, query,
comment.Content,
time.Now(),
comment.ID,
)
if err != nil {
return fmt.Errorf("failed to update comment: %w", err)
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return fmt.Errorf("failed to get rows affected: %w", err)
}
if rowsAffected == 0 {
return ErrCommentNotFound
}
comment.UpdatedAt = time.Now()
return nil
}
func (r *commentRepository) Delete(ctx context.Context, id int) error {
query := `
UPDATE clip_comments
SET deleted_at = $1
WHERE id = $2 AND deleted_at IS NULL
`
result, err := r.db.ExecContext(ctx, query, time.Now(), id)
if err != nil {
return fmt.Errorf("failed to delete comment: %w", err)
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return fmt.Errorf("failed to get rows affected: %w", err)
}
if rowsAffected == 0 {
return ErrCommentNotFound
}
return nil
}
func (r *commentRepository) DeleteByClipID(ctx context.Context, clipID int) error {
query := `
UPDATE clip_comments
SET deleted_at = $1
WHERE clip_id = $2 AND deleted_at IS NULL
`
_, err := r.db.ExecContext(ctx, query, time.Now(), clipID)
if err != nil {
return fmt.Errorf("failed to delete comments by clip ID: %w", err)
}
return nil
}
func (r *commentRepository) DeleteByAuthorID(ctx context.Context, authorID int) error {
query := `
UPDATE clip_comments
SET deleted_at = $1
WHERE author_id = $2 AND deleted_at IS NULL
`
_, err := r.db.ExecContext(ctx, query, time.Now(), authorID)
if err != nil {
return fmt.Errorf("failed to delete comments by author ID: %w", err)
}
return nil
}