def __init__(self): self._priority = 90 self._common = OFDBCommon() self._genrenorm = GenreNormalize('ofdb.genre') self._attrs = { 'title', 'original_title', 'plot', 'imdbid', 'vote_count', 'rating', 'directors', 'writers', 'outline', 'year', 'poster', 'countries', 'genre', 'genre_norm', 'actors' }
def __init__(self): self._base_url = 'http://www.omdbapi.com/?{query}&plot=full' self._genrenorm = GenreNormalize('omdb.genre') self._priority = 80 self._attrs = { 'title', 'plot', 'runtime', 'imdbid', 'vote_count', 'rating', 'directors', 'writers', 'year', 'poster', 'genre', 'genre_norm', 'actors', 'original_title' }
def __init__(self): self._config = TMDBConfig.get_instance() self._priority = 100 self._genrenorm = GenreNormalize('tmdb.genre') self._attrs = { 'title', 'original_title', 'plot', 'runtime', 'imdbid', 'vote_count', 'rating', 'providerid', 'alternative_titles', 'directors', 'writers', 'crew', 'year', 'poster', 'fanart', 'countries', 'genre', 'genre_norm', 'collection', 'studios', 'trailers', 'actors', 'keywords', 'tagline' }
class OFDBMovie(provider.IMovieProvider): """ OFDB Movie text metadata provider. Interfaces implemented according to hugin.provider.interfaces. """ def __init__(self): self._priority = 90 self._common = OFDBCommon() self._genrenorm = GenreNormalize('ofdb.genre') self._attrs = { 'title', 'original_title', 'plot', 'imdbid', 'vote_count', 'rating', 'directors', 'writers', 'outline', 'year', 'poster', 'countries', 'genre', 'genre_norm', 'actors' } def build_url(self, search_params): # not enough search params if search_params.title is None and search_params.imdbid is None: return None # try to search by imdbid if available, else use title if search_params.imdbid: path, query = 'imdb2ofdb_json', search_params.imdbid else: path, query = 'search_json', quote_plus(search_params.title) return [self._common.get_base_url().format(path=path, query=query)] def parse_response(self, url_response, search_params): # validate the response data status, retvalue, url, response = self._common.validate_url_response( url_response ) # CHECK IF CRITICAL MATCHES if status in ['retry', 'critical']: return retvalue # validate the response status of the provider status, retv = self._common.check_response_status(response) if status in ['critical', 'unknown', 'no_data']: return retv response_type = response['status']['modul'] response = response['resultat'] if 'search' in response_type: return self._parse_search_module(response, search_params), False if 'imdb2ofdb' in response_type: return self._parse_imdb2ofdb_module(response), False if 'movie' in response_type: return self._parse_movie_module(response), True return None, True def _parse_imdb2ofdb_module(self, response): """ Invoke url build method for movie id found in response. """ return self._common.movieids_to_urllist([response['ofdbid']]) def _parse_search_module(self, response, search_params): """ Parse a search response. Find high prio result. Build urllist.""" # create similarity matrix for title, check agains german and original # title, higher ratio wins similarity_map = [] for response in response['eintrag']: # Get the title with the highest similarity ratio: ratio = 0.0 if '-Serie' not in response['titel_de']: for title_key in ['titel_de', 'titel_orig']: ratio = max( ratio, string_similarity_ratio( response[title_key], search_params.title ) ) similarity_map.append( {'ofdbid': response['id'], 'ratio': ratio} ) # sort by ratio, generate ofdbid list with requestet item count similarity_map.sort( key=lambda value: value['ratio'], reverse=True ) item_count = min(len(similarity_map), search_params.amount) matches = [item['ofdbid'] for item in similarity_map[:item_count]] return self._common.movieids_to_urllist(matches) def _parse_movie_module(self, response): """ Fill in result_dict. """ result_dict = {k: None for k in self._attrs} #str attrs result_dict['title'] = response['titel'] result_dict['original_title'] = response['alternativ'] result_dict['plot'] = response['beschreibung'] result_dict['outline'] = response['kurzbeschreibung'] result_dict['imdbid'] = 'tt{0}'.format(response['imdbid']) result_dict['rating'] = response['bewertung']['note'] # number attrs result_dict['vote_count'] = int(response['bewertung'].get('stimmen') or 0) result_dict['year'] = int(response['jahr'] or 0) # list attrs result_dict['poster'] = [(None, response['bild'])] result_dict['countries'] = response['produktionsland'] result_dict['actors'] = self._extract_person( response['besetzung'], 'actors' ) try: result_dict['directors'] = [r['name'] for r in response['regie']] except: print('invalid value') result_dict['writers'] = self._extract_person( response['drehbuch'], 'directors' ) result_dict['genre'] = response['genre'] result_dict['genre_norm'] = self._genrenorm.normalize_genre_list( result_dict['genre'] ) return result_dict def _extract_person(self, persons, person_type): """ Extract person information from person response part. """ person_list = [] try: for person in persons: role, name = person.get('rolle'), person.get('name') if person_type == 'actors': person_list.append((role, name)) elif person_type == 'directors': person_list.append(name) except (AttributeError, TypeError): return [] return person_list @property def supported_attrs(self): return self._attrs
class TMDBMovie(provider.IMovieProvider, provider.IMoviePictureProvider): def __init__(self): self._config = TMDBConfig.get_instance() self._priority = 100 self._genrenorm = GenreNormalize('tmdb.genre') self._attrs = { 'title', 'original_title', 'plot', 'runtime', 'imdbid', 'vote_count', 'rating', 'providerid', 'alternative_titles', 'directors', 'writers', 'crew', 'year', 'poster', 'fanart', 'countries', 'genre', 'genre_norm', 'collection', 'studios', 'trailers', 'actors', 'keywords', 'tagline' } def build_url(self, search_params): if search_params.imdbid: return self._config.build_movie_urllist( [search_params.imdbid], search_params ).pop() if search_params.title: title = quote_plus(search_params.title) query = '{title}&year={year}&language={language}'.format( title=title, year=search_params.year or '', language=search_params.language or '' ) return [self._config.baseurl.format( path='search/movie', apikey=self._config.apikey, query=query )] def parse_response(self, url_response, search_params): url, response = self._config.validate_url_response(url_response) if response is None or response and 'status_code' in response: return None, True if 'search/movie?' in url and response['total_results'] == 0: return [], True if 'search/movie?' in url: return self._parse_search_module(response, search_params), False if '/movie/' in url: return self._parse_movie_module(response), True return None, True def _parse_search_module(self, result, search_params): similarity_map = [] for result in result['results']: if result is not None: ratio = 0.0 for title_key in ['original_title', 'title']: ratio = max( ratio, string_similarity_ratio( result[title_key], search_params.title ) ) similarity_map.append({'tmdbid': result['id'], 'ratio': ratio}) similarity_map.sort(key=lambda value: value['ratio'], reverse=True) item_count = min(len(similarity_map), search_params.amount) movieids = [item['tmdbid'] for item in similarity_map[:item_count]] return self._config.build_movie_urllist(movieids, search_params) def _parse_movie_module(self, result): result_dict = {key: None for key in self._attrs} # str attrs strattr_keymap = [ 'imdbid:imdb_id', 'plot:overview', 'rating:vote_average', 'title:title', 'original_title:original_title', 'providerid:id', 'tagline:tagline' ] for keymap in strattr_keymap: key_result, key_response = keymap.split(':', maxsplit=1) if result[key_response]: result_dict[key_result] = str(result[key_response]) # list attrs crew = self._config.extract_keyvalue_attrs( result['credits']['crew'], key_a='job', key_b='name' ) result_dict['directors'] = [n for j, n in crew if j == 'Director'] result_dict['writers'] = [n for j, n in crew if j == 'Writer'] result_dict['crew'] = [(j, n) for j, n in crew if j not in ['Director', 'Writer']] result_dict['actors'] = self._config.extract_keyvalue_attrs( result['credits']['cast'], key_a='character', key_b='name' ) result_dict['poster'] = self._config.extract_image_by_type( result, 'posters' ) result_dict['fanart'] = self._config.extract_image_by_type( result, 'backdrops' ) result_dict['trailers'] = self._extract_trailers(result['trailers']) if result['belongs_to_collection']: result_dict['collection'] = [result['belongs_to_collection']['name']] else: result_dict['collection'] = [] result_dict['alternative_titles'] = self._config.extract_keyvalue_attrs( result['alternative_titles']['titles'], 'iso_3166_1', 'title' ) listattr_keymap = [ 'studios:production_companies', 'genre:genres', 'countries:production_countries' ] for keymap in listattr_keymap: key_result, key_response = keymap.split(':', maxsplit=1) result_dict[key_result] = self._config.extract_keyvalue_attrs( result[key_response], 'name' ) result_dict['genre_norm'] = self._genrenorm.normalize_genre_list( result_dict['genre'] ) result_dict['keywords'] = self._config.extract_keyvalue_attrs( result['keywords']['keywords'], 'name' ) # numeric attrs result_dict['year'] = int(result['release_date'][0:4] or 0) or None result_dict['runtime'] = int(result['runtime'] or 0) or None result_dict['vote_count'] = int(result['vote_count'] or 0) or None return result_dict def _extract_trailers(self, response): yt_url = 'http://www.youtube.com/watch\\?v\\={path}' result = [] for path in response['youtube']: trailer_url = (path['size'], yt_url.format(path=path['source'])) result.append(trailer_url) for source in response['quicktime']: for path in source['sources']: trailer_url = (path['size'], path['source']) result.append(trailer_url) return result @property def supported_attrs(self): return self._attrs
class OMDBMovie(provider.IMovieProvider): """ OMDB Person text metadata provider. Interfaces implemented according to hugin.provider.interfaces. """ def __init__(self): self._base_url = 'http://www.omdbapi.com/?{query}&plot=full' self._genrenorm = GenreNormalize('omdb.genre') self._priority = 80 self._attrs = { 'title', 'plot', 'runtime', 'imdbid', 'vote_count', 'rating', 'directors', 'writers', 'year', 'poster', 'genre', 'genre_norm', 'actors', 'original_title' } def build_url(self, search_params): if search_params.imdbid: params = { 'i': search_params.imdbid } return [self._base_url.format(query=urlencode(params))] if search_params.title: params = { 's': quote_plus(search_params.title) or '', 'y': search_params.year or '' } return [self._base_url.format(query=urlencode(params))] def parse_response(self, url_response, search_params): fail_states = ['Incorrect IMDb ID', 'Movie not found!'] try: url, response = url_response.pop() if response is None: return None, False if response: # some json docs from this provider have mysterious newlines. response = response.replace('\n', '') response = json.loads(response) except (TypeError, ValueError) as e: print('Exception in parse_response omdbmovie:', e) return None, True if 'Error' in response and response['Error'] in fail_states: return [], True if 'Search' in response: return self._parse_search_module(response, search_params), False if 'Title' in response: return self._parse_movie_module(response, search_params), True return None, True def _parse_search_module(self, result, search_params): similarity_map = [] for result in result['Search']: if result['Type'] == 'movie' or result['Type'] == 'N/A': ratio = string_similarity_ratio( result['Title'], search_params.title ) similarity_map.append( {'imdbid': result['imdbID'], 'ratio': ratio} ) similarity_map.sort(key=lambda value: value['ratio'], reverse=True) item_count = min(len(similarity_map), search_params.amount) movieids = [item['imdbid'] for item in similarity_map[:item_count]] return self._movieids_to_urllist(movieids) def _movieids_to_urllist(self, movieids): url_list = [] for movieid in movieids: query = 'i={imdb_id}'.format(imdb_id=movieid) url_list.append([self._base_url.format(query=query)]) return url_list def _parse_movie_module(self, result, search_params): result_dict = {k: None for k in self._attrs} #str attrs result_dict['title'] = ''.join(result['Title'].split(',')) result_dict['original_title'] = result_dict.get('title') result_dict['plot'] = ''.join(result['Plot'].split(',')) result_dict['imdbid'] = result.get('imdbID') result_dict['rating'] = result.get('imdbRating') #list attrs result_dict['poster'] = self._parse_poster(result) result_dict['actors'] = self._parse_list_attr(result, 'Actors') result_dict['directors'] = self._parse_list_attr(result, 'Director') result_dict['writers'] = self._parse_list_attr(result, 'Writer') result_dict['genre'] = self._parse_list_attr(result, 'Genre') result_dict['genre_norm'] = self._genrenorm.normalize_genre_list( result_dict['genre'] ) #numeric attrs result_dict['runtime'] = int(self._format_runtime(result['Runtime'])) vote_count = result['imdbVotes'].replace(',', '') if vote_count.isnumeric(): result_dict['vote_count'] = int(vote_count) if result['Year'].isdecimal(): result_dict['year'] = int(result['Year']) return {key: self._filter_na(val) for key, val in result_dict.items()} def _parse_poster(self, response): poster = response.get('Poster') if self._filter_na(poster): return [(None, poster)] def _parse_list_attr(self, response, person_type): persons = response.get(person_type) if self._filter_na(persons): persons = persons.split(',') if person_type == 'Actors': return [(None, person.strip()) for person in persons] return [person.strip() for person in persons] def _filter_na(self, value): if value == 'N/A' or value == ['N/A']: return None return value def _format_runtime(self, runtime): result = 0 time_fmt = {'HM': '{:d} h {:d} min', 'H': '{:d} h', 'M': '{:d} min'} if runtime and 'h' in runtime and 'min' in runtime: h, m = parse(time_fmt['HM'], runtime) result = (h * 60) + m elif 'min' in runtime: result, = parse(time_fmt['M'], runtime) elif 'h' in runtime: result, = parse(time_fmt['H'], runtime) return result @property def supported_attrs(self): return self._attrs