feat: rework Lidarr library integration

This commit is contained in:
2026-10-04 20:28:24 -07:00
parent 880c2217b1
commit b3e6f66097
17 changed files with 1839 additions and 127 deletions

View File

@@ -50,18 +50,47 @@ def test_perform_youtube_calls_act_youtube(monkeypatch):
assert result["lidarr_album_id"] is None
def test_perform_lidarr_album_handled(monkeypatch):
monkeypatch.setattr(mf, "act_lidarr_album",
lambda hit, root, search_all, dry_run: True)
def _release(guid="g1"):
return {"guid": guid, "indexerId": 2, "title": "Avril-Under_My_Skin",
"size": 312 * 1024 * 1024, "seeders": 24, "indexer": "Redacted",
"quality": {"quality": {"name": "FLAC"}}}
@pytest.fixture
def in_library(monkeypatch):
"""Lidarr holds the artist and the album."""
monkeypatch.setattr(mf, "ensure_album", lambda album, root, search_all, dry_run: {
"album": {"id": 5}, "album_id": 5, "artist_name": "Avril Lavigne",
"album_title": "Under My Skin", "artist_state": "existing",
"album_state": "existing"})
def test_perform_lidarr_album_offers_choices_by_default(monkeypatch, in_library):
monkeypatch.setattr(mf, "list_releases", lambda album_id, **kw: [_release("a"), _release("b")])
monkeypatch.setattr(mf, "grab_release", lambda *a, **kw: (_ for _ in ()).throw(
AssertionError("must not grab before the user picks")))
hit = make_lidarr_album_hit()
result = actions.perform_fetch(hit, [hit], quality="best", root="/media/music")
assert result["outcome"] == "choices"
assert [c["n"] for c in result["choices"]] == [1, 2]
assert result["pending"] == [_release("a"), _release("b")]
assert result["lidarr_album_id"] == 5
assert result["path"] is None
def test_perform_lidarr_album_fallsthrough_to_youtube(monkeypatch):
monkeypatch.setattr(mf, "act_lidarr_album",
lambda hit, root, search_all, dry_run: False)
def test_perform_lidarr_album_auto_grabs_the_best_release(monkeypatch, in_library):
grabbed = {}
monkeypatch.setattr(mf, "list_releases", lambda album_id, **kw: [_release("best"), _release("b")])
monkeypatch.setattr(mf, "grab_release",
lambda rel, dry_run=False: grabbed.update(guid=rel["guid"]) or True)
hit = make_lidarr_album_hit()
result = actions.perform_fetch(hit, [hit], quality="best", root="/media/music", auto=True)
assert result["outcome"] == "album_grabbed"
assert grabbed["guid"] == "best"
assert not result.get("choices")
def test_perform_lidarr_album_fallsthrough_to_youtube(monkeypatch, in_library):
monkeypatch.setattr(mf, "list_releases", lambda album_id, **kw: [])
yt_calls = {}
monkeypatch.setattr(mf, "act_youtube",
lambda hit, root, quality, dry_run: yt_calls.update(hit=hit))
@@ -70,14 +99,35 @@ def test_perform_lidarr_album_fallsthrough_to_youtube(monkeypatch):
result = actions.perform_fetch(lidarr_hit, [lidarr_hit, yt_hit],
quality="best", root="/media/music")
assert yt_calls["hit"] is yt_hit
assert result["outcome"] == "youtube_fallback"
assert result["path"] == "/media/music/Avril Lavigne/youtube"
def test_perform_lidarr_album_no_release_no_fallback_raises(monkeypatch):
monkeypatch.setattr(mf, "act_lidarr_album",
lambda hit, root, search_all, dry_run: False)
def test_perform_lidarr_album_reports_no_release_without_a_fallback(monkeypatch, in_library):
monkeypatch.setattr(mf, "list_releases", lambda album_id, **kw: [])
hit = make_lidarr_album_hit()
with pytest.raises(RuntimeError):
result = actions.perform_fetch(hit, [hit], quality="best", root="/media/music")
assert result["outcome"] == "no_release"
def test_perform_lidarr_album_skips_youtube_when_not_allowed(monkeypatch, in_library):
monkeypatch.setattr(mf, "list_releases", lambda album_id, **kw: [])
monkeypatch.setattr(mf, "act_youtube", lambda *a, **kw: (_ for _ in ()).throw(
AssertionError("source=lidarr must not use YouTube")))
lidarr_hit = make_lidarr_album_hit()
result = actions.perform_fetch(lidarr_hit, [lidarr_hit, make_yt_hit()],
quality="best", root="/media/music",
allow_youtube=False)
assert result["outcome"] == "no_release"
def test_perform_lidarr_album_raises_when_the_album_is_not_in_lidarr(monkeypatch):
monkeypatch.setattr(mf, "ensure_album", lambda album, root, search_all, dry_run: {
"album": None, "album_id": None, "artist_name": "Avril Lavigne",
"album_title": "Under My Skin", "artist_state": "existing",
"album_state": "missing"})
hit = make_lidarr_album_hit()
with pytest.raises(RuntimeError, match="no album called"):
actions.perform_fetch(hit, [hit], quality="best", root="/media/music")