Merge pull request #1026 from croneter/search

Support Plex search across all media and Plex Media Servers: Navigate to the PlexKodiConnect Add-on, then "Search"
This commit is contained in:
croneter 2019-10-31 13:38:59 +01:00 committed by GitHub
commit 1618d96699
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 11 deletions

View file

@ -61,6 +61,13 @@ class Main():
elif mode == 'channels': elif mode == 'channels':
entrypoint.browse_plex(key='/channels/all') entrypoint.browse_plex(key='/channels/all')
elif mode == 'search':
# "Search"
entrypoint.browse_plex(key='/hubs/search',
args={'includeCollections': 1,
'includeExternalMedia': 1},
prompt=utils.lang(137))
elif mode == 'route_to_extras': elif mode == 'route_to_extras':
# Hack so we can store this path in the Kodi DB # Hack so we can store this path in the Kodi DB
handle = ('plugin://%s?mode=extras&plex_id=%s' handle = ('plugin://%s?mode=extras&plex_id=%s'

View file

@ -146,6 +146,8 @@ def show_main_menu(content_type=None):
if content_type: if content_type:
path += '&content_type=%s' % content_type path += '&content_type=%s' % content_type
directory_item('Plex Hub', path) directory_item('Plex Hub', path)
# Plex Search "Search"
directory_item(utils.lang(137), "plugin://%s?mode=search" % v.ADDON_ID)
# Plex Watch later # Plex Watch later
if content_type not in ('image', 'audio'): if content_type not in ('image', 'audio'):
directory_item(utils.lang(39211), directory_item(utils.lang(39211),
@ -466,7 +468,7 @@ def watchlater():
def browse_plex(key=None, plex_type=None, section_id=None, synched=True, def browse_plex(key=None, plex_type=None, section_id=None, synched=True,
prompt=None): args=None, prompt=None):
""" """
Lists the content of a Plex folder, e.g. channels. Either pass in key (to Lists the content of a Plex folder, e.g. channels. Either pass in key (to
be used directly for PMS url {server}<key>) or the section_id be used directly for PMS url {server}<key>) or the section_id
@ -474,28 +476,43 @@ def browse_plex(key=None, plex_type=None, section_id=None, synched=True,
Pass synched=False if the items have NOT been synched to the Kodi DB Pass synched=False if the items have NOT been synched to the Kodi DB
""" """
LOG.debug('Browsing to key %s, section %s, plex_type: %s, synched: %s, ' LOG.debug('Browsing to key %s, section %s, plex_type: %s, synched: %s, '
'prompt "%s"', key, section_id, plex_type, synched, prompt) 'prompt "%s", args %s', key, section_id, plex_type, synched,
prompt, args)
if not _wait_for_auth(): if not _wait_for_auth():
xbmcplugin.endOfDirectory(int(sys.argv[1]), False) xbmcplugin.endOfDirectory(int(sys.argv[1]), False)
return return
app.init(entrypoint=True) app.init(entrypoint=True)
args = args or {}
if prompt: if prompt:
prompt = utils.dialog('input', prompt) prompt = utils.dialog('input', prompt)
if prompt is None: if prompt is None:
# User cancelled # User cancelled
return return
prompt = prompt.strip().decode('utf-8') prompt = prompt.strip().decode('utf-8')
if '?' not in key: args['query'] = prompt
key = '%s?query=%s' % (key, prompt) xml = DU().downloadUrl(utils.extend_url('{server}%s' % key, args))
else:
key = '%s&query=%s' % (key, prompt)
xml = DU().downloadUrl('{server}%s' % key)
try: try:
xml.attrib xml[0].attrib
except AttributeError: except (TypeError, IndexError, AttributeError):
LOG.error('Could not browse to key %s, section %s', LOG.error('Could not browse to key %s, section %s',
key, section_id) key, section_id)
return return
if xml[0].tag == 'Hub':
# E.g. when hitting the endpoint '/hubs/search'
answ = utils.etree.Element(xml.tag, attrib=xml.attrib)
for hub in xml:
if not utils.cast(int, hub.get('size')):
# Empty category
continue
for entry in hub:
api = API(entry)
if api.plex_type == v.PLEX_TYPE_TAG:
# Append the type before the actual element for all "tags"
# like genres, actors, etc.
entry.attrib['tag'] = '%s: %s' % (hub.get('title'),
api.tag_label())
answ.append(entry)
xml = answ
show_listing(xml, plex_type, section_id, synched, key) show_listing(xml, plex_type, section_id, synched, key)

View file

@ -57,6 +57,12 @@ class Base(object):
""" """
return self.xml.tag return self.xml.tag
def tag_label(self):
"""
Returns the 'tag' attribute of the xml
"""
return self.xml.get('tag')
@property @property
def attrib(self): def attrib(self):
""" """

View file

@ -181,6 +181,9 @@ PLEX_TYPE_PHOTO = 'photo'
PLEX_TYPE_PLAYLIST = 'playlist' PLEX_TYPE_PLAYLIST = 'playlist'
PLEX_TYPE_CHANNEL = 'channel' PLEX_TYPE_CHANNEL = 'channel'
# E.g. PMS answer when hitting the PMS endpoint /hubs/search
PLEX_TYPE_TAG = 'tag'
# Used for /:/timeline XML messages # Used for /:/timeline XML messages
PLEX_PLAYLIST_TYPE_VIDEO = 'video' PLEX_PLAYLIST_TYPE_VIDEO = 'video'
PLEX_PLAYLIST_TYPE_AUDIO = 'music' PLEX_PLAYLIST_TYPE_AUDIO = 'music'

View file

@ -105,9 +105,10 @@ def _generate_folder(api):
return content return content
else: else:
art = api.artwork() art = api.artwork()
title = api.title() if api.plex_type != v.PLEX_TYPE_TAG else api.tag_label()
return { return {
'title': api.title(), 'title': title,
'label': api.title(), 'label': title,
'file': api.directory_path(section_id=SECTION_ID, 'file': api.directory_path(section_id=SECTION_ID,
plex_type=PLEX_TYPE, plex_type=PLEX_TYPE,
old_key=KEY), old_key=KEY),