plugin.video.torrenter/resources/scrapers/tmdb.py

473 lines
16 KiB
Python

# !/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
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):
for i in self.movies["results"]:
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