From 3d6ec1feba621e6af6d762f5469ec9b9a8ada373 Mon Sep 17 00:00:00 2001 From: Ruud Date: Sat, 24 Aug 2013 15:20:00 +0200 Subject: [PATCH] Move info providers to proper folder --- couchpotato/core/providers/info/__init__.py | 0 .../core/providers/info/_modifier/__init__.py | 7 + couchpotato/core/providers/info/_modifier/main.py | 95 +++++++++ couchpotato/core/providers/info/base.py | 5 + .../core/providers/info/couchpotatoapi/__init__.py | 6 + .../core/providers/info/couchpotatoapi/main.py | 98 ++++++++++ .../core/providers/info/omdbapi/__init__.py | 6 + couchpotato/core/providers/info/omdbapi/main.py | 123 ++++++++++++ .../core/providers/info/themoviedb/__init__.py | 24 +++ couchpotato/core/providers/info/themoviedb/main.py | 216 +++++++++++++++++++++ couchpotato/core/providers/movie/__init__.py | 0 .../core/providers/movie/_modifier/__init__.py | 7 - couchpotato/core/providers/movie/_modifier/main.py | 95 --------- couchpotato/core/providers/movie/base.py | 5 - .../providers/movie/couchpotatoapi/__init__.py | 6 - .../core/providers/movie/couchpotatoapi/main.py | 98 ---------- .../core/providers/movie/omdbapi/__init__.py | 6 - couchpotato/core/providers/movie/omdbapi/main.py | 123 ------------ .../core/providers/movie/themoviedb/__init__.py | 24 --- .../core/providers/movie/themoviedb/main.py | 216 --------------------- 20 files changed, 580 insertions(+), 580 deletions(-) create mode 100644 couchpotato/core/providers/info/__init__.py create mode 100644 couchpotato/core/providers/info/_modifier/__init__.py create mode 100644 couchpotato/core/providers/info/_modifier/main.py create mode 100644 couchpotato/core/providers/info/base.py create mode 100644 couchpotato/core/providers/info/couchpotatoapi/__init__.py create mode 100644 couchpotato/core/providers/info/couchpotatoapi/main.py create mode 100644 couchpotato/core/providers/info/omdbapi/__init__.py create mode 100755 couchpotato/core/providers/info/omdbapi/main.py create mode 100644 couchpotato/core/providers/info/themoviedb/__init__.py create mode 100644 couchpotato/core/providers/info/themoviedb/main.py delete mode 100644 couchpotato/core/providers/movie/__init__.py delete mode 100644 couchpotato/core/providers/movie/_modifier/__init__.py delete mode 100644 couchpotato/core/providers/movie/_modifier/main.py delete mode 100644 couchpotato/core/providers/movie/base.py delete mode 100644 couchpotato/core/providers/movie/couchpotatoapi/__init__.py delete mode 100644 couchpotato/core/providers/movie/couchpotatoapi/main.py delete mode 100644 couchpotato/core/providers/movie/omdbapi/__init__.py delete mode 100755 couchpotato/core/providers/movie/omdbapi/main.py delete mode 100644 couchpotato/core/providers/movie/themoviedb/__init__.py delete mode 100644 couchpotato/core/providers/movie/themoviedb/main.py diff --git a/couchpotato/core/providers/info/__init__.py b/couchpotato/core/providers/info/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/couchpotato/core/providers/info/_modifier/__init__.py b/couchpotato/core/providers/info/_modifier/__init__.py new file mode 100644 index 0000000..3bdf5e0 --- /dev/null +++ b/couchpotato/core/providers/info/_modifier/__init__.py @@ -0,0 +1,7 @@ +from .main import MovieResultModifier + +def start(): + + return MovieResultModifier() + +config = [] diff --git a/couchpotato/core/providers/info/_modifier/main.py b/couchpotato/core/providers/info/_modifier/main.py new file mode 100644 index 0000000..835cce0 --- /dev/null +++ b/couchpotato/core/providers/info/_modifier/main.py @@ -0,0 +1,95 @@ +from couchpotato import get_session +from couchpotato.core.event import addEvent, fireEvent +from couchpotato.core.helpers.variable import mergeDicts, randomString +from couchpotato.core.logger import CPLog +from couchpotato.core.plugins.base import Plugin +from couchpotato.core.settings.model import Library +import copy +import traceback + +log = CPLog(__name__) + + +class MovieResultModifier(Plugin): + + default_info = { + 'tmdb_id': 0, + 'titles': [], + 'original_title': '', + 'year': 0, + 'images': { + 'poster': [], + 'backdrop': [], + 'poster_original': [], + 'backdrop_original': [] + }, + 'runtime': 0, + 'plot': '', + 'tagline': '', + 'imdb': '', + 'genres': [], + 'mpaa': None + } + + def __init__(self): + addEvent('result.modify.movie.search', self.combineOnIMDB) + addEvent('result.modify.movie.info', self.checkLibrary) + + def combineOnIMDB(self, results): + + temp = {} + order = [] + + # Combine on imdb id + for item in results: + random_string = randomString() + imdb = item.get('imdb', random_string) + imdb = imdb if imdb else random_string + + if not temp.get(imdb): + temp[imdb] = self.getLibraryTags(imdb) + order.append(imdb) + + # Merge dicts + temp[imdb] = mergeDicts(temp[imdb], item) + + # Make it a list again + temp_list = [temp[x] for x in order] + + return temp_list + + def getLibraryTags(self, imdb): + + temp = { + 'in_wanted': False, + 'in_library': False, + } + + # Add release info from current library + db = get_session() + try: + l = db.query(Library).filter_by(identifier = imdb).first() + if l: + + # Statuses + active_status, done_status = fireEvent('status.get', ['active', 'done'], single = True) + + for movie in l.movies: + if movie.status_id == active_status['id']: + temp['in_wanted'] = fireEvent('movie.get', movie.id, single = True) + + for release in movie.releases: + if release.status_id == done_status['id']: + temp['in_library'] = fireEvent('movie.get', movie.id, single = True) + except: + log.error('Tried getting more info on searched movies: %s', traceback.format_exc()) + + return temp + + def checkLibrary(self, result): + + result = mergeDicts(copy.deepcopy(self.default_info), copy.deepcopy(result)) + + if result and result.get('imdb'): + return mergeDicts(result, self.getLibraryTags(result['imdb'])) + return result diff --git a/couchpotato/core/providers/info/base.py b/couchpotato/core/providers/info/base.py new file mode 100644 index 0000000..1b43ab8 --- /dev/null +++ b/couchpotato/core/providers/info/base.py @@ -0,0 +1,5 @@ +from couchpotato.core.providers.base import Provider + + +class MovieProvider(Provider): + type = 'movie' diff --git a/couchpotato/core/providers/info/couchpotatoapi/__init__.py b/couchpotato/core/providers/info/couchpotatoapi/__init__.py new file mode 100644 index 0000000..37d9eca --- /dev/null +++ b/couchpotato/core/providers/info/couchpotatoapi/__init__.py @@ -0,0 +1,6 @@ +from .main import CouchPotatoApi + +def start(): + return CouchPotatoApi() + +config = [] diff --git a/couchpotato/core/providers/info/couchpotatoapi/main.py b/couchpotato/core/providers/info/couchpotatoapi/main.py new file mode 100644 index 0000000..cdbc513 --- /dev/null +++ b/couchpotato/core/providers/info/couchpotatoapi/main.py @@ -0,0 +1,98 @@ +from couchpotato.core.event import addEvent, fireEvent +from couchpotato.core.helpers.encoding import tryUrlencode +from couchpotato.core.logger import CPLog +from couchpotato.core.providers.info.base import MovieProvider +from couchpotato.environment import Env +import time + +log = CPLog(__name__) + + +class CouchPotatoApi(MovieProvider): + + urls = { + 'search': 'https://api.couchpota.to/search/%s/', + 'info': 'https://api.couchpota.to/info/%s/', + 'is_movie': 'https://api.couchpota.to/ismovie/%s/', + 'eta': 'https://api.couchpota.to/eta/%s/', + 'suggest': 'https://api.couchpota.to/suggest/', + 'updater': 'https://api.couchpota.to/updater/?%s', + 'messages': 'https://api.couchpota.to/messages/?%s', + } + http_time_between_calls = 0 + api_version = 1 + + def __init__(self): + addEvent('movie.info', self.getInfo, priority = 1) + addEvent('movie.search', self.search, priority = 1) + addEvent('movie.release_date', self.getReleaseDate) + addEvent('movie.suggest', self.getSuggestions) + addEvent('movie.is_movie', self.isMovie) + + addEvent('cp.source_url', self.getSourceUrl) + addEvent('cp.messages', self.getMessages) + + def getMessages(self, last_check = 0): + + data = self.getJsonData(self.urls['messages'] % tryUrlencode({ + 'last_check': last_check, + }), headers = self.getRequestHeaders(), cache_timeout = 10) + + return data + + def getSourceUrl(self, repo = None, repo_name = None, branch = None): + return self.getJsonData(self.urls['updater'] % tryUrlencode({ + 'repo': repo, + 'name': repo_name, + 'branch': branch, + }), headers = self.getRequestHeaders()) + + def search(self, q, limit = 5): + return self.getJsonData(self.urls['search'] % tryUrlencode(q) + ('?limit=%s' % limit), headers = self.getRequestHeaders()) + + def isMovie(self, identifier = None): + + if not identifier: + return + + data = self.getJsonData(self.urls['is_movie'] % identifier, headers = self.getRequestHeaders()) + if data: + return data.get('is_movie', True) + + return True + + def getInfo(self, identifier = None): + + if not identifier: + return + + result = self.getJsonData(self.urls['info'] % identifier, headers = self.getRequestHeaders()) + if result: + return dict((k, v) for k, v in result.iteritems() if v) + + return {} + + def getReleaseDate(self, identifier = None): + if identifier is None: return {} + + dates = self.getJsonData(self.urls['eta'] % identifier, headers = self.getRequestHeaders()) + log.debug('Found ETA for %s: %s', (identifier, dates)) + + return dates + + def getSuggestions(self, movies = [], ignore = []): + suggestions = self.getJsonData(self.urls['suggest'], params = { + 'movies': ','.join(movies), + 'ignore': ','.join(ignore), + }, headers = self.getRequestHeaders()) + log.info('Found suggestions for %s movies, %s ignored', (len(movies), len(ignore))) + + return suggestions + + def getRequestHeaders(self): + return { + 'X-CP-Version': fireEvent('app.version', single = True), + 'X-CP-API': self.api_version, + 'X-CP-Time': time.time(), + 'X-CP-Identifier': '+%s' % Env.setting('api_key', 'core')[:10], # Use first 10 as identifier, so we don't need to use IP address in api stats + } diff --git a/couchpotato/core/providers/info/omdbapi/__init__.py b/couchpotato/core/providers/info/omdbapi/__init__.py new file mode 100644 index 0000000..765662e --- /dev/null +++ b/couchpotato/core/providers/info/omdbapi/__init__.py @@ -0,0 +1,6 @@ +from .main import OMDBAPI + +def start(): + return OMDBAPI() + +config = [] diff --git a/couchpotato/core/providers/info/omdbapi/main.py b/couchpotato/core/providers/info/omdbapi/main.py new file mode 100755 index 0000000..2726ef5 --- /dev/null +++ b/couchpotato/core/providers/info/omdbapi/main.py @@ -0,0 +1,123 @@ +from couchpotato.core.event import addEvent, fireEvent +from couchpotato.core.helpers.encoding import tryUrlencode +from couchpotato.core.helpers.variable import tryInt, tryFloat, splitString +from couchpotato.core.logger import CPLog +from couchpotato.core.providers.info.base import MovieProvider +import json +import re +import traceback + +log = CPLog(__name__) + + +class OMDBAPI(MovieProvider): + + urls = { + 'search': 'http://www.omdbapi.com/?%s', + 'info': 'http://www.omdbapi.com/?i=%s', + } + + http_time_between_calls = 0 + + def __init__(self): + addEvent('movie.search', self.search) + addEvent('movie.info', self.getInfo) + + def search(self, q, limit = 12): + + name_year = fireEvent('scanner.name_year', q, single = True) + + if not name_year or (name_year and not name_year.get('name')): + name_year = { + 'name': q + } + + cache_key = 'omdbapi.cache.%s' % q + cached = self.getCache(cache_key, self.urls['search'] % tryUrlencode({'t': name_year.get('name'), 'y': name_year.get('year', '')}), timeout = 3) + + if cached: + result = self.parseMovie(cached) + if result.get('titles') and len(result.get('titles')) > 0: + log.info('Found: %s', result['titles'][0] + ' (' + str(result['year']) + ')') + return [result] + + return [] + + return [] + + def getInfo(self, identifier = None): + + if not identifier: + return {} + + cache_key = 'omdbapi.cache.%s' % identifier + cached = self.getCache(cache_key, self.urls['info'] % identifier, timeout = 3) + + if cached: + result = self.parseMovie(cached) + if result.get('titles') and len(result.get('titles')) > 0: + log.info('Found: %s', result['titles'][0] + ' (' + str(result['year']) + ')') + return result + + return {} + + def parseMovie(self, movie): + + movie_data = {} + try: + + try: + if isinstance(movie, (str, unicode)): + movie = json.loads(movie) + except ValueError: + log.info('No proper json to decode') + return movie_data + + if movie.get('Response') == 'Parse Error' or movie.get('Response') == 'False': + return movie_data + + tmp_movie = movie.copy() + for key in tmp_movie: + if tmp_movie.get(key).lower() == 'n/a': + del movie[key] + + year = tryInt(movie.get('Year', '')) + + movie_data = { + 'via_imdb': True, + 'titles': [movie.get('Title')] if movie.get('Title') else [], + 'original_title': movie.get('Title'), + 'images': { + 'poster': [movie.get('Poster', '')] if movie.get('Poster') and len(movie.get('Poster', '')) > 4 else [], + }, + 'rating': { + 'imdb': (tryFloat(movie.get('imdbRating', 0)), tryInt(movie.get('imdbVotes', '').replace(',', ''))), + #'rotten': (tryFloat(movie.get('tomatoRating', 0)), tryInt(movie.get('tomatoReviews', '').replace(',', ''))), + }, + 'imdb': str(movie.get('imdbID', '')), + 'mpaa': str(movie.get('Rated', '')), + 'runtime': self.runtimeToMinutes(movie.get('Runtime', '')), + 'released': movie.get('Released'), + 'year': year if isinstance(year, (int)) else None, + 'plot': movie.get('Plot'), + 'genres': splitString(movie.get('Genre', '')), + 'directors': splitString(movie.get('Director', '')), + 'writers': splitString(movie.get('Writer', '')), + 'actors': splitString(movie.get('Actors', '')), + } + movie_data = dict((k, v) for k, v in movie_data.iteritems() if v) + except: + log.error('Failed parsing IMDB API json: %s', traceback.format_exc()) + + return movie_data + + def runtimeToMinutes(self, runtime_str): + runtime = 0 + + regex = '(\d*.?\d+).(h|hr|hrs|mins|min)+' + matches = re.findall(regex, runtime_str) + for match in matches: + nr, size = match + runtime += tryInt(nr) * (60 if 'h' is str(size)[0] else 1) + + return runtime diff --git a/couchpotato/core/providers/info/themoviedb/__init__.py b/couchpotato/core/providers/info/themoviedb/__init__.py new file mode 100644 index 0000000..66ac536 --- /dev/null +++ b/couchpotato/core/providers/info/themoviedb/__init__.py @@ -0,0 +1,24 @@ +from .main import TheMovieDb + +def start(): + return TheMovieDb() + +config = [{ + 'name': 'themoviedb', + 'groups': [ + { + 'tab': 'providers', + 'name': 'tmdb', + 'label': 'TheMovieDB', + 'hidden': True, + 'description': 'Used for all calls to TheMovieDB.', + 'options': [ + { + 'name': 'api_key', + 'default': '9b939aee0aaafc12a65bf448e4af9543', + 'label': 'Api Key', + }, + ], + }, + ], +}] diff --git a/couchpotato/core/providers/info/themoviedb/main.py b/couchpotato/core/providers/info/themoviedb/main.py new file mode 100644 index 0000000..e2ff937 --- /dev/null +++ b/couchpotato/core/providers/info/themoviedb/main.py @@ -0,0 +1,216 @@ +from couchpotato.core.event import addEvent +from couchpotato.core.helpers.encoding import simplifyString, toUnicode +from couchpotato.core.logger import CPLog +from couchpotato.core.providers.info.base import MovieProvider +from themoviedb import tmdb +import traceback + +log = CPLog(__name__) + + +class TheMovieDb(MovieProvider): + + def __init__(self): + addEvent('movie.by_hash', self.byHash) + addEvent('movie.search', self.search, priority = 2) + addEvent('movie.info', self.getInfo, priority = 2) + addEvent('movie.info_by_tmdb', self.getInfoByTMDBId) + + # Use base wrapper + tmdb.configure(self.conf('api_key')) + + def byHash(self, file): + ''' Find movie by hash ''' + + if self.isDisabled(): + return False + + cache_key = 'tmdb.cache.%s' % simplifyString(file) + results = self.getCache(cache_key) + + if not results: + log.debug('Searching for movie by hash: %s', file) + try: + raw = tmdb.searchByHashingFile(file) + + results = [] + if raw: + try: + results = self.parseMovie(raw) + log.info('Found: %s', results['titles'][0] + ' (' + str(results.get('year', 0)) + ')') + + self.setCache(cache_key, results) + return results + except SyntaxError, e: + log.error('Failed to parse XML response: %s', e) + return False + except: + log.debug('No movies known by hash for: %s', file) + pass + + return results + + def search(self, q, limit = 12): + ''' Find movie by name ''' + + if self.isDisabled(): + return False + + search_string = simplifyString(q) + cache_key = 'tmdb.cache.%s.%s' % (search_string, limit) + results = self.getCache(cache_key) + + if not results: + log.debug('Searching for movie: %s', q) + + raw = None + try: + raw = tmdb.search(search_string) + except: + log.error('Failed searching TMDB for "%s": %s', (search_string, traceback.format_exc())) + + results = [] + if raw: + try: + nr = 0 + + for movie in raw: + results.append(self.parseMovie(movie)) + + nr += 1 + if nr == limit: + break + + log.info('Found: %s', [result['titles'][0] + ' (' + str(result.get('year', 0)) + ')' for result in results]) + + self.setCache(cache_key, results) + return results + except SyntaxError, e: + log.error('Failed to parse XML response: %s', e) + return False + + return results + + def getInfo(self, identifier = None): + + if not identifier: + return {} + + cache_key = 'tmdb.cache.%s' % identifier + result = self.getCache(cache_key) + + if not result: + result = {} + movie = None + + try: + log.debug('Getting info: %s', cache_key) + movie = tmdb.imdbLookup(id = identifier) + except: + pass + + if movie: + result = self.parseMovie(movie[0]) + self.setCache(cache_key, result) + + return result + + def getInfoByTMDBId(self, id = None): + + cache_key = 'tmdb.cache.%s' % id + result = self.getCache(cache_key) + + if not result: + result = {} + movie = None + + try: + log.debug('Getting info: %s', cache_key) + movie = tmdb.getMovieInfo(id = id) + except: + pass + + if movie: + result = self.parseMovie(movie) + self.setCache(cache_key, result) + + return result + + def parseMovie(self, movie): + + # Images + poster = self.getImage(movie, type = 'poster', size = 'cover') + #backdrop = self.getImage(movie, type = 'backdrop', size = 'w1280') + poster_original = self.getImage(movie, type = 'poster', size = 'original') + backdrop_original = self.getImage(movie, type = 'backdrop', size = 'original') + + # Genres + try: + genres = self.getCategory(movie, 'genre') + except: + genres = [] + + # 1900 is the same as None + year = str(movie.get('released', 'none'))[:4] + if year == '1900' or year.lower() == 'none': + year = None + + movie_data = { + 'via_tmdb': True, + 'tmdb_id': int(movie.get('id', 0)), + 'titles': [toUnicode(movie.get('name'))], + 'original_title': movie.get('original_name'), + 'images': { + 'poster': [poster] if poster else [], + #'backdrop': [backdrop] if backdrop else [], + 'poster_original': [poster_original] if poster_original else [], + 'backdrop_original': [backdrop_original] if backdrop_original else [], + }, + 'imdb': movie.get('imdb_id'), + 'mpaa': movie.get('certification', ''), + 'runtime': movie.get('runtime'), + 'released': movie.get('released'), + 'year': year, + 'plot': movie.get('overview'), + 'genres': genres, + } + + movie_data = dict((k, v) for k, v in movie_data.iteritems() if v) + + # Add alternative names + for alt in ['original_name', 'alternative_name']: + alt_name = toUnicode(movie.get(alt)) + if alt_name and not alt_name in movie_data['titles'] and alt_name.lower() != 'none' and alt_name != None: + movie_data['titles'].append(alt_name) + + return movie_data + + def getImage(self, movie, type = 'poster', size = 'cover'): + + image_url = '' + for image in movie.get('images', []): + if(image.get('type') == type) and image.get(size): + image_url = image.get(size) + break + + return image_url + + def getCategory(self, movie, type = 'genre'): + + cats = movie.get('categories', {}).get(type) + + categories = [] + for category in cats: + try: + categories.append(category) + except: + pass + + return categories + + def isDisabled(self): + if self.conf('api_key') == '': + log.error('No API key provided.') + True + else: + False diff --git a/couchpotato/core/providers/movie/__init__.py b/couchpotato/core/providers/movie/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/couchpotato/core/providers/movie/_modifier/__init__.py b/couchpotato/core/providers/movie/_modifier/__init__.py deleted file mode 100644 index 3bdf5e0..0000000 --- a/couchpotato/core/providers/movie/_modifier/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from .main import MovieResultModifier - -def start(): - - return MovieResultModifier() - -config = [] diff --git a/couchpotato/core/providers/movie/_modifier/main.py b/couchpotato/core/providers/movie/_modifier/main.py deleted file mode 100644 index 835cce0..0000000 --- a/couchpotato/core/providers/movie/_modifier/main.py +++ /dev/null @@ -1,95 +0,0 @@ -from couchpotato import get_session -from couchpotato.core.event import addEvent, fireEvent -from couchpotato.core.helpers.variable import mergeDicts, randomString -from couchpotato.core.logger import CPLog -from couchpotato.core.plugins.base import Plugin -from couchpotato.core.settings.model import Library -import copy -import traceback - -log = CPLog(__name__) - - -class MovieResultModifier(Plugin): - - default_info = { - 'tmdb_id': 0, - 'titles': [], - 'original_title': '', - 'year': 0, - 'images': { - 'poster': [], - 'backdrop': [], - 'poster_original': [], - 'backdrop_original': [] - }, - 'runtime': 0, - 'plot': '', - 'tagline': '', - 'imdb': '', - 'genres': [], - 'mpaa': None - } - - def __init__(self): - addEvent('result.modify.movie.search', self.combineOnIMDB) - addEvent('result.modify.movie.info', self.checkLibrary) - - def combineOnIMDB(self, results): - - temp = {} - order = [] - - # Combine on imdb id - for item in results: - random_string = randomString() - imdb = item.get('imdb', random_string) - imdb = imdb if imdb else random_string - - if not temp.get(imdb): - temp[imdb] = self.getLibraryTags(imdb) - order.append(imdb) - - # Merge dicts - temp[imdb] = mergeDicts(temp[imdb], item) - - # Make it a list again - temp_list = [temp[x] for x in order] - - return temp_list - - def getLibraryTags(self, imdb): - - temp = { - 'in_wanted': False, - 'in_library': False, - } - - # Add release info from current library - db = get_session() - try: - l = db.query(Library).filter_by(identifier = imdb).first() - if l: - - # Statuses - active_status, done_status = fireEvent('status.get', ['active', 'done'], single = True) - - for movie in l.movies: - if movie.status_id == active_status['id']: - temp['in_wanted'] = fireEvent('movie.get', movie.id, single = True) - - for release in movie.releases: - if release.status_id == done_status['id']: - temp['in_library'] = fireEvent('movie.get', movie.id, single = True) - except: - log.error('Tried getting more info on searched movies: %s', traceback.format_exc()) - - return temp - - def checkLibrary(self, result): - - result = mergeDicts(copy.deepcopy(self.default_info), copy.deepcopy(result)) - - if result and result.get('imdb'): - return mergeDicts(result, self.getLibraryTags(result['imdb'])) - return result diff --git a/couchpotato/core/providers/movie/base.py b/couchpotato/core/providers/movie/base.py deleted file mode 100644 index 1b43ab8..0000000 --- a/couchpotato/core/providers/movie/base.py +++ /dev/null @@ -1,5 +0,0 @@ -from couchpotato.core.providers.base import Provider - - -class MovieProvider(Provider): - type = 'movie' diff --git a/couchpotato/core/providers/movie/couchpotatoapi/__init__.py b/couchpotato/core/providers/movie/couchpotatoapi/__init__.py deleted file mode 100644 index 37d9eca..0000000 --- a/couchpotato/core/providers/movie/couchpotatoapi/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from .main import CouchPotatoApi - -def start(): - return CouchPotatoApi() - -config = [] diff --git a/couchpotato/core/providers/movie/couchpotatoapi/main.py b/couchpotato/core/providers/movie/couchpotatoapi/main.py deleted file mode 100644 index 9f76381..0000000 --- a/couchpotato/core/providers/movie/couchpotatoapi/main.py +++ /dev/null @@ -1,98 +0,0 @@ -from couchpotato.core.event import addEvent, fireEvent -from couchpotato.core.helpers.encoding import tryUrlencode -from couchpotato.core.logger import CPLog -from couchpotato.core.providers.movie.base import MovieProvider -from couchpotato.environment import Env -import time - -log = CPLog(__name__) - - -class CouchPotatoApi(MovieProvider): - - urls = { - 'search': 'https://api.couchpota.to/search/%s/', - 'info': 'https://api.couchpota.to/info/%s/', - 'is_movie': 'https://api.couchpota.to/ismovie/%s/', - 'eta': 'https://api.couchpota.to/eta/%s/', - 'suggest': 'https://api.couchpota.to/suggest/', - 'updater': 'https://api.couchpota.to/updater/?%s', - 'messages': 'https://api.couchpota.to/messages/?%s', - } - http_time_between_calls = 0 - api_version = 1 - - def __init__(self): - addEvent('movie.info', self.getInfo, priority = 1) - addEvent('movie.search', self.search, priority = 1) - addEvent('movie.release_date', self.getReleaseDate) - addEvent('movie.suggest', self.getSuggestions) - addEvent('movie.is_movie', self.isMovie) - - addEvent('cp.source_url', self.getSourceUrl) - addEvent('cp.messages', self.getMessages) - - def getMessages(self, last_check = 0): - - data = self.getJsonData(self.urls['messages'] % tryUrlencode({ - 'last_check': last_check, - }), headers = self.getRequestHeaders(), cache_timeout = 10) - - return data - - def getSourceUrl(self, repo = None, repo_name = None, branch = None): - return self.getJsonData(self.urls['updater'] % tryUrlencode({ - 'repo': repo, - 'name': repo_name, - 'branch': branch, - }), headers = self.getRequestHeaders()) - - def search(self, q, limit = 5): - return self.getJsonData(self.urls['search'] % tryUrlencode(q) + ('?limit=%s' % limit), headers = self.getRequestHeaders()) - - def isMovie(self, identifier = None): - - if not identifier: - return - - data = self.getJsonData(self.urls['is_movie'] % identifier, headers = self.getRequestHeaders()) - if data: - return data.get('is_movie', True) - - return True - - def getInfo(self, identifier = None): - - if not identifier: - return - - result = self.getJsonData(self.urls['info'] % identifier, headers = self.getRequestHeaders()) - if result: - return dict((k, v) for k, v in result.iteritems() if v) - - return {} - - def getReleaseDate(self, identifier = None): - if identifier is None: return {} - - dates = self.getJsonData(self.urls['eta'] % identifier, headers = self.getRequestHeaders()) - log.debug('Found ETA for %s: %s', (identifier, dates)) - - return dates - - def getSuggestions(self, movies = [], ignore = []): - suggestions = self.getJsonData(self.urls['suggest'], params = { - 'movies': ','.join(movies), - 'ignore': ','.join(ignore), - }, headers = self.getRequestHeaders()) - log.info('Found suggestions for %s movies, %s ignored', (len(movies), len(ignore))) - - return suggestions - - def getRequestHeaders(self): - return { - 'X-CP-Version': fireEvent('app.version', single = True), - 'X-CP-API': self.api_version, - 'X-CP-Time': time.time(), - 'X-CP-Identifier': '+%s' % Env.setting('api_key', 'core')[:10], # Use first 10 as identifier, so we don't need to use IP address in api stats - } diff --git a/couchpotato/core/providers/movie/omdbapi/__init__.py b/couchpotato/core/providers/movie/omdbapi/__init__.py deleted file mode 100644 index 765662e..0000000 --- a/couchpotato/core/providers/movie/omdbapi/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from .main import OMDBAPI - -def start(): - return OMDBAPI() - -config = [] diff --git a/couchpotato/core/providers/movie/omdbapi/main.py b/couchpotato/core/providers/movie/omdbapi/main.py deleted file mode 100755 index c9f4d92..0000000 --- a/couchpotato/core/providers/movie/omdbapi/main.py +++ /dev/null @@ -1,123 +0,0 @@ -from couchpotato.core.event import addEvent, fireEvent -from couchpotato.core.helpers.encoding import tryUrlencode -from couchpotato.core.helpers.variable import tryInt, tryFloat, splitString -from couchpotato.core.logger import CPLog -from couchpotato.core.providers.movie.base import MovieProvider -import json -import re -import traceback - -log = CPLog(__name__) - - -class OMDBAPI(MovieProvider): - - urls = { - 'search': 'http://www.omdbapi.com/?%s', - 'info': 'http://www.omdbapi.com/?i=%s', - } - - http_time_between_calls = 0 - - def __init__(self): - addEvent('movie.search', self.search) - addEvent('movie.info', self.getInfo) - - def search(self, q, limit = 12): - - name_year = fireEvent('scanner.name_year', q, single = True) - - if not name_year or (name_year and not name_year.get('name')): - name_year = { - 'name': q - } - - cache_key = 'omdbapi.cache.%s' % q - cached = self.getCache(cache_key, self.urls['search'] % tryUrlencode({'t': name_year.get('name'), 'y': name_year.get('year', '')}), timeout = 3) - - if cached: - result = self.parseMovie(cached) - if result.get('titles') and len(result.get('titles')) > 0: - log.info('Found: %s', result['titles'][0] + ' (' + str(result['year']) + ')') - return [result] - - return [] - - return [] - - def getInfo(self, identifier = None): - - if not identifier: - return {} - - cache_key = 'omdbapi.cache.%s' % identifier - cached = self.getCache(cache_key, self.urls['info'] % identifier, timeout = 3) - - if cached: - result = self.parseMovie(cached) - if result.get('titles') and len(result.get('titles')) > 0: - log.info('Found: %s', result['titles'][0] + ' (' + str(result['year']) + ')') - return result - - return {} - - def parseMovie(self, movie): - - movie_data = {} - try: - - try: - if isinstance(movie, (str, unicode)): - movie = json.loads(movie) - except ValueError: - log.info('No proper json to decode') - return movie_data - - if movie.get('Response') == 'Parse Error' or movie.get('Response') == 'False': - return movie_data - - tmp_movie = movie.copy() - for key in tmp_movie: - if tmp_movie.get(key).lower() == 'n/a': - del movie[key] - - year = tryInt(movie.get('Year', '')) - - movie_data = { - 'via_imdb': True, - 'titles': [movie.get('Title')] if movie.get('Title') else [], - 'original_title': movie.get('Title'), - 'images': { - 'poster': [movie.get('Poster', '')] if movie.get('Poster') and len(movie.get('Poster', '')) > 4 else [], - }, - 'rating': { - 'imdb': (tryFloat(movie.get('imdbRating', 0)), tryInt(movie.get('imdbVotes', '').replace(',', ''))), - #'rotten': (tryFloat(movie.get('tomatoRating', 0)), tryInt(movie.get('tomatoReviews', '').replace(',', ''))), - }, - 'imdb': str(movie.get('imdbID', '')), - 'mpaa': str(movie.get('Rated', '')), - 'runtime': self.runtimeToMinutes(movie.get('Runtime', '')), - 'released': movie.get('Released'), - 'year': year if isinstance(year, (int)) else None, - 'plot': movie.get('Plot'), - 'genres': splitString(movie.get('Genre', '')), - 'directors': splitString(movie.get('Director', '')), - 'writers': splitString(movie.get('Writer', '')), - 'actors': splitString(movie.get('Actors', '')), - } - movie_data = dict((k, v) for k, v in movie_data.iteritems() if v) - except: - log.error('Failed parsing IMDB API json: %s', traceback.format_exc()) - - return movie_data - - def runtimeToMinutes(self, runtime_str): - runtime = 0 - - regex = '(\d*.?\d+).(h|hr|hrs|mins|min)+' - matches = re.findall(regex, runtime_str) - for match in matches: - nr, size = match - runtime += tryInt(nr) * (60 if 'h' is str(size)[0] else 1) - - return runtime diff --git a/couchpotato/core/providers/movie/themoviedb/__init__.py b/couchpotato/core/providers/movie/themoviedb/__init__.py deleted file mode 100644 index 66ac536..0000000 --- a/couchpotato/core/providers/movie/themoviedb/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -from .main import TheMovieDb - -def start(): - return TheMovieDb() - -config = [{ - 'name': 'themoviedb', - 'groups': [ - { - 'tab': 'providers', - 'name': 'tmdb', - 'label': 'TheMovieDB', - 'hidden': True, - 'description': 'Used for all calls to TheMovieDB.', - 'options': [ - { - 'name': 'api_key', - 'default': '9b939aee0aaafc12a65bf448e4af9543', - 'label': 'Api Key', - }, - ], - }, - ], -}] diff --git a/couchpotato/core/providers/movie/themoviedb/main.py b/couchpotato/core/providers/movie/themoviedb/main.py deleted file mode 100644 index 241fc6b..0000000 --- a/couchpotato/core/providers/movie/themoviedb/main.py +++ /dev/null @@ -1,216 +0,0 @@ -from couchpotato.core.event import addEvent -from couchpotato.core.helpers.encoding import simplifyString, toUnicode -from couchpotato.core.logger import CPLog -from couchpotato.core.providers.movie.base import MovieProvider -from themoviedb import tmdb -import traceback - -log = CPLog(__name__) - - -class TheMovieDb(MovieProvider): - - def __init__(self): - addEvent('movie.by_hash', self.byHash) - addEvent('movie.search', self.search, priority = 2) - addEvent('movie.info', self.getInfo, priority = 2) - addEvent('movie.info_by_tmdb', self.getInfoByTMDBId) - - # Use base wrapper - tmdb.configure(self.conf('api_key')) - - def byHash(self, file): - ''' Find movie by hash ''' - - if self.isDisabled(): - return False - - cache_key = 'tmdb.cache.%s' % simplifyString(file) - results = self.getCache(cache_key) - - if not results: - log.debug('Searching for movie by hash: %s', file) - try: - raw = tmdb.searchByHashingFile(file) - - results = [] - if raw: - try: - results = self.parseMovie(raw) - log.info('Found: %s', results['titles'][0] + ' (' + str(results.get('year', 0)) + ')') - - self.setCache(cache_key, results) - return results - except SyntaxError, e: - log.error('Failed to parse XML response: %s', e) - return False - except: - log.debug('No movies known by hash for: %s', file) - pass - - return results - - def search(self, q, limit = 12): - ''' Find movie by name ''' - - if self.isDisabled(): - return False - - search_string = simplifyString(q) - cache_key = 'tmdb.cache.%s.%s' % (search_string, limit) - results = self.getCache(cache_key) - - if not results: - log.debug('Searching for movie: %s', q) - - raw = None - try: - raw = tmdb.search(search_string) - except: - log.error('Failed searching TMDB for "%s": %s', (search_string, traceback.format_exc())) - - results = [] - if raw: - try: - nr = 0 - - for movie in raw: - results.append(self.parseMovie(movie)) - - nr += 1 - if nr == limit: - break - - log.info('Found: %s', [result['titles'][0] + ' (' + str(result.get('year', 0)) + ')' for result in results]) - - self.setCache(cache_key, results) - return results - except SyntaxError, e: - log.error('Failed to parse XML response: %s', e) - return False - - return results - - def getInfo(self, identifier = None): - - if not identifier: - return {} - - cache_key = 'tmdb.cache.%s' % identifier - result = self.getCache(cache_key) - - if not result: - result = {} - movie = None - - try: - log.debug('Getting info: %s', cache_key) - movie = tmdb.imdbLookup(id = identifier) - except: - pass - - if movie: - result = self.parseMovie(movie[0]) - self.setCache(cache_key, result) - - return result - - def getInfoByTMDBId(self, id = None): - - cache_key = 'tmdb.cache.%s' % id - result = self.getCache(cache_key) - - if not result: - result = {} - movie = None - - try: - log.debug('Getting info: %s', cache_key) - movie = tmdb.getMovieInfo(id = id) - except: - pass - - if movie: - result = self.parseMovie(movie) - self.setCache(cache_key, result) - - return result - - def parseMovie(self, movie): - - # Images - poster = self.getImage(movie, type = 'poster', size = 'cover') - #backdrop = self.getImage(movie, type = 'backdrop', size = 'w1280') - poster_original = self.getImage(movie, type = 'poster', size = 'original') - backdrop_original = self.getImage(movie, type = 'backdrop', size = 'original') - - # Genres - try: - genres = self.getCategory(movie, 'genre') - except: - genres = [] - - # 1900 is the same as None - year = str(movie.get('released', 'none'))[:4] - if year == '1900' or year.lower() == 'none': - year = None - - movie_data = { - 'via_tmdb': True, - 'tmdb_id': int(movie.get('id', 0)), - 'titles': [toUnicode(movie.get('name'))], - 'original_title': movie.get('original_name'), - 'images': { - 'poster': [poster] if poster else [], - #'backdrop': [backdrop] if backdrop else [], - 'poster_original': [poster_original] if poster_original else [], - 'backdrop_original': [backdrop_original] if backdrop_original else [], - }, - 'imdb': movie.get('imdb_id'), - 'mpaa': movie.get('certification', ''), - 'runtime': movie.get('runtime'), - 'released': movie.get('released'), - 'year': year, - 'plot': movie.get('overview'), - 'genres': genres, - } - - movie_data = dict((k, v) for k, v in movie_data.iteritems() if v) - - # Add alternative names - for alt in ['original_name', 'alternative_name']: - alt_name = toUnicode(movie.get(alt)) - if alt_name and not alt_name in movie_data['titles'] and alt_name.lower() != 'none' and alt_name != None: - movie_data['titles'].append(alt_name) - - return movie_data - - def getImage(self, movie, type = 'poster', size = 'cover'): - - image_url = '' - for image in movie.get('images', []): - if(image.get('type') == type) and image.get(size): - image_url = image.get(size) - break - - return image_url - - def getCategory(self, movie, type = 'genre'): - - cats = movie.get('categories', {}).get(type) - - categories = [] - for category in cats: - try: - categories.append(category) - except: - pass - - return categories - - def isDisabled(self): - if self.conf('api_key') == '': - log.error('No API key provided.') - True - else: - False