refactor(server/coverart): provider interface takes ArtistRef/AlbumRef
Changes the AlbumCoverProvider and ArtistArtProvider interfaces from MBID-only string parameters to ref-struct signatures so name-based providers (Deezer, Last.fm in upcoming tasks) can act on rows without MBIDs. Today, 53 of 213 artists in the dev DB have NULL MBIDs — featured artists, remixers, and compilation contributors created from track-tag splits where the primary-artist MBID is in the file but collaborator IDs aren't. These rows are unreachable by the current MBID-only chain. Refactoring the interface unblocks future name-based providers from acting on them. TheAudioDB and MBCAA keep MBID-only behavior internally: they return ErrNotFound when ref.MBID is empty rather than attempting a name-based fallback. The MBID guard inside EnrichAlbum/EnrichArtist is removed; providers receive the ref unconditionally and decide whether they can act on it. GetAlbumWithFirstTrackPath now JOINs artists to return artist_name alongside the existing fields, supporting AlbumRef construction. No behavioral change today (only TheAudioDB + MBCAA registered, both keep MBID-only behavior). The change unblocks T3 (Deezer) and T4 (Last.fm) which can now register and act on every artist/album regardless of MBID presence. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -86,13 +86,14 @@ func (p *theAudioDBProvider) currentKey() string {
|
||||
|
||||
// FetchAlbumCover hits /album-mb.php?i=<mbid>, parses strAlbumThumb,
|
||||
// then GETs the image URL. Two HTTP round-trips per call; both
|
||||
// counted against the rate-limit guard.
|
||||
func (p *theAudioDBProvider) FetchAlbumCover(ctx context.Context, mbid string) ([]byte, error) {
|
||||
// counted against the rate-limit guard. TheAudioDB is MBID-only;
|
||||
// returns ErrNotFound when ref.MBID is empty.
|
||||
func (p *theAudioDBProvider) FetchAlbumCover(ctx context.Context, ref AlbumRef) ([]byte, error) {
|
||||
if !p.enabled.Load() {
|
||||
return nil, ErrNotFound // defensive; enricher already filters on enabled
|
||||
}
|
||||
if mbid == "" {
|
||||
return nil, fmt.Errorf("coverart: empty mbid")
|
||||
if ref.MBID == "" {
|
||||
return nil, ErrNotFound // TheAudioDB is MBID-only
|
||||
}
|
||||
|
||||
var resp struct {
|
||||
@@ -100,7 +101,7 @@ func (p *theAudioDBProvider) FetchAlbumCover(ctx context.Context, mbid string) (
|
||||
StrAlbumThumb *string `json:"strAlbumThumb"`
|
||||
} `json:"album"`
|
||||
}
|
||||
if err := p.getJSON(ctx, "album-mb.php?i="+mbid, &resp); err != nil {
|
||||
if err := p.getJSON(ctx, "album-mb.php?i="+ref.MBID, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(resp.Album) == 0 || resp.Album[0].StrAlbumThumb == nil || *resp.Album[0].StrAlbumThumb == "" {
|
||||
@@ -111,6 +112,7 @@ func (p *theAudioDBProvider) FetchAlbumCover(ctx context.Context, mbid string) (
|
||||
|
||||
// FetchArtistArt hits /artist-mb.php?i=<mbid>, parses strArtistThumb +
|
||||
// strArtistFanart, GETs both. Up to three HTTP round-trips per call.
|
||||
// TheAudioDB is MBID-only; returns ErrNotFound when ref.MBID is empty.
|
||||
//
|
||||
// Atomic at the JSON step: if the JSON parse yields no images at all
|
||||
// (artist not found OR both image fields null/empty), returns
|
||||
@@ -119,12 +121,12 @@ func (p *theAudioDBProvider) FetchAlbumCover(ctx context.Context, mbid string) (
|
||||
// returns the successful one with nil for the failed one — the
|
||||
// enricher persists whichever bytes landed. If BOTH image GETs fail
|
||||
// transiently, returns ErrTransient so the row stays NULL for retry.
|
||||
func (p *theAudioDBProvider) FetchArtistArt(ctx context.Context, mbid string) (thumb, fanart []byte, err error) {
|
||||
func (p *theAudioDBProvider) FetchArtistArt(ctx context.Context, ref ArtistRef) (thumb, fanart []byte, err error) {
|
||||
if !p.enabled.Load() {
|
||||
return nil, nil, ErrNotFound
|
||||
}
|
||||
if mbid == "" {
|
||||
return nil, nil, fmt.Errorf("coverart: empty mbid")
|
||||
if ref.MBID == "" {
|
||||
return nil, nil, ErrNotFound // TheAudioDB is MBID-only
|
||||
}
|
||||
|
||||
var resp struct {
|
||||
@@ -133,7 +135,7 @@ func (p *theAudioDBProvider) FetchArtistArt(ctx context.Context, mbid string) (t
|
||||
StrArtistFanart *string `json:"strArtistFanart"`
|
||||
} `json:"artists"`
|
||||
}
|
||||
if err := p.getJSON(ctx, "artist-mb.php?i="+mbid, &resp); err != nil {
|
||||
if err := p.getJSON(ctx, "artist-mb.php?i="+ref.MBID, &resp); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if len(resp.Artists) == 0 {
|
||||
|
||||
Reference in New Issue
Block a user