diff --git a/.gitignore b/.gitignore index 6d89f1a8..0955eba4 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ venv/ .DS_Store /podsync +podsync.log db config.toml \ No newline at end of file diff --git a/README.md b/README.md index fdc1be3f..74372e05 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ any device in podcast client. - Supports feeds configuration: video/audio, high/low quality, max video height, etc. - mp3 encoding - Update scheduler supports cron expressions -- Episodes filtering (match by title). +- Episodes filtering (match by title, duration). - Feeds customizations (custom artwork, category, language, etc). - OPML export. - Supports episodes cleanup (keep last X episodes). diff --git a/cmd/podsync/config_test.go b/cmd/podsync/config_test.go index ef5e5fff..9a79a977 100644 --- a/cmd/podsync/config_test.go +++ b/cmd/podsync/config_test.go @@ -37,7 +37,7 @@ timeout = 15 update_period = "5h" format = "audio" quality = "low" - filters = { title = "regex for title here" } + filters = { title = "regex for title here", min_duration = 0, max_duration = 86400} playlist_sort = "desc" clean = { keep_last = 10 } [feeds.XYZ.custom] @@ -78,6 +78,8 @@ timeout = 15 assert.EqualValues(t, "audio", feed.Format) assert.EqualValues(t, "low", feed.Quality) assert.EqualValues(t, "regex for title here", feed.Filters.Title) + assert.EqualValues(t, 0, feed.Filters.MinDuration) + assert.EqualValues(t, 86400, feed.Filters.MaxDuration) assert.EqualValues(t, 10, feed.Clean.KeepLast) assert.EqualValues(t, model.SortingDesc, feed.PlaylistSort) diff --git a/config.toml.example b/config.toml.example index 98cea593..b7cb5fef 100644 --- a/config.toml.example +++ b/config.toml.example @@ -74,7 +74,8 @@ vimeo = [ # Multiple keys will be rotated. # Optional Golang regexp format. # If set, then only download matching episodes. - filters = { title = "regex for title here", not_title = "regex for negative title match", description = "...", not_description = "..." } + # Duration filters are in seconds. + filters = { title = "regex for title here", not_title = "regex for negative title match", description = "...", not_description = "...", min_duration = 0, max_duration = 86400 } # Optional extra arguments passed to youtube-dl when downloading videos from this feed. # This example would embed available English closed captions in the videos. diff --git a/pkg/feed/config.go b/pkg/feed/config.go index facfa6ff..dd755517 100644 --- a/pkg/feed/config.go +++ b/pkg/feed/config.go @@ -30,7 +30,7 @@ type Config struct { Format model.Format `toml:"format"` // Custom format properties CustomFormat CustomFormat `toml:"custom_format"` - // Only download episodes that match this regexp (defaults to matching anything) + // Only download episodes that match the filters (defaults to matching anything) Filters Filters `toml:"filters"` // Clean is a cleanup policy to use for this feed Clean Cleanup `toml:"clean"` @@ -56,6 +56,8 @@ type Filters struct { NotTitle string `toml:"not_title"` Description string `toml:"description"` NotDescription string `toml:"not_description"` + MinDuration int64 `toml:"min_duration"` + MaxDuration int64 `toml:"max_duration"` // More filters to be added here } diff --git a/services/update/matcher.go b/services/update/matcher.go index f28753d9..b432fcb8 100644 --- a/services/update/matcher.go +++ b/services/update/matcher.go @@ -15,7 +15,7 @@ func matchRegexpFilter(pattern, str string, negative bool, logger log.FieldLogge logger.Warnf("pattern %q is not a valid") } else { if matched == negative { - logger.Infof("skipping due to mismatch") + logger.Infof("skipping due to regexp mismatch") return false } } @@ -41,5 +41,15 @@ func matchFilters(episode *model.Episode, filters *feed.Filters) bool { return false } + if filters.MaxDuration > 0 && episode.Duration > filters.MaxDuration { + logger.WithField("filter", "max_duration").Infof("skipping due to duration filter (%ds)", episode.Duration) + return false + } + + if filters.MinDuration > 0 && episode.Duration < filters.MinDuration { + logger.WithField("filter", "min_duration").Infof("skipping due to duration filter (%ds)", episode.Duration) + return false + } + return true }