def include_movie(cls, genres: Optional[List[str]] = None, tags: Optional[List[str]] = None) -> bool: if not Settings.get_filter_genres(): return True if genres is None: genres = [] if tags is None: tags = [] allowed_genres = GenreUtils.get_external_genre_ids( GenreUtils.TMDB_DATABASE_STR, exclude=False) allowed_tags = GenreUtils.get_external_keyword_ids( GenreUtils.TMDB_DATABASE_STR, exclude=False) excluded_genres = GenreUtils.get_external_genre_ids( GenreUtils.TMDB_DATABASE_STR, exclude=True) excluded_tags = GenreUtils.get_external_keyword_ids( GenreUtils.TMDB_DATABASE_STR, exclude=True) genre_found = False genre_excluded = False for genre_id in genres: genre_id = str(genre_id) if genre_id in allowed_genres: genre_found = True elif genre_id in excluded_genres: genre_excluded = True tag_found = False tag_excluded = False for tag_id in tags: tag_id = str(tag_id) if tag_id in allowed_tags: tag_found = True elif tag_id in excluded_tags: tag_excluded = True genre_fails = False if genre_found or tag_found: # Include movie pass elif genre_excluded or tag_excluded: genre_fails = True # If user specified any Included genres or tags. Then # Ignored items will have no impact on selection, but # when none are specified, then the movie is selected, # unless Excluded. elif len(allowed_genres) == 0 and len(allowed_tags) == 0: pass else: genre_fails = True return not genre_fails
def include_movie(cls, genres: List[str] = None, tags: List[str] = None) -> bool: if not Settings.get_filter_genres(): return True if genres is None: genres = [] if tags is None: ignore_tags = True tags = [] else: # When tags is None, they haven't been discovered yet for this # movie. Assume that any allowed_tag will be found. ignore_tags = False allowed_genres = GenreUtils.get_external_genre_ids( GenreUtils.TMDB_DATABASE, exclude=False) allowed_tags = GenreUtils.get_external_keyword_ids( GenreUtils.TMDB_DATABASE, exclude=False) excluded_genres = GenreUtils.get_external_genre_ids( GenreUtils.TMDB_DATABASE, exclude=True) excluded_tags = GenreUtils.get_external_keyword_ids( GenreUtils.TMDB_DATABASE, exclude=True) genre_found = False genre_excluded = False for genre_id in genres: genre_id = str(genre_id) if genre_id in allowed_genres: genre_found = True elif genre_id in excluded_genres: genre_excluded = True tag_found = False tag_excluded = False for tag_id in tags: tag_id = str(tag_id) if tag_id in allowed_tags: tag_found = True elif tag_id in excluded_tags: tag_excluded = True genre_passes = True if genre_found or tag_found: # Include movie pass elif genre_excluded or tag_excluded: genre_passes = False # When ignore_tags is set, then tag information has not yet been # discovered, so don't fail due to tags. elif len(allowed_genres) == 0 and ignore_tags: pass # If user specified any Included genres or tags. Then # Ignored items will have no impact on selection, but # when none are specified, then the movie is selected, # unless Excluded. elif len(allowed_genres) == 0 and len(allowed_tags) == 0: pass else: genre_passes = False return genre_passes
def run_worker(self): # type: () -> None """ Initial Discovery of all movies in Kodi. :return: """ # Discovery is done in two parts: # # 1- query DB for every movie in library # 2- Get additional information # # There are three types of trailers for these movies: # # a- Movies with local trailers # b- Movies with trailer URLS (typically youtube links from tmdb) # TMdb will need to be queried for details # c. Movies with no trailer information, requiring a check with tmdb # to see if one exists # # Because of the above, this manager will query the DB for every movie # and then only process the ones with local trailers. The others will # be handed off to their own managers. This is done because of # the way that this application works: # Once enough information to identify a movie that matches # what the user wants, it is added to the pool of movies that # can be randomly selected for playing. Once a movie has been # selected, it is placed into a TrailerFetcherQueue. A # TrailerFetcher then gathers the remaining information so that # it can be played. # # If the lion's share of movies in the pool require significant # extra processing because they don't have local trailers, then # the fetcher can get overwhelmed. clz = DiscoverLibraryMovies self._selected_keywords = [] self._excluded_keywords = [] self._selected_genres = [] self._excluded_genres = [] if Settings.get_filter_genres(): self._selected_genres = GenreUtils.get_internal_kodi_genre_ids( GenreUtils.LOCAL_DATABASE, exclude=False) self._excluded_genres = GenreUtils.get_internal_kodi_genre_ids( GenreUtils.LOCAL_DATABASE, exclude=True) self._selected_keywords = GenreUtils.get_internal_kodi_keyword_ids( GenreUtils.LOCAL_DATABASE, exclude=False) self._excluded_keywords = GenreUtils.get_internal_kodi_keyword_ids( GenreUtils.LOCAL_DATABASE, exclude=True) query = self.create_query( self._selected_genres, self._excluded_genres, self._selected_keywords, self._excluded_keywords) if Monitor.is_abort_requested(): return start_time = datetime.datetime.now() Monitor.throw_exception_if_abort_requested() # Expensive operation query_result = JsonUtilsBasic.get_kodi_json(query, dump_results=False) Monitor.throw_exception_if_abort_requested() elapsed_time = datetime.datetime.now() - start_time if clz.logger.isEnabledFor(LazyLogger.DEBUG_VERBOSE): clz.logger.debug_verbose('Library query seconds:', elapsed_time.total_seconds()) movies_skipped = 0 movies_found = 0 movies_with_local_trailers = 0 movies_with_trailer_urls = 0 movies_without_trailer_info = 0 self.throw_exception_on_forced_to_stop() result = query_result.get('result', {}) del query_result movies = result.get('movies', []) del result DiskUtils.RandomGenerator.shuffle(movies) if self._libraryURLManager is None: self._libraryURLManager = DiscoverLibraryURLTrailerMovies() self._libraryNoTrailerInfoManager = DiscoverLibraryNoTrailerMovies() library_movies = [] library_url_movies = [] library_no_trailer_movies = [] empty_limit = 50 movie_data = None if Settings.is_enable_movie_stats(): movie_data = LibraryMovieStats() country_id = Settings.get_country_iso_3166_1().lower() certifications = WorldCertifications.get_certifications(country_id) unrated_id = certifications.get_unrated_certification().get_preferred_id() for movie in movies: self.throw_exception_on_forced_to_stop() try: #clz.logger.debug('movie:', movie) movies_found += 1 if Settings.get_hide_watched_movies() and Movie.LAST_PLAYED in movie: if (self.get_days_since_last_played(movie[Movie.LAST_PLAYED], movie[Movie.TITLE]) > Settings.get_minimum_days_since_watched()): movies_skipped += 1 if clz.logger.isEnabledFor(LazyLogger.DEBUG_EXTRA_VERBOSE): clz.logger.debug_extra_verbose(movie[Movie.TITLE], 'will not be played due to ' 'Hide', 'Watched Movies') continue # Normalize certification # if clz.logger.isEnabledFor(LazyLogger.DEBUG): # clz.logger.debug('mpaa:', movie[Movie.MPAA], # 'movie:', movie[Movie.TITLE]) if certifications.is_valid(movie.get(Movie.MPAA, '')): movie[Movie.MPAA] = unrated_id certification = certifications.get_certification( movie.get(Movie.MPAA), movie.get(Movie.ADULT)) movie[Movie.ADULT] = movie.get(Movie.ADULT, False) if not isinstance(movie[Movie.ADULT], bool): if clz.logger.isEnabledFor(LazyLogger.DEBUG_VERBOSE): clz.logger.debug_verbose(movie[Movie.TITLE], 'has invalid ADULT field: ', movie[Movie.ADULT]) movie[Movie.ADULT] = str(movie[Movie.ADULT]).lower == 'true' movie[Movie.SOURCE] = Movie.LIBRARY_SOURCE movie.setdefault(Movie.TRAILER, '') movie[Movie.TYPE] = '' if clz.logger.isEnabledFor(LazyLogger.DEBUG_VERBOSE): Debug.validate_basic_movie_properties(movie) if Settings.is_enable_movie_stats(): movie_data.collect_data(movie) # Basic discovery is complete at this point. Now send # all of the movies without any trailer information to # DiscoverLibraryNoTrailerMovies while # those with trailer URLs to DiscoverLibraryURLTrailerMovies if certifications.filter(certification): trailer = movie[Movie.TRAILER] if trailer == '': movies_without_trailer_info += 1 library_no_trailer_movies.append(movie) elif trailer.startswith('plugin://') or trailer.startswith('http'): movies_with_trailer_urls += 1 library_url_movies.append(movie) elif Settings.get_include_library_trailers(): movies_with_local_trailers += 1 library_movies.append(movie) if len(library_movies) >= empty_limit: self.add_to_discovered_trailers(library_movies) del library_movies[:] # Unblock other discovery now that a few movies have been # found. if not self._some_movies_discovered_event.isSet(): self._some_movies_discovered_event.set() if len(library_no_trailer_movies) >= empty_limit: self._libraryNoTrailerInfoManager.add_to_discovered_trailers( library_no_trailer_movies) del library_no_trailer_movies[:] if len(library_url_movies) >= empty_limit: self._libraryURLManager.add_to_discovered_trailers( library_url_movies) del library_no_trailer_movies[:] # Unblock other discovery now that a few movies have been # found. self._some_movies_discovered_event.set() except AbortException: reraise(*sys.exc_info()) except Exception: clz.logger.exception('') try: if len(library_movies) >= 0: self.add_to_discovered_trailers(library_movies) if len(library_no_trailer_movies) >= 0: self._libraryNoTrailerInfoManager.add_to_discovered_trailers( library_no_trailer_movies) if len(library_url_movies) >= 0: self._libraryURLManager.add_to_discovered_trailers( library_url_movies) except AbortException: reraise(*sys.exc_info()) except Exception: clz.logger.exception('') if (clz.logger.isEnabledFor(LazyLogger.DEBUG) and clz.logger.is_trace_enabled(Trace.STATS)): clz.logger.debug('Local movies found in library:', movies_found, trace=Trace.STATS) clz.logger.debug('Local movies filtered out', movies_skipped, trace=Trace.STATS) clz.logger.debug('Movies with local trailers:', movies_with_local_trailers, trace=Trace.STATS) clz.logger.debug('Movies with trailer URLs:', movies_with_trailer_urls, trace=Trace.STATS) clz.logger.debug('Movies with no trailer information:', movies_without_trailer_info, trace=Trace.STATS) if Settings.is_enable_movie_stats(): movie_data.report_data() del movie_data