mirror of
https://github.com/miniflux/v2.git
synced 2025-06-27 16:36:00 +00:00
feat: add date-based entry filtering rules
This commit is contained in:
parent
7346d751cc
commit
bca9bea676
3 changed files with 57 additions and 4 deletions
|
@ -10,6 +10,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/tdewolff/minify/v2"
|
||||||
|
"github.com/tdewolff/minify/v2/html"
|
||||||
|
|
||||||
"miniflux.app/v2/internal/config"
|
"miniflux.app/v2/internal/config"
|
||||||
"miniflux.app/v2/internal/metric"
|
"miniflux.app/v2/internal/metric"
|
||||||
"miniflux.app/v2/internal/model"
|
"miniflux.app/v2/internal/model"
|
||||||
|
@ -20,9 +23,6 @@ import (
|
||||||
"miniflux.app/v2/internal/reader/scraper"
|
"miniflux.app/v2/internal/reader/scraper"
|
||||||
"miniflux.app/v2/internal/reader/urlcleaner"
|
"miniflux.app/v2/internal/reader/urlcleaner"
|
||||||
"miniflux.app/v2/internal/storage"
|
"miniflux.app/v2/internal/storage"
|
||||||
|
|
||||||
"github.com/tdewolff/minify/v2"
|
|
||||||
"github.com/tdewolff/minify/v2/html"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var customReplaceRuleRegex = regexp.MustCompile(`rewrite\("([^"]+)"\|"([^"]+)"\)`)
|
var customReplaceRuleRegex = regexp.MustCompile(`rewrite\("([^"]+)"\|"([^"]+)"\)`)
|
||||||
|
@ -141,6 +141,9 @@ func isBlockedEntry(feed *model.Feed, entry *model.Entry, user *model.User) bool
|
||||||
|
|
||||||
var match bool
|
var match bool
|
||||||
switch parts[0] {
|
switch parts[0] {
|
||||||
|
case "EntryDate":
|
||||||
|
datePattern := parts[1]
|
||||||
|
match = isDateMatchingPattern(entry.Date, datePattern)
|
||||||
case "EntryTitle":
|
case "EntryTitle":
|
||||||
match, _ = regexp.MatchString(parts[1], entry.Title)
|
match, _ = regexp.MatchString(parts[1], entry.Title)
|
||||||
case "EntryURL":
|
case "EntryURL":
|
||||||
|
@ -211,6 +214,9 @@ func isAllowedEntry(feed *model.Feed, entry *model.Entry, user *model.User) bool
|
||||||
|
|
||||||
var match bool
|
var match bool
|
||||||
switch parts[0] {
|
switch parts[0] {
|
||||||
|
case "EntryDate":
|
||||||
|
datePattern := parts[1]
|
||||||
|
match = isDateMatchingPattern(entry.Date, datePattern)
|
||||||
case "EntryTitle":
|
case "EntryTitle":
|
||||||
match, _ = regexp.MatchString(parts[1], entry.Title)
|
match, _ = regexp.MatchString(parts[1], entry.Title)
|
||||||
case "EntryURL":
|
case "EntryURL":
|
||||||
|
@ -462,3 +468,44 @@ func minifyEntryContent(entryContent string) string {
|
||||||
|
|
||||||
return entryContent
|
return entryContent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isDateMatchingPattern(entryDate time.Time, pattern string) bool {
|
||||||
|
if pattern == "future" {
|
||||||
|
return entryDate.After(time.Now())
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.SplitN(pattern, ":", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
operator := parts[0]
|
||||||
|
dateStr := parts[1]
|
||||||
|
|
||||||
|
switch operator {
|
||||||
|
case "before":
|
||||||
|
targetDate, err := time.Parse("2006-01-02", dateStr)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return entryDate.Before(targetDate)
|
||||||
|
case "after":
|
||||||
|
targetDate, err := time.Parse("2006-01-02", dateStr)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return entryDate.After(targetDate)
|
||||||
|
case "between":
|
||||||
|
dates := strings.Split(dateStr, ",")
|
||||||
|
if len(dates) != 2 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
startDate, err1 := time.Parse("2006-01-02", dates[0])
|
||||||
|
endDate, err2 := time.Parse("2006-01-02", dates[1])
|
||||||
|
if err1 != nil || err2 != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return entryDate.After(startDate) && entryDate.Before(endDate)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -75,6 +75,12 @@ func TestAllowEntries(t *testing.T) {
|
||||||
{&model.Feed{ID: 1, BlocklistRules: ""}, &model.Entry{Author: "Example", Tags: []string{"example", "something else"}}, &model.User{KeepFilterEntryRules: "EntryAuthor=(?i)example\nEntryTag=(?i)Test"}, true},
|
{&model.Feed{ID: 1, BlocklistRules: ""}, &model.Entry{Author: "Example", Tags: []string{"example", "something else"}}, &model.User{KeepFilterEntryRules: "EntryAuthor=(?i)example\nEntryTag=(?i)Test"}, true},
|
||||||
{&model.Feed{ID: 1, BlocklistRules: ""}, &model.Entry{Author: "Different", Tags: []string{"example", "something else"}}, &model.User{KeepFilterEntryRules: "EntryAuthor=(?i)example\nEntryTag=(?i)example"}, true},
|
{&model.Feed{ID: 1, BlocklistRules: ""}, &model.Entry{Author: "Different", Tags: []string{"example", "something else"}}, &model.User{KeepFilterEntryRules: "EntryAuthor=(?i)example\nEntryTag=(?i)example"}, true},
|
||||||
{&model.Feed{ID: 1, BlocklistRules: ""}, &model.Entry{Author: "Different", Tags: []string{"example", "something else"}}, &model.User{KeepFilterEntryRules: "EntryAuthor=(?i)example\nEntryTag=(?i)Test"}, false},
|
{&model.Feed{ID: 1, BlocklistRules: ""}, &model.Entry{Author: "Different", Tags: []string{"example", "something else"}}, &model.User{KeepFilterEntryRules: "EntryAuthor=(?i)example\nEntryTag=(?i)Test"}, false},
|
||||||
|
{&model.Feed{ID: 1, BlocklistRules: ""}, &model.Entry{Date: time.Now().Add(24 * time.Hour)}, &model.User{KeepFilterEntryRules: "EntryDate=future"}, true},
|
||||||
|
{&model.Feed{ID: 1, BlocklistRules: ""}, &model.Entry{Date: time.Now().Add(-24 * time.Hour)}, &model.User{KeepFilterEntryRules: "EntryDate=future"}, false},
|
||||||
|
{&model.Feed{ID: 1, BlocklistRules: ""}, &model.Entry{Date: time.Date(2024, 3, 14, 0, 0, 0, 0, time.UTC)}, &model.User{KeepFilterEntryRules: "EntryDate=before:2024-03-15"}, true},
|
||||||
|
{&model.Feed{ID: 1, BlocklistRules: ""}, &model.Entry{Date: time.Date(2024, 3, 16, 0, 0, 0, 0, time.UTC)}, &model.User{KeepFilterEntryRules: "EntryDate=after:2024-03-15"}, true},
|
||||||
|
{&model.Feed{ID: 1, BlocklistRules: ""}, &model.Entry{Date: time.Date(2024, 3, 10, 0, 0, 0, 0, time.UTC)}, &model.User{KeepFilterEntryRules: "EntryDate=between:2024-03-01,2024-03-15"}, true},
|
||||||
|
{&model.Feed{ID: 1, BlocklistRules: ""}, &model.Entry{Date: time.Date(2024, 2, 28, 0, 0, 0, 0, time.UTC)}, &model.User{KeepFilterEntryRules: "EntryDate=between:2024-03-01,2024-03-15"}, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range scenarios {
|
for _, tc := range scenarios {
|
||||||
|
|
|
@ -219,7 +219,7 @@ func validateMediaPlaybackRate(mediaPlaybackRate float64) *locale.LocalizedError
|
||||||
|
|
||||||
func isValidFilterRules(filterEntryRules string, filterType string) *locale.LocalizedError {
|
func isValidFilterRules(filterEntryRules string, filterType string) *locale.LocalizedError {
|
||||||
// Valid Format: FieldName=RegEx\nFieldName=RegEx...
|
// Valid Format: FieldName=RegEx\nFieldName=RegEx...
|
||||||
fieldNames := []string{"EntryTitle", "EntryURL", "EntryCommentsURL", "EntryContent", "EntryAuthor", "EntryTag"}
|
fieldNames := []string{"EntryTitle", "EntryURL", "EntryCommentsURL", "EntryContent", "EntryAuthor", "EntryTag", "EntryDate"}
|
||||||
|
|
||||||
rules := strings.Split(filterEntryRules, "\n")
|
rules := strings.Split(filterEntryRules, "\n")
|
||||||
for i, rule := range rules {
|
for i, rule := range rules {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue