Plex discovery on demand (#35303)
* Allow Plex discovery on demand * Add new discovery source * Add tests
This commit is contained in:
parent
ee96ff2846
commit
c12f8bed43
5 changed files with 81 additions and 2 deletions
|
@ -4,6 +4,7 @@ import logging
|
|||
|
||||
from aiohttp import web_response
|
||||
import plexapi.exceptions
|
||||
from plexapi.gdm import GDM
|
||||
from plexauth import PlexAuth
|
||||
import requests.exceptions
|
||||
import voluptuous as vol
|
||||
|
@ -62,6 +63,18 @@ def configured_servers(hass):
|
|||
}
|
||||
|
||||
|
||||
async def async_discover(hass):
|
||||
"""Scan for available Plex servers."""
|
||||
gdm = GDM()
|
||||
await hass.async_add_executor_job(gdm.scan)
|
||||
for server_data in gdm.entries:
|
||||
await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
context={"source": config_entries.SOURCE_INTEGRATION_DISCOVERY},
|
||||
data=server_data,
|
||||
)
|
||||
|
||||
|
||||
class PlexFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a Plex config flow."""
|
||||
|
||||
|
@ -266,6 +279,19 @@ class PlexFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
_LOGGER.debug("Imported Plex configuration")
|
||||
return await self.async_step_server_validate(import_config)
|
||||
|
||||
async def async_step_integration_discovery(self, discovery_info):
|
||||
"""Handle GDM discovery."""
|
||||
machine_identifier = discovery_info["data"]["Resource-Identifier"]
|
||||
await self.async_set_unique_id(machine_identifier)
|
||||
self._abort_if_unique_id_configured()
|
||||
host = f"{discovery_info['from'][0]}:{discovery_info['data']['Port']}"
|
||||
name = discovery_info["data"]["Name"]
|
||||
self.context["title_placeholders"] = { # pylint: disable=no-member
|
||||
"host": host,
|
||||
"name": name,
|
||||
}
|
||||
return await self.async_step_user()
|
||||
|
||||
async def async_step_plex_website_auth(self):
|
||||
"""Begin external auth flow on Plex website."""
|
||||
self.hass.http.register_view(PlexAuthorizationCallbackView)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"config": {
|
||||
"flow_title": "{name} ({host})",
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Plex Media Server",
|
||||
|
|
|
@ -22,6 +22,7 @@ _UNDEF: dict = {}
|
|||
|
||||
SOURCE_DISCOVERY = "discovery"
|
||||
SOURCE_IMPORT = "import"
|
||||
SOURCE_INTEGRATION_DISCOVERY = "integration_discovery"
|
||||
SOURCE_SSDP = "ssdp"
|
||||
SOURCE_USER = "user"
|
||||
SOURCE_ZEROCONF = "zeroconf"
|
||||
|
|
|
@ -8,6 +8,32 @@ from homeassistant.const import CONF_URL
|
|||
|
||||
from .const import DEFAULT_DATA, MOCK_SERVERS, MOCK_USERS
|
||||
|
||||
GDM_PAYLOAD = [
|
||||
{
|
||||
"data": {
|
||||
"Content-Type": "plex/media-server",
|
||||
"Name": "plextest",
|
||||
"Port": "32400",
|
||||
"Resource-Identifier": "1234567890123456789012345678901234567890",
|
||||
"Updated-At": "157762684800",
|
||||
"Version": "1.0",
|
||||
},
|
||||
"from": ("1.2.3.4", 32414),
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
class MockGDM:
|
||||
"""Mock a GDM instance."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize the object."""
|
||||
self.entries = GDM_PAYLOAD
|
||||
|
||||
def scan(self):
|
||||
"""Mock the scan call."""
|
||||
pass
|
||||
|
||||
|
||||
class MockResource:
|
||||
"""Mock a PlexAccount resource."""
|
||||
|
|
|
@ -22,7 +22,10 @@ from homeassistant.components.plex.const import (
|
|||
SERVERS,
|
||||
)
|
||||
from homeassistant.config import async_process_ha_core_config
|
||||
from homeassistant.config_entries import ENTRY_STATE_LOADED
|
||||
from homeassistant.config_entries import (
|
||||
ENTRY_STATE_LOADED,
|
||||
SOURCE_INTEGRATION_DISCOVERY,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONF_HOST,
|
||||
CONF_PORT,
|
||||
|
@ -34,7 +37,7 @@ from homeassistant.const import (
|
|||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
|
||||
from .const import DEFAULT_DATA, DEFAULT_OPTIONS, MOCK_SERVERS, MOCK_TOKEN
|
||||
from .mock_classes import MockPlexAccount, MockPlexServer
|
||||
from .mock_classes import MockGDM, MockPlexAccount, MockPlexServer
|
||||
|
||||
from tests.async_mock import patch
|
||||
from tests.common import MockConfigEntry
|
||||
|
@ -746,3 +749,25 @@ async def test_setup_with_limited_credentials(hass):
|
|||
|
||||
assert len(hass.config_entries.async_entries(DOMAIN)) == 1
|
||||
assert entry.state == ENTRY_STATE_LOADED
|
||||
|
||||
|
||||
async def test_integration_discovery(hass):
|
||||
"""Test integration self-discovery."""
|
||||
mock_gdm = MockGDM()
|
||||
|
||||
with patch("homeassistant.components.plex.config_flow.GDM", return_value=mock_gdm):
|
||||
await config_flow.async_discover(hass)
|
||||
|
||||
flows = hass.config_entries.flow.async_progress()
|
||||
|
||||
assert len(flows) == 1
|
||||
|
||||
flow = flows[0]
|
||||
|
||||
assert flow["handler"] == DOMAIN
|
||||
assert flow["context"]["source"] == SOURCE_INTEGRATION_DISCOVERY
|
||||
assert (
|
||||
flow["context"]["unique_id"]
|
||||
== mock_gdm.entries[0]["data"]["Resource-Identifier"]
|
||||
)
|
||||
assert flow["step_id"] == "user"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue