From d7e0391e03a2aeddd6c66900cd57e8f721622d1b Mon Sep 17 00:00:00 2001 From: jjlawren Date: Thu, 28 Jan 2021 11:21:31 -0500 Subject: [PATCH] Allow Plex playback using provided playqueue ID (#45580) --- homeassistant/components/plex/media_player.py | 25 +++++++++++++------ homeassistant/components/plex/server.py | 4 +++ homeassistant/components/plex/services.py | 22 +++++++++++----- tests/components/plex/conftest.py | 6 +++++ tests/components/plex/test_services.py | 17 +++++++++++++ tests/fixtures/plex/media_100.xml | 8 +++++- tests/fixtures/plex/playqueue_1234.xml | 7 ++++++ 7 files changed, 75 insertions(+), 14 deletions(-) create mode 100644 tests/fixtures/plex/playqueue_1234.xml diff --git a/homeassistant/components/plex/media_player.py b/homeassistant/components/plex/media_player.py index 24e37216b70..1a57186bd9b 100644 --- a/homeassistant/components/plex/media_player.py +++ b/homeassistant/components/plex/media_player.py @@ -22,6 +22,7 @@ from homeassistant.components.media_player.const import ( ) from homeassistant.const import STATE_IDLE, STATE_PAUSED, STATE_PLAYING from homeassistant.core import callback +from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.dispatcher import ( async_dispatcher_connect, async_dispatcher_send, @@ -495,16 +496,26 @@ class PlexMediaPlayer(MediaPlayerEntity): if isinstance(src, int): src = {"plex_key": src} - shuffle = src.pop("shuffle", 0) - media = self.plex_server.lookup_media(media_type, **src) + playqueue_id = src.pop("playqueue_id", None) - if media is None: - _LOGGER.error("Media could not be found: %s", media_id) - return + if playqueue_id: + try: + playqueue = self.plex_server.get_playqueue(playqueue_id) + except plexapi.exceptions.NotFound as err: + raise HomeAssistantError( + f"PlayQueue '{playqueue_id}' could not be found" + ) from err + else: + shuffle = src.pop("shuffle", 0) + media = self.plex_server.lookup_media(media_type, **src) - _LOGGER.debug("Attempting to play %s on %s", media, self.name) + if media is None: + _LOGGER.error("Media could not be found: %s", media_id) + return + + _LOGGER.debug("Attempting to play %s on %s", media, self.name) + playqueue = self.plex_server.create_playqueue(media, shuffle=shuffle) - playqueue = self.plex_server.create_playqueue(media, shuffle=shuffle) try: self.device.playMedia(playqueue) except requests.exceptions.ConnectTimeout: diff --git a/homeassistant/components/plex/server.py b/homeassistant/components/plex/server.py index f8d55c71fc4..1baceb78ff1 100644 --- a/homeassistant/components/plex/server.py +++ b/homeassistant/components/plex/server.py @@ -593,6 +593,10 @@ class PlexServer: """Create playqueue on Plex server.""" return plexapi.playqueue.PlayQueue.create(self._plex_server, media, **kwargs) + def get_playqueue(self, playqueue_id): + """Retrieve existing playqueue from Plex server.""" + return plexapi.playqueue.PlayQueue.get(self._plex_server, playqueue_id) + def fetch_item(self, item): """Fetch item from Plex server.""" return self._plex_server.fetchItem(item) diff --git a/homeassistant/components/plex/services.py b/homeassistant/components/plex/services.py index 2e4057b890a..a5faa56a8bb 100644 --- a/homeassistant/components/plex/services.py +++ b/homeassistant/components/plex/services.py @@ -105,15 +105,25 @@ def lookup_plex_media(hass, content_type, content_id): content_type = DOMAIN plex_server_name = content.pop("plex_server", None) - shuffle = content.pop("shuffle", 0) - plex_server = get_plex_server(hass, plex_server_name) - media = plex_server.lookup_media(content_type, **content) - if media is None: - raise HomeAssistantError(f"Plex media not found using payload: '{content_id}'") + playqueue_id = content.pop("playqueue_id", None) + if playqueue_id: + try: + playqueue = plex_server.get_playqueue(playqueue_id) + except NotFound as err: + raise HomeAssistantError( + f"PlayQueue '{playqueue_id}' could not be found" + ) from err + else: + shuffle = content.pop("shuffle", 0) + media = plex_server.lookup_media(content_type, **content) + if media is None: + raise HomeAssistantError( + f"Plex media not found using payload: '{content_id}'" + ) + playqueue = plex_server.create_playqueue(media, shuffle=shuffle) - playqueue = plex_server.create_playqueue(media, shuffle=shuffle) return (playqueue, plex_server) diff --git a/tests/components/plex/conftest.py b/tests/components/plex/conftest.py index 8fc25a819e8..d3e66cc4989 100644 --- a/tests/components/plex/conftest.py +++ b/tests/components/plex/conftest.py @@ -168,6 +168,12 @@ def playqueue_created_fixture(): return load_fixture("plex/playqueue_created.xml") +@pytest.fixture(name="playqueue_1234", scope="session") +def playqueue_1234_fixture(): + """Load payload for playqueue 1234 and return it.""" + return load_fixture("plex/playqueue_1234.xml") + + @pytest.fixture(name="plex_server_accounts", scope="session") def plex_server_accounts_fixture(): """Load payload accounts on the Plex server and return it.""" diff --git a/tests/components/plex/test_services.py b/tests/components/plex/test_services.py index 9d1715aa72b..cf8bc63c5da 100644 --- a/tests/components/plex/test_services.py +++ b/tests/components/plex/test_services.py @@ -113,6 +113,7 @@ async def test_sonos_play_media( setup_plex_server, requests_mock, empty_payload, + playqueue_1234, playqueue_created, plextv_account, sonos_resources, @@ -178,3 +179,19 @@ async def test_sonos_play_media( play_on_sonos(hass, MEDIA_TYPE_MUSIC, content_id_bad_media, sonos_speaker_name) assert "Plex media not found" in str(excinfo.value) assert playback_mock.call_count == 3 + + # Test with speakers available and playqueue + requests_mock.get("https://1.2.3.4:32400/playQueues/1234", text=playqueue_1234) + content_id_with_playqueue = '{"playqueue_id": 1234}' + play_on_sonos(hass, MEDIA_TYPE_MUSIC, content_id_with_playqueue, sonos_speaker_name) + assert playback_mock.call_count == 4 + + # Test with speakers available and invalid playqueue + requests_mock.get("https://1.2.3.4:32400/playQueues/1235", status_code=404) + content_id_with_playqueue = '{"playqueue_id": 1235}' + with pytest.raises(HomeAssistantError) as excinfo: + play_on_sonos( + hass, MEDIA_TYPE_MUSIC, content_id_with_playqueue, sonos_speaker_name + ) + assert "PlayQueue '1235' could not be found" in str(excinfo.value) + assert playback_mock.call_count == 4 diff --git a/tests/fixtures/plex/media_100.xml b/tests/fixtures/plex/media_100.xml index e1326a4c862..88ad7048fc0 100644 --- a/tests/fixtures/plex/media_100.xml +++ b/tests/fixtures/plex/media_100.xml @@ -1 +1,7 @@ - + + + + + + + diff --git a/tests/fixtures/plex/playqueue_1234.xml b/tests/fixtures/plex/playqueue_1234.xml new file mode 100644 index 00000000000..837c2ffbc3c --- /dev/null +++ b/tests/fixtures/plex/playqueue_1234.xml @@ -0,0 +1,7 @@ + + + + + + +