mirror of
https://github.com/home-assistant/core
synced 2024-09-09 12:51:22 +02:00
Improve server selection for Plex config flows (#63408)
This commit is contained in:
parent
cf1df5ff38
commit
10195dc700
@ -246,26 +246,26 @@ class PlexFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
"""Use selected Plex server."""
|
||||
config = dict(self.current_login)
|
||||
if user_input is not None:
|
||||
config[CONF_SERVER] = user_input[CONF_SERVER]
|
||||
config[CONF_SERVER_IDENTIFIER] = user_input[CONF_SERVER_IDENTIFIER]
|
||||
return await self.async_step_server_validate(config)
|
||||
|
||||
configured = configured_servers(self.hass)
|
||||
available_servers = [
|
||||
name
|
||||
for (name, server_id) in self.available_servers
|
||||
available_servers = {
|
||||
server_id: f"{name} ({owner})" if owner else name
|
||||
for (name, server_id, owner) in self.available_servers
|
||||
if server_id not in configured
|
||||
]
|
||||
}
|
||||
|
||||
if not available_servers:
|
||||
return self.async_abort(reason="all_configured")
|
||||
if len(available_servers) == 1:
|
||||
config[CONF_SERVER] = available_servers[0]
|
||||
config[CONF_SERVER_IDENTIFIER] = next(iter(available_servers))
|
||||
return await self.async_step_server_validate(config)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="select_server",
|
||||
data_schema=vol.Schema(
|
||||
{vol.Required(CONF_SERVER): vol.In(available_servers)}
|
||||
{vol.Required(CONF_SERVER_IDENTIFIER): vol.In(available_servers)}
|
||||
),
|
||||
errors={},
|
||||
)
|
||||
|
@ -24,6 +24,7 @@ from .const import (
|
||||
CONF_IGNORE_PLEX_WEB_CLIENTS,
|
||||
CONF_MONITORED_USERS,
|
||||
CONF_SERVER,
|
||||
CONF_SERVER_IDENTIFIER,
|
||||
CONF_USE_EPISODE_ART,
|
||||
DEBOUNCE_TIMEOUT,
|
||||
DEFAULT_VERIFY_SSL,
|
||||
@ -73,7 +74,7 @@ class PlexServer:
|
||||
self._token = server_config.get(CONF_TOKEN)
|
||||
self._server_name = server_config.get(CONF_SERVER)
|
||||
self._verify_ssl = server_config.get(CONF_VERIFY_SSL, DEFAULT_VERIFY_SSL)
|
||||
self._server_id = known_server_id
|
||||
self._server_id = known_server_id or server_config.get(CONF_SERVER_IDENTIFIER)
|
||||
self.options = options
|
||||
self.server_choice = None
|
||||
self._accounts = []
|
||||
@ -136,19 +137,20 @@ class PlexServer:
|
||||
all_servers = [
|
||||
x for x in self.account.resources() if "server" in x.provides
|
||||
]
|
||||
servers = [x for x in all_servers if x.presence] or all_servers
|
||||
available_servers = [(x.name, x.clientIdentifier) for x in servers]
|
||||
available_servers = [
|
||||
(x.name, x.clientIdentifier, x.sourceTitle) for x in all_servers
|
||||
]
|
||||
|
||||
if not available_servers:
|
||||
if not all_servers:
|
||||
raise NoServersFound
|
||||
if not self._server_name and len(available_servers) > 1:
|
||||
if not self._server_id and len(all_servers) > 1:
|
||||
raise ServerNotSpecified(available_servers)
|
||||
|
||||
self.server_choice = (
|
||||
self._server_name if self._server_name else available_servers[0][0]
|
||||
)
|
||||
self._plex_server = self.account.resource(self.server_choice).connect(
|
||||
timeout=10
|
||||
self.server_choice = self._server_id or available_servers[0][1]
|
||||
self._plex_server = next(
|
||||
x.connect(timeout=10)
|
||||
for x in all_servers
|
||||
if x.clientIdentifier == self.server_choice
|
||||
)
|
||||
|
||||
def _connect_with_url():
|
||||
|
@ -278,20 +278,20 @@ def plextv_account_fixture():
|
||||
return load_fixture("plex/plextv_account.xml")
|
||||
|
||||
|
||||
@pytest.fixture(name="plextv_resources_base", scope="session")
|
||||
def plextv_resources_base_fixture():
|
||||
"""Load base payload for plex.tv resources and return it."""
|
||||
return load_fixture("plex/plextv_resources_base.xml")
|
||||
|
||||
|
||||
@pytest.fixture(name="plextv_resources", scope="session")
|
||||
def plextv_resources_fixture(plextv_resources_base):
|
||||
"""Load default payload for plex.tv resources and return it."""
|
||||
return plextv_resources_base.format(first_server_enabled=1, second_server_enabled=0)
|
||||
def plextv_resources_fixture():
|
||||
"""Load single-server payload for plex.tv resources and return it."""
|
||||
return load_fixture("plex/plextv_resources_one_server.xml")
|
||||
|
||||
|
||||
@pytest.fixture(name="plextv_resources_two_servers", scope="session")
|
||||
def plextv_resources_two_servers_fixture():
|
||||
"""Load two-server payload for plex.tv resources and return it."""
|
||||
return load_fixture("plex/plextv_resources_two_servers.xml")
|
||||
|
||||
|
||||
@pytest.fixture(name="plextv_shared_users", scope="session")
|
||||
def plextv_shared_users_fixture(plextv_resources_base):
|
||||
def plextv_shared_users_fixture():
|
||||
"""Load payload for plex.tv shared users and return it."""
|
||||
return load_fixture("plex/plextv_shared_users.xml")
|
||||
|
||||
|
@ -0,0 +1,18 @@
|
||||
<MediaContainer size="5">
|
||||
<Device name="Plex Server 1" product="Plex Media Server" productVersion="1.20.4.3517-ab5e1197c" platform="Linux" platformVersion="20.04.1 LTS (Focal Fossa)" device="PC" clientIdentifier="unique_id_123" createdAt="1429510140" lastSeenAt="1605500006" provides="server" owned="1" accessToken="faketoken" publicAddress="10.20.30.40" httpsRequired="0" synced="0" relay="0" dnsRebindingProtection="0" natLoopbackSupported="1" publicAddressMatches="1" presence="1">
|
||||
<Connection protocol="https" address="1.2.3.4" port="32400" uri="https://1-2-3-4.123456789001234567890.plex.direct:32400" local="1"/>
|
||||
</Device>
|
||||
<Device name="Chrome" product="Plex Web" productVersion="4.46.2" platform="Chrome" platformVersion="14.0" device="OSX" clientIdentifier="plexweb_id" createdAt="1578086003" lastSeenAt="1605461664" provides="client,player,pubsub-player" owned="1" publicAddress="10.20.30.40" publicAddressMatches="1" presence="1" accessToken="faketoken">
|
||||
<Connection protocol="https" address="1.2.3.5" port="32400" uri="https://1-2-3-5.123456789001234567890.plex.direct:32400" local="1"/>
|
||||
<Connection protocol="https" address="10.20.30.40" port="35872" uri="https://10-20-30-40.123456789001234567890.plex.direct:35872" local="0"/>
|
||||
</Device>
|
||||
<Device name="AppleTV" product="Plex for Apple TV" productVersion="7.9" platform="tvOS" platformVersion="14.2" device="Apple TV" clientIdentifier="A10E4083-BF1A-4586-B884-C638A32D5285" createdAt="1447217545" lastSeenAt="1605495521" provides="client,player,pubsub-player,provider-playback" owned="1" publicAddress="10.20.30.40" publicAddressMatches="1" presence="0">
|
||||
<Connection protocol="http" address="1.2.3.6" port="32500" uri="http://1.2.3.6:32500" local="1"/>
|
||||
</Device>
|
||||
<Device name="jPhone" product="Plex for iOS" productVersion="7.9" platform="iOS" platformVersion="14.2" device="iPhone" clientIdentifier="CDB83941-F8C2-4B56-989E-F3EFD0165BC1" createdAt="1537584529" lastSeenAt="1605501046" provides="client,controller,sync-target,player,pubsub-player,provider-playback" owned="1" publicAddress="10.20.30.40" publicAddressMatches="1" presence="0">
|
||||
<Connection protocol="http" address="1.2.3.7" port="32500" uri="http://1.2.3.7:32500" local="1"/>
|
||||
</Device>
|
||||
<Device name="SHIELD Android TV" product="Plex for Android (TV)" productVersion="8.8.2.21525" platform="Android" platformVersion="9" device="SHIELD Android TV" clientIdentifier="2f2a5ae50a45837c-com-plexapp-android" createdAt="1584850408" lastSeenAt="1605384938" provides="player,pubsub-player,controller" owned="1" publicAddress="10.20.30.40" publicAddressMatches="1" presence="1">
|
||||
<Connection protocol="http" address="1.2.3.11" port="32500" uri="http://1.2.3.11:32500" local="1"/>
|
||||
</Device>
|
||||
</MediaContainer>
|
@ -1,8 +1,8 @@
|
||||
<MediaContainer size="5">
|
||||
<Device name="Plex Server 1" product="Plex Media Server" productVersion="1.20.4.3517-ab5e1197c" platform="Linux" platformVersion="20.04.1 LTS (Focal Fossa)" device="PC" clientIdentifier="unique_id_123" createdAt="1429510140" lastSeenAt="1605500006" provides="server" owned="1" accessToken="faketoken" publicAddress="10.20.30.40" httpsRequired="0" synced="0" relay="0" dnsRebindingProtection="0" natLoopbackSupported="1" publicAddressMatches="1" presence="{first_server_enabled}">
|
||||
<MediaContainer size="6">
|
||||
<Device name="Plex Server 1" product="Plex Media Server" productVersion="1.20.4.3517-ab5e1197c" platform="Linux" platformVersion="20.04.1 LTS (Focal Fossa)" device="PC" clientIdentifier="unique_id_123" createdAt="1429510140" lastSeenAt="1605500006" provides="server" owned="1" accessToken="faketoken" publicAddress="10.20.30.40" httpsRequired="0" synced="0" relay="0" dnsRebindingProtection="0" natLoopbackSupported="1" publicAddressMatches="1" presence="1">
|
||||
<Connection protocol="https" address="1.2.3.4" port="32400" uri="https://1-2-3-4.123456789001234567890.plex.direct:32400" local="1"/>
|
||||
</Device>
|
||||
<Device name="Plex Server 2" product="Plex Media Server" productVersion="1.20.4.3517-ab5e1197c" platform="Linux" platformVersion="20.04.1 LTS (Focal Fossa)" device="PC" clientIdentifier="unique_id_456" createdAt="1429510140" lastSeenAt="1605500006" provides="server" owned="1" accessToken="faketoken" publicAddress="10.20.30.40" httpsRequired="0" synced="0" relay="0" dnsRebindingProtection="0" natLoopbackSupported="1" publicAddressMatches="1" presence="{second_server_enabled}">
|
||||
<Device name="Plex Server 2" product="Plex Media Server" productVersion="1.20.4.3517-ab5e1197c" platform="Linux" platformVersion="20.04.1 LTS (Focal Fossa)" device="PC" clientIdentifier="unique_id_456" createdAt="1429510140" lastSeenAt="1605500006" provides="server" owned="1" accessToken="faketoken" publicAddress="10.20.30.40" httpsRequired="0" synced="0" relay="0" dnsRebindingProtection="0" natLoopbackSupported="1" publicAddressMatches="1" presence="1">
|
||||
<Connection protocol="https" address="4.3.2.1" port="32400" uri="https://4-3-2-1.123456789001234567890.plex.direct:32400" local="1"/>
|
||||
</Device>
|
||||
<Device name="Chrome" product="Plex Web" productVersion="4.46.2" platform="Chrome" platformVersion="14.0" device="OSX" clientIdentifier="plexweb_id" createdAt="1578086003" lastSeenAt="1605461664" provides="client,player,pubsub-player" owned="1" publicAddress="10.20.30.40" publicAddressMatches="1" presence="1" accessToken="faketoken">
|
@ -198,7 +198,7 @@ async def test_multiple_servers_with_selection(
|
||||
hass,
|
||||
mock_plex_calls,
|
||||
requests_mock,
|
||||
plextv_resources_base,
|
||||
plextv_resources_two_servers,
|
||||
current_request_with_host,
|
||||
):
|
||||
"""Test creating an entry with multiple servers available."""
|
||||
@ -210,9 +210,7 @@ async def test_multiple_servers_with_selection(
|
||||
|
||||
requests_mock.get(
|
||||
"https://plex.tv/api/resources",
|
||||
text=plextv_resources_base.format(
|
||||
first_server_enabled=1, second_server_enabled=1
|
||||
),
|
||||
text=plextv_resources_two_servers,
|
||||
)
|
||||
with patch("plexauth.PlexAuth.initiate_auth"), patch(
|
||||
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN
|
||||
@ -231,7 +229,9 @@ async def test_multiple_servers_with_selection(
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
user_input={CONF_SERVER: MOCK_SERVERS[0][CONF_SERVER]},
|
||||
user_input={
|
||||
CONF_SERVER_IDENTIFIER: MOCK_SERVERS[0][CONF_SERVER_IDENTIFIER]
|
||||
},
|
||||
)
|
||||
assert result["type"] == "create_entry"
|
||||
|
||||
@ -250,47 +250,11 @@ async def test_multiple_servers_with_selection(
|
||||
assert result["data"][PLEX_SERVER_CONFIG][CONF_TOKEN] == MOCK_TOKEN
|
||||
|
||||
|
||||
async def test_only_non_present_servers(
|
||||
hass,
|
||||
mock_plex_calls,
|
||||
requests_mock,
|
||||
plextv_resources_base,
|
||||
current_request_with_host,
|
||||
):
|
||||
"""Test creating an entry with one server available."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}
|
||||
)
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
requests_mock.get(
|
||||
"https://plex.tv/api/resources",
|
||||
text=plextv_resources_base.format(
|
||||
first_server_enabled=0, second_server_enabled=0
|
||||
),
|
||||
)
|
||||
with patch("plexauth.PlexAuth.initiate_auth"), patch(
|
||||
"plexauth.PlexAuth.token", return_value=MOCK_TOKEN
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
assert result["type"] == "external"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||
assert result["type"] == "external_done"
|
||||
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"])
|
||||
assert result["type"] == "form"
|
||||
assert result["step_id"] == "select_server"
|
||||
|
||||
|
||||
async def test_adding_last_unconfigured_server(
|
||||
hass,
|
||||
mock_plex_calls,
|
||||
requests_mock,
|
||||
plextv_resources_base,
|
||||
plextv_resources_two_servers,
|
||||
current_request_with_host,
|
||||
):
|
||||
"""Test automatically adding last unconfigured server when multiple servers on account."""
|
||||
@ -310,9 +274,7 @@ async def test_adding_last_unconfigured_server(
|
||||
|
||||
requests_mock.get(
|
||||
"https://plex.tv/api/resources",
|
||||
text=plextv_resources_base.format(
|
||||
first_server_enabled=1, second_server_enabled=1
|
||||
),
|
||||
text=plextv_resources_two_servers,
|
||||
)
|
||||
|
||||
with patch("plexauth.PlexAuth.initiate_auth"), patch(
|
||||
@ -349,7 +311,7 @@ async def test_all_available_servers_configured(
|
||||
entry,
|
||||
requests_mock,
|
||||
plextv_account,
|
||||
plextv_resources_base,
|
||||
plextv_resources_two_servers,
|
||||
current_request_with_host,
|
||||
):
|
||||
"""Test when all available servers are already configured."""
|
||||
@ -372,9 +334,7 @@ async def test_all_available_servers_configured(
|
||||
requests_mock.get("https://plex.tv/users/account", text=plextv_account)
|
||||
requests_mock.get(
|
||||
"https://plex.tv/api/resources",
|
||||
text=plextv_resources_base.format(
|
||||
first_server_enabled=1, second_server_enabled=1
|
||||
),
|
||||
text=plextv_resources_two_servers,
|
||||
)
|
||||
|
||||
with patch("plexauth.PlexAuth.initiate_auth"), patch(
|
||||
|
Loading…
Reference in New Issue
Block a user