Skip to content

Add GetAlbumImages capability and negative caching - #2

Merged
deluan merged 16 commits into
mainfrom
feat/album-images-and-negative-caching
Mar 15, 2026
Merged

Add GetAlbumImages capability and negative caching#2
deluan merged 16 commits into
mainfrom
feat/album-images-and-negative-caching

Conversation

@deluan

@deluan deluan commented Mar 15, 2026

Copy link
Copy Markdown
Member

Summary

  • GetAlbumImages capability: New AlbumImagesProvider implementation that returns album artwork in 300/600/1000px sizes via the iTunes Lookup API (disabled by default)
  • Negative caching: Cache "not found" results with a 2-hour TTL for both artist ID resolution and album artwork lookups, avoiding repeated API calls for missing data
  • Codebase improvements: Extract httpGetJSON/buildImageList/normalizeName helpers, add warn log on KVStore errors, normalize error logging across capability methods

Album matching strategy

Uses the iTunes Lookup API (/lookup?id={artistID}&entity=album) instead of the Search API, which is far more reliable. Matches album names with a multi-pass fuzzy strategy:

  1. Exact match on full normalized name
  2. Base name match (strip decorations at (, [, -, : delimiters)
  3. Containment match (one base name contains the other, min 4 chars)

This handles real-world mismatches like:

  • "Dark Side of the Moon (2020) - 7.1 Multichannel...""The Dark Side of the Moon"
  • "Versions""Versions - Single"
  • "COWBOY BEBOP (Original Motion Picture Soundtrack)""Cowboy Bebop (Original Soundtrack)"

Test plan

  • All 81 tests pass (go test -v -count=1 ./...)
  • make package builds successfully
  • Verify album artwork appears for various artists (Taylor Swift, Pink Floyd, The Roots, Thievery Corporation)
  • Verify negative caching: search for non-existent album, confirm no repeated API calls in logs
  • Verify enable_album_images toggle works (default: disabled)

deluan added 15 commits March 14, 2026 19:10
Cache ArtistID=0 with 2-hour TTL when iTunes Search returns no match.
On cache hit of ArtistID=0, return error immediately without API call.
Add itunesAlbumSearchResponse, itunesAlbumResult, cachedAlbumArtwork
types and findBestAlbumMatch function that filters by wrapperType=collection
and matches both album name and artist name case-insensitively.
Searches iTunes API for album artwork by artist+album name, caches
results with standard TTL. Caches 'not found' with 2-hour TTL.
Implement AlbumImagesProvider interface to return album artwork in
300/600/1000px sizes from iTunes Search API. Add enable_album_images
config toggle to manifest with uiSchema placement.
- Extract duplicated image size generation loop into buildImageList()
- Cache negative result when album match has no artwork URL
The function is a generic string normalizer (lowercase + trim) used for
both artist and album names. The new name reflects its actual scope.
- Remove unused struct fields (ArtistType, ArtistLinkURL, PrimaryGenre)
- Add warn log to kvGet on KVStore errors (was silently swallowed)
- Remove inconsistent error logging from GetArtistBiography and
  GetSimilarArtists (lower-level functions already log)
- Pass wantField to parsePage to skip unnecessary parsing (avoids
  60KB regex scan when only biography/image is needed)
Add GetAlbumImages capability to features, capabilities table, flow,
and data sources. Document negative caching behavior (2-hour TTL for
"not found" results).
The iTunes Search API often fails to find albums when searching with
combined "artist album" terms (e.g., "The Roots Phrenology" returns 0
results). Switch to using the Lookup API with the artist ID
(itunes.apple.com/lookup?id={artistID}&entity=album) which reliably
returns all albums for a given artist.
iTunes often adds suffixes like " - Single", " - EP", or
" (Deluxe Edition)" to collection names. Add a two-pass matching
strategy: first try exact match, then try after stripping common
suffixes from both the iTunes name and the input album name.

Fixes matching for albums like "Versions" which iTunes lists as
"Versions - Single".
Replace the suffix-stripping approach with a more robust multi-pass
album matching strategy:

  Pass 1: exact match on full normalized name
  Pass 2: exact match on base names (truncated at delimiters like
          " (", " [", " - ", ": " to strip decorations)
  Pass 3: containment match (one base name contains the other,
          with a minimum length of 4 to prevent false positives)

This handles real-world mismatches like:
- User: "Dark Side of the Moon (2020) - 7.1 Multichannel..."
  iTunes: "The Dark Side of the Moon"
- User: "Pink Floyd at Pompeii: MCMLXXII"
  iTunes: "Pink Floyd at Pompeii - MCMLXXII (2025 Mix)"
- User: "Versions", iTunes: "Versions - Single"
- User: "1989", iTunes: "1989 (Deluxe Edition)"
Since albums are fetched via the Lookup API scoped to a specific artist
ID, requiring an exact artist name match on the results is redundant
and causes failures when iTunes uses a different artist name than the
user's library (e.g., Japanese "シートベルツ" vs English "SEAT BELTS",
or "Yoko Kanno & SEAT BELTS" vs "SEAT BELTS").

The artist ID already guarantees the albums belong to the correct
artist, so only album name matching is needed.
Album Images is a new capability; default to disabled so existing
users are not affected until they explicitly opt in.
…date negative cache

- Extract httpGetJSON helper to eliminate repeated fetch+status+unmarshal
  pattern across resolveArtistID, resolveAlbumArtwork, GetArtistTopSongs
- Revert parsePage field-selective optimization: always parse all fields
  so cached page data is complete for any subsequent capability request
  (prevents re-fetching the same HTML page for different capabilities)
- Consolidate duplicate negative-cache write in resolveAlbumArtwork
These tests rely on resolveArtistID hitting the KVStore cache before
calling getCountries(). Add a .Maybe() mock for configCountries so
the tests don't break if resolveArtistID's internal ordering changes.
Copilot AI review requested due to automatic review settings March 15, 2026 01:24
@github-actions

github-actions Bot commented Mar 15, 2026

Copy link
Copy Markdown
Contributor

Download the plugin for this PR: apple-music.zip

Built from 37582bb on 2026-03-15T01:31:22Z

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds optional album artwork support to the Apple Music metadata agent and introduces negative caching to reduce repeated iTunes API calls for missing artists/albums.

Changes:

  • Add GetAlbumImages capability (disabled by default) backed by iTunes Lookup API album results.
  • Implement negative caching (2-hour TTL) for unresolved artist IDs and missing album artwork.
  • Refactor shared helpers (httpGetJSON, buildImageList, normalizeName) and improve KVStore error logging.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
manifest.json Adds enable_album_images config and exposes it in the capabilities UI.
main.go Implements album artwork lookup + negative caching, plus helper extraction/logging tweaks.
main_test.go Adds tests for album matching, negative caching behavior, and GetAlbumImages.
README.md Updates documented feature set and behavior to include album artwork + negative caching.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md Outdated
Comment thread main_test.go Outdated
Comment thread main.go Outdated
Comment thread README.md Outdated
Comment thread README.md
- README: GetAlbumImages uses Lookup API, not Search API
- README: update flow and data sources to reflect actual lookup strategy
- Test: remove misleading "artist name" from test name
- Docstring: extractBaseName truncates at each delimiter, not first
@deluan
deluan merged commit 3afab77 into main Mar 15, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants