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", "DeletedAt", "SourceId", "Tags", "Title", "Url", "PubDate", "IsVideo", "ThumbnailUrl", "Description", "AuthorName", "AuthorImageUrl") queryBuilder.Values(dt, dt, timeZero, 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 time.Time 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, DeletedAt: deletedAt, SourceID: sourceId, Tags: tags, Title: title, Url: url, PubDate: pubDate, IsVideo: isVideo, Thumbnail: thumbnail, Description: description, AuthorName: authorName, AuthorImageUrl: authorImageUrl, } items = append(items, item) } return items }