Add enclosures to /v1/entries API endpoint

This commit is contained in:
Frédéric Guillot 2023-10-05 20:51:00 -07:00
parent fccc25f7a3
commit 6dd090a848
3 changed files with 31 additions and 11 deletions

View file

@ -147,6 +147,7 @@ func (h *handler) findEntries(w http.ResponseWriter, r *http.Request, feedID int
builder.WithOffset(offset) builder.WithOffset(offset)
builder.WithLimit(limit) builder.WithLimit(limit)
builder.WithTags(tags) builder.WithTags(tags)
builder.WithEnclosures()
configureFilters(builder, r) configureFilters(builder, r)
entries, err := builder.GetEntries() entries, err := builder.GetEntries()

View file

@ -43,6 +43,10 @@ func NewEntry() *Entry {
return &Entry{ return &Entry{
Enclosures: make(EnclosureList, 0), Enclosures: make(EnclosureList, 0),
Tags: make([]string, 0), Tags: make([]string, 0),
Feed: &Feed{
Category: &Category{},
Icon: &FeedIcon{},
},
} }
} }

View file

@ -23,6 +23,13 @@ type EntryQueryBuilder struct {
sortExpressions []string sortExpressions []string
limit int limit int
offset int offset int
fetchEnclosures bool
}
// WithEnclosures fetches enclosures for each entry.
func (e *EntryQueryBuilder) WithEnclosures() *EntryQueryBuilder {
e.fetchEnclosures = true
return e
} }
// WithSearchQuery adds full-text search query to the condition. // WithSearchQuery adds full-text search query to the condition.
@ -223,7 +230,7 @@ func (e *EntryQueryBuilder) CountEntries() (count int, err error) {
err = e.store.db.QueryRow(fmt.Sprintf(query, condition), e.args...).Scan(&count) err = e.store.db.QueryRow(fmt.Sprintf(query, condition), e.args...).Scan(&count)
if err != nil { if err != nil {
return 0, fmt.Errorf("unable to count entries: %v", err) return 0, fmt.Errorf("store: unable to count entries: %v", err)
} }
return count, nil return count, nil
@ -270,11 +277,13 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
e.created_at, e.created_at,
e.changed_at, e.changed_at,
e.tags, e.tags,
(SELECT true FROM enclosures WHERE entry_id=e.id LIMIT 1) as has_enclosure,
f.title as feed_title, f.title as feed_title,
f.feed_url, f.feed_url,
f.site_url, f.site_url,
f.checked_at, f.checked_at,
f.category_id, c.title as category_title, f.category_id,
c.title as category_title,
f.scraper_rules, f.scraper_rules,
f.rewrite_rules, f.rewrite_rules,
f.crawler, f.crawler,
@ -303,19 +312,17 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
rows, err := e.store.db.Query(query, e.args...) rows, err := e.store.db.Query(query, e.args...)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to get entries: %v", err) return nil, fmt.Errorf("store: unable to get entries: %v", err)
} }
defer rows.Close() defer rows.Close()
entries := make(model.Entries, 0) entries := make(model.Entries, 0)
for rows.Next() { for rows.Next() {
var entry model.Entry
var iconID sql.NullInt64 var iconID sql.NullInt64
var tz string var tz string
var hasEnclosure sql.NullBool
entry.Feed = &model.Feed{} entry := model.NewEntry()
entry.Feed.Category = &model.Category{}
entry.Feed.Icon = &model.FeedIcon{}
err := rows.Scan( err := rows.Scan(
&entry.ID, &entry.ID,
@ -335,6 +342,7 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
&entry.CreatedAt, &entry.CreatedAt,
&entry.ChangedAt, &entry.ChangedAt,
pq.Array(&entry.Tags), pq.Array(&entry.Tags),
&hasEnclosure,
&entry.Feed.Title, &entry.Feed.Title,
&entry.Feed.FeedURL, &entry.Feed.FeedURL,
&entry.Feed.SiteURL, &entry.Feed.SiteURL,
@ -353,7 +361,14 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to fetch entry row: %v", err) return nil, fmt.Errorf("store: unable to fetch entry row: %v", err)
}
if hasEnclosure.Valid && hasEnclosure.Bool && e.fetchEnclosures {
entry.Enclosures, err = e.store.GetEnclosures(entry.ID)
if err != nil {
return nil, fmt.Errorf("store: unable to fetch enclosures for entry #%d: %w", entry.ID, err)
}
} }
if iconID.Valid { if iconID.Valid {
@ -372,7 +387,7 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
entry.Feed.UserID = entry.UserID entry.Feed.UserID = entry.UserID
entry.Feed.Icon.FeedID = entry.FeedID entry.Feed.Icon.FeedID = entry.FeedID
entry.Feed.Category.UserID = entry.UserID entry.Feed.Category.UserID = entry.UserID
entries = append(entries, &entry) entries = append(entries, entry)
} }
return entries, nil return entries, nil
@ -387,7 +402,7 @@ func (e *EntryQueryBuilder) GetEntryIDs() ([]int64, error) {
rows, err := e.store.db.Query(query, e.args...) rows, err := e.store.db.Query(query, e.args...)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to get entries: %v", err) return nil, fmt.Errorf("store: unable to get entries: %v", err)
} }
defer rows.Close() defer rows.Close()
@ -397,7 +412,7 @@ func (e *EntryQueryBuilder) GetEntryIDs() ([]int64, error) {
err := rows.Scan(&entryID) err := rows.Scan(&entryID)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to fetch entry row: %v", err) return nil, fmt.Errorf("store: unable to fetch entry row: %v", err)
} }
entryIDs = append(entryIDs, entryID) entryIDs = append(entryIDs, entryID)