summaryrefslogtreecommitdiffstats
path: root/addons/metadata.tvshows.themoviedb.org.python/libs/actions.py
diff options
context:
space:
mode:
Diffstat (limited to 'addons/metadata.tvshows.themoviedb.org.python/libs/actions.py')
-rw-r--r--addons/metadata.tvshows.themoviedb.org.python/libs/actions.py240
1 files changed, 240 insertions, 0 deletions
diff --git a/addons/metadata.tvshows.themoviedb.org.python/libs/actions.py b/addons/metadata.tvshows.themoviedb.org.python/libs/actions.py
new file mode 100644
index 0000000..100476a
--- /dev/null
+++ b/addons/metadata.tvshows.themoviedb.org.python/libs/actions.py
@@ -0,0 +1,240 @@
+# -*- coding: UTF-8 -*-
+#
+# Copyright (C) 2020, Team Kodi
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+# pylint: disable=missing-docstring
+#
+# This is based on the metadata.tvmaze scrapper by Roman Miroshnychenko aka Roman V.M.
+
+"""Plugin route actions"""
+
+from __future__ import absolute_import, unicode_literals
+
+import sys
+import json
+import urllib.parse
+import xbmcgui
+import xbmcplugin
+from . import tmdb, data_utils
+from .utils import logger, safe_get
+try:
+ from typing import Optional, Text, Union, ByteString # pylint: disable=unused-import
+except ImportError:
+ pass
+
+HANDLE = int(sys.argv[1]) # type: int
+
+
+def find_show(title, year=None):
+ # type: (Union[Text, bytes], Optional[Text]) -> None
+ """Find a show by title"""
+ if not isinstance(title, str):
+ title = title.decode('utf-8')
+ logger.debug('Searching for TV show {} ({})'.format(title, year))
+ search_results = tmdb.search_show(title, year)
+ for search_result in search_results:
+ show_name = search_result['name']
+ if safe_get(search_result, 'first_air_date') is not None:
+ show_name += ' ({})'.format(search_result['first_air_date'][:4])
+ list_item = xbmcgui.ListItem(show_name, offscreen=True)
+ show_info = search_result
+ list_item = data_utils.add_main_show_info(
+ list_item, show_info, full_info=False)
+ # Below "url" is some unique ID string (may be an actual URL to a show page)
+ # that is used to get information about a specific TV show.
+ xbmcplugin.addDirectoryItem(
+ HANDLE,
+ url=str(search_result['id']),
+ listitem=list_item,
+ isFolder=True
+ )
+
+
+def get_show_id_from_nfo(nfo):
+ # type: (Text) -> None
+ """
+ Get show ID by NFO file contents
+
+ This function is called first instead of find_show
+ if a NFO file is found in a TV show folder.
+
+ :param nfo: the contents of a NFO file
+ """
+ if isinstance(nfo, bytes):
+ nfo = nfo.decode('utf-8', 'replace')
+ logger.debug('Parsing NFO file:\n{}'.format(nfo))
+ parse_result, named_seasons = data_utils.parse_nfo_url(nfo)
+ if parse_result:
+ if parse_result.provider == 'themoviedb':
+ show_info = tmdb.load_show_info(
+ parse_result.show_id, ep_grouping=parse_result.ep_grouping, named_seasons=named_seasons)
+ else:
+ show_info = None
+ if show_info is not None:
+ list_item = xbmcgui.ListItem(show_info['name'], offscreen=True)
+ # "url" is some string that unique identifies a show.
+ # It may be an actual URL of a TV show page.
+ xbmcplugin.addDirectoryItem(
+ HANDLE,
+ url=str(show_info['id']),
+ listitem=list_item,
+ isFolder=True
+ )
+
+
+def get_details(show_id):
+ # type: (Text) -> None
+ """Get details about a specific show"""
+ logger.debug('Getting details for show id {}'.format(show_id))
+ show_info = tmdb.load_show_info(show_id)
+ if show_info is not None:
+ list_item = xbmcgui.ListItem(show_info['name'], offscreen=True)
+ list_item = data_utils.add_main_show_info(
+ list_item, show_info, full_info=True)
+ xbmcplugin.setResolvedUrl(HANDLE, True, list_item)
+ else:
+ xbmcplugin.setResolvedUrl(
+ HANDLE, False, xbmcgui.ListItem(offscreen=True))
+
+
+def get_episode_list(show_ids): # pylint: disable=missing-docstring
+ # type: (Text) -> None
+ # Kodi has a bug: when a show directory contains an XML NFO file with
+ # episodeguide URL, that URL is always passed here regardless of
+ # the actual parsing result in get_show_from_nfo()
+ # so much of this weird logic is to deal with that
+ try:
+ all_ids = json.loads(show_ids)
+ show_id = all_ids.get('tmdb')
+ if not show_id:
+ for key, value in all_ids.items():
+ show_id = str(data_utils._convert_ext_id(key, value))
+ if show_id:
+ break
+ if not show_id:
+ show_id = str(show_ids)
+ except (ValueError, AttributeError):
+ show_id = str(show_ids)
+ if show_id.isdigit():
+ logger.error(
+ 'using deprecated episodeguide format, this show should be refreshed or rescraped')
+ if not show_id:
+ raise RuntimeError(
+ 'No TMDb TV show id found in episode guide, this show should be refreshed or rescraped')
+ elif not show_id.isdigit():
+ parse_result, named_seasons = data_utils.parse_nfo_url(show_id)
+ if parse_result:
+ show_id = parse_result.show_id
+ else:
+ raise RuntimeError(
+ 'No TMDb TV show id found in episode guide, this show should be refreshed or rescraped')
+ logger.debug('Getting episode list for show id {}'.format(show_id))
+ show_info = tmdb.load_show_info(show_id)
+ if show_info is not None:
+ theindex = 0
+ for episode in show_info['episodes']:
+ epname = episode.get('name', 'Episode ' +
+ str(episode['episode_number']))
+ list_item = xbmcgui.ListItem(epname, offscreen=True)
+ list_item = data_utils.add_episode_info(
+ list_item, episode, full_info=False)
+ encoded_ids = urllib.parse.urlencode(
+ {'show_id': str(show_info['id']), 'episode_id': str(theindex)}
+ )
+ theindex = theindex + 1
+ # Below "url" is some unique ID string (may be an actual URL to an episode page)
+ # that allows to retrieve information about a specific episode.
+ url = urllib.parse.quote(encoded_ids)
+ xbmcplugin.addDirectoryItem(
+ HANDLE,
+ url=url,
+ listitem=list_item,
+ isFolder=True
+ )
+ else:
+ logger.error(
+ 'unable to get show information using show id {}'.format(show_id))
+ logger.error('you may need to refresh the show to get a valid show id')
+
+
+def get_episode_details(encoded_ids): # pylint: disable=missing-docstring
+ # type: (Text) -> None
+ encoded_ids = urllib.parse.unquote(encoded_ids)
+ decoded_ids = dict(urllib.parse.parse_qsl(encoded_ids))
+ logger.debug('Getting episode details for {}'.format(decoded_ids))
+ episode_info = tmdb.load_episode_info(
+ decoded_ids['show_id'], decoded_ids['episode_id']
+ )
+ if episode_info:
+ list_item = xbmcgui.ListItem(episode_info['name'], offscreen=True)
+ list_item = data_utils.add_episode_info(
+ list_item, episode_info, full_info=True)
+ xbmcplugin.setResolvedUrl(HANDLE, True, list_item)
+ else:
+ xbmcplugin.setResolvedUrl(
+ HANDLE, False, xbmcgui.ListItem(offscreen=True))
+
+
+def get_artwork(show_id):
+ # type: (Text) -> None
+ """
+ Get available artwork for a show
+
+ :param show_id: default unique ID set by setUniqueIDs() method
+ """
+ if not show_id:
+ return
+ logger.debug('Getting artwork for show ID {}'.format(show_id))
+ show_info = tmdb.load_show_info(show_id)
+ if show_info is not None:
+ list_item = xbmcgui.ListItem(show_info['name'], offscreen=True)
+ list_item = data_utils.set_show_artwork(show_info, list_item)
+ xbmcplugin.setResolvedUrl(HANDLE, True, list_item)
+ else:
+ xbmcplugin.setResolvedUrl(
+ HANDLE, False, xbmcgui.ListItem(offscreen=True))
+
+
+def router(paramstring):
+ # type: (Text) -> None
+ """
+ Route addon calls
+
+ :param paramstring: url-encoded query string
+ :raises RuntimeError: on unknown call action
+ """
+ params = dict(urllib.parse.parse_qsl(paramstring))
+ logger.debug('Called addon with params: {}'.format(sys.argv))
+ if params['action'] == 'find':
+ logger.debug('performing find action')
+ find_show(params['title'], params.get('year'))
+ elif params['action'].lower() == 'nfourl':
+ logger.debug('performing nfourl action')
+ get_show_id_from_nfo(params['nfo'])
+ elif params['action'] == 'getdetails':
+ logger.debug('performing getdetails action')
+ get_details(params['url'])
+ elif params['action'] == 'getepisodelist':
+ logger.debug('performing getepisodelist action')
+ get_episode_list(params['url'])
+ elif params['action'] == 'getepisodedetails':
+ logger.debug('performing getepisodedetails action')
+ get_episode_details(params['url'])
+ elif params['action'] == 'getartwork':
+ logger.debug('performing getartwork action')
+ get_artwork(params.get('id'))
+ else:
+ raise RuntimeError('Invalid addon call: {}'.format(sys.argv))
+ xbmcplugin.endOfDirectory(HANDLE)