Add API endpoint to fetch unread and read counters
This commit is contained in:
parent
953c1742e0
commit
d118aa8649
7 changed files with 77 additions and 0 deletions
|
@ -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)
|
||||
|
|
10
api/feed.go
10
api/feed.go
|
@ -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)
|
||||
|
|
|
@ -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{}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue