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
Esempio n. 3
0
    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