3 Commits

Author SHA1 Message Date
bvandeusen f6975cfad3 fix(tracks): rewrite RemoveTrack — direct os.Remove + optional Lidarr unmonitor
Replaces commit 50a231f's wrong-shape Lidarr-routed delete. The previous
design called lidarrquarantine.DeleteViaLidarr for Lidarr-managed tracks,
which deletes the entire **album** in Lidarr (Lidarr is album-granular,
no per-track delete API) — silently dropping sibling tracks the operator
didn't ask to remove.

New shape per spec revision 723eee9:
- Always: os.Remove + DB delete + cascade through Minstrel.
- When unmonitor=true AND track has mbid: call new Lidarr.UnmonitorTrack
  primitive so Lidarr won't replace. Failure is non-fatal — file is
  already gone, DB consistent; the lidarrUnmonitorFailed bool flows to
  the wire response so the UI can surface a follow-up "unmonitor
  manually" toast.

Service signature changes from `(trackID, adminID) → (delAlbum, delArtist, err)`
to `(trackID, adminID, unmonitor) → (delAlbum, delArtist, lidarrFailed, err)`.

Adds Lidarr.UnmonitorTrack with full three-step API walk:
  1. GET /api/v1/album?foreignAlbumId={mbid} → Lidarr's internal album id
  2. GET /api/v1/track?albumId={id} → match track by foreignTrackId
  3. PUT /api/v1/track/monitor with {trackIds:[id], monitored:false}

Refactors post() into a shared bodyRequest() so put() reuses the same
status-code → typed-error mapping. The album mbid is captured *before*
the cascade-delete transaction — DeleteAlbumIfEmpty may remove the
album row, after which a post-commit GetAlbumByID returns ErrNoRows
and the unmonitor walk would have nothing to walk against.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 22:35:34 -04:00
bvandeusen ebff8f69a0 fix(lidarr): address review findings on HTTP client
- Add ArtistMBID/AlbumMBID to LookupResult so handlers can build the
  full lidarr_requests row from album/track lookups (parent MBID is
  needed for the AddAlbum API call and for the schema's NOT NULL
  lidarr_artist_mbid)
- Trim trailing slash on BaseURL before joining paths to avoid
  double-slash URLs when operators enter "http://lidarr.lan/"
- Check json.Marshal errors in AddArtist/AddAlbum
- Extract lidarrImage as a named unexported type instead of repeating
  the anonymous struct three times
- Add NewClient(baseURL, apiKey) constructor with 30s default timeout
- Add ErrLookupFailed test coverage for the 4xx-non-auth branch on
  both get and post helpers
- Rename TestListRootFolders_BadJSON -> _NullBody (it tests null,
  not malformed); add a real malformed-JSON test
- Defensive separator guard on LookupAlbum.Secondary so an empty
  ArtistName doesn't produce a leading " · "

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 16:26:23 -04:00
bvandeusen a43fa09a04 feat(lidarr): typed HTTP client for v1 API (lookup, add, profiles, ping)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 15:25:10 -04:00