diff --git a/homeassistant/components/media_player/__init__.py b/homeassistant/components/media_player/__init__.py index 4fb0cdae33e..71db60baa2e 100644 --- a/homeassistant/components/media_player/__init__.py +++ b/homeassistant/components/media_player/__init__.py @@ -900,6 +900,9 @@ class MediaPlayerEntity(Entity): except asyncio.TimeoutError: pass + if content is None: + _LOGGER.warning("Error retrieving proxied image from %s", url) + return content, content_type def get_browse_image_url( @@ -910,15 +913,12 @@ class MediaPlayerEntity(Entity): f"/api/media_player_proxy/{self.entity_id}/browse_media" f"/{media_content_type}/{media_content_id}" ) - url = str( - URL(url_path).with_query( - { - "token": self.access_token, - "media_image_id": media_image_id, - } - ) - ) - return url + + url_query = {"token": self.access_token} + if media_image_id: + url_query["media_image_id"] = media_image_id + + return str(URL(url_path).with_query(url_query)) class MediaPlayerImageView(HomeAssistantView): diff --git a/homeassistant/components/roku/browse_media.py b/homeassistant/components/roku/browse_media.py index b5be3e99d9a..8110174450e 100644 --- a/homeassistant/components/roku/browse_media.py +++ b/homeassistant/components/roku/browse_media.py @@ -34,7 +34,7 @@ EXPANDABLE_MEDIA_TYPES = [ ] -def build_item_response(coordinator, payload): +def build_item_response(coordinator, payload, get_thumbnail_url=None): """Create response payload for the provided media query.""" search_id = payload["search_id"] search_type = payload["search_type"] @@ -75,13 +75,13 @@ def build_item_response(coordinator, payload): title=title, can_play=search_type in PLAYABLE_MEDIA_TYPES and search_id, can_expand=True, - children=[item_payload(item, coordinator) for item in media], + children=[item_payload(item, coordinator, get_thumbnail_url) for item in media], children_media_class=children_media_class, thumbnail=thumbnail, ) -def item_payload(item, coordinator): +def item_payload(item, coordinator, get_thumbnail_url=None): """ Create response payload for a single media item. @@ -92,7 +92,8 @@ def item_payload(item, coordinator): if "app_id" in item: media_content_type = MEDIA_TYPE_APP media_content_id = item["app_id"] - thumbnail = coordinator.roku.app_icon_url(item["app_id"]) + if get_thumbnail_url: + thumbnail = get_thumbnail_url(media_content_type, media_content_id) elif "channel_number" in item: media_content_type = MEDIA_TYPE_CHANNEL media_content_id = item["channel_number"] @@ -115,7 +116,7 @@ def item_payload(item, coordinator): ) -def library_payload(coordinator): +def library_payload(coordinator, get_thumbnail_url=None): """ Create response payload to describe contents of a specific library. @@ -147,6 +148,7 @@ def library_payload(coordinator): item_payload( {"title": item["title"], "type": item["type"]}, coordinator, + get_thumbnail_url, ) ) diff --git a/homeassistant/components/roku/media_player.py b/homeassistant/components/roku/media_player.py index 0e035106824..e1662972cf6 100644 --- a/homeassistant/components/roku/media_player.py +++ b/homeassistant/components/roku/media_player.py @@ -238,16 +238,30 @@ class RokuMediaPlayer(RokuEntity, MediaPlayerEntity): """Emulate opening the search screen and entering the search keyword.""" await self.coordinator.roku.search(keyword) + async def async_get_browse_image( + self, media_content_type, media_content_id, media_image_id=None + ): + """Fetch media browser image to serve via proxy.""" + if media_content_type == MEDIA_TYPE_APP and media_content_id: + image_url = self.coordinator.roku.app_icon_url(media_content_id) + return await self._async_fetch_image(image_url) + + return (None, None) + async def async_browse_media(self, media_content_type=None, media_content_id=None): """Implement the websocket media browsing helper.""" + + def _get_thumbnail_url(*args, **kwargs): + return self.get_browse_image_url(*args, **kwargs) + if media_content_type in [None, "library"]: - return library_payload(self.coordinator) + return library_payload(self.coordinator, _get_thumbnail_url) payload = { "search_type": media_content_type, "search_id": media_content_id, } - response = build_item_response(self.coordinator, payload) + response = build_item_response(self.coordinator, payload, _get_thumbnail_url) if response is None: raise BrowseError( diff --git a/tests/components/roku/test_media_player.py b/tests/components/roku/test_media_player.py index b4ce1811c91..23dd9dbc6c8 100644 --- a/tests/components/roku/test_media_player.py +++ b/tests/components/roku/test_media_player.py @@ -539,18 +539,14 @@ async def test_media_browse(hass, aioclient_mock, hass_ws_client): assert msg["result"]["children"][0]["media_content_type"] == MEDIA_TYPE_APP assert msg["result"]["children"][0]["media_content_id"] == "tvinput.hdmi2" assert ( - msg["result"]["children"][0]["thumbnail"] - == "http://192.168.1.161:8060/query/icon/tvinput.hdmi2" + "/browse_media/app/tvinput.hdmi2" in msg["result"]["children"][0]["thumbnail"] ) assert msg["result"]["children"][0]["can_play"] assert msg["result"]["children"][3]["title"] == "Roku Channel Store" assert msg["result"]["children"][3]["media_content_type"] == MEDIA_TYPE_APP assert msg["result"]["children"][3]["media_content_id"] == "11" - assert ( - msg["result"]["children"][3]["thumbnail"] - == "http://192.168.1.161:8060/query/icon/11" - ) + assert "/browse_media/app/11" in msg["result"]["children"][3]["thumbnail"] assert msg["result"]["children"][3]["can_play"] # test channels