mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 01:08:12 +00:00
Make uploaded images browsable in media (#131468)
* Make uploaded images browsable in media * tests * Update homeassistant/components/image_upload/media_source.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * use executor * more executor * use thumbnail --------- Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
e8ced4fa12
commit
2c1a754e5d
76
homeassistant/components/image_upload/media_source.py
Normal file
76
homeassistant/components/image_upload/media_source.py
Normal file
@ -0,0 +1,76 @@
|
||||
"""Expose image_upload as media sources."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from homeassistant.components.media_player import BrowseError, MediaClass
|
||||
from homeassistant.components.media_source import (
|
||||
BrowseMediaSource,
|
||||
MediaSource,
|
||||
MediaSourceItem,
|
||||
PlayMedia,
|
||||
Unresolvable,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
|
||||
async def async_get_media_source(hass: HomeAssistant) -> ImageUploadMediaSource:
|
||||
"""Set up image media source."""
|
||||
return ImageUploadMediaSource(hass)
|
||||
|
||||
|
||||
class ImageUploadMediaSource(MediaSource):
|
||||
"""Provide images as media sources."""
|
||||
|
||||
name: str = "Image Upload"
|
||||
|
||||
def __init__(self, hass: HomeAssistant) -> None:
|
||||
"""Initialize ImageMediaSource."""
|
||||
super().__init__(DOMAIN)
|
||||
self.hass = hass
|
||||
|
||||
async def async_resolve_media(self, item: MediaSourceItem) -> PlayMedia:
|
||||
"""Resolve media to a url."""
|
||||
image = self.hass.data[DOMAIN].data.get(item.identifier)
|
||||
|
||||
if not image:
|
||||
raise Unresolvable(f"Could not resolve media item: {item.identifier}")
|
||||
|
||||
return PlayMedia(
|
||||
f"/api/image/serve/{image['id']}/original", image["content_type"]
|
||||
)
|
||||
|
||||
async def async_browse_media(
|
||||
self,
|
||||
item: MediaSourceItem,
|
||||
) -> BrowseMediaSource:
|
||||
"""Return media."""
|
||||
if item.identifier:
|
||||
raise BrowseError("Unknown item")
|
||||
|
||||
children = [
|
||||
BrowseMediaSource(
|
||||
domain=DOMAIN,
|
||||
identifier=image["id"],
|
||||
media_class=MediaClass.IMAGE,
|
||||
media_content_type=image["content_type"],
|
||||
title=image["name"],
|
||||
thumbnail=f"/api/image/serve/{image['id']}/256x256",
|
||||
can_play=True,
|
||||
can_expand=False,
|
||||
)
|
||||
for image in self.hass.data[DOMAIN].data.values()
|
||||
]
|
||||
|
||||
return BrowseMediaSource(
|
||||
domain=DOMAIN,
|
||||
identifier=None,
|
||||
media_class=MediaClass.APP,
|
||||
media_content_type="",
|
||||
title="Image Upload",
|
||||
can_play=False,
|
||||
can_expand=True,
|
||||
children_media_class=MediaClass.IMAGE,
|
||||
children=children,
|
||||
)
|
90
tests/components/image_upload/test_media_source.py
Normal file
90
tests/components/image_upload/test_media_source.py
Normal file
@ -0,0 +1,90 @@
|
||||
"""Test image_upload media source."""
|
||||
|
||||
import tempfile
|
||||
from unittest.mock import patch
|
||||
|
||||
from aiohttp import ClientSession
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import media_source
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from . import TEST_IMAGE
|
||||
|
||||
from tests.typing import ClientSessionGenerator
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
async def setup_media_source(hass: HomeAssistant) -> None:
|
||||
"""Set up media source."""
|
||||
assert await async_setup_component(hass, "media_source", {})
|
||||
|
||||
|
||||
async def __upload_test_image(
|
||||
hass: HomeAssistant,
|
||||
hass_client: ClientSessionGenerator,
|
||||
) -> str:
|
||||
with (
|
||||
tempfile.TemporaryDirectory() as tempdir,
|
||||
patch.object(hass.config, "path", return_value=tempdir),
|
||||
):
|
||||
assert await async_setup_component(hass, "image_upload", {})
|
||||
client: ClientSession = await hass_client()
|
||||
|
||||
file = await hass.async_add_executor_job(TEST_IMAGE.open, "rb")
|
||||
res = await client.post("/api/image/upload", data={"file": file})
|
||||
hass.async_add_executor_job(file.close)
|
||||
|
||||
assert res.status == 200
|
||||
item = await res.json()
|
||||
assert item["content_type"] == "image/png"
|
||||
assert item["filesize"] == 38847
|
||||
return item["id"]
|
||||
|
||||
|
||||
async def test_browsing(
|
||||
hass: HomeAssistant,
|
||||
hass_client: ClientSessionGenerator,
|
||||
) -> None:
|
||||
"""Test browsing image media source."""
|
||||
image_id = await __upload_test_image(hass, hass_client)
|
||||
|
||||
item = await media_source.async_browse_media(hass, "media-source://image_upload")
|
||||
|
||||
assert item is not None
|
||||
assert item.title == "Image Upload"
|
||||
assert len(item.children) == 1
|
||||
assert item.children[0].media_content_type == "image/png"
|
||||
assert item.children[0].identifier == image_id
|
||||
assert item.children[0].thumbnail == f"/api/image/serve/{image_id}/256x256"
|
||||
|
||||
with pytest.raises(
|
||||
media_source.BrowseError,
|
||||
match="Unknown item",
|
||||
):
|
||||
await media_source.async_browse_media(
|
||||
hass, "media-source://image_upload/invalid_path"
|
||||
)
|
||||
|
||||
|
||||
async def test_resolving(
|
||||
hass: HomeAssistant, hass_client: ClientSessionGenerator
|
||||
) -> None:
|
||||
"""Test resolving."""
|
||||
image_id = await __upload_test_image(hass, hass_client)
|
||||
item = await media_source.async_resolve_media(
|
||||
hass, f"media-source://image_upload/{image_id}", None
|
||||
)
|
||||
assert item is not None
|
||||
assert item.url == f"/api/image/serve/{image_id}/original"
|
||||
assert item.mime_type == "image/png"
|
||||
|
||||
invalid_id = "aabbccddeeff"
|
||||
with pytest.raises(
|
||||
media_source.Unresolvable,
|
||||
match=f"Could not resolve media item: {invalid_id}",
|
||||
):
|
||||
await media_source.async_resolve_media(
|
||||
hass, f"media-source://image_upload/{invalid_id}", None
|
||||
)
|
Loading…
x
Reference in New Issue
Block a user