diff --git a/docker/start.sh b/docker/start.sh index b11dddc4..6910c8ac 100644 --- a/docker/start.sh +++ b/docker/start.sh @@ -11,6 +11,9 @@ echo "[setup] Web UI available at http://localhost:${WEB_ADDR##*:}" echo "[setup] Initializing cron jobs..." +# Start with a clean crontab +: > /etc/crontabs/root + # Load *_SCHEDULE and *_FLAGS from .env if not already set in the environment. # This allows the web UI to configure schedules by writing to the .env file. _cfg="${WEB_ENV_PATH:-/opt/explo/.env}" diff --git a/src/config/config.go b/src/config/config.go index a68b6ce3..9d1cdceb 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -34,6 +34,7 @@ type Flags struct { CfgPath string CfgSet bool Playlist string + PlaylistSet bool DownloadMode string ExcludeLocal bool Persist bool diff --git a/src/config/flags.go b/src/config/flags.go index 70593315..81e81888 100644 --- a/src/config/flags.go +++ b/src/config/flags.go @@ -42,6 +42,7 @@ func (cfg *Config) GetFlags() error { } persistSet := flag.Lookup("persist").Changed cfgSet := flag.Lookup("config").Changed + playlistSet := flag.Lookup("playlist").Changed @@ -59,6 +60,7 @@ func (cfg *Config) GetFlags() error { cfg.Flags.CfgPath = configPath cfg.Flags.CfgSet = cfgSet cfg.Flags.Playlist = playlist + cfg.Flags.PlaylistSet = playlistSet cfg.Flags.DownloadMode = downloadMode cfg.Flags.ExcludeLocal = excludeLocal cfg.Flags.Persist = persist diff --git a/src/downloader/monitor.go b/src/downloader/monitor.go index beb87a8b..79d10dee 100644 --- a/src/downloader/monitor.go +++ b/src/downloader/monitor.go @@ -89,7 +89,7 @@ func (c *DownloadClient) MonitorDownloads(tracks []*models.Track, m Monitor) err track.File, path = parsePath(track.File) if monCfg.MigrateDownload { if err = c.MoveDownload(monCfg.FromDir, monCfg.ToDir, path, track); err != nil { - return fmt.Errorf("error while moving file: %w", err) + slog.Error("error while moving file", "err", err.Error()) } else { slog.Info("track moved successfully", "service", monCfg.Service) } diff --git a/src/downloader/slskd.go b/src/downloader/slskd.go index 15ec5a42..c6ff7418 100644 --- a/src/downloader/slskd.go +++ b/src/downloader/slskd.go @@ -445,6 +445,11 @@ func parsePath(p string) (string, string) { // parse filepath to downloaded form } func wildcardArtist(artist string) string { + prefix := "" + if len(artist) >= 4 && strings.EqualFold(artist[:4], "the ") { + prefix = artist[:4] + artist = strings.TrimSpace(artist[4:]) +} r := []rune(strings.TrimSpace(artist)) if len(r) < 3 { @@ -452,7 +457,7 @@ func wildcardArtist(artist string) string { } r[0] = '*' - return string(r) + return prefix + string(r) } // different failure states slskd has (format is "Completed,Rejected", "Errored,Cancelled" etc..) diff --git a/src/main/main.go b/src/main/main.go index 32ad0629..e34f64bc 100644 --- a/src/main/main.go +++ b/src/main/main.go @@ -138,13 +138,22 @@ func main() { return } + if cfg.Flags.RefreshOnly { + if err := client.TriggerRefresh(&cfg); err != nil { + slog.Error("refresh-only failed", "err", err.Error()) + os.Exit(1) + } + slog.Info("library refresh triggered") + return + } + slog.Info("Starting Explo...") if err := os.MkdirAll(cfg.DownloadCfg.Youtube.CoversDir, 0755); err != nil { slog.Error("failed making directory", "msg", err.Error()) } - if cfg.ServerCfg.Enabled { + if cfg.ServerCfg.Enabled || !cfg.Flags.PlaylistSet { exploPath, err := os.Executable() if err != nil { @@ -156,15 +165,6 @@ func main() { log.Fatal(srv.Start()) } - if cfg.Flags.RefreshOnly { - if err := client.TriggerRefresh(&cfg); err != nil { - slog.Error("refresh-only failed", "err", err.Error()) - os.Exit(1) - } - slog.Info("library refresh triggered") - return - } - var tracks []*models.Track var err error if strings.HasPrefix(cfg.Flags.Playlist, "custom-") { diff --git a/src/web/backend/server.go b/src/web/backend/server.go index ffa1403c..7043f72d 100644 --- a/src/web/backend/server.go +++ b/src/web/backend/server.go @@ -689,7 +689,7 @@ func formatEnvValue(v string) string { return v } - if strings.ContainsAny(v, `"$#?' `) { + if strings.ContainsAny(v, `"$#?'`) { // escape single quotes inside value v = strings.ReplaceAll(v, `'`, `'\''`) return fmt.Sprintf(`'%s'`, v)