Jelajahi Sumber

refactor(processor): move FilterEntryMaxAgeDays filter to filter package

Frédéric Guillot 9 bulan lalu
induk
melakukan
db49e41acf

+ 25 - 0
internal/reader/filter/filter.go

@@ -11,6 +11,7 @@ import (
 	"strings"
 	"time"
 
+	"miniflux.app/v2/internal/config"
 	"miniflux.app/v2/internal/model"
 )
 
@@ -21,7 +22,31 @@ const (
 	filterActionAllow filterActionType = "allow"
 )
 
+func isBlockedGlobally(entry *model.Entry) bool {
+	if config.Opts == nil {
+		return false
+	}
+
+	if config.Opts.FilterEntryMaxAgeDays() > 0 {
+		maxAge := time.Duration(config.Opts.FilterEntryMaxAgeDays()) * 24 * time.Hour
+		if entry.Date.Before(time.Now().Add(-maxAge)) {
+			slog.Debug("Entry is blocked globally due to max age",
+				slog.String("entry_url", entry.URL),
+				slog.Time("entry_date", entry.Date),
+				slog.Duration("max_age", maxAge),
+			)
+			return true
+		}
+	}
+
+	return false
+}
+
 func IsBlockedEntry(feed *model.Feed, entry *model.Entry, user *model.User) bool {
+	if isBlockedGlobally(entry) {
+		return true
+	}
+
 	combinedRules := combineFilterRules(user.BlockFilterEntryRules, feed.BlockFilterEntryRules)
 	if combinedRules != "" {
 		if matchesEntryFilterRules(combinedRules, entry, feed, filterActionBlock) {

+ 65 - 0
internal/reader/filter/filter_test.go

@@ -4,9 +4,11 @@
 package filter // import "miniflux.app/v2/internal/reader/filter"
 
 import (
+	"os"
 	"testing"
 	"time"
 
+	"miniflux.app/v2/internal/config"
 	"miniflux.app/v2/internal/model"
 )
 
@@ -171,3 +173,66 @@ func TestMaxAgeFilter(t *testing.T) {
 		t.Error("Expected new entry to not be blocked with max-age:1d")
 	}
 }
+
+func TestIsBlockedGlobally(t *testing.T) {
+	var err error
+	config.Opts, err = config.NewParser().ParseEnvironmentVariables()
+	if err != nil {
+		t.Fatalf(`Parsing failure: %v`, err)
+	}
+
+	if isBlockedGlobally(&model.Entry{Title: "Test Entry", Date: time.Date(2020, 5, 1, 05, 05, 05, 05, time.UTC)}) {
+		t.Error("Expected no entries to be blocked globally when max-age is not set")
+	}
+
+	os.Setenv("FILTER_ENTRY_MAX_AGE_DAYS", "30")
+	defer os.Clearenv()
+
+	config.Opts, err = config.NewParser().ParseEnvironmentVariables()
+	if err != nil {
+		t.Fatalf(`Parsing failure: %v`, err)
+	}
+
+	if !isBlockedGlobally(&model.Entry{Title: "Test Entry", Date: time.Date(2020, 5, 1, 05, 05, 05, 05, time.UTC)}) {
+		t.Error("Expected entries to be blocked globally when max-age is set")
+	}
+
+	if isBlockedGlobally(&model.Entry{Title: "Test Entry", Date: time.Now().Add(-2 * time.Hour)}) {
+		t.Error("Expected entries not to be blocked globally when they are within the max-age limit")
+	}
+}
+
+func TestIsBlockedEntryWithGlobalMaxAge(t *testing.T) {
+	os.Setenv("FILTER_ENTRY_MAX_AGE_DAYS", "30")
+	defer os.Clearenv()
+
+	var err error
+	config.Opts, err = config.NewParser().ParseEnvironmentVariables()
+	if err != nil {
+		t.Fatalf(`Parsing failure: %v`, err)
+	}
+
+	entry := &model.Entry{Title: "Test Entry", Date: time.Now().Add(-31 * 24 * time.Hour)} // 31 days old
+	feed := &model.Feed{ID: 1}
+	user := &model.User{}
+
+	if !IsBlockedEntry(feed, entry, user) {
+		t.Error("Expected entry to be blocked due to global max-age rule")
+	}
+}
+
+func TestIsBlockedEntryWithDefaultGlobalMaxAge(t *testing.T) {
+	var err error
+	config.Opts, err = config.NewParser().ParseEnvironmentVariables()
+	if err != nil {
+		t.Fatalf(`Parsing failure: %v`, err)
+	}
+
+	entry := &model.Entry{Title: "Test Entry", Date: time.Now().Add(-31 * 24 * time.Hour)} // 31 days old
+	feed := &model.Feed{ID: 1}
+	user := &model.User{}
+
+	if IsBlockedEntry(feed, entry, user) {
+		t.Error("Expected entry not to be blocked due to default global max-age rule")
+	}
+}

+ 2 - 8
internal/reader/processor/processor.go

@@ -47,7 +47,8 @@ func ProcessFeedEntries(store *storage.Storage, feed *model.Feed, userID int64,
 			slog.Int64("feed_id", feed.ID),
 			slog.String("feed_url", feed.FeedURL),
 		)
-		if filter.IsBlockedEntry(feed, entry, user) || !filter.IsAllowedEntry(feed, entry, user) || !isRecentEntry(entry) {
+
+		if filter.IsBlockedEntry(feed, entry, user) || !filter.IsAllowedEntry(feed, entry, user) {
 			continue
 		}
 
@@ -183,10 +184,3 @@ func ProcessEntryWebPage(feed *model.Feed, entry *model.Entry, user *model.User)
 
 	return nil
 }
-
-func isRecentEntry(entry *model.Entry) bool {
-	if config.Opts.FilterEntryMaxAgeDays() == 0 || entry.Date.After(time.Now().AddDate(0, 0, -config.Opts.FilterEntryMaxAgeDays())) {
-		return true
-	}
-	return false
-}

+ 0 - 28
internal/reader/processor/processor_test.go

@@ -5,36 +5,8 @@ package processor // import "miniflux.app/v2/internal/reader/processor"
 
 import (
 	"testing"
-	"time"
-
-	"miniflux.app/v2/internal/config"
-	"miniflux.app/v2/internal/model"
 )
 
-func TestIsRecentEntry(t *testing.T) {
-	parser := config.NewParser()
-	var err error
-	config.Opts, err = parser.ParseEnvironmentVariables()
-	if err != nil {
-		t.Fatalf(`Parsing failure: %v`, err)
-	}
-	var scenarios = []struct {
-		entry    *model.Entry
-		expected bool
-	}{
-		{&model.Entry{Title: "Example1", Date: time.Date(2005, 5, 1, 05, 05, 05, 05, time.UTC)}, true},
-		{&model.Entry{Title: "Example2", Date: time.Date(2010, 5, 1, 05, 05, 05, 05, time.UTC)}, true},
-		{&model.Entry{Title: "Example3", Date: time.Date(2020, 5, 1, 05, 05, 05, 05, time.UTC)}, true},
-		{&model.Entry{Title: "Example4", Date: time.Date(2024, 3, 15, 05, 05, 05, 05, time.UTC)}, true},
-	}
-	for _, tc := range scenarios {
-		result := isRecentEntry(tc.entry)
-		if tc.expected != result {
-			t.Errorf(`Unexpected result, got %v for entry %q`, result, tc.entry.Title)
-		}
-	}
-}
-
 func TestMinifyEntryContent(t *testing.T) {
 	input := `<p>    Some text with a <a href="http://example.org/"> link   </a>    </p>`
 	expected := `<p>Some text with a <a href="http://example.org/">link</a></p>`