Skip to content

Commit

Permalink
Decouple config package
Browse files Browse the repository at this point in the history
  • Loading branch information
mxpv committed Jan 2, 2022
1 parent 0edf283 commit 5483455
Show file tree
Hide file tree
Showing 21 changed files with 156 additions and 161 deletions.
108 changes: 13 additions & 95 deletions pkg/config/config.go → cmd/podsync/config.go
Original file line number Diff line number Diff line change
@@ -1,78 +1,22 @@
package config
package main

import (
"fmt"
"io/ioutil"
"path/filepath"
"regexp"
"time"

"github.com/hashicorp/go-multierror"
"github.com/pelletier/go-toml"
"github.com/pkg/errors"

"github.com/mxpv/podsync/pkg/db"
"github.com/mxpv/podsync/pkg/feed"
"github.com/mxpv/podsync/pkg/model"
"github.com/mxpv/podsync/pkg/ytdl"
)

// Feed is a configuration for a feed
type Feed struct {
ID string `toml:"-"`
// URL is a full URL of the field
URL string `toml:"url"`
// PageSize is the number of pages to query from YouTube API.
// NOTE: larger page sizes/often requests might drain your API token.
PageSize int `toml:"page_size"`
// UpdatePeriod is how often to check for updates.
// Format is "300ms", "1.5h" or "2h45m".
// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
// NOTE: too often update check might drain your API token.
UpdatePeriod time.Duration `toml:"update_period"`
// Cron expression format is how often to check update
// NOTE: too often update check might drain your API token.
CronSchedule string `toml:"cron_schedule"`
// Quality to use for this feed
Quality model.Quality `toml:"quality"`
// Maximum height of video
MaxHeight int `toml:"max_height"`
// Format to use for this feed
Format model.Format `toml:"format"`
// Only download episodes that match this regexp (defaults to matching anything)
Filters Filters `toml:"filters"`
// Clean is a cleanup policy to use for this feed
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
YouTubeDLArgs []string `toml:"youtube_dl_args"`
// Included in OPML file
OPML bool `toml:"opml"`
// Playlist sort
PlaylistSort model.Sorting `toml:"playlist_sort"`
}

type Filters struct {
Title string `toml:"title"`
NotTitle string `toml:"not_title"`
Description string `toml:"description"`
NotDescription string `toml:"not_description"`
// More filters to be added here
}

type Custom struct {
CoverArt string `toml:"cover_art"`
CoverArtQuality model.Quality `toml:"cover_art_quality"`
Category string `toml:"category"`
Subcategories []string `toml:"subcategories"`
Explicit bool `toml:"explicit"`
Language string `toml:"lang"`
Author string `toml:"author"`
Title string `toml:"title"`
Description string `toml:"description"`
OwnerName string `toml:"ownerName"`
OwnerEmail string `toml:"ownerEmail"`
}

type Server struct {
type ServerConfig struct {
// Hostname to use for download links
Hostname string `toml:"hostname"`
// Port is a server port to listen to
Expand All @@ -88,24 +32,6 @@ type Server struct {
DataDir string `toml:"data_dir"`
}

type Database struct {
// Dir is a directory to keep database files
Dir string `toml:"dir"`
Badger *Badger `toml:"badger"`
}

// Badger represents BadgerDB configuration parameters
// See https://github.com/dgraph-io/badger#memory-usage
type Badger struct {
Truncate bool `toml:"truncate"`
FileIO bool `toml:"file_io"`
}

type Cleanup struct {
// KeepLast defines how many episodes to keep
KeepLast int `toml:"keep_last"`
}

type Log struct {
// Filename to write the log to (instead of stdout)
Filename string `toml:"filename"`
Expand All @@ -119,28 +45,20 @@ type Log struct {
Compress bool `toml:"compress"`
}

// Downloader is a youtube-dl related configuration
type Downloader struct {
// SelfUpdate toggles self update every 24 hour
SelfUpdate bool `toml:"self_update"`
// Timeout in minutes for youtube-dl process to finish download
Timeout int `toml:"timeout"`
}

type Config struct {
// Server is the web server configuration
Server Server `toml:"server"`
Server ServerConfig `toml:"server"`
// Log is the optional logging configuration
Log Log `toml:"log"`
// Database configuration
Database Database `toml:"database"`
Database db.Config `toml:"database"`
// Feeds is a list of feeds to host by this app.
// ID will be used as feed ID in http://podsync.net/{FEED_ID}.xml
Feeds map[string]*Feed
Feeds map[string]*feed.Config
// Tokens is API keys to use to access YouTube/Vimeo APIs.
Tokens map[model.Provider][]string `toml:"tokens"`
// Downloader (youtube-dl) configuration
Downloader Downloader `toml:"downloader"`
Downloader ytdl.Config `toml:"downloader"`
}

// LoadConfig loads TOML configuration from a file path
Expand All @@ -155,8 +73,8 @@ func LoadConfig(path string) (*Config, error) {
return nil, errors.Wrap(err, "failed to unmarshal toml")
}

for id, feed := range config.Feeds {
feed.ID = id
for id, f := range config.Feeds {
f.ID = id
}

config.applyDefaults(path)
Expand Down Expand Up @@ -186,8 +104,8 @@ func (c *Config) validate() error {
result = multierror.Append(result, errors.New("at least one feed must be specified"))
}

for id, feed := range c.Feeds {
if feed.URL == "" {
for id, f := range c.Feeds {
if f.URL == "" {
result = multierror.Append(result, errors.Errorf("URL is required for %q", id))
}
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/config/config_test.go → cmd/podsync/config_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package config
package main

import (
"io/ioutil"
Expand Down Expand Up @@ -173,7 +173,7 @@ data_dir = "/data"

func TestDefaultHostname(t *testing.T) {
cfg := Config{
Server: Server{},
Server: ServerConfig{},
}

t.Run("empty hostname", func(t *testing.T) {
Expand Down
6 changes: 3 additions & 3 deletions cmd/podsync/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import (
"time"

"github.com/jessevdk/go-flags"
"github.com/mxpv/podsync/pkg/feed"
"github.com/robfig/cron/v3"
log "github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
"gopkg.in/natefinch/lumberjack.v2"

"github.com/mxpv/podsync/pkg/config"
"github.com/mxpv/podsync/pkg/db"
"github.com/mxpv/podsync/pkg/fs"
"github.com/mxpv/podsync/pkg/ytdl"
Expand Down Expand Up @@ -75,7 +75,7 @@ func main() {

// Load TOML file
log.Debugf("loading configuration %q", opts.ConfigPath)
cfg, err := config.LoadConfig(opts.ConfigPath)
cfg, err := LoadConfig(opts.ConfigPath)
if err != nil {
log.WithError(err).Fatal("failed to load configuration file")
}
Expand Down Expand Up @@ -121,7 +121,7 @@ func main() {
}

// Queue of feeds to update
updates := make(chan *config.Feed, 16)
updates := make(chan *feed.Config, 16)
defer close(updates)

// Create Cron
Expand Down
4 changes: 1 addition & 3 deletions cmd/podsync/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@ import (
"net/http"

log "github.com/sirupsen/logrus"

"github.com/mxpv/podsync/pkg/config"
)

type Server struct {
http.Server
}

func NewServer(cfg *config.Config, storage http.FileSystem) *Server {
func NewServer(cfg *Config, storage http.FileSystem) *Server {
port := cfg.Server.Port
if port == 0 {
port = 8080
Expand Down
21 changes: 10 additions & 11 deletions cmd/podsync/updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
log "github.com/sirupsen/logrus"

"github.com/mxpv/podsync/pkg/builder"
"github.com/mxpv/podsync/pkg/config"
"github.com/mxpv/podsync/pkg/db"
"github.com/mxpv/podsync/pkg/feed"
"github.com/mxpv/podsync/pkg/fs"
Expand All @@ -24,18 +23,18 @@ import (
)

type Downloader interface {
Download(ctx context.Context, feedConfig *config.Feed, episode *model.Episode) (io.ReadCloser, error)
Download(ctx context.Context, feedConfig *feed.Config, episode *model.Episode) (io.ReadCloser, error)
}

type Updater struct {
config *config.Config
config *Config
downloader Downloader
db db.Storage
fs fs.Storage
keys map[model.Provider]feed.KeyProvider
}

func NewUpdater(config *config.Config, downloader Downloader, db db.Storage, fs fs.Storage) (*Updater, error) {
func NewUpdater(config *Config, downloader Downloader, db db.Storage, fs fs.Storage) (*Updater, error) {
keys := map[model.Provider]feed.KeyProvider{}

for name, list := range config.Tokens {
Expand All @@ -55,7 +54,7 @@ func NewUpdater(config *config.Config, downloader Downloader, db db.Storage, fs
}, nil
}

func (u *Updater) Update(ctx context.Context, feedConfig *config.Feed) error {
func (u *Updater) Update(ctx context.Context, feedConfig *feed.Config) error {
log.WithFields(log.Fields{
"feed_id": feedConfig.ID,
"format": feedConfig.Format,
Expand Down Expand Up @@ -90,7 +89,7 @@ func (u *Updater) Update(ctx context.Context, feedConfig *config.Feed) error {
}

// updateFeed pulls API for new episodes and saves them to database
func (u *Updater) updateFeed(ctx context.Context, feedConfig *config.Feed) error {
func (u *Updater) updateFeed(ctx context.Context, feedConfig *feed.Config) error {
info, err := builder.ParseURL(feedConfig.URL)
if err != nil {
return errors.Wrapf(err, "failed to parse URL: %s", feedConfig.URL)
Expand Down Expand Up @@ -162,7 +161,7 @@ func (u *Updater) matchRegexpFilter(pattern, str string, negative bool, logger l
return true
}

func (u *Updater) matchFilters(episode *model.Episode, filters *config.Filters) bool {
func (u *Updater) matchFilters(episode *model.Episode, filters *feed.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
Expand All @@ -181,7 +180,7 @@ func (u *Updater) matchFilters(episode *model.Episode, filters *config.Filters)
return true
}

func (u *Updater) downloadEpisodes(ctx context.Context, feedConfig *config.Feed) error {
func (u *Updater) downloadEpisodes(ctx context.Context, feedConfig *feed.Config) error {
var (
feedID = feedConfig.ID
downloadList []*model.Episode
Expand Down Expand Up @@ -308,7 +307,7 @@ func (u *Updater) downloadEpisodes(ctx context.Context, feedConfig *config.Feed)
return nil
}

func (u *Updater) buildXML(ctx context.Context, feedConfig *config.Feed) error {
func (u *Updater) buildXML(ctx context.Context, feedConfig *feed.Config) error {
f, err := u.db.GetFeed(ctx, feedConfig.ID)
if err != nil {
return err
Expand Down Expand Up @@ -336,7 +335,7 @@ func (u *Updater) buildXML(ctx context.Context, feedConfig *config.Feed) error {
func (u *Updater) buildOPML(ctx context.Context) error {
// Build OPML with data received from builder
log.Debug("building podcast OPML")
opml, err := feed.BuildOPML(ctx, u.config, u.db, u.config.Server.Hostname)
opml, err := feed.BuildOPML(ctx, u.config.Feeds, u.db, u.config.Server.Hostname)
if err != nil {
return err
}
Expand All @@ -353,7 +352,7 @@ func (u *Updater) buildOPML(ctx context.Context) error {
return nil
}

func (u *Updater) cleanup(ctx context.Context, feedConfig *config.Feed) error {
func (u *Updater) cleanup(ctx context.Context, feedConfig *feed.Config) error {
var (
feedID = feedConfig.ID
logger = log.WithField("feed_id", feedID)
Expand Down
4 changes: 2 additions & 2 deletions pkg/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ package builder
import (
"context"

"github.com/mxpv/podsync/pkg/feed"
"github.com/pkg/errors"

"github.com/mxpv/podsync/pkg/config"
"github.com/mxpv/podsync/pkg/model"
)

type Builder interface {
Build(ctx context.Context, cfg *config.Feed) (*model.Feed, error)
Build(ctx context.Context, cfg *feed.Config) (*model.Feed, error)
}

func New(ctx context.Context, provider model.Provider, key string) (Builder, error) {
Expand Down
4 changes: 2 additions & 2 deletions pkg/builder/soundcloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ import (
"strconv"
"time"

"github.com/mxpv/podsync/pkg/feed"
"github.com/pkg/errors"
soundcloudapi "github.com/zackradisic/soundcloud-api"

"github.com/mxpv/podsync/pkg/config"
"github.com/mxpv/podsync/pkg/model"
)

type SoundCloudBuilder struct {
client *soundcloudapi.API
}

func (s *SoundCloudBuilder) Build(_ctx context.Context, cfg *config.Feed) (*model.Feed, error) {
func (s *SoundCloudBuilder) Build(_ctx context.Context, cfg *feed.Config) (*model.Feed, error) {
info, err := ParseURL(cfg.URL)
if err != nil {
return nil, err
Expand Down
5 changes: 2 additions & 3 deletions pkg/builder/soundcloud_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ package builder
import (
"testing"

"github.com/mxpv/podsync/pkg/feed"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/mxpv/podsync/pkg/config"
)

func TestSC_BUILDFEED(t *testing.T) {
Expand All @@ -20,7 +19,7 @@ func TestSC_BUILDFEED(t *testing.T) {

for _, addr := range urls {
t.Run(addr, func(t *testing.T) {
feed, err := builder.Build(testCtx, &config.Feed{URL: addr})
feed, err := builder.Build(testCtx, &feed.Config{URL: addr})
require.NoError(t, err)

assert.NotEmpty(t, feed.Title)
Expand Down
Loading

0 comments on commit 5483455

Please sign in to comment.