|
|
|
@ -4,7 +4,6 @@ from contextlib import closing |
|
|
|
from datetime import date |
|
|
|
from datetime import date |
|
|
|
from enum import Enum |
|
|
|
from enum import Enum |
|
|
|
import json |
|
|
|
import json |
|
|
|
from pprint import pprint |
|
|
|
|
|
|
|
import re |
|
|
|
import re |
|
|
|
import ssl |
|
|
|
import ssl |
|
|
|
from urllib.error import URLError, HTTPError |
|
|
|
from urllib.error import URLError, HTTPError |
|
|
|
@ -20,9 +19,11 @@ from .. import util |
|
|
|
# constants |
|
|
|
# constants |
|
|
|
|
|
|
|
|
|
|
|
bp = Blueprint('tmdb', __name__, url_prefix='/tmdb') |
|
|
|
bp = Blueprint('tmdb', __name__, url_prefix='/tmdb') |
|
|
|
TMDB_URL = 'https://api.themoviedb.org' |
|
|
|
TMDB_API_URL = 'https://api.themoviedb.org' |
|
|
|
TMDB_SEARCH_MOVIE = '/3/search/movie' |
|
|
|
TMDB_SEARCH_MOVIE = '/3/search/movie' |
|
|
|
TMDB_SEARCH_TV = '/3/search/tv' |
|
|
|
TMDB_SEARCH_TV = '/3/search/tv' |
|
|
|
|
|
|
|
TMDB_MOVIE_LINK_URL = 'https://www.themoviedb.org/movie/' |
|
|
|
|
|
|
|
TMDB_TV_LINK_URL = 'https://www.themoviedb.org/tv/' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#################### |
|
|
|
#################### |
|
|
|
@ -42,11 +43,44 @@ class query_data(object): |
|
|
|
self.query_params = {} |
|
|
|
self.query_params = {} |
|
|
|
self.query_type = query_type.UNKNOWN |
|
|
|
self.query_type = query_type.UNKNOWN |
|
|
|
self.raw_query_str = '' |
|
|
|
self.raw_query_str = '' |
|
|
|
|
|
|
|
self.tmdb_api_key = '' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class response_data(object): |
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
|
|
|
|
self.errors = [] |
|
|
|
|
|
|
|
self.parsed_response = {} |
|
|
|
self.response_body = '' |
|
|
|
self.response_body = '' |
|
|
|
self.response_headers = [] |
|
|
|
self.response_headers = [] |
|
|
|
self.response_object = {} |
|
|
|
|
|
|
|
self.response_status = 0 |
|
|
|
self.response_status = 0 |
|
|
|
self.tmdb_api_key = '' |
|
|
|
self.result_count = 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class view_result(object): |
|
|
|
|
|
|
|
def __init__(self): |
|
|
|
|
|
|
|
self.id = 0 |
|
|
|
|
|
|
|
self.title = '' |
|
|
|
|
|
|
|
self.date = 0 |
|
|
|
|
|
|
|
self.description = '' |
|
|
|
|
|
|
|
self.genre_ids = [] |
|
|
|
|
|
|
|
self.original_language = '' |
|
|
|
|
|
|
|
self.poster_path = 'no_image.png' |
|
|
|
|
|
|
|
self.tmdb_link = '' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# NOTE: result is parsed JSON object from tmdb API |
|
|
|
|
|
|
|
def copy_result(self, result, query_type): |
|
|
|
|
|
|
|
self.id = result['id'] |
|
|
|
|
|
|
|
self.title = result['original_title'] |
|
|
|
|
|
|
|
self.release_date = result['release_date'] |
|
|
|
|
|
|
|
self.description = result['overview'] |
|
|
|
|
|
|
|
self.genre_ids = result['genre_ids'] |
|
|
|
|
|
|
|
self.original_language = result['original_language'] |
|
|
|
|
|
|
|
self.poster_path = result['poster_path'] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if query_type == query_type.MOVIE: |
|
|
|
|
|
|
|
self.tmdb_link = TMDB_MOVIE_LINK_URL + str(result['id']) |
|
|
|
|
|
|
|
elif query_type == query_type.TV_SHOW: |
|
|
|
|
|
|
|
self.tmdb_link = TMDB_TV_LINK_URL + str(result['id']) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return self |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#################### |
|
|
|
#################### |
|
|
|
@ -54,32 +88,46 @@ class query_data(object): |
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/query_movie') |
|
|
|
@bp.route('/query_movie') |
|
|
|
def query_movie(): |
|
|
|
def query_movie(): |
|
|
|
view_data = query_data() |
|
|
|
errors = [] |
|
|
|
view_data.tmdb_api_key = current_app.config['TMDB_API_KEY'] |
|
|
|
query = query_data() |
|
|
|
|
|
|
|
response = response_data() |
|
|
|
|
|
|
|
view_results = [] |
|
|
|
|
|
|
|
query.tmdb_api_key = current_app.config['TMDB_API_KEY'] |
|
|
|
|
|
|
|
|
|
|
|
# NOTE: query string can be submitted from a link or form input |
|
|
|
# NOTE: query string can be submitted from a link or form input |
|
|
|
if 'query' in request.form: |
|
|
|
if 'query' in request.form: |
|
|
|
view_data.raw_query_str = request.form['query'] |
|
|
|
query.raw_query_str = request.form['query'] |
|
|
|
elif 'query' in request.args: |
|
|
|
elif 'query' in request.args: |
|
|
|
view_data.raw_query_str = request.args['query'] |
|
|
|
query.raw_query_str = request.args['query'] |
|
|
|
|
|
|
|
|
|
|
|
if parseQueryStr(view_data) and makeQuery(view_data): |
|
|
|
if query.raw_query_str and parseQueryStr(query): |
|
|
|
try: |
|
|
|
if makeQuery(query, response): |
|
|
|
p = view_data.response_object = json.loads(view_data.response_body) |
|
|
|
try: |
|
|
|
pprint(p) |
|
|
|
response.parsed_response = json.loads(response.response_body) |
|
|
|
except json.JSONDecodeError as e: |
|
|
|
response.result_count = response.parsed_response['total_results'] |
|
|
|
view_data.errors.append(e) |
|
|
|
except json.JSONDecodeError as e: |
|
|
|
|
|
|
|
view_data.errors.append(e) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for result in response.parsed_response['results']: |
|
|
|
|
|
|
|
copy = view_result() |
|
|
|
|
|
|
|
view_results.append(copy.copy_result(result, query.query_type)) |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
query.errors.append('{}, error making query'.format(util.getFunctionName)) |
|
|
|
else: |
|
|
|
else: |
|
|
|
# display errors |
|
|
|
errors.append('{}, error in query string'.format(util.getFunctionName())) |
|
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if view_data.errors: |
|
|
|
errors.extend(query.errors) |
|
|
|
flash(view_data.errors) |
|
|
|
errors.extend(response.errors) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if errors: |
|
|
|
|
|
|
|
flash(errors) |
|
|
|
|
|
|
|
|
|
|
|
return render_template( |
|
|
|
return render_template( |
|
|
|
'tmdb/query.html', |
|
|
|
'tmdb/query.html', |
|
|
|
view_data=view_data, |
|
|
|
view_data = view_results, |
|
|
|
debug_str=util.dumpObjAttr(view_data) |
|
|
|
debug_str = str(util.dumpObjAttr(query) + '\n' |
|
|
|
|
|
|
|
+ util.dumpObjAttr(response)) + '\n' |
|
|
|
|
|
|
|
+ util.dumpList(view_results, 0) + '\n' |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -89,12 +137,7 @@ def query_movie(): |
|
|
|
# TODO: need a way to correctly parse titles like: "2001: A Space Odyssey (1968)" |
|
|
|
# TODO: need a way to correctly parse titles like: "2001: A Space Odyssey (1968)" |
|
|
|
# with legitimate dates in the title |
|
|
|
# with legitimate dates in the title |
|
|
|
def parseQueryStr(query_obj): |
|
|
|
def parseQueryStr(query_obj): |
|
|
|
if not query_obj.raw_query_str: |
|
|
|
|
|
|
|
query_obj.errors.append('%s: raw query string is empty' % util.getFunctionName()) |
|
|
|
|
|
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s = query_obj.raw_query_str.replace('.', ' ').strip() |
|
|
|
s = query_obj.raw_query_str.replace('.', ' ').strip() |
|
|
|
year = None |
|
|
|
|
|
|
|
current_year = date.today().year |
|
|
|
current_year = date.today().year |
|
|
|
|
|
|
|
|
|
|
|
# NOTE: find all 4 digit numbers to match the year of queries with 4 digit numbers in the title |
|
|
|
# NOTE: find all 4 digit numbers to match the year of queries with 4 digit numbers in the title |
|
|
|
@ -110,13 +153,13 @@ def parseQueryStr(query_obj): |
|
|
|
break |
|
|
|
break |
|
|
|
|
|
|
|
|
|
|
|
# TODO: parse tv show titles |
|
|
|
# TODO: parse tv show titles |
|
|
|
if query_obj.query_type == query_type.MOVIE: |
|
|
|
if query_obj.query_type == query_type.UNKNOWN: |
|
|
|
return True |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
query_obj.errors.append('%s: unable to determine query type' % util.getFunctionName()) |
|
|
|
query_obj.errors.append('%s: unable to determine query type' % util.getFunctionName()) |
|
|
|
return False |
|
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
def makeQuery(query_obj): |
|
|
|
return True |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def makeQuery(query_obj, response_obj): |
|
|
|
if query_obj.query_type == query_type.MOVIE: |
|
|
|
if query_obj.query_type == query_type.MOVIE: |
|
|
|
search_part = TMDB_SEARCH_MOVIE |
|
|
|
search_part = TMDB_SEARCH_MOVIE |
|
|
|
elif query_obj.query_type == query_type.TV_SHOW: |
|
|
|
elif query_obj.query_type == query_type.TV_SHOW: |
|
|
|
@ -134,7 +177,7 @@ def makeQuery(query_obj): |
|
|
|
} |
|
|
|
} |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
query_obj.full_url = TMDB_URL + search_part + '?' + query_obj.query_params |
|
|
|
query_obj.full_url = TMDB_API_URL + search_part + '?' + query_obj.query_params |
|
|
|
context = ssl.create_default_context() |
|
|
|
context = ssl.create_default_context() |
|
|
|
req = urllib.request.Request(query_obj.full_url, None, request_headers) |
|
|
|
req = urllib.request.Request(query_obj.full_url, None, request_headers) |
|
|
|
ct_header = '' |
|
|
|
ct_header = '' |
|
|
|
@ -149,18 +192,18 @@ def makeQuery(query_obj): |
|
|
|
return False |
|
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
for k, v in response.info().items(): |
|
|
|
for k, v in response.info().items(): |
|
|
|
query_obj.response_headers.append((k, v)) |
|
|
|
response_obj.response_headers.append((k, v)) |
|
|
|
if k == 'Content-Type': |
|
|
|
if k == 'Content-Type': |
|
|
|
ct_header = str(k + ':' + v) |
|
|
|
ct_header = str(k + ':' + v) |
|
|
|
|
|
|
|
|
|
|
|
query_obj.response_status = response.status |
|
|
|
response_obj.response_status = response.status |
|
|
|
|
|
|
|
|
|
|
|
if 'charset' in ct_header: |
|
|
|
if 'charset' in ct_header: |
|
|
|
charset = cgi.parse_header(ct_header)[1]['charset'] |
|
|
|
charset = cgi.parse_header(ct_header)[1]['charset'] |
|
|
|
query_obj.response_body = response.read().decode(charset) |
|
|
|
response_obj.response_body = response.read().decode(charset) |
|
|
|
else: |
|
|
|
else: |
|
|
|
query_obj.errors.append('%s(), no charset key in ct_header' % util.getFunctionName()) |
|
|
|
response_obj.errors.append('%s(), no charset key in ct_header' % util.getFunctionName()) |
|
|
|
query_obj.response_body = response.read() |
|
|
|
response_obj.response_body = response.read() |
|
|
|
return False |
|
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
return True |
|
|
|
return True |
|
|
|
|