def list_discoverdir_router(self, **kwargs): if kwargs.get('clear_cache') != 'True' and kwargs.get( 'method') not in ['delete', 'rename']: return self.list_discoverdir(**kwargs) params = kwargs.copy() params.pop('clear_cache', None) params.pop('method', None) params.pop('idx', None) self.container_update = '{},replace'.format( encode_url(PLUGINPATH, **params)) if kwargs.get('clear_cache') == 'True': set_search_history('discover', clear_cache=True) elif kwargs.get('method') == 'delete': idx = try_int(kwargs.get('idx', -1)) if idx == -1: return set_search_history('discover', replace=idx) elif kwargs.get('method') == 'rename': idx = try_int(kwargs.get('idx', -1)) if idx == -1: return history = get_search_history('discover') try: item = history[idx] except IndexError: return if not item: return item['label'] = xbmcgui.Dialog().input( 'Rename', defaultt=item.get('label')) or item.get('label') set_search_history('discover', item, replace=idx)
def get_collection_properties(v): ratings = [] infoproperties = {} year_l, year_h, votes = 9999, 0, 0 for p, i in enumerate(v): infoproperties[u'set.{}.title'.format(p)] = i.get('title', '') infoproperties[u'set.{}.tmdb_id'.format(p)] = i.get('id', '') infoproperties[u'set.{}.originaltitle'.format(p)] = i.get('original_title', '') infoproperties[u'set.{}.plot'.format(p)] = i.get('overview', '') infoproperties[u'set.{}.premiered'.format(p)] = i.get('release_date', '') infoproperties[u'set.{}.year'.format(p)] = i.get('release_date', '')[:4] infoproperties[u'set.{}.rating'.format(p)] = u'{:0,.1f}'.format(try_float(i.get('vote_average'))) infoproperties[u'set.{}.votes'.format(p)] = i.get('vote_count', '') infoproperties[u'set.{}.poster'.format(p)] = get_imagepath_poster(i.get('poster_path', '')) infoproperties[u'set.{}.fanart'.format(p)] = get_imagepath_fanart(i.get('backdrop_path', '')) year_l = min(try_int(i.get('release_date', '')[:4]), year_l) year_h = max(try_int(i.get('release_date', '')[:4]), year_h) if i.get('vote_average'): ratings.append(i['vote_average']) votes += try_int(i.get('vote_count', 0)) if year_l == 9999: year_l = None if year_l: infoproperties['set.year.first'] = year_l if year_h: infoproperties['set.year.last'] = year_h if year_l and year_h: infoproperties['set.years'] = u'{0} - {1}'.format(year_l, year_h) if len(ratings): infoproperties['set.rating'] = infoproperties['tmdb_rating'] = u'{:0,.1f}'.format(sum(ratings) / len(ratings)) if votes: infoproperties['set.votes'] = infoproperties['tmdb_votes'] = u'{:0,.0f}'.format(votes) infoproperties['set.numitems'] = p return infoproperties
def _add_season(self, season, blacklist=[0]): number = season.get('season_number', 0) folder = u'Season {}'.format(number) # Skip blacklisted seasons if try_int(number) in blacklist: # TODO: Optional whitelist also self._log._add('tv', self.tv.tmdb_id, 'skipped special season', season=number) return # Skip if we've added season before and it isn't the most recent season # We still add most recent season even if we added it before because it might currently be airing if self._log._add('tv', self.tv.tmdb_id, self.tv._cache.is_added_season(number), season=number): return # Add our episodes for x, episode in enumerate(self.tv.get_episodes(number), 1): self._add_episode(episode, number, folder) self._update(x, self.tv.e_total) # Store a season value of where we got up to if self.tv.e_total > 2 and season.get( 'air_date') and not is_future_timestamp( season.get('air_date'), "%Y-%m-%d", 10): self.tv._cache.my_history['latest_season'] = try_int(number)
def get_info( self, info, dbid=None, imdb_id=None, originaltitle=None, title=None, year=None, season=None, episode=None, fuzzy_match=False, tmdb_id=None, tvdb_id=None): if not self.database or not info: return yearcheck = False index_list = find_dict_in_list(self.database, 'dbid', dbid) if dbid else [] if not index_list and season: index_list = find_dict_in_list(self.database, 'season', try_int(season)) if not index_list and imdb_id: index_list = find_dict_in_list(self.database, 'imdb_id', imdb_id) if not index_list and tmdb_id: index_list = find_dict_in_list(self.database, 'tmdb_id', str(tmdb_id)) if not index_list and tvdb_id: index_list = find_dict_in_list(self.database, 'tvdb_id', str(tvdb_id)) if not index_list: yearcheck = str(year) or 'dummynull' # Also use year if matching by title to be certain we have correct item. Dummy value for True value that will always fail comparison check. if not index_list and originaltitle: index_list = find_dict_in_list(self.database, 'originaltitle', originaltitle) if not index_list and title: index_list = find_dict_in_list(self.database, 'title', title) for i in index_list: if season and episode: if try_int(episode) == self.database[i].get('episode'): return self.database[i].get(info) elif not yearcheck or yearcheck in str(self.database[i].get('year')): return self.database[i].get(info) if index_list and fuzzy_match and not season and not episode: """ Fuzzy Match """ i = index_list[0] return self.database[i].get(info)
def _get_language_item(tmdb_type, tmdb_id, season=None, episode=None, language=None, year=None): item = _get_language_details(tmdb_type, tmdb_id, language=language) if not item: return item['showname'] = item['clearname'] = item['tvshowtitle'] = item.get( 'title') item['name'] = u'{} ({})'.format( item['title'], year) if item.get('title') and year else None if season is None or episode is None: return item episode = _get_language_details(tmdb_type, tmdb_id, season, episode, language=language) if not episode: return item item['title'] = episode.get('title') item['plot'] = episode.get('plot') or item.get('plot') item['name'] = u'{0} S{1:02d}E{2:02d}'.format( item['showname'], try_int(season), try_int(episode)) if item.get('showname') else None return item
def _get_tmdb_id(self, tmdb_type, imdb_id, tvdb_id, query, year, episode_year, raw_data, **kwargs): func = self.get_request_sc if not tmdb_type: return request = None if tmdb_type == 'genre' and query: return TMDB_GENRE_IDS.get(query, '') elif imdb_id: request = func('find', imdb_id, language=self.req_language, external_source='imdb_id') request = request.get('{0}_results'.format(tmdb_type), []) elif tvdb_id: request = func('find', tvdb_id, language=self.req_language, external_source='tvdb_id') request = request.get('{0}_results'.format(tmdb_type), []) elif query: query = query.split(' (', 1)[0] # Scrub added (Year) or other cruft in parentheses () added by Addons or TVDb if tmdb_type == 'tv': request = func('search', tmdb_type, language=self.req_language, query=query, first_air_date_year=year) else: request = func('search', tmdb_type, language=self.req_language, query=query, year=year) request = request.get('results', []) if not request: return if raw_data: return request if tmdb_type == 'tv' and episode_year and len(request) > 1: for i in sorted(request, key=lambda k: k.get('first_air_date', ''), reverse=True): if not i.get('first_air_date'): continue if try_int(i.get('first_air_date', '9999')[:4]) <= try_int(episode_year): if query in [i.get('name'), i.get('original_name')]: return i.get('id') return request[0].get('id')
def __init__(self, trakt_type, unique_id, season=None, episode=None, id_type=None): self.trakt_type = trakt_type self.unique_id = unique_id self.season = try_int(season) if season is not None else None self.episode = try_int(episode) if episode is not None else None self.id_type = id_type self.trakt_api = TraktAPI()
def _translate_discover_params(tmdb_type, params): lookup_keyword = None if params.get('with_id') and params.get('with_id') != 'False' else 'keyword' lookup_company = None if params.get('with_id') and params.get('with_id') != 'False' else 'company' lookup_person = None if params.get('with_id') and params.get('with_id') != 'False' else 'person' lookup_genre = None if params.get('with_id') and params.get('with_id') != 'False' else 'genre' with_separator = params.get('with_separator') if params.get('with_genres'): params['with_genres'] = TMDb().get_translated_list( split_items(params.get('with_genres')), lookup_genre, separator=with_separator) if params.get('without_genres'): params['without_genres'] = TMDb().get_translated_list( split_items(params.get('without_genres')), lookup_genre, separator=with_separator) if params.get('with_keywords'): params['with_keywords'] = TMDb().get_translated_list( split_items(params.get('with_keywords')), lookup_keyword, separator=with_separator) if params.get('without_keywords'): params['without_keywords'] = TMDb().get_translated_list( split_items(params.get('without_keywords')), lookup_keyword, separator=with_separator) if params.get('with_companies'): params['with_companies'] = TMDb().get_translated_list( split_items(params.get('with_companies')), lookup_company, separator='NONE') if params.get('with_people'): params['with_people'] = TMDb().get_translated_list( split_items(params.get('with_people')), lookup_person, separator=with_separator) if params.get('with_cast'): params['with_cast'] = TMDb().get_translated_list( split_items(params.get('with_cast')), lookup_person, separator=with_separator) if params.get('with_crew'): params['with_crew'] = TMDb().get_translated_list( split_items(params.get('with_crew')), lookup_person, separator=with_separator) if params.get('with_release_type'): params['with_release_type'] = TMDb().get_translated_list( split_items(params.get('with_release_type')), None, separator='OR') # Translate relative dates based upon today's date for i in RELATIVE_DATES: datecode = params.get(i, '') datecode = datecode.lower() if not datecode or all(x not in datecode for x in ['t-', 't+']): continue # No value or not a relative date so skip elif 't-' in datecode: days = try_int(datecode.replace('t-', '')) date = get_datetime_now() - get_timedelta(days=days) elif 't+' in datecode: days = try_int(datecode.replace('t+', '')) date = get_datetime_now() + get_timedelta(days=days) params[i] = date.strftime("%Y-%m-%d") return params
def get_basic_list(self, path, tmdb_type, key='results', params=None, base_tmdb_type=None, **kwargs): response = self.get_request_sc(path, **kwargs) results = response.get(key, []) if response else [] items = [ self.mapper.get_info(i, tmdb_type, definition=params, base_tmdb_type=base_tmdb_type) for i in results if i] if try_int(response.get('page', 0)) < try_int(response.get('total_pages', 0)): items.append({'next_page': try_int(response.get('page', 0)) + 1}) return items
def get_calendar_episodes(self, startdate=0, days=1, user=True): # Broaden date range in case utc conversion bumps into different day mod_date = try_int(startdate) - 1 mod_days = try_int(days) + 2 date = get_datetime_today() + get_timedelta(days=mod_date) return self.get_calendar('shows', user, start_date=date.strftime('%Y-%m-%d'), days=mod_days)
def get_episode_playcount(self, unique_id, id_type, season, episode): season = try_int(season, fallback=-2) # Make fallback -2 to prevent matching on 0 episode = try_int(episode, fallback=-2) # Make fallback -2 to prevent matching on 0 for i in self.get_sync('watched', 'show', id_type).get(unique_id, {}).get('seasons', []): if i.get('number', -1) != season: continue for j in i.get('episodes', []): if j.get('number', -1) == episode: return j.get('plays', 1)
def _player_dialog_select(self, folder, auto=False): d_items = [] for f in folder: # Skip items without labels as probably not worth playing if not f.get('label') or f.get('label') == 'None': continue # Get the label of the item label_a = f.get('label') # Add year to our label if exists and not special value of 1601 if f.get('year') and f.get('year') != 1601: label_a = u'{} ({})'.format(label_a, f.get('year')) # Add season and episode numbers to label if try_int(f.get('season', 0)) > 0 and try_int(f.get('episode', 0)) > 0: label_a = u'{}x{}. {}'.format(f.get('season'), f.get('episode'), label_a) # Add various stream details to ListItem.Label2 (aka label_b) label_b_list = [] if f.get('streamdetails'): sdv_list = f.get('streamdetails', {}).get('video', [{}]) or [{}] sda_list = f.get('streamdetails', {}).get('audio', [{}]) or [{}] sdv, sda = sdv_list[0], sda_list[0] if sdv.get('width') or sdv.get('height'): label_b_list.append(u'{}x{}'.format(sdv.get('width'), sdv.get('height'))) if sdv.get('codec'): label_b_list.append(u'{}'.format(sdv.get('codec', '').upper())) if sda.get('codec'): label_b_list.append(u'{}'.format(sda.get('codec', '').upper())) if sda.get('channels'): label_b_list.append(u'{} CH'.format(sda.get('channels', ''))) for i in sda_list: if i.get('language'): label_b_list.append(u'{}'.format(i.get('language', '').upper())) if sdv.get('duration'): label_b_list.append(u'{} mins'.format(try_int(sdv.get('duration', 0)) // 60)) if f.get('size'): label_b_list.append(u'{}'.format(normalise_filesize(f.get('size', 0)))) label_b = ' | '.join(label_b_list) if label_b_list else '' # Add item to select dialog list d_items.append(ListItem(label=label_a, label2=label_b, art={'thumb': f.get('thumbnail')}).get_listitem()) if not d_items: return -1 # No items so ask user to select new player # If autoselect enabled and only 1 item choose that otherwise ask user to choose idx = 0 if auto and len(d_items) == 1 else xbmcgui.Dialog().select(ADDON.getLocalizedString(32236), d_items, useDetails=True) if idx == -1: return # User exited the dialog so return nothing is_folder = False if folder[idx].get('filetype') == 'file' else True return (folder[idx].get('file'), is_folder) # Return the player
def get_person_stats(person): infoproperties = {} infoproperties['numitems.dbid.movies'] = get_num_credits('movie', person) infoproperties['numitems.dbid.tvshows'] = get_num_credits('tvshow', person) infoproperties['numitems.dbid.episodes'] = get_num_credits('episode', person) infoproperties['numitems.dbid.total'] = ( try_int(infoproperties.get('numitems.dbid.movies')) + try_int(infoproperties.get('numitems.dbid.tvshows')) + try_int(infoproperties.get('numitems.dbid.episodes'))) return infoproperties
def set_episode_label(self, format_label=u'{season}x{episode:0>2}. {label}'): season = try_int(self.infolabels.get('season', 0)) episode = try_int(self.infolabels.get('episode', 0)) if not season or not episode: return self.label = format_label.format(season=season, episode=episode, label=self.infolabels.get( 'title', ''))
def get_detailed_item(tmdb_type, tmdb_id, season=None, episode=None, details=None): details = details or get_item_details(tmdb_type, tmdb_id, season, episode) if not details: return None item = defaultdict(lambda: '+') item['id'] = item['tmdb'] = tmdb_id item['imdb'] = details.unique_ids.get('imdb') item['tvdb'] = details.unique_ids.get('tvdb') item['trakt'] = details.unique_ids.get('trakt') item['slug'] = details.unique_ids.get('slug') item['season'] = season item['episode'] = episode item['originaltitle'] = details.infolabels.get('originaltitle') item['title'] = details.infolabels.get( 'tvshowtitle') or details.infolabels.get('title') item['showname'] = item['clearname'] = item['tvshowtitle'] = item.get( 'title') item['year'] = details.infolabels.get('year') item['name'] = u'{} ({})'.format(item.get('title'), item.get('year')) item['premiered'] = item['firstaired'] = item[ 'released'] = details.infolabels.get('premiered') item['plot'] = details.infolabels.get('plot') item['cast'] = item['actors'] = " / ".join( [i.get('name') for i in details.cast if i.get('name')]) item['thumbnail'] = details.art.get('thumb') item['poster'] = details.art.get('poster') item['fanart'] = details.art.get('fanart') item['now'] = get_datetime_now().strftime('%Y%m%d%H%M%S%f') if tmdb_type == 'tv' and season is not None and episode is not None: item['id'] = item['epid'] = item['eptvdb'] = item.get('tvdb') item['title'] = details.infolabels.get('title') # Set Episode Title item['name'] = u'{0} S{1:02d}E{2:02d}'.format(item.get('showname'), try_int(season), try_int(episode)) item['season'] = season item['episode'] = episode item['showpremiered'] = details.infoproperties.get('tvshow.premiered') item['showyear'] = details.infoproperties.get('tvshow.year') item['eptmdb'] = details.unique_ids.get('tmdb') item['epimdb'] = details.unique_ids.get('imdb') item['eptrakt'] = details.unique_ids.get('trakt') item['epslug'] = details.unique_ids.get('slug') item['tmdb'] = details.unique_ids.get('tvshow.tmdb') item['imdb'] = details.unique_ids.get('tvshow.imdb') item['tvdb'] = details.unique_ids.get('tvshow.tvdb') item['trakt'] = details.unique_ids.get('tvshow.trakt') item['slug'] = details.unique_ids.get('tvshow.slug') return _url_encode_item(item)
def sync_trakt_item(trakt_type, unique_id, season=None, episode=None, id_type=None): menu = _Menu(items=_menu_items(), trakt_type=trakt_type, unique_id=unique_id, id_type=id_type, season=try_int(season, fallback=None), episode=try_int(episode, fallback=None)) menu.select()
def _get_best_artwork(self, ftv_id, ftv_type, artwork_type): artwork = self.get_artwork_type(ftv_id, ftv_type, artwork_type) best_like = -1 best_item = None for i in artwork: if i.get('lang', '') == self.language: return i.get('url', '') if (i.get('lang', '') == 'en' or not i.get('lang')) and try_int( i.get('likes', 0)) > try_int(best_like): best_item = i.get('url', '') best_like = i.get('likes', 0) return best_item
def set_playcount(self, playcount): playcount = try_int(playcount) if not try_int(self.infolabels.get('episode')): return ip, il = self.infoproperties, self.infolabels ip['watchedepisodes'] = playcount ip['totalepisodes'] = try_int(il.get('episode')) ip['unwatchedepisodes'] = ip.get('totalepisodes') - try_int(ip.get('watchedepisodes')) if not playcount or ip.get('unwatchedepisodes'): return il['playcount'] = playcount il['overlay'] = 5
def _add_episode(self, episode, season, folder): number = episode.get('episode_number') filename = validify_filename(u'S{:02d}E{:02d} - {}'.format( try_int(season), try_int(number), episode.get('name'))) self.tv._cache.my_history['episodes'].append(filename) # Skip episodes we added in the past if self._log._add('tv', self.tv.tmdb_id, self.tv._cache.is_added_episode(filename), season=season, episode=number): return # Skip future episodes if self.hide_unaired and is_future_timestamp(episode.get('air_date'), "%Y-%m-%d", 10): self.tv._cache.my_history['skipped'].append(filename) self._log._add('tv', self.tv.tmdb_id, 'unaired episode', season=season, episode=number, air_date=episode.get('air_date')) return # Check if item has already been added file = self.tv.get_episode_db_info(season, number, info='file') if file: self._log._add('tv', self.tv.tmdb_id, 'found in library', season=season, episode=number, path=file) return # Add our strm file file = create_file(STRM_EPISODE.format(self.tv.tmdb_id, season, number), filename, self.tv.name, folder, basedir=BASEDIR_TV) self._log._add('tv', self.tv.tmdb_id, 'added strm file', season=season, episode=number, path=file)
def list_trakt_calendar(self, info, startdate, days, page=None, library=False, **kwargs): kodi_db = get_kodi_library('tv') if library else None items = self.trakt_api.get_calendar_episodes_list( try_int(startdate), try_int(days), kodi_db=kodi_db, user=False if library else True, page=page) self.kodi_db = kodi_db or self.get_kodi_database('tv') self.tmdb_cache_only = False self.library = 'video' self.container_content = 'episodes' self.plugin_category = get_calendar_name(startdate=try_int(startdate), days=try_int(days)) return items
def refresh_token(self): # Check we haven't attempted too many refresh attempts refresh_attempts = try_int(get_property('TraktRefreshAttempts')) + 1 if refresh_attempts > 5: kodi_log( 'Trakt Unauthorised!\nExceeded refresh_token attempt limit\nSuppressing retries for 10 minutes', 1) get_property('TraktRefreshTimeStamp', set_timestamp(600)) get_property('TraktRefreshAttempts', 0) # Reset refresh attempts return get_property('TraktRefreshAttempts', refresh_attempts) kodi_log('Attempting to refresh Trakt token', 2) if not self.authorization or not self.authorization.get( 'refresh_token'): kodi_log('Trakt refresh token not found!', 1) return postdata = { 'refresh_token': self.authorization.get('refresh_token'), 'client_id': self.client_id, 'client_secret': self.client_secret, 'redirect_uri': 'urn:ietf:wg:oauth:2.0:oob', 'grant_type': 'refresh_token' } self.authorization = self.get_api_request_json( 'https://api.trakt.tv/oauth/token', postdata=postdata) if not self.authorization or not self.authorization.get( 'access_token'): kodi_log('Failed to refresh Trakt token!', 2) return self.on_authenticated(auth_dialog=False) kodi_log('Trakt token refreshed', 1) return self.authorization
def _is_updating(container_id): is_updating = xbmc.getCondVisibility( "Container({}).IsUpdating".format(container_id)) is_numitems = try_int( xbmc.getInfoLabel("Container({}).NumItems".format(container_id))) if is_updating or not is_numitems: return True
def get_custom_list(self, list_slug, user_slug=None, page=1, limit=20, params=None, authorize=False, sort_by=None, sort_how=None, extended=None): if authorize and not self.authorize(): return path = 'users/{}/lists/{}/items'.format(user_slug or 'me', list_slug) # Refresh cache on first page for user list because it might've changed cache_refresh = True if try_int(page, fallback=1) == 1 else False sorted_items = self.get_sorted_list( path, sort_by, sort_how, extended, permitted_types=['movie', 'show', 'person'], cache_refresh=cache_refresh) or {} paginated_items = PaginatedItems(items=sorted_items.get('items', []), page=page, limit=limit) return { 'items': paginated_items.items, 'movies': sorted_items.get('movies', []), 'shows': sorted_items.get('shows', []), 'persons': sorted_items.get('persons', []), 'next_page': paginated_items.next_page }
def get_episodes_watchcount( self, unique_id, id_type, season=None, exclude_specials=True, tvshow=None, count_progress=False): """ Get the number of episodes watched in a show or season Pass tvshow dict directly for speed otherwise will look-up ID from watched sync list Use count_progress to check progress against reset_at value rather than just count watched """ season = try_int(season) if season is not None else None if not tvshow and id_type and unique_id: tvshow = self.get_sync('watched', 'show', id_type).get(unique_id) if not tvshow: return reset_at = None if count_progress and tvshow.get('reset_at'): reset_at = convert_timestamp(tvshow['reset_at']) count = 0 for i in tvshow.get('seasons', []): if season is not None and i.get('number', -1) != season: continue if exclude_specials and i.get('number') == 0: continue # Reset_at is None so just count length of watched episode list if not reset_at: count += len(i.get('episodes', [])) continue # Reset_at has a value so check progress rather than just watched count for j in i.get('episodes', []): if convert_timestamp(j.get('last_watched_at')) >= reset_at: continue count += 1 return count
def _get_calendar_episode_item(self, i): air_date = convert_timestamp(i.get('first_aired'), utc_convert=True) item = get_empty_item() item['label'] = i.get('episode', {}).get('title') item['infolabels'] = { 'mediatype': 'episode', 'premiered': air_date.strftime('%Y-%m-%d'), 'year': air_date.strftime('%Y'), 'title': item['label'], 'episode': i.get('episode', {}).get('number'), 'season': i.get('episode', {}).get('season'), 'tvshowtitle': i.get('show', {}).get('title'), 'duration': try_int(i.get('episode', {}).get('runtime', 0)) * 60, 'plot': i.get('episode', {}).get('overview'), 'mpaa': i.get('show', {}).get('certification')} item['infoproperties'] = { 'air_date': get_region_date(air_date, 'datelong'), 'air_time': get_region_date(air_date, 'time'), 'air_day': air_date.strftime('%A'), 'air_day_short': air_date.strftime('%a'), 'air_date_short': air_date.strftime('%d %b')} item['unique_ids'] = {u'tvshow.{}'.format(k): v for k, v in viewitems(i.get('show', {}).get('ids', {}))} item['params'] = { 'info': 'details', 'tmdb_type': 'tv', 'tmdb_id': i.get('show', {}).get('ids', {}).get('tmdb'), 'episode': i.get('episode', {}).get('number'), 'season': i.get('episode', {}).get('season')} return item
def get_property(name, set_property=None, clear_property=False, window_id=None, prefix=None, is_type=None): if prefix != -1: prefix = prefix or 'TMDbHelper' name = '{}.{}'.format(prefix, name) if window_id == 'current': window = xbmcgui.Window(xbmcgui.getCurrentWindowId()) elif window_id: window = xbmcgui.Window(window_id) else: window = xbmcgui.Window(10000) if clear_property: window.clearProperty(name) return elif set_property is not None: window.setProperty(name, u'{}'.format(set_property)) return set_property if is_type == int: return try_int(window.getProperty(name)) if is_type == float: return try_float(window.getProperty(name)) return window.getProperty(name)
def list_userdiscover(self, tmdb_type, **kwargs): method = kwargs.get('method') # Method routing if not method or method == 'clear': _clear_properties() elif method == 'save': _save_rules(tmdb_type) elif method == 'edit': _edit_rules(idx=try_int(kwargs.get('idx'), fallback=-1)) else: _add_rule(tmdb_type, method) # Build directory items basedir_items = [] basedir_items += _get_basedir_top(tmdb_type) basedir_items += _get_basedir_add(tmdb_type) basedir_items += _get_basedir_end(tmdb_type) self.update_listing = True if method and method != 'edit' else False self.container_content = 'files' items = [_get_formatted_item(i) for i in basedir_items] items[0]['params'] = _get_discover_params(tmdb_type) return items
def play(self, folder_path=None, reset_focus=None, handle=None): # Get some info about current container for container update hack if not folder_path: folder_path = xbmc.getInfoLabel("Container.FolderPath") if not reset_focus and folder_path: containerid = xbmc.getInfoLabel("System.CurrentControlID") current_pos = xbmc.getInfoLabel("Container({}).CurrentItem".format(containerid)) reset_focus = 'SetFocus({},{},absolute)'.format(containerid, try_int(current_pos) - 1) # Get the resolved path listitem = self.get_resolved_path() # Reset folder hack self._update_listing_hack(folder_path=folder_path, reset_focus=reset_focus) # Check we have an actual path to open if not listitem.getPath() or listitem.getPath() == PLUGINPATH: return action = self.configure_action(listitem, handle) # Kodi launches busy dialog on home screen that needs to be told to close # Otherwise the busy dialog will prevent window activation for folder path xbmc.executebuiltin('Dialog.Close(busydialog)') # If a folder we need to resolve to dummy and then open folder if listitem.getProperty('is_folder') == 'true': if self.is_strm or not ADDON.getSettingBool('only_resolve_strm'): resolve_to_dummy(handle, self.dummy_duration, self.dummy_delay) xbmc.executebuiltin(action) kodi_log(['lib.player - finished executing action\n', action], 1) return # Set our playerstring for player monitor to update kodi watched status if self.playerstring: get_property('PlayerInfoString', set_property=self.playerstring) # If PlayMedia method chosen re-route to Player() unless expert settings on if action: if self.is_strm or not ADDON.getSettingBool('only_resolve_strm'): resolve_to_dummy(handle, self.dummy_duration, self.dummy_delay) # If we're calling external we need to resolve to dummy xbmc.Player().play(action, listitem) if self.force_xbmcplayer else xbmc.executebuiltin(u'PlayMedia({})'.format(action)) kodi_log([ 'lib.player - playing path with {}\n'.format('xbmc.Player()' if self.force_xbmcplayer else 'PlayMedia'), listitem.getPath()], 1) return # Otherwise we have a url we can resolve to xbmcplugin.setResolvedUrl(handle, True, listitem) kodi_log(['lib.player - finished resolving path to url\n', listitem.getPath()], 1) # Re-send local files to player due to "bug" (or maybe "feature") of setResolvedUrl # Because setResolvedURL doesn't set id/type (sets None, "unknown" instead) to player for plugins # If id/type not set to Player.GetItem things like Trakt don't work correctly. # Looking for better solution than this hack. if ADDON.getSettingBool('trakt_localhack') and listitem.getProperty('is_local') == 'true': xbmc.Player().play(listitem.getPath(), listitem) if self.force_xbmcplayer else xbmc.executebuiltin(u'PlayMedia({})'.format(listitem.getPath())) kodi_log([ 'Finished executing {}\n'.format('xbmc.Player()' if self.force_xbmcplayer else 'PlayMedia'), listitem.getPath()], 1)
def run(self): self.xbmc_monitor.waitForAbort( 600) # Wait 10 minutes before doing updates to give boot time if self.xbmc_monitor.abortRequested(): del self.xbmc_monitor return self.next_time = datetime.datetime.combine( datetime.datetime.today(), datetime.time(try_int(self.update_hour))) # Get today at hour self.last_time = xbmc.getInfoLabel( 'Skin.String(TMDbHelper.AutoUpdate.LastTime)') # Get last update self.last_time = convert_timestamp( self.last_time) if self.last_time else None if self.last_time and self.last_time > self.next_time: self.next_time += datetime.timedelta( hours=24) # Already updated today so set for tomorrow while not self.xbmc_monitor.abortRequested( ) and not self.exit and self.poll_time: if ADDON.getSettingBool('library_autoupdate'): if datetime.datetime.now( ) > self.next_time: # Scheduled time has past so lets update xbmc.executebuiltin( 'RunScript(plugin.video.themoviedb.helper,library_autoupdate)' ) xbmc.executebuiltin( 'Skin.SetString(TMDbHelper.AutoUpdate.LastTime,{})'. format(datetime.datetime.now().strftime( "%Y-%m-%dT%H:%M:%S"))) self.next_time += datetime.timedelta( hours=24) # Set next update for tomorrow self.xbmc_monitor.waitForAbort(self.poll_time) del self.xbmc_monitor
def add_items(self, items=None, pagination=True, parent_params=None, property_params=None, kodi_db=None, tmdb_cache_only=True): if not items: return check_is_aired = parent_params.get('info') not in NO_LABEL_FORMATTING for i in items: if not pagination and 'next_page' in i: continue if self.item_is_excluded(i): continue li = ListItem(parent_params=parent_params, **i) li.set_details(details=self.get_tmdb_details(li, cache_only=tmdb_cache_only)) # Quick because only get cached li.set_episode_label() if check_is_aired and li.is_unaired(): continue li.set_details(details=self.get_ftv_artwork(li), reverse=True) # Slow when not cache only li.set_details(details=self.get_kodi_details(li), reverse=True) # Quick because local db li.set_playcount(playcount=self.get_playcount_from_trakt(li)) # Quick because of agressive caching of Trakt object and pre-emptive dict comprehension if self.hide_watched and try_int(li.infolabels.get('playcount')) != 0: continue li.set_context_menu() # Set the context menu items li.set_uids_to_info() # Add unique ids to properties so accessible in skins li.set_params_reroute(self.ftv_forced_lookup, self.flatten_seasons) # Reroute details to proper end point li.set_params_to_info(self.plugin_category) # Set path params to properties for use in skins li.infoproperties.update(property_params or {}) xbmcplugin.addDirectoryItem( handle=self.handle, url=li.get_url(), listitem=li.get_listitem(), isFolder=li.is_folder)