# !/usr/bin/env python #-*- coding:utf-8 -*- #author:doganaydin #project:themoviedb #repository:http://github.com/doganaydin/themoviedb #license: LGPLv3 http://www.gnu.org/licenses/lgpl.html """An interface to the themoviedb.org API""" __author__ = "doganaydin" __version__ = "1.0b" import os os.sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)))) try: import simplejson except: import json as simplejson import fuzzywuzzy.fuzz import requests ### from functions import log ### config = {} def configure(api_key, language='en'): config['apikey'] = api_key config['language'] = language config['urls'] = {} config['urls'][ 'movie.search'] = "http://api.themoviedb.org/3/search/movie?query=%%s&year=%%s&api_key=%(apikey)s&page=%%s" % ( config) config['urls']['movie.info'] = "http://api.themoviedb.org/3/movie/%%s?api_key=%(apikey)s" % (config) config['urls'][ 'people.search'] = "http://api.themoviedb.org/3/search/person?query=%%s&api_key=%(apikey)s&page=%%s" % (config) config['urls']['collection.info'] = "http://api.themoviedb.org/3/collection/%%s&api_key=%(apikey)s" % (config) config['urls'][ 'movie.alternativetitles'] = "http://api.themoviedb.org/3/movie/%%s/alternative_titles?api_key=%(apikey)s" % ( config) config['urls']['movie.casts'] = "http://api.themoviedb.org/3/movie/%%s/casts?api_key=%(apikey)s" % (config) config['urls']['movie.images'] = "http://api.themoviedb.org/3/movie/%%s/images?api_key=%(apikey)s" % (config) config['urls']['movie.keywords'] = "http://api.themoviedb.org/3/movie/%%s/keywords?api_key=%(apikey)s" % (config) config['urls']['movie.releases'] = "http://api.themoviedb.org/3/movie/%%s/releases?api_key=%(apikey)s" % (config) config['urls']['movie.trailers'] = "http://api.themoviedb.org/3/movie/%%s/trailers?api_key=%(apikey)s" % (config) config['urls']['movie.translations'] = "http://api.themoviedb.org/3/movie/%%s/translations?api_key=%(apikey)s" % ( config) config['urls'][ 'person.info'] = "http://api.themoviedb.org/3/person/%%s?api_key=%(apikey)s&append_to_response=images,credits" % ( config) config['urls']['latestmovie'] = "http://api.themoviedb.org/3/latest/movie?api_key=%(apikey)s" % (config) config['urls']['config'] = "http://api.themoviedb.org/3/configuration?api_key=%(apikey)s" % (config) config['urls']['request.token'] = "http://api.themoviedb.org/3/authentication/token/new?api_key=%(apikey)s" % ( config) config['urls'][ 'session.id'] = "http://api.themoviedb.org/3/authentication/session/new?api_key=%(apikey)s&request_token=%%s" % ( config) config['urls'][ 'movie.add.rating'] = "http://api.themoviedb.org/3/movie/%%s/rating?session_id=%%s&api_key=%(apikey)s" % ( config) config['api'] = {} config['api']['backdrop.sizes'] = "" config['api']['base.url'] = "" config['api']['poster.sizes'] = "" config['api']['profile.sizes'] = "" config['api']['session.id'] = "" class Core(object): def getJSON(self, url, language=None): language = language or config['language'] page = requests.get(url, params={'language': language}).content try: return simplejson.loads(page) except: try: return simplejson.loads(page.decode('utf-8')) except: return def escape(self, text): if len(text) > 0: try: return requests.utils.quote(text) except: return requests.utils.quote(text.encode('utf-8')) return False def update_configuration(self): c = self.getJSON(config['urls']['config']) try: config['api']['backdrop.sizes'] = c['images']['backdrop_sizes'] config['api']['base.url'] = c['images']['base_url'] config['api']['poster.sizes'] = c['images']['poster_sizes'] config['api']['profile.sizes'] = c['images']['profile_sizes'] return "ok" except: return 'not ok' def backdrop_sizes(self, img_size): size_list = {'s': 'w300', 'm': 'w780', 'l': 'w1280', 'o': 'original'} return size_list[img_size] def poster_sizes(self, img_size): size_list = {'s': 'w92', 'm': 'w185', 'l': 'w500', 'o': 'original'} return size_list[img_size] def profile_sizes(self, img_size): size_list = {'s': 'w45', 'm': '185', 'l': 'w632', 'o': 'original'} return size_list[img_size] def request_token(self): req = self.getJSON(config['urls']['request.token']) r = req["request_token"] return {"url": "http://themoviedb.org/authenticate/%s" % r, "request_token": r} def session_id(self, token): sess = self.getJSON(config['urls']['session.id'] % token) config['api']['session.id'] = sess["session_id"] return sess["session_id"] class Movies(Core): def __init__(self, title="", year="", limit=True, language=None): self.limit = limit self.update_configuration() self.searched = title title = self.escape(title) self.movies = self.getJSON(config['urls']['movie.search'] % (title, str(year), str(1)), language=language) #pages = self.movies.get('total_pages') #if not self.limit and pages: # if int(pages) > 1: # # for i in range(2,int(pages)+1): # Thanks @tBuLi # self.movies["results"].extend(self.getJSON(config['urls']['movie.search'] % (title,str(i)), language=language)["results"]) def __iter__(self): if self.movies.get('results'): for i in self.movies["results"]: yield Movie(i["id"]) def get_total_results(self): if self.limit: return len(self.movies["results"]) return self.movies["total_results"] def iter_results(self): if 'results' in self.movies.keys(): res = self.movies["results"] else: log('self.movies: %s' % (repr(self.movies))) res = [] for i in res: yield i def get_ordered_matches(self): """ Return a list of tuples. Each tuples first element is a percentage similarity between the search term and the tuples second element 'title' value. Ordered, descending, by the percentage similarity. """ our_results = [] for movie in self.iter_results(): ratio = fuzzywuzzy.fuzz.ratio(self.searched, movie['title']) our_results.append((ratio, movie)) return sorted(our_results, reverse=True) def get_best_match(self): """ Returns a tuple whose first element is the percent similarity between the search term and the tuple's second element's 'title' value. The result is the best-matching result from all the results we get from TMDb. """ for show in Data: itemIndex = itemIndex + 1 Shref = show['link'] Syear = show['year'][0] Stitle = show['title'] rate = scoreMediaTitleMatch(title, ruTitle, year, Stitle.encode('utf-8'), Syear, itemIndex) shows.append({'rate': rate, 'href': Shref, 'title': Stitle, 'year': Syear}) shows = sorted(shows, key=lambda x: x['rate'], reverse=True) #print str(shows) if shows: return shows[0] try: return self.get_ordered_matches()[0] except IndexError: return class Movie(Core): def __init__(self, movie_id, language=None): self.movie_id = movie_id self.update_configuration() self.movies = self.getJSON(config['urls']['movie.info'] % self.movie_id, language=language) self.casts = self.getJSON(config['urls']['movie.casts'] % self.movie_id, language=language) def is_adult(self): return self.movies['adult'] def get_collection_id(self): return self.movies['belongs_to_collection']["id"] def get_collection_name(self): return self.movies['belongs_to_collection']["name"] # Sizes = s->w300 m->w780 l->w1280 o->original(default) def get_collection_backdrop(self, img_size="o"): try: img_path = self.movies["belongs_to_collection"]["backdrop_path"] except KeyError: return return config['api']['base.url'] + self.poster_sizes(img_size) + img_path # Sizes = s->w92 m->w185 l->w500 o->original(default) def get_collection_poster(self, img_size="o"): try: img_path = self.movies["belongs_to_collection"]["poster_path"] except KeyError: return return config['api']['base.url'] + self.poster_sizes(img_size) + img_path def get_budget(self): return self.movies['budget'] def get_genres(self): genres = [] for i in self.movies['genres']: genres.append({"id": i["id"], "name": i["name"]}) return genres def get_homepage(self): return self.movies['homepage'] def get_imdb_id(self): return self.movies['imdb_id'] def get_overview(self): return self.movies['overview'] def get_production_companies(self): companies = [] for i in self.movies['production_companies']: companies.append({"id": i["id"], "name": i["name"]}) return companies def get_productions_countries(self): countries = [] for i in self.movies['production_countries']: countries.append({"iso_3166_1": i["iso_3166_1"], "name": i["name"]}) return countries def get_revenue(self): return self.movies['revenue'] def get_runtime(self): return self.movies['runtime'] def get_spoken_languages(self): langs = [] for i in self.movies['spoken_languages']: langs.append({"iso_639_1": i["iso_639_1"], "name": i["name"]}) return langs def get_tagline(self): return self.movies['tagline'] def get_vote_average(self): return self.movies['vote_average'] def get_vote_count(self): return self.movies['vote_count'] def get_id(self): return self.movie_id # Sizes = s->w300 m->w780 l->w1280 o->original(default) def get_backdrop(self, img_size="o"): img_path = self.movies.get("backdrop_path") if not img_path: return return config['api']['base.url'] + self.backdrop_sizes(img_size) + img_path def get_original_title(self): return self.movies["original_title"] def get_popularity(self): return self.movies["popularity"] def get_release_date(self): return self.movies["release_date"] def get_title(self): return self.movies["title"] # Sizes = s->w92 m->w185 l->w500 o->original(default) def get_poster(self, img_size="o"): img_path = self.movies.get("poster_path") if not img_path: return return config['api']['base.url'] + self.poster_sizes(img_size) + img_path def get_trailers(self, language=None): return self.getJSON(config['urls']['movie.trailers'] % self.movie_id, language=language) def add_rating(self, value): if isinstance(value, float) or isinstance(value, int): if config["api"]["session.id"] == "": return "PROBLEM_AUTH" sess_id = config["api"]["session.id"] data = {"value": float(value)} req = requests.post(config['urls']['movie.add.rating'] % (self.movie_id, sess_id), data=data) res = simplejson.loads(bytes(req.content).decode()) if res['status_message'] == "Success": return True else: return False return "ERROR" class People(Core): def __init__(self, people_name, limit=False, language=None): self.limit = limit self.update_configuration() people_name = self.escape(people_name) self.people = self.getJSON(config['urls']['people.search'] % (people_name, str(1)), language=language) pages = self.people["total_pages"] if not self.limit: if int(pages) > 1: for i in range(2, int(pages) + 1): self.people["results"].extend( self.getJSON(config['urls']['people.search'] % (people_name, str(i)), language=language)[ "results"]) def __iter__(self): for i in self.people["results"]: yield Person(i["id"]) def total_results(self): return self.people["total_results"] def get_total_results(self): if self.limit: return len(self.movies["results"]) return self.movies["total_results"] def iter_results(self): for i in self.people["results"]: yield i class Person(Core): def __init__(self, person_id, language=None): self.person_id = person_id self.update_configuration() self.person = self.getJSON(config['urls']['person.info'] % self.person_id, language=language) def get_id(self): return self.person_id def is_adult(self): return self.person["adult"] def get_name(self): return self.person["name"] # Sizes = s->w45 m->w185 l->w632 o->original(default) def get_profile_image(self, img_size="o"): img_path = self.person.get("profile_path") if not img_path: return return config['api']['base.url'] + self.profile_sizes(img_size) + img_path def get_biography(self): return self.person['biography'] def get_birthday(self): return self.person['birthday'] def get_deathday(self): return self.person['deathday'] def get_place_of_birth(self): return self.person['place_of_birth'] def get_homepage(self): return self.person['homepage'] def get_also_known_as(self): return self.person['also_known_as'] def get_image_aspect_ratio(self, image_index=0): return self.person["images"]['profiles'][image_index]['aspect_ratio'] def get_image_height(self, image_index=0): return self.person["images"]['profiles'][image_index]['height'] def get_image_width(self, image_index=0): return self.person["images"]['profiles'][image_index]['width'] def get_image_iso_639_1(self, image_index=0): return self.person["images"]['profiles'][image_index]['iso_639_1'] #Sizes = s->w92 m->w185 l->w500 o->original(default) def get_image(self, img_size="o", image_index=0): try: img_path = self.person["images"]['profiles'][image_index]['file_path'] except KeyError: return return config['api']['base.url'] + self.poster_sizes(img_size) + img_path def cast(self): for c in self.person["credits"]["cast"]: yield Cast(c) def crew(self): for c in self.person["credits"]["crew"]: yield Crew(c) class Cast: def __init__(self, c): self.cast = c def get_id(self): return self.cast["id"] def get_character(self): return self.cast["character"] def get_original_title(self): return self.cast["original_title"] def get_title(self): return self.cast["title"] def get_release_date(self): return self.cast["release_date"] # Sizes = s->w92 m->w185 l->w500 o->original(default) def get_poster(self, img_size="o", person_index=0): img_path = self.cast.get("poster_path") if not img_path: return return config['api']['base.url'] + Core().poster_sizes(img_size) + img_path class Crew: def __init__(self, c): self.crew = c def get_id(self): return self.crew["id"] def get_department(self): return self.crew["department"] def get_job(self): return self.crew["job"] def get_original_title(self): return self.crew["original_title"] def get_title(self): return self.crew["title"] def get_release_date(self): return self.crew["release_date"] # Sizes = s->w92 m->w185 l->w500 o->original(default) def get_poster(self, img_size="o"): img_path = self.crew.get("poster_path") if not img_path: return return config['api']['base.url'] + Core().poster_sizes(img_size) + img_path