Add more filters for API call /entries

New filters:

- before (unix timestamp)
- before_entry_id
- after
- after_entry_id
- starred (boolean)
This commit is contained in:
Frédéric Guillot 2018-06-09 19:13:41 -07:00
parent c5373ff2bf
commit 36dab8b518
7 changed files with 99 additions and 17 deletions

2
Gopkg.lock generated
View File

@ -45,7 +45,7 @@
branch = "master"
name = "github.com/miniflux/miniflux-go"
packages = ["."]
revision = "8863d558cbf1f20beeb640328829205971f1a632"
revision = "ec30672607d4dd72470f4c156bd36ba07d9a9a2a"
[[projects]]
name = "github.com/tdewolff/minify"

View File

@ -7,11 +7,13 @@ package api
import (
"errors"
"net/http"
"time"
"github.com/miniflux/miniflux/http/context"
"github.com/miniflux/miniflux/http/request"
"github.com/miniflux/miniflux/http/response/json"
"github.com/miniflux/miniflux/model"
"github.com/miniflux/miniflux/storage"
)
// GetFeedEntry is the API handler to get a single feed entry.
@ -116,6 +118,7 @@ func (c *Controller) GetFeedEntries(w http.ResponseWriter, r *http.Request) {
builder.WithDirection(direction)
builder.WithOffset(offset)
builder.WithLimit(limit)
configureFilters(builder, r)
entries, err := builder.GetEntries()
if err != nil {
@ -167,6 +170,7 @@ func (c *Controller) GetEntries(w http.ResponseWriter, r *http.Request) {
builder.WithDirection(direction)
builder.WithOffset(offset)
builder.WithLimit(limit)
configureFilters(builder, r)
entries, err := builder.GetEntries()
if err != nil {
@ -219,3 +223,29 @@ func (c *Controller) ToggleBookmark(w http.ResponseWriter, r *http.Request) {
json.NoContent(w)
}
func configureFilters(builder *storage.EntryQueryBuilder, r *http.Request) {
beforeEntryID := request.QueryInt64Param(r, "before_entry_id", 0)
if beforeEntryID != 0 {
builder.BeforeEntryID(beforeEntryID)
}
afterEntryID := request.QueryInt64Param(r, "after_entry_id", 0)
if afterEntryID != 0 {
builder.AfterEntryID(afterEntryID)
}
beforeTimestamp := request.QueryInt64Param(r, "before", 0)
if beforeTimestamp != 0 {
builder.BeforeDate(time.Unix(beforeTimestamp, 0))
}
afterTimestamp := request.QueryInt64Param(r, "after", 0)
if afterTimestamp != 0 {
builder.AfterDate(time.Unix(afterTimestamp, 0))
}
if request.HasQueryParam(r, "starred") {
builder.WithStarred()
}
}

View File

@ -490,7 +490,7 @@ func (c *Controller) handleWriteItems(w http.ResponseWriter, r *http.Request) {
userID := ctx.UserID()
logger.Debug("[Fever] Receiving mark=item call for userID=%d", userID)
entryID := request.FormIntValue(r, "id")
entryID := request.FormInt64Value(r, "id")
if entryID <= 0 {
return
}
@ -548,7 +548,7 @@ func (c *Controller) handleWriteFeeds(w http.ResponseWriter, r *http.Request) {
userID := ctx.UserID()
logger.Debug("[Fever] Receiving mark=feed call for userID=%d", userID)
feedID := request.FormIntValue(r, "id")
feedID := request.FormInt64Value(r, "id")
if feedID <= 0 {
return
}
@ -557,7 +557,7 @@ func (c *Controller) handleWriteFeeds(w http.ResponseWriter, r *http.Request) {
builder.WithStatus(model.EntryStatusUnread)
builder.WithFeedID(feedID)
before := request.FormIntValue(r, "before")
before := request.FormInt64Value(r, "before")
if before > 0 {
t := time.Unix(before, 0)
builder.BeforeDate(t)
@ -589,7 +589,7 @@ func (c *Controller) handleWriteGroups(w http.ResponseWriter, r *http.Request) {
userID := ctx.UserID()
logger.Debug("[Fever] Receiving mark=group call for userID=%d", userID)
groupID := request.FormIntValue(r, "id")
groupID := request.FormInt64Value(r, "id")
if groupID < 0 {
return
}
@ -598,7 +598,7 @@ func (c *Controller) handleWriteGroups(w http.ResponseWriter, r *http.Request) {
builder.WithStatus(model.EntryStatusUnread)
builder.WithCategoryID(groupID)
before := request.FormIntValue(r, "before")
before := request.FormInt64Value(r, "before")
if before > 0 {
t := time.Unix(before, 0)
builder.BeforeDate(t)

View File

@ -24,11 +24,15 @@ func Cookie(r *http.Request, name string) string {
return cookie.Value
}
// FormIntValue returns a form value as integer.
func FormIntValue(r *http.Request, param string) int64 {
// FormInt64Value returns a form value as integer.
func FormInt64Value(r *http.Request, param string) int64 {
value := r.FormValue(param)
integer, _ := strconv.Atoi(value)
return int64(integer)
integer, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return 0
}
return integer
}
// IntParam returns an URL route parameter as integer.
@ -67,12 +71,17 @@ func QueryParam(r *http.Request, param, defaultValue string) string {
// QueryIntParam returns a querystring parameter as integer.
func QueryIntParam(r *http.Request, param string, defaultValue int) int {
return int(QueryInt64Param(r, param, int64(defaultValue)))
}
// QueryInt64Param returns a querystring parameter as int64.
func QueryInt64Param(r *http.Request, param string, defaultValue int64) int64 {
value := r.URL.Query().Get(param)
if value == "" {
return defaultValue
}
val, err := strconv.Atoi(value)
val, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return defaultValue
}

View File

@ -986,7 +986,16 @@ func TestGetAllFeedEntries(t *testing.T) {
}
if allResults.Entries[0].ID == filteredResults.Entries[0].ID {
t.Fatal(`Filtered entries should be different than previous result`)
t.Fatal(`Filtered entries should be different than previous results`)
}
filteredResultsByEntryID, err := client.FeedEntries(feedID, &miniflux.Filter{BeforeEntryID: allResults.Entries[0].ID})
if err != nil {
t.Fatal(err)
}
if filteredResultsByEntryID.Entries[0].ID == allResults.Entries[0].ID {
t.Fatal(`The first entry should filtered out`)
}
}
@ -1035,6 +1044,15 @@ func TestGetAllEntries(t *testing.T) {
if resultWithDifferentSorting.Entries[0].Title == resultWithoutSorting.Entries[0].Title {
t.Fatalf(`The items should be sorted differently "%v" vs "%v"`, resultWithDifferentSorting.Entries[0].Title, resultWithoutSorting.Entries[0].Title)
}
resultWithStarredEntries, err := client.Entries(&miniflux.Filter{Starred: true})
if err != nil {
t.Fatal(err)
}
if resultWithStarredEntries.Total != 0 {
t.Fatalf(`We are not supposed to have starred entries yet`)
}
}
func TestInvalidFilters(t *testing.T) {

View File

@ -477,6 +477,26 @@ func buildFilterQueryString(path string, filter *Filter) string {
values.Set("offset", strconv.Itoa(filter.Offset))
}
if filter.After > 0 {
values.Set("after", strconv.FormatInt(filter.After, 10))
}
if filter.AfterEntryID > 0 {
values.Set("after_entry_id", strconv.FormatInt(filter.AfterEntryID, 10))
}
if filter.Before > 0 {
values.Set("before", strconv.FormatInt(filter.Before, 10))
}
if filter.BeforeEntryID > 0 {
values.Set("before_entry_id", strconv.FormatInt(filter.BeforeEntryID, 10))
}
if filter.Starred {
values.Set("starred", "1")
}
path = fmt.Sprintf("%s?%s", path, values.Encode())
}

View File

@ -127,11 +127,16 @@ type Enclosures []*Enclosure
// Filter is used to filter entries.
type Filter struct {
Status string
Offset int
Limit int
Order string
Direction string
Status string
Offset int
Limit int
Order string
Direction string
Starred bool
Before int64
After int64
BeforeEntryID int64
AfterEntryID int64
}
// EntryResultSet represents the response when fetching entries.