mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 14:17:45 +00:00
Add level of collections in Immich media source tree (#145734)
* add layer for collections in media source tree * re-arange tests, add test for collection layer * fix
This commit is contained in:
parent
2708c1c94c
commit
afa97f8ec1
@ -40,11 +40,12 @@ class ImmichMediaSourceIdentifier:
|
||||
def __init__(self, identifier: str) -> None:
|
||||
"""Split identifier into parts."""
|
||||
parts = identifier.split("/")
|
||||
# coonfig_entry.unique_id/album_id/asset_it/filename
|
||||
# config_entry.unique_id/collection/collection_id/asset_id/file_name
|
||||
self.unique_id = parts[0]
|
||||
self.album_id = parts[1] if len(parts) > 1 else None
|
||||
self.asset_id = parts[2] if len(parts) > 2 else None
|
||||
self.file_name = parts[3] if len(parts) > 2 else None
|
||||
self.collection = parts[1] if len(parts) > 1 else None
|
||||
self.collection_id = parts[2] if len(parts) > 2 else None
|
||||
self.asset_id = parts[3] if len(parts) > 3 else None
|
||||
self.file_name = parts[4] if len(parts) > 3 else None
|
||||
|
||||
|
||||
class ImmichMediaSource(MediaSource):
|
||||
@ -83,6 +84,7 @@ class ImmichMediaSource(MediaSource):
|
||||
) -> list[BrowseMediaSource]:
|
||||
"""Handle browsing different immich instances."""
|
||||
if not item.identifier:
|
||||
LOGGER.debug("Render all Immich instances")
|
||||
return [
|
||||
BrowseMediaSource(
|
||||
domain=DOMAIN,
|
||||
@ -104,8 +106,22 @@ class ImmichMediaSource(MediaSource):
|
||||
assert entry
|
||||
immich_api = entry.runtime_data.api
|
||||
|
||||
if identifier.album_id is None:
|
||||
# Get Albums
|
||||
if identifier.collection is None:
|
||||
LOGGER.debug("Render all collections for %s", entry.title)
|
||||
return [
|
||||
BrowseMediaSource(
|
||||
domain=DOMAIN,
|
||||
identifier=f"{identifier.unique_id}/albums",
|
||||
media_class=MediaClass.DIRECTORY,
|
||||
media_content_type=MediaClass.IMAGE,
|
||||
title="albums",
|
||||
can_play=False,
|
||||
can_expand=True,
|
||||
)
|
||||
]
|
||||
|
||||
if identifier.collection_id is None:
|
||||
LOGGER.debug("Render all albums for %s", entry.title)
|
||||
try:
|
||||
albums = await immich_api.albums.async_get_all_albums()
|
||||
except ImmichError:
|
||||
@ -114,7 +130,7 @@ class ImmichMediaSource(MediaSource):
|
||||
return [
|
||||
BrowseMediaSource(
|
||||
domain=DOMAIN,
|
||||
identifier=f"{item.identifier}/{album.album_id}",
|
||||
identifier=f"{identifier.unique_id}/albums/{album.album_id}",
|
||||
media_class=MediaClass.DIRECTORY,
|
||||
media_content_type=MediaClass.IMAGE,
|
||||
title=album.name,
|
||||
@ -125,10 +141,14 @@ class ImmichMediaSource(MediaSource):
|
||||
for album in albums
|
||||
]
|
||||
|
||||
# Request items of album
|
||||
LOGGER.debug(
|
||||
"Render all assets of album %s for %s",
|
||||
identifier.collection_id,
|
||||
entry.title,
|
||||
)
|
||||
try:
|
||||
album_info = await immich_api.albums.async_get_album_info(
|
||||
identifier.album_id
|
||||
identifier.collection_id
|
||||
)
|
||||
except ImmichError:
|
||||
return []
|
||||
@ -137,8 +157,8 @@ class ImmichMediaSource(MediaSource):
|
||||
BrowseMediaSource(
|
||||
domain=DOMAIN,
|
||||
identifier=(
|
||||
f"{identifier.unique_id}/"
|
||||
f"{identifier.album_id}/"
|
||||
f"{identifier.unique_id}/albums/"
|
||||
f"{identifier.collection_id}/"
|
||||
f"{asset.asset_id}/"
|
||||
f"{asset.file_name}"
|
||||
),
|
||||
@ -157,8 +177,8 @@ class ImmichMediaSource(MediaSource):
|
||||
BrowseMediaSource(
|
||||
domain=DOMAIN,
|
||||
identifier=(
|
||||
f"{identifier.unique_id}/"
|
||||
f"{identifier.album_id}/"
|
||||
f"{identifier.unique_id}/albums/"
|
||||
f"{identifier.collection_id}/"
|
||||
f"{asset.asset_id}/"
|
||||
f"{asset.file_name}"
|
||||
),
|
||||
|
@ -44,8 +44,8 @@ async def test_get_media_source(hass: HomeAssistant) -> None:
|
||||
("identifier", "exception_msg"),
|
||||
[
|
||||
("unique_id", "No file name"),
|
||||
("unique_id/album_id", "No file name"),
|
||||
("unique_id/album_id/asset_id/filename", "No file extension"),
|
||||
("unique_id/albums/album_id", "No file name"),
|
||||
("unique_id/albums/album_id/asset_id/filename", "No file extension"),
|
||||
],
|
||||
)
|
||||
async def test_resolve_media_bad_identifier(
|
||||
@ -64,12 +64,12 @@ async def test_resolve_media_bad_identifier(
|
||||
("identifier", "url", "mime_type"),
|
||||
[
|
||||
(
|
||||
"unique_id/album_id/asset_id/filename.jpg",
|
||||
"unique_id/albums/album_id/asset_id/filename.jpg",
|
||||
"/immich/unique_id/asset_id/filename.jpg/fullsize",
|
||||
"image/jpeg",
|
||||
),
|
||||
(
|
||||
"unique_id/album_id/asset_id/filename.png",
|
||||
"unique_id/albums/album_id/asset_id/filename.png",
|
||||
"/immich/unique_id/asset_id/filename.png/fullsize",
|
||||
"image/png",
|
||||
),
|
||||
@ -95,13 +95,82 @@ async def test_browse_media_unconfigured(hass: HomeAssistant) -> None:
|
||||
|
||||
source = await async_get_media_source(hass)
|
||||
item = MediaSourceItem(
|
||||
hass, DOMAIN, "unique_id/album_id/asset_id/filename.png", None
|
||||
hass, DOMAIN, "unique_id/albums/album_id/asset_id/filename.png", None
|
||||
)
|
||||
with pytest.raises(BrowseError, match="Immich is not configured"):
|
||||
await source.async_browse_media(item)
|
||||
|
||||
|
||||
async def test_browse_media_album_error(
|
||||
async def test_browse_media_get_root(
|
||||
hass: HomeAssistant,
|
||||
mock_immich: Mock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test browse_media returning root media sources."""
|
||||
assert await async_setup_component(hass, "media_source", {})
|
||||
|
||||
with patch("homeassistant.components.immich.PLATFORMS", []):
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
source = await async_get_media_source(hass)
|
||||
|
||||
# get root
|
||||
item = MediaSourceItem(hass, DOMAIN, "", None)
|
||||
result = await source.async_browse_media(item)
|
||||
|
||||
assert result
|
||||
assert len(result.children) == 1
|
||||
media_file = result.children[0]
|
||||
assert isinstance(media_file, BrowseMedia)
|
||||
assert media_file.title == "Someone"
|
||||
assert media_file.media_content_id == (
|
||||
"media-source://immich/e7ef5713-9dab-4bd4-b899-715b0ca4379e"
|
||||
)
|
||||
|
||||
# get collections
|
||||
item = MediaSourceItem(hass, DOMAIN, "e7ef5713-9dab-4bd4-b899-715b0ca4379e", None)
|
||||
result = await source.async_browse_media(item)
|
||||
|
||||
assert result
|
||||
assert len(result.children) == 1
|
||||
media_file = result.children[0]
|
||||
assert isinstance(media_file, BrowseMedia)
|
||||
assert media_file.title == "albums"
|
||||
assert media_file.media_content_id == (
|
||||
"media-source://immich/e7ef5713-9dab-4bd4-b899-715b0ca4379e/albums"
|
||||
)
|
||||
|
||||
|
||||
async def test_browse_media_get_albums(
|
||||
hass: HomeAssistant,
|
||||
mock_immich: Mock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test browse_media returning albums."""
|
||||
assert await async_setup_component(hass, "media_source", {})
|
||||
|
||||
with patch("homeassistant.components.immich.PLATFORMS", []):
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
source = await async_get_media_source(hass)
|
||||
item = MediaSourceItem(
|
||||
hass, DOMAIN, "e7ef5713-9dab-4bd4-b899-715b0ca4379e/albums", None
|
||||
)
|
||||
result = await source.async_browse_media(item)
|
||||
|
||||
assert result
|
||||
assert len(result.children) == 1
|
||||
media_file = result.children[0]
|
||||
assert isinstance(media_file, BrowseMedia)
|
||||
assert media_file.title == "My Album"
|
||||
assert media_file.media_content_id == (
|
||||
"media-source://immich/"
|
||||
"e7ef5713-9dab-4bd4-b899-715b0ca4379e/albums/"
|
||||
"721e1a4b-aa12-441e-8d3b-5ac7ab283bb6"
|
||||
)
|
||||
|
||||
|
||||
async def test_browse_media_get_albums_error(
|
||||
hass: HomeAssistant,
|
||||
mock_immich: Mock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
@ -124,7 +193,7 @@ async def test_browse_media_album_error(
|
||||
|
||||
source = await async_get_media_source(hass)
|
||||
|
||||
item = MediaSourceItem(hass, DOMAIN, mock_config_entry.unique_id, None)
|
||||
item = MediaSourceItem(hass, DOMAIN, f"{mock_config_entry.unique_id}/albums", None)
|
||||
result = await source.async_browse_media(item)
|
||||
|
||||
assert result
|
||||
@ -132,59 +201,7 @@ async def test_browse_media_album_error(
|
||||
assert len(result.children) == 0
|
||||
|
||||
|
||||
async def test_browse_media_get_root(
|
||||
hass: HomeAssistant,
|
||||
mock_immich: Mock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test browse_media returning root media sources."""
|
||||
assert await async_setup_component(hass, "media_source", {})
|
||||
|
||||
with patch("homeassistant.components.immich.PLATFORMS", []):
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
source = await async_get_media_source(hass)
|
||||
item = MediaSourceItem(hass, DOMAIN, "", None)
|
||||
result = await source.async_browse_media(item)
|
||||
|
||||
assert result
|
||||
assert len(result.children) == 1
|
||||
media_file = result.children[0]
|
||||
assert isinstance(media_file, BrowseMedia)
|
||||
assert media_file.title == "Someone"
|
||||
assert media_file.media_content_id == (
|
||||
"media-source://immich/e7ef5713-9dab-4bd4-b899-715b0ca4379e"
|
||||
)
|
||||
|
||||
|
||||
async def test_browse_media_get_albums(
|
||||
hass: HomeAssistant,
|
||||
mock_immich: Mock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test browse_media returning albums."""
|
||||
assert await async_setup_component(hass, "media_source", {})
|
||||
|
||||
with patch("homeassistant.components.immich.PLATFORMS", []):
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
source = await async_get_media_source(hass)
|
||||
item = MediaSourceItem(hass, DOMAIN, "e7ef5713-9dab-4bd4-b899-715b0ca4379e", None)
|
||||
result = await source.async_browse_media(item)
|
||||
|
||||
assert result
|
||||
assert len(result.children) == 1
|
||||
media_file = result.children[0]
|
||||
assert isinstance(media_file, BrowseMedia)
|
||||
assert media_file.title == "My Album"
|
||||
assert media_file.media_content_id == (
|
||||
"media-source://immich/"
|
||||
"e7ef5713-9dab-4bd4-b899-715b0ca4379e/"
|
||||
"721e1a4b-aa12-441e-8d3b-5ac7ab283bb6"
|
||||
)
|
||||
|
||||
|
||||
async def test_browse_media_get_items_error(
|
||||
async def test_browse_media_get_album_items_error(
|
||||
hass: HomeAssistant,
|
||||
mock_immich: Mock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
@ -202,7 +219,7 @@ async def test_browse_media_get_items_error(
|
||||
item = MediaSourceItem(
|
||||
hass,
|
||||
DOMAIN,
|
||||
"e7ef5713-9dab-4bd4-b899-715b0ca4379e/721e1a4b-aa12-441e-8d3b-5ac7ab283bb6",
|
||||
"e7ef5713-9dab-4bd4-b899-715b0ca4379e/albums/721e1a4b-aa12-441e-8d3b-5ac7ab283bb6",
|
||||
None,
|
||||
)
|
||||
result = await source.async_browse_media(item)
|
||||
@ -223,7 +240,7 @@ async def test_browse_media_get_items_error(
|
||||
item = MediaSourceItem(
|
||||
hass,
|
||||
DOMAIN,
|
||||
"e7ef5713-9dab-4bd4-b899-715b0ca4379e/721e1a4b-aa12-441e-8d3b-5ac7ab283bb6",
|
||||
"e7ef5713-9dab-4bd4-b899-715b0ca4379e/albums/721e1a4b-aa12-441e-8d3b-5ac7ab283bb6",
|
||||
None,
|
||||
)
|
||||
result = await source.async_browse_media(item)
|
||||
@ -233,7 +250,7 @@ async def test_browse_media_get_items_error(
|
||||
assert len(result.children) == 0
|
||||
|
||||
|
||||
async def test_browse_media_get_items(
|
||||
async def test_browse_media_get_album_items(
|
||||
hass: HomeAssistant,
|
||||
mock_immich: Mock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
@ -249,7 +266,7 @@ async def test_browse_media_get_items(
|
||||
item = MediaSourceItem(
|
||||
hass,
|
||||
DOMAIN,
|
||||
"e7ef5713-9dab-4bd4-b899-715b0ca4379e/721e1a4b-aa12-441e-8d3b-5ac7ab283bb6",
|
||||
"e7ef5713-9dab-4bd4-b899-715b0ca4379e/albums/721e1a4b-aa12-441e-8d3b-5ac7ab283bb6",
|
||||
None,
|
||||
)
|
||||
result = await source.async_browse_media(item)
|
||||
@ -259,7 +276,7 @@ async def test_browse_media_get_items(
|
||||
media_file = result.children[0]
|
||||
assert isinstance(media_file, BrowseMedia)
|
||||
assert media_file.identifier == (
|
||||
"e7ef5713-9dab-4bd4-b899-715b0ca4379e/"
|
||||
"e7ef5713-9dab-4bd4-b899-715b0ca4379e/albums/"
|
||||
"721e1a4b-aa12-441e-8d3b-5ac7ab283bb6/"
|
||||
"2e94c203-50aa-4ad2-8e29-56dd74e0eff4/filename.jpg"
|
||||
)
|
||||
@ -276,7 +293,7 @@ async def test_browse_media_get_items(
|
||||
media_file = result.children[1]
|
||||
assert isinstance(media_file, BrowseMedia)
|
||||
assert media_file.identifier == (
|
||||
"e7ef5713-9dab-4bd4-b899-715b0ca4379e/"
|
||||
"e7ef5713-9dab-4bd4-b899-715b0ca4379e/albums/"
|
||||
"721e1a4b-aa12-441e-8d3b-5ac7ab283bb6/"
|
||||
"2e65a5f2-db83-44c4-81ab-f5ff20c9bd7b/filename.mp4"
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user