Add API endpoint to fetch unread and read counters

This commit is contained in:
Pascal Noisette 2022-05-21 20:44:56 +02:00 committed by GitHub
parent 953c1742e0
commit d118aa8649
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 77 additions and 0 deletions

View file

@ -47,6 +47,7 @@ func Serve(router *mux.Router, store *storage.Storage, pool *worker.Pool) {
sr.HandleFunc("/discover", handler.discoverSubscriptions).Methods(http.MethodPost)
sr.HandleFunc("/feeds", handler.createFeed).Methods(http.MethodPost)
sr.HandleFunc("/feeds", handler.getFeeds).Methods(http.MethodGet)
sr.HandleFunc("/feeds/counters", handler.fetchCounters).Methods(http.MethodGet)
sr.HandleFunc("/feeds/refresh", handler.refreshAllFeeds).Methods(http.MethodPut)
sr.HandleFunc("/feeds/{feedID}/refresh", handler.refreshFeed).Methods(http.MethodPut)
sr.HandleFunc("/feeds/{feedID}", handler.getFeed).Methods(http.MethodGet)

View file

@ -170,6 +170,16 @@ func (h *handler) getFeeds(w http.ResponseWriter, r *http.Request) {
json.OK(w, r, feeds)
}
func (h *handler) fetchCounters(w http.ResponseWriter, r *http.Request) {
counters, err := h.store.FetchCounters(request.UserID(r))
if err != nil {
json.ServerError(w, r, err)
return
}
json.OK(w, r, counters)
}
func (h *handler) getFeed(w http.ResponseWriter, r *http.Request) {
feedID := request.RouteInt64Param(r, "feedID")
feed, err := h.store.FeedByID(request.UserID(r), feedID)

View file

@ -502,6 +502,23 @@ func (c *Client) ToggleBookmark(entryID int64) error {
return err
}
// FetchCounters
func (c *Client) FetchCounters() (*FeedCounters, error) {
body, err := c.request.Get("/v1/feeds/counters")
if err != nil {
return nil, err
}
defer body.Close()
var result FeedCounters
decoder := json.NewDecoder(body)
if err := decoder.Decode(&result); err != nil {
return nil, fmt.Errorf("miniflux: response error (%v)", err)
}
return &result, nil
}
func buildFilterQueryString(path string, filter *Filter) string {
if filter != nil {
values := url.Values{}

View file

@ -180,6 +180,11 @@ type FeedIcon struct {
Data string `json:"data"`
}
type FeedCounters struct {
ReadCounters map[int64]int `json:"reads"`
UnreadCounters map[int64]int `json:"unreads"`
}
// Feeds represents a list of feeds.
type Feeds []*Feed

View file

@ -56,6 +56,11 @@ type Feed struct {
ReadCount int `json:"-"`
}
type FeedCounters struct {
ReadCounters map[int64]int `json:"reads"`
UnreadCounters map[int64]int `json:"unreads"`
}
func (f *Feed) String() string {
return fmt.Sprintf("ID=%d, UserID=%d, FeedURL=%s, SiteURL=%s, Title=%s, Category={%s}",
f.ID,

View file

@ -158,6 +158,14 @@ func (s *Storage) FeedsWithCounters(userID int64) (model.Feeds, error) {
return getFeedsSorted(builder)
}
// Return read and unread count.
func (s *Storage) FetchCounters(userID int64) (model.FeedCounters, error) {
builder := NewFeedQueryBuilder(s, userID)
builder.WithCounters()
reads, unreads, err := builder.fetchFeedCounter()
return model.FeedCounters{ReadCounters: reads, UnreadCounters: unreads}, err
}
// FeedsByCategoryWithCounters returns all feeds of the given user/category with counters of read and unread entries.
func (s *Storage) FeedsByCategoryWithCounters(userID, categoryID int64) (model.Feeds, error) {
builder := NewFeedQueryBuilder(s, userID)

View file

@ -677,6 +677,37 @@ func TestMarkFeedAsRead(t *testing.T) {
}
}
func TestFetchCounters(t *testing.T) {
client := createClient(t)
feed, _ := createFeed(t, client)
results, err := client.FeedEntries(feed.ID, nil)
if err != nil {
t.Fatalf(`Failed to get entries: %v`, err)
}
counters, err := client.FetchCounters()
if err != nil {
t.Fatalf(`Failed to fetch unread count: %v`, err)
}
unreadCounter, exists := counters.UnreadCounters[feed.ID]
if !exists {
unreadCounter = 0
}
unreadExpected := 0
for _, entry := range results.Entries {
if entry.Status == miniflux.EntryStatusUnread {
unreadExpected++
}
}
if unreadExpected != unreadCounter {
t.Errorf(`Expected %d unread entries but %d instead`, unreadExpected, unreadCounter)
}
}
func TestDeleteFeed(t *testing.T) {
client := createClient(t)
feed, _ := createFeed(t, client)