Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions homeassistant/components/plex/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from aiohttp import web_response
import plexapi.exceptions
from plexapi.gdm import GDM
from plexauth import PlexAuth
import requests.exceptions
import voluptuous as vol
Expand Down Expand Up @@ -62,6 +63,18 @@ def configured_servers(hass):
}


async def async_discover(hass):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is calling this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing yet (besides the tests). The plan discussed is to offer integration-handled discovery as part of onboarding.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there an architecture issue where this is described?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, this is already described pretty well in home-assistant/architecture#172.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think those are just ideas. The api is not described from what I read.

"""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."""

Expand Down Expand Up @@ -266,6 +279,19 @@ async def async_step_import(self, import_config):
_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)
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/plex/strings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"config": {
"flow_title": "{name} ({host})",
"step": {
"user": {
"title": "Plex Media Server",
Expand Down
1 change: 1 addition & 0 deletions homeassistant/config_entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

SOURCE_DISCOVERY = "discovery"
SOURCE_IMPORT = "import"
SOURCE_INTEGRATION_DISCOVERY = "integration_discovery"
SOURCE_SSDP = "ssdp"
SOURCE_USER = "user"
SOURCE_ZEROCONF = "zeroconf"
Expand Down
26 changes: 26 additions & 0 deletions tests/components/plex/mock_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,32 @@

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."""
Expand Down
29 changes: 27 additions & 2 deletions tests/components/plex/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
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,
Expand All @@ -34,7 +37,7 @@
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
Expand Down Expand Up @@ -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"