|
|
|
|
@ -4,6 +4,8 @@ from dataclasses import dataclass, field
|
|
|
|
|
from datetime import date, datetime |
|
|
|
|
from enum import IntEnum |
|
|
|
|
import json |
|
|
|
|
import os |
|
|
|
|
from pathlib import Path |
|
|
|
|
import re |
|
|
|
|
from sqlite3 import DatabaseError |
|
|
|
|
import ssl |
|
|
|
|
@ -12,8 +14,8 @@ from urllib.error import URLError, HTTPError
|
|
|
|
|
import urllib.parse |
|
|
|
|
import urllib.request |
|
|
|
|
|
|
|
|
|
from flask import Blueprint, current_app, flash, Flask, jsonify, request, redirect, \ |
|
|
|
|
render_template, Response, url_for |
|
|
|
|
from flask import Blueprint, current_app, flash, Flask, jsonify, make_response, request, \ |
|
|
|
|
redirect, render_template, Response, url_for |
|
|
|
|
|
|
|
|
|
from .. import util |
|
|
|
|
from .. import db |
|
|
|
|
@ -31,6 +33,7 @@ TMDB_TV_LINK_URL = 'https://www.themoviedb.org/tv/'
|
|
|
|
|
TMDB_POSTER_PREFIX = 'https://image.tmdb.org/t/p/w154' |
|
|
|
|
VALID_IMAGE_EXTENSIONS = ('.jpg', '.png', '.svg') |
|
|
|
|
DEFAULT_POSTER_IMAGE = 'no_poster_w154.jpg' |
|
|
|
|
LOCAL_POSTER_PATH = 'image_cache' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#################### |
|
|
|
|
@ -78,7 +81,7 @@ class view_result:
|
|
|
|
|
overview: str = '' |
|
|
|
|
genre_ids: List[int] = field(default_factory=list) |
|
|
|
|
original_language: str = '' |
|
|
|
|
poster_path: str = 'no_image.png' |
|
|
|
|
poster_path: str = '' |
|
|
|
|
tmdb_link: str = '' |
|
|
|
|
|
|
|
|
|
# TODO: flask 1.1 adds support for JSON encoding dataclasses |
|
|
|
|
@ -279,27 +282,55 @@ def create_path_mapping():
|
|
|
|
|
return jsonify({'errors':errors, 'message':message}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/images') |
|
|
|
|
@bp.route('/images/<string:image_name>') |
|
|
|
|
def cache_image(image_name:str = ''): |
|
|
|
|
current_app.logger.debug(f'image_name: {image_name}') |
|
|
|
|
# validate image name |
|
|
|
|
if (image_name == '' |
|
|
|
|
or re.search(r'[^ a-zA-z0-9./]', image_name) |
|
|
|
|
or not Path(image_name).suffix in VALID_IMAGE_EXTENSIONS): |
|
|
|
|
current_app.logger.error(f'invalid image name: {image_name}') |
|
|
|
|
return redirect(url_for('static', filename=DEFAULT_POSTER_IMAGE)) |
|
|
|
|
|
|
|
|
|
if image_name != '': |
|
|
|
|
s = re.sub(r'/', '', image_name) |
|
|
|
|
ext = re.compile(r'.[a-zA-Z]{3}$').search(image_name).group(0) |
|
|
|
|
print(f'ext: "{ext}"') |
|
|
|
|
# look for image in cache folder |
|
|
|
|
local_dir = Path(current_app.instance_path).joinpath(LOCAL_POSTER_PATH) |
|
|
|
|
image = Path(image_name).name |
|
|
|
|
p = local_dir.joinpath(image) |
|
|
|
|
current_app.logger.debug(f'checking for local path: {p}') |
|
|
|
|
|
|
|
|
|
if not ext in VALID_IMAGE_EXTENSIONS: |
|
|
|
|
print('oops') |
|
|
|
|
else: |
|
|
|
|
print(f'seems okay: {ext}') |
|
|
|
|
if not p.exists(): |
|
|
|
|
# make request for remote image |
|
|
|
|
response = util.URLResponse |
|
|
|
|
|
|
|
|
|
url = f'{TMDB_POSTER_PREFIX}/{s}' |
|
|
|
|
if util.getURL(f'{TMDB_POSTER_PREFIX}/{image}', response, current_app.logger): |
|
|
|
|
# store remote image |
|
|
|
|
current_app.logger.debug(f'content-type for {image}: {response.content_type}') |
|
|
|
|
try: |
|
|
|
|
fp = open(p, 'wb') |
|
|
|
|
fp.write(response.body) |
|
|
|
|
fp.close() |
|
|
|
|
except OSError as e: |
|
|
|
|
current_app.logger.error(e) |
|
|
|
|
return redirect(url_for('static', filename=DEFAULT_POSTER_IMAGE)) |
|
|
|
|
|
|
|
|
|
#res = Response(json.dumps(results, cls=result_encoder)) |
|
|
|
|
#res.headers.set('Content-Type', 'application/json') |
|
|
|
|
#return str(f'image_name: {image_name}, url: {url}') |
|
|
|
|
# redirect to saved image |
|
|
|
|
try: |
|
|
|
|
fp = open(p, 'rb') |
|
|
|
|
image_bytes = fp.read() |
|
|
|
|
except OSError as e: |
|
|
|
|
current_app.logger.error(e) |
|
|
|
|
return redirect(url_for('static', filename=DEFAULT_POSTER_IMAGE)) |
|
|
|
|
|
|
|
|
|
def getCType(s): |
|
|
|
|
if s is '.jpg': |
|
|
|
|
return 'image/jpeg' |
|
|
|
|
elif s is '.png': |
|
|
|
|
return 'image/png' |
|
|
|
|
elif s is '.svg': |
|
|
|
|
return 'image/svg+xml' |
|
|
|
|
|
|
|
|
|
return make_response(tuple([image_bytes, {'Content-Type': getCType(p.suffix)} ])) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
################### |
|
|
|
|
# helpers |
|
|
|
|
|