Exemplo n.º 1
0
    def get_tmdb_id(cls, movie):
        # type: (MovieType) -> int
        """

        :param movie:
        :return:
        """
        tmdb_id: Optional[str] = None
        imdb_id = None
        title = movie[Movie.TITLE]
        unique_id = movie.get(Movie.UNIQUE_ID, None)
        if unique_id is not None:
            # if cls._logger.isEnabledFor(LazyLogger.DEBUG_EXTRA_VERBOSE):
            #     for key in unique_id:
            #         cls._logger.debug_extra_verbose(title, key, unique_id.get(key, ''))
            tmdb_id = unique_id.get(Movie.UNIQUE_ID_TMDB, None)
            if tmdb_id is not None:
                # Make sure we don't have a IMDB id in here by error
                if tmdb_id.startswith('tt'):
                    tmdb_id = None
            if tmdb_id is not None:
                tmdb_id: int = int(tmdb_id)
            else:
                imdb_id = unique_id.get(Movie.UNIQUE_ID_IMDB, None)
                if imdb_id is None:
                    imdb_id = unique_id.get(Movie.UNIQUE_ID_UNKNOWN, None)
                    if imdb_id is not None and not imdb_id.startswith('tt'):
                        imdb_id = None
                if imdb_id is not None:
                    data = {}
                    data['external_source'] = 'imdb_id'

                    # TODO: iso-639-1 gives two char lang. Prefer en-US

                    data['language'] = Settings.get_lang_iso_639_1()
                    data['api_key'] = Settings.get_tmdb_api_key()
                    url = 'http://api.themoviedb.org/3/find/' + str(imdb_id)
                    try:
                        Monitor.throw_exception_if_abort_requested()
                        status_code, tmdb_result = JsonUtilsBasic.get_json(
                            url, error_msg=title,
                            params=data, dump_results=True, dump_msg='')

                        Monitor.throw_exception_if_abort_requested()

                        if status_code == 0 and tmdb_result is not None:
                            s_code = tmdb_result.get('status_code', None)
                            if s_code is not None:
                                status_code = s_code
                        if status_code != 0:
                            pass
                        elif tmdb_result is not None:
                            movie_results = tmdb_result.get(
                                'movie_results', [])
                            if len(movie_results) == 0:
                                pass
                            elif len(movie_results) > 1:
                                pass
                            else:
                                tmdb_id = movie_results[0].get('id', None)
                                if tmdb_id is None:
                                    if cls._logger.isEnabledFor(LazyLogger.DEBUG):
                                        cls._logger.debug('Did not find movie for',
                                                          'imdb_id:', imdb_id,
                                                          'title:', title)
                                else:
                                    cls.set_tmdb_id(movie, tmdb_id)
                                    cls.update_database_unique_id(movie)
                    except AbortException:
                        reraise(*sys.exc_info())
                    except Exception:
                        cls._logger.exception('')
        if tmdb_id is not None:
            tmdb_id = int(tmdb_id)
        return tmdb_id
    def __init__(self, title: str, year: Union[str, None],
                 runtime_seconds: int) -> None:
        clz = type(self)
        if clz._logger is None:
            clz._logger = module_logger.getChild(clz.__name__)

        self._title_to_match: str = title
        self._year_to_match: Union[str, None] = year
        self._runtime_seconds_to_match: int = runtime_seconds

        self.candidate_movies: List[clz.CandidateMovie] = []

        data = {
            'api_key': Settings.get_tmdb_api_key(),
            'page': '1',
            'query': title,
            'language': Settings.get_lang_iso_639_1()
        }

        if year is not None:
            data['primary_release_year'] = year

        try:
            include_adult = 'false'

            country_id = Settings.get_country_iso_3166_1().lower()
            certifications = WorldCertifications.get_certifications(country_id)
            adult_certification = certifications.get_certification(
                'dummy', True)
            if certifications.filter(adult_certification):
                include_adult = 'true'
            data['include_adult'] = include_adult
            data['append_to_response'] = 'alternative_titles'

            url = 'https://api.themoviedb.org/3/search/movie'
            status_code, _info_string = \
                JsonUtilsBasic.get_json(url, params=data,
                                        dump_msg='get_tmdb_id_from_title_year',
                                        dump_results=True,
                                        error_msg=title +
                                        f' ({year})')
            if clz._logger.isEnabledFor(LazyLogger.DEBUG_EXTRA_VERBOSE):
                clz._logger.debug_extra_verbose(
                    f'Getting TMDB movie for title: {title} year: {year} '
                    f'runtime: {runtime_seconds}')

            if _info_string is not None:
                results = _info_string.get('results', [])
                if len(results) > 1:
                    if clz._logger.isEnabledFor(
                            LazyLogger.DEBUG_EXTRA_VERBOSE):
                        clz._logger.debug_extra_verbose(
                            f'Got multiple matching movies: {title} '
                            f'year: {year} runtime: {runtime_seconds}')

                # TODO: Improve. Create best trailer function from get_tmdb_trailer
                # TODO: find best trailer_id

                current_language = Settings.get_lang_iso_639_1()

                for movie in results:
                    release_date = movie.get('release_date', '')  # 1932-04-22
                    tmdb_year = release_date[:-6]
                    movie[Movie.YEAR] = tmdb_year
                    tmdb_title = movie.get('title', '')
                    tmdb_id = movie.get('id', None)
                    tmdb_language = movie.get('original_language')
                    runtime_minutes = movie.get(Movie.RUNTIME, 0)
                    runtime_seconds = int(runtime_minutes * 60)

                    titles = movie.get('alternative_titles', {'titles': []})
                    alt_titles = []
                    for title in titles['titles']:
                        alt_title = (title['title'], title['iso_3166_1'])
                        alt_titles.append(alt_title)

                    if clz._logger.isEnabledFor(
                            LazyLogger.DEBUG_EXTRA_VERBOSE):
                        clz._logger.debug_extra_verbose(
                            f'Matching Movie date: {tmdb_year}'
                            f' tmdb_title: {tmdb_title}'
                            f' lang: {tmdb_language}'
                            f' current_lang: {current_language}')

                    self._add(movie, tmdb_title, tmdb_year, tmdb_language,
                              tmdb_id, runtime_seconds)

        except AbortException:
            reraise(*sys.exc_info())

        except Exception as e:
            clz._logger.exception(e)
Exemplo n.º 3
0
    def get_alternate_titles(cls,
                             movie_title,  # type: str
                             movie_id,  # type: Union[int, str]
                             ):
        # type: (...) -> MovieType
        """

        :param cls:
        :param movie_title:
        :param movie_id:
        :return:
        """
        if cls._logger.isEnabledFor(LazyLogger.DEBUG):
            cls._logger.debug('title:', movie_title, 'movie_id:', movie_id)

        data = {}
        # data['append_to_response'] = 'credits,releases'
        data['language'] = Settings.get_lang_iso_639_1()
        data['api_key'] = Settings.get_tmdb_api_key()
        data['append_to_response'] = 'alternative_titles'
        url = 'http://api.themoviedb.org/3/movie/' + str(movie_id)

        tmdb_result = None
        year = 0
        dump_msg = 'movie_id: ' + str(movie_id)
        try:
            Monitor.throw_exception_if_abort_requested()

            status_code, tmdb_result = JsonUtilsBasic.get_json(
                url, error_msg=movie_title,
                params=data, dump_results=False, dump_msg=dump_msg)
            Monitor.throw_exception_if_abort_requested()

            if status_code == 0:
                s_code = tmdb_result.get('status_code', None)
                if s_code is not None:
                    status_code = s_code
            if status_code != 0 and cls._logger.isEnabledFor(LazyLogger.DEBUG):
                cls._logger.debug(
                    'Error getting TMDB data for:', movie_title,
                    'status:', status_code)
                return None
        except AbortException:
            reraise(*sys.exc_info())
        except Exception:
            cls._logger.exception('Error processing movie: ', movie_title)
            return None

        parsed_data = {}
        try:
            # release_date TMDB key is different from Kodi's
            try:
                year = tmdb_result['release_date'][:-6]
                year = int(year)
            except AbortException:
                reraise(*sys.exc_info())
            except Exception:
                year = 0

            parsed_data[Movie.YEAR] = year

            title = tmdb_result[Movie.TITLE]
            if cls._logger.isEnabledFor(LazyLogger.DEBUG):
                cls._logger.debug('Processing:', title, 'type:',
                                  type(title).__name__)
            parsed_data[Movie.TITLE] = title

            studios = tmdb_result['production_companies']
            studio = []
            for s in studios:
                studio.append(s['name'])

            parsed_data[Movie.STUDIO] = studio

            tmdb_cast_members = tmdb_result['credits']['cast']
            cast = []
            for cast_member in tmdb_cast_members:
                fake_cast_entry = {}
                fake_cast_entry['name'] = cast_member['name']
                fake_cast_entry['character'] = cast_member['character']
                cast.append(fake_cast_entry)

            parsed_data[Movie.CAST] = cast

            tmdb_crew_members = tmdb_result['credits']['crew']
            director = []
            writer = []
            for crew_member in tmdb_crew_members:
                if crew_member['job'] == 'Director':
                    director.append(crew_member['name'])
                if crew_member['department'] == 'Writing':
                    writer.append(crew_member['name'])

            parsed_data[Movie.DIRECTOR] = director
            parsed_data[Movie.WRITER] = writer

            titles = tmdb_result.get('alternative_titles', {'titles': []})
            alt_titles = []
            for title in titles['titles']:
                alt_title = (title['title'], title['iso_3166_1'])
                alt_titles.append(alt_title)

            parsed_data['alt_titles'] = alt_titles
            original_title = tmdb_result['original_title']
            if original_title is not None:
                parsed_data[Movie.ORIGINAL_TITLE] = original_title

        except AbortException as e:
            reraise(*sys.exc_info())
        except Exception as e:
            cls._logger.exception('%s %s'.format(
                'Error getting info for movie_id:', movie_id))
            try:
                if cls._logger.isEnabledFor(LazyLogger.DEBUG):
                    json_text = json.dumps(
                        tmdb_result, indent=3, sort_keys=True)
                    cls._logger.debug(json_text)
            except AbortException:
                reraise(*sys.exc_info())
            except Exception as e:
                cls._logger('failed to get Json data')

            parsed_data = None

        cls._logger.exit('Finished processing movie: ', movie_title, 'year:',
                         year)
        return parsed_data
    def _get_tmdb_id_from_title_year(title: str, year: int) -> Optional[int]:
        """
            When we don't have a trailer for a movie, we can
            see if TMDB has one.
        :param title:
        :param year:
        :return:
        """
        year_str = str(year)
        found_movie = None
        trailer_id = None
        data = {}
        data['api_key'] = Settings.get_tmdb_api_key()
        data['page'] = '1'
        data['query'] = title
        data['language'] = Settings.get_lang_iso_639_1()
        data['primary_release_year'] = year

        try:
            include_adult = 'false'

            country_id = Settings.get_country_iso_3166_1().lower()
            certifications = WorldCertifications.get_certifications(country_id)
            adult_certification = certifications.get_certification(
                'dummy', True)
            if certifications.filter(adult_certification):
                include_adult = 'true'
            data['include_adult'] = include_adult

            url = 'https://api.themoviedb.org/3/search/movie'
            status_code, _info_string = \
                JsonUtilsBasic.get_json(url, params=data,
                                        dump_msg='get_tmdb_id_from_title_year',
                                        dump_results=True,
                                        error_msg=title +
                                                  ' (' + year_str + ')')
            if _info_string is not None:
                results = _info_string.get('results', [])
                if len(results) > 1:
                    if TMDBUtils._logger.isEnabledFor(
                            LazyLogger.DEBUG_EXTRA_VERBOSE):
                        TMDBUtils._logger.debug_extra_verbose(
                            'Got multiple matching movies:', title, 'year:',
                            year)

                # TODO: Improve. Create best trailer function from get_tmdb_trailer
                # TODO: find best trailer_id

                matches = []
                current_language = Settings.get_lang_iso_639_1()
                movie = None
                for movie in results:
                    release_date = movie.get('release_date', '')  # 1932-04-22
                    found_year = release_date[:-6]
                    found_title = movie.get('title', '')

                    if (found_title.lower() == title.lower()
                            and found_year == year_str
                            and movie.get('original_language')
                            == current_language):
                        matches.append(movie)

                # TODO: Consider close match heuristics.

                if len(matches) == 1:
                    found_movie = matches[0]
                elif len(matches) > 1:
                    if TMDBUtils._logger.isEnabledFor(
                            LazyLogger.DEBUG_VERBOSE):
                        TMDBUtils._logger.debug_extra_verbose(
                            'More than one matching movie in same year choosing first '
                            'one matching current language.', 'Num choices:',
                            len(matches))
                    found_movie = matches[0]

                if movie is None:
                    if TMDBUtils._logger.isEnabledFor(
                            LazyLogger.DEBUG_EXTRA_VERBOSE):
                        TMDBUtils._logger.debug_extra_verbose(
                            'Could not find movie:', title, 'year:', year,
                            'at TMDB. found', len(results), 'candidates')
                    for a_movie in results:
                        release_date = a_movie.get('release_date',
                                                   '')  # 1932-04-22
                        found_year = release_date[:-6]
                        found_title = a_movie.get('title', '')
                        tmdb_id = a_movie.get('id', None)
                        if TMDBUtils._logger.isEnabledFor(LazyLogger.DISABLED):
                            TMDBUtils._logger.debug_extra_verbose(
                                'found:', found_title, '(', found_year, ')',
                                'tmdb id:', tmdb_id)
                        tmdb_data = MovieEntryUtils.get_alternate_titles(
                            title, tmdb_id)
                        for alt_title, country in tmdb_data['alt_titles']:
                            if alt_title.lower() == title.lower():
                                found_movie = tmdb_data  # Not actually in "movie" format
                                break
            else:
                if TMDBUtils._logger.isEnabledFor(LazyLogger.INFO):
                    TMDBUtils._logger.info('Could not find movie:', title,
                                           'year:', year,
                                           'at TMDB. found no candidates')
        except AbortException:
            reraise(*sys.exc_info())

        except Exception:
            TMDBUtils._logger.exception('')

        tmdb_id = None
        if found_movie is not None:
            tmdb_id = found_movie.get('id', None)
        if tmdb_id is None:
            return None
        return int(tmdb_id)