2024-04-27 07:44:41 -07:00
|
|
|
package repository
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"git.jamestombleson.com/jtom38/newsbot-api/internal/domain"
|
|
|
|
"github.com/huandu/go-sqlbuilder"
|
|
|
|
)
|
|
|
|
|
2024-04-27 13:11:03 -07:00
|
|
|
const (
|
|
|
|
ArticleOrderByPublishDateDesc = "pubDate desc"
|
|
|
|
ArticleOrderByPublishDatAsc = "pubDate asc"
|
|
|
|
)
|
|
|
|
|
2024-04-27 07:44:41 -07:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2024-04-27 13:11:03 -07:00
|
|
|
func (ar ArticleRepository) ListTop(limit int) ([]domain.ArticleEntity, error) {
|
2024-04-27 07:44:41 -07:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2024-04-27 13:11:03 -07:00
|
|
|
func (ar ArticleRepository) ListByPublishDate(page, limit int, orderBy string) ([]domain.ArticleEntity, error) {
|
2024-04-27 07:44:41 -07:00
|
|
|
builder := sqlbuilder.NewSelectBuilder()
|
|
|
|
builder.Select("*")
|
|
|
|
builder.From("articles")
|
2024-04-27 13:11:03 -07:00
|
|
|
if orderBy != "" {
|
|
|
|
builder.OrderBy(orderBy)
|
|
|
|
}
|
|
|
|
builder.Offset(page * limit)
|
2024-04-27 07:44:41 -07:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2024-04-27 13:11:03 -07:00
|
|
|
func (ar ArticleRepository) ListBySource(page, limit int, orderBy string) ([]domain.ArticleEntity, error) {
|
2024-04-27 07:44:41 -07:00
|
|
|
builder := sqlbuilder.NewSelectBuilder()
|
|
|
|
builder.Select("*")
|
|
|
|
builder.From("articles")
|
|
|
|
builder.JoinWithOption("InnerJoin", "sources", "articles.sourceId=sources.Id")
|
2024-04-27 13:11:03 -07:00
|
|
|
if orderBy != "" {
|
|
|
|
builder.OrderBy(orderBy)
|
|
|
|
}
|
2024-04-27 07:44:41 -07:00
|
|
|
builder.Offset(50)
|
2024-04-27 13:11:03 -07:00
|
|
|
builder.Limit(page * limit)
|
2024-04-27 07:44:41 -07:00
|
|
|
|
|
|
|
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")
|
2024-04-28 10:02:57 -07:00
|
|
|
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)
|
2024-04-27 07:44:41 -07:00
|
|
|
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
|
2024-04-28 10:02:57 -07:00
|
|
|
var deletedAt time.Time
|
2024-04-27 07:44:41 -07:00
|
|
|
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,
|
2024-04-28 10:02:57 -07:00
|
|
|
DeletedAt: deletedAt,
|
2024-04-27 07:44:41 -07:00
|
|
|
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
|
|
|
|
}
|