Răsfoiți Sursa

Add enclosures to /v1/entries API endpoint

Frédéric Guillot 2 ani în urmă
părinte
comite
6dd090a848
3 a modificat fișierele cu 31 adăugiri și 11 ștergeri
  1. 1 0
      internal/api/entry.go
  2. 4 0
      internal/model/entry.go
  3. 26 11
      internal/storage/entry_query_builder.go

+ 1 - 0
internal/api/entry.go

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

+ 4 - 0
internal/model/entry.go

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

+ 26 - 11
internal/storage/entry_query_builder.go

@@ -23,6 +23,13 @@ type EntryQueryBuilder struct {
 	sortExpressions []string
 	limit           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.
@@ -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)
 	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
@@ -270,11 +277,13 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
 			e.created_at,
 			e.changed_at,
 			e.tags,
+			(SELECT true FROM enclosures WHERE entry_id=e.id LIMIT 1) as has_enclosure,
 			f.title as feed_title,
 			f.feed_url,
 			f.site_url,
 			f.checked_at,
-			f.category_id, c.title as category_title,
+			f.category_id,
+			c.title as category_title,
 			f.scraper_rules,
 			f.rewrite_rules,
 			f.crawler,
@@ -303,19 +312,17 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
 
 	rows, err := e.store.db.Query(query, e.args...)
 	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()
 
 	entries := make(model.Entries, 0)
 	for rows.Next() {
-		var entry model.Entry
 		var iconID sql.NullInt64
 		var tz string
+		var hasEnclosure sql.NullBool
 
-		entry.Feed = &model.Feed{}
-		entry.Feed.Category = &model.Category{}
-		entry.Feed.Icon = &model.FeedIcon{}
+		entry := model.NewEntry()
 
 		err := rows.Scan(
 			&entry.ID,
@@ -335,6 +342,7 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
 			&entry.CreatedAt,
 			&entry.ChangedAt,
 			pq.Array(&entry.Tags),
+			&hasEnclosure,
 			&entry.Feed.Title,
 			&entry.Feed.FeedURL,
 			&entry.Feed.SiteURL,
@@ -353,7 +361,14 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
 		)
 
 		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 {
@@ -372,7 +387,7 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
 		entry.Feed.UserID = entry.UserID
 		entry.Feed.Icon.FeedID = entry.FeedID
 		entry.Feed.Category.UserID = entry.UserID
-		entries = append(entries, &entry)
+		entries = append(entries, entry)
 	}
 
 	return entries, nil
@@ -387,7 +402,7 @@ func (e *EntryQueryBuilder) GetEntryIDs() ([]int64, error) {
 
 	rows, err := e.store.db.Query(query, e.args...)
 	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()
 
@@ -397,7 +412,7 @@ func (e *EntryQueryBuilder) GetEntryIDs() ([]int64, error) {
 
 		err := rows.Scan(&entryID)
 		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)