fix(import): stop several entries from claiming one request

This commit is contained in:
Steppenstreuner
2026-08-28 21:01:07 +02:00
parent a816dcb27a
commit 60b9e44a11
6 changed files with 280 additions and 52 deletions
+109
View File
@@ -538,3 +538,112 @@ def test_merged_parts_clean_up_nested_source_folders(client):
assert not (base / "A - Sphinx").exists()
assert not (base / "B - Volk").exists()
assert (base / "Cover" / "front.jpg").exists()
def test_letter_indexed_parts_are_one_audiobook(client):
""""Teil A/B/C" and "A - Titel/B - Titel" both describe one story."""
schattenwelt = client.downloads / "175 Schattenwelt-3CD-DE-2015-VOiCE"
for part in ("Teil A", "Teil B", "Teil C"):
d = schattenwelt / part
d.mkdir(parents=True)
(d / "01.mp3").write_bytes(b"")
toteninsel = client.downloads / "100 - Toteninsel"
for part in ("A - Das.Raetsel.der.Sphinx", "B - Das.vergessene.Volk",
"C - Der Fluch der Graeber"):
d = toteninsel / part
d.mkdir(parents=True)
(d / "01.mp3").write_bytes(b"")
(toteninsel / "Cover").mkdir()
(toteninsel / "Cover" / "f.jpg").write_bytes(b"")
items = {i["name"]: i for i in client.get("/api/import/scan").json()["items"]}
assert sorted(items) == ["100 - Toteninsel", "175 Schattenwelt-3CD-DE-2015-VOiCE"]
for item in items.values():
assert item["is_dir"] and len(item["files"]) == 3
# parts stay in A, B, C order
assert [Path(f).parent.name[0] for f in item["files"]] in (
["T", "T", "T"], ["A", "B", "C"],
)
order = [Path(f).parent.name for f in items["175 Schattenwelt-3CD-DE-2015-VOiCE"]["files"]]
assert order == ["Teil A", "Teil B", "Teil C"]
def test_letter_folders_that_are_not_parts_stay_separate(client):
"""Two episodes that happen to start with a letter must not be merged."""
base = client.downloads / "Sammlung"
for name in ("A - Erste Folge", "Zweite Folge"):
d = base / name
d.mkdir(parents=True)
(d / "01.mp3").write_bytes(b"")
(d / "02.mp3").write_bytes(b"")
names = sorted(i["name"] for i in client.get("/api/import/scan").json()["items"])
assert names == ["A - Erste Folge", "Zweite Folge"]
def test_append_to_an_already_imported_audiobook(client):
"""The Toteninsel case: part A got imported, B and C failed. They can be
added afterwards without moving anything back by hand."""
root = client.tmp_path / "library" / "kids"
lib_id = client.post("/api/libraries", json={
"name": "K", "media_type": "audiobook", "root_path": str(root),
"folder_template": "{Title}", "file_template": "{Title}",
}).json()["id"]
req_id = client.post("/api/requests",
json={"library_id": lib_id, "title": "Toteninsel"}).json()["id"]
part_a = client.downloads / "A - Sphinx"
part_a.mkdir()
for i in (1, 2, 3):
(part_a / f"{i:02d}.mp3").write_bytes(b"")
client.post("/api/import", json={"items": [{
"path": str(part_a), "is_dir": True,
"files": [str(f) for f in sorted(part_a.iterdir())], "request_id": req_id,
}]})
imported = client.get("/api/requests", params={"status": "imported"}).json()[0]
assert len(list(Path(imported["imported_path"]).iterdir())) == 3
# B and C arrive later
later = []
for part in ("B - Volk", "C - Graeber"):
d = client.downloads / part
d.mkdir()
for i in (1, 2):
f = d / f"{i:02d}.mp3"
f.write_bytes(b"")
later.append(str(f))
res = client.post("/api/import", json={"items": [{
"path": str(client.downloads / "B - Volk"), "is_dir": True,
"files": later, "request_id": req_id, "append": True,
}]}).json()["results"][0]
assert res["ok"] and res["appended"]
files = sorted(p.name for p in Path(res["dest"]).iterdir())
assert files == [f"Toteninsel - Part 0{i}.mp3" for i in range(1, 8)]
def test_append_without_the_flag_is_still_refused(client):
lib_id = client.post("/api/libraries", json={
"name": "K", "media_type": "audiobook", "root_path": str(client.tmp_path / "k"),
}).json()["id"]
req_id = client.post("/api/requests",
json={"library_id": lib_id, "title": "X"}).json()["id"]
folder = client.downloads / "first"
folder.mkdir()
(folder / "a.mp3").write_bytes(b"")
(folder / "b.mp3").write_bytes(b"")
client.post("/api/import", json={"items": [{
"path": str(folder), "is_dir": True,
"files": [str(folder / "a.mp3"), str(folder / "b.mp3")], "request_id": req_id,
}]})
second = client.downloads / "second"
second.mkdir()
(second / "c.mp3").write_bytes(b"")
res = client.post("/api/import", json={"items": [{
"path": str(second), "is_dir": False,
"files": [str(second / "c.mp3")], "request_id": req_id,
}]}).json()["results"][0]
assert not res["ok"]
assert "bereits importiert" in res["error"]
assert (second / "c.mp3").exists()