Skip to content

feat: scrape album editorial notes (closes #8)#9

Merged
deluan merged 5 commits into
mainfrom
more-album-info
Apr 27, 2026
Merged

feat: scrape album editorial notes (closes #8)#9
deluan merged 5 commits into
mainfrom
more-album-info

Conversation

@deluan
Copy link
Copy Markdown
Member

@deluan deluan commented Apr 10, 2026

Summary

  • Adds a new GetAlbumInfo capability that returns the Apple Music album URL and editorial notes for an album, closing [Feature Request] Scrape Album details #8.
  • Splits main.go (1109 lines) into four domain-focused files (main.go, helpers.go, artist.go, album.go) with a matching test-file split, keeping all capability methods in main.go so a reader immediately sees what the plugin implements.

Details

Album info capability

The plugin now implements metadata.AlbumInfoProvider. Gated behind a new enable_album_info manifest flag (default true). The Apple Music URL comes from the iTunes Lookup API's collectionViewUrl field; editorial notes are scraped from the serialized-server-data script block on the album page at data[0].data.sections[*].items[*].modalPresentationDescriptor.paragraphText.

Caching: dedicated album_info:{artist}:{album} KVStore key caches the {url, description} pair with the configured TTL. On cache hit, neither the iTunes Lookup KV read nor the album page fetch runs. Cached only when at least one country fetch succeeds — all-failures path is not cached so the next call retries.

Country fallback: reuses the existing pattern — iterates configured countries, rewriting the URL's country segment, until editorial notes are found. Empty description (album has no notes) is a valid cacheable result.

Non-obvious finding: Apple's JSON-LD description field on album pages is always a generic "Listen to X by Y on Apple Music..." string, even for famous albums. Real editorial notes only live in the embedded server data block.

Version bumped 0.1.10.2.0.

File split

main.go grew past 1000 lines. Split by domain:

File Purpose
main.go Entry point, constants, interface assertions, all seven Get* capability methods
helpers.go Shared infrastructure: config, KVStore, HTTP, image URL rewriting, normalizeName
artist.go Artist resolution, JSON-LD parsing, placeholder detection, similar-artists scraping, fetchArtistPage
album.go Album resolution, iTunes lookup matching, serialized-server-data scraping, fetchAlbumDescription

Test files mirror the split. Shared test helpers (resetMocks, mustMarshal, setupTaylorSwiftCache) live in plugin_suite_test.go alongside a single package-level BeforeEach(resetMocks).

Test plan

  • go test -race ./... — 112/112 Ginkgo specs pass
  • go vet ./... — clean
  • make packageapple-music.ndp builds cleanly (1.1 MB, unchanged size)
  • Manual smoke test: install apple-music.ndp into a local Navidrome, enable enable_album_info, trigger album metadata refresh on a few albums with known editorial notes (e.g. Taylor Swift's Lover, The Beatles' Abbey Road), and confirm descriptions + Apple Music URL appear in the album detail view.
  • Verify country fallback by configuring countries = "us,br,fi" and requesting an album only available in a non-US storefront (e.g. the issue's example, Karnivool's IN VERSES at fi).

deluan added 2 commits April 10, 2026 13:09
Split the 1109-line main.go into four domain-focused files:
main.go keeps the entry point and all capability methods (acts as
the plugin's manifest of what it implements), helpers.go holds
shared infrastructure (config, KVStore, HTTP, image URL rewriting),
artist.go contains artist resolution and page scraping, and album.go
contains album resolution and editorial notes scraping.

main_test.go is split similarly, with shared test helpers
(resetMocks, mustMarshal, setupTaylorSwiftCache) colocated with the
suite entry point in plugin_suite_test.go. A single package-level
BeforeEach(resetMocks) replaces the per-Describe wiring.
Copilot AI review requested due to automatic review settings April 10, 2026 18:09
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 10, 2026

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

Built from 97b4292 on 2026-04-27T21:10:55Z

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds an Album Info capability to return Apple Music album URLs plus scraped editorial notes, and refactors the codebase into smaller domain-focused files with matching test splits.

Changes:

  • Implement GetAlbumInfo (gated by enable_album_info) with caching and country fallback for scraping editorial notes.
  • Refactor: split the previous large main.go into helpers.go, artist.go, and album.go (and split tests accordingly).
  • Update plugin docs and manifest (new config flag, version bump to 0.2.0).

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
README.md Documents the new Album Info capability and data sources.
manifest.json Bumps version and adds enable_album_info config/UI control.
main.go Adds metadata.AlbumInfoProvider + GetAlbumInfo; routes album images through shared album match resolver.
helpers.go Centralizes config/KV/HTTP helpers and image URL rewriting.
artist.go Moves artist resolution and artist-page scraping/parsing logic out of main.go.
album.go Adds album match resolution (artwork + canonical URL) and album editorial-notes scraping/parsing.
plugin_suite_test.go Introduces suite-wide mock reset + shared mustMarshal.
main_test.go Keeps capability-method tests; adds GetAlbumInfo specs.
helpers_test.go Adds unit tests for shared helper functions.
artist_test.go Adds unit tests for artist resolution and parsing helpers.
album_test.go Adds unit tests for album matching, URL normalization, and editorial-notes parsing.

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

Comment thread album.go Outdated
Comment thread album.go Outdated
deluan added 3 commits April 10, 2026 15:35
The cachedAlbumMatch struct added CollectionViewURL in 0.2.0, but
pre-0.2.0 entries stored only artworkUrl. After upgrade, those
entries unmarshal with CollectionViewURL == "", causing GetAlbumInfo
to return nil until the cache TTL expires. Treat such entries as a
cache miss so the URL gets populated on re-fetch.

Also relax the post-lookup check: accept a match when either
ArtworkURL100 or CollectionViewURL is populated, instead of requiring
artwork. GetAlbumInfo doesn't need artwork, and this guards against
Apple returning URL-only entries in the future.
@deluan deluan merged commit 9e07bae into main Apr 27, 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