feat: use Cover Art Archive for albums with MusicBrainz IDs #27

Merged
deluan merged 9 commits from feat/cover-art-archive into main 2026-03-20 18:34:11 -06:00
3 changed files with 10 additions and 10 deletions
Showing only changes of commit 6ed2c2ce45 - Show all commits
+6 -8
View File
4
@@ -10,11 +10,6 @@ import (
"github.com/navidrome/navidrome/plugins/pdk/go/scrobbler"
)
// Configuration key for uguu.se image hosting
const uguuEnabledKey = "uguuenabled"
const caaEnabledKey = "caaenabled"
// headCoverArt sends a HEAD request to the given CAA URL without following redirects.
// Returns the Location header value on 307 (image exists), or "" otherwise.
func headCoverArt(url string) string {
@@ -22,6 +17,7 @@ func headCoverArt(url string) string {
Method: "HEAD",
URL: url,
NoFollowRedirects: true,
TimeoutMs: 5000, // 5s timeout to avoid blocking NowPlaying
})
if err != nil {
pdk.Log(pdk.LogDebug, fmt.Sprintf("CAA HEAD request failed for %s: %v", url, err))
@@ -37,9 +33,11 @@ func headCoverArt(url string) string {
return location
}
// Cache TTLs for cover art lookups
const (
caaCacheTTLHit int64 = 24 * 60 * 60 // 24 hours for resolved artwork
caaCacheTTLMiss int64 = 4 * 60 * 60 // 4 hours for misses
caaCacheTTLHit int64 = 24 * 60 * 60 // 24 hours for resolved CAA artwork
caaCacheTTLMiss int64 = 4 * 60 * 60 // 4 hours for CAA misses
uguuCacheTTL int64 = 9000 // ~2.5 hours for uguu.se uploads
)
// getImageViaCoverArt checks the Cover Art Archive for album artwork.
@@ -153,7 +151,7 @@ func getImageViaUguu(username, trackID string) string {
return ""
}
_ = host.CacheSetString(cacheKey, url, 9000)
_ = host.CacheSetString(cacheKey, url, uguuCacheTTL)
return url
}
+2 -2
View File
@@ -134,11 +134,11 @@ var _ = Describe("getImageURL", func() {
})).Return(&host.HTTPResponse{StatusCode: 200, Body: []byte(`{"success":true,"files":[{"url":"https://a.uguu.se/uploaded.jpg"}]}`)}, nil)
// Mock cache set
host.CacheMock.On("SetString", "uguu.artwork.track1", "https://a.uguu.se/uploaded.jpg", int64(9000)).Return(nil)
host.CacheMock.On("SetString", "uguu.artwork.track1", "https://a.uguu.se/uploaded.jpg", uguuCacheTTL).Return(nil)
url := getImageURL("testuser", scrobbler.TrackInfo{ID: "track1"})
Expect(url).To(Equal("https://a.uguu.se/uploaded.jpg"))
host.CacheMock.AssertCalled(GinkgoT(), "SetString", "uguu.artwork.track1", "https://a.uguu.se/uploaded.jpg", int64(9000))
host.CacheMock.AssertCalled(GinkgoT(), "SetString", "uguu.artwork.track1", "https://a.uguu.se/uploaded.jpg", uguuCacheTTL)
})
It("returns empty when artwork data fetch fails", func() {
+2
View File
@@ -29,6 +29,8 @@ const (
usersKey = "users"
activityNameKey = "activityname"
spotifyLinksKey = "spotifylinks"
caaEnabledKey = "caaenabled"
uguuEnabledKey = "uguuenabled"
gemini-code-assist[bot] commented 2026-03-20 18:24:36 -06:00 (Migrated from github.com)
Review

medium

These constants are only used in coverart.go. To improve code organization and maintainability, it's best to define constants in the file where they are used. Please consider moving caaEnabledKey and uguuEnabledKey to coverart.go. This would also be consistent with how uguuEnabledKey was defined before this change.

![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg) These constants are only used in `coverart.go`. To improve code organization and maintainability, it's best to define constants in the file where they are used. Please consider moving `caaEnabledKey` and `uguuEnabledKey` to `coverart.go`. This would also be consistent with how `uguuEnabledKey` was defined before this change.
deluan commented 2026-03-20 18:33:16 -06:00 (Migrated from github.com)
Review

Intentional — all config keys are grouped together in main.go for discoverability. Having them scattered across files makes it harder to audit which config keys exist.

Intentional — all config keys are grouped together in `main.go` for discoverability. Having them scattered across files makes it harder to audit which config keys exist.
)
const (