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("/discover", handler.discoverSubscriptions).Methods(http.MethodPost)
|
||||||
sr.HandleFunc("/feeds", handler.createFeed).Methods(http.MethodPost)
|
sr.HandleFunc("/feeds", handler.createFeed).Methods(http.MethodPost)
|
||||||
sr.HandleFunc("/feeds", handler.getFeeds).Methods(http.MethodGet)
|
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/refresh", handler.refreshAllFeeds).Methods(http.MethodPut)
|
||||||
sr.HandleFunc("/feeds/{feedID}/refresh", handler.refreshFeed).Methods(http.MethodPut)
|
sr.HandleFunc("/feeds/{feedID}/refresh", handler.refreshFeed).Methods(http.MethodPut)
|
||||||
sr.HandleFunc("/feeds/{feedID}", handler.getFeed).Methods(http.MethodGet)
|
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)
|
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) {
|
func (h *handler) getFeed(w http.ResponseWriter, r *http.Request) {
|
||||||
feedID := request.RouteInt64Param(r, "feedID")
|
feedID := request.RouteInt64Param(r, "feedID")
|
||||||
feed, err := h.store.FeedByID(request.UserID(r), feedID)
|
feed, err := h.store.FeedByID(request.UserID(r), feedID)
|
||||||
|
|
|
@ -502,6 +502,23 @@ func (c *Client) ToggleBookmark(entryID int64) error {
|
||||||
return err
|
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 {
|
func buildFilterQueryString(path string, filter *Filter) string {
|
||||||
if filter != nil {
|
if filter != nil {
|
||||||
values := url.Values{}
|
values := url.Values{}
|
||||||
|
|
|
@ -180,6 +180,11 @@ type FeedIcon struct {
|
||||||
Data string `json:"data"`
|
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.
|
// Feeds represents a list of feeds.
|
||||||
type Feeds []*Feed
|
type Feeds []*Feed
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,11 @@ type Feed struct {
|
||||||
ReadCount int `json:"-"`
|
ReadCount int `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FeedCounters struct {
|
||||||
|
ReadCounters map[int64]int `json:"reads"`
|
||||||
|
UnreadCounters map[int64]int `json:"unreads"`
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Feed) String() string {
|
func (f *Feed) String() string {
|
||||||
return fmt.Sprintf("ID=%d, UserID=%d, FeedURL=%s, SiteURL=%s, Title=%s, Category={%s}",
|
return fmt.Sprintf("ID=%d, UserID=%d, FeedURL=%s, SiteURL=%s, Title=%s, Category={%s}",
|
||||||
f.ID,
|
f.ID,
|
||||||
|
|
|
@ -158,6 +158,14 @@ func (s *Storage) FeedsWithCounters(userID int64) (model.Feeds, error) {
|
||||||
return getFeedsSorted(builder)
|
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.
|
// 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) {
|
func (s *Storage) FeedsByCategoryWithCounters(userID, categoryID int64) (model.Feeds, error) {
|
||||||
builder := NewFeedQueryBuilder(s, userID)
|
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) {
|
func TestDeleteFeed(t *testing.T) {
|
||||||
client := createClient(t)
|
client := createClient(t)
|
||||||
feed, _ := createFeed(t, client)
|
feed, _ := createFeed(t, client)
|
||||||
|
|
Loading…
Add table
Reference in a new issue