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
149 changes: 76 additions & 73 deletions src/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,92 +5,94 @@ import (
"fmt"
"log"
"os"
"time"
"strings"
"time"

"github.com/ilyakaznacheev/cleanenv"
)

type Config struct {
DownloadCfg DownloadConfig
DownloadCfg DownloadConfig
DiscoveryCfg DiscoveryConfig
ClientCfg ClientConfig
Persist bool `env:"PERSIST" env-default:"true"`
System string `env:"EXPLO_SYSTEM"`
Debug bool `env:"DEBUG" env-default:"false"`
ClientCfg ClientConfig
Persist bool `env:"PERSIST" env-default:"true"`
System string `env:"EXPLO_SYSTEM"`
Debug bool `env:"DEBUG" env-default:"false"`
}

type ClientConfig struct {
ClientID string `env:"CLIENT_ID" env-default:"explo"`
LibraryName string `env:"LIBRARY_NAME" env-default:"Explo"`
URL string `env:"SYSTEM_URL"`
DownloadDir string `env:"DOWNLOAD_DIR" env-default:"/data/"`
PlaylistDir string `env:"PLAYLIST_DIR"`
ClientID string `env:"CLIENT_ID" env-default:"explo"`
LibraryName string `env:"LIBRARY_NAME" env-default:"Explo"`
URL string `env:"SYSTEM_URL"`
DownloadDir string `env:"DOWNLOAD_DIR" env-default:"/data/"`
PlaylistDir string `env:"PLAYLIST_DIR"`
PlaylistName string
PlaylistID string
Sleep int `env:"SLEEP" env-default:"2"`
Creds Credentials
Subsonic SubsonicConfig
PlaylistID string
Sleep int `env:"SLEEP" env-default:"2"`
Creds Credentials
Subsonic SubsonicConfig
}

type Credentials struct {
APIKey string `env:"API_KEY"`
User string `env:"SYSTEM_USERNAME"`
APIKey string `env:"API_KEY"`
User string `env:"SYSTEM_USERNAME"`
Password string `env:"SYSTEM_PASSWORD"`
Headers map[string]string
Token string
Salt string
Headers map[string]string
Token string
Salt string
}


type SubsonicConfig struct {
Version string `env:"SUBSONIC_VERSION" env-default:"1.16.1"`
ID string `env:"CLIENT" env-default:"explo"`
URL string `env:"SUBSONIC_URL" env-default:"http://127.0.0.1:4533"`
User string `env:"SUBSONIC_USER"`
Password string `env:"SUBSONIC_PASSWORD"`
type DiscoveryConfig struct {
Discovery string `env:"DISCOVERY_SERVICE" env-default:"listenbrainz"`
Separator string `env:"FILENAME_SEPARATOR" env-default:" "`
Listenbrainz Listenbrainz
}

type DownloadConfig struct {
DownloadDir string `env:"DOWNLOAD_DIR" env-default:"/data/"`
Youtube Youtube
Slskd Slskd
Discovery string `env:"LISTENBRAINZ_DISCOVERY" env-default:"playlist"`
Services []string `env:"DOWNLOAD_SERVICES" env-default:"youtube"`
DownloadDir string `env:"DOWNLOAD_DIR" env-default:"/data/"`
Slskd Slskd
Youtube Youtube
Discovery string `env:"LISTENBRAINZ_DISCOVERY" env-default:"playlist"`
Services []string `env:"DOWNLOAD_SERVICES" env-default:"youtube"`
}

type Filters struct {
Extensions []string `env:"EXTENSIONS" env-default:"flac,mp3"`
MinBitDepth int `env:"MIN_BIT_DEPTH" env-default:"8"`
MinBitRate int `env:"MIN_BITRATE" env-default:"256"`
FilterList []string `env:"FILTER_LIST" env-default:"live,remix,instrumental,extended"`
Extensions []string `env:"EXTENSIONS" env-default:"flac,mp3"`
MinBitDepth int `env:"MIN_BIT_DEPTH" env-default:"8"`
MinBitRate int `env:"MIN_BITRATE" env-default:"256"`
FilterList []string `env:"FILTER_LIST" env-default:"live,remix,instrumental,extended"`
}

type Youtube struct {
APIKey string `env:"YOUTUBE_API_KEY"`
FfmpegPath string `env:"FFMPEG_PATH"`
YtdlpPath string `env:"YTDLP_PATH"`
Filters Filters
type Listenbrainz struct {
Discovery string `env:"LISTENBRAINZ_DISCOVERY" env-default:"playlist"`
User string `env:"LISTENBRAINZ_USER"`
SingleArtist bool `env:"SINGLE_ARTIST" env-default:"true"`
}

type Slskd struct {
APIKey string `env:"SLSKD_API_KEY"`
URL string `env:"SLSKD_URL"`
Retry int `env:"SLSKD_RETRY" env-default:"5"` // Number of times to check search status before skipping the track
DownloadAttempts int `env:"SLSKD_DL_ATTEMPTS" env-default:"3"` // Max number of files to attempt downloading per track
SlskdDir string `env:"SLSKD_DIR" env-default:"/slskd/"`
MigrateDL bool `env:"MIGRATE_DOWNLOADS" env-default:"false"` // Move downloads from SlskdDir to DownloadDir
Timeout time.Duration `env:"SLSKD_TIMEOUT" env-default:"20s"`
Filters Filters
type SubsonicConfig struct {
Version string `env:"SUBSONIC_VERSION" env-default:"1.16.1"`
ID string `env:"CLIENT" env-default:"explo"`
URL string `env:"SUBSONIC_URL" env-default:"http://127.0.0.1:4533"`
User string `env:"SUBSONIC_USER"`
Password string `env:"SUBSONIC_PASSWORD"`
}

type DiscoveryConfig struct {
Discovery string `env:"DISCOVERY_SERVICE" env-default:"listenbrainz"`
Listenbrainz Listenbrainz
type Youtube struct {
APIKey string `env:"YOUTUBE_API_KEY"`
FfmpegPath string `env:"FFMPEG_PATH"`
YtdlpPath string `env:"YTDLP_PATH"`
Filters Filters
}
type Listenbrainz struct {
Discovery string `env:"LISTENBRAINZ_DISCOVERY" env-default:"playlist"`
User string `env:"LISTENBRAINZ_USER"`
SingleArtist bool `env:"SINGLE_ARTIST" env-default:"true"`

type Slskd struct {
APIKey string `env:"SLSKD_API_KEY"`
URL string `env:"SLSKD_URL"`
Retry int `env:"SLSKD_RETRY" env-default:"5"` // Number of times to check search status before skipping the track
DownloadAttempts int `env:"SLSKD_DL_ATTEMPTS" env-default:"3"` // Max number of files to attempt downloading per track
SlskdDir string `env:"SLSKD_DIR" env-default:"/slskd/"`
MigrateDL bool `env:"MIGRATE_DOWNLOADS" env-default:"false"` // Move downloads from SlskdDir to DownloadDir
Timeout time.Duration `env:"SLSKD_TIMEOUT" env-default:"20s"`
Filters Filters
}

func ReadEnv() Config {
Expand Down Expand Up @@ -128,24 +130,25 @@ func fixDir(dir string) string {
return dir
}

/* func (cfg *Config) HandleDeprecation() { // no deprecations at the moment (keeping this for reference)
switch cfg.System {
case "subsonic":
if cfg.Subsonic.User != "" && cfg.Creds.User == "" {
log.Println("Warning: 'SUBSONIC_USER' is deprecated. Please use 'SYSTEM_USERNAME'.")
cfg.Creds.User = cfg.Subsonic.User
}
if cfg.Subsonic.Password != "" && cfg.Creds.Password == "" {
log.Println("Warning: 'SUBSONIC_PASSWORD' is deprecated. Please use 'SYSTEM_PASSWORD'.")
cfg.Creds.Password = cfg.Subsonic.Password
}
if cfg.Subsonic.URL != "" && cfg.URL == "" {
log.Println("Warning: 'SUBSONIC_URL' is deprecated. Please use 'SYSTEM_URL'.")
cfg.URL = cfg.Subsonic.URL
/*
func (cfg *Config) HandleDeprecation() { // no deprecations at the moment (keeping this for reference)
switch cfg.System {
case "subsonic":
if cfg.Subsonic.User != "" && cfg.Creds.User == "" {
log.Println("Warning: 'SUBSONIC_USER' is deprecated. Please use 'SYSTEM_USERNAME'.")
cfg.Creds.User = cfg.Subsonic.User
}
if cfg.Subsonic.Password != "" && cfg.Creds.Password == "" {
log.Println("Warning: 'SUBSONIC_PASSWORD' is deprecated. Please use 'SYSTEM_PASSWORD'.")
cfg.Creds.Password = cfg.Subsonic.Password
}
if cfg.Subsonic.URL != "" && cfg.URL == "" {
log.Println("Warning: 'SUBSONIC_URL' is deprecated. Please use 'SYSTEM_URL'.")
cfg.URL = cfg.Subsonic.URL
}
}
}
}
*/
*/
func (cfg *Config) GetPlaylistName() { // Generate playlist name depending if user wants to keep it or not
playlistName := "Discover-Weekly"
if cfg.Persist {
Expand Down
72 changes: 36 additions & 36 deletions src/downloader/downloader.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package downloader

import (
"fmt"
"io"
"log"
"os"
"path"
"log"
"strings"
"regexp"
"fmt"
"path/filepath"
"io"
"regexp"
"strings"

"golang.org/x/sync/errgroup"

cfg "explo/src/config"
Expand All @@ -17,7 +18,7 @@ import (
)

type DownloadClient struct {
Cfg *cfg.DownloadConfig
Cfg *cfg.DownloadConfig
Downloaders []Downloader
}

Expand All @@ -27,7 +28,6 @@ type Downloader interface {
MonitorDownloads([]*models.Track) error
}


func NewDownloader(cfg *cfg.DownloadConfig, httpClient *util.HttpClient) *DownloadClient { // get download services from config and append them to DownloadClient
var downloader []Downloader
for _, service := range cfg.Services {
Expand All @@ -44,39 +44,39 @@ func NewDownloader(cfg *cfg.DownloadConfig, httpClient *util.HttpClient) *Downlo
}

return &DownloadClient{
Cfg: cfg,
Cfg: cfg,
Downloaders: downloader}
}

func (c *DownloadClient) StartDownload(tracks *[]*models.Track) {
for _, d := range c.Downloaders {
var g errgroup.Group
g.SetLimit(5)

for _, track := range *tracks {
if track.Present {
continue
func (c *DownloadClient) StartDownload(tracks *[]*models.Track) {
for _, d := range c.Downloaders {
var g errgroup.Group
g.SetLimit(5)

for _, track := range *tracks {
if track.Present {
continue
}

g.Go(func() error {

if err := d.QueryTrack(track); err != nil {
log.Println(err.Error())
return nil
}

g.Go(func() error {

if err := d.QueryTrack(track); err != nil {
log.Println(err.Error())
return nil
}
if err := d.GetTrack(track); err != nil {
log.Println(err.Error())
return nil
}
if err := d.GetTrack(track); err != nil {
log.Println(err.Error())
return nil
})
}
return nil
})
}
if err := g.Wait(); err != nil {
return
}

if err := d.MonitorDownloads(*tracks); err != nil {
log.Printf("track monitoring failed: %s", err.Error())
log.Printf("track monitoring failed: %s", err.Error())
}
}
filterTracks(tracks)
Expand All @@ -90,7 +90,7 @@ func (c *DownloadClient) DeleteSongs() {
for _, entry := range entries {
if !(entry.IsDir()) {
err = os.Remove(path.Join(c.Cfg.DownloadDir, entry.Name()))

if err != nil {
log.Printf("failed to remove file: %s", err.Error())
}
Expand All @@ -112,9 +112,9 @@ func filterTracks(tracks *[]*models.Track) { // only keep tracks that were downl
func containsLower(str string, substr string) bool {

return strings.Contains(
strings.ToLower(str),
strings.ToLower(substr),
)
strings.ToLower(str),
strings.ToLower(substr),
)
}

func sanitizeName(s string) string { // return string with only letters and digits
Expand All @@ -129,7 +129,7 @@ func getFilename(title, artist string) string {
t := re.ReplaceAllString(title, "_")
a := re.ReplaceAllString(artist, "_")

return fmt.Sprintf("%s-%s",t,a)
return fmt.Sprintf("%s-%s", t, a)
}

func moveDownload(srcDir, destDir, trackPath, file string) error { // Move download from the source dir to the dest dir (download dir)
Expand Down Expand Up @@ -186,4 +186,4 @@ func moveDownload(srcDir, destDir, trackPath, file string) error { // Move downl
}

return nil
}
}
Loading