Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions cmd/podsync/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ type Config struct {
Tokens map[model.Provider]StringSlice `toml:"tokens"`
// Downloader (youtube-dl) configuration
Downloader ytdl.Config `toml:"downloader"`
// Global cleanup policy applied to feeds that don't specify their own cleanup policy
Cleanup *feed.Cleanup `toml:"cleanup"`
}

type Log struct {
Expand Down Expand Up @@ -179,6 +181,11 @@ func (c *Config) applyDefaults(configPath string) {
if _feed.PlaylistSort == "" {
_feed.PlaylistSort = model.SortingAsc
}

// Apply global cleanup policy if feed doesn't have its own
if _feed.Clean == nil && c.Cleanup != nil {
_feed.Clean = c.Cleanup
}
}
}

Expand Down
109 changes: 109 additions & 0 deletions cmd/podsync/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ timeout = 15
assert.EqualValues(t, 86400, feed.Filters.MaxDuration)
assert.EqualValues(t, 365, feed.Filters.MaxAge)
assert.EqualValues(t, 1, feed.Filters.MinAge)
require.NotNil(t, feed.Clean)
assert.EqualValues(t, 10, feed.Clean.KeepLast)
assert.EqualValues(t, model.SortingDesc, feed.PlaylistSort)

Expand Down Expand Up @@ -233,6 +234,114 @@ data_dir = "/data"
assert.True(t, config.Database.Badger.FileIO)
}

func TestGlobalCleanupPolicy(t *testing.T) {
t.Run("global cleanup policy applied to feeds without cleanup", func(t *testing.T) {
const file = `
[cleanup]
keep_last = 25

[server]
data_dir = "/data"

[feeds]
[feeds.FEED1]
url = "https://youtube.com/channel/test1"

[feeds.FEED2]
url = "https://youtube.com/channel/test2"
clean = { keep_last = 5 }
`
path := setup(t, file)
defer os.Remove(path)

config, err := LoadConfig(path)
assert.NoError(t, err)
require.NotNil(t, config)

// Global cleanup policy should be set
require.NotNil(t, config.Cleanup)
assert.EqualValues(t, 25, config.Cleanup.KeepLast)

// FEED1 should inherit global cleanup policy
feed1, ok := config.Feeds["FEED1"]
assert.True(t, ok)
require.NotNil(t, feed1.Clean)
assert.EqualValues(t, 25, feed1.Clean.KeepLast)

// FEED2 should keep its own cleanup policy
feed2, ok := config.Feeds["FEED2"]
assert.True(t, ok)
require.NotNil(t, feed2.Clean)
assert.EqualValues(t, 5, feed2.Clean.KeepLast)
})

t.Run("no global cleanup policy", func(t *testing.T) {
const file = `
[server]
data_dir = "/data"

[feeds]
[feeds.FEED1]
url = "https://youtube.com/channel/test1"

[feeds.FEED2]
url = "https://youtube.com/channel/test2"
clean = { keep_last = 5 }
`
path := setup(t, file)
defer os.Remove(path)

config, err := LoadConfig(path)
assert.NoError(t, err)
require.NotNil(t, config)

// Global cleanup policy should not be set
assert.Nil(t, config.Cleanup)

// FEED1 should have no cleanup policy
feed1, ok := config.Feeds["FEED1"]
assert.True(t, ok)
assert.Nil(t, feed1.Clean)

// FEED2 should keep its own cleanup policy
feed2, ok := config.Feeds["FEED2"]
assert.True(t, ok)
require.NotNil(t, feed2.Clean)
assert.EqualValues(t, 5, feed2.Clean.KeepLast)
})

t.Run("feed cleanup overrides global cleanup", func(t *testing.T) {
const file = `
[cleanup]
keep_last = 100

[server]
data_dir = "/data"

[feeds]
[feeds.FEED1]
url = "https://youtube.com/channel/test1"
clean = { keep_last = 10 }
`
path := setup(t, file)
defer os.Remove(path)

config, err := LoadConfig(path)
assert.NoError(t, err)
require.NotNil(t, config)

// Global cleanup policy should be set
require.NotNil(t, config.Cleanup)
assert.EqualValues(t, 100, config.Cleanup.KeepLast)

// FEED1 should use its own cleanup policy, not the global one
feed1, ok := config.Feeds["FEED1"]
assert.True(t, ok)
require.NotNil(t, feed1.Clean)
assert.EqualValues(t, 10, feed1.Clean.KeepLast)
})
}

func setup(t *testing.T, file string) string {
t.Helper()

Expand Down
9 changes: 8 additions & 1 deletion config.toml.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# This is an example of TOML configuration file for Podsync.

# Global cleanup policy applied to feeds that don't specify their own cleanup policy.
# When set, this policy is used as a fallback for all feeds.
# Comment out or remove this section if you don't want a global cleanup policy.
[cleanup]
keep_last = 50 # Keep last 50 episodes globally (unless overridden per feed)

# Web server related configuration.
[server]
# HTTP server port.
Expand Down Expand Up @@ -75,8 +81,9 @@ vimeo = [ # Multiple keys will be rotated.
# If set then overwrite 'update_period'.
cron_schedule = "@every 12h"

# Whether to cleanup old episodes.
# Whether to cleanup old episodes for this specific feed.
# Keep last 10 episodes (order desc by PubDate)
# This overrides the global cleanup policy if one is set.
clean = { keep_last = 10 }

# Optional Golang regexp format.
Expand Down
2 changes: 1 addition & 1 deletion pkg/feed/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type Config struct {
// 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"`
Clean *Cleanup `toml:"clean"`
// Custom is a list of feed customizations
Custom Custom `toml:"custom"`
// List of additional youtube-dl arguments passed at download time
Expand Down
7 changes: 6 additions & 1 deletion services/update/updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,11 +327,16 @@ func (u *Manager) cleanup(ctx context.Context, feedConfig *feed.Config) error {
var (
feedID = feedConfig.ID
logger = log.WithField("feed_id", feedID)
count = feedConfig.Clean.KeepLast
list []*model.Episode
result *multierror.Error
)

if feedConfig.Clean == nil {
logger.Debug("no cleanup policy configured")
return nil
}

count := feedConfig.Clean.KeepLast
if count < 1 {
logger.Info("nothing to clean")
return nil
Expand Down
Loading