Esempio n. 1
0
    def get_extracted_zip(self):
        if not self.download_url or not self.extract_to:
            return

        with busy_dialog():
            response = self.open_url(self.download_url)
        if not response:
            xbmcgui.Dialog().ok(ADDON.getAddonInfo('name'),
                                ADDON.getLocalizedString(32058))
            return

        if not os.path.exists(self.extract_to):
            os.makedirs(self.extract_to)

        if xbmcgui.Dialog().yesno(ADDON.getAddonInfo('name'),
                                  self.msg_cleardir):
            with busy_dialog():
                self.clear_dir(self.extract_to)

        with busy_dialog():
            num_files = 0
            with zipfile.ZipFile(BytesIO(response.content)) as downloaded_zip:
                for item in [
                        x for x in downloaded_zip.namelist()
                        if x.endswith('.json')
                ]:
                    filename = os.path.basename(item)
                    if not filename:
                        continue

                    _file = downloaded_zip.open(item)
                    with open(os.path.join(self.extract_to, filename),
                              'w') as target:
                        target.write(_file.read())
                        num_files += 1

            try:
                _tempzip = os.path.join(self.extract_to, 'temp.zip')
                os.remove(_tempzip)
            except Exception as e:
                kodi_log(u'Could not delete package {0}: {1}'.format(
                    _tempzip, str(e)))

        if num_files:
            xbmcgui.Dialog().ok(
                ADDON.getAddonInfo('name'),
                u'{0}\n\n{1} {2}.'.format(ADDON.getLocalizedString(32059),
                                          num_files,
                                          ADDON.getLocalizedString(32060)))
Esempio n. 2
0
def get_userlist(user_slug=None, list_slug=None, confirm=True, busy_spinner=True):
    with busy_dialog(is_enabled=busy_spinner):
        request = TraktAPI().get_response_json('users', user_slug, 'lists', list_slug, 'items')
    if not request:
        return
    if confirm:
        d_head = ADDON.getLocalizedString(32125)
        i_check_limits = check_overlimit(request)
        if i_check_limits:
            # List over limit so inform user that it is too large to add
            d_body = [
                ADDON.getLocalizedString(32168).format(list_slug, user_slug),
                ADDON.getLocalizedString(32170).format(i_check_limits.get('show'), i_check_limits.get('movie')),
                '',
                ADDON.getLocalizedString(32164).format(LIBRARY_ADD_LIMIT_TVSHOWS, LIBRARY_ADD_LIMIT_MOVIES)]
            xbmcgui.Dialog().ok(d_head, '\n'.join(d_body))
            return
        elif isinstance(confirm, bool) or len(request) > confirm:
            # List is within limits so ask for confirmation before adding it
            d_body = [
                ADDON.getLocalizedString(32168).format(list_slug, user_slug),
                ADDON.getLocalizedString(32171).format(len(request)) if len(request) > 20 else '',
                '',
                ADDON.getLocalizedString(32126)]
            if not xbmcgui.Dialog().yesno(d_head, '\n'.join(d_body)):
                return
    return request
Esempio n. 3
0
 def _sync_userlist(self):
     with busy_dialog():
         list_sync = self.trakt_api.get_list_of_lists('users/me/lists') or []
         list_sync.append({'label': ADDON.getLocalizedString(32299)})
     x = xbmcgui.Dialog().contextmenu([i.get('label') for i in list_sync])
     if x == -1:
         return
     if list_sync[x].get('label') == ADDON.getLocalizedString(32299):
         return  # TODO: CREATE NEW LIST
     list_slug = list_sync[x].get('params', {}).get('list_slug')
     if not list_slug:
         return
     with busy_dialog():
         return self.trakt_api.add_list_item(
             list_slug, self.trakt_type, self.unique_id, self.id_type,
             season=self.season, episode=self.episode)
Esempio n. 4
0
 def build_menu(self, items):
     with busy_dialog():
         self.menu = [
             j for j in (i['class'](self, **i.get('kwargs', {}))._getself()
                         for i in items) if j
         ]
     return self.menu
Esempio n. 5
0
def log_request(**kwargs):
    with busy_dialog():
        kwargs['response'] = None
        if not kwargs.get('url'):
            kwargs['url'] = xbmcgui.Dialog().input('URL')
        if not kwargs['url']:
            return
        if kwargs.get('log_request').lower() == 'trakt':
            kwargs['response'] = TraktAPI().get_response_json(kwargs['url'])
        else:
            kwargs['response'] = TMDb().get_response_json(kwargs['url'])
        if not kwargs['response']:
            xbmcgui.Dialog().ok(kwargs['log_request'].capitalize(),
                                u'{}\nNo Response!'.format(kwargs['url']))
            return
        filename = validify_filename(u'{}_{}.json'.format(
            kwargs['log_request'], kwargs['url']))
        dumps_to_file(kwargs, 'log_request', filename)
        xbmcgui.Dialog().ok(
            kwargs['log_request'].capitalize(),
            u'[B]{}[/B]\n\n{}\n{}\n{}'.format(
                kwargs['url'],
                xbmc.translatePath('special://profile/addon_data/'),
                'plugin.video.themoviedb.helper/log_request', filename))
        xbmcgui.Dialog().textviewer(filename,
                                    dumps(kwargs['response'], indent=2))
Esempio n. 6
0
def resolve_to_dummy(handle=None, stop_after=1, delay_wait=0):
    """
    Kodi does 5x retries to resolve url if isPlayable property is set - strm files force this property.
    However, external plugins might not resolve directly to URL and instead might require PlayMedia.
    Also, if external plugin endpoint is a folder we need to do ActivateWindow/Container.Update instead.
    Passing False to setResolvedUrl doesn't work correctly and the retry is triggered anyway.
    In these instances we use a hack to avoid the retry by first resolving to a dummy file instead.
    """
    # If we don't have a handle there's nothing to resolve
    if handle is None:
        return

    # Set our dummy resolved url
    path = u'{}/resources/dummy.mp4'.format(ADDONPATH)
    kodi_log(['lib.player.players - attempt to resolve dummy file\n', path], 1)
    xbmcplugin.setResolvedUrl(handle, True, ListItem(path=path).get_listitem())

    # Wait till our file plays and then stop after setting duration
    if wait_for_player(to_start='dummy.mp4', stop_after=stop_after) <= 0:
        kodi_log(['lib.player.players - resolving dummy file timeout\n', path], 1)
        return -1

    # Wait for our file to stop before continuing
    if wait_for_player() <= 0:
        kodi_log(['lib.player.players - stopping dummy file timeout\n', path], 1)
        return -1

    # Added delay
    with busy_dialog(False if delay_wait < 1 else True):
        xbmc.Monitor().waitForAbort(delay_wait)

    # Success
    kodi_log(['lib.player.players -- successfully resolved dummy file\n', path], 1)
Esempio n. 7
0
 def _view_comments(self):
     trakt_type = 'show' if self.trakt_type in ['season', 'episode'] else self.trakt_type
     with busy_dialog():
         slug = self.trakt_api.get_id(self.unique_id, self.id_type, trakt_type, 'slug')
         comments = self.trakt_api.get_response_json('{}s'.format(trakt_type), slug, 'comments', limit=50) or []
         itemlist = [i.get('comment', '').replace('\n', ' ') for i in comments]
     return self._choose_comment(itemlist, comments)
 def __init__(self,
              tmdb_type,
              tmdb_id=None,
              season=None,
              episode=None,
              ignore_default=False,
              **kwargs):
     with busy_dialog():
         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
 def sync(self):
     with busy_dialog():
         choices = self._build_choices()
     x = xbmcgui.Dialog().contextmenu([i.get('name') for i in choices])
     if x == -1:
         return
     name = choices[x].get('name')
     item_sync = self._sync_item(**choices[x])
     if item_sync == -1:
         return
     if item_sync and item_sync.status_code in [200, 201, 204]:
         xbmcgui.Dialog().ok(
             ADDON.getLocalizedString(32295),
             ADDON.getLocalizedString(32297).format(name, self.trakt_type,
                                                    self.id_type.upper(),
                                                    self.unique_id))
         xbmc.executebuiltin('Container.Refresh')
         xbmc.executebuiltin(
             'UpdateLibrary(video,/fake/path/to/force/refresh/on/home)')
         return
     xbmcgui.Dialog().ok(
         ADDON.getLocalizedString(32295),
         ADDON.getLocalizedString(32296).format(name, self.trakt_type,
                                                self.id_type.upper(),
                                                self.unique_id))
Esempio n. 10
0
def run_plugin(**kwargs):
    with busy_dialog():
        kodi_log([
            'lib.script.router - attempting to play\n',
            kwargs.get('run_plugin')
        ], 1)
        xbmc.executebuiltin(
            try_encode(u'RunPlugin({})'.format(kwargs.get('run_plugin'))))
Esempio n. 11
0
def play_media(**kwargs):
    with busy_dialog():
        kodi_log([
            'lib.script.router - attempting to play\n',
            kwargs.get('play_media')
        ], 1)
        xbmc.executebuiltin(
            try_encode(u'PlayMedia({})'.format(kwargs.get('play_media'))))
Esempio n. 12
0
 def sync(self):
     """ Called after user selects choice """
     with busy_dialog():
         self._sync = self._trakt.sync_item(
             '{}/remove'.format(self.method) if self.remove else
             self.method, self._item.trakt_type, self._item.unique_id,
             self._item.id_type, self._item.season, self._item.episode)
     return self._sync
 def _sync_item(self, method, **kwargs):
     if method == 'userlist':
         return self._sync_userlist(**kwargs)
     if method == 'comments':
         return self._view_comments()
     with busy_dialog():
         return self.trakt_api.sync_item(method, self.trakt_type,
                                         self.unique_id, self.id_type,
                                         self.season, self.episode)
Esempio n. 14
0
 def add_query(self, query, tmdb_type):
     with busy_dialog():
         query = try_decode(query)
         tmdb_id = TMDb().get_tmdb_id_from_query(tmdb_type, query, header=query, use_details=True, auto_single=True)
     if not tmdb_id:
         xbmcgui.Dialog().notification('TMDbHelper', ADDON.getLocalizedString(32310).format(query))
         return
     url = 'plugin://plugin.video.themoviedb.helper/?info=details&tmdb_type={}&tmdb_id={}'
     url = url.format(tmdb_type, tmdb_id)
     return self.add_path(url)
 def _sync_userlist_getlist(self):
     with busy_dialog():
         list_sync = self.trakt_api.get_list_of_lists(
             'users/me/lists') or []
         list_sync.append({'label': ADDON.getLocalizedString(32299)})
     x = xbmcgui.Dialog().contextmenu([i.get('label') for i in list_sync])
     if x == -1:
         return
     if list_sync[x].get('label') == ADDON.getLocalizedString(32299):
         return self._sync_userlist_addlist()
     return list_sync[x].get('params', {}).get('list_slug')
 def delete_player(self, filename):
     if not xbmcgui.Dialog().yesno(
             ADDON.getLocalizedString(32334),
             ADDON.getLocalizedString(32335).format(filename),
             yeslabel=xbmc.getLocalizedString(13007),
             nolabel=xbmc.getLocalizedString(222)):
         return
     with busy_dialog():
         delete_file(PLAYERS_BASEDIR_SAVE, filename, join_addon_data=False)
         self.players = get_players_from_file()
         self.dialog_players = _get_dialog_players(self.players)
Esempio n. 17
0
 def refresh_all_artwork(self, ftv_id, ftv_type, ok_dialog=True, container_refresh=True):
     self.cache_refresh = True
     with busy_dialog():
         artwork = self.get_all_artwork(ftv_id, ftv_type)
     if ok_dialog and not artwork:
         xbmcgui.Dialog().ok('FanartTV', ADDON.getLocalizedString(32217).format(ftv_type, ftv_id))
     if ok_dialog and artwork:
         xbmcgui.Dialog().ok('FanartTV', ADDON.getLocalizedString(32218).format(
             ftv_type, ftv_id, ', '.join([k.capitalize() for k, v in artwork.items() if v])))
     if artwork and container_refresh:
         xbmc.executebuiltin('Container.Refresh')
         xbmc.executebuiltin('UpdateLibrary(video,/fake/path/to/force/refresh/on/home)')
     return artwork
    def get_gzip_text(self):
        if not self.download_url:
            return

        with busy_dialog():
            response = self.open_url(self.download_url)
        if not response:
            xbmcgui.Dialog().ok(ADDON.getAddonInfo('name'), ADDON.getLocalizedString(32058))
            return

        with gzip.GzipFile(fileobj=BytesIO(response.content)) as downloaded_gzip:
            content = downloaded_gzip.read()
        return content
 def _sync_userlist(self, remove=False, **kwargs):
     list_slug = xbmc.getInfoLabel(
         "ListItem.Property(param.list_slug)"
     ) if remove else self._sync_userlist_getlist()
     if not list_slug:
         return
     with busy_dialog():
         return self.trakt_api.add_list_item(list_slug,
                                             self.trakt_type,
                                             self.unique_id,
                                             self.id_type,
                                             season=self.season,
                                             episode=self.episode,
                                             remove=remove)
Esempio n. 20
0
 def sync(self):
     trakt_type = 'show' if self._item.trakt_type in [
         'season', 'episode'
     ] else self._item.trakt_type
     with busy_dialog():
         slug = self._trakt.get_id(self._item.unique_id, self._item.id_type,
                                   trakt_type, 'slug')
         comments = self._trakt.get_response_json(
             u'{}s'.format(trakt_type), slug, 'comments', limit=50) or []
         itemlist = [
             i.get('comment', '').replace('\n', ' ') for i in comments
         ]
     self._sync = self._getcomment(itemlist, comments)
     return self._sync
Esempio n. 21
0
 def _getlist(self, get_currentlist=False):
     """ Get an existing Trakt list and returns tuple of list and user slug """
     if get_currentlist:
         return (xbmc.getInfoLabel("ListItem.Property(param.list_slug)"),
                 xbmc.getInfoLabel("ListItem.Property(param.user_slug)"))
     with busy_dialog():
         list_sync = self._trakt.get_list_of_lists('users/me/lists') or []
         list_sync.append({'label': ADDON.getLocalizedString(32299)})
     x = xbmcgui.Dialog().contextmenu([i.get('label') for i in list_sync])
     if x == -1:
         return
     if list_sync[x].get('label') == ADDON.getLocalizedString(32299):
         return self._addlist()
     return (list_sync[x].get('params', {}).get('list_slug'),
             list_sync[x].get('params', {}).get('user_slug'))
 def save_player(self, player, filename, confirm=True):
     if confirm and not xbmcgui.Dialog().yesno(
             ADDON.getLocalizedString(32336),
             ADDON.getLocalizedString(32337).format(filename),
             yeslabel=xbmc.getLocalizedString(190),
             nolabel=ADDON.getLocalizedString(32338)):
         return
     with busy_dialog():
         self.players[filename] = player  # Update our players dictionary
         self.dialog_players = _get_dialog_players(
             self.players)  # Update our dialog list
         dumps_to_file(player,
                       PLAYERS_BASEDIR_SAVE,
                       filename,
                       indent=4,
                       join_addon_data=False)  # Write out file
Esempio n. 23
0
def monitor_userlist():
    # Build list choices
    with busy_dialog():
        user_lists = []
        user_lists += TraktAPI().get_list_of_lists(
            'users/me/lists', authorize=True, next_page=False) or []
        user_lists += TraktAPI().get_list_of_lists(
            'users/likes/lists', authorize=True, next_page=False) or []
        saved_lists = _get_monitor_userlists()
        dialog_list = [i['label'] for i in user_lists]
        preselected = [
            x for x, i in enumerate(user_lists)
            if (i.get('params', {}).get('list_slug'),
                i.get('params', {}).get('user_slug')) in saved_lists
        ]

    # Ask user to choose lists
    indices = xbmcgui.Dialog().multiselect(ADDON.getLocalizedString(32312),
                                           dialog_list,
                                           preselect=preselected)
    if indices is None:
        return

    # Build the new settings and check that lists aren't over limit
    added_lists, added_users = [], []
    for x in indices:
        list_slug = user_lists[x].get('params', {}).get('list_slug')
        user_slug = user_lists[x].get('params', {}).get('user_slug')
        if get_userlist(user_slug, list_slug, confirm=50):
            added_lists.append(list_slug)
            added_users.append(user_slug)

    # Set the added lists to our settings
    if not added_lists or not added_users:
        return
    added_lists = ' | '.join(added_lists)
    added_users = ' | '.join(added_users)
    ADDON.setSettingString('monitor_userlist', added_lists)
    ADDON.setSettingString('monitor_userslug', added_users)

    # Update library?
    if xbmcgui.Dialog().yesno(xbmc.getLocalizedString(653),
                              ADDON.getLocalizedString(32132)):
        library_autoupdate(list_slugs=added_lists,
                           user_slugs=added_users,
                           busy_spinner=True)
Esempio n. 24
0
    def select_artwork(self, ftv_id, ftv_type, container_refresh=True, blacklist=[]):
        if ftv_type not in ['movies', 'tv']:
            return
        with busy_dialog():
            artwork = self.get_artwork_request(ftv_id, ftv_type)
        if not artwork:
            return xbmcgui.Dialog().notification('FanartTV', ADDON.getLocalizedString(32217).format(ftv_type, ftv_id))

        # Choose Type
        _artwork_types = ['poster', 'fanart', 'clearart', 'clearlogo', 'landscape', 'banner']
        _artwork_types.append('discart' if ftv_type == 'movies' else 'characterart')
        artwork_types = [i for i in _artwork_types if i not in blacklist]  # Remove types that we previously looked for
        choice = xbmcgui.Dialog().select(xbmc.getLocalizedString(13511), artwork_types)
        if choice == -1:
            return

        # Get artwork of user's choosing
        artwork_type = artwork_types[choice]
        artwork_items = self.get_artwork(ftv_id, ftv_type, artwork_type, get_list=True)

        # If there was not artwork of that type found then blacklist it before re-prompting
        if not artwork_items:
            xbmcgui.Dialog().notification('FanartTV', ADDON.getLocalizedString(32217).format(ftv_type, ftv_id))
            blacklist.append(artwork_types[choice])
            return self.select_artwork(ftv_id, ftv_type, container_refresh, blacklist)

        # Choose artwork from options
        items = [
            ListItem(
                label=i.get('url'),
                label2=ADDON.getLocalizedString(32219).format(i.get('lang', ''), i.get('likes', 0), i.get('id', '')),
                art={'thumb': i.get('url')}).get_listitem() for i in artwork_items if i.get('url')]
        choice = xbmcgui.Dialog().select(xbmc.getLocalizedString(13511), items, useDetails=True)
        if choice == -1:  # If user hits back go back to main menu rather than exit completely
            return self.select_artwork(ftv_id, ftv_type, container_refresh, blacklist)

        # Cache our choice as the best artwork forever since it was selected manually
        # Some types have have HD and SD variants so set cache for both
        for i in ARTWORK_TYPES.get(ftv_type, {}).get(artwork_type, []):
            success = self._cache.set_cache(
                artwork_items[choice].get('url'),
                cache_name=u'FanartTV.best.{}.{}.{}.{}'.format(self.language, ftv_id, ftv_type, i),
                cache_days=10000)
        if success and container_refresh:
            xbmc.executebuiltin('Container.Refresh')
            xbmc.executebuiltin('UpdateLibrary(video,/fake/path/to/force/refresh/on/home)')
    def _get_path_from_actions(self, actions, is_folder=True):
        """ Returns tuple of (path, is_folder) """
        keyboard_input = None
        path = (actions[0], is_folder)
        for action in actions[1:]:
            # Check if we've got a playable item already
            if not is_folder:
                return path

            # Start thread with keyboard inputter if needed
            if action.get('keyboard'):
                if action.get('keyboard') in [
                        'Up', 'Down', 'Left', 'Right', 'Select'
                ]:
                    keyboard_input = KeyboardInputter(
                        action="Input.{}".format(action.get('keyboard')))
                else:
                    keyboard_input = KeyboardInputter(text=string_format_map(
                        action.get('keyboard', ''), self.item))
                keyboard_input.setName('keyboard_input')
                keyboard_input.start()
                continue  # Go to next action

            # Get the next folder from the plugin
            with busy_dialog():
                folder = get_directory(string_format_map(path[0], self.item))

            # Kill our keyboard inputter thread
            if keyboard_input:
                keyboard_input.exit = True
                keyboard_input = None

            # Special option to show dialog of items to select
            if action.get('dialog'):
                auto = True if action.get('dialog',
                                          '').lower() == 'auto' else False
                return self._player_dialog_select(folder, auto=auto)

            # Apply the rules for the current action and grab the path
            path = self._get_path_from_rules(folder, action)
            if not path:
                return
        return path
Esempio n. 26
0
def refresh_details(tmdb_id=None,
                    tmdb_type=None,
                    season=None,
                    episode=None,
                    confirm=True,
                    **kwargs):
    if not tmdb_id or not tmdb_type:
        return
    with busy_dialog():
        details = TMDb().get_details(tmdb_type,
                                     tmdb_id,
                                     season,
                                     episode,
                                     cache_refresh=True)
    if details and confirm:
        xbmcgui.Dialog().ok(
            'TMDbHelper',
            ADDON.getLocalizedString(32234).format(tmdb_type, tmdb_id))
        container_refresh()
    return details
Esempio n. 27
0
 def sync(self):
     """ Entry point """
     slug = self._getlist(get_currentlist=self.remove)
     if not slug:
         return
     with busy_dialog():
         self._sync = self._trakt.add_list_item(slug[0],
                                                self._item.trakt_type,
                                                self._item.unique_id,
                                                self._item.id_type,
                                                season=self._item.season,
                                                episode=self._item.episode,
                                                remove=self.remove)
     if self._sync and self._sync.status_code in [
             200, 201, 204
     ] and self._item.id_type == 'tmdb':
         self._addlibrary(convert_trakt_type(self._item.trakt_type),
                          self._item.unique_id,
                          slug=slug)
     return self._sync
def refresh_details(tmdb_id=None,
                    tmdb_type=None,
                    season=None,
                    episode=None,
                    **kwargs):
    if not tmdb_id or not tmdb_type:
        return
    with busy_dialog():
        details = TMDb().get_details(tmdb_type,
                                     tmdb_id,
                                     season,
                                     episode,
                                     cache_refresh=True)
    if details:
        xbmcgui.Dialog().ok(
            'TMDbHelper',
            ADDON.getLocalizedString(32234).format(tmdb_type, tmdb_id))
        xbmc.executebuiltin('Container.Refresh')
        xbmc.executebuiltin(
            'UpdateLibrary(video,/fake/path/to/force/refresh/on/home)')
 def _update_listing_hack(self, folder_path=None, reset_focus=None):
     """
     Some plugins use container.update after search results to rewrite path history
     This is a quick hack to rewrite the path back to our original path before updating
     """
     if not folder_path:
         return
     xbmc.Monitor().waitForAbort(2)
     container_folderpath = xbmc.getInfoLabel("Container.FolderPath")
     if container_folderpath == folder_path:
         return
     xbmc.executebuiltin(
         try_encode(u'Container.Update({},replace)'.format(folder_path)))
     if not reset_focus:
         return
     with busy_dialog():
         timeout = 20
         while not xbmc.Monitor().abortRequested() and xbmc.getInfoLabel(
                 "Container.FolderPath") != folder_path and timeout > 0:
             xbmc.Monitor().waitForAbort(0.25)
             timeout -= 1
         xbmc.executebuiltin(reset_focus)
         xbmc.Monitor().waitForAbort(0.5)
 def __init__(self):
     with busy_dialog():
         self.players = get_players_from_file()
         self.dialog_players = _get_dialog_players(self.players)