Source code for flexget.components.thetvdb.api

from flask import jsonify
from flask_restx import inputs

from flexget.api import APIResource, api
from flexget.api.app import BadRequest, NotFoundError, etag
from flexget.components.thetvdb.api_tvdb import lookup_episode, lookup_series, search_for_series

tvdb_api = api.namespace('tvdb', description='TheTVDB Shows')


[docs] class ObjectsContainer: tvdb_series_object = { 'type': 'object', 'properties': { 'tvdb_id': {'type': 'integer'}, 'last_updated': {'type': 'string', 'format': 'date-time'}, 'expired': {'type': 'boolean'}, 'series_name': {'type': 'string'}, 'rating': {'type': 'number'}, 'status': {'type': 'string'}, 'runtime': {'type': 'integer'}, 'airs_time': {'type': 'string'}, 'airs_dayofweek': {'type': 'string'}, 'content_rating': {'type': 'string'}, 'network': {'type': 'string'}, 'overview': {'type': 'string'}, 'imdb_id': {'type': 'string'}, 'zap2it_id': {'type': 'string'}, 'banner': {'type': 'string'}, 'first_aired': {'type': 'string'}, 'actors': {'type': 'array', 'items': {'type': 'string'}}, 'aliases': {'type': 'array', 'items': {'type': 'string'}}, 'posters': {'type': 'array', 'items': {'type': 'string'}}, 'genres': {'type': 'array', 'items': {'type': 'string'}}, 'language': {'type': 'string'}, }, 'required': [ 'tvdb_id', 'last_updated', 'expired', 'series_name', 'rating', 'status', 'runtime', 'airs_time', 'airs_dayofweek', 'content_rating', 'network', 'overview', 'imdb_id', 'zap2it_id', 'banner', 'first_aired', 'aliases', 'posters', 'genres', 'language', ], 'additionalProperties': False, } episode_object = { 'type': 'object', 'properties': { 'id': {'type': 'integer'}, 'expired': {'type': 'boolean'}, 'last_update': {'type': 'integer'}, 'season_number': {'type': 'integer'}, 'episode_number': {'type': 'integer'}, 'absolute_number': {'type': ['integer', 'null']}, 'episode_name': {'type': 'string'}, 'overview': {'type': 'string'}, 'director': {'type': 'string'}, 'rating': {'type': 'number'}, 'image': {'type': ['string', 'null']}, 'first_aired': {'type': 'string'}, 'series_id': {'type': 'integer'}, }, 'required': [ 'id', 'expired', 'last_update', 'season_number', 'episode_number', 'absolute_number', 'episode_name', 'overview', 'director', 'rating', 'image', 'first_aired', 'series_id', ], 'additionalProperties': False, } search_result_object = { 'type': 'object', 'properties': { 'aliases': {'type': 'array', 'items': {'type': 'string'}}, 'first_aired': {'type': 'string', 'format': 'date-time'}, 'banner': {'type': ['string', 'null']}, 'network': {'type': 'string'}, 'series_name': {'type': 'string'}, 'status': {'type': 'string'}, 'overview': {'type': ['string', 'null']}, 'tvdb_id': {'type': 'integer'}, }, 'required': [ 'aliases', 'first_aired', 'banner', 'network', 'series_name', 'status', 'overview', 'tvdb_id', ], 'additionalProperties': False, } search_results_object = {'type': 'array', 'items': search_result_object}
tvdb_series_schema = api.schema_model('tvdb_series_schema', ObjectsContainer.tvdb_series_object) tvdb_episode_schema = api.schema_model('tvdb_episode_schema', ObjectsContainer.episode_object) search_results_schema = api.schema_model( 'tvdb_search_results_schema', ObjectsContainer.search_results_object ) base_parser = api.parser() base_parser.add_argument( 'language', default='en', help='Language abbreviation string for different language support' ) series_parser = base_parser.copy() series_parser.add_argument( 'include_actors', type=inputs.boolean, help='Include actors in response' )
[docs] @tvdb_api.route('/series/<string:title>/') @api.doc(params={'title': 'TV Show name or TVDB ID'}, expect=[series_parser]) class TVDBSeriesLookupAPI(APIResource):
[docs] @etag(cache_age=3600) @api.response(200, 'Successfully found show', tvdb_series_schema) @api.response(NotFoundError) def get(self, title, session=None): """TheTVDB series lookup.""" args = series_parser.parse_args() language = args['language'] try: tvdb_id = int(title) except ValueError: tvdb_id = None kwargs = {'session': session, 'language': language} if tvdb_id: kwargs['tvdb_id'] = tvdb_id else: kwargs['name'] = title try: series = lookup_series(**kwargs) except LookupError as e: raise NotFoundError(e.args[0]) result = series.to_dict() if args.get('include_actors'): result['actors'] = series.actors return jsonify(result)
episode_parser = base_parser.copy() episode_parser.add_argument('season_number', type=int, help='Season number') episode_parser.add_argument('ep_number', type=int, help='Episode number') episode_parser.add_argument('absolute_number', type=int, help='Absolute episode number') episode_parser.add_argument( 'air_date', type=inputs.date, help='Episode airdate in `YYYY-mm-dd` format' )
[docs] @tvdb_api.route('/episode/<int:tvdb_id>/') @api.doc(params={'tvdb_id': 'TVDB ID of show'}, expect=[episode_parser]) class TVDBEpisodeSearchAPI(APIResource):
[docs] @etag(cache_age=3600) @api.response(200, 'Successfully found episode', tvdb_episode_schema) @api.response(NotFoundError) @api.response(BadRequest) def get(self, tvdb_id, session=None): """TheTVDB episode lookup.""" args = episode_parser.parse_args() language = args['language'] absolute_number = args.get('absolute_number') season_number = args.get('season_number') ep_number = args.get('ep_number') air_date = args.get('air_date') if not ((season_number and ep_number) or absolute_number or air_date): raise BadRequest( 'not enough parameters for lookup. Either season and episode number or absolute number ' 'are required.' ) kwargs = {'tvdb_id': tvdb_id, 'session': session, 'language': language} if absolute_number: kwargs['absolute_number'] = absolute_number if season_number and ep_number: kwargs['season_number'] = season_number kwargs['episode_number'] = ep_number if air_date: kwargs['first_aired'] = air_date try: episode = lookup_episode(**kwargs) except LookupError as e: raise NotFoundError(e.args[0]) return jsonify(episode.to_dict())
search_parser = base_parser.copy() search_parser.add_argument('search_name', help='Series Name') search_parser.add_argument('imdb_id', help='Series IMDB ID') search_parser.add_argument('zap2it_id', help='Series ZAP2IT ID') search_parser.add_argument( 'force_search', type=inputs.boolean, help='Force online lookup or allow for result to be retrieved from cache', )
[docs] @tvdb_api.route('/search/') @api.doc(expect=[search_parser]) class TVDBSeriesSearchAPI(APIResource):
[docs] @etag(cache_age=3600) @api.response(200, 'Successfully got results', search_results_schema) @api.response(BadRequest) @api.response(NotFoundError) def get(self, session=None): """TheTVDB series search.""" args = search_parser.parse_args() language = args['language'] search_name = args.get('search_name') imdb_id = args.get('imdb_id') zap2it_id = args.get('zap2it_id') force_search = args.get('force_search') if not any(arg for arg in [search_name, imdb_id, zap2it_id]): raise BadRequest('Not enough lookup arguments') kwargs = { 'search_name': search_name, 'imdb_id': imdb_id, 'zap2it_id': zap2it_id, 'force_search': force_search, 'session': session, 'language': language, } try: search_results = search_for_series(**kwargs) except LookupError as e: raise NotFoundError(e.args[0]) return jsonify([a.to_dict() for a in search_results])