diff --git a/README.md b/README.md index 4e0d249..90177d0 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ vimeo = [ # Multiple keys will be rotated. # custom = { cover_art = "{IMAGE_URL}}", category = "TV", explicit = true, lang = "en" } # Optional feed customizations # max_height = "720" # Optional maximal height of video, example: 720, 1080, 1440, 2160, ... # cron_schedule = "@every 12h" # Optional cron expression format. If set then overwrite 'update_period'. See details below - # filters = { title = "regex for title here" } # Optional Golang regexp format. If set, then only download episodes with matching titles. + # filters = { title = "regex for title here", not_title = "regex for negative title match", description = "...", not_description = "..." } # Optional Golang regexp format. If set, then only download matching episodes. # opml = true|false # Optional inclusion of the feed in the OPML file (default value: false) # clean = { keep_last = 10 } # Keep last 10 episodes (order desc by PubDate) diff --git a/cmd/podsync/updater.go b/cmd/podsync/updater.go index bc30372..50b10fc 100644 --- a/cmd/podsync/updater.go +++ b/cmd/podsync/updater.go @@ -124,6 +124,40 @@ func (u *Updater) updateFeed(ctx context.Context, feedConfig *config.Feed) error return nil } +func (u *Updater) matchRegexpFilter(pattern, str string, negative bool, logger log.FieldLogger) bool { + if pattern != "" { + matched, err := regexp.MatchString(pattern, str) + if err != nil { + logger.Warnf("pattern %q is not a valid") + } else { + if matched == negative { + logger.Infof("skipping due to mismatch") + return false + } + } + } + return true +} + +func (u *Updater) matchFilters(episode *model.Episode, filters *config.Filters) bool { + logger := log.WithFields(log.Fields{"episode_id": episode.ID}) + if !u.matchRegexpFilter(filters.Title, episode.Title, false, logger.WithField("filter", "title")) { + return false + } + if !u.matchRegexpFilter(filters.NotTitle, episode.Title, true, logger.WithField("filter", "not_title")) { + return false + } + + if !u.matchRegexpFilter(filters.Description, episode.Description, false, logger.WithField("filter", "description")) { + return false + } + if !u.matchRegexpFilter(filters.NotDescription, episode.Description, true, logger.WithField("filter", "not_description")) { + return false + } + + return true +} + func (u *Updater) downloadEpisodes(ctx context.Context, feedConfig *config.Feed) error { var ( feedID = feedConfig.ID @@ -140,16 +174,8 @@ func (u *Updater) downloadEpisodes(ctx context.Context, feedConfig *config.Feed) return nil } - if feedConfig.Filters.Title != "" { - matched, err := regexp.MatchString(feedConfig.Filters.Title, episode.Title) - if err != nil { - log.Warnf("pattern %q is not a valid filter for %q Title", feedConfig.Filters.Title, feedConfig.ID) - } else { - if !matched { - log.Infof("skipping %q due to lack of match with %q", episode.Title, feedConfig.Filters.Title) - return nil - } - } + if !u.matchFilters(episode, &feedConfig.Filters) { + return nil } // Limit the number of episodes downloaded at once diff --git a/pkg/config/config.go b/pkg/config/config.go index 2241497..0496d85 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -45,7 +45,10 @@ type Feed struct { } type Filters struct { - Title string `toml:"title"` + Title string `toml:"title"` + NotTitle string `toml:"not_title"` + Description string `toml:"description"` + NotDescription string `toml:"not_description"` // More filters to be added here }