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)
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)