85 lines
2.4 KiB
Python
85 lines
2.4 KiB
Python
"""Helper methods to search for Plex media."""
|
|
import logging
|
|
|
|
from plexapi.exceptions import BadRequest, NotFound
|
|
|
|
LEGACY_PARAM_MAPPING = {
|
|
"show_name": "show.title",
|
|
"season_number": "season.index",
|
|
"episode_name": "episode.title",
|
|
"episode_number": "episode.index",
|
|
"artist_name": "artist.title",
|
|
"album_name": "album.title",
|
|
"track_name": "track.title",
|
|
"track_number": "track.index",
|
|
"video_name": "movie.title",
|
|
}
|
|
|
|
PREFERRED_LIBTYPE_ORDER = (
|
|
"episode",
|
|
"season",
|
|
"show",
|
|
"track",
|
|
"album",
|
|
"artist",
|
|
)
|
|
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
def search_media(media_type, library_section, allow_multiple=False, **kwargs):
|
|
"""Search for specified Plex media in the provided library section.
|
|
|
|
Returns a single media item or None.
|
|
|
|
If `allow_multiple` is `True`, return a list of matching items.
|
|
"""
|
|
search_query = {}
|
|
libtype = kwargs.pop("libtype", None)
|
|
|
|
# Preserve legacy service parameters
|
|
for legacy_key, key in LEGACY_PARAM_MAPPING.items():
|
|
if value := kwargs.pop(legacy_key, None):
|
|
_LOGGER.debug(
|
|
"Legacy parameter '%s' used, consider using '%s'", legacy_key, key
|
|
)
|
|
search_query[key] = value
|
|
|
|
search_query.update(**kwargs)
|
|
|
|
if not libtype:
|
|
# Default to a sane libtype if not explicitly provided
|
|
for preferred_libtype in PREFERRED_LIBTYPE_ORDER:
|
|
if any(key.startswith(preferred_libtype) for key in search_query):
|
|
libtype = preferred_libtype
|
|
break
|
|
|
|
search_query.update(libtype=libtype)
|
|
_LOGGER.debug("Processed search query: %s", search_query)
|
|
|
|
try:
|
|
results = library_section.search(**search_query)
|
|
except (BadRequest, NotFound) as exc:
|
|
_LOGGER.error("Problem in query %s: %s", search_query, exc)
|
|
return None
|
|
|
|
if not results:
|
|
return None
|
|
|
|
if len(results) > 1:
|
|
if allow_multiple:
|
|
return results
|
|
|
|
if title := search_query.get("title") or search_query.get("movie.title"):
|
|
exact_matches = [x for x in results if x.title.lower() == title.lower()]
|
|
if len(exact_matches) == 1:
|
|
return exact_matches[0]
|
|
_LOGGER.warning(
|
|
"Multiple matches, make content_id more specific or use `allow_multiple`: %s",
|
|
results,
|
|
)
|
|
return None
|
|
|
|
return results[0]
|