Implements Task 8: artist detail page (local albums + found-missing
with ignore buttons), ignored-releases archive with restore, and POST
handlers toggling ignore flags and ignore_singles. Adds ErrArtistNotFound
sentinel so callers can distinguish missing artists, and wires routes via
the enhanced ServeMux path wildcard.
Replace compute-only run() with an immediate sync+scan followed by a
ticker-driven periodic loop, add the sync.interval config field (default
6h) with defaults and validation, and add tests for the scheduling logic.
Add ResolveArtistMBID to query the MB artist search endpoint and return the
first matching artist ID, with httptest-backed tests for match, no-match,
HTTP error, and invalid-JSON paths.
Additive migration 008 adds an mbid column to artist_settings, extend the
ArtistSettings struct and persistence functions (SaveArtistSettings,
GetArtistSettings, GetAllArtistSettings, UpdateArtistSettings) to carry the
MusicBrainz ID, and add round-trip tests covering empty and set MBID values.
Implements ScanArtist/ScanAll in internal/scanner loading local/external
releases via the database layer with ctx-cancellation checks, plus a
compute-only run() hook that logs missing-release counts. Add table-driven
tests using in-memory SQLite fixtures.
Add FindMissingReleases and MissingRelease to internal/scanner: skips
IsIgnored external releases, scopes matches per ArtistID, and reports
external releases with no local album above the fuzzy threshold.
Creates internal/musicbrainz/sync.go with SyncArtistDiscography function
that orchestrates the full flow: cache check via GetCachedReleases, fetch
from MusicBrainz API on cache miss, filter via FilterReleaseGroups, and
upsert into external_releases via database.SaveExternalRelease. Includes
SyncArtistDiscographyWithFilter variant for per-artist type filtering. All
functions support context cancellation. 14 new tests cover cache hit/miss,
status/type filtering, context cancellation, idempotency, API errors, and
full XML pipeline integration.
- Add GetArtistReleaseGroups method with pagination support
- Implement status filtering (exclude Bootleg/Promotion/Pseudo-Release)
- Implement type filtering (include Album/Single/EP/Compilation)
- Add per-artist type filtering hooks (ArtistTypeFilter) for Web UI
- Add NormalizeString and NormalizeArtistName for fuzzy matching prep
- Add ReleaseGroup.ToExternalRelease conversion method
- Write comprehensive table-driven tests for filtering logic
- Write tests for normalization functions (18 cases)
- Write tests for GetArtistReleaseGroups (success, pagination, empty, errors)
- All tests pass (47 total across project), go vet clean
Add the Navidrome client module that connects to a Navidrome server via
the Subsonic API, fetches artist and album data, and syncs it into the
local SQLite database.
- Add go-subsonic dependency for Subsonic API communication
- Create internal/navidrome/client.go with NavidromeClient wrapper
- NewClient constructor with token-based auth
- Ping health check with HTTP status validation
- GetArtists fetches all artists via getArtists endpoint
- GetArtistAlbums fetches albums per artist via getArtist endpoint
- Create internal/navidrome/sync.go with sync orchestration
- SyncArtists upserts artists into artist_settings table
- SyncAlbums fetches and stores albums for monitored artists
- Add local_albums table (migration 003) with FK to artist_settings
- Add LocalAlbum CRUD operations in internal/database/local_albums.go
- Full test coverage: 19 tests across client and sync packages
- All tests pass, go vet and go fmt clean