mirror of
https://github.com/MrSleeps/jellyfin-scene-search.git
synced 2026-11-15 22:41:28 +00:00
143 lines
4.8 KiB
Python
143 lines
4.8 KiB
Python
from __future__ import annotations
|
|
|
|
import io
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import Mock
|
|
|
|
from PIL import Image
|
|
|
|
from scene_search.jellyfin import (
|
|
JellyfinClient,
|
|
TrickplaySelection,
|
|
caption_context_from_tags,
|
|
route_override_from_tags,
|
|
)
|
|
|
|
|
|
class JellyfinIntegrationTests(unittest.TestCase):
|
|
def test_item_detail_uses_items_query_not_direct_item_route(self) -> None:
|
|
client = JellyfinClient("http://jellyfin.test", "token")
|
|
response = Mock()
|
|
response.ok = True
|
|
response.json.return_value = {
|
|
"Items": [
|
|
{
|
|
"Id": "item-1",
|
|
"Name": "Example",
|
|
"Tags": ["Tag"],
|
|
"MediaSources": [],
|
|
"Trickplay": {},
|
|
"Etag": "etag-1",
|
|
}
|
|
]
|
|
}
|
|
client._get = Mock(return_value=response)
|
|
|
|
result = client.item("item-1")
|
|
|
|
self.assertEqual(result["Id"], "item-1")
|
|
call = client._get.call_args
|
|
self.assertEqual(call.args[0], "/Items")
|
|
self.assertEqual(call.kwargs["params"]["Ids"], "item-1")
|
|
self.assertIn("Tags", call.kwargs["params"]["Fields"])
|
|
self.assertIn("MediaSources", call.kwargs["params"]["Fields"])
|
|
self.assertIn("Trickplay", call.kwargs["params"]["Fields"])
|
|
self.assertIn("Etag", call.kwargs["params"]["Fields"])
|
|
|
|
def test_select_trickplay_prefers_nearest_width(self) -> None:
|
|
item = {
|
|
"Trickplay": {
|
|
"source-1": {
|
|
"160": {
|
|
"Width": 160,
|
|
"Height": 90,
|
|
"Interval": 10000,
|
|
"ThumbnailCount": 20,
|
|
"TileWidth": 5,
|
|
"TileHeight": 4,
|
|
},
|
|
"320": {
|
|
"Width": 320,
|
|
"Height": 180,
|
|
"Interval": 10000,
|
|
"ThumbnailCount": 20,
|
|
"TileWidth": 5,
|
|
"TileHeight": 4,
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
selected = JellyfinClient.select_trickplay(item, preferred_width=300)
|
|
|
|
self.assertIsNotNone(selected)
|
|
assert selected is not None
|
|
self.assertEqual(selected.media_source_id, "source-1")
|
|
self.assertEqual(selected.width, 320)
|
|
self.assertEqual(selected.interval_ms, 10000)
|
|
self.assertEqual(selected.thumbnails_per_sheet, 20)
|
|
|
|
def test_download_trickplay_frames_splits_sheet(self) -> None:
|
|
client = JellyfinClient("http://jellyfin.test", "token")
|
|
selection = TrickplaySelection(
|
|
media_source_id="source-1",
|
|
width=10,
|
|
height=5,
|
|
interval_ms=10000,
|
|
thumbnail_count=4,
|
|
tile_columns=2,
|
|
tile_rows=2,
|
|
)
|
|
|
|
sheet = Image.new("RGB", (20, 10), "white")
|
|
payload = io.BytesIO()
|
|
sheet.save(payload, "JPEG")
|
|
response = Mock()
|
|
response.ok = True
|
|
response.content = payload.getvalue()
|
|
client._get = Mock(return_value=response)
|
|
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
paths = client.download_trickplay_frames(
|
|
"item-1",
|
|
selection,
|
|
Path(tmp),
|
|
)
|
|
self.assertEqual(len(paths), 4)
|
|
self.assertTrue(all(path.is_file() for path in paths))
|
|
|
|
call = client._get.call_args
|
|
self.assertIn("/Videos/item-1/Trickplay/10/0.jpg", call.args[0])
|
|
self.assertEqual(call.kwargs["params"]["MediaSourceId"], "source-1")
|
|
|
|
def test_jellyfin_tags_can_force_specialist_route(self) -> None:
|
|
override = route_override_from_tags(
|
|
["Archive", "scene-search:specialist"],
|
|
force_specialist_tag="scene-search:specialist",
|
|
force_general_tag="scene-search:general",
|
|
specialist_tags=(),
|
|
)
|
|
self.assertEqual(override, ("specialist", "jellyfin-force-tag"))
|
|
|
|
def test_configured_specialist_tag_routes_to_specialist(self) -> None:
|
|
override = route_override_from_tags(
|
|
["Custom Category"],
|
|
force_specialist_tag="scene-search:specialist",
|
|
force_general_tag="scene-search:general",
|
|
specialist_tags=("custom category",),
|
|
)
|
|
self.assertEqual(override, ("specialist", "jellyfin-specialist-tag"))
|
|
|
|
def test_control_tags_are_not_added_to_caption_context(self) -> None:
|
|
context = caption_context_from_tags(
|
|
["holiday", "scene-search:specialist", "beach"],
|
|
control_tags=("scene-search:specialist",),
|
|
)
|
|
self.assertEqual(context, "Jellyfin tags: holiday, beach")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|