From 6c33acf06262ce26df6a7f3f404333af506344c6 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Mon, 4 May 2026 15:06:28 -0400 Subject: [PATCH] feat(server/m7-353): config + main.go wiring for coverart enricher --- cmd/minstrel/main.go | 24 ++++++++++++++++++++++++ internal/config/config.go | 24 ++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/cmd/minstrel/main.go b/cmd/minstrel/main.go index 3a2b10fa..bb2ae9bd 100644 --- a/cmd/minstrel/main.go +++ b/cmd/minstrel/main.go @@ -13,6 +13,7 @@ import ( "git.fabledsword.com/bvandeusen/minstrel/internal/auth" "git.fabledsword.com/bvandeusen/minstrel/internal/config" + "git.fabledsword.com/bvandeusen/minstrel/internal/coverart" "git.fabledsword.com/bvandeusen/minstrel/internal/db" "git.fabledsword.com/bvandeusen/minstrel/internal/library" "git.fabledsword.com/bvandeusen/minstrel/internal/lidarrconfig" @@ -71,11 +72,34 @@ func run() error { } scanner := library.New(pool, logger, cfg.Library.ScanPaths) + + contact := cfg.Library.ContactEmail + if contact == "" { + contact = "https://git.fabledsword.com/bvandeusen/minstrel" + } + coverFetcher := coverart.NewFetcher(coverart.FetcherConfig{ + UserAgent: fmt.Sprintf("Minstrel/dev (%s)", contact), + MinPeriod: time.Second, + }) + coverEnricher := coverart.NewEnricher(pool, logger.With("component", "coverart"), coverFetcher, cfg.Library.CoverArtFromMBCAA) + if cfg.Library.ScanOnStartup && len(cfg.Library.ScanPaths) > 0 { go func() { if _, err := scanner.Scan(ctx); err != nil { logger.Error("startup scan failed", "err", err) } + // Enrich any newly-imported albums (and resume any partial backlog). + if _, err := coverEnricher.EnrichBatch(ctx, cfg.Library.CoverArtBackfillCap); err != nil { + logger.Warn("post-scan cover enrichment failed", "err", err) + } + }() + } else { + // No startup scan — still run the boot backfill once for any rows + // the previous run didn't get to. + go func() { + if _, err := coverEnricher.EnrichBatch(ctx, cfg.Library.CoverArtBackfillCap); err != nil { + logger.Warn("boot cover enrichment failed", "err", err) + } }() } diff --git a/internal/config/config.go b/internal/config/config.go index cf252537..28120601 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -69,8 +69,11 @@ type AdminBootstrapConfig struct { } type LibraryConfig struct { - ScanPaths []string `yaml:"scan_paths"` - ScanOnStartup bool `yaml:"scan_on_startup"` + ScanPaths []string `yaml:"scan_paths"` + ScanOnStartup bool `yaml:"scan_on_startup"` + CoverArtFromMBCAA bool `yaml:"coverart_from_mbcaa"` // default true + CoverArtBackfillCap int `yaml:"coverart_backfill_cap"` // default 500 + ContactEmail string `yaml:"contact_email"` // optional override for MBCAA UA } // SubsonicConfig controls wire-format concessions on the /rest/* surface. @@ -134,6 +137,10 @@ func Default() Config { RadioSize: 50, RadioSizeMax: 200, }, + Library: LibraryConfig{ + CoverArtFromMBCAA: true, + CoverArtBackfillCap: 500, + }, } } @@ -189,6 +196,19 @@ func applyEnv(cfg *Config) { cfg.Library.ScanOnStartup = b } } + if v, ok := os.LookupEnv("MINSTREL_LIBRARY_COVERART_FROM_MBCAA"); ok { + if b, err := strconv.ParseBool(v); err == nil { + cfg.Library.CoverArtFromMBCAA = b + } + } + if v, ok := os.LookupEnv("MINSTREL_LIBRARY_COVERART_BACKFILL_CAP"); ok { + if n, err := strconv.Atoi(v); err == nil { + cfg.Library.CoverArtBackfillCap = n + } + } + if v, ok := os.LookupEnv("MINSTREL_CONTACT_EMAIL"); ok { + cfg.Library.ContactEmail = v + } if v, ok := os.LookupEnv("MINSTREL_SUBSONIC_ALLOW_PLAINTEXT_PASSWORD"); ok { if b, err := strconv.ParseBool(v); err == nil { cfg.Subsonic.AllowPlaintextPassword = b