def get_upnext(self, show_id, response_only=False, last_updated=None):
        items = []
        if not self.authorize():
            return items

        cache_refresh = self.get_upnext_cache_refresh(show_id, last_updated)

        request = 'shows/{0}/progress/watched'.format(show_id)
        response = self.get_request(request, cache_refresh=cache_refresh, cache_days=1)
        reset_at = utils.convert_timestamp(response.get('reset_at')) if response.get('reset_at') else None
        seasons = response.get('seasons', [])
        for season in seasons:
            s_num = season.get('number')
            for episode in season.get('episodes', []):
                item = None
                e_num = episode.get('number')
                if episode.get('completed'):
                    if reset_at and utils.convert_timestamp(episode.get('last_watched_at')) < reset_at:
                        item = (s_num, e_num)
                else:
                    item = (s_num, e_num)
                if item:
                    if response_only:
                        # utils.kodi_log(u'Up Next {} Episodes:\nFound next episode - S{}E{}'.format(show_id, s_num, e_num), 1)
                        return response
                    items.append(item)
        if not response_only:
            return items if items else [(1, 1)]
 def get_upnext(self, show_id, response_only=False):
     items = []
     if not self.authorize():
         return items
     request = 'shows/{0}/progress/watched'.format(show_id)
     response = self.get_response_json(request)
     reset_at = utils.convert_timestamp(
         response.get('reset_at')) if response.get('reset_at') else None
     seasons = response.get('seasons', [])
     for season in seasons:
         s_num = season.get('number')
         for episode in season.get('episodes', []):
             item = None
             e_num = episode.get('number')
             if episode.get('completed'):
                 if reset_at and utils.convert_timestamp(
                         episode.get('last_watched_at')) < reset_at:
                     item = (s_num, e_num)
             else:
                 item = (s_num, e_num)
             if item:
                 if response_only:
                     return response
                 items.append(item)
     if not response_only:
         return items if items else [(1, 1)]
    def get_upnext_cache_refresh(self, show_id, last_updated):
        if not last_updated:  # No last Trakt update date so refresh cache
            return True  # Refresh cache

        ts_last = utils.convert_timestamp(last_updated)
        if not ts_last:
            return True  # Timestamp doesn't convert so refresh cache

        cache_name = '{0}.trakt.show.{1}.last_updated'.format(self.cache_name, show_id)
        ts_prev = utils.convert_timestamp(self.get_cache(cache_name))
        if not ts_prev:  # No previous update date or cant convert save value to timestamp so refresh
            return self.set_cache(last_updated, cache_name)  # Set the cache date and refresh cache

        if ts_prev < ts_last:  # Changes on Trakt since previous update date so refresh cache
            return self.set_cache(last_updated, cache_name)  # Set the cache date and refresh cache
Ejemplo n.º 4
0
    def run(self):
        self.kodimonitor.waitForAbort(
            450)  # Delay start-up to give time for datetime python module
        self.nexttime = datetime.datetime.combine(
            datetime.datetime.today(),
            datetime.time(utils.try_parse_int(
                self.update_hour)))  # Get today at hour
        self.lasttime = xbmc.getInfoLabel(
            'Skin.String(TMDbHelper.AutoUpdate.LastTime)')  # Get last update
        self.lasttime = utils.convert_timestamp(
            self.lasttime) if self.lasttime else None
        if self.lasttime and self.lasttime > self.nexttime:
            self.nexttime += datetime.timedelta(
                hours=24)  # Already updated today so set for tomorrow

        while not self.kodimonitor.abortRequested(
        ) and not self.exit and self.poll_time:
            if self.addon.getSettingBool('library_autoupdate'):
                if datetime.datetime.now(
                ) > self.nexttime:  # 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.nexttime += datetime.timedelta(
                        hours=24)  # Set next update for tomorrow
            self.kodimonitor.waitForAbort(self.poll_time)
    def get_trakt_watched(self, trakt_watched=None):
        if not trakt_watched:
            return

        key = 'movie' if self.infolabels.get(
            'mediatype') == 'movie' else 'show'
        item = utils.get_dict_in_list(trakt_watched, 'tmdb',
                                      utils.try_parse_int(self.tmdb_id),
                                      [key, 'ids'])
        if not item:
            return

        if self.infolabels.get('mediatype') == 'episode':
            found_ep = None
            for s in item.get('seasons', []):
                if s.get('number', -2) == utils.try_parse_int(
                        self.infolabels.get('season', -1)):
                    for ep in s.get('episodes', []):
                        if ep.get('number', -2) == utils.try_parse_int(
                                self.infolabels.get('episode', -1)):
                            found_ep = item = ep
                            break
                    break
            if not found_ep:
                return

        lastplayed = utils.convert_timestamp(item.get('last_watched_at'))
        self.infolabels['lastplayed'] = lastplayed.strftime(
            '%Y-%m-%d %H:%M:%S') if lastplayed else None
        self.infolabels['playcount'] = item.get('plays', 0)
        self.infolabels['overlay'] = 5 if item.get('plays') else 4
Ejemplo n.º 6
0
    def get_calendar_properties(self, item, i):
        # Create our airing properties
        air_date = utils.convert_timestamp(i.get('first_aired'),
                                           utc_convert=True)
        item.infolabels['premiered'] = air_date.strftime('%Y-%m-%d')
        item.infolabels['year'] = air_date.strftime('%Y')
        item.infoproperties['air_date'] = utils.get_region_date(
            air_date, 'datelong')
        item.infoproperties['air_time'] = utils.get_region_date(
            air_date, 'time')
        item.infoproperties['air_day'] = air_date.strftime('%A')
        item.infoproperties['air_day_short'] = air_date.strftime('%a')
        item.infoproperties['air_date_short'] = air_date.strftime('%d %b')

        # Do some fallback properties in-case TMDb doesn't have info
        item.infolabels['title'] = item.label = i.get('episode',
                                                      {}).get('title')
        item.infolabels['episode'] = item.infolabels.get('episode') or i.get(
            'episode', {}).get('number')
        item.infolabels['season'] = item.infolabels.get('season') or i.get(
            'episode', {}).get('season')
        item.infolabels['tvshowtitle'] = i.get('show', {}).get('title')
        item.infolabels['duration'] = item.infolabels.get(
            'duration') or utils.try_parse_int(
                i.get('episode', {}).get('runtime', 0)) * 60
        item.infolabels['plot'] = item.infolabels.get('plot') or i.get(
            'episode', {}).get('overview')
        item.infolabels['mpaa'] = item.infolabels.get('mpaa') or i.get(
            'show', {}).get('certification')

        return item
Ejemplo n.º 7
0
    def run(self):
        xbmc.Monitor().waitForAbort(120)
        if self.addon.getSettingString('trakt_token'):
            _homewindow.setProperty('TMDbHelper.TraktIsAuth', 'True')
            self.get_trakt_usernameslug()
        xbmc.Monitor().waitForAbort(540)  # Wait a bit before updating
        self.nexttime = datetime.datetime.combine(
            datetime.datetime.today(),
            datetime.time(utils.try_parse_int(
                self.update_hour)))  # Get today at hour
        self.lasttime = xbmc.getInfoLabel(
            'Skin.String(TMDbHelper.AutoUpdate.LastTime)')  # Get last update
        self.lasttime = utils.convert_timestamp(
            self.lasttime) if self.lasttime else None
        if self.lasttime and self.lasttime > self.nexttime:
            self.nexttime += datetime.timedelta(
                hours=24)  # Already updated today so set for tomorrow

        while not xbmc.Monitor().abortRequested(
        ) and not self.exit and self.poll_time:
            if self.addon.getSettingBool('library_autoupdate'):
                if datetime.datetime.now(
                ) > self.nexttime:  # 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.nexttime += datetime.timedelta(
                        hours=24)  # Set next update for tomorrow
            xbmc.Monitor().waitForAbort(self.poll_time)
Ejemplo n.º 8
0
    def get_calendar_episodes(self, startdate=0, days=1, limit=25):
        items = []

        if not self.tmdb or not self.authorize():
            return items

        date = datetime.datetime.today() + datetime.timedelta(days=startdate)
        response = TraktAPI().get_calendar(
            'shows', True, start_date=date.strftime('%Y-%m-%d'), days=days)

        if not response:
            return items

        for i in response[-limit:]:
            episode = i.get('episode', {}).get('number')
            season = i.get('episode', {}).get('season')
            tmdb_id = i.get('show', {}).get('ids', {}).get('tmdb')
            item = ListItem(library=self.library,
                            **self.tmdb.get_detailed_item(itemtype='tv',
                                                          tmdb_id=tmdb_id,
                                                          season=season,
                                                          episode=episode))
            item.tmdb_id, item.season, item.episode = tmdb_id, season, episode
            item.infolabels['title'] = item.label = i.get('episode',
                                                          {}).get('title')
            air_date = utils.convert_timestamp(i.get(
                'first_aired', '')) + datetime.timedelta(hours=self.utc_offset)
            item.infolabels['premiered'] = air_date.strftime('%Y-%m-%d')
            item.infolabels['year'] = air_date.strftime('%Y')
            item.infoproperties['air_time'] = air_date.strftime('%I:%M %p')
            items.append(item)
        return items
    def get_upnext_cache_refresh(self, show_id, last_updated):
        if not last_updated:  # No last Trakt update date so refresh cache
            # utils.kodi_log(u'Up Next {} Episodes:\nNo last Trakt update date. Refreshing cache...'.format(show_id), 1)
            return True  # Refresh cache

        cache_name = '{0}.trakt.show.{1}.last_updated'.format(
            self.cache_name, show_id)
        prev_updated = self.get_cache(cache_name)
        if not prev_updated:  # No previous update date so refresh cache
            # utils.kodi_log(u'Up Next {} Episodes:\nNo previous update date. Refreshing cache...'.format(show_id), 1)
            return self.set_cache(
                last_updated,
                cache_name)  # Set the cache date and refresh cache

        if utils.convert_timestamp(prev_updated) < utils.convert_timestamp(
                last_updated
        ):  # Changes on Trakt since previous update date so refresh cache
            # utils.kodi_log(u'Up Next {} Episodes:\nChanges on Trakt since previous update date. Refreshing cache...'.format(show_id), 1)
            return self.set_cache(
                last_updated,
                cache_name)  # Set the cache date and refresh cache
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)
Ejemplo n.º 11
0
def add_tvshow(basedir=None, folder=None, url=None, tmdb_id=None, tvdb_id=None, imdb_id=None, p_dialog=None, force=False):
    if not basedir or not folder or not url or not tmdb_id:
        return

    # Get our cached info
    cache_name = 'plugin.video.themoviedb.helper.library_autoupdate_tv.{}'.format(tmdb_id)
    cache_info = {} if force else _cache.get(cache_name) or {}
    cache_version = 7

    # If there's already a folder for a different show with the same name then create a separate folder
    nfo_id = utils.get_tmdbid_nfo(basedir, folder) if folder in xbmcvfs.listdir(basedir)[0] else None
    if nfo_id and utils.try_parse_int(nfo_id) != utils.try_parse_int(tmdb_id):
        folder += ' (TMDB {})'.format(tmdb_id)

    # Only use cache info if version matches
    if not cache_info.get('version') or cache_info.get('version') != cache_version:
        cache_info = {}

    # If there is a next check value and it hasn't elapsed then skip the update
    next_check = cache_info.get('next_check')
    if next_check and utils.convert_timestamp(next_check, "%Y-%m-%d", 10) > datetime.datetime.today():
        if _debuglogging:
            log_msg = cache_info.get('log_msg') or ''
            utils.kodi_log(u'Skipping updating {} (TMDB {})\nNext update {}{}'.format(
                cache_info.get('name'), tmdb_id, next_check, log_msg), 2)
        return

    # Get all seasons in the tvshow except specials
    details_tvshow = _plugin.tmdb.get_request('tv', tmdb_id, cache_days=1, append_to_response='external_ids')
    if not details_tvshow:
        return

    # Update IDs from detailed info
    tvdb_id = details_tvshow.get('external_ids', {}).get('tvdb_id') or tvdb_id
    imdb_id = details_tvshow.get('external_ids', {}).get('imdb_id') or imdb_id

    # Create the .nfo file in the folder
    create_nfo('tv', tmdb_id, folder, basedir=basedir)

    # Construct our cache object
    today_date = datetime.datetime.today().strftime('%Y-%m-%d')
    my_history = {
        'version': cache_version,
        'name': details_tvshow.get('name', ''),
        'skipped': [],
        'episodes': [],
        'latest_season': 0,
        'next_check': today_date,
        'last_check': today_date,
        'log_msg': ''}

    # Set the next check date for this show
    next_aired = details_tvshow.get('next_episode_to_air', {})
    if next_aired and next_aired.get('air_date'):
        next_aired_dt = utils.convert_timestamp(next_aired.get('air_date'), "%Y-%m-%d", 10)
        if next_aired_dt > datetime.datetime.today():
            if next_aired_dt < (datetime.datetime.today() + datetime.timedelta(days=7)):
                my_history['next_check'] = next_aired.get('air_date')
                my_history['log_msg'] = '\nShow had next aired date this week'
                # Check again on the next aired date
            elif next_aired_dt < (datetime.datetime.today() + datetime.timedelta(days=30)):
                my_next_check = datetime.datetime.today() + datetime.timedelta(days=7)
                my_history['next_check'] = my_next_check.strftime('%Y-%m-%d')
                my_history['log_msg'] = '\nShow has next aired date this month'
                # Check again in a week just to be safe in case air date changes
            else:
                my_next_check = datetime.datetime.today() + datetime.timedelta(days=30)
                my_history['next_check'] = my_next_check.strftime('%Y-%m-%d')
                my_history['log_msg'] = '\nShow has next aired date in more than a month'
                # Check again in a month just to be safe in case air date changes
        else:
            next_aired = None  # Next aired was in the past for some reason so dont use that date

    last_aired = details_tvshow.get('last_episode_to_air', {})
    if not next_aired and last_aired and last_aired.get('air_date'):
        last_aired_dt = utils.convert_timestamp(last_aired.get('air_date'), "%Y-%m-%d", 10)
        if last_aired_dt > (datetime.datetime.today() - datetime.timedelta(days=30)):
            my_next_check = datetime.datetime.today() + datetime.timedelta(days=1)
            my_history['next_check'] = my_next_check.strftime('%Y-%m-%d')
            my_history['log_msg'] = '\nShow aired in last month but no next aired date'
            # Show might be currently airing but just hasnt updated next date yet so check again tomorrow
        elif last_aired_dt > (datetime.datetime.today() - datetime.timedelta(days=90)):
            my_history['log_msg'] = '\nShow aired in last quarter but not in last month'
            my_next_check = datetime.datetime.today() + datetime.timedelta(days=7)
            my_history['next_check'] = my_next_check.strftime('%Y-%m-%d')
            # Show might be on a mid-season break so check again in a week for a return date
        elif details_tvshow.get('status') in ['Canceled', 'Ended']:
            my_history['log_msg'] = '\nShow was canceled or ended'
            my_next_check = datetime.datetime.today() + datetime.timedelta(days=30)
            my_history['next_check'] = my_next_check.strftime('%Y-%m-%d')
            # Show was canceled so check again in a month just to be safe
        else:
            my_history['log_msg'] = '\nShow last aired more than 3 months ago and no next aired date set'
            my_next_check = datetime.datetime.today() + datetime.timedelta(days=7)
            my_history['next_check'] = my_next_check.strftime('%Y-%m-%d')
            # Show hasnt aired in a while so check every week for a return date

    prev_added_eps = cache_info.get('episodes') or []
    prev_skipped_eps = cache_info.get('skipped') or []

    seasons = details_tvshow.get('seasons', [])
    s_total = len(seasons)
    for s_count, season in enumerate(seasons):
        # Skip special seasons
        if season.get('season_number', 0) == 0:
            if _debuglogging:
                utils.kodi_log(u'{} (TMDB {})\nSpecial Season. Skipping...'.format(details_tvshow.get('name'), tmdb_id), 2)
            s_total -= 1
            continue

        season_name = u'Season {}'.format(season.get('season_number'))

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

        # If weve scanned before we only want to scan the most recent seasons (that have already started airing)
        latest_season = utils.try_parse_int(cache_info.get('latest_season', 0))
        if utils.try_parse_int(season.get('season_number', 0)) < latest_season:
            if _debuglogging:
                utils.kodi_log(u'{} (TMDB {})\nPreviously Added {}. Skipping...'.format(details_tvshow.get('name'), tmdb_id, season_name), 2)
            continue

        # Get all episodes in the season except specials
        details_season = _plugin.tmdb.get_request('tv', tmdb_id, 'season', season.get('season_number'), cache_refresh=True)
        if not details_season:
            utils.kodi_log(u'{} (TMDB {})\nNo details found for {}. Skipping...'.format(details_tvshow.get('name'), tmdb_id, season_name))
            return
        episodes = [i for i in details_season.get('episodes', []) if i.get('episode_number', 0) != 0]  # Only get non-special seasons
        skipped_eps, future_eps, library_eps = [], [], []
        for e_count, episode in enumerate(episodes):
            episode_name = 'S{:02d}E{:02d} - {}'.format(
                utils.try_parse_int(season.get('season_number')), utils.try_parse_int(episode.get('episode_number')),
                utils.validify_filename(episode.get('name')))

            my_history['episodes'].append(episode_name)

            # Skip episodes we added in the past
            if episode_name in prev_added_eps:
                if episode_name not in prev_skipped_eps:
                    if _debuglogging:
                        skipped_eps.append(episode_name)
                    continue

            # Skip future episodes
            if _addon.getSettingBool('hide_unaired_episodes'):
                air_date = utils.convert_timestamp(episode.get('air_date'), "%Y-%m-%d", 10)
                if not air_date or air_date > datetime.datetime.now():
                    if _debuglogging:
                        future_eps.append(episode_name)
                    my_history['skipped'].append(episode_name)
                    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, tvdb_id=tvdb_id, season=season.get('season_number'), episode=episode.get('episode_number')):
                if _debuglogging:
                    library_eps.append(episode_name)
                continue

            # Update progress dialog
            if p_dialog:
                p_dialog.update(((e_count + 1) * 100) // len(episodes))

            # Create our .strm file for the episode
            episode_path = 'plugin://plugin.video.themoviedb.helper/?info=play&type=episode&islocal=True'
            episode_path += '&tmdb_id={}&season={}&episode={}'.format(tmdb_id, season.get('season_number', 0), episode.get('episode_number'))
            create_file(episode_name, episode_path, folder, season_name, basedir=basedir)

        # Some logging of what we did
        if _debuglogging:
            klog_msg = u'{} (TMDB {}) - {} - Done!'.format(details_tvshow.get('name'), tmdb_id, season_name)
            if skipped_eps:
                klog_msg += u'\nSkipped Previously Added Episodes:\n{}'.format(skipped_eps)
            if library_eps:
                klog_msg += u'\nSkipped Episodes in Library:\n{}'.format(library_eps)
            if future_eps:
                klog_msg += u'\nSkipped Unaired Episodes:\n{}'.format(future_eps)
            utils.kodi_log(klog_msg, 2)

        # Store a season value of where we got up to
        if len(episodes) > 2:
            air_date = utils.convert_timestamp(season.get('air_date'), "%Y-%m-%d", 10)
            if air_date and air_date < datetime.datetime.now():  # Make sure the season has actually aired!
                my_history['latest_season'] = utils.try_parse_int(season.get('season_number'))

    # Store details about what we did into the cache
    _cache.set(cache_name, my_history, expiration=datetime.timedelta(days=120))