Commit Graph

44 Commits

Author SHA1 Message Date
6e6bec7a0d Plan playlists + profile hardening (5 TDD tasks)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 23:42:13 -07:00
a24c894c61 Add design spec: YouTube playlists + Lidarr profile hardening
Playlists download each track to per-track artist folders (CLI + REST API,
one job per playlist, done if >=1 track succeeds). Profile selection by name
with env overrides (LIDARR_METADATA_PROFILE/LIDARR_QUALITY_PROFILE).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 23:38:06 -07:00
a424fbfd2f Merge feat/rest-api: REST API + smarter Lidarr matching
- FastAPI async job-based REST API wrapping musicfetch (X-API-Key auth,
  Siri-friendly messages, dockerized for the Lidarr stack).
- Smarter Lidarr search: MusicBrainz track->album resolution + exact
  mbid: lookup (prefers own-artist studio album), no fuzzy ranking.
- Bug fixes from live testing: single first-artist tag (no doubling).
2026-06-08 23:31:41 -07:00
b99e5eb9cb fix(lidarr): prefer own-artist studio album over various-artists comps
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 23:30:15 -07:00
1661cb1742 refactor(lidarr): drop now-unused Timeout import 2026-06-08 23:24:59 -07:00
18f72a5626 feat(lidarr): exact MBID album lookup via MusicBrainz resolution
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 23:22:11 -07:00
babbd84fda feat(lidarr): MusicBrainz track-to-album resolver
Add musicbrainz_best_album() that resolves an artist+track pair to its
best studio album via the MusicBrainz search API, with a 1 req/sec
courtesy rate-limiter. Prefers plain studio albums over compilations,
singles, and live releases; falls back to any release group when no
studio album is found. Never raises — returns None on any failure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 23:17:43 -07:00
b0e3ce6e6c feat(lidarr): add Artist - Track query splitter 2026-06-08 21:08:02 -07:00
45121dd807 Plan smarter Lidarr matching via exact MBID lookup
Drop fuzzy difflib scoring: MusicBrainz resolves track->album release-group
MBID, Lidarr album/lookup?term=mbid:<id> returns the exact album. Live-verified
against the user's Lidarr.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 21:06:39 -07:00
6687a5a0fc Add design spec for smarter Lidarr matching
Scored best-first lidarr_search with MusicBrainz track->album resolution,
difflib scoring, preserved YouTube fallback. Fixes noninteractive API
picking junk (Pignickel) over the real album.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 20:51:15 -07:00
425a973d85 fix: write single first-artist tag, not doubled/multi-artist
Live end-to-end test surfaced two bugs in youtube tagging:
- `--replace-in-metadata artist .* NAME` matched twice and doubled the
  artist tag (e.g. "SLVMLORDSLVMLORD"). Anchor with ^.*$ to match once.
- Use only the first artist when several are present (SLVMLORD, not
  "SLVMLORD, Travis Bradley, ...") for both the embedded tag and the
  spoken/echoed API messages.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 20:39:03 -07:00
9984c162c6 fix(server): return {message} body for request validation errors
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 20:27:00 -07:00
eecf0836f7 fix(server): make .dockerignore effective at repo root, pin yt-dlp in requirements
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 20:23:37 -07:00
809de44e2e feat(server): Dockerfile and compose for the Lidarr stack
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 20:21:14 -07:00
5b6986e01c test(server): cover validation 422s and pick-None 404; tighten message assert
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 20:18:54 -07:00
d4c1b18e58 feat(server): /fetch and /jobs endpoints with async download jobs
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 20:15:28 -07:00
49a45e6270 feat(server): FastAPI app with API-key auth and health check
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 20:09:50 -07:00
257ed5e0a5 fix(server): announce track title not album in messages; cover error paths
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 20:07:09 -07:00
f4ffd23ed8 docs: REST API usage and Siri Shortcuts walkthrough
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 20:02:51 -07:00
9912eb48a4 feat(server): action dispatch with structured result and messages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 20:02:18 -07:00
09a0d7e682 fix(server): harden job eviction and worker against missing job id
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 19:59:31 -07:00
35df01f08e feat(server): in-memory async job store with thread-pool worker
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 19:55:57 -07:00
c46ff2ff1a refactor(server): register loaded module in sys.modules, add __all__
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 19:54:37 -07:00
ad660afae3 feat(server): load musicfetch binary as importable module
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 19:49:18 -07:00
11a57bfa67 Add implementation plan for MusicFetch REST API
TDD task breakdown: module loader, job store, action dispatch, FastAPI
auth/endpoints, Docker/compose, README + Siri Shortcuts walkthrough.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 19:46:13 -07:00
033bc00ccc Add design spec for MusicFetch REST API
Async job-based HTTP wrapper around the musicfetch binary, dockerized for the
Lidarr stack, X-API-Key auth, Siri-friendly human messages, port via
MUSICFETCH_PORT (default 6769).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 19:42:17 -07:00
9fd4c8585b Rewrite musicfetch as v2: dual-source search with interactive picker
Accept free-form queries (artist/album/title and combos) instead of strict
"Artist - Track". Search Lidarr and YouTube Music concurrently, present a
unified rich picker with bold keyword matching, and act on the chosen hit.

- Normalize results via a Hit dataclass across both sources
- Lidarr: /api/v1/search (album+artist) with album/artist lookup fallback
- YouTube: ytmusicapi for accurate metadata + music.youtube.com URLs,
  yt-dlp scrape fallback; tag overrides from the chosen hit
- Lidarr album pick adds artist+album monitored, runs interactive release
  search, and falls through to top YouTube hit when no indexer release exists
- argparse CLI: -n/--noninteractive, -s/--ytsearch, -d/--dry-run,
  -q/--quality, --limit, --lidarr-only/--yt-only, -o/--root, --search-all
- Config via LIDARR_URL / LIDARR_API_KEY / MUSICFETCH_ROOT env vars
- Update README; add .gitignore for __pycache__

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 19:30:47 -07:00
51871fd296 Additional tweaks to search_artist function. 2025-06-12 16:28:23 -07:00
0cfee8205c Command Line Arguments added to musicfetch script
--debug for debug mode
--search-all will search all music sources as soon as the artist is added to Lidarr. The default behavior is to not search all sources.
2025-06-12 16:24:44 -07:00
5d1a494e77 oops, wrong license before 2025-06-09 17:10:05 -07:00
35ff6c5dcc updated README 2025-06-09 17:09:28 -07:00
61d45301da updated readme 2025-06-09 16:59:16 -07:00
966a823f09 updated README 2025-06-09 16:58:47 -07:00
9d41f4dc33 updated README 2025-06-09 16:57:48 -07:00
36553fa766 updated README 2025-06-09 16:57:10 -07:00
255aae6459 Search functions now have verbosity 2025-06-09 15:37:57 -07:00
dd42d924ef Updates to API key input 2025-06-09 14:24:23 -07:00
2751e65038 Update musicfetch
Specify API key by environment variable instead of in plaintext
2025-06-09 21:20:31 +00:00
6110146908 Update README.md 2025-06-09 21:11:28 +00:00
c2fbc08c3b New Readme 2025-06-09 14:09:03 -07:00
7522a541d4 Timeout search to yt-dlp requires ytsearch: when searching via name and
not URL
2025-06-09 14:03:06 -07:00
d186e32c03 For Lidarr searches, implemented 15 sec timeout before falling back to yt-dlp 2025-06-09 13:33:32 -07:00
6810c0ecbb initial commit 2025-06-09 13:29:52 -07:00
5af040e3fd Initial commit 2025-06-09 20:25:03 +00:00