diff --git a/src/config/config.go b/src/config/config.go index 3b336681..fc4a0383 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -38,6 +38,7 @@ type Flags struct { ExcludeLocal bool Persist bool PersistSet bool + SearchMBID string RefreshOnly bool } diff --git a/src/config/flags.go b/src/config/flags.go index 6c03826c..ebab5b70 100644 --- a/src/config/flags.go +++ b/src/config/flags.go @@ -22,6 +22,7 @@ func (cfg *Config) GetFlags() error { var excludeLocal bool var persist bool var showVersion bool + var searchMBID string var refreshOnly bool // Long flags flag.StringVarP(&configPath, "config", "c", ".env", "Path of the configuration file") @@ -30,9 +31,10 @@ func (cfg *Config) GetFlags() error { flag.BoolVarP(&excludeLocal, "exclude-local", "e", false, "Exclude locally found tracks from the imported playlist") flag.BoolVar(&persist, "persist", true, "Keep playlists between generations") flag.BoolVarP(&showVersion, "version", "v", false, "Print version and exit") + flag.StringVar(&searchMBID, "search-mbid", "", "Test Plex search for a single recording MBID (resolves via ListenBrainz, then searches your library)") flag.BoolVar(&refreshOnly, "refresh-only", false, "Trigger alibrary rescan and exit; skips discovery and downloads") - flag.Parse() + flag.Parse() if showVersion { fmt.Println(Version) @@ -41,24 +43,29 @@ func (cfg *Config) GetFlags() error { persistSet := flag.Lookup("persist").Changed cfgSet := flag.Lookup("config").Changed - // Validation for playlist — built-in types or user-imported custom-* IDs - if !contains(validPlaylists, playlist) && !strings.HasPrefix(playlist, "custom-") { - return fmt.Errorf("flag validation error: invalid playlist %s (must be one of: %s, or a custom-* id)", - playlist, strings.Join(validPlaylists, ", ")) - } - // Validation for download mode - if !contains(validDownloadMode, downloadMode) { - return fmt.Errorf("flag validation error: invalid download mode %s (must be one of: %s)", - downloadMode, strings.Join(validDownloadMode, ", ")) - } + if searchMBID == "" { + if !contains(validPlaylists, playlist) { + return fmt.Errorf("flag validation error: invalid playlist %s (must be one of: %s)", + playlist, strings.Join(validPlaylists, ", ")) + } + if !contains(validDownloadMode, downloadMode) { + return fmt.Errorf("flag validation error: invalid download mode %s (must be one of: %s)", + downloadMode, strings.Join(validDownloadMode, ", ")) + } + if !contains(validPlaylists, playlist) && !strings.HasPrefix(playlist, "custom-") { + return fmt.Errorf("flag validation error: invalid playlist %s (must be one of: %s, or a custom-* id)", + playlist, strings.Join(validPlaylists, ", ")) + } + } cfg.Flags.CfgPath = configPath cfg.Flags.CfgSet = cfgSet cfg.Flags.Playlist = playlist cfg.Flags.DownloadMode = downloadMode cfg.Flags.ExcludeLocal = excludeLocal cfg.Flags.Persist = persist + cfg.Flags.SearchMBID = searchMBID cfg.Flags.RefreshOnly = refreshOnly // for deprecation purposes (can be removed at a later date) diff --git a/src/discovery/listenbrainz.go b/src/discovery/listenbrainz.go index a4436b91..8f94f538 100644 --- a/src/discovery/listenbrainz.go +++ b/src/discovery/listenbrainz.go @@ -289,7 +289,13 @@ func (c *ListenBrainz) getTopRecordings(user string) ([]*models.Track, error) { return tracks, nil } - +func (c *ListenBrainz) LookupRecording(mbid string) (*models.Track, error) { + tracks, err := c.getTracks([]string{mbid}, false) + if err != nil { + return nil, err + } + return tracks[0], nil +} func (c *ListenBrainz) getTracks(mbids []string, singleArtist bool) ([]*models.Track, error) { strMbids := strings.Join(mbids, ",") diff --git a/src/main/main.go b/src/main/main.go index 1bad8d2e..468b3304 100644 --- a/src/main/main.go +++ b/src/main/main.go @@ -97,7 +97,29 @@ func setup(cfg *config.Config) { logging.Init(cfg.LogLevel, notifyClient) cfg.GenPlaylistName() } +func runSearchTest(cfg *config.Config, httpClient *util.HttpClient) { + lb := discovery.NewListenBrainz(cfg.DiscoveryCfg, httpClient) + track, err := lb.LookupRecording(cfg.Flags.SearchMBID) + if err != nil { + log.Fatalf("failed to resolve MBID %s from ListenBrainz: %s", cfg.Flags.SearchMBID, err) + } + slog.Info("resolved recording", "title", track.CleanTitle, "artist", track.MainArtist, "album", track.Album, "duration_ms", track.Duration) + + c, err := client.NewClient(cfg) + if err != nil { + log.Fatalf("failed to init client: %s", err) + } + tracks := []*models.Track{track} + if err := c.CheckTracks(tracks); err != nil { + slog.Warn("CheckTracks error", "err", err) + } + if track.Present { + slog.Info("FOUND in library", "system", cfg.System, "key", track.ID) + } else { + slog.Info("NOT FOUND in library", "system", cfg.System) + } +} func main() { var cfg config.Config if err := cfg.GetFlags(); err != nil { @@ -106,6 +128,14 @@ func main() { cfg.ReadEnv() cfg.MergeFlags() setup(&cfg) + + httpClient := initHttpClient() + + if cfg.Flags.SearchMBID != "" { + runSearchTest(&cfg, httpClient) + return + } + slog.Info("Starting Explo...") if err := os.MkdirAll(cfg.DownloadCfg.Youtube.CoversDir, 0755); err != nil { @@ -133,8 +163,6 @@ func main() { return } - httpClient := initHttpClient() - var tracks []*models.Track var err error if strings.HasPrefix(cfg.Flags.Playlist, "custom-") { @@ -147,7 +175,8 @@ func main() { disc := discovery.NewDiscoverer(cfg.DiscoveryCfg, httpClient) tracks, err = disc.Discover() } - if err != nil { + + if err != nil { slog.Error(err.Error(), "notify", true) os.Exit(1) }