newsbot-api/internal/repository/article.go

234 lines
5.5 KiB
Go

package repository
import (
"database/sql"
"errors"
"fmt"
"time"
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
"github.com/huandu/go-sqlbuilder"
)
const (
ArticleOrderByPublishDateDesc = "pubDate desc"
ArticleOrderByPublishDatAsc = "pubDate asc"
)
type ArticleRepository struct {
conn *sql.DB
defaultLimit int
defaultOffset int
}
func NewArticleRepository(conn *sql.DB) ArticleRepository {
return ArticleRepository{
conn: conn,
defaultLimit: 50,
defaultOffset: 50,
}
}
func (ar ArticleRepository) GetById(id int64) (domain.ArticleEntity, error) {
builder := sqlbuilder.NewSelectBuilder()
builder.Select("*")
builder.From("articles").Where(
builder.E("id", id),
)
builder.Limit(1)
query, args := builder.Build()
rows, err := ar.conn.Query(query, args...)
if err != nil {
return domain.ArticleEntity{}, err
}
data := ar.processRows(rows)
if len(data) == 0 {
return domain.ArticleEntity{}, errors.New(ErrUserNotFound)
}
return data[0], nil
}
func (ar ArticleRepository) GetByUrl(url string) (domain.ArticleEntity, error) {
builder := sqlbuilder.NewSelectBuilder()
builder.Select("*")
builder.From("articles").Where(
builder.E("url", url),
)
builder.Limit(1)
query, args := builder.Build()
rows, err := ar.conn.Query(query, args...)
if err != nil {
return domain.ArticleEntity{}, err
}
data := ar.processRows(rows)
if len(data) == 0 {
return domain.ArticleEntity{}, errors.New(ErrUserNotFound)
}
return data[0], nil
}
func (ar ArticleRepository) ListTop(limit int) ([]domain.ArticleEntity, error) {
builder := sqlbuilder.NewSelectBuilder()
builder.Select("*")
builder.From("articles")
builder.Limit(limit)
query, args := builder.Build()
rows, err := ar.conn.Query(query, args...)
if err != nil {
return []domain.ArticleEntity{}, err
}
data := ar.processRows(rows)
if len(data) == 0 {
return []domain.ArticleEntity{}, errors.New(ErrUserNotFound)
}
return data, nil
}
func (ar ArticleRepository) ListByPage(page, limit int) ([]domain.ArticleEntity, error) {
builder := sqlbuilder.NewSelectBuilder()
builder.Select("*")
builder.From("articles")
builder.OrderBy("pubdate desc")
builder.Offset(page * limit)
builder.Limit(limit)
query, args := builder.Build()
rows, err := ar.conn.Query(query, args...)
if err != nil {
return []domain.ArticleEntity{}, err
}
data := ar.processRows(rows)
if len(data) == 0 {
return []domain.ArticleEntity{}, errors.New(ErrUserNotFound)
}
return data, nil
}
func (ar ArticleRepository) ListByPublishDate(page, limit int, orderBy string) ([]domain.ArticleEntity, error) {
builder := sqlbuilder.NewSelectBuilder()
builder.Select("*")
builder.From("articles")
if orderBy != "" {
builder.OrderBy(orderBy)
}
builder.Offset(page * limit)
builder.Limit(limit)
query, args := builder.Build()
rows, err := ar.conn.Query(query, args...)
if err != nil {
return []domain.ArticleEntity{}, err
}
data := ar.processRows(rows)
if len(data) == 0 {
return []domain.ArticleEntity{}, errors.New(ErrUserNotFound)
}
return data, nil
}
func (ar ArticleRepository) ListBySource(page, limit int, orderBy string) ([]domain.ArticleEntity, error) {
builder := sqlbuilder.NewSelectBuilder()
builder.Select("*")
builder.From("articles")
builder.JoinWithOption("InnerJoin", "sources", "articles.sourceId=sources.Id")
if orderBy != "" {
builder.OrderBy(orderBy)
}
builder.Offset(50)
builder.Limit(page * limit)
query, args := builder.Build()
rows, err := ar.conn.Query(query, args...)
if err != nil {
return []domain.ArticleEntity{}, err
}
data := ar.processRows(rows)
if len(data) == 0 {
return []domain.ArticleEntity{}, errors.New(ErrUserNotFound)
}
return data, nil
}
func (ar ArticleRepository) Create(sourceId int64, tags, title, url, thumbnailUrl, description, authorName, authorImageUrl string, pubDate time.Time, isVideo bool) (int64, error) {
dt := time.Now()
queryBuilder := sqlbuilder.NewInsertBuilder()
queryBuilder.InsertInto("articles")
queryBuilder.Cols("UpdatedAt", "CreatedAt", "SourceId", "Tags", "Title", "Url", "PubDate", "IsVideo", "ThumbnailUrl", "Description", "AuthorName", "AuthorImageUrl")
queryBuilder.Values(dt, dt, sourceId, tags, title, url, pubDate, isVideo, thumbnailUrl, description, authorName, authorImageUrl)
query, args := queryBuilder.Build()
_, err := ar.conn.Exec(query, args...)
if err != nil {
return 0, err
}
return 1, nil
}
func (ur ArticleRepository) processRows(rows *sql.Rows) []domain.ArticleEntity {
items := []domain.ArticleEntity{}
for rows.Next() {
var id int64
var createdAt time.Time
var updatedAt time.Time
var deletedAt sql.NullTime
var sourceId int64
var tags string
var title string
var url string
var pubDate time.Time
var isVideo bool
var thumbnail string
var description string
var authorName string
var authorImageUrl string
err := rows.Scan(
&id, &createdAt, &updatedAt,
&deletedAt, &sourceId, &tags,
&title, &url, &pubDate,
&isVideo, &thumbnail, &description,
&authorName, &authorImageUrl)
if err != nil {
fmt.Println(err)
}
item := domain.ArticleEntity{
ID: id,
CreatedAt: createdAt,
UpdatedAt: updatedAt,
SourceID: sourceId,
Tags: tags,
Title: title,
Url: url,
PubDate: pubDate,
IsVideo: isVideo,
Thumbnail: thumbnail,
Description: description,
AuthorName: authorName,
AuthorImageUrl: authorImageUrl,
}
if deletedAt.Valid {
item.DeletedAt = deletedAt.Time
}
items = append(items, item)
}
return items
}