e1d544f59f
Adds an embedded-art layer to the album cover chain between the sidecar lookup and the external provider chain. Reads ID3v2 APIC, FLAC METADATA_BLOCK_PICTURE, and MP4 covr atoms via the dhowden/tag library (already a dependency for MBID extraction). Whatever Picard or Lidarr embedded into the file at tag time becomes available without any network call. Diagnostic context: file managers (GNOME Files, Dolphin, etc.) generate audio-file thumbnails by reading exactly this picture block. An album that "has no art" in Minstrel but renders a thumbnail in the file manager is the smoking-gun signal that embedded art is present and we were ignoring it. Adds 'embedded' to the chain so those albums get covered without any external provider hit. Chain after this change: sidecar → embedded → MBCAA → TheAudioDB → Deezer → Last.fm → none Embedded beats every external provider for accuracy because it's the canonical art the operator/Picard chose at tag time, not a guess from a remote catalog. Refactors the post-fetch write logic into Enricher.writeAlbumArt so the embedded layer and the provider chain share the same sidecar-then-managed-cache fallback semantics. Behavior identical to before for the provider path.
49 lines
1.3 KiB
Go
49 lines
1.3 KiB
Go
package coverart
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestExtractEmbeddedAlbumArt_NonexistentFile(t *testing.T) {
|
|
_, err := ExtractEmbeddedAlbumArt("/nonexistent/path/track.mp3")
|
|
if err == nil {
|
|
t.Fatal("err = nil, want non-nil for nonexistent file")
|
|
}
|
|
if errors.Is(err, ErrNoEmbeddedArt) {
|
|
t.Errorf("err is ErrNoEmbeddedArt; want a wrapped open error instead")
|
|
}
|
|
}
|
|
|
|
func TestExtractEmbeddedAlbumArt_EmptyFile(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "empty.mp3")
|
|
if err := os.WriteFile(path, []byte{}, 0o644); err != nil {
|
|
t.Fatalf("seed: %v", err)
|
|
}
|
|
_, err := ExtractEmbeddedAlbumArt(path)
|
|
if err == nil {
|
|
t.Fatal("err = nil, want non-nil for empty file (tag.ReadFrom should fail)")
|
|
}
|
|
if errors.Is(err, ErrNoEmbeddedArt) {
|
|
t.Errorf("err is ErrNoEmbeddedArt; want a wrapped tag-read error instead")
|
|
}
|
|
}
|
|
|
|
func TestExtractEmbeddedAlbumArt_NonAudioFile(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "not-audio.mp3")
|
|
if err := os.WriteFile(path, []byte("this is not an audio file"), 0o644); err != nil {
|
|
t.Fatalf("seed: %v", err)
|
|
}
|
|
_, err := ExtractEmbeddedAlbumArt(path)
|
|
if err == nil {
|
|
t.Fatal("err = nil, want non-nil for non-audio bytes")
|
|
}
|
|
if errors.Is(err, ErrNoEmbeddedArt) {
|
|
t.Errorf("err is ErrNoEmbeddedArt; want a wrapped tag-read error instead")
|
|
}
|
|
}
|