Rework Curator into a Jellyfin-first library manager
This commit is contained in:
+93
-10
@@ -203,22 +203,21 @@ class TestPoolManagement:
|
||||
source = tmp_path / "raw.mkv"
|
||||
source.write_bytes(b"x" * 10)
|
||||
|
||||
movie = file_manager.import_movie(source, "Matrix", "https://csfd.cz/film/1")
|
||||
movie = file_manager.import_movie(source, "Matrix")
|
||||
|
||||
assert movie.file_path == tmp_path / "pool" / "Filmy" / "Matrix.mkv"
|
||||
assert source.exists() # non-destructive copy
|
||||
assert movie.title == "Matrix"
|
||||
assert movie.csfd_link == "https://csfd.cz/film/1"
|
||||
assert file_manager.index.get(movie.file_path) is not None
|
||||
|
||||
def test_statistics_aggregates_pool(self, file_manager, tmp_path):
|
||||
file_manager.set_pool_dir(tmp_path / "pool")
|
||||
(tmp_path / "a.mkv").write_bytes(b"x" * 100)
|
||||
(tmp_path / "b.mkv").write_bytes(b"y" * 50)
|
||||
a = file_manager.import_movie(tmp_path / "a.mkv", "A", "https://csfd/1")
|
||||
a = file_manager.import_movie(tmp_path / "a.mkv", "A")
|
||||
a.add_tag("Žánr/Akční")
|
||||
a.add_tag("Žánr/Sci-Fi")
|
||||
a.csfd_cache = {"rating": 90}
|
||||
a.meta = {"rating": 90}
|
||||
a.save_metadata()
|
||||
b = file_manager.import_movie(tmp_path / "b.mkv", "B")
|
||||
b.add_tag("Žánr/Akční")
|
||||
@@ -226,7 +225,7 @@ class TestPoolManagement:
|
||||
s = file_manager.statistics()
|
||||
assert s["count"] == 2
|
||||
assert s["total_size"] == 150
|
||||
assert s["with_csfd"] == 1 and s["without_csfd"] == 1
|
||||
assert s["with_nfo"] == 1 and s["without_nfo"] == 1
|
||||
assert s["untagged"] == 0
|
||||
assert s["avg_rating"] == 90
|
||||
# Akční on both movies → count 2, sorted first
|
||||
@@ -319,7 +318,7 @@ class TestPoolManagement:
|
||||
old_path = first.file_path
|
||||
|
||||
second = file_manager.import_movie(
|
||||
tmp_path / "b.mkv", "Matrix", csfd_link="x", on_conflict="replace")
|
||||
tmp_path / "b.mkv", "Matrix", on_conflict="replace")
|
||||
|
||||
assert second.file_path.name == "Matrix.mkv"
|
||||
assert second.file_path == old_path # same name reused
|
||||
@@ -328,7 +327,6 @@ class TestPoolManagement:
|
||||
# index record reflects the new import (fresh metadata, old tags dropped)
|
||||
record = file_manager.index.get(second.file_path)
|
||||
assert record is not None
|
||||
assert record["csfd_link"] == "x"
|
||||
assert record["tags"] == []
|
||||
assert second.tags == []
|
||||
|
||||
@@ -419,6 +417,91 @@ class TestPoolManagement:
|
||||
assert movie.file_path.name == "Matrix (1999).mkv"
|
||||
assert movie.title == "Matrix" # clean title, no year
|
||||
|
||||
def test_import_movie_with_tmdb_id_names_for_jellyfin(self, file_manager, tmp_path):
|
||||
file_manager.set_pool_dir(tmp_path / "pool")
|
||||
(tmp_path / "raw.mkv").write_bytes(b"x")
|
||||
|
||||
movie = file_manager.import_movie(
|
||||
tmp_path / "raw.mkv", "Matrix", year=1999, tmdb_id=603)
|
||||
|
||||
assert movie.file_path.name == "Matrix (1999) [tmdbid-603].mkv"
|
||||
assert movie.title == "Matrix" # clean title, no year/id
|
||||
|
||||
def test_import_into_named_library(self, file_manager, tmp_path):
|
||||
file_manager.set_pool_dir(tmp_path / "pool")
|
||||
file_manager.set_movie_libraries(["Filmy", "Kids"])
|
||||
(tmp_path / "a.mkv").write_bytes(b"x")
|
||||
|
||||
movie = file_manager.import_movie(
|
||||
tmp_path / "a.mkv", "Auta", year=2006, tmdb_id=920, library="Kids")
|
||||
|
||||
assert movie.file_path == tmp_path / "pool" / "Kids" / "Auta (2006) [tmdbid-920].mkv"
|
||||
assert file_manager.library_of(movie) == "Kids"
|
||||
|
||||
def test_move_to_library_reindexes(self, file_manager, tmp_path):
|
||||
file_manager.set_pool_dir(tmp_path / "pool")
|
||||
file_manager.set_movie_libraries(["Filmy", "Kids"])
|
||||
(tmp_path / "a.mkv").write_bytes(b"x")
|
||||
movie = file_manager.import_movie(tmp_path / "a.mkv", "Auta", year=2006)
|
||||
old_key = movie.file_path.relative_to(tmp_path / "pool").as_posix()
|
||||
|
||||
file_manager.move_to_library(movie, "Kids")
|
||||
|
||||
assert file_manager.library_of(movie) == "Kids"
|
||||
assert movie.file_path.exists()
|
||||
assert file_manager.index.records.get(old_key) is None # old key dropped
|
||||
new_key = movie.file_path.relative_to(tmp_path / "pool").as_posix()
|
||||
assert file_manager.index.records.get(new_key) is not None
|
||||
|
||||
def test_move_to_unknown_library_rejected(self, file_manager, tmp_path):
|
||||
file_manager.set_pool_dir(tmp_path / "pool")
|
||||
(tmp_path / "a.mkv").write_bytes(b"x")
|
||||
movie = file_manager.import_movie(tmp_path / "a.mkv", "Auta", year=2006)
|
||||
with pytest.raises(ValueError):
|
||||
file_manager.move_to_library(movie, "Neexistuje")
|
||||
|
||||
def test_load_scans_all_movie_libraries(self, file_manager, tmp_path):
|
||||
file_manager.set_pool_dir(tmp_path / "pool")
|
||||
file_manager.set_movie_libraries(["Filmy", "Kids"])
|
||||
(tmp_path / "a.mkv").write_bytes(b"x")
|
||||
(tmp_path / "b.mkv").write_bytes(b"y")
|
||||
file_manager.import_movie(tmp_path / "a.mkv", "Matrix", year=1999)
|
||||
file_manager.import_movie(tmp_path / "b.mkv", "Auta", year=2006, library="Kids")
|
||||
|
||||
reloaded = FileManager(TagManager())
|
||||
reloaded.set_pool_dir(tmp_path / "pool")
|
||||
reloaded.load_pool_movies()
|
||||
|
||||
libs = sorted(reloaded.library_of(f) for f in reloaded.filelist)
|
||||
assert libs == ["Filmy", "Kids"]
|
||||
|
||||
def test_load_skips_jellyfin_sidecars(self, file_manager, tmp_path):
|
||||
file_manager.set_pool_dir(tmp_path / "pool")
|
||||
(tmp_path / "a.mkv").write_bytes(b"x")
|
||||
movie = file_manager.import_movie(tmp_path / "a.mkv", "Matrix", year=1999)
|
||||
# Jellyfin writes these next to the movie — must not count as movies
|
||||
movie.file_path.with_suffix(".nfo").write_text("<movie/>")
|
||||
(movie.file_path.parent / "poster.jpg").write_bytes(b"img")
|
||||
|
||||
reloaded = FileManager(TagManager())
|
||||
reloaded.set_pool_dir(tmp_path / "pool")
|
||||
reloaded.load_pool_movies()
|
||||
|
||||
assert len(reloaded.filelist) == 1
|
||||
assert reloaded.filelist[0].file_path.suffix == ".mkv"
|
||||
|
||||
def test_rename_to_canonical_preserves_tmdb_id(self, file_manager, tmp_path):
|
||||
file_manager.set_pool_dir(tmp_path / "pool")
|
||||
(tmp_path / "raw.mkv").write_bytes(b"x")
|
||||
movie = file_manager.import_movie(
|
||||
tmp_path / "raw.mkv", "Matrix", year=1999, tmdb_id=603)
|
||||
|
||||
movie.title = "Matrix Reloaded" # metadata title changed
|
||||
renamed = file_manager.rename_to_canonical(movie)
|
||||
|
||||
assert renamed is not None
|
||||
assert movie.file_path.name == "Matrix Reloaded (1999) [tmdbid-603].mkv"
|
||||
|
||||
def test_import_movie_rejects_invalid_year(self, file_manager, tmp_path):
|
||||
file_manager.set_pool_dir(tmp_path / "pool")
|
||||
(tmp_path / "a.mkv").write_bytes(b"a")
|
||||
@@ -441,7 +524,7 @@ class TestPoolManagement:
|
||||
movie = file_manager.import_movie(tmp_path / "raw.mkv", "Matrix") # plain
|
||||
assert movie.file_path.name == "Matrix.mkv"
|
||||
|
||||
movie.csfd_cache = {"year": 1999}
|
||||
movie.meta = {"year": 1999}
|
||||
renamed = file_manager.rename_to_canonical(movie)
|
||||
|
||||
assert renamed is not None
|
||||
@@ -461,7 +544,7 @@ class TestPoolManagement:
|
||||
for n in ("a.mkv", "b.mkv", "c.mkv"):
|
||||
(tmp_path / n).write_bytes(b"x")
|
||||
with_year = file_manager.import_movie(tmp_path / "a.mkv", "Matrix")
|
||||
with_year.csfd_cache = {"year": 1999}
|
||||
with_year.meta = {"year": 1999}
|
||||
already = file_manager.import_movie(tmp_path / "b.mkv", "Solaris", year=1972)
|
||||
_no_year = file_manager.import_movie(tmp_path / "c.mkv", "Mystery")
|
||||
|
||||
@@ -476,7 +559,7 @@ class TestPoolManagement:
|
||||
file_manager.set_pool_dir(tmp_path / "pool")
|
||||
source = tmp_path / "raw.mkv"
|
||||
source.write_bytes(b"x" * 10)
|
||||
file_manager.import_movie(source, "Matrix", "https://csfd.cz/film/1")
|
||||
file_manager.import_movie(source, "Matrix")
|
||||
|
||||
reloaded = FileManager(TagManager())
|
||||
reloaded.set_pool_dir(tmp_path / "pool")
|
||||
|
||||
Reference in New Issue
Block a user