mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Add Recently Added and On Deck to Plex media browser (#39232)
This commit is contained in:
parent
49daf57c54
commit
d66bc6a873
@ -13,6 +13,10 @@ PLAYLISTS_BROWSE_PAYLOAD = {
|
|||||||
"can_play": False,
|
"can_play": False,
|
||||||
"can_expand": True,
|
"can_expand": True,
|
||||||
}
|
}
|
||||||
|
SPECIAL_METHODS = {
|
||||||
|
"On Deck": "onDeck",
|
||||||
|
"Recently Added": "recentlyAdded",
|
||||||
|
}
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -36,14 +40,43 @@ def browse_media(
|
|||||||
media_info["children"].append(item_payload(item))
|
media_info["children"].append(item_payload(item))
|
||||||
return media_info
|
return media_info
|
||||||
|
|
||||||
|
if media_content_id and ":" in media_content_id:
|
||||||
|
media_content_id, special_folder = media_content_id.split(":")
|
||||||
|
else:
|
||||||
|
special_folder = None
|
||||||
|
|
||||||
if (
|
if (
|
||||||
media_content_type == "server"
|
media_content_type
|
||||||
|
and media_content_type == "server"
|
||||||
and media_content_id != plex_server.machine_identifier
|
and media_content_id != plex_server.machine_identifier
|
||||||
):
|
):
|
||||||
raise BrowseError(
|
raise BrowseError(
|
||||||
f"Plex server with ID '{media_content_id}' is not associated with {entity_id}"
|
f"Plex server with ID '{media_content_id}' is not associated with {entity_id}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if special_folder:
|
||||||
|
if media_content_type == "server":
|
||||||
|
library_or_section = plex_server.library
|
||||||
|
title = plex_server.friendly_name
|
||||||
|
elif media_content_type == "library":
|
||||||
|
library_or_section = plex_server.library.sectionByID(media_content_id)
|
||||||
|
title = library_or_section.title
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
"title": title,
|
||||||
|
"media_content_id": f"{media_content_id}:{special_folder}",
|
||||||
|
"media_content_type": media_content_type,
|
||||||
|
"can_play": False,
|
||||||
|
"can_expand": True,
|
||||||
|
"children": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
method = SPECIAL_METHODS[special_folder]
|
||||||
|
items = getattr(library_or_section, method)()
|
||||||
|
for item in items:
|
||||||
|
payload["children"].append(item_payload(item))
|
||||||
|
return payload
|
||||||
|
|
||||||
if media_content_type in ["server", None]:
|
if media_content_type in ["server", None]:
|
||||||
return server_payload(plex_server)
|
return server_payload(plex_server)
|
||||||
|
|
||||||
@ -89,6 +122,18 @@ def library_section_payload(section):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def special_library_payload(parent_payload, special_type):
|
||||||
|
"""Create response payload for special library folders."""
|
||||||
|
title = f"{special_type} ({parent_payload['title']})"
|
||||||
|
return {
|
||||||
|
"title": title,
|
||||||
|
"media_content_id": f"{parent_payload['media_content_id']}:{special_type}",
|
||||||
|
"media_content_type": parent_payload["media_content_type"],
|
||||||
|
"can_play": False,
|
||||||
|
"can_expand": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def server_payload(plex_server):
|
def server_payload(plex_server):
|
||||||
"""Create response payload to describe libraries of the Plex server."""
|
"""Create response payload to describe libraries of the Plex server."""
|
||||||
server_info = {
|
server_info = {
|
||||||
@ -99,6 +144,10 @@ def server_payload(plex_server):
|
|||||||
"can_expand": True,
|
"can_expand": True,
|
||||||
}
|
}
|
||||||
server_info["children"] = []
|
server_info["children"] = []
|
||||||
|
server_info["children"].append(special_library_payload(server_info, "On Deck"))
|
||||||
|
server_info["children"].append(
|
||||||
|
special_library_payload(server_info, "Recently Added")
|
||||||
|
)
|
||||||
for library in plex_server.library.sections():
|
for library in plex_server.library.sections():
|
||||||
if library.type == "photo":
|
if library.type == "photo":
|
||||||
continue
|
continue
|
||||||
@ -112,6 +161,10 @@ def library_payload(plex_server, library_id):
|
|||||||
library = plex_server.library.sectionByID(library_id)
|
library = plex_server.library.sectionByID(library_id)
|
||||||
library_info = library_section_payload(library)
|
library_info = library_section_payload(library)
|
||||||
library_info["children"] = []
|
library_info["children"] = []
|
||||||
|
library_info["children"].append(special_library_payload(library_info, "On Deck"))
|
||||||
|
library_info["children"].append(
|
||||||
|
special_library_payload(library_info, "Recently Added")
|
||||||
|
)
|
||||||
for item in library.all():
|
for item in library.all():
|
||||||
library_info["children"].append(item_payload(item))
|
library_info["children"].append(item_payload(item))
|
||||||
return library_info
|
return library_info
|
||||||
|
@ -346,6 +346,14 @@ class MockPlexLibrary:
|
|||||||
"""Mock the sectionByID lookup."""
|
"""Mock the sectionByID lookup."""
|
||||||
return [x for x in self.sections() if x.key == section_id][0]
|
return [x for x in self.sections() if x.key == section_id][0]
|
||||||
|
|
||||||
|
def onDeck(self):
|
||||||
|
"""Mock an empty On Deck folder."""
|
||||||
|
return []
|
||||||
|
|
||||||
|
def recentlyAdded(self):
|
||||||
|
"""Mock an empty Recently Added folder."""
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
class MockPlexLibrarySection:
|
class MockPlexLibrarySection:
|
||||||
"""Mock a Plex LibrarySection instance."""
|
"""Mock a Plex LibrarySection instance."""
|
||||||
@ -381,6 +389,14 @@ class MockPlexLibrarySection:
|
|||||||
if child.ratingKey == ratingKey:
|
if child.ratingKey == ratingKey:
|
||||||
return child
|
return child
|
||||||
|
|
||||||
|
def onDeck(self):
|
||||||
|
"""Mock an empty On Deck folder."""
|
||||||
|
return []
|
||||||
|
|
||||||
|
def recentlyAdded(self):
|
||||||
|
"""Mock an empty Recently Added folder."""
|
||||||
|
return self.all()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def type(self):
|
def type(self):
|
||||||
"""Mock the library type."""
|
"""Mock the library type."""
|
||||||
|
@ -4,6 +4,7 @@ from homeassistant.components.media_player.const import (
|
|||||||
ATTR_MEDIA_CONTENT_TYPE,
|
ATTR_MEDIA_CONTENT_TYPE,
|
||||||
)
|
)
|
||||||
from homeassistant.components.plex.const import CONF_SERVER_IDENTIFIER, DOMAIN
|
from homeassistant.components.plex.const import CONF_SERVER_IDENTIFIER, DOMAIN
|
||||||
|
from homeassistant.components.plex.media_browser import SPECIAL_METHODS
|
||||||
from homeassistant.components.websocket_api.const import ERR_UNKNOWN_ERROR, TYPE_RESULT
|
from homeassistant.components.websocket_api.const import ERR_UNKNOWN_ERROR, TYPE_RESULT
|
||||||
|
|
||||||
from .const import DEFAULT_DATA, DEFAULT_OPTIONS
|
from .const import DEFAULT_DATA, DEFAULT_OPTIONS
|
||||||
@ -77,10 +78,61 @@ async def test_browse_media(hass, hass_ws_client):
|
|||||||
result = msg["result"]
|
result = msg["result"]
|
||||||
assert result[ATTR_MEDIA_CONTENT_TYPE] == "server"
|
assert result[ATTR_MEDIA_CONTENT_TYPE] == "server"
|
||||||
assert result[ATTR_MEDIA_CONTENT_ID] == DEFAULT_DATA[CONF_SERVER_IDENTIFIER]
|
assert result[ATTR_MEDIA_CONTENT_ID] == DEFAULT_DATA[CONF_SERVER_IDENTIFIER]
|
||||||
assert len(result["children"]) == len(mock_plex_server.library.sections())
|
assert len(result["children"]) == len(mock_plex_server.library.sections()) + len(
|
||||||
|
SPECIAL_METHODS
|
||||||
|
)
|
||||||
|
|
||||||
tvshows = next(iter(x for x in result["children"] if x["title"] == "TV Shows"))
|
tvshows = next(iter(x for x in result["children"] if x["title"] == "TV Shows"))
|
||||||
playlists = next(iter(x for x in result["children"] if x["title"] == "Playlists"))
|
playlists = next(iter(x for x in result["children"] if x["title"] == "Playlists"))
|
||||||
|
special_keys = list(SPECIAL_METHODS.keys())
|
||||||
|
|
||||||
|
# Browse into a special folder (server)
|
||||||
|
msg_id += 1
|
||||||
|
await websocket_client.send_json(
|
||||||
|
{
|
||||||
|
"id": msg_id,
|
||||||
|
"type": "media_player/browse_media",
|
||||||
|
"entity_id": media_players[0],
|
||||||
|
ATTR_MEDIA_CONTENT_TYPE: "server",
|
||||||
|
ATTR_MEDIA_CONTENT_ID: f"{DEFAULT_DATA[CONF_SERVER_IDENTIFIER]}:{special_keys[0]}",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
msg = await websocket_client.receive_json()
|
||||||
|
assert msg["id"] == msg_id
|
||||||
|
assert msg["type"] == TYPE_RESULT
|
||||||
|
assert msg["success"]
|
||||||
|
result = msg["result"]
|
||||||
|
assert result[ATTR_MEDIA_CONTENT_TYPE] == "server"
|
||||||
|
assert (
|
||||||
|
result[ATTR_MEDIA_CONTENT_ID]
|
||||||
|
== f"{DEFAULT_DATA[CONF_SERVER_IDENTIFIER]}:{special_keys[0]}"
|
||||||
|
)
|
||||||
|
assert len(result["children"]) == len(mock_plex_server.library.onDeck())
|
||||||
|
|
||||||
|
# Browse into a special folder (library)
|
||||||
|
msg_id += 1
|
||||||
|
library_section_id = next(iter(mock_plex_server.library.sections())).key
|
||||||
|
await websocket_client.send_json(
|
||||||
|
{
|
||||||
|
"id": msg_id,
|
||||||
|
"type": "media_player/browse_media",
|
||||||
|
"entity_id": media_players[0],
|
||||||
|
ATTR_MEDIA_CONTENT_TYPE: "library",
|
||||||
|
ATTR_MEDIA_CONTENT_ID: f"{library_section_id}:{special_keys[1]}",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
msg = await websocket_client.receive_json()
|
||||||
|
assert msg["id"] == msg_id
|
||||||
|
assert msg["type"] == TYPE_RESULT
|
||||||
|
assert msg["success"]
|
||||||
|
result = msg["result"]
|
||||||
|
assert result[ATTR_MEDIA_CONTENT_TYPE] == "library"
|
||||||
|
assert result[ATTR_MEDIA_CONTENT_ID] == f"{library_section_id}:{special_keys[1]}"
|
||||||
|
assert len(result["children"]) == len(
|
||||||
|
mock_plex_server.library.sectionByID(library_section_id).recentlyAdded()
|
||||||
|
)
|
||||||
|
|
||||||
# Browse into a Plex TV show library
|
# Browse into a Plex TV show library
|
||||||
msg_id += 1
|
msg_id += 1
|
||||||
@ -103,7 +155,7 @@ async def test_browse_media(hass, hass_ws_client):
|
|||||||
result_id = result[ATTR_MEDIA_CONTENT_ID]
|
result_id = result[ATTR_MEDIA_CONTENT_ID]
|
||||||
assert len(result["children"]) == len(
|
assert len(result["children"]) == len(
|
||||||
mock_plex_server.library.sectionByID(result_id).all()
|
mock_plex_server.library.sectionByID(result_id).all()
|
||||||
)
|
) + len(SPECIAL_METHODS)
|
||||||
|
|
||||||
# Browse into a Plex TV show
|
# Browse into a Plex TV show
|
||||||
msg_id += 1
|
msg_id += 1
|
||||||
@ -112,8 +164,8 @@ async def test_browse_media(hass, hass_ws_client):
|
|||||||
"id": msg_id,
|
"id": msg_id,
|
||||||
"type": "media_player/browse_media",
|
"type": "media_player/browse_media",
|
||||||
"entity_id": media_players[0],
|
"entity_id": media_players[0],
|
||||||
ATTR_MEDIA_CONTENT_TYPE: result["children"][0][ATTR_MEDIA_CONTENT_TYPE],
|
ATTR_MEDIA_CONTENT_TYPE: result["children"][-1][ATTR_MEDIA_CONTENT_TYPE],
|
||||||
ATTR_MEDIA_CONTENT_ID: str(result["children"][0][ATTR_MEDIA_CONTENT_ID]),
|
ATTR_MEDIA_CONTENT_ID: str(result["children"][-1][ATTR_MEDIA_CONTENT_ID]),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user