mirror of
https://github.com/pkkid/python-plexapi
synced 2024-11-12 23:17:07 +00:00
Fix server hub searches (#643)
* Add hub search media tag objects * Fix server search * Fix hub media tag thumb * Update server search test with tags
This commit is contained in:
parent
a9a44a6a41
commit
dfc5aa1eef
5 changed files with 149 additions and 7 deletions
|
@ -77,7 +77,7 @@ class PlexObject(object):
|
||||||
if cls is not None:
|
if cls is not None:
|
||||||
return cls(self._server, elem, initpath, parent=self)
|
return cls(self._server, elem, initpath, parent=self)
|
||||||
# cls is not specified, try looking it up in PLEXOBJECTS
|
# cls is not specified, try looking it up in PLEXOBJECTS
|
||||||
etype = elem.attrib.get('type', elem.attrib.get('streamType'))
|
etype = elem.attrib.get('streamType', elem.attrib.get('tagType', elem.attrib.get('type')))
|
||||||
ehash = '%s.%s' % (elem.tag, etype) if etype else elem.tag
|
ehash = '%s.%s' % (elem.tag, etype) if etype else elem.tag
|
||||||
ecls = utils.PLEXOBJECTS.get(ehash, utils.PLEXOBJECTS.get(elem.tag))
|
ecls = utils.PLEXOBJECTS.get(ehash, utils.PLEXOBJECTS.get(elem.tag))
|
||||||
# log.debug('Building %s as %s', elem.tag, ecls.__name__)
|
# log.debug('Building %s as %s', elem.tag, ecls.__name__)
|
||||||
|
|
|
@ -1247,6 +1247,110 @@ class Hub(PlexObject):
|
||||||
self.size = len(self.items)
|
self.size = len(self.items)
|
||||||
|
|
||||||
|
|
||||||
|
class HubMediaTag(PlexObject):
|
||||||
|
""" Base class of hub media tag search results.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
count (int): The number of items where this tag is found.
|
||||||
|
filter (str): The URL filter for the tag.
|
||||||
|
id (int): The id of the tag.
|
||||||
|
key (str): API URL (/library/section/<librarySectionID>/all?<filter>).
|
||||||
|
librarySectionID (int): The library section ID where the tag is found.
|
||||||
|
librarySectionKey (str): API URL for the library section (/library/section/<librarySectionID>)
|
||||||
|
librarySectionTitle (str): The library title where the tag is found.
|
||||||
|
librarySectionType (int): The library type where the tag is found.
|
||||||
|
reason (str): The reason for the search result.
|
||||||
|
reasonID (int): The reason ID for the search result.
|
||||||
|
reasonTitle (str): The reason title for the search result.
|
||||||
|
type (str): The type of search result (tag).
|
||||||
|
tag (str): The title of the tag.
|
||||||
|
tagType (int): The type ID of the tag.
|
||||||
|
tagValue (int): The value of the tag.
|
||||||
|
thumb (str): The URL for the thumbnail of the tag (if available).
|
||||||
|
"""
|
||||||
|
TAG = 'Directory'
|
||||||
|
|
||||||
|
def _loadData(self, data):
|
||||||
|
""" Load attribute values from Plex XML response. """
|
||||||
|
self._data = data
|
||||||
|
self.count = utils.cast(int, data.attrib.get('count'))
|
||||||
|
self.filter = data.attrib.get('filter')
|
||||||
|
self.id = utils.cast(int, data.attrib.get('id'))
|
||||||
|
self.key = data.attrib.get('key')
|
||||||
|
self.librarySectionID = utils.cast(int, data.attrib.get('librarySectionID'))
|
||||||
|
self.librarySectionKey = data.attrib.get('librarySectionKey')
|
||||||
|
self.librarySectionTitle = data.attrib.get('librarySectionTitle')
|
||||||
|
self.librarySectionType = utils.cast(int, data.attrib.get('librarySectionType'))
|
||||||
|
self.reason = data.attrib.get('reason')
|
||||||
|
self.reasonID = utils.cast(int, data.attrib.get('reasonID'))
|
||||||
|
self.reasonTitle = data.attrib.get('reasonTitle')
|
||||||
|
self.type = data.attrib.get('type')
|
||||||
|
self.tag = data.attrib.get('tag')
|
||||||
|
self.tagType = utils.cast(int, data.attrib.get('tagType'))
|
||||||
|
self.tagValue = utils.cast(int, data.attrib.get('tagValue'))
|
||||||
|
self.thumb = data.attrib.get('thumb')
|
||||||
|
|
||||||
|
|
||||||
|
@utils.registerPlexObject
|
||||||
|
class Tag(HubMediaTag):
|
||||||
|
""" Represents a single Tag hub search media tag.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
TAGTYPE (int): 0
|
||||||
|
"""
|
||||||
|
TAGTYPE = 0
|
||||||
|
|
||||||
|
|
||||||
|
@utils.registerPlexObject
|
||||||
|
class Genre(HubMediaTag):
|
||||||
|
""" Represents a single Genre hub search media tag.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
TAGTYPE (int): 1
|
||||||
|
"""
|
||||||
|
TAGTYPE = 1
|
||||||
|
|
||||||
|
|
||||||
|
@utils.registerPlexObject
|
||||||
|
class Director(HubMediaTag):
|
||||||
|
""" Represents a single Director hub search media tag.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
TAGTYPE (int): 4
|
||||||
|
"""
|
||||||
|
TAGTYPE = 4
|
||||||
|
|
||||||
|
|
||||||
|
@utils.registerPlexObject
|
||||||
|
class Actor(HubMediaTag):
|
||||||
|
""" Represents a single Actor hub search media tag.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
TAGTYPE (int): 6
|
||||||
|
"""
|
||||||
|
TAGTYPE = 6
|
||||||
|
|
||||||
|
|
||||||
|
@utils.registerPlexObject
|
||||||
|
class AutoTag(HubMediaTag):
|
||||||
|
""" Represents a single AutoTag hub search media tag.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
TAGTYPE (int): 207
|
||||||
|
"""
|
||||||
|
TAGTYPE = 207
|
||||||
|
|
||||||
|
|
||||||
|
@utils.registerPlexObject
|
||||||
|
class Place(HubMediaTag):
|
||||||
|
""" Represents a single Place hub search media tag.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
TAGTYPE (int): 400
|
||||||
|
"""
|
||||||
|
TAGTYPE = 400
|
||||||
|
|
||||||
|
|
||||||
@utils.registerPlexObject
|
@utils.registerPlexObject
|
||||||
class Station(PlexObject):
|
class Station(PlexObject):
|
||||||
""" Represents the Station area in the MusicSection.
|
""" Represents the Station area in the MusicSection.
|
||||||
|
|
|
@ -522,17 +522,24 @@ class PlexServer(PlexObject):
|
||||||
Parameters:
|
Parameters:
|
||||||
query (str): Query to use when searching your library.
|
query (str): Query to use when searching your library.
|
||||||
mediatype (str): Optionally limit your search to the specified media type.
|
mediatype (str): Optionally limit your search to the specified media type.
|
||||||
|
actor, album, artist, autotag, collection, director, episode, game, genre,
|
||||||
|
movie, photo, photoalbum, place, playlist, shared, show, tag, track
|
||||||
limit (int): Optionally limit to the specified number of results per Hub.
|
limit (int): Optionally limit to the specified number of results per Hub.
|
||||||
"""
|
"""
|
||||||
results = []
|
results = []
|
||||||
params = {'query': query}
|
params = {
|
||||||
if mediatype:
|
'query': query,
|
||||||
params['section'] = utils.SEARCHTYPES[mediatype]
|
'includeCollections': 1,
|
||||||
|
'includeExternalMedia': 1}
|
||||||
if limit:
|
if limit:
|
||||||
params['limit'] = limit
|
params['limit'] = limit
|
||||||
key = '/hubs/search?%s' % urlencode(params)
|
key = '/hubs/search?%s' % urlencode(params)
|
||||||
for hub in self.fetchItems(key, Hub):
|
for hub in self.fetchItems(key, Hub):
|
||||||
results += hub.items
|
if mediatype:
|
||||||
|
if hub.type == mediatype:
|
||||||
|
return hub.items
|
||||||
|
else:
|
||||||
|
results += hub.items
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def sessions(self):
|
def sessions(self):
|
||||||
|
|
|
@ -57,7 +57,7 @@ def registerPlexObject(cls):
|
||||||
define a few helper functions to dynamically convery the XML into objects. See
|
define a few helper functions to dynamically convery the XML into objects. See
|
||||||
buildItem() below for an example.
|
buildItem() below for an example.
|
||||||
"""
|
"""
|
||||||
etype = getattr(cls, 'STREAMTYPE', cls.TYPE)
|
etype = getattr(cls, 'STREAMTYPE', getattr(cls, 'TAGTYPE', cls.TYPE))
|
||||||
ehash = '%s.%s' % (cls.TAG, etype) if etype else cls.TAG
|
ehash = '%s.%s' % (cls.TAG, etype) if etype else cls.TAG
|
||||||
if ehash in PLEXOBJECTS:
|
if ehash in PLEXOBJECTS:
|
||||||
raise Exception('Ambiguous PlexObject definition %s(tag=%s, type=%s) with %s' %
|
raise Exception('Ambiguous PlexObject definition %s(tag=%s, type=%s) with %s' %
|
||||||
|
|
|
@ -109,7 +109,38 @@ def test_server_search(plex, movie):
|
||||||
title = movie.title
|
title = movie.title
|
||||||
# this search seem to fail on my computer but not at travis, wtf.
|
# this search seem to fail on my computer but not at travis, wtf.
|
||||||
assert plex.search(title)
|
assert plex.search(title)
|
||||||
assert plex.search(title, mediatype="movie")
|
results = plex.search(title, mediatype="movie")
|
||||||
|
assert results[0] == movie
|
||||||
|
# Test genre search
|
||||||
|
genre = movie.genres[0]
|
||||||
|
results = plex.search(genre.tag, mediatype="genre")
|
||||||
|
hub_tag = results[0]
|
||||||
|
assert utils.is_int(hub_tag.count)
|
||||||
|
assert hub_tag.filter == "genre={}".format(hub_tag.id)
|
||||||
|
assert utils.is_int(hub_tag.id)
|
||||||
|
assert utils.is_metadata(
|
||||||
|
hub_tag.key,
|
||||||
|
prefix=hub_tag.librarySectionKey,
|
||||||
|
contains="{}/all".format(hub_tag.librarySectionID),
|
||||||
|
suffix=hub_tag.filter)
|
||||||
|
assert utils.is_int(hub_tag.librarySectionID)
|
||||||
|
assert utils.is_metadata(hub_tag.librarySectionKey, prefix="/library/sections")
|
||||||
|
assert hub_tag.librarySectionTitle == "Movies"
|
||||||
|
assert hub_tag.librarySectionType == 1
|
||||||
|
assert hub_tag.reason == "section"
|
||||||
|
assert hub_tag.reasonID == hub_tag.librarySectionID
|
||||||
|
assert hub_tag.reasonTitle == hub_tag.librarySectionTitle
|
||||||
|
assert hub_tag.type == "tag"
|
||||||
|
assert hub_tag.tag == genre.tag
|
||||||
|
assert hub_tag.tagType == 1
|
||||||
|
assert hub_tag.tagValue is None
|
||||||
|
assert hub_tag.thumb is None
|
||||||
|
# Test director search
|
||||||
|
director = movie.directors[0]
|
||||||
|
assert plex.search(director.tag, mediatype="director")
|
||||||
|
# Test actor search
|
||||||
|
role = movie.roles[0]
|
||||||
|
assert plex.search(role.tag, mediatype="actor")
|
||||||
|
|
||||||
|
|
||||||
def test_server_playlist(plex, show):
|
def test_server_playlist(plex, show):
|
||||||
|
|
Loading…
Reference in a new issue