def __init__(self):
     self.handle = int(sys.argv[1])
     self.paramstring = try_decode(sys.argv[2][1:])
     self.params = parse_paramstring(self.paramstring)
     self.parent_params = self.params
     # self.container_path = u'{}?{}'.format(sys.argv[0], self.paramstring)
     self.update_listing = False
     self.plugin_category = ''
     self.container_content = ''
     self.container_update = None
     self.container_refresh = False
     self.item_type = None
     self.kodi_db = None
     self.kodi_db_tv = {}
     self.library = None
     self.tmdb_cache_only = True
     self.tmdb_api = TMDb()
     self.trakt_watchedindicators = ADDON.getSettingBool('trakt_watchedindicators')
     self.trakt_api = TraktAPI()
     self.is_widget = True if self.params.pop('widget', '').lower() == 'true' else False
     self.hide_watched = ADDON.getSettingBool('widgets_hidewatched') if self.is_widget else False
     self.flatten_seasons = ADDON.getSettingBool('flatten_seasons')
     self.ftv_forced_lookup = self.params.pop('fanarttv', '').lower()
     self.ftv_api = FanartTV(cache_only=self.ftv_is_cache_only())
     self.filter_key = self.params.pop('filter_key', None)
     self.filter_value = split_items(self.params.pop('filter_value', None))[0]
     self.exclude_key = self.params.pop('exclude_key', None)
     self.exclude_value = split_items(self.params.pop('exclude_value', None))[0]
     self.pagination = self.pagination_is_allowed()
     self.params = reconfigure_legacy_params(**self.params)
Esempio n. 2
0
    def play(self, folder_path=None, reset_focus=None, handle=None):
        # Get some info about current container for container update hack
        if not folder_path:
            folder_path = xbmc.getInfoLabel("Container.FolderPath")
        if not reset_focus and folder_path:
            containerid = xbmc.getInfoLabel("System.CurrentControlID")
            current_pos = xbmc.getInfoLabel("Container({}).CurrentItem".format(containerid))
            reset_focus = 'SetFocus({},{},absolute)'.format(containerid, try_int(current_pos) - 1)

        # Get the resolved path
        listitem = self.get_resolved_path()

        # Reset folder hack
        self._update_listing_hack(folder_path=folder_path, reset_focus=reset_focus)

        # Check we have an actual path to open
        if not listitem.getPath() or listitem.getPath() == PLUGINPATH:
            return

        action = self.configure_action(listitem, handle)

        # Kodi launches busy dialog on home screen that needs to be told to close
        # Otherwise the busy dialog will prevent window activation for folder path
        xbmc.executebuiltin('Dialog.Close(busydialog)')

        # If a folder we need to resolve to dummy and then open folder
        if listitem.getProperty('is_folder') == 'true':
            if self.is_strm or not ADDON.getSettingBool('only_resolve_strm'):
                resolve_to_dummy(handle, self.dummy_duration, self.dummy_delay)
            xbmc.executebuiltin(action)
            kodi_log(['lib.player - finished executing action\n', action], 1)
            return

        # Set our playerstring for player monitor to update kodi watched status
        if self.playerstring:
            get_property('PlayerInfoString', set_property=self.playerstring)

        # If PlayMedia method chosen re-route to Player() unless expert settings on
        if action:
            if self.is_strm or not ADDON.getSettingBool('only_resolve_strm'):
                resolve_to_dummy(handle, self.dummy_duration, self.dummy_delay)  # If we're calling external we need to resolve to dummy
            xbmc.Player().play(action, listitem) if self.force_xbmcplayer else xbmc.executebuiltin(u'PlayMedia({})'.format(action))
            kodi_log([
                'lib.player - playing path with {}\n'.format('xbmc.Player()' if self.force_xbmcplayer else 'PlayMedia'),
                listitem.getPath()], 1)
            return

        # Otherwise we have a url we can resolve to
        xbmcplugin.setResolvedUrl(handle, True, listitem)
        kodi_log(['lib.player - finished resolving path to url\n', listitem.getPath()], 1)

        # Re-send local files to player due to "bug" (or maybe "feature") of setResolvedUrl
        # Because setResolvedURL doesn't set id/type (sets None, "unknown" instead) to player for plugins
        # If id/type not set to Player.GetItem things like Trakt don't work correctly.
        # Looking for better solution than this hack.
        if ADDON.getSettingBool('trakt_localhack') and listitem.getProperty('is_local') == 'true':
            xbmc.Player().play(listitem.getPath(), listitem) if self.force_xbmcplayer else xbmc.executebuiltin(u'PlayMedia({})'.format(listitem.getPath()))
            kodi_log([
                'Finished executing {}\n'.format('xbmc.Player()' if self.force_xbmcplayer else 'PlayMedia'),
                listitem.getPath()], 1)
 def ftv_is_cache_only(self):
     if self.ftv_forced_lookup == 'true':
         return False
     if self.ftv_forced_lookup == 'false':
         return True
     if self.is_widget and ADDON.getSettingBool('widget_fanarttv_lookup'):
         return False
     if not self.is_widget and ADDON.getSettingBool('fanarttv_lookup'):
         return False
     return True
Esempio n. 4
0
 def __init__(self, busy_spinner=True):
     self.kodi_db_movies = rpc.get_kodi_library('movie')
     self.kodi_db_tv = rpc.get_kodi_library('tv')
     self.p_dialog = xbmcgui.DialogProgressBG() if busy_spinner else None
     self.auto_update = ADDON.getSettingBool('auto_update')
     self._log = _LibraryLogger()
     self.tv = None
     self.hide_unaired = ADDON.getSettingBool('hide_unaired_episodes')
     # self.debug_logging = ADDON.getSettingBool('debug_logging')
     self.debug_logging = True
Esempio n. 5
0
    def get_playingitem(self):
        if not self.isPlayingVideo():
            return  # Not a video so don't get info
        if self.getVideoInfoTag().getMediaType() not in ['movie', 'episode']:
            return  # Not a movie or episode so don't get info TODO Maybe get PVR details also?
        self.playerstring = get_property('PlayerInfoString')
        self.playerstring = loads(
            self.playerstring) if self.playerstring else None

        self.total_time = self.getTotalTime()
        self.dbtype = self.getVideoInfoTag().getMediaType()
        self.dbid = self.getVideoInfoTag().getDbId()
        self.imdb_id = self.getVideoInfoTag().getIMDBNumber()
        self.query = self.getVideoInfoTag().getTVShowTitle(
        ) if self.dbtype == 'episode' else self.getVideoInfoTag().getTitle()
        self.year = self.getVideoInfoTag().getYear(
        ) if self.dbtype == 'movie' else None
        self.epyear = self.getVideoInfoTag().getYear(
        ) if self.dbtype == 'episodes' else None
        self.season = self.getVideoInfoTag().getSeason(
        ) if self.dbtype == 'episodes' else None
        self.episode = self.getVideoInfoTag().getEpisode(
        ) if self.dbtype == 'episodes' else None
        self.query = try_decode(self.query)

        self.tmdb_type = 'movie' if self.dbtype == 'movie' else 'tv'
        self.tmdb_id = self.get_tmdb_id(self.tmdb_type, self.imdb_id,
                                        self.query, self.year, self.epyear)
        self.details = self.tmdb_api.get_details(self.tmdb_type, self.tmdb_id,
                                                 self.season, self.episode)

        # Clear everything if we didn't get details because nothing to compare
        if not self.details:
            return self.reset_properties()

        # Get ratings (no need for threading since we're only getting one item in player ever)
        if xbmc.getCondVisibility(
                "!Skin.HasSetting(TMDbHelper.DisableRatings)"):
            self.details = self.get_omdb_ratings(self.details)
            if self.tmdb_type == 'movie':
                self.details = self.get_imdb_top250_rank(self.details)
            if self.tmdb_type in ['movie', 'tv']:
                self.details = self.get_trakt_ratings(
                    self.details,
                    'movie' if self.tmdb_type == 'movie' else 'show',
                    season=self.season,
                    episode=self.episode)
            self.set_iter_properties(self.details.get('infoproperties', {}),
                                     SETPROP_RATINGS)

        # Get artwork (no need for threading since we're only getting one item in player ever)
        # No need for merging Kodi DB artwork as we should have access to that via normal player properties
        if xbmc.getCondVisibility(
                "!Skin.HasSetting(TMDbHelper.DisableArtwork)"):
            if ADDON.getSettingBool('service_fanarttv_lookup'):
                self.details = self.get_fanarttv_artwork(
                    self.details, self.tmdb_type)
            self.set_iter_properties(self.details, SETMAIN_ARTWORK)

        self.set_properties(self.details)
Esempio n. 6
0
    def run(self):
        self.xbmc_monitor.waitForAbort(
            600)  # Wait 10 minutes before doing updates to give boot time
        if self.xbmc_monitor.abortRequested():
            del self.xbmc_monitor
            return

        self.next_time = datetime.datetime.combine(
            datetime.datetime.today(),
            datetime.time(try_int(self.update_hour)))  # Get today at hour
        self.last_time = xbmc.getInfoLabel(
            'Skin.String(TMDbHelper.AutoUpdate.LastTime)')  # Get last update
        self.last_time = convert_timestamp(
            self.last_time) if self.last_time else None
        if self.last_time and self.last_time > self.next_time:
            self.next_time += datetime.timedelta(
                hours=24)  # Already updated today so set for tomorrow

        while not self.xbmc_monitor.abortRequested(
        ) and not self.exit and self.poll_time:
            if ADDON.getSettingBool('library_autoupdate'):
                if datetime.datetime.now(
                ) > self.next_time:  # Scheduled time has past so lets update
                    xbmc.executebuiltin(
                        'RunScript(plugin.video.themoviedb.helper,library_autoupdate)'
                    )
                    xbmc.executebuiltin(
                        'Skin.SetString(TMDbHelper.AutoUpdate.LastTime,{})'.
                        format(datetime.datetime.now().strftime(
                            "%Y-%m-%dT%H:%M:%S")))
                    self.next_time += datetime.timedelta(
                        hours=24)  # Set next update for tomorrow
            self.xbmc_monitor.waitForAbort(self.poll_time)

        del self.xbmc_monitor
Esempio n. 7
0
 def __init__(self,
              tmdb_type,
              tmdb_id=None,
              season=None,
              episode=None,
              ignore_default=False,
              **kwargs):
     self.players = get_players_from_file()
     self.details = get_item_details(tmdb_type, tmdb_id, season, episode)
     self.item = get_detailed_item(
         tmdb_type, tmdb_id, season, episode, details=self.details) or {}
     self.playerstring = get_playerstring(tmdb_type,
                                          tmdb_id,
                                          season,
                                          episode,
                                          details=self.details)
     self.dialog_players = self._get_players_for_dialog(tmdb_type)
     self.default_player = ADDON.getSettingString(
         'default_player_movies'
     ) if tmdb_type == 'movie' else ADDON.getSettingString(
         'default_player_episodes')
     self.ignore_default = ignore_default
     self.tmdb_type, self.tmdb_id, self.season, self.episode = tmdb_type, tmdb_id, season, episode
     self.dummy_duration = try_float(
         ADDON.getSettingString('dummy_duration')) or 1.0
     self.dummy_delay = try_float(
         ADDON.getSettingString('dummy_delay')) or 1.0
     self.force_xbmcplayer = ADDON.getSettingBool('force_xbmcplayer')
 def _set_params_reroute_details(self, flatten_seasons):
     if (self.parent_params.get('info') == 'library_nextaired'
             and ADDON.getSettingBool('nextaired_linklibrary')
             and self.infoproperties.get('tvshow.dbid')):
         self.path = u'videodb://tvshows/titles/{}/'.format(self.infoproperties['tvshow.dbid'])
         self.params = {}
         self.is_folder = True
         return
     self._set_params_reroute_default()
Esempio n. 9
0
 def _set_params_reroute_default(self):
     if not ADDON.getSettingInt('default_select'):
         self.params['info'] = 'play'
         if not ADDON.getSettingBool('only_resolve_strm'):
             self.infoproperties['isPlayable'] = 'true'
     else:
         self.params['info'] = 'related'
     self.is_folder = False
     self.infoproperties['tmdbhelper.context.playusing'] = u'{}&ignore_default=true'.format(self.get_url())
    def add_items(self, items=None, pagination=True, parent_params=None, property_params=None, kodi_db=None, cache_only=True):
        if not items:
            return
        check_is_aired = parent_params.get('info') not in NO_LABEL_FORMATTING
        hide_nodate = ADDON.getSettingBool('nodate_is_unaired')

        # Pre-game details and artwork cache for seasons/episodes before threading to avoid multiple API calls
        ftv_art = None
        if parent_params.get('info') in ['seasons', 'episodes', 'episode_groups', 'trakt_upnext']:
            details = self.tmdb_api.get_details('tv', parent_params.get('tmdb_id'), parent_params.get('season', 0), cache_only=cache_only)
            ftv_art = self.get_ftv_artwork(ListItem(parent_params=parent_params, **details))

        # Build empty queue and thread pool
        self.items_queue, pool = [None] * len(items), [None] * len(items)

        # Start item build threads
        for x, i in enumerate(items):
            if not pagination and 'next_page' in i:
                continue
            if self.item_is_excluded(i):
                continue
            li = ListItem(parent_params=parent_params, **i)
            pool[x] = Thread(target=self._add_item, args=[x, li, cache_only, ftv_art])
            pool[x].start()

        # Wait to join threads in pool first before adding item to directory
        for x, i in enumerate(pool):
            if not i:
                continue
            i.join()
            li = self.items_queue[x]
            if not li:
                continue
            li.set_episode_label()
            if check_is_aired and li.is_unaired(no_date=hide_nodate):
                continue
            li.set_details(details=self.get_kodi_details(li), reverse=True)  # Quick because local db
            li.set_playcount(playcount=self.get_playcount_from_trakt(li))  # Quick because of agressive caching of Trakt object and pre-emptive dict comprehension
            if self.hide_watched and try_int(li.infolabels.get('playcount')) != 0:
                continue
            li.set_cast()
            li.set_context_menu()  # Set the context menu items
            li.set_uids_to_info()  # Add unique ids to properties so accessible in skins
            li.set_thumb_to_art(self.thumb_override == 2) if self.thumb_override else None
            li.set_params_reroute(self.ftv_forced_lookup, self.flatten_seasons)  # Reroute details to proper end point
            li.set_params_to_info(self.plugin_category)  # Set path params to properties for use in skins
            li.infoproperties.update(property_params or {})
            if self.thumb_override:
                li.infolabels.pop('dbid', None)  # Need to pop the DBID if overriding thumb otherwise Kodi overrides after item is created
            xbmcplugin.addDirectoryItem(
                handle=self.handle,
                url=li.get_url(),
                listitem=li.get_listitem(),
                isFolder=li.is_folder)
def make_path(path, warn_dialog=False):
    if xbmcvfs.exists(path):
        return xbmc.translatePath(path)
    if xbmcvfs.mkdirs(path):
        return xbmc.translatePath(path)
    if ADDON.getSettingBool('ignore_folderchecking'):
        kodi_log(u'Ignored xbmcvfs folder check error\n{}'.format(path), 2)
        return xbmc.translatePath(path)
    kodi_log(u'XBMCVFS unable to create path:\n{}'.format(path), 2)
    if not warn_dialog:
        return
    xbmcgui.Dialog().ok(
        'XBMCVFS', u'{} [B]{}[/B]\n{}'.format(ADDON.getLocalizedString(32122),
                                              path,
                                              ADDON.getLocalizedString(32123)))
    def process_artwork(self, details, tmdb_type):
        self.clear_property_list(SETMAIN_ARTWORK)
        if self.dbtype not in ['movies', 'tvshows', 'episodes']:
            if tmdb_type not in ['movie', 'tv']:
                return
        if ADDON.getSettingBool('service_fanarttv_lookup'):
            details = self.get_fanarttv_artwork(details, tmdb_type)
        if not self.is_same_item():
            return
        self.set_iter_properties(details.get('art', {}), SETMAIN_ARTWORK)

        # Crop Image
        if details.get('clearlogo'):
            if xbmc.getCondVisibility("Skin.HasSetting(TMDbHelper.EnableCrop)"):
                self.crop_img = ImageFunctions(method='crop', artwork=details.get('clearlogo'))
                self.crop_img.setName('crop_img')
                self.crop_img.start()
Esempio n. 13
0
 def get_default_player(self):
     """ Returns default player """
     if self.ignore_default:
         return
     # Check local first if we have the setting
     if ADDON.getSettingBool('default_player_local') and self.dialog_players[0].get('is_local'):
         player = self.dialog_players[0]
         player['idx'] = 0
         return player
     if not self.default_player:
         return
     all_players = [u'{} {}'.format(i.get('file'), i.get('mode')) for i in self.dialog_players]
     try:
         x = all_players.index(self.default_player)
     except Exception:
         return
     player = self.dialog_players[x]
     player['idx'] = x
     return player
Esempio n. 14
0
    def __init__(self,
                 tmdb_type,
                 tmdb_id=None,
                 season=None,
                 episode=None,
                 ignore_default=False,
                 islocal=False,
                 **kwargs):
        with ProgressDialog('TMDbHelper',
                            u'{}...'.format(ADDON.getLocalizedString(32374)),
                            total=3) as _p_dialog:
            self.api_language = None
            self.players = get_players_from_file()

            _p_dialog.update(u'{}...'.format(ADDON.getLocalizedString(32375)))
            self.details = get_item_details(tmdb_type, tmdb_id, season,
                                            episode)
            self.item = get_detailed_item(
                tmdb_type, tmdb_id, season, episode,
                details=self.details) or {}

            _p_dialog.update(u'{}...'.format(ADDON.getLocalizedString(32376)))
            self.playerstring = get_playerstring(tmdb_type,
                                                 tmdb_id,
                                                 season,
                                                 episode,
                                                 details=self.details)
            self.dialog_players = self._get_players_for_dialog(tmdb_type)

            self.default_player = ADDON.getSettingString(
                'default_player_movies'
            ) if tmdb_type == 'movie' else ADDON.getSettingString(
                'default_player_episodes')
            self.ignore_default = ignore_default
            self.tmdb_type, self.tmdb_id, self.season, self.episode = tmdb_type, tmdb_id, season, episode
            self.dummy_duration = try_float(
                ADDON.getSettingString('dummy_duration')) or 1.0
            self.dummy_delay = try_float(
                ADDON.getSettingString('dummy_delay')) or 1.0
            self.force_xbmcplayer = ADDON.getSettingBool('force_xbmcplayer')
            self.is_strm = islocal
def get_players_from_file():
    players = {}
    basedirs = [PLAYERS_BASEDIR_USER]
    if ADDON.getSettingBool('bundled_players'):
        basedirs += [PLAYERS_BASEDIR_BUNDLED]
    basedirs += [PLAYERS_BASEDIR_SAVE
                 ]  # Add saved players last so they overwrite
    for basedir in basedirs:
        files = get_files_in_folder(basedir, r'.*\.json')
        for file in files:
            meta = loads(read_file(basedir + file)) or {}
            plugins = meta.get(
                'plugin'
            ) or 'plugin.undefined'  # Give dummy name to undefined plugins so that they fail the check
            plugins = plugins if isinstance(
                plugins, list) else [plugins]  # Listify for simplicity of code
            for i in plugins:
                if not xbmc.getCondVisibility(
                        u'System.HasAddon({0})'.format(i)):
                    break  # System doesn't have a required plugin so skip this player
            else:
                meta['plugin'] = plugins[0]
                players[try_decode(file)] = meta
    return players
 def pagination_is_allowed(self):
     if self.params.pop('nextpage', '').lower() == 'false':
         return False
     if self.is_widget and not ADDON.getSettingBool('widgets_nextpage'):
         return False
     return True
Esempio n. 17
0
 def _start(self):
     if self.p_dialog:
         self.p_dialog.create('TMDbHelper', ADDON.getLocalizedString(32166))
     if not ADDON.getSettingBool('legacy_conversion'):
         self.legacy_conversion()
 def get_kodi_database(self, tmdb_type):
     if ADDON.getSettingBool('local_db'):
         return get_kodi_library(tmdb_type)
Esempio n. 19
0
 def list_seasons(self, tmdb_id, **kwargs):
     items = self.tmdb_api.get_season_list(
         tmdb_id,
         hide_specials=ADDON.getSettingBool('hide_special_seasons'))
     self.container_content = convert_type('season', 'container')
     return items
 def unaired_bool(self):
     if ADDON.getSettingBool('hide_unaired_episodes'):
         return True
Esempio n. 21
0
import xbmcgui
from resources.lib.addon.decorators import busy_dialog
from resources.lib.addon.plugin import kodi_log, ADDON
from resources.lib.addon.parser import try_int
from resources.lib.files.utils import validify_filename, make_path, write_to_file, get_tmdb_id_nfo
from resources.lib.trakt.api import TraktAPI

STRM_MOVIE = 'plugin://plugin.video.themoviedb.helper/?info=play&tmdb_id={}&tmdb_type=movie&islocal=True'
STRM_EPISODE = 'plugin://plugin.video.themoviedb.helper/?info=play&tmdb_type=tv&islocal=True&tmdb_id={}&season={}&episode={}'
BASEDIR_MOVIE = ADDON.getSettingString(
    'movies_library'
) or 'special://profile/addon_data/plugin.video.themoviedb.helper/movies/'
BASEDIR_TV = ADDON.getSettingString(
    'tvshows_library'
) or 'special://profile/addon_data/plugin.video.themoviedb.helper/tvshows/'
NFOFILE_MOVIE = u'movie-tmdbhelper' if ADDON.getSettingBool(
    'alternative_nfo') else u'movie'
NFOFILE_TV = u'tvshow-tmdbhelper' if ADDON.getSettingBool(
    'alternative_nfo') else u'tvshow'
"""
IMPORTANT: These limits are set to prevent excessive API data usage.
Please respect the APIs that provide this data for free.
"""
LIBRARY_ADD_LIMIT_TVSHOWS = 500
LIBRARY_ADD_LIMIT_MOVIES = 2500


def replace_content(content, old, new):
    content = content.replace(old, new)
    return replace_content(content, old, new) if old in content else content