예제 #1
0
    def process_artwork(self, details, tmdbtype):
        try:
            if self.dbtype not in ['movies', 'tvshows', 'episodes'
                                   ] and tmdbtype not in ['movie', 'tv']:
                return
            pre_item = self.pre_item
            details = self.get_fanarttv_artwork(
                details, tmdbtype) if self.addon.getSettingBool(
                    'service_fanarttv_lookup') else details
            details = self.get_kodi_artwork(
                details, self.dbtype, self.dbid) if self.addon.getSettingBool(
                    'local_db') else details
            if not self.is_same_item(update=False, pre_item=pre_item):
                return
            self.set_iter_properties(details, _setmain_artwork)

            # Crop Image
            if details.get('clearlogo') and 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()

        except Exception as exc:
            utils.kodi_log(u'Func: process_ratings\n{}'.format(exc), 1)
예제 #2
0
    def library_autoupdate(self):
        utils.kodi_log('UPDATING TV SHOWS LIBRARY', 1)
        basedir_tv = self.addon.getSettingString('tvshows_library') or 'special://profile/addon_data/plugin.video.themoviedb.helper/tvshows/'
        for f in xbmcvfs.listdir(basedir_tv)[0]:
            try:
                folder = basedir_tv + f + '/'
                # Get nfo file
                nfo = None
                for x in xbmcvfs.listdir(folder)[1]:
                    if x.endswith('.nfo'):
                        nfo = x
                if not nfo:
                    continue

                # Read nfo file
                vfs_file = xbmcvfs.File(folder + nfo)
                content = ''
                try:
                    content = vfs_file.read()
                finally:
                    vfs_file.close()
                tmdb_id = content.replace('https://www.themoviedb.org/tv/', '')
                if not tmdb_id:
                    continue

                # Get the tvshow
                url = 'plugin://plugin.video.themoviedb.helper/?info=seasons&tmdb_id={}&type=tv'.format(tmdb_id)
                context.library_addtvshow(basedir=basedir_tv, folder=f, url=url, tmdb_id=tmdb_id)
            except Exception as exc:
                utils.kodi_log('LIBRARY AUTO UPDATE ERROR:\n{}'.format(exc))
        if self.addon.getSettingBool('auto_update'):
            xbmc.executebuiltin('UpdateLibrary(video, {})'.format(basedir_tv))
def library_createfile(filename, content, *args, **kwargs):
    """
    Create the file and folder structure: filename=.strm file, content= content of file.
    *args = folders to create.
    """
    file_ext = kwargs.pop('file_ext', 'strm')
    clean_url = kwargs.pop('clean_url', True)
    path = kwargs.pop('basedir', '')
    path = path.replace('\\', '/')
    if not path:
        utils.kodi_log(u'ADD LIBRARY -- No basedir specified!', 2)
        return
    content = library_cleancontent(content) if clean_url else content
    for folder in args:
        folder = utils.validify_filename(folder)
        path = '{}{}/'.format(path, folder)
    if not content:
        utils.kodi_log(u'ADD LIBRARY -- No content specified!', 2)
        return
    if not filename:
        utils.kodi_log(u'ADD LIBRARY -- No filename specified!', 2)
        return
    if not library_createpath(path):
        xbmcgui.Dialog().ok(
            xbmc.getLocalizedString(20444),
            _addon.getLocalizedString(32122) + ' [B]{}[/B]'.format(path),
            _addon.getLocalizedString(32123))
        utils.kodi_log(u'ADD LIBRARY -- XBMCVFS unable to create path:\n{}'.format(path), 2)
        return
    filepath = '{}{}.{}'.format(path, utils.validify_filename(filename), file_ext)
    f = xbmcvfs.File(filepath, 'w')
    f.write(utils.try_encode_string(content))
    f.close()
    utils.kodi_log(u'ADD LIBRARY -- Successfully added:\n{}\n{}'.format(filepath, content), 2)
    return filepath
예제 #4
0
 def play(self):
     utils.kodi_log('Script -- Attempting to play item:\n{0}'.format(self.params), 2)
     if not self.params.get('play') or not self.params.get('tmdb_id'):
         return
     Player().play(
         itemtype=self.params.get('play'), tmdb_id=self.params.get('tmdb_id'),
         season=self.params.get('season'), episode=self.params.get('episode'))
 def build_selectbox(self, clearsetting=False, assertplayers=True):
     self.itemlist, self.actions = [], []
     if clearsetting:
         self.itemlist.append(
             xbmcgui.ListItem(
                 xbmc.getLocalizedString(13403)))  # Clear Default
     if self.is_local:
         self.append_playeraction(u'{0} {1}'.format(
             self.addon.getLocalizedString(32061), 'Kodi'),
                                  self.is_local,
                                  identifier='play_kodi')
     for i in sorted(self.play_movie, key=lambda x: x[1]):
         self.build_playeraction(i[0],
                                 'play_movie',
                                 assertplayers=assertplayers)
     for i in sorted(self.search_movie, key=lambda x: x[1]):
         self.build_playeraction(i[0],
                                 'search_movie',
                                 assertplayers=assertplayers)
     for i in sorted(self.play_episode, key=lambda x: x[1]):
         self.build_playeraction(i[0],
                                 'play_episode',
                                 assertplayers=assertplayers)
     for i in sorted(self.search_episode, key=lambda x: x[1]):
         self.build_playeraction(i[0],
                                 'search_episode',
                                 assertplayers=assertplayers)
     utils.kodi_log(
         u'Player -- Built {} Players!\n{}'.format(len(self.itemlist),
                                                   self.identifierlist), 2)
 def on_authenticated(self, auth_dialog=True):
     """Triggered when device authentication has been completed"""
     utils.kodi_log(u'Trakt Authenticated Successfully!', 1)
     self.addon.setSettingString('trakt_token', dumps(self.authorization))
     self.headers['Authorization'] = 'Bearer {0}'.format(self.authorization.get('access_token'))
     if auth_dialog:
         self.auth_dialog.close()
 def get_stored_token(self):
     try:
         token = loads(self.addon.getSettingString('trakt_token')) or {}
     except Exception as exc:
         token = {}
         utils.kodi_log(exc, 1)
     return token
 def set_property(self, key, value):
     try:
         if value is None:
             _homewindow.clearProperty('{}.{}'.format(self.property_basename, key))
         else:
             _homewindow.setProperty('{}.{}'.format(self.property_basename, key), u'{0}'.format(value))
     except Exception as exc:
         utils.kodi_log(u'{0}{1}'.format(key, exc), 1)
 def get_tmdb_id(self, itemtype, imdb_id=None, query=None, year=None):
     try:
         if imdb_id and imdb_id.startswith('tt'):
             return self.tmdb.get_tmdb_id(itemtype=itemtype, imdb_id=imdb_id)
         return self.tmdb.get_tmdb_id(itemtype=itemtype, query=query, year=year)
     except Exception as exc:
         utils.kodi_log(u'Func: get_tmdb_id\n{0}'.format(exc), 1)
         return
    def library_autoupdate(self, list_slug=None, user_slug=None):
        busy_dialog = True if self.params.get('busy_dialog') else False
        utils.kodi_log(u'UPDATING TV SHOWS LIBRARY', 1)
        xbmcgui.Dialog().notification('TMDbHelper', 'Auto-Updating Library...')
        basedir_tv = self.addon.getSettingString(
            'tvshows_library'
        ) or 'special://profile/addon_data/plugin.video.themoviedb.helper/tvshows/'

        list_slug = list_slug or self.addon.getSettingString(
            'monitor_userlist') or ''
        user_slug = user_slug or TraktAPI().get_usernameslug()
        if user_slug and list_slug:
            for i in list_slug.split(' | '):
                context.library_userlist(user_slug=user_slug,
                                         list_slug=i,
                                         confirmation_dialog=False,
                                         allow_update=False,
                                         busy_dialog=busy_dialog)

        p_dialog = xbmcgui.DialogProgressBG() if busy_dialog else None
        p_dialog.create('TMDbHelper',
                        'Adding items to library...') if p_dialog else None
        for f in xbmcvfs.listdir(basedir_tv)[0]:
            try:
                folder = basedir_tv + f + '/'
                # Get nfo file
                nfo = None
                for x in xbmcvfs.listdir(folder)[1]:
                    if x.endswith('.nfo'):
                        nfo = x
                if not nfo:
                    continue

                # Read nfo file
                vfs_file = xbmcvfs.File(folder + nfo)
                content = ''
                try:
                    content = vfs_file.read()
                finally:
                    vfs_file.close()
                tmdb_id = content.replace('https://www.themoviedb.org/tv/', '')
                tmdb_id = tmdb_id.replace('&islocal=True', '')
                if not tmdb_id:
                    continue

                # Get the tvshow
                url = 'plugin://plugin.video.themoviedb.helper/?info=seasons&tmdb_id={}&type=tv'.format(
                    tmdb_id)
                context.library_addtvshow(basedir=basedir_tv,
                                          folder=f,
                                          url=url,
                                          tmdb_id=tmdb_id,
                                          p_dialog=p_dialog)
            except Exception as exc:
                utils.kodi_log(u'LIBRARY AUTO UPDATE ERROR:\n{}'.format(exc))
        p_dialog.close() if p_dialog else None
        if self.addon.getSettingBool('auto_update'):
            xbmc.executebuiltin('UpdateLibrary(video)')
    def colors(self, source):
        filename = '{}.png'.format(utils.md5hash(source))
        destination = self.save_path + filename

        try:
            if xbmcvfs.exists(destination):
                os.utime(destination, None)
                img = Image.open(xbmcvfs.translatepath(destination))
            else:
                img = _openimage(source, self.save_path, filename)
                img.thumbnail((256, 256))
                img = img.convert('RGB')
                img.save(destination)

            avg_rgb = self.get_avg_color(img)
            maincolor_rgb = self.get_maincolor(*avg_rgb)
            maincolor_hex = self.rgb_to_hex(*self.get_color_lumsat(
                *maincolor_rgb))
            compcolor_rgb = self.get_compcolor(*avg_rgb)
            compcolor_hex = self.rgb_to_hex(*self.get_color_lumsat(
                *compcolor_rgb))

            maincolor_propname = self.save_prop + '.Main'
            maincolor_propchek = self.save_prop + '.MainCheck'
            maincolor_propvalu = _homewindow.getProperty(maincolor_propname)
            if not maincolor_propvalu:
                _homewindow.setProperty(maincolor_propname, maincolor_hex)
            else:
                _homewindow.setProperty(maincolor_propchek, maincolor_propvalu)
                thread_maincolor = Thread(target=self.set_prop_colorgradient,
                                          args=[
                                              maincolor_propname,
                                              maincolor_propvalu,
                                              maincolor_hex, maincolor_propchek
                                          ])
                thread_maincolor.start()

            compcolor_propname = self.save_prop + '.Comp'
            compcolor_propchek = self.save_prop + '.CompCheck'
            compcolor_propvalu = _homewindow.getProperty(compcolor_propname)
            if not compcolor_propvalu:
                _homewindow.setProperty(compcolor_propname, compcolor_hex)
            else:
                _homewindow.setProperty(compcolor_propchek, compcolor_propvalu)
                thread_compcolor = Thread(target=self.set_prop_colorgradient,
                                          args=[
                                              compcolor_propname,
                                              compcolor_propvalu,
                                              compcolor_hex, compcolor_propchek
                                          ])
                thread_compcolor.start()

            img.close()
            return maincolor_hex

        except Exception as exc:
            utils.kodi_log(exc, 1)
            return ''
def library_createpath(path):
    if xbmcvfs.exists(path):
        return path
    if xbmcvfs.mkdirs(path):
        utils.kodi_log(u'ADD LIBRARY -- Created path:\n{}'.format(path), 2)
        return path
    if _addon.getSettingBool('ignore_folderchecking'):
        utils.kodi_log(u'ADD LIBRARY -- xbmcvfs reports folder does NOT exist:\n{}\nIGNORING ERROR: User set folder checking to ignore'.format(path), 2)
        return path
 def play(self):
     utils.kodi_log(u'Script -- Attempting to play item:\n{0}'.format(self.params), 2)
     if not self.params.get('play') or not self.params.get('tmdb_id'):
         return
     Player().play(
         itemtype=self.params.get('play'), tmdb_id=self.params.get('tmdb_id'),
         season=self.params.get('season'), episode=self.params.get('episode'),
         force_dialog=self.params.get('force_dialog'))
     self.home.clearProperty('TMDbHelper.Player.ResolvedUrl')  # Clear our lock property
    def get_listitem(self):
        try:
            self.get_container()
            if self.is_same_item():
                return  # Current item was the previous item so no need to do a look-up

            self.cur_folder = '{0}{1}{2}'.format(
                self.container, xbmc.getInfoLabel(self.get_dbtype()),
                xbmc.getInfoLabel('{0}NumItems'.format(self.container)))
            if self.cur_folder != self.pre_folder:
                self.clear_properties()  # Clear props if the folder changed
                self.pre_folder = self.cur_folder
            if self.get_infolabel('Label') == '..':
                self.clear_properties()
                return  # Parent folder so clear properties and don't do look-up

            if self.dbtype in ['tvshows', 'seasons', 'episodes']:
                tmdbtype = 'tv'
            elif self.dbtype in ['movies']:
                tmdbtype = 'movie'
            elif self.dbtype in ['sets']:
                tmdbtype = 'collection'
            elif self.dbtype in ['actors', 'directors']:
                tmdbtype = 'person'
            else:
                return

            self.home.setProperty('TMDbHelper.IsUpdating', 'True')

            tmdb_id = self.get_tmdb_id(
                tmdbtype, self.imdb_id, self.query,
                self.year if tmdbtype == 'movie' else None)
            details = self.tmdb.get_detailed_item(tmdbtype,
                                                  tmdb_id,
                                                  season=self.season,
                                                  episode=self.episode)
            details = self.get_kodi_person_stats(
                details) if tmdbtype == 'person' else details
            details = self.get_omdb_ratings(
                details) if tmdbtype == 'movie' else details
            details = self.get_top250_rank(
                details) if tmdbtype == 'movie' else details
            details = self.get_fanarttv_artwork(details, tmdbtype)
            details = self.get_trakt_ratings(
                details, tmdbtype, tmdb_id, self.season,
                self.episode) if tmdbtype in ['movie', 'tv'] else details

            if not details or not self.is_same_item():
                self.clear_properties(
                )  # No details or the item changed so let's clear everything
                return

            self.set_properties(details)

        except Exception as exc:
            utils.kodi_log('Func: get_listitem\n{0}'.format(exc), 1)
예제 #15
0
    def player_resolveurl(self, player=None):
        if not player or not player[1] or not isinstance(player[1], list):
            return player  # No player configured or not a list of actions so return

        keyboard_input = None
        player_actions = player[1]
        player = (False, player_actions[0]
                  )  # player tuple is: isPlayable flag; path URI to call.

        for action in player_actions[1:]:

            # If playable item was found in last action then let's break and play it
            if player[0]:
                break

            # 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 utils.busy_dialog():
                folder = KodiLibrary().get_directory(
                    string_format_map(player[1], 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 from
            if action.get('dialog'):
                auto = True if action.get('dialog',
                                          '').lower() == 'auto' else False
                return self.player_dialogselect(folder, auto=auto)

            utils.kodi_log(
                'Player -- Retrieved Folder\n{}'.format(
                    string_format_map(player[1], self.item)), 2)

            # Iterate through plugin folder looking for item that matches rules
            player = self.player_applyrules(folder, action) or player

            if player == -1:
                break

        return player
    def call_service(self):
        call_id = utils.try_parse_int(self.params.get('call_auto'))
        kodi_id = call_id + 10000 if call_id < 10000 else call_id  # Convert to Kodi ID in 10000 range
        my_call_id = None if self.first_run else call_id

        # Close info dialogs if still open
        if xbmc.getCondVisibility('Window.IsVisible({})'.format(ID_VIDEOINFO)):
            xbmc.executebuiltin('Dialog.Close({})'.format(ID_VIDEOINFO))
            if not self.wait_for_id(to_close=True, window_id=ID_VIDEOINFO, call_id=my_call_id):
                return self.call_reset()  # Clear and exit if timeout or user closed base window

        # If we're at 0 then close and exit
        if self.get_position() == 0:
            xbmc.executebuiltin('Action(Back)')
            return self.call_reset(openinfo=True)  # Clear and exit but reopen original info dialog

        # Open our call_id window if first run
        if self.first_run:
            xbmc.executebuiltin('ActivateWindow({})'.format(call_id))
            if not self.wait_for_id(window_id=call_id, poll=0.5):
                return self.call_reset()  # Clear and exit if timeout
        window = xbmcgui.Window(kodi_id)

        # Check that list 9999 exists
        controllist = window.getControl(9999)
        if not controllist:
            utils.kodi_log(u'SKIN ERROR!\nList control 9999 not available in Window {0}'.format(call_id), 1)
            return self.call_reset()  # Clear and exit if timeout or user closed base window
        controllist.reset()

        # Wait until container updates
        self.monitor.waitForAbort(1)
        if not self.wait_for_update(call_id=call_id):
            return self.call_reset()  # Clear and exit if timeout or user closed base window

        # Open info dialog
        window.setFocus(controllist)
        xbmc.executebuiltin('SetFocus(9999,0,absolute)')
        xbmc.executebuiltin('Action(Info)')
        if not self.wait_for_id(window_id=ID_VIDEOINFO, call_id=call_id):
            return self.call_reset()  # Clear and exit if timeout or user closed base window

        # Wait for action
        func = None
        while not self.monitor.abortRequested() and not func:
            current_path = self.home.getProperty(self.prefixcurrent)
            if not xbmc.getCondVisibility("Window.IsVisible({})".format(call_id)):
                func = self.call_reset  # User closed out everything so let's do the nuclear option
            elif not xbmc.getCondVisibility("Window.IsVisible({})".format(ID_VIDEOINFO)):
                func = self.call_previous  # Dialog closed so we should delete the path and call loopback
            elif self.added_path != current_path:
                self.added_path = current_path
                func = self.call_service  # New path added so call loopback
            self.monitor.waitForAbort(0.5)  # Poll every X
        self.first_run = False
        func()
 def clear_dir(self, folder):
     for filename in os.listdir(folder):
         file_path = os.path.join(folder, filename)
         try:
             if os.path.isfile(file_path):
                 os.unlink(file_path)
             elif os.path.isdir(file_path):
                 self.recursive_delete_dir(file_path)
         except Exception as e:
             utils.kodi_log(u'Could not delete file {0}: {1}'.format(file_path, str(e)))
예제 #18
0
 def set_list_properties(self, items, key, prop):
     if not isinstance(items, list):
         return
     try:
         joinlist = [i.get(key) for i in items[:10] if i.get(key)]
         joinlist = ' / '.join(joinlist)
         self.properties.add(prop)
         self.set_property(prop, joinlist)
     except Exception as exc:
         utils.kodi_log(u'Func: set_list_properties\n{0}'.format(exc), 1)
 def get_jsonrpc(self, method=None, params=None):
     if not method or not params:
         return {}
     query = {"jsonrpc": "2.0", "params": params, "method": method, "id": 1}
     try:
         response = json.loads(xbmc.executeJSONRPC(json.dumps(query)))
     except Exception as exc:
         utils.kodi_log(u'TMDbHelper - JSONRPC Error:\n{}'.format(exc), 1)
         response = {}
     return response
def _openimage(image, targetpath, filename):
    """ Open image helper with thanks to sualfred """
    # some paths require unquoting to get a valid cached thumb hash
    cached_image_path = urllib.unquote(image.replace('image://', ''))
    if cached_image_path.endswith('/'):
        cached_image_path = cached_image_path[:-1]

    cached_files = []
    for path in [xbmc.getCacheThumbName(cached_image_path), xbmc.getCacheThumbName(image)]:
        cached_files.append(os.path.join('special://profile/Thumbnails/', path[0], path[:-4] + '.jpg'))
        cached_files.append(os.path.join('special://profile/Thumbnails/', path[0], path[:-4] + '.png'))
        cached_files.append(os.path.join('special://profile/Thumbnails/Video/', path[0], path))

    for i in range(1, 4):
        try:
            ''' Try to get cached image at first
            '''
            for cache in cached_files:
                if xbmcvfs.exists(cache):
                    try:
                        img = Image.open(xbmc.translatePath(cache))
                        return img

                    except Exception as error:
                        utils.kodi_log('Image error: Could not open cached image --> %s' % error, 2)

            ''' Skin images will be tried to be accessed directly. For all other ones
                the source will be copied to the addon_data folder to get access.
            '''
            if xbmc.skinHasImage(image):
                if not image.startswith('special://skin'):
                    image = os.path.join('special://skin/media/', image)

                try:  # in case image is packed in textures.xbt
                    img = Image.open(xbmc.translatePath(image))
                    return img

                except Exception:
                    return ''

            else:
                targetfile = os.path.join(targetpath, filename)
                if not xbmcvfs.exists(targetfile):
                    xbmcvfs.copy(image, targetfile)

                img = Image.open(targetfile)
                return img

        except Exception as error:
            utils.kodi_log('Image error: Could not get image for %s (try %d) -> %s' % (image, i, error), 2)
            xbmc.sleep(500)
            pass

    return ''
예제 #21
0
def add_userlist(user_slug=None, list_slug=None, confirm=True, allow_update=True, busy_dialog=True, force=False):
    user_slug = user_slug or sys.listitem.getProperty('Item.user_slug')
    list_slug = list_slug or sys.listitem.getProperty('Item.list_slug')

    request = get_userlist(user_slug=user_slug, list_slug=list_slug, confirm=confirm, busy_dialog=busy_dialog)

    i_total = len(request)

    p_dialog = xbmcgui.DialogProgressBG() if busy_dialog else None
    p_dialog.create('TMDbHelper', _addon.getLocalizedString(32166)) if p_dialog else None

    all_movies = []
    all_tvshows = []

    for i_count, i in enumerate(request):
        i_type = i.get('type')
        if i_type not in ['movie', 'show']:
            continue

        item = i.get(i_type, {})
        tmdb_id = item.get('ids', {}).get('tmdb')
        imdb_id = item.get('ids', {}).get('imdb')
        tvdb_id = item.get('ids', {}).get('tvdb')

        if not tmdb_id:  # Extra request for ID lookup is too expensive so skip
            utils.kodi_log(u'{} ({}) - Missing TMDb ID! Skipping...'.format(item.get('title'), item.get('year')), 2)
            continue

        if p_dialog:
            p_dialog.update(
                ((i_count + 1) * 100) // i_total,
                message=u'Adding {} ({})...'.format(item.get('title'), item.get('year')))

        if i_type == 'movie':
            playlist_item = add_movie(tmdb_id=tmdb_id, imdb_id=imdb_id, title=item.get('title'), year=item.get('year'))
            all_movies.append(playlist_item)

        if i_type == 'show':
            playlist_item = ('title', item.get('title'))
            all_tvshows.append(playlist_item)
            add_tvshow(
                basedir=_basedir_tv, folder=u'{}'.format(item.get('title')),
                url='plugin://plugin.video.themoviedb.helper/?info=seasons&nextpage=True&tmdb_id={}&type=tv'.format(tmdb_id),
                tmdb_id=tmdb_id, imdb_id=imdb_id, tvdb_id=tvdb_id, p_dialog=p_dialog, force=force)

    if p_dialog:
        p_dialog.close()
    if all_movies:
        create_playlist(all_movies, 'movies', user_slug, list_slug)
    if all_tvshows:
        create_playlist(all_tvshows, 'tvshows', user_slug, list_slug)
    if allow_update and _addon.getSettingBool('auto_update'):
        xbmc.executebuiltin('UpdateLibrary(video)')
def library_addtvshow(basedir=None, folder=None, url=None, tmdb_id=None, tvdb_id=None, imdb_id=None, p_dialog=None):
    if not basedir or not folder or not url:
        return

    nfo_tmdbid = library_getnfo_tmdbid(basedir, folder)  # Check the nfo file in the folder to make sure it matches the TMDB ID
    if nfo_tmdbid and utils.try_parse_int(nfo_tmdbid) != utils.try_parse_int(tmdb_id):
        folder += ' (TMDB {})'.format(tmdb_id)  # If different tvshow with same name exists create new folder with TMDB ID added

    details_tvshow = _plugin.tmdb.get_request_sc('tv', tmdb_id)  # Get base tv show
    if not details_tvshow:
        return

    library_create_nfo('tv', tmdb_id, folder, basedir=basedir)  # Create .nfo for tvshow
    seasons = [i.get('season_number') for i in details_tvshow.get('seasons', []) if i.get('season_number', 0) != 0]  # Don't get specials

    s_count, s_total = 0, len(seasons)  # Used to update p_dialog progress
    for season in seasons:
        s_count += 1
        season_name = u'Season {}'.format(season)  # Originally made a bad choice here to localise season name but reverted that now

        if p_dialog:  # Update our progress dialog
            p_dialog_val = (s_count * 100) // s_total
            p_dialog_msg = u'Adding {} - {} to library...'.format(details_tvshow.get('original_name'), season_name)
            p_dialog.update(p_dialog_val, message=p_dialog_msg)

        details_season = _plugin.tmdb.get_request_sc('tv', tmdb_id, 'season', season)  # Get season
        if not details_season:
            return
        episodes = [i for i in details_season.get('episodes', []) if i.get('episode_number', 0) != 0]  # Only get non-special seasons

        e_count, e_total = 0, len(episodes)  # Used to update p_dialog progress
        for episode in episodes:
            e_count += 1
            episode_name = 'S{:02d}E{:02d} - {}'.format(
                utils.try_parse_int(season), utils.try_parse_int(episode.get('episode_number')),
                utils.validify_filename(episode.get('name')))

            # Skip future episodes
            if _addon.getSettingBool('hide_unaired_episodes'):
                if not episode.get('air_date') or utils.convert_timestamp(episode.get('air_date'), "%Y-%m-%d", 10) > datetime.datetime.now():
                    p_dialog.update((e_count * 100) // e_total, message=u'{} not aired yet. Skipping...'.format(episode_name)) if p_dialog else None
                    continue

            # Check if item has already been added
            if _plugin.get_db_info(info='dbid', tmdbtype='episode', imdb_id=imdb_id, tmdb_id=tmdb_id, season=season, episode=episode.get('episode_number')):
                utils.kodi_log(u'Add to Library\nFound {} - {} in library. Skipping...'.format(episode.get('showtitle'), episode_name))
                p_dialog.update((e_count * 100) // e_total, message=u'Found {} in library. Skipping...'.format(episode_name)) if p_dialog else None
                continue

            p_dialog.update((e_count * 100) // e_total, message=u'Adding {} to library...'.format(episode_name)) if p_dialog else None
            episode_path = 'plugin://plugin.video.themoviedb.helper/?info=play&type=episode&islocal=True'
            episode_path += '&tmdb_id={}&season={}&episode={}'.format(tmdb_id, season, episode.get('episode_number'))
            library_createfile(episode_name, episode_path, folder, season_name, basedir=basedir)
예제 #23
0
    def build_details(self):
        self.item['id'] = self.tmdb_id
        self.item['tmdb'] = self.tmdb_id
        self.item['imdb'] = self.details.get('infolabels', {}).get('imdbnumber')
        self.item['name'] = u'{0} ({1})'.format(self.item.get('title'), self.item.get('year'))
        self.item['premiered'] = self.item['firstaired'] = self.item['released'] = self.details.get('infolabels', {}).get('premiered')
        self.item['plot'] = self.details.get('infolabels', {}).get('plot')
        self.item['cast'] = self.item['actors'] = " / ".join([i.get('name') for i in self.details.get('cast', []) if i.get('name')])
        self.item['showname'] = self.item['clearname'] = self.item['tvshowtitle'] = self.item['title'] = self.item.get('title')
        self.item['thumbnail'] = self.details.get('thumb')
        self.item['poster'] = self.details.get('poster')
        self.item['fanart'] = self.details.get('fanart')
        self.item['now'] = datetime.datetime.now().strftime('%Y%m%d%H%M%S%f')

        if self.traktapi:
            slug_type = utils.type_convert(self.tmdbtype, 'trakt')
            trakt_details = self.traktapi.get_details(slug_type, self.traktapi.get_traktslug(slug_type, 'tmdb', self.tmdb_id))
            self.item['trakt'] = trakt_details.get('ids', {}).get('trakt')
            self.item['imdb'] = self.details.get('infoproperties', {}).get('tvshow.imdb_id') or trakt_details.get('ids', {}).get('imdb')
            self.item['tvdb'] = self.details.get('infoproperties', {}).get('tvshow.tvdb_id') or trakt_details.get('ids', {}).get('tvdb')
            self.item['slug'] = trakt_details.get('ids', {}).get('slug')

        if self.itemtype == 'episode':  # Do some special episode stuff
            self.item['id'] = self.item.get('tvdb')
            self.item['title'] = self.details.get('infolabels', {}).get('title')  # Set Episode Title
            self.item['name'] = u'{0} S{1:02d}E{2:02d}'.format(self.item.get('showname'), int(utils.try_parse_int(self.season)), int(utils.try_parse_int(self.episode)))
            self.item['season'] = self.season
            self.item['episode'] = self.episode
            self.item['showpremiered'] = self.details.get('infoproperties', {}).get('tvshow.premiered')
            self.item['showyear'] = self.details.get('infoproperties', {}).get('tvshow.year')

        if self.traktapi and self.itemtype == 'episode':
            trakt_details = self.traktapi.get_details(slug_type, self.item.get('slug'), season=self.season, episode=self.episode)
            self.item['epid'] = self.details.get('infoproperties', {}).get('tvdb_id') or trakt_details.get('ids', {}).get('tvdb')
            self.item['epimdb'] = trakt_details.get('ids', {}).get('imdb')
            self.item['eptmdb'] = self.details.get('infoproperties', {}).get('tmdb_id') or trakt_details.get('ids', {}).get('tmdb')
            self.item['eptrakt'] = trakt_details.get('ids', {}).get('trakt')

        utils.kodi_log(u'Player Details - Item:\n{}'.format(self.item), 2)

        for k, v in self.item.copy().items():
            if k not in constants.PLAYER_URLENCODE:
                continue
            v = u'{0}'.format(v)
            for key, value in {k: v, '{}_meta'.format(k): dumps(v)}.items():
                self.item[key] = value.replace(',', '')
                self.item[key + '_+'] = value.replace(',', '').replace(' ', '+')
                self.item[key + '_-'] = value.replace(',', '').replace(' ', '-')
                self.item[key + '_escaped'] = quote(quote(utils.try_encode_string(value)))
                self.item[key + '_escaped+'] = quote(quote_plus(utils.try_encode_string(value)))
                self.item[key + '_url'] = quote(utils.try_encode_string(value))
                self.item[key + '_url+'] = quote_plus(utils.try_encode_string(value))
 def close_dialog(self):
     self.reset_props()
     xbmc.executebuiltin('Dialog.Close({})'.format(ID_VIDEOINFO))
     close_id = utils.try_parse_int(self.params.get('close_dialog'))
     if close_id and xbmc.getCondVisibility('Window.IsVisible({})'.format(close_id)):
         close_id = close_id + 10000 if close_id < 10000 else close_id
         try:
             xbmcgui.Window(close_id).close()
         except Exception as exc:
             utils.kodi_log(exc, 1)
     if self.params.get('playmedia'):
         xbmc.executebuiltin('PlayMedia({})'.format(self.params.get('playmedia')))
     self.call_window()
 def process_ratings(self, details, tmdbtype, tmdb_id):
     try:
         if tmdbtype not in ['movie', 'tv']:
             return
         pre_item = self.pre_item
         details = self.get_omdb_ratings(details)
         details = self.get_top250_rank(details) if tmdbtype == 'movie' else details
         details = self.get_trakt_ratings(details, tmdbtype, tmdb_id, self.season, self.episode) if tmdbtype in ['movie', 'tv'] else details
         if not self.is_same_item(update=False, pre_item=pre_item):
             return
         self.set_iter_properties(details.get('infoproperties', {}), _setprop_ratings)
     except Exception as exc:
         utils.kodi_log(u'Func: process_ratings\n{}'.format(exc), 1)
예제 #26
0
def add_movie(tmdb_id, imdb_id=None, title='', year=''):
    content = 'plugin://plugin.video.themoviedb.helper/?info=play&tmdb_id={}&type=movie'.format(tmdb_id)
    folder = u'{} ({})'.format(title, year)
    db_file = _plugin.get_db_info(info='file', tmdbtype='movie', imdb_id=imdb_id, tmdb_id=tmdb_id)

    if not db_file:
        log_msg = u'Adding {} to library...'.format(folder)
        db_file = create_file(folder, content, folder, basedir=_basedir_movie)
        create_nfo('movie', tmdb_id, folder, basedir=_basedir_movie)
    else:
        log_msg = u'Found {} in library.'.format(folder)

    utils.kodi_log(log_msg)
    return ('filename', db_file.replace('\\', '/').split('/')[-1])
예제 #27
0
 def player_applyrules(self, folder, action):
     for x, f in enumerate(folder):
         for k, v in action.items():  # Iterate through our key (infolabel) / value (infolabel must match) pairs of our action
             if k == 'position':  # We're looking for an item position not an infolabel
                 if utils.try_parse_int(string_format_map(v, self.item)) != x + 1:  # Format our position value and add one since people are dumb and don't know that arrays start at 0
                     break  # Not the item position we want so let's go to next item in folder
             elif not f.get(k) or not re.match(string_format_map(v, self.item), u'{}'.format(f.get(k, ''))):  # Format our value and check if it regex matches the infolabel key
                 break  # Item's key value doesn't match value we are looking for so let's got to next item in folder
         else:  # Item matched our criteria so let's return it
             utils.kodi_log('Player -- Found Match!\n{}'.format(f), 2)
             resolve_url = True if f.get('filetype') == 'file' else False  # Set true for files so we can play
             return (resolve_url, f.get('file'))  # Get ListItem.FolderPath for item and return as player
     utils.kodi_log('Player -- Failed to find match!\n{}'.format(action), 2)
     return -1  # Got through the entire folder without a match so ask user to select new player
예제 #28
0
 def get_api_request(self, request=None, is_json=True, postdata=None, headers=None, dictify=True):
     """
     Make the request to the API by passing a url request string
     """
     if utils.get_timestamp(self.req_connect_err):
         return {} if dictify else None  # Connection error in last minute for this api so don't keep trying
     if self.req_wait_time:
         utils.rate_limiter(addon_name=self.cache_name, wait_time=self.req_wait_time, api_name=self.req_api_name)
     try:
         response = requests.post(request, data=postdata, headers=headers) if postdata else requests.get(request, headers=headers)  # Request our data
     except Exception as err:
         self.req_connect_err = utils.set_timestamp()
         xbmcgui.Window(10000).setProperty(self.req_connect_err_prop, str(self.req_connect_err))
         utils.kodi_log(u'ConnectionError: {}\nSuppressing retries for 1 minute'.format(err), 1)
         return {} if dictify else None
     if not response.status_code == requests.codes.ok and utils.try_parse_int(response.status_code) >= 400:  # Error Checking
         if response.status_code == 401:
             utils.kodi_log(u'HTTP Error Code: {0}\nRequest: {1}\nPostdata: {2}\nHeaders: {3}\nResponse: {4}'.format(response.status_code, request, postdata, headers, response), 1)
             self.invalid_apikey()
         elif response.status_code == 500:
             self.req_connect_err = utils.set_timestamp()
             xbmcgui.Window(10000).setProperty(self.req_connect_err_prop, str(self.req_connect_err))
             utils.kodi_log(u'HTTP Error Code: {0}\nRequest: {1}\nSuppressing retries for 1 minute'.format(response.status_code, request), 1)
         elif utils.try_parse_int(response.status_code) > 400:  # Don't write 400 error to log
             utils.kodi_log(u'HTTP Error Code: {0}\nRequest: {1}'.format(response.status_code, request), 1)
         return {} if dictify else None
     if dictify and is_json:
         response = response.json()  # Make the response nice
     elif dictify:
         response = self.translate_xml(response)
     return response
    def play_external(self, playerindex=-1, force_dialog=False):
        playerindex = self.player_getnewindex(playerindex, force_dialog=force_dialog)

        # User cancelled dialog
        if not playerindex > -1:
            utils.kodi_log(u'Player -- User cancelled', 2)
            return False

        # Run through player actions
        player = self.player_resolveurl(self.actions[playerindex])

        # Previous player failed so ask user to select a new one
        if player == -1:
            return self.play_external(playerindex, force_dialog=force_dialog)

        # Play/Search found item
        if player and player[1]:
            action = string_format_map(player[1], self.item)
            if player[0] and (action.endswith('.strm') or self.identifierlist[playerindex] == 'play_kodi'):  # Action is play and is a strm/local so PlayMedia
                utils.kodi_log(u'Player -- Found strm or local.\nAttempting PLAYMEDIA({})'.format(action), 1)
                xbmc.executebuiltin(utils.try_decode_string(u'PlayMedia(\"{0}\")'.format(action)))
            elif player[0]:  # Action is play and not a strm so play with player
                utils.kodi_log(u'Player -- Found file.\nAttempting to PLAY: {}'.format(action), 2)
                xbmcgui.Window(10000).setProperty('TMDbHelper.PlayerInfoString', self.playerstring) if self.playerstring else None
                xbmc.Player().play(action, ListItem(library='video', **self.details).set_listitem())
            else:
                action = u'Container.Update({0})'.format(action) if xbmc.getCondVisibility("Window.IsMedia") else u'ActivateWindow(videos,{0},return)'.format(action)
                utils.kodi_log(u'Player -- Found folder.\nAttempting to OPEN: {}'.format(action), 2)
                xbmc.executebuiltin(utils.try_encode_string(utils.try_decode_string(action)))
            return action
 def set_url_props(self, url, prefix='Item'):
     for k, v in url.items():
         if not k or not v:
             continue
         try:
             self.infoproperties[u'{}.{}'.format(
                 prefix, utils.try_decode_string(k))] = u'{}'.format(
                     utils.try_decode_string(v))
         except Exception as exc:
             utils.kodi_log(
                 u'ERROR in ListItem set_url_props\nk:{} v:{}'.format(
                     utils.try_decode_string(k),
                     utils.try_decode_string(v)), 1)
             utils.kodi_log(exc, 1)