core/homeassistant/components/plex/__init__.py

181 lines
5.2 KiB
Python
Raw Normal View History

"""Support to embed Plex."""
import asyncio
from datetime import timedelta
import logging
import plexapi.exceptions
import requests.exceptions
import voluptuous as vol
from homeassistant import config_entries
from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
from homeassistant.const import (
CONF_HOST,
CONF_PORT,
CONF_SSL,
CONF_TOKEN,
CONF_URL,
CONF_VERIFY_SSL,
)
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.event import async_track_time_interval
from .const import (
CONF_USE_EPISODE_ART,
CONF_SHOW_ALL_CONTROLS,
CONF_SERVER,
CONF_SERVER_IDENTIFIER,
DEFAULT_PORT,
DEFAULT_SSL,
DEFAULT_VERIFY_SSL,
DISPATCHERS,
DOMAIN as PLEX_DOMAIN,
PLATFORMS,
PLEX_MEDIA_PLAYER_OPTIONS,
PLEX_SERVER_CONFIG,
REFRESH_LISTENERS,
SERVERS,
)
from .server import PlexServer
MEDIA_PLAYER_SCHEMA = vol.Schema(
{
vol.Optional(CONF_USE_EPISODE_ART, default=False): cv.boolean,
vol.Optional(CONF_SHOW_ALL_CONTROLS, default=False): cv.boolean,
}
)
SERVER_CONFIG_SCHEMA = vol.Schema(
vol.All(
{
vol.Optional(CONF_HOST): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_TOKEN): cv.string,
vol.Optional(CONF_SERVER): cv.string,
vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean,
vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean,
vol.Optional(MP_DOMAIN, default={}): MEDIA_PLAYER_SCHEMA,
},
cv.has_at_least_one_key(CONF_HOST, CONF_TOKEN),
)
)
CONFIG_SCHEMA = vol.Schema({PLEX_DOMAIN: SERVER_CONFIG_SCHEMA}, extra=vol.ALLOW_EXTRA)
_LOGGER = logging.getLogger(__package__)
def setup(hass, config):
"""Set up the Plex component."""
hass.data.setdefault(
PLEX_DOMAIN, {SERVERS: {}, REFRESH_LISTENERS: {}, DISPATCHERS: {}}
)
plex_config = config.get(PLEX_DOMAIN, {})
if plex_config:
_setup_plex(hass, plex_config)
return True
def _setup_plex(hass, config):
"""Pass configuration to a config flow."""
server_config = dict(config)
if MP_DOMAIN in server_config:
hass.data.setdefault(PLEX_MEDIA_PLAYER_OPTIONS, server_config.pop(MP_DOMAIN))
if CONF_HOST in server_config:
prefix = "https" if server_config.pop(CONF_SSL) else "http"
server_config[
CONF_URL
] = f"{prefix}://{server_config.pop(CONF_HOST)}:{server_config.pop(CONF_PORT)}"
hass.async_create_task(
hass.config_entries.flow.async_init(
PLEX_DOMAIN,
context={"source": config_entries.SOURCE_IMPORT},
data=server_config,
)
)
async def async_setup_entry(hass, entry):
"""Set up Plex from a config entry."""
server_config = entry.data[PLEX_SERVER_CONFIG]
if MP_DOMAIN not in entry.options:
options = dict(entry.options)
options.setdefault(
MP_DOMAIN,
hass.data.get(PLEX_MEDIA_PLAYER_OPTIONS) or MEDIA_PLAYER_SCHEMA({}),
)
hass.config_entries.async_update_entry(entry, options=options)
plex_server = PlexServer(hass, server_config, entry.options)
try:
await hass.async_add_executor_job(plex_server.connect)
except requests.exceptions.ConnectionError as error:
_LOGGER.error(
"Plex server (%s) could not be reached: [%s]",
server_config[CONF_URL],
error,
)
return False
except (
plexapi.exceptions.BadRequest,
plexapi.exceptions.Unauthorized,
plexapi.exceptions.NotFound,
) as error:
_LOGGER.error(
"Login to %s failed, verify token and SSL settings: [%s]",
entry.data[CONF_SERVER],
error,
)
return False
_LOGGER.debug(
"Connected to: %s (%s)", plex_server.friendly_name, plex_server.url_in_use
)
server_id = plex_server.machine_identifier
hass.data[PLEX_DOMAIN][SERVERS][server_id] = plex_server
hass.data[PLEX_DOMAIN][DISPATCHERS][server_id] = []
for platform in PLATFORMS:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, platform)
)
entry.add_update_listener(async_options_updated)
hass.data[PLEX_DOMAIN][REFRESH_LISTENERS][server_id] = async_track_time_interval(
hass, lambda now: plex_server.update_platforms(), timedelta(seconds=10)
)
return True
async def async_unload_entry(hass, entry):
"""Unload a config entry."""
server_id = entry.data[CONF_SERVER_IDENTIFIER]
cancel = hass.data[PLEX_DOMAIN][REFRESH_LISTENERS].pop(server_id)
cancel()
dispatchers = hass.data[PLEX_DOMAIN][DISPATCHERS].pop(server_id)
for unsub in dispatchers:
unsub()
tasks = [
hass.config_entries.async_forward_entry_unload(entry, platform)
for platform in PLATFORMS
]
await asyncio.gather(*tasks)
hass.data[PLEX_DOMAIN][SERVERS].pop(server_id)
return True
async def async_options_updated(hass, entry):
"""Triggered by config entry options updates."""
server_id = entry.data[CONF_SERVER_IDENTIFIER]
hass.data[PLEX_DOMAIN][SERVERS][server_id].options = entry.options