Changed file formatting and fixed comic viewer.

This commit is contained in:
Matthew Welch 2020-08-05 18:47:29 -07:00
parent 51c6b5e572
commit f8aa5ff2d7
19 changed files with 2180 additions and 1745 deletions

View File

@ -1,5 +1,5 @@
from flask import Blueprint, flash, redirect, url_for, render_template from flask import Blueprint, flash, redirect, render_template, url_for
from flask_login import login_required, current_user from flask_login import current_user, login_required
Admin = Blueprint("admin", __name__, template_folder="templates") Admin = Blueprint("admin", __name__, template_folder="templates")
@ -7,7 +7,7 @@ Admin = Blueprint("admin", __name__, template_folder="templates")
@Admin.route("/admin") @Admin.route("/admin")
@login_required @login_required
def index(): def index():
if not current_user.is_admin: if not current_user.is_admin:
flash("you must be an admin to access this page, login with an admin account.") flash("you must be an admin to access this page, login with an admin account.")
return redirect(url_for("login")) return redirect(url_for("login"))
return render_template("admin/index.html", title="Admin") return render_template("admin/index.html", title="Admin")

View File

@ -1,10 +1,12 @@
from flask import Blueprint, render_template, request, make_response, current_app import datetime
from flask_login import login_required
from urllib import parse
import filetype
import os, pytz, datetime
import inspect import inspect
import os
from urllib import parse
import filetype
import pytz
from flask import Blueprint, current_app, make_response, render_template, request
from flask_login import login_required
from scripts import database, func from scripts import database, func
@ -16,145 +18,195 @@ MOBILE_DEVICES = ["android", "blackberry", "ipad", "iphone"]
@Comics.route("/comics") @Comics.route("/comics")
@login_required @login_required
def index(): def index():
try: try:
page = request.args.get("page", 1, type=int) page = request.args.get("page", 1, type=int)
max_items = request.args.get("max_items", 30, type=int) max_items = request.args.get("max_items", 30, type=int)
publishers = database.get_publishers() publishers = database.get_publishers()
start = (max_items*(page-1)) start = max_items * (page - 1)
end = len(publishers) if len(publishers) < max_items*page else max_items*page end = len(publishers) if len(publishers) < max_items * page else max_items * page
return render_template("comics/index.html", title="Comics", publishers=publishers, page=page, max_items=max_items, start=start, end=end, item_count=len(publishers)) return render_template(
except Exception as e: "comics/index.html",
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) title="Comics",
return str(type(e)) + " " + str(e) publishers=publishers,
page=page,
max_items=max_items,
start=start,
end=end,
item_count=len(publishers),
)
except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e)) + " " + str(e)
@Comics.route("/comics/search") @Comics.route("/comics/search")
@login_required @login_required
def search(): def search():
try: try:
page = request.args.get("page", 1, type=int) page = request.args.get("page", 1, type=int)
max_items = request.args.get("max_items", 30, type=int) max_items = request.args.get("max_items", 30, type=int)
publisher_end = 0 publisher_end = 0
series_end = 0 series_end = 0
comics_end = 0 comics_end = 0
publisher_start = 0 publisher_start = 0
series_start = 0 series_start = 0
comics_start = 0 comics_start = 0
item_count = 0 item_count = 0
query = request.args.get("q") query = request.args.get("q")
results = { results = {"publisher": [], "series": [], "comics": []}
"publisher": [], if query:
"series": [], results = database.db_search_comics(query)
"comics": [] item_count = len(results["publisher"]) + len(results["series"]) + len(results["comics"])
} for temp_page in range(1, page + 1):
if query: publisher_start = publisher_end
results = database.db_search_comics(query) series_start = series_end
item_count = len(results["publisher"]) + len(results["series"]) + len(results["comics"]) comics_start = comics_end
for temp_page in range(1, page+1): items = 0
publisher_start = publisher_end publisher_end = len(results["publisher"]) if len(results["publisher"]) < max_items * temp_page else max_items * temp_page
series_start = series_end items += publisher_end - publisher_start
comics_start = comics_end if items < max_items:
items = 0 series_end = (
publisher_end = len(results["publisher"]) if len(results["publisher"]) < max_items*temp_page else max_items*temp_page len(results["series"]) if len(results["series"]) < (max_items * temp_page) - items else (max_items * temp_page) - items
items += publisher_end - publisher_start )
if items < max_items: items += series_end - series_start
series_end = len(results["series"]) if len(results["series"]) < (max_items*temp_page)-items else (max_items*temp_page)-items if items < max_items:
items += series_end-series_start comics_end = (
if items < max_items: len(results["comics"])
comics_end = len(results["comics"]) if len(results["comics"]) < (max_items*temp_page)-series_end-publisher_end else (max_items*temp_page)-series_end-publisher_end if len(results["comics"]) < (max_items * temp_page) - series_end - publisher_end
return render_template("comics/search.html", title="Comics: Search", publishers=results["publisher"], publisher_series=results["series"], else (max_items * temp_page) - series_end - publisher_end
comics=results["comics"], page=page, max_items=max_items, item_count=item_count, )
publisher_start=publisher_start, series_start=series_start, comics_start=comics_start, return render_template(
publisher_end=publisher_end, series_end=series_end, comics_end=comics_end) "comics/search.html",
except Exception as e: title="Comics: Search",
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) publishers=results["publisher"],
return str(type(e))+" "+str(e) publisher_series=results["series"],
comics=results["comics"],
page=page,
max_items=max_items,
item_count=item_count,
publisher_start=publisher_start,
series_start=series_start,
comics_start=comics_start,
publisher_end=publisher_end,
series_end=series_end,
comics_end=comics_end,
)
except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e)) + " " + str(e)
@Comics.route("/comics/<publisher>") @Comics.route("/comics/<publisher>")
@login_required @login_required
def comics_publisher(publisher): def comics_publisher(publisher):
try: try:
publisher = parse.unquote(publisher) publisher = parse.unquote(publisher)
series = request.args.get("series") series = request.args.get("series")
series_year = request.args.get("seriesYear") series_year = request.args.get("seriesYear")
issue = request.args.get("issue") issue = request.args.get("issue")
page_number = request.args.get("pageNumber") page_number = request.args.get("pageNumber")
page = request.args.get("page", 1, type=int) page = request.args.get("page", 1, type=int)
max_items = request.args.get("max_items", 30, type=int) max_items = request.args.get("max_items", 30, type=int)
publisher_series = database.db_get_series_by_publisher(publisher) publisher_series = database.db_get_series_by_publisher(publisher)
start = (max_items*(page-1)) start = max_items * (page - 1)
end = len(publisher_series) if len(publisher_series) < max_items*page else max_items*page end = len(publisher_series) if len(publisher_series) < max_items * page else max_items * page
if series: if series:
comics = database.db_get_comics_in_series(series, publisher, series_year) comics = database.db_get_comics_in_series(series, publisher, series_year)
start = (max_items * (page - 1)) start = max_items * (page - 1)
end = len(comics) if len(comics) < max_items * page else max_items * page end = len(comics) if len(comics) < max_items * page else max_items * page
if issue: if issue:
return comic_gallery(publisher, series, series_year, issue) return comic_gallery(publisher, series, series_year, issue)
comics_dict = [] comics_dict = []
for i in comics: for i in comics:
item = i.__dict__ item = i.__dict__
item.pop('_sa_instance_state', None) item.pop("_sa_instance_state", None)
item.pop('path', None) item.pop("path", None)
comics_dict.append(item) comics_dict.append(item)
return render_template("comics/seriesView.html", title="Comics", comics=comics_dict, return render_template(
start=start, end=end, page=page, max_items=max_items, item_count=len(comics)) "comics/seriesView.html",
pub_series_dict = [] title="Comics",
for i in publisher_series: comics=comics_dict,
item = i.__dict__ start=start,
item.pop('_sa_instance_state', None) end=end,
item.pop('path', None) page=page,
pub_series_dict.append(item) max_items=max_items,
return render_template("comics/publisherSeriesView.html", title="Comics", publisher_series=pub_series_dict, item_count=len(comics),
start=start, end=end, page=page, max_items=max_items, item_count=len(publisher_series)) )
except Exception as e: pub_series_dict = []
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) for i in publisher_series:
return str(type(e)) + " " + str(e) item = i.__dict__
item.pop("_sa_instance_state", None)
item.pop("path", None)
pub_series_dict.append(item)
return render_template(
"comics/publisherSeriesView.html",
title="Comics",
publisher_series=pub_series_dict,
start=start,
end=end,
page=page,
max_items=max_items,
item_count=len(publisher_series),
)
except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e)) + " " + str(e)
@Comics.route("/comics/<int:comic_id>") @Comics.route("/comics/<int:comic_id>")
@login_required @login_required
def comic_gallery(comic_id): def comic_gallery(comic_id):
try: try:
page = request.args.get("page", 1, type=int) page = request.args.get("page", 1, type=int)
max_items = request.args.get("max_items", 30, type=int) max_items = request.args.get("max_items", 30, type=int)
meta = database.db_get_comic(comic_id) meta = database.db_get_comic(comic_id)
start = (max_items*(page-1)) start = max_items * (page - 1)
end = meta.pagecount if meta.pagecount < max_items*page else max_items*page end = meta.pagecount if meta.pagecount < max_items * page else max_items * page
comic_dict = meta.__dict__ comic_dict = meta.__dict__
comic_dict.pop('_sa_instance_state', None) comic_dict.pop("_sa_instance_state", None)
comic_dict.pop('path', None) comic_dict.pop("path", None)
return render_template("comics/comicGallery.html", title="Comics", comic=comic_dict, start=start, end=end, page=page, max_items=max_items, item_count=meta.pagecount) return render_template(
except Exception as e: "comics/comicGallery.html",
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) title="Comics",
return str(type(e)) + " " + str(e) comic=comic_dict,
start=start,
end=end,
page=page,
max_items=max_items,
item_count=meta.pagecount,
)
except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e)) + " " + str(e)
@Comics.route("/comics/get_comic/<int:comic_id>/<int:page_number>") @Comics.route("/comics/get_comic/<int:comic_id>/<int:page_number>")
@login_required @login_required
def get_comic_page(comic_id, page_number): def get_comic_page(comic_id, page_number):
meta = database.db_get_comic_by_id(comic_id) meta = database.db_get_comic_by_id(comic_id)
comic = func.open_comic(meta.path) comic = func.open_comic(meta.path)
byte_image = comic.getPage(page_number) byte_image = comic.getPage(page_number)
type = filetype.guess(byte_image).mime type = filetype.guess(byte_image).mime
response = make_response(byte_image) response = make_response(byte_image)
response.headers["content-type"] = type response.headers["content-type"] = type
response.headers["cache-control"] = "public" response.headers["cache-control"] = "public"
date = pytz.utc.localize(datetime.datetime.utcfromtimestamp(os.path.getmtime(meta.path))) date = pytz.utc.localize(datetime.datetime.utcfromtimestamp(os.path.getmtime(meta.path)))
response.headers["last-modified"] = date.strftime('%a, %d %b %Y %H:%M:%S %Z') response.headers["last-modified"] = date.strftime("%a, %d %b %Y %H:%M:%S %Z")
response.headers["Content-Disposition"] = "attachment; filename=\"{} {}_{}{}\"".format(str(meta.series), meta.issuetext, str(page_number), filetype.guess(byte_image).extension) response.headers["Content-Disposition"] = 'attachment; filename="{} {}_{}{}"'.format(
return response str(meta.series), meta.issuetext, str(page_number), filetype.guess(byte_image).extension
)
return response
@Comics.route("/comics/get_comic/<int:comic_id>/<int:page_number>/thumbnail") @Comics.route("/comics/get_comic/<int:comic_id>/<int:page_number>/thumbnail")
@login_required @login_required
def get_comic_thumbnail(comic_id, page_number): def get_comic_thumbnail(comic_id, page_number):
meta = database.db_get_comic_by_id(comic_id) meta = database.db_get_comic_by_id(comic_id)
thumb = database.db_get_thumbnail_by_id_page(comic_id, page_number) thumb = database.db_get_thumbnail_by_id_page(comic_id, page_number)
response = make_response(thumb.image) response = make_response(thumb.image)
response.headers["cache-control"] = "public" response.headers["cache-control"] = "public"
date = pytz.utc.localize(datetime.datetime.utcfromtimestamp(os.path.getmtime(meta.path))) date = pytz.utc.localize(datetime.datetime.utcfromtimestamp(os.path.getmtime(meta.path)))
response.headers["last-modified"] = date.strftime('%a, %d %b %Y %H:%M:%S %Z') response.headers["last-modified"] = date.strftime("%a, %d %b %Y %H:%M:%S %Z")
response.headers["content-type"] = thumb.type response.headers["content-type"] = thumb.type
response.headers["Content-Disposition"] = "attachment; filename=\"{} {}_{}_thumbnail\"".format(str(meta.series), meta.issuetext, str(page_number)) response.headers["Content-Disposition"] = 'attachment; filename="{} {}_{}_thumbnail"'.format(str(meta.series), meta.issuetext, str(page_number))
return response return response

View File

@ -117,7 +117,7 @@
page_container.innerHTML = ""; page_container.innerHTML = "";
for (i = start;i < end; i++) { for (i = start;i < end; i++) {
var list_element = `<div style="margin: auto" class="comic-thumbnail card bg-dark text-white"> var list_element = `<div style="margin: auto" class="comic-thumbnail card bg-dark text-white">
<img src="/comics/get_comic/${comic.id}/${i}/thumbnail" alt="" style="display: inline" onerror="this.src='/static/images/default.png';this.height='256'" onclick="openLightBox();currentImage(${1+i})"> <img src="/comics/get_comic/${comic.id}/${i}/thumbnail" alt="" style="display: inline" onerror="this.src='/static/images/default.png';this.height='256'" onclick="openLightBox();currentImage(${1+i});load_next_image(${i});">
<p class="card-text">${1+i}/${comic.pagecount}</p> <p class="card-text">${1+i}/${comic.pagecount}</p>
</div>`; </div>`;
page_container.innerHTML += list_element; page_container.innerHTML += list_element;
@ -134,15 +134,24 @@
let next_image = document.getElementById("next"); let next_image = document.getElementById("next");
let prev_image = document.getElementById("prev"); let prev_image = document.getElementById("prev");
for (let i=0; i<{{ item_count }};i++) {
light_box_content.innerHTML += `<div class="images" style="display: none"></div>`
}
function load_next_image(page_number) { function load_next_image(page_number) {
if (document.getElementById(page_number.toString())) {return;} if (document.getElementById(page_number.toString())) {return;}
if (page_number >= page_count) {return;} if (page_number >= page_count) {return;}
console.log("start loading: page "+(page_number+1).toString()); console.log("start loading: page "+(page_number+1).toString());
let image = '<div class="images">'; let image = '<div class="images" style="display: none">';
image += `<div class="numbertext">${1 + page_number} / ${page_count}</div>`; image += `<div class="numbertext">${1 + page_number} / ${page_count}</div>`;
image += `<img id="${page_number}" style="width: 100%" src="/comics/get_comic/${comic_id}/${page_number}" alt="" onerror="this.src=\'/static/images/default.png\';load_next_image(${page_number + 1})" ondragstart="return false" onload="load_next_image(${page_number + 1})">`; image += `<img id="${page_number}" style="width: 100%" src="/comics/get_comic/${comic_id}/${page_number}" alt="" onerror="this.src=\'/static/images/default.png\';load_next_image(${page_number + 1})" ondragstart="return false" onload="load_next_image(${page_number + 1})">`;
image += '</div>'; image += '</div>';
light_box_content.innerHTML += image; {#light_box_content.innerHTML += image;#}
var slides = document.getElementsByClassName("images");
slides[page_number].outerHTML = image
if (imageIndex == page_number+1) {
currentImage(page_number+1)
}
} }
// Open the Modal // Open the Modal
@ -202,4 +211,6 @@
}); });
load_next_image(0); load_next_image(0);
</script> </script>
<script type="text/python">
</script>
{% endblock %} {% endblock %}

View File

@ -1,10 +1,9 @@
from flask import Blueprint, render_template, request, send_file, current_app, jsonify, abort
from flask_login import login_required
from pathvalidate import sanitize_filename
import os
import inspect import inspect
import re import json
import os
from flask import Blueprint, abort, current_app, jsonify, render_template, request, send_file
from flask_login import login_required
from scripts import database, func from scripts import database, func
@ -14,78 +13,157 @@ Games = Blueprint("games", __name__, template_folder="templates")
@Games.route("/games") @Games.route("/games")
@login_required @login_required
def index(): def index():
try: try:
page = request.args.get("page", 1, type=int) page = request.args.get("page", 1, type=int)
max_items = request.args.get("max_items", 30, type=int) max_items = request.args.get("max_items", 30, type=int)
games = database.get_all_games() games = database.get_all_games()
start = (max_items*(page-1)) start = max_items * (page - 1)
end = len(games) if len(games) < max_items*page else max_items*page end = len(games) if len(games) < max_items * page else max_items * page
return render_template("games/index.html", title="Games", games=games) return render_template("games/index.html", title="Games", games=games)
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e)) + " " + str(e) return str(type(e)) + " " + str(e)
@Games.route('/games/get_games') @Games.route("/games/get_games")
@login_required @login_required
def get_games(): def get_games():
try: try:
games = database.get_all_games() games = database.get_all_games()
games_json = {} games_json = {}
for game in games: for game in games:
games_json[game.game_id] = { games_json[game.game_id] = {
"id": game.game_id, "id": game.game_id,
"title": game.title, "title": game.title,
"windows": game.windows, "description": game.description,
"mac": game.mac, "poster_path": game.poster_path,
"linux": game.linux, "windows": game.windows,
"description": game.description, "mac": game.mac,
"poster_path": game.poster_path "linux": game.linux,
} "title_sanitized": game.title_sanitized,
return jsonify(games_json) }
# return jsonify({game["id"]: game for game in games}) return jsonify(games_json)
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e)) + " " + str(e) return str(type(e)) + " " + str(e)
@Games.route('/games/get_game/<int:game_id>') @Games.route("/games/get_games/windows")
@login_required
def get_games_windows():
try:
games = database.get_windows_games()
games_json = {}
for game in games:
with open(os.path.join(game.path, "info.json")) as f:
info = json.load(f)
games_json[game.game_id] = {
"id": game.game_id,
"title": game.title,
"description": game.description,
"poster_path": game.poster_path,
"windows": {"executable": info["windows"]["executable"]},
"title_sanitized": game.title_sanitized,
}
return jsonify(games_json)
except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e)) + " " + str(e)
@Games.route("/games/get_games/mac")
@login_required
def get_games_mac():
try:
games = database.get_mac_games()
games_json = {}
for game in games:
with open(os.path.join(game.path, "info.json")) as f:
info = json.load(f)
games_json[game.game_id] = {
"id": game.game_id,
"title": game.title,
"description": game.description,
"poster_path": game.poster_path,
"title_sanitized": game.title_sanitized,
"mac": {},
}
if "executable" in info["mac"].keys():
games_json[game.game_id]["mac"] = {"executable": info["mac"]["executable"]}
return jsonify(games_json)
except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e)) + " " + str(e)
@Games.route("/games/get_games/linux")
@login_required
def get_games_linux():
try:
games = database.get_linux_games()
games_json = {}
for game in games:
with open(os.path.join(game.path, "info.json")) as f:
info = json.load(f)
games_json[game.game_id] = {
"id": game.game_id,
"title": game.title,
"description": game.description,
"poster_path": game.poster_path,
"title_sanitized": game.title_sanitized,
"linux": {"executable": info["linux"]["executable"]},
}
return jsonify(games_json)
except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e)) + " " + str(e)
@Games.route("/games/get_game/<int:game_id>")
@login_required @login_required
def get_game(game_id): def get_game(game_id):
try: try:
game = database.get_game(game_id) game = database.get_game(game_id)
if game: if game:
game_json = { with open(os.path.join(game.path, "info.json")) as f:
"title": game.title, info = json.load(f)
"game_id": game.game_id, windows = None
"description": game.description, mac = None
"poster_path": game.poster_path, linux = None
"windows": game.windows, if "windows" in info.keys():
"mac": game.mac, windows = info["windows"]
"linux": game.linux if "mac" in info.keys():
} mac = info["mac"]
return jsonify(game_json) if "linux" in info.keys():
abort(404) linux = info["linux"]
except Exception as e: game_json = {
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) "title": game.title,
return str(type(e)) + " " + str(e) "game_id": game.game_id,
"description": game.description,
"poster_path": game.poster_path,
"windows": windows,
"mac": mac,
"linux": linux,
"title_sanitized": game.title_sanitized,
}
return jsonify(game_json)
abort(404)
except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e)) + " " + str(e)
@Games.route("/games/download/<int:game_id>") @Games.route("/games/download_hash/<int:game_id>/<file_hash>")
@login_required @login_required
def download_game(game_id): def download_game_hash(game_id, file_hash):
try: try:
game = database.get_game(game_id) game = database.get_game(game_id)
if game: if game:
files = game.windows["files"] folder = game.path
filename = sanitize_filename(files[0]) path = os.path.join(folder, file_hash[:2], file_hash)
folder = re.match(r"(.+)_setup_win.(exe|msi)", filename).group(1) return send_file(path, as_attachment=True, attachment_filename=file_hash)
if len(files) > 1: else:
filename = sanitize_filename(game.title+".zip") abort(404)
path = os.path.join(func.GAMES_DIRECTORY, folder, filename) except Exception as e:
return send_file(path, as_attachment=True, attachment_filename=filename) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
else: return str(type(e)) + " " + str(e)
abort(404)
except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e)) + " " + str(e)

View File

@ -2,7 +2,7 @@
{% block content %} {% block content %}
{% for game in games %} {% for game in games %}
<a class="btn btn-primary" href="{{ url_for("games.index") }}/download/{{ game.game_id }}">Download</a> <a class="btn btn-primary" href="{{ url_for("games.index") }}/download/windows/{{ game.game_id }}" download>Download</a>
<p>{{ game.title }} - {{ game.game_id }}</p> <p>{{ game.title }} - {{ game.game_id }}</p>
{% endfor %} {% endfor %}
{% endblock %} {% endblock %}

View File

@ -1,47 +1,48 @@
from flask import Flask import base64
from flask import render_template, request, g, redirect, url_for, flash, current_app, Response import datetime
from flask_login import LoginManager, current_user, login_user, logout_user, login_required import inspect
import json
import logging
import os
import pathlib
import threading
from urllib.parse import urljoin, urlsplit, urlunsplit
import inotify.adapters
import inotify.constants
import requests
from flask import Flask, Response, current_app, flash, g, redirect, render_template, request, url_for
from flask_login import LoginManager, current_user, login_required, login_user, logout_user
from oauthlib.oauth2 import WebApplicationClient from oauthlib.oauth2 import WebApplicationClient
import threading
import logging
import inotify.adapters, inotify.constants
import inspect
import datetime
import requests
import json
import os
import base64
import scripts.func as func import scripts.func as func
from scripts import database
from admin import admin from admin import admin
from comics import comics from comics import comics
from tv_movies import tv_movies
from games import games from games import games
from scripts import database
from tv_movies import tv_movies
class NullHandler(logging.Handler): class NullHandler(logging.Handler):
def emit(self, record=None): def emit(self, record=None):
pass pass
def debug(self, *arg):
pass
def debug(self, *arg):
pass
nullLog = NullHandler() nullLog = NullHandler()
inotify.adapters._LOGGER = nullLog inotify.adapters._LOGGER = nullLog
GOOGLE_CLIENT_ID = "***REMOVED***" GOOGLE_CLIENT_ID = "***REMOVED***"
GOOGLE_CLIENT_SECRET = "***REMOVED***" GOOGLE_CLIENT_SECRET = "***REMOVED***"
GOOGLE_DISCOVERY_URL = ( GOOGLE_DISCOVERY_URL = "https://accounts.google.com/.well-known/openid-configuration"
"https://accounts.google.com/.well-known/openid-configuration"
)
client = WebApplicationClient(GOOGLE_CLIENT_ID) client = WebApplicationClient(GOOGLE_CLIENT_ID)
def get_google_provider_cfg(): def get_google_provider_cfg():
return requests.get(GOOGLE_DISCOVERY_URL).json() return requests.get(GOOGLE_DISCOVERY_URL).json()
app = Flask(__name__) app = Flask(__name__)
@ -54,7 +55,7 @@ app.logger.setLevel("DEBUG")
# app.use_x_sendfile = True # app.use_x_sendfile = True
login_manager = LoginManager(app) login_manager = LoginManager(app)
login_manager.login_view = "login" # login_manager.login_view = "login"
app.config["REMEMBER_COOKIE_DOMAIN"] = "narnian.us" app.config["REMEMBER_COOKIE_DOMAIN"] = "narnian.us"
@ -62,101 +63,135 @@ MOBILE_DEVICES = ["android", "blackberry", "ipad", "iphone"]
def get_comics(): def get_comics():
with app.app_context(): with app.app_context():
i = inotify.adapters.InotifyTree(func.COMICS_DIRECTORY) i = inotify.adapters.InotifyTree(func.COMICS_DIRECTORY)
func.get_comics() new_dirs = []
for event in i.event_gen(yield_nones=False): func.get_comics()
(header, type_names, path, filename) = event while True:
file_path = os.path.join(path, filename) for event in i.event_gen(timeout_s=5*60, yield_nones=False):
if "IN_CLOSE_WRITE" in type_names or "IN_MOVED_TO" in type_names: (header, type_names, path, filename) = event
func.get_comic(file_path) file_path = pathlib.Path(path, filename)
if "IN_CLOSE_WRITE" in type_names or "IN_MOVED_TO" in type_names:
func.get_comic(file_path)
elif "IN_CREATE" in type_names:
if file_path.is_dir():
new_dirs.append(file_path)
for new_dir in new_dirs:
for file in new_dir.glob("*"):
func.get_comic(file)
new_dirs.clear()
def get_movies(): def get_movies():
with app.app_context(): with app.app_context():
i = inotify.adapters.InotifyTree(func.MOVIES_DIRECTORY) i = inotify.adapters.InotifyTree(func.MOVIES_DIRECTORY)
func.get_movies()
for event in i.event_gen(yield_nones=False): func.get_movies()
(header, type_names, path, filename) = event
file_path = os.path.join(path, filename) for event in i.event_gen(yield_nones=False):
if "IN_CLOSE_WRITE" in type_names or "IN_MOVED_TO" in type_names: (header, type_names, path, filename) = event
func.get_movie(file_path) file_path = pathlib.Path(path, filename)
if "IN_CLOSE_WRITE" in type_names or "IN_MOVED_TO" in type_names:
func.get_movie(file_path)
def get_tv_shows(): def get_tv_shows():
with app.app_context(): with app.app_context():
i = inotify.adapters.InotifyTree(func.TV_SHOWS_DIRECTORY) i = inotify.adapters.InotifyTree(func.TV_SHOWS_DIRECTORY)
func.get_tv_shows() func.get_tv_shows()
func.get_tv_episodes() func.get_tv_episodes()
for event in i.event_gen(yield_nones=False): for event in i.event_gen(yield_nones=False):
(header, type_names, path, filename) = event (header, type_names, path, filename) = event
file_path = os.path.join(path, filename) file_path = pathlib.Path(path, filename)
if "IN_CLOSE_WRITE" in type_names or "IN_MOVED_TO" in type_names: if "IN_CLOSE_WRITE" in type_names or "IN_MOVED_TO" in type_names:
func.get_tv_shows() if file_path.is_dir():
func.get_tv_episode(file_path) func.get_tv_shows()
else:
func.get_tv_episode(file_path)
def get_games(): def get_games():
with app.app_context(): with app.app_context():
func.get_games() i = inotify.adapters.Inotify()
i.add_watch(func.GAMES_DIRECTORY)
for directory in os.listdir(func.GAMES_DIRECTORY):
path = pathlib.Path(func.GAMES_DIRECTORY, directory)
if path.is_dir():
i.add_watch(str(path))
func.get_games()
func.update_games()
for event in i.event_gen(yield_nones=False):
(header, type_names, path, filename) = event
file_path = pathlib.Path(path, filename)
if "IN_CLOSE_WRITE" in type_names or "IN_MOVED_TO" in type_names:
func.get_game(file_path)
elif "IN_CREATE" in type_names:
if file_path.is_dir() and len(file_path.name) > 2:
i.add_watch(str(file_path))
elif "IN_DELETE_SELF" in type_names:
if file_path.is_dir():
i.remove_watch(file_path)
with app.app_context(): with app.app_context():
current_app.logger.info("server start") current_app.logger.info("server start")
thread = threading.Thread(target=get_comics, args=()) thread = threading.Thread(target=get_comics, args=())
thread.daemon = True thread.daemon = True
thread.start() thread.start()
thread2 = threading.Thread(target=get_movies, args=()) thread2 = threading.Thread(target=get_movies, args=())
thread2.daemon = True thread2.daemon = True
thread2.start() thread2.start()
thread3 = threading.Thread(target=get_tv_shows, args=()) thread3 = threading.Thread(target=get_tv_shows, args=())
thread3.daemon = True thread3.daemon = True
thread3.start() thread3.start()
thread4 = threading.Thread(target=get_games, args=()) thread4 = threading.Thread(target=get_games, args=())
thread4.daemon = True thread4.daemon = True
thread4.start() thread4.start()
@app.teardown_appcontext @app.teardown_appcontext
def close_connection(exception): def close_connection(exception):
db = getattr(g, '_database', None) db = getattr(g, "_database", None)
if db is not None: if db is not None:
db.close() db.close()
def update_comic_db(sender, **kw): def update_comic_db(sender, **kw):
try: try:
database.add_comics(kw["meta"], kw["thumbnails"]) database.add_comics(kw["meta"], kw["thumbnails"])
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
def update_movie_db(sender, **kw): def update_movie_db(sender, **kw):
try: try:
database.add_movies(kw["movies"]) database.add_movies(kw["movies"])
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
def update_tv_show_db(sender, **kw): def update_tv_show_db(sender, **kw):
try: try:
database.add_tv_shows(kw["tv_show"]) database.add_tv_shows(kw["tv_show"])
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
def update_tv_episodes_db(sender, **kw): def update_tv_episodes_db(sender, **kw):
try: try:
database.add_tv_episodes(kw["tv_episodes"]) database.add_tv_episodes(kw["tv_episodes"])
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
def update_games_db(sender, **kw): def update_games_db(sender, **kw):
try: try:
database.add_games(kw["games"]) database.add_games(kw["games"])
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
func.comic_loaded.connect(update_comic_db) func.comic_loaded.connect(update_comic_db)
@ -168,177 +203,183 @@ func.games_loaded.connect(update_games_db)
@login_manager.user_loader @login_manager.user_loader
def load_user(email): def load_user(email):
try: try:
return database.get_user(email) return database.get_user(email)
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) return str(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
@login_manager.request_loader @login_manager.request_loader
def load_user_from_request(request): def load_user_from_request(request):
try: try:
api_key = request.headers.get('Authorization') api_key = request.headers.get("Authorization")
if api_key: if api_key:
api_key = api_key.replace('Basic ', '', 1) api_key = api_key.replace("Basic ", "", 1)
try: try:
api_key = base64.b64decode(api_key).decode("utf-8") api_key = base64.b64decode(api_key).decode("utf-8")
except TypeError: except TypeError:
pass pass
email = api_key.split(":")[0] email = api_key.split(":")[0]
password = api_key.split(":")[1] password = api_key.split(":")[1]
user = load_user(email) user = load_user(email)
if user and user.check_password(password): if user and user.check_password(password):
return user return user
return None return None
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) return str(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
@app.route("/login", methods=["GET", "POST"]) @app.route("/login", methods=["GET", "POST"])
def login(): def login():
try: try:
google_provider_cfg = get_google_provider_cfg() url = urlsplit(request.url)
authorization_endpoint = google_provider_cfg["authorization_endpoint"] google_redirect = urlunsplit(("", "", url.path, url.query, ""))
next_page = google_redirect
if "login" in url.path:
next_page = url_for("home")
if request.args.get("url", default=None):
next_page = request.args.get("url", default=None)
request_uri = client.prepare_request_uri( google_provider_cfg = get_google_provider_cfg()
authorization_endpoint, authorization_endpoint = google_provider_cfg["authorization_endpoint"]
redirect_uri=request.base_url + "/callback",
scope=["openid", "email", "profile"],
)
if request.method == "POST": request_uri = client.prepare_request_uri(
email = request.form.get("email") authorization_endpoint,
password = request.form.get("password") redirect_uri=urljoin(request.host_url, url_for("callback")),
user = database.get_user(email) scope=["openid", "email", "profile"],
if user is None or not user.check_password(password): state=next_page,
flash("invalid email or password") hd="narnian.us",
return redirect(url_for("login")) )
login_user(user, remember=True, duration=datetime.timedelta(days=7))
next_page = request.args.get("next") if request.method == "POST":
if not next_page: email = request.form.get("email")
next_page = url_for("home") password = request.form.get("password")
return redirect(next_page) user = database.get_user(email)
return render_template("login.html", title="login", auth_url=request_uri) if user is None or not user.check_password(password):
except Exception as e: flash("invalid email or password")
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) return redirect(url_for("login"))
return str(e) login_user(user, remember=True, duration=datetime.timedelta(days=7))
return redirect(next_page)
return render_template("login.html", title="login", auth_url=request_uri)
except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(e)
@app.route("/login/callback") @app.route("/login/callback")
def callback(): def callback():
try: try:
# Get authorization code Google sent back to you # Get authorization code Google sent back to you
code = request.args.get("code") code = request.args.get("code")
google_provider_cfg = get_google_provider_cfg() google_provider_cfg = get_google_provider_cfg()
token_endpoint = google_provider_cfg["token_endpoint"] token_endpoint = google_provider_cfg["token_endpoint"]
token_url, headers, body = client.prepare_token_request( token_url, headers, body = client.prepare_token_request(
token_endpoint, token_endpoint, authorization_response=request.url, redirect_url=request.base_url, code=code
authorization_response=request.url, )
redirect_url=request.base_url, token_response = requests.post(token_url, headers=headers, data=body, auth=(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET))
code=code
)
token_response = requests.post(
token_url,
headers=headers,
data=body,
auth=(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET)
)
client.parse_request_body_response(json.dumps(token_response.json())) client.parse_request_body_response(json.dumps(token_response.json()))
userinfo_endpoint = google_provider_cfg["userinfo_endpoint"] userinfo_endpoint = google_provider_cfg["userinfo_endpoint"]
uri, headers, body = client.add_token(userinfo_endpoint) uri, headers, body = client.add_token(userinfo_endpoint)
userinfo_response = requests.get(uri, headers=headers, data=body) userinfo_response = requests.get(uri, headers=headers, data=body)
if userinfo_response.json().get("email_verified"): if userinfo_response.json().get("email_verified"):
unique_id = userinfo_response.json()["sub"] unique_id = userinfo_response.json()["sub"]
users_email = userinfo_response.json()["email"] users_email = userinfo_response.json()["email"]
users_name = userinfo_response.json()["given_name"] users_name = userinfo_response.json()["given_name"]
else: else:
return "User email not available or not verified by Google.", 400 return "User email not available or not verified by Google.", 400
data = (unique_id, users_name, users_email, None, False) data = (unique_id, users_name, users_email, None, False)
current_app.logger.info("user data from google: " + str(data)) current_app.logger.info("user data from google: " + str(data))
user = database.get_user(users_email) user = database.get_user(users_email)
if not user: if not user:
user = database.add_user(data) user = database.add_user(data)
current_app.logger.info("new user: {} created".format(users_email)) current_app.logger.info("new user: {} created".format(users_email))
current_app.logger.info("email: "+str(user.email)) current_app.logger.info("email: " + str(user.email))
current_app.logger.info("username: "+str(user.username)) current_app.logger.info("username: " + str(user.username))
current_app.logger.info("authenticated: "+str(user.is_authenticated)) current_app.logger.info("authenticated: " + str(user.is_authenticated))
current_app.logger.info("active: "+str(user.is_active)) current_app.logger.info("active: " + str(user.is_active))
current_app.logger.info("id: "+str(user.get_id())) current_app.logger.info("id: " + str(user.get_id()))
login_user(user, remember=True, duration=datetime.timedelta(days=7), force=True) login_user(user, remember=True, duration=datetime.timedelta(days=7), force=True)
return redirect(url_for("home")) return redirect(request.args.get("state"))
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(e) return str(e)
@app.route("/logout") @app.route("/logout")
def logout(): def logout():
try: try:
logout_user() logout_user()
return redirect(url_for("login")) return redirect(url_for("login"))
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(e) return str(e)
@app.route("/") @app.route("/")
def root(): def root():
return redirect(url_for("home")) return redirect(url_for("home"))
@app.route("/home") @app.route("/home")
@login_required @login_required
def home(): def home():
try: try:
return render_template("home.html", title="Home", current_user=current_user) return render_template("home.html", title="Home", current_user=current_user)
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(e) return str(e)
@app.after_request @app.after_request
def apply_headers(response: Response): def apply_headers(response: Response):
try: try:
user_name = "anonymous" user_name = "anonymous"
if current_user: if current_user:
user_name = getattr(current_user, "email", "anonymous") user_name = getattr(current_user, "email", "anonymous")
response.set_cookie("rpi_name", user_name) response.set_cookie("rpi_name", user_name)
return response response.headers.set("email", user_name)
except Exception as e: return response
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) except Exception as e:
return str(e) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(e)
@app.route("/music") @app.route("/music")
@login_required @login_required
def music(): def music():
return "No music" return "No music"
@app.errorhandler(404) @app.errorhandler(404)
def resource_not_found(e): def resource_not_found(e):
try: try:
return render_template("404.html"), 404 return render_template("404.html"), 404
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(e) return str(e)
@login_manager.unauthorized_handler
def handle_unauthorized():
temp = login()
return temp, 401
@app.errorhandler(Exception) @app.errorhandler(Exception)
def handle_exception(e): def handle_exception(e):
return render_template("error.html", e=e), 500 return render_template("error.html", e=e), 500
games.Games.register_error_handler(404, resource_not_found) games.Games.register_error_handler(404, resource_not_found)
@ -351,5 +392,5 @@ comics.Comics.register_error_handler(Exception, handle_exception)
admin.Admin.register_error_handler(Exception, handle_exception) admin.Admin.register_error_handler(Exception, handle_exception)
if __name__ == '__main__': if __name__ == "__main__":
app.run() app.run()

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,8 @@
import os
import sqlite3
from io import BytesIO from io import BytesIO
from wand.image import Image
import sqlite3, os
from wand.image import Image
RPI_DATABASE = "/var/lib/rpiWebApp/database.db" RPI_DATABASE = "/var/lib/rpiWebApp/database.db"
@ -15,32 +16,35 @@ db.row_factory = sqlite3.Row
def resize_image(image, new_width=256, new_height=256): def resize_image(image, new_width=256, new_height=256):
new_image = image new_image = image
orig_height = new_image.height orig_height = new_image.height
orig_width = new_image.width orig_width = new_image.width
if orig_height >= orig_width: if orig_height >= orig_width:
width = int((orig_width/orig_height) * new_height) width = int((orig_width / orig_height) * new_height)
height = new_height height = new_height
else: else:
height = int((orig_height/orig_width) * new_width) height = int((orig_height / orig_width) * new_width)
width = new_width width = new_width
new_image.thumbnail(width, height) new_image.thumbnail(width, height)
return new_image return new_image
def fix_thumbnails(): def fix_thumbnails():
new_height = 256 new_height = 256
new_width = 256 new_width = 256
print("Start fix thumbnail size") print("Start fix thumbnail size")
rows = db.execute("SELECT * FROM comic_thumbnails") rows = db.execute("SELECT * FROM comic_thumbnails")
print("got list of all thumbnails\n") print("got list of all thumbnails\n")
for row in rows: for row in rows:
image = Image(file=BytesIO(row["image"])) image = Image(file=BytesIO(row["image"]))
if image.width > new_width or image.height > new_height: if image.width > new_width or image.height > new_height:
print("id:", row["id"], "pageNumber:", row["pageNumber"]) print("id:", row["id"], "pageNumber:", row["pageNumber"])
db.execute("UPDATE comic_thumbnails SET image=? WHERE id=? AND pageNumber=?", [resize_image(image, new_width, new_height).make_blob(), row["id"], row["pageNumber"]]) db.execute(
db.commit() "UPDATE comic_thumbnails SET image=? WHERE id=? AND pageNumber=?",
[resize_image(image, new_width, new_height).make_blob(), row["id"], row["pageNumber"]],
)
db.commit()
fix_thumbnails() fix_thumbnails()

View File

@ -1,15 +1,17 @@
from flask import current_app
from comicapi import comicarchive
from blinker import Namespace
from datetime import timedelta
from io import BytesIO
from wand.image import Image
import os, re
import inspect import inspect
import json import json
import os
import pathlib
import re
from datetime import timedelta
from io import BytesIO
import enzyme import enzyme
import requests import requests
from blinker import Namespace
from comicapi import comicarchive
from flask import current_app
from wand.image import Image
from scripts import database from scripts import database
@ -22,6 +24,8 @@ games_loaded = rpi_signals.signal("games_loaded")
publishers_to_ignore = ["***REMOVED***"] publishers_to_ignore = ["***REMOVED***"]
API_KEY = "***REMOVED***"
# Directories # Directories
RPI_COMICS_DIRECTORY = "/usb/storage/media/Comics/" RPI_COMICS_DIRECTORY = "/usb/storage/media/Comics/"
@ -45,434 +49,555 @@ GAMES_DIRECTORY = RPI_GAMES_DIRECTORY if os.path.exists(RPI_GAMES_DIRECTORY) els
def get_comics(): def get_comics():
total_comics = 0 total_comics = 0
comics_in_db = 0 comics_in_db = 0
comics_added = 0 comics_added = 0
meta = [] meta = []
thumbnails = [] thumbnails = []
i = 0 i = 0
for root, dirs, files in os.walk(COMICS_DIRECTORY): for root, dirs, files in os.walk(COMICS_DIRECTORY):
for f in files: for f in files:
if "temp" in root: if "temp" in root:
continue continue
if f.endswith(".cbr"): if f.endswith(".cbr"):
total_comics += 1 total_comics += 1
path = os.path.join(root, f) path = os.path.join(root, f)
if not database.comic_path_in_db(path): if not database.comic_path_in_db(path):
try: try:
test_path = path.encode("utf8") test_path = path.encode("utf8")
except Exception as e: except Exception as e:
current_app.logger.info("encoding failed on: "+path) current_app.logger.info("encoding failed on: " + path)
continue continue
archive = open_comic(path) archive = open_comic(path)
md = archive.readCIX() md = archive.readCIX()
if md.publisher in publishers_to_ignore: if md.publisher in publishers_to_ignore:
continue continue
current_app.logger.info(path) current_app.logger.info(path)
try: try:
meta.append((path, md)) meta.append((path, md))
thumbnails.append(get_comic_thumbnails(archive)) thumbnails.append(get_comic_thumbnails(archive))
comics_added += 1 comics_added += 1
i += 1 i += 1
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
continue continue
if i >= 2: if i >= 2:
comic_loaded.send("anonymous", meta=meta.copy(), thumbnails=thumbnails.copy()) comic_loaded.send("anonymous", meta=meta.copy(), thumbnails=thumbnails.copy())
meta.clear() meta.clear()
thumbnails.clear() thumbnails.clear()
i = 0 i = 0
comics_in_db += 1 comics_in_db += 1
current_app.logger.info("total number of comics: "+str(total_comics)) current_app.logger.info("total number of comics: " + str(total_comics))
current_app.logger.info("comics in database: "+str(comics_in_db)) current_app.logger.info("comics in database: " + str(comics_in_db))
current_app.logger.info("number of comics added: "+str(comics_added)) current_app.logger.info("number of comics added: " + str(comics_added))
comic_loaded.send("anonymous", meta=meta, thumbnails=thumbnails) comic_loaded.send("anonymous", meta=meta, thumbnails=thumbnails)
def get_comic(path): def get_comic(path: pathlib.Path):
meta = [] meta = []
thumbnails = [] thumbnails = []
if path.endswith(".cbr"): if path.suffix == ".cbr":
if not database.comic_path_in_db(path): if not database.comic_path_in_db(str(path)):
try: try:
test_path = path.encode("utf8") test_path = str(path).encode("utf8")
except Exception as e: except Exception as e:
current_app.logger.info("encoding failed on: "+path) current_app.logger.info(f"encoding failed on: {path}")
return return
archive = open_comic(path) archive = open_comic(str(path))
md = archive.readCIX() md = archive.readCIX()
if md.publisher in publishers_to_ignore: if md.publisher in publishers_to_ignore:
return return
current_app.logger.info(path) current_app.logger.info(path)
meta.append((path, md)) meta.append((str(path), md))
try: try:
thumbnails.append(get_comic_thumbnails(archive)) thumbnails.append(get_comic_thumbnails(archive))
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return return
comic_loaded.send("anonymous", meta=meta, thumbnails=thumbnails) comic_loaded.send("anonymous", meta=meta, thumbnails=thumbnails)
def get_comic_thumbnails(comic): def get_comic_thumbnails(comic):
thumbnails = [] thumbnails = []
size = "256x256" size = "256x256"
new_height = 256 new_height = 256
new_width = 256 new_width = 256
for page in range(comic.getNumberOfPages()): for page in range(comic.getNumberOfPages()):
image_bytes = BytesIO(comic.getPage(page)) image_bytes = BytesIO(comic.getPage(page))
image = Image(file=image_bytes) image = Image(file=image_bytes)
orig_height = image.height orig_height = image.height
orig_width = image.width orig_width = image.width
if orig_height >= orig_width: if orig_height >= orig_width:
width = int((orig_width/orig_height) * new_height) width = int((orig_width / orig_height) * new_height)
height = new_height height = new_height
else: else:
height = int((orig_height/orig_width) * new_width) height = int((orig_height / orig_width) * new_width)
width = new_width width = new_width
image.thumbnail(width, height) image.thumbnail(width, height)
thumbnails.append((image.make_blob(), "image/"+image.format)) thumbnails.append((image.make_blob(), "image/" + image.format))
return thumbnails return thumbnails
def open_comic(path): def open_comic(path):
archive = comicarchive.ComicArchive(path, default_image_path="static/images/icon.png") archive = comicarchive.ComicArchive(path, default_image_path="static/images/icon.png")
return archive return archive
def get_movies(): def get_movies():
current_app.logger.info("start load movies") current_app.logger.info("start loading movies")
pattern = r"(?P<title>.+) \((?P<year>\d+)\)(?P<extended>\(extended\))?(?P<directors_cut> Director's Cut)?(?P<extension>\.mkv)" pattern = r"(?P<title>.+) \((?P<year>\d+)\)(?P<extended>\(extended\))?(?P<directors_cut> Director's Cut)?(?P<extension>\.mkv)"
movies = [] url = "https://api.themoviedb.org/3/search/movie"
total_movies = 0 movies = []
movies_in_db = 0 total_movies = 0
movies_added = 0 movies_in_db = 0
for root, dirs, files in os.walk(MOVIES_DIRECTORY): movies_added = 0
for f in files: for root, dirs, files in os.walk(MOVIES_DIRECTORY):
if f.endswith(".mkv"): for f in files:
total_movies += 1 if f.endswith(".mkv"):
path = os.path.join(root, f) total_movies += 1
if not database.movie_path_in_db(path): path = os.path.join(root, f)
try: if not database.movie_path_in_db(path):
match = re.match(pattern, f) try:
if not match: match = re.match(pattern, f)
current_app.logger.info(f+" did not match regex.") if not match:
continue current_app.logger.info(f + " did not match regex.")
current_app.logger.info("movie path: "+path) continue
title = match.group("title") current_app.logger.info("movie path: " + path)
current_app.logger.info("movie title: "+title) title = match.group("title")
year = int(match.group("year")) current_app.logger.info("movie title: " + title)
extended = False year = int(match.group("year"))
directors_cut = False extended = True if match.group("extended") else False
if match.group("extended"): directors_cut = True if match.group("directors_cut") else False
extended = True
imdb_data = database.imdb_get_movie(title.replace(match.group("extended"), ""), year)
elif match.group("directors_cut"):
imdb_data = database.imdb_get_movie(title.replace(match.group("directors_cut"), ""), year)
directors_cut = True
else:
imdb_data = database.imdb_get_movie(title, year)
if not imdb_data:
current_app.logger.info("could not get imdb data for: "+title+" "+str(year))
continue
imdb_id = imdb_data["tconst"]
length = imdb_data["runtimeMinutes"]
tmdb_data = database.tmdb_get_movie_by_imdb_id(imdb_id) data = {
if not tmdb_data: "api_key": API_KEY,
current_app.logger.info("could not get tmdb data") "query": title,
continue "primary_release_year": year,
tmdb_id = tmdb_data[0] "language": "en-US",
description = tmdb_data[1] }
poster_path = tmdb_data[2] r = requests.get(url, params=data)
backdrop_path = tmdb_data[3] if len(r.json()["results"]) == 0:
movies_added += 1 data = {
"api_key": API_KEY,
"query": title,
"year": year,
"language": "en-US",
}
r = requests.get(url, params=data)
if len(r.json()["results"]) == 0:
current_app.logger.info(f"no movie results for {title} - ({year})")
continue
info = r.json()["results"][0]
movies.append((path, imdb_id, tmdb_id, title, year, length, description, extended, directors_cut, poster_path, backdrop_path)) tmdb_id = info["id"]
if len(movies) >= 20: description = info["overview"]
movie_loaded.send("anonymous", movies=movies.copy()) poster_path = info["poster_path"]
movies.clear() backdrop_path = info["backdrop_path"]
except Exception as e: movies_added += 1
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) +" "+ str(e))
# print(e) movies.append((path, tmdb_id, title, year, description, extended, directors_cut, poster_path, backdrop_path,))
movies_in_db += 1 if len(movies) >= 20:
movie_loaded.send("anonymous", movies=movies) movie_loaded.send("anonymous", movies=movies.copy())
current_app.logger.info("finish load movies") movies.clear()
current_app.logger.info("total movies: "+str(total_movies)) except Exception as e:
current_app.logger.info("movies in database: "+str(movies_in_db)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
current_app.logger.info("movies added: "+str(movies_added)) # print(e)
movies_in_db += 1
movie_loaded.send("anonymous", movies=movies)
current_app.logger.info("finish loading movies")
current_app.logger.info("total movies: " + str(total_movies))
current_app.logger.info("movies in database: " + str(movies_in_db))
current_app.logger.info("movies added: " + str(movies_added))
def get_movie(path): def get_movie(path: pathlib.Path):
pattern = r"(?P<title>.+) \((?P<year>\d+)\)(?P<extended>\(extended\))?(?P<directors_cut> Director's Cut)?(?P<extension>\.mkv)" pattern = r"(?P<title>.+) \((?P<year>\d+)\)(?P<extended>\(extended\))?(?P<directors_cut> Director's Cut)?(?P<extension>\.mkv)"
movies = [] url = "https://api.themoviedb.org/3/search/movie"
if not database.movie_path_in_db(path): movies = []
try: if not database.movie_path_in_db(str(path)):
match = re.match(pattern, path) try:
if not match: match = re.match(pattern, path.name)
current_app.logger.info(path + " did not match regex.") if not match:
return current_app.logger.info(f"{path.name} did not match regex.")
current_app.logger.info("movie path: " + path) return
title = match.group("title") current_app.logger.info(f"movie path: {path}")
current_app.logger.info("movie title: " + title) title = match.group("title")
year = int(match.group("year")) current_app.logger.info("movie title: " + title)
extended = False year = int(match.group("year"))
directors_cut = False extended = match.group("extended") is True
if match.group("extended"): directors_cut = match.group("directors_cut") is True
extended = True
imdb_data = database.imdb_get_movie(title.replace(match.group("extended"), ""), year)
elif match.group("directors_cut"):
imdb_data = database.imdb_get_movie(title.replace(match.group("directors_cut"), ""), year)
directors_cut = True
else:
imdb_data = database.imdb_get_movie(title, year)
if not imdb_data:
current_app.logger.info("could not get imdb data for: " + title + " " + str(year))
return
imdb_id = imdb_data["tconst"]
length = imdb_data["runtimeMinutes"]
tmdb_data = database.tmdb_get_movie_by_imdb_id(imdb_id) data = {
if not tmdb_data: "api_key": API_KEY,
current_app.logger.info("could not get tmdb data") "query": title,
return "primary_release_year": year,
tmdb_id = tmdb_data[0] "language": "en-US",
description = tmdb_data[1] }
poster_path = tmdb_data[2] r = requests.get(url, params=data)
backdrop_path = tmdb_data[3] if len(r.json()["results"]) == 0:
data = {
"api_key": API_KEY,
"query": title,
"year": year,
"language": "en-US",
}
r = requests.get(url, params=data)
info = r.json()["results"][0]
if len(r.json()["results"]) == 0:
current_app.logger.info(f"no movie results for {title} - ({year})")
return
movies.append((path, imdb_id, tmdb_id, title, year, length, description, extended, directors_cut, tmdb_id = info["id"]
poster_path, backdrop_path)) description = info["overview"]
movie_loaded.send("anonymous", movies=movies.copy()) poster_path = info["poster_path"]
movies.clear() backdrop_path = info["backdrop_path"]
current_app.logger.info("finish load movie")
except Exception as e: movies.append((str(path), tmdb_id, title, year, description, extended, directors_cut, poster_path, backdrop_path,))
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) movie_loaded.send("anonymous", movies=movies.copy())
movies.clear()
current_app.logger.info("finish loading movie")
except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
def get_tv_shows(): def get_tv_shows():
dir_pattern = r"(?P<title>.+) \((?P<year>\d+)\)" dir_pattern = r"(?P<title>.+) \((?P<year>\d+)\)"
for dir in sorted(os.listdir(TV_SHOWS_DIRECTORY)): search_url = "https://api.themoviedb.org/3/search/tv"
dir_match = re.match(dir_pattern, dir) tv_url = "https://api.themoviedb.org/3/tv/"
if dir_match: current_app.logger.info("start loading tv shows")
path = TV_SHOWS_DIRECTORY+dir for dir in sorted(os.listdir(TV_SHOWS_DIRECTORY)):
if not database.tv_show_path_in_db(path): dir_match = re.match(dir_pattern, dir)
info = {} if dir_match:
if os.path.exists(path+"/info.json"): path = TV_SHOWS_DIRECTORY + dir
with open(path+"/info.json") as f: if not database.tv_show_path_in_db(path):
info = json.load(f) json_info = {}
series_name = dir_match.group("title") if os.path.exists(path + "/info.json"):
series_year = int(dir_match.group("year")) with open(path + "/info.json") as f:
imdb_data = database.imdb_get_tv_show(series_name, series_year, info) json_info = json.load(f)
if not imdb_data: series_name = dir_match.group("title")
current_app.logger.info("could not get imdb data for:"+series_name+" "+str(series_year)) series_year = int(dir_match.group("year"))
# print("could not get imdb data for:", series_name, series_year)
continue if not json_info:
imdb_id = imdb_data["tconst"] data = {
tmdb_data = database.tmdb_get_tv_show_by_imdb_id(imdb_id) "api_key": API_KEY,
if not tmdb_data: "query": series_name,
current_app.logger.info("could not get tmdb data for:" + series_name + " " + str(series_year)) "first_air_date_year": series_year,
# print("could not get tmdb data for:", series_name, series_year) "language": "en-US",
with open("/var/lib/rpiWebApp/log.txt", "a") as f: }
f.write("could not get tmdb data for: " + imdb_id + " " + series_name + " " + str(series_year)+"\n") r = requests.get(search_url, params=data)
continue if len(r.json()["results"]) == 0:
tmdb_id = tmdb_data[0] current_app.logger.info(f"no tv show results for {series_name} - ({series_year})")
description = tmdb_data[1] continue
poster_path = tmdb_data[2] info = r.json()["results"][0]
tv_show_data = (imdb_id, tmdb_id, series_name, series_year, description, poster_path, path) else:
tv_show_loaded.send("anonymous", tv_show=tv_show_data) data = {"api_key": API_KEY, "language": "en-US"}
current_app.logger.info("finished load tv shows.") r = requests.get(tv_url + str(json_info["tmdb_id"]), params=data)
if "status_code" in r.json().keys():
current_app.logger.info(f"no tv show results for {series_name} - ({series_year})")
continue
info = r.json()
tmdb_id = info["id"]
description = info["overview"]
poster_path = info["poster_path"]
tv_show_data = (
tmdb_id,
series_name,
series_year,
description,
poster_path,
path,
)
tv_show_loaded.send("anonymous", tv_show=tv_show_data)
current_app.logger.info("finished loading tv shows.")
def get_tv_episodes(): def get_tv_episodes():
try: video_pattern = r"S(?P<season>\d+)E(?P<episode>\d+) - (?P<title>.+)(?P<extension>.mkv)"
video_pattern = r"S(?P<season>\d+)E(?P<episode>\d+) - (?P<title>.+)(?P<extension>.mp4|.mkv)" rows = database.get_all_tv_shows()
rows = database.get_all_tv_shows() current_app.logger.info("start loading tv episodes")
for tv_show in rows: for tv_show in rows:
episodes = [] try:
for video in sorted(os.listdir(tv_show.path)): episodes = []
video_match = re.match(video_pattern, video) for video in sorted(os.listdir(tv_show.path)):
if video_match: video_match = re.match(video_pattern, video)
path = os.path.join(tv_show.path, video) if video_match:
if not database.tv_episode_path_in_db(path): path = os.path.join(tv_show.path, video)
season = int(video_match.group("season")) if not database.tv_episode_path_in_db(path):
episode = int(video_match.group("episode")) season = int(video_match.group("season"))
episode_name = video_match.group("title") episode = int(video_match.group("episode"))
episode_imdb_data = database.imdb_get_tv_episode(tv_show.imdb_id, season, episode) episode_name = video_match.group("title")
if not episode_imdb_data: current_app.logger.info(f"S{season} E{episode} - {tv_show.title}: {episode_name}")
current_app.logger.info("could not get imdb data for: "+tv_show.title+" "+str(tv_show.year)+" "+str(season)+" "+str(episode)) url = f"https://api.themoviedb.org/3/tv/{tv_show.tmdb_id}/season/{season}/episode/{episode}"
print("could not get imdb data for:", tv_show.title, tv_show.year, season, episode)
continue data = {"api_key": API_KEY, "language": "en-US"}
episode_imdb_id = episode_imdb_data["tconst"] r = requests.get(url, params=data)
episode_tmdb_data = database.tmdb_get_tv_episode_by_imdb_id(episode_imdb_id) if "status_code" in r.json().keys():
if not episode_tmdb_data: current_app.logger.info(f"no tv episode results for S{season} E{episode} - {tv_show.title}: {episode_name}")
current_app.logger.info("could not get tmdb data for: "+tv_show.title+" "+str(tv_show.year)+" "+str(season)+" "+str(episode)) continue
with open("/var/lib/rpiWebApp/log.txt", "w") as f: info = r.json()
f.write("could not get tmdb data for: " + episode_imdb_id + " " + tv_show.title + " " + str(
tv_show.year) + " " + str(season) + " " + str(episode) + "\n") episode_tmdb_id = info["id"]
continue episode_description = info["overview"]
episode_tmdb_id = episode_tmdb_data[0] episode_still_path = info["still_path"]
episode_description = episode_tmdb_data[1] episodes.append(
episode_still_path = episode_tmdb_data[2] (episode_tmdb_id, tv_show.tmdb_id, episode_name, season, episode, episode_description, episode_still_path, path,)
episodes.append((episode_imdb_id, tv_show.imdb_id, episode_tmdb_id, episode_name, season, episode, )
episode_description, episode_still_path, path)) if len(episodes) >= 10:
tv_episodes_loaded.send("anonymous", tv_episodes=episodes) tv_episodes_loaded.send("anonymous", tv_episodes=episodes.copy())
current_app.logger.info("finished load tv episodes") episodes.clear()
except Exception as e: tv_episodes_loaded.send("anonymous", tv_episodes=episodes)
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
current_app.logger.info("finished loading tv episodes")
def get_tv_episode(path): def get_tv_episode(path: pathlib.Path):
folder, name = os.path.split(path) video_pattern = r"S(?P<season>\d+)E(?P<episode>\d+) - (?P<title>.+)(?P<extension>.mkv)"
video_pattern = r"S(?P<season>\d+)E(?P<episode>\d+) - (?P<title>.+)(?P<extension>.mp4|.mkv)" video_match = re.match(video_pattern, path.name)
video_match = re.match(video_pattern, name) if video_match:
if video_match: rows = database.get_all_tv_shows()
rows = database.get_all_tv_shows() for tv_show in rows:
for tv_show in rows: if path.parent == tv_show.path:
if folder == tv_show.path: if not database.tv_episode_path_in_db(str(path)):
if not database.tv_episode_path_in_db(path): episodes = []
episodes = [] season = int(video_match.group("season"))
season = int(video_match.group("season")) episode = int(video_match.group("episode"))
episode = int(video_match.group("episode")) episode_name = video_match.group("title")
episode_name = video_match.group("title") url = f"https://api.themoviedb.org/3/tv/{tv_show.tmdb_id}/season/{season}/episode/{episode}"
episode_imdb_data = database.imdb_get_tv_episode(tv_show.imdb_id, season, episode)
if not episode_imdb_data: data = {"api_key": API_KEY, "language": "en-US"}
current_app.logger.info( r = requests.get(url, params=data)
"could not get imdb data for: " + tv_show.title + " " + str(tv_show.year) + " " + str( if "status_code" in r.json().keys():
season) + " " + str(episode)) current_app.logger.info(f"no tv episode results for S{season} E{episode} - {tv_show.title}: {episode_name}")
print("could not get imdb data for:", tv_show.title, tv_show.year, season, episode) continue
return info = r.json()
episode_imdb_id = episode_imdb_data["tconst"]
episode_tmdb_data = database.tmdb_get_tv_episode_by_imdb_id(episode_imdb_id) episode_tmdb_id = info["id"]
if not episode_tmdb_data: episode_description = info["overview"]
current_app.logger.info( episode_still_path = info["still_path"]
"could not get tmdb data for: " + tv_show.title + " " + str(tv_show.year) + " " + str( episodes.append(
season) + " " + str(episode)) (episode_tmdb_id, tv_show.tmdb_id, episode_name, season, episode, episode_description, episode_still_path, str(path),)
with open("/var/lib/rpiWebApp/log.txt", "w") as f: )
f.write("could not get tmdb data for: " + episode_imdb_id + " " + tv_show.title + " " + str( tv_episodes_loaded.send("anonymous", tv_episodes=episodes)
tv_show.year) + " " + str(season) + " " + str(episode) + "\n") current_app.logger.info("finished loading tv episode")
return
episode_tmdb_id = episode_tmdb_data[0]
episode_description = episode_tmdb_data[1]
episode_still_path = episode_tmdb_data[2]
episodes.append((episode_imdb_id, tv_show.imdb_id, episode_tmdb_id, episode_name, season, episode,
episode_description, episode_still_path, path))
tv_episodes_loaded.send("anonymous", tv_episodes=episodes)
current_app.logger.info("finished load tv episode")
def get_chapters(path): def get_chapters(path):
try: try:
with open(path, 'rb') as f: with open(path, "rb") as f:
mkv = enzyme.MKV(f) mkv = enzyme.MKV(f)
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
mkv_info = {} return {}
for chapter in mkv.chapters: mkv_info = {}
if chapter.string == "Intro": for chapter in mkv.chapters:
mkv_info["intro"] = { if chapter.string == "Intro":
"start": chapter.start.seconds, mkv_info["intro"] = {
"end": timedelta(microseconds=chapter.end//1000).seconds "start": chapter.start.seconds,
} "end": timedelta(microseconds=chapter.end // 1000).seconds,
if chapter.string == "Credits": }
mkv_info["credits"] = {"start": chapter.start.seconds} if chapter.string == "Credits":
if chapter.string == "end-credit scene": mkv_info["credits"] = {"start": chapter.start.seconds}
if "end-credit scene" not in mkv_info.keys(): if chapter.string == "end-credit scene":
mkv_info["end-credit scene"] = [] if "end-credit scene" not in mkv_info.keys():
end_credit = {"start": chapter.start.seconds} mkv_info["end-credit scene"] = []
if chapter.end: end_credit = {"start": chapter.start.seconds}
end_credit["end"] = timedelta(microseconds=chapter.end//1000).seconds if chapter.end:
mkv_info["end-credit scene"].append(end_credit) end_credit["end"] = timedelta(microseconds=chapter.end // 1000).seconds
return mkv_info mkv_info["end-credit scene"].append(end_credit)
return mkv_info
def get_tags(path): def get_tags(path):
try: try:
with open(path, 'rb') as f: with open(path, "rb") as f:
mkv = enzyme.MKV(f) mkv = enzyme.MKV(f)
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
mkv_info = {} mkv_info = {}
for tag in mkv.tags: for tag in mkv.tags:
if tag.targets.data[0].data == 70: if tag.targets.data[0].data == 70:
mkv_info["collection"] = {} mkv_info["collection"] = {}
for simple in tag.simpletags: for simple in tag.simpletags:
if simple.name == "TITLE": if simple.name == "TITLE":
mkv_info["collection"]["title"] = simple.string mkv_info["collection"]["title"] = simple.string
if simple.name == "TOTAL_PARTS": if simple.name == "TOTAL_PARTS":
mkv_info["collection"]["episodes"] = int(simple.string) mkv_info["collection"]["episodes"] = int(simple.string)
if simple.name == "KEYWORDS": if simple.name == "KEYWORDS":
mkv_info["collection"]["key_words"] = simple.string.split(",") mkv_info["collection"]["key_words"] = simple.string.split(",")
if simple.name == "DATE_RELEASED": if simple.name == "DATE_RELEASED":
mkv_info["collection"]["year"] = int(simple.string) mkv_info["collection"]["year"] = int(simple.string)
if simple.name == "SUMMARY": if simple.name == "SUMMARY":
mkv_info["collection"]["summary"] = simple.string mkv_info["collection"]["summary"] = simple.string
if tag.targets.data[0].data == 60: if tag.targets.data[0].data == 60:
mkv_info["season"] = {} mkv_info["season"] = {}
for simple in tag.simpletags: for simple in tag.simpletags:
if simple.name == "TITLE": if simple.name == "TITLE":
mkv_info["season"]["title"] = simple.string mkv_info["season"]["title"] = simple.string
if simple.name == "TOTAL_PARTS": if simple.name == "TOTAL_PARTS":
mkv_info["season"]["episodes"] = int(simple.string) mkv_info["season"]["episodes"] = int(simple.string)
if tag.targets.data[0].data == 50: if tag.targets.data[0].data == 50:
mkv_info["movie"] = {} mkv_info["movie"] = {}
for simple in tag.simpletags: for simple in tag.simpletags:
if simple.name == "TITLE": if simple.name == "TITLE":
mkv_info["movie"]["title"] = simple.string mkv_info["movie"]["title"] = simple.string
if simple.name == "DATE_RELEASED": if simple.name == "DATE_RELEASED":
mkv_info["movie"]["year"] = int(simple.string) mkv_info["movie"]["year"] = int(simple.string)
if simple.name == "PART_NUMBER": if simple.name == "PART_NUMBER":
mkv_info["movie"]["episode"] = int(simple.string) mkv_info["movie"]["episode"] = int(simple.string)
if simple.name == "KEYWORDS": if simple.name == "KEYWORDS":
mkv_info["movie"]["key_words"] = simple.string.split(",") mkv_info["movie"]["key_words"] = simple.string.split(",")
if simple.name == "SUMMARY": if simple.name == "SUMMARY":
mkv_info["movie"]["summary"] = simple.string mkv_info["movie"]["summary"] = simple.string
return mkv_info return mkv_info
def get_games(): def get_games():
games = [] games = []
cover_url = "https://api-v3.igdb.com/covers" cover_url = "https://api-v3.igdb.com/covers"
games_url = "https://api-v3.igdb.com/games" games_url = "https://api-v3.igdb.com/games"
headers = { headers = {
"accept": "application/json", "accept": "application/json",
"user-key": "641f7f0e3af5273dcc1105ce851ea804" "user-key": "641f7f0e3af5273dcc1105ce851ea804",
} }
i = 0 i = 0
for folder in sorted(os.listdir(GAMES_DIRECTORY), key=str.casefold): current_app.logger.info("start loading games")
root = os.path.join(GAMES_DIRECTORY, folder) for folder in sorted(os.listdir(GAMES_DIRECTORY), key=str.casefold):
if os.path.isdir(os.path.join(root)): root = os.path.join(GAMES_DIRECTORY, folder)
path = os.path.join(root, "info.json") if os.path.isdir(os.path.join(root)):
with open(path, "r") as f: try:
info = json.load(f) path = os.path.join(root, "info.json")
game_id = info["id"] with open(path, "r") as f:
if not database.game_in_db(game_id): info = json.load(f)
current_app.logger.info(f"start loading game: {info['name']}:{info['id']}") game_id = info["id"]
data = f"fields summary;limit 1;where id={game_id};" if not database.game_in_db(game_id):
r = requests.get(games_url, headers=headers, data=data).json()[0] current_app.logger.info(f"start loading game: {info['name']}:{info['id']}")
description = "" data = f"fields summary;limit 1;where id={game_id};"
if "summary" in r.keys(): r = requests.get(games_url, headers=headers, data=data).json()[0]
description = r["summary"] description = ""
data = f"fields image_id;limit 1;where game={game_id};" if "summary" in r.keys():
r = requests.get(cover_url, headers=headers, data=data).json() description = r["summary"]
poster_path = None data = f"fields image_id;limit 1;where game={game_id};"
if r: r = requests.get(cover_url, headers=headers, data=data).json()
if "image_id" in r[0].keys(): poster_path = None
poster_path = "https://images.igdb.com/igdb/image/upload/t_cover_big/" + r[0]["image_id"] + ".jpg" if r:
windows = None if "image_id" in r[0].keys():
mac = None poster_path = "https://images.igdb.com/igdb/image/upload/t_cover_big/" + r[0]["image_id"] + ".jpg"
linux = None windows = False
if "windows" in info.keys(): mac = False
windows = info["windows"] linux = False
if "mac" in info.keys(): if "windows" in info.keys():
mac = info["mac"] windows = True
if "linux" in info.keys(): if "mac" in info.keys():
linux = info["linux"] mac = True
game = (info["name"], game_id, description, poster_path, windows, mac, linux) if "linux" in info.keys():
games.append(game) linux = True
i += 1 game = (
if i >= 5: info["name"],
games_loaded.send("anonymous", games=games.copy()) game_id,
games.clear() description,
i = 0 poster_path,
games_loaded.send("anonymous", games=games) root,
current_app.logger.info("finished loading games") windows,
mac,
linux,
folder,
)
games.append(game)
i += 1
if i >= 5:
games_loaded.send("anonymous", games=games.copy())
games.clear()
i = 0
except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
games_loaded.send("anonymous", games=games)
current_app.logger.info("finished loading games")
def get_game(path: pathlib.Path):
try:
games = []
cover_url = "https://api-v3.igdb.com/covers"
games_url = "https://api-v3.igdb.com/games"
headers = {
"accept": "application/json",
"user-key": "***REMOVED***",
}
if not path.name == "info.json":
return
else:
with path.open("r") as f:
info = json.load(f)
game_id = info["id"]
if database.game_in_db(game_id):
update_game(path)
else:
dir = path.parent
folder = path.parts[-2]
current_app.logger.info(f"start loading game: {info['name']}:{info['id']}")
data = f"fields summary;limit 1;where id={game_id};"
r = requests.get(games_url, headers=headers, data=data).json()[0]
description = ""
if "summary" in r.keys():
description = r["summary"]
data = f"fields image_id;limit 1;where game={game_id};"
r = requests.get(cover_url, headers=headers, data=data).json()
poster_path = None
if r:
if "image_id" in r[0].keys():
poster_path = "https://images.igdb.com/igdb/image/upload/t_cover_big/" + r[0]["image_id"] + ".jpg"
windows = False
mac = False
linux = False
if "windows" in info.keys():
windows = True
if "mac" in info.keys():
mac = True
if "linux" in info.keys():
linux = True
game = (
info["name"],
game_id,
description,
poster_path,
str(dir),
windows,
mac,
linux,
folder,
)
games.append(game)
games_loaded.send("anonymous", games=games)
current_app.logger.info("finished loading game")
except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
def update_games():
current_app.logger.info("start updating game data")
for folder in sorted(os.listdir(GAMES_DIRECTORY), key=str.casefold):
root = pathlib.Path(GAMES_DIRECTORY, folder, "info.json")
update_game(root)
current_app.logger.info("finished updating game data")
def update_game(path: pathlib.Path):
try:
if path.name == "info.json" and path.exists():
with path.open("r") as f:
info = json.load(f)
game_id = info["id"]
windows = False
mac = False
linux = False
if "windows" in info.keys():
windows = True
if "mac" in info.keys():
mac = True
if "linux" in info.keys():
linux = True
database.update_game((game_id, windows, mac, linux))
except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))

View File

@ -1,4 +1,6 @@
import sqlite3, subprocess, os import os
import sqlite3
import subprocess
RPI_IMDB_DATABASE = "/var/lib/rpiWebApp/" RPI_IMDB_DATABASE = "/var/lib/rpiWebApp/"
RPI_TSV_DIRECTORY = "/var/lib/imdb-rename/" RPI_TSV_DIRECTORY = "/var/lib/imdb-rename/"
@ -15,19 +17,25 @@ CSV_DIRECTORY = RPI_CSV_DIRECTORY if os.path.exists(RPI_CSV_DIRECTORY) else MC_C
def create_csv_files(): def create_csv_files():
print("start create csv") print("start create csv")
subprocess.run(["xsv", "input", "-d", "\t", "--no-quoting", "{}title.akas.tsv".format(TSV_DIRECTORY), "-o", "{}title_akas.csv".format(CSV_DIRECTORY)]) subprocess.run(
subprocess.run(["xsv", "input", "-d", "\t", "--no-quoting", "{}title.basics.tsv".format(TSV_DIRECTORY), "-o", "{}title_basics.csv".format(CSV_DIRECTORY)]) ["xsv", "input", "-d", "\t", "--no-quoting", "{}title.akas.tsv".format(TSV_DIRECTORY), "-o", "{}title_akas.csv".format(CSV_DIRECTORY)]
subprocess.run(["xsv", "input", "-d", "\t", "--no-quoting", "{}title.episode.tsv".format(TSV_DIRECTORY), "-o", "{}title_episode.csv".format(CSV_DIRECTORY)]) )
print("end create csv") subprocess.run(
["xsv", "input", "-d", "\t", "--no-quoting", "{}title.basics.tsv".format(TSV_DIRECTORY), "-o", "{}title_basics.csv".format(CSV_DIRECTORY)]
)
subprocess.run(
["xsv", "input", "-d", "\t", "--no-quoting", "{}title.episode.tsv".format(TSV_DIRECTORY), "-o", "{}title_episode.csv".format(CSV_DIRECTORY)]
)
print("end create csv")
def import_csv_files(): def import_csv_files():
print("start import csv") print("start import csv")
f = open("import_csv.sql").read() f = open("import_csv.sql").read()
sql_script = f.format(CSV_DIRECTORY) sql_script = f.format(CSV_DIRECTORY)
subprocess.run(["sudo", "-u", "http", "sqlite3", IMDB_DATABASE+"imdb.db"], input=sql_script.encode("utf8")) subprocess.run(["sudo", "-u", "http", "sqlite3", IMDB_DATABASE + "imdb.db"], input=sql_script.encode("utf8"))
print("end import csv") print("end import csv")
create_csv_files() create_csv_files()

View File

@ -1,7 +1,8 @@
from flask import current_app
import requests
import inspect import inspect
import requests
from flask import current_app
API_KEY = "***REMOVED***" API_KEY = "***REMOVED***"
TMDB_FIND_URL = "https://api.themoviedb.org/3/find/" TMDB_FIND_URL = "https://api.themoviedb.org/3/find/"
TMDB_GET_TV_URL = "https://api.themoviedb.org/3/tv/" TMDB_GET_TV_URL = "https://api.themoviedb.org/3/tv/"
@ -10,83 +11,70 @@ TMDB_IMG_URL = "https://image.tmdb.org/t/p/original"
def get_movie_data(imdb_id): def get_movie_data(imdb_id):
try: try:
data = { data = {"api_key": API_KEY, "language": "en-US", "external_source": "imdb_id"}
"api_key": API_KEY, r = requests.get(TMDB_FIND_URL + imdb_id, params=data)
"language": "en-US", info = dict(r.json())
"external_source": "imdb_id" if "status_code" in info.keys():
} current_app.logger.info("error getting tmdb movie data, status code: " + str(info["status_code"]) + " " + str(info["status_message"]))
r = requests.get(TMDB_FIND_URL+imdb_id, params=data) return None
info = dict(r.json()) if info["movie_results"] == []:
if "status_code" in info.keys(): current_app.logger.info("no tmdb results for: " + str(imdb_id))
current_app.logger.info("error getting tmdb movie data, status code: "+str(info["status_code"])+" "+str(info["status_message"])) return None
return None current_app.logger.info("tmdb movie title: " + str(info["movie_results"][0]["title"]))
if info["movie_results"] == []: movie_id = info["movie_results"][0]["id"]
current_app.logger.info("no tmdb results for: " + str(imdb_id)) overview = info["movie_results"][0]["overview"]
return None poster_path = info["movie_results"][0]["poster_path"]
current_app.logger.info("tmdb movie title: " + str(info["movie_results"][0]["title"])) backdrop_path = info["movie_results"][0]["backdrop_path"]
movie_id = info["movie_results"][0]["id"]
overview = info["movie_results"][0]["overview"]
poster_path = info["movie_results"][0]["poster_path"]
backdrop_path = info["movie_results"][0]["backdrop_path"]
return movie_id, overview, poster_path, backdrop_path return movie_id, overview, poster_path, backdrop_path
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
def get_tv_show_data(imdb_id): def get_tv_show_data(imdb_id):
try: try:
data = { data = {"api_key": API_KEY, "language": "en-US", "external_source": "imdb_id"}
"api_key": API_KEY, r = requests.get(TMDB_FIND_URL + imdb_id, params=data)
"language": "en-US", info = dict(r.json())
"external_source": "imdb_id" if "status_code" in info.keys():
} current_app.logger.info("error getting tmdb tv show data, status code: " + str(info["status_code"]) + " " + str(info["status_message"]))
r = requests.get(TMDB_FIND_URL+imdb_id, params=data) return None
info = dict(r.json()) if info["tv_results"] == []:
if "status_code" in info.keys(): current_app.logger.info("no tmdb results for: " + str(imdb_id))
current_app.logger.info("error getting tmdb tv show data, status code: " + str(info["status_code"])+" "+str(info["status_message"])) return None
return None current_app.logger.info("tmdb tv show title: " + str(info["tv_results"][0]["name"]))
if info["tv_results"] == []: tv_show_id = info["tv_results"][0]["id"]
current_app.logger.info("no tmdb results for: " + str(imdb_id)) overview = info["tv_results"][0]["overview"]
return None poster_path = info["tv_results"][0]["poster_path"]
current_app.logger.info("tmdb tv show title: " + str(info["tv_results"][0]["name"]))
tv_show_id = info["tv_results"][0]["id"]
overview = info["tv_results"][0]["overview"]
poster_path = info["tv_results"][0]["poster_path"]
return tv_show_id, overview, poster_path return tv_show_id, overview, poster_path
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
def get_tv_episode_data(imdb_id): def get_tv_episode_data(imdb_id):
try: try:
data = { data = {"api_key": API_KEY, "language": "en-US", "external_source": "imdb_id"}
"api_key": API_KEY, r = requests.get(TMDB_FIND_URL + imdb_id, params=data)
"language": "en-US", episode_info = dict(r.json())
"external_source": "imdb_id" if "status_code" in episode_info.keys():
} current_app.logger.info(
r = requests.get(TMDB_FIND_URL+imdb_id, params=data) "error getting tmdb tv episode data, status code: " + str(episode_info["status_code"]) + " " + str(episode_info["status_message"])
episode_info = dict(r.json()) )
if "status_code" in episode_info.keys(): return None
current_app.logger.info("error getting tmdb tv episode data, status code: " + str(episode_info["status_code"])+" "+str(episode_info["status_message"])) if episode_info["tv_episode_results"] == []:
return None current_app.logger.info("no tmdb results for: " + str(imdb_id))
if episode_info["tv_episode_results"] == []: return None
current_app.logger.info("no tmdb results for: " + str(imdb_id)) data = {"api_key": API_KEY, "language": "en-US"}
return None r = requests.get(TMDB_GET_TV_URL + str(episode_info["tv_episode_results"][0]["show_id"]), params=data)
data = { show_name = dict(r.json())["name"]
"api_key": API_KEY, current_app.logger.info("tmdb tv_episode title: " + show_name + ": " + str(episode_info["tv_episode_results"][0]["name"]))
"language": "en-US" tv_episode_id = episode_info["tv_episode_results"][0]["id"]
} name = episode_info["tv_episode_results"][0]["name"]
r = requests.get(TMDB_GET_TV_URL+str(episode_info["tv_episode_results"][0]["show_id"]), params=data) overview = episode_info["tv_episode_results"][0]["overview"]
show_name = dict(r.json())["name"] still_path = episode_info["tv_episode_results"][0]["still_path"]
current_app.logger.info("tmdb tv_episode title: " + show_name + ": " + str(episode_info["tv_episode_results"][0]["name"]))
tv_episode_id = episode_info["tv_episode_results"][0]["id"]
name = episode_info["tv_episode_results"][0]["name"]
overview = episode_info["tv_episode_results"][0]["overview"]
still_path = episode_info["tv_episode_results"][0]["still_path"]
return tv_episode_id, overview, still_path return tv_episode_id, overview, still_path
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -61,7 +61,7 @@
</div> </div>
<script> <script>
var page_num = {{ page }}; var page_num = {% if page %}{{ page }}{% else %}1{% endif %};
var max_items = {{ max_items }}; var max_items = {{ max_items }};
var item_count = {{ item_count }}; var item_count = {{ item_count }};
var start = max_items*(page_num-1); var start = max_items*(page_num-1);
@ -74,6 +74,10 @@
var page_container = document.getElementById("page-container"); var page_container = document.getElementById("page-container");
function go_to_page(pagenumber) { function go_to_page(pagenumber) {
let url = new URL(document.location)
url.searchParams.set("page", pagenumber)
window.history.replaceState(null, null, url.toString())
{#document.location.search = search#}
page_num = pagenumber; page_num = pagenumber;
start = max_items*(page_num-1); start = max_items*(page_num-1);
if (item_count < max_items*page_num) { if (item_count < max_items*page_num) {
@ -126,6 +130,7 @@
} }
} }
} }
window.scrollTo(0, 0)
} }
function offset_page(i) { function offset_page(i) {

View File

@ -1,11 +1,13 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
<div class="container" style="text-align: center"> <div class="w3-row" style="text-align: center">
<div class="w3-col s1 w3-hide-small m1 l2"><p></p></div>
<div class="w3-col s12 m10 l8">
<video id="player" class="video-js vjs-big-play-centered" style="display: inline-block" controls preload="auto" width="1100" <video id="player" class="video-js vjs-big-play-centered vjs-16-9" style="display: inline-block; width:100%" controls preload="auto"
poster="https://image.tmdb.org/t/p/original{{ episode.still_path }}" data-setup="{}"> poster="https://image.tmdb.org/t/p/original{{ episode.still_path }}" data-setup="{}">
<source src="{{ url_for("tv_movies.index") }}/get_episode/{{ episode.imdb_id }}" type="video/webm"> <source src="{{ url_for("tv_movies.index") }}/get_episode/{{ episode.tmdb_id }}" type="video/webm">
<p class='vjs-no-js'> <p class='vjs-no-js'>
To view this video please enable JavaScript, and consider upgrading to a web browser that To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href='https://videojs.com/html5-video-support/' target='_blank'>supports HTML5 video</a> <a href='https://videojs.com/html5-video-support/' target='_blank'>supports HTML5 video</a>
@ -32,7 +34,7 @@
{% endif %} {% endif %}
{% endfor %} {% endfor %}
<p style="text-align: left">{{ episode.description }}</p> <p style="text-align: left">{{ episode.description }}</p>
<a class="btn btn-primary" href="{{ url_for("tv_movies.index") }}/get_episode/{{ episode.imdb_id }}" download="{{ episode.title }}">Download</a> <a class="btn btn-primary" href="{{ url_for("tv_movies.index") }}/get_episode/{{ episode.tmdb_id }}" download="{{ episode.title }}">Download</a>
{% with %} {% with %}
{% set seasons = [] %} {% set seasons = [] %}
@ -63,7 +65,7 @@
<div class="w3-display-topleft w3-container w3-round" style="background: rgba(105,105,105,0.61);color: white">Episode {{ episode.episode }}</div> <div class="w3-display-topleft w3-container w3-round" style="background: rgba(105,105,105,0.61);color: white">Episode {{ episode.episode }}</div>
<div class="w3-display-bottommiddle w3-container w3-round" style="background: rgba(105,105,105,0.61);color: white">{{ episode.title }}</div> <div class="w3-display-bottommiddle w3-container w3-round" style="background: rgba(105,105,105,0.61);color: white">{{ episode.title }}</div>
{% for data in user_tv_show_data %} {% for data in user_tv_show_data %}
{% if data.imdb_id == episode.imdb_id and data.finished %} {% if data.tmdb_id == episode.tmdb_id and data.finished %}
<div class="w3-display-topright w3-container" style="background: rgba(105,105,105,0.61); border-radius: 5px 0 0 5px"> <div class="w3-display-topright w3-container" style="background: rgba(105,105,105,0.61); border-radius: 5px 0 0 5px">
<img src="/static/svg/verified.svg" > <img src="/static/svg/verified.svg" >
</div> </div>
@ -71,7 +73,7 @@
{% endfor %} {% endfor %}
</div> </div>
{% for data in user_tv_show_data %} {% for data in user_tv_show_data %}
{% if data.imdb_id == episode.imdb_id and data.time != 0 and data.length != 0 %} {% if data.tmdb_id == episode.tmdb_id and data.time != 0 and data.length != 0 %}
<div class="w3-light-gray"> <div class="w3-light-gray">
<div class="w3-red" style="height: 5px; width: {{ (data.time/data.length)*100 }}%"></div> <div class="w3-red" style="height: 5px; width: {{ (data.time/data.length)*100 }}%"></div>
</div> </div>
@ -83,6 +85,8 @@
</form> </form>
</div> </div>
</div> </div>
<div class="w3-col s1 w3-hide-small m1 l2"><p></p></div>
</div>
{% endblock %} {% endblock %}
@ -133,7 +137,7 @@
//length = myPlayer.duration(); //length = myPlayer.duration();
let oReq = new XMLHttpRequest(); let oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener); oReq.addEventListener("load", reqListener);
oReq.open("POST", "https://rpi.narnian.us/tv_movies/{{ episode.imdb_id }}?time="+(time+5)+"&parent={{ episode.parent_imdb_id }}&length="+length+"&finished="+finished); oReq.open("POST", "https://rpi.narnian.us/tv_movies/{{ episode.tmdb_id }}?time="+(time+5)+"&parent={{ episode.parent_tmdb_id }}&length="+length+"&finished="+finished);
oReq.send(); oReq.send();
time = myPlayer.currentTime(); time = myPlayer.currentTime();
} }
@ -143,7 +147,7 @@
//length = myPlayer.duration(); //length = myPlayer.duration();
let oReq = new XMLHttpRequest(); let oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener); oReq.addEventListener("load", reqListener);
oReq.open("POST", "https://rpi.narnian.us/tv_movies/{{ episode.imdb_id }}?time="+(time+5)+"&parent={{ episode.parent_imdb_id }}&length="+length+"&finished="+finished); oReq.open("POST", "https://rpi.narnian.us/tv_movies/{{ episode.tmdb_id }}?time="+(time+5)+"&parent={{ episode.parent_tmdb_id }}&length="+length+"&finished="+finished);
oReq.send(); oReq.send();
time = myPlayer.currentTime(); time = myPlayer.currentTime();
}); });

View File

@ -16,8 +16,8 @@
<div style="text-align: center"> <div style="text-align: center">
{% include "pagination.html" %} {% include "pagination.html" %}
</div> </div>
<div class="container col-10"> <div class="w3-container">
<div id="page-container" class="row justify-content-start"></div> <div id="page-container" style="display: flow-root; text-align: center"></div>
</div> </div>
<div style="text-align: center"> <div style="text-align: center">
{% include "pagination.html" %} {% include "pagination.html" %}
@ -34,28 +34,42 @@
function populate_page() { function populate_page() {
page_container.innerHTML = ""; page_container.innerHTML = "";
for (i = start;i < end; i++) { for (i = start;i < end; i++) {
var anchor = `<a href="/tv_movies/${tv_shows[i][0].imdb_id}">`; let badge = ""
var anchor = `<a href="/tv_movies/${tv_shows[i][0].tmdb_id}">`;
if (tv_shows[i][0].extended && tv_shows[i][0].directors_cut) { if (tv_shows[i][0].extended && tv_shows[i][0].directors_cut) {
anchor = `<a href="/tv_movies/${tv_shows[i][0].imdb_id}?extended=True&directors_cut=True">`; anchor = `<a href="/tv_movies/${tv_shows[i][0].tmdb_id}?extended=True&directors_cut=True">`;
} else if (tv_shows[i][0].extended) { } else if (tv_shows[i][0].extended) {
anchor = `<a href="/tv_movies/${tv_shows[i][0].imdb_id}?extended=True">`; badge = `<div class="w3-display-topleft w3-container" style="color: white; background: rgba(105,105,105,0.61); border-radius: 0 5px 5px 0">
extended
</div>`
anchor = `<a href="/tv_movies/${tv_shows[i][0].tmdb_id}?extended=True">`;
} else if (tv_shows[i][0].directors_cut) { } else if (tv_shows[i][0].directors_cut) {
anchor = `<a href="/tv_movies/${tv_shows[i][0].imdb_id}?directors_cut=True">`; badge = `<div class="w3-display-topleft w3-container" style="color: white; background: rgba(105,105,105,0.61); border-radius: 0 5px 5px 0">
director's cut
</div>`
anchor = `<a href="/tv_movies/${tv_shows[i][0].tmdb_id}?directors_cut=True">`;
} }
var finished = ``; var finished = ``;
if (tv_shows[i][1]) { if (tv_shows[i][1]) {
finished = `<div class="w3-display-topright w3-container" style="background: rgba(105,105,105,0.61); border-radius: 5px 0 0 5px"> finished = `<div class="w3-display-topright w3-container" style="background: rgba(105,105,105,0.61); border-radius: 5px 0 0 5px">
<img src="/static/svg/verified.svg" > <img src="/static/svg/verified.svg" >
</div>` </div>`
} }
var list_element = `<div class="col-3" style="padding: 10px">
var text = ""
if (!tv_shows[i][0].poster_path) {
text = `<div class='w3-display-middle w3-container' style="color: white; text-align: center;font-size: 20px; width: 100%">
${tv_shows[i][0].title} (${tv_shows[i][0].year})</div>`
}
var list_element = `<div class="w3-display-container w3-round" style="width: 350px; display: inline-block; padding: 10px">
${anchor} ${anchor}
<div class="card w3-display-container"> <div class="card w3-display-container">
<img class="card-img" src="https://image.tmdb.org/t/p/original${tv_shows[i][0].poster_path}" alt="" onerror="this.src='/static/images/default.png'"> <img class="card-img" src="https://image.tmdb.org/t/p/original${tv_shows[i][0].poster_path}" alt="${tv_shows[i][0].title} (${tv_shows[i][0].year})" title="${tv_shows[i][0].title} (${tv_shows[i][0].year})" onerror="this.src='/static/images/default.png'">
<div class="card-body"> ${text}
${tv_shows[i][0].title} (${tv_shows[i][0].year})
</div>
${finished} ${finished}
${badge}
</div> </div>
</a> </a>
</div>`; </div>`;

View File

@ -1,17 +1,19 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
<div class="container" style="text-align: center"> <div class="w3-row" style="text-align: center">
<video id="player" class="video-js vjs-big-play-centered" style="display: inline-block" controls preload="auto" width="1100" <div class="w3-col s1 w3-hide-small m1 l2"><p></p></div>
<div class="w3-col s12 m10 l8">
<video id="player" class="video-js vjs-big-play-centered vjs-16-9" style="display: inline-block" controls preload="auto"
poster="https://image.tmdb.org/t/p/original{{ movie.backdrop_path }}" data-setup="{}"> poster="https://image.tmdb.org/t/p/original{{ movie.backdrop_path }}" data-setup="{}">
{% if movie.extended and movie.directors_cut %} {% if movie.extended and movie.directors_cut %}
<source src="{{ url_for("tv_movies.index") }}/get_movie/{{ movie.imdb_id }}?extended=True&directors_cut=True" type="video/webm"> <source src="{{ url_for("tv_movies.index") }}/get_movie/{{ movie.tmdb_id }}?extended=True&directors_cut=True" type="video/webm">
{% elif movie.extended %} {% elif movie.extended %}
<source src="{{ url_for("tv_movies.index") }}/get_movie/{{ movie.imdb_id }}?extended=True" type="video/webm"> <source src="{{ url_for("tv_movies.index") }}/get_movie/{{ movie.tmdb_id }}?extended=True" type="video/webm">
{% elif movie.directors_cut %} {% elif movie.directors_cut %}
<source src="{{ url_for("tv_movies.index") }}/get_movie/{{ movie.imdb_id }}?directors_cut=True" type="video/webm"> <source src="{{ url_for("tv_movies.index") }}/get_movie/{{ movie.tmdb_id }}?directors_cut=True" type="video/webm">
{% else %} {% else %}
<source src="{{ url_for("tv_movies.index") }}/get_movie/{{ movie.imdb_id }}" type="video/webm"> <source src="{{ url_for("tv_movies.index") }}/get_movie/{{ movie.tmdb_id }}" type="video/webm">
{% endif %} {% endif %}
<p class='vjs-no-js'> <p class='vjs-no-js'>
To view this video please enable JavaScript, and consider upgrading to a web browser that To view this video please enable JavaScript, and consider upgrading to a web browser that
@ -20,7 +22,9 @@
</video> </video>
<h1>{{ movie.title }}</h1> <h1>{{ movie.title }}</h1>
<p style="text-align: left">{{ movie.description }}</p> <p style="text-align: left">{{ movie.description }}</p>
<a class="btn btn-primary" href="{{ url_for("tv_movies.index") }}/get_movie/{{ movie.imdb_id }}{% if movie.extended == 1 %}/extended{% endif %}{% if movie.directors_cut==1 %}/directors_cut{% endif %}" download="{{ movie.title }}">Download</a> <a class="btn btn-primary" href="{{ url_for("tv_movies.index") }}/get_movie/{{ movie.tmdb_id }}{% if movie.extended == 1 %}/extended{% endif %}{% if movie.directors_cut==1 %}/directors_cut{% endif %}" download="{{ movie.title }}">Download</a>
</div>
<div class="w3-col s1 w3-hide-small m1 l2"><p></p></div>
</div> </div>
{% endblock %} {% endblock %}
@ -60,7 +64,7 @@
length = myPlayer.duration(); length = myPlayer.duration();
let oReq = new XMLHttpRequest(); let oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener); oReq.addEventListener("load", reqListener);
oReq.open("POST", "https://rpi.narnian.us/tv_movies/{{ movie.imdb_id }}?time="+(time)+"&length="+length+"&finished="+finished{% if movie.extended %}+"&extended=True"{% endif %}{% if movie.directors_cut %}+"&directors_cut=True"{% endif %}); oReq.open("POST", "https://rpi.narnian.us/tv_movies/{{ movie.tmdb_id }}?time="+(time)+"&length="+length+"&finished="+finished{% if movie.extended %}+"&extended=True"{% endif %}{% if movie.directors_cut %}+"&directors_cut=True"{% endif %});
oReq.send(); oReq.send();
time = myPlayer.currentTime(); time = myPlayer.currentTime();
} }
@ -70,7 +74,7 @@
length = myPlayer.duration(); length = myPlayer.duration();
let oReq = new XMLHttpRequest(); let oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener); oReq.addEventListener("load", reqListener);
oReq.open("POST", "https://rpi.narnian.us/tv_movies/{{ movie.imdb_id }}?time="+(time)+"&length="+length+"&finished="+finished{% if movie.extended %}+"&extended=True"{% endif %}{% if movie.directors_cut %}+"&directors_cut=True"{% endif %}); oReq.open("POST", "https://rpi.narnian.us/tv_movies/{{ movie.tmdb_id }}?time="+(time)+"&length="+length+"&finished="+finished{% if movie.extended %}+"&extended=True"{% endif %}{% if movie.directors_cut %}+"&directors_cut=True"{% endif %});
oReq.send(); oReq.send();
time = myPlayer.currentTime(); time = myPlayer.currentTime();
}); });

View File

@ -16,9 +16,9 @@
<div style="text-align: center"> <div style="text-align: center">
{% include "pagination.html" %} {% include "pagination.html" %}
</div> </div>
<div class="container col-10"> <div class="w3-container">
{% if movies != [] %} {% if movies != [] %}
<div id="page-container" class="row justify-content-start"></div> <div id="page-container" style="display: flow-root; text-align: center"></div>
{% else %} {% else %}
<h1>No results.</h1> <h1>No results.</h1>
{% endif %} {% endif %}
@ -38,28 +38,42 @@
function populate_page() { function populate_page() {
page_container.innerHTML = ""; page_container.innerHTML = "";
for (i = start;i < end; i++) { for (i = start;i < end; i++) {
var anchor = `<a href="/tv_movies/${tv_shows[i][0].imdb_id}">`; let badge = ""
var anchor = `<a href="/tv_movies/${tv_shows[i][0].tmdb_id}">`;
if (tv_shows[i][0].extended && tv_shows[i][0].directors_cut) { if (tv_shows[i][0].extended && tv_shows[i][0].directors_cut) {
anchor = `<a href="/tv_movies/${tv_shows[i][0].imdb_id}?extended=True&directors_cut=True">`; anchor = `<a href="/tv_movies/${tv_shows[i][0].tmdb_id}?extended=True&directors_cut=True">`;
} else if (tv_shows[i][0].extended) { } else if (tv_shows[i][0].extended) {
anchor = `<a href="/tv_movies/${tv_shows[i][0].imdb_id}?extended=True">`; badge = `<div class="w3-display-topleft w3-container" style="color: white; background: rgba(105,105,105,0.61); border-radius: 0 5px 5px 0">
extended
</div>`
anchor = `<a href="/tv_movies/${tv_shows[i][0].tmdb_id}?extended=True">`;
} else if (tv_shows[i][0].directors_cut) { } else if (tv_shows[i][0].directors_cut) {
anchor = `<a href="/tv_movies/${tv_shows[i][0].imdb_id}?directors_cut=True">`; badge = `<div class="w3-display-topleft w3-container" style="color: white; background: rgba(105,105,105,0.61); border-radius: 0 5px 5px 0">
director's cut
</div>`
anchor = `<a href="/tv_movies/${tv_shows[i][0].tmdb_id}?directors_cut=True">`;
} }
var finished = ``; var finished = ``;
if (tv_shows[i][1]) { if (tv_shows[i][1]) {
finished = `<div class="w3-display-topright w3-container" style="background: rgba(105,105,105,0.61); border-radius: 5px 0 0 5px"> finished = `<div class="w3-display-topright w3-container" style="background: rgba(105,105,105,0.61); border-radius: 5px 0 0 5px">
<img src="/static/svg/verified.svg" > <img src="/static/svg/verified.svg" >
</div>` </div>`
} }
var list_element = `<div class="col-3" style="padding: 10px">
var text = ""
if (!tv_shows[i][0].poster_path) {
text = `<div class='w3-display-middle w3-container' style="color: white; text-align: center;font-size: 20px; width: 100%">
${tv_shows[i][0].title} (${tv_shows[i][0].year})</div>`
}
var list_element = `<div class="w3-display-container w3-round" style="width: 350px; display: inline-block; padding: 10px">
${anchor} ${anchor}
<div class="card w3-display-container"> <div class="card w3-display-container">
<img class="card-img" src="https://image.tmdb.org/t/p/original${tv_shows[i][0].poster_path}" alt="" onerror="this.src='/static/images/default.png'"> <img class="card-img" src="https://image.tmdb.org/t/p/original${tv_shows[i][0].poster_path}" alt="${tv_shows[i][0].title} (${tv_shows[i][0].year})" title="${tv_shows[i][0].title} (${tv_shows[i][0].year})" onerror="this.src='/static/images/default.png'">
<div class="card-body"> ${text}
${tv_shows[i][0].title} (${tv_shows[i][0].year})
</div>
${finished} ${finished}
${badge}
</div> </div>
</a> </a>
</div>`; </div>`;

View File

@ -1,9 +1,10 @@
from flask import Blueprint, render_template, request, make_response, send_from_directory, current_app import datetime
import inspect
from flask import Blueprint, current_app, make_response, render_template, request, send_from_directory
from flask_login import login_required from flask_login import login_required
from scripts import database, func from scripts import database, func
import inspect
import datetime
TV_Movies = Blueprint("tv_movies", __name__, template_folder="templates") TV_Movies = Blueprint("tv_movies", __name__, template_folder="templates")
@ -11,154 +12,169 @@ TV_Movies = Blueprint("tv_movies", __name__, template_folder="templates")
@TV_Movies.route("/tv_movies") @TV_Movies.route("/tv_movies")
@login_required @login_required
def index(): def index():
try: try:
page = request.args.get("page", 1, type=int) page = request.args.get("page", 1, type=int)
max_items = request.args.get("max_items", 30, type=int) max_items = request.args.get("max_items", 30, type=int)
tv = database.get_all_tv_movies() tv = database.get_all_tv_movies()
start = (max_items * (page - 1)) start = max_items * (page - 1)
end = len(tv) if len(tv) < max_items * page else max_items * page end = len(tv) if len(tv) < max_items * page else max_items * page
tv_dict = [] tv_dict = []
for tv_item in tv: for tv_item in tv:
item = tv_item[0].__dict__ item = tv_item[0].__dict__
item.pop('_sa_instance_state', None) item.pop("_sa_instance_state", None)
item.pop('path', None) item.pop("path", None)
tv_dict.append((item, tv_item[1])) tv_dict.append((item, tv_item[1]))
return render_template("tv_movies/index.html", title="tv & movies", tv_shows=tv_dict, page=page, max_items=max_items, start=start, end=end, item_count=len(tv)) return render_template(
except Exception as e: "tv_movies/index.html", title="tv & movies", tv_shows=tv_dict, page=page, max_items=max_items, start=start, end=end, item_count=len(tv)
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) )
return str(type(e))+" "+str(e) except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e)) + " " + str(e)
@TV_Movies.route("/tv_movies/search") @TV_Movies.route("/tv_movies/search")
@login_required @login_required
def search(): def search():
try: try:
page = request.args.get("page", 1, type=int) page = request.args.get("page", 1, type=int)
max_items = request.args.get("max_items", 30, type=int) max_items = request.args.get("max_items", 30, type=int)
start = 0 start = 0
end = 0 end = 0
query = request.args.get("q") query = request.args.get("q")
tv = [] tv = []
if query: if query:
tv = database.db_search_tv_movie(query) tv = database.db_search_tv_movie(query)
start = (max_items * (page - 1)) start = max_items * (page - 1)
end = len(tv) if len(tv) < max_items * page else max_items * page end = len(tv) if len(tv) < max_items * page else max_items * page
tv_dict = [] tv_dict = []
for tv_item in tv: for tv_item in tv:
item = tv_item[0].__dict__ item = tv_item[0].__dict__
item.pop('_sa_instance_state', None) item.pop("_sa_instance_state", None)
item.pop('path', None) item.pop("path", None)
tv_dict.append((item, tv_item[1])) tv_dict.append((item, tv_item[1]))
return render_template("tv_movies/search.html", title="tv_movies", tv_shows=tv_dict, page=page, max_items=max_items, return render_template(
start=start, end=end, item_count=len(tv)) "tv_movies/search.html", title="tv_movies", tv_shows=tv_dict, page=page, max_items=max_items, start=start, end=end, item_count=len(tv)
except Exception as e: )
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) except Exception as e:
return str(type(e))+" "+str(e) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e)) + " " + str(e)
@TV_Movies.route("/tv_movies/<imdb_id>", methods=["GET", "POST"]) @TV_Movies.route("/tv_movies/<tmdb_id>", methods=["GET", "POST"])
@login_required @login_required
def tv_movie_viewer(imdb_id): def tv_movie_viewer(tmdb_id):
try: try:
tv_movie = database.get_tv_movie_by_imdb_id(imdb_id) tv_movie = database.get_tv_movie_by_tmdb_id(tmdb_id)
if type(tv_movie) is database.Movie: if type(tv_movie) is database.Movie:
extended = request.args.get("extended", default=False, type=bool) extended = request.args.get("extended", default=False, type=bool)
directors_cut = request.args.get("directors_cut", default=False, type=bool) directors_cut = request.args.get("directors_cut", default=False, type=bool)
return movie_view(imdb_id, extended=extended, directors_cut=directors_cut) return movie_view(tmdb_id, extended=extended, directors_cut=directors_cut)
else: else:
return episode_viewer(imdb_id) return episode_viewer(tmdb_id)
except Exception as e: except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e))+" "+str(e) return str(type(e)) + " " + str(e)
@login_required @login_required
def movie_view(imdb_id, extended=False, directors_cut=False): def movie_view(tmdb_id, extended=False, directors_cut=False):
try: try:
if request.method == "POST": if request.method == "POST":
time = int(request.args.get("time", type=float)) time = int(request.args.get("time", type=float))
length = int(request.args.get("length", type=float, default=0)) length = int(request.args.get("length", type=float, default=0))
finished = True if request.args.get("finished", default="false") == "true" else False finished = True if request.args.get("finished", default="false") == "true" else False
database.update_user_tv_movie_data(imdb_id, None, time, length, finished, extended, directors_cut) database.update_user_tv_movie_data(tmdb_id, None, time, length, finished, extended, directors_cut)
return make_response("", 201) return make_response("", 201)
else: else:
movie_data = database.db_get_movie_by_imdb_id(imdb_id, extended=extended, directors_cut=directors_cut) movie_data = database.db_get_movie_by_tmdb_id(tmdb_id, extended=extended, directors_cut=directors_cut)
user_data = database.db_get_user_tv_movie_data(movie_data.imdb_id, extended=extended, directors_cut=directors_cut) user_data = database.db_get_user_tv_movie_data(movie_data.tmdb_id, extended=extended, directors_cut=directors_cut)
chapters = func.get_chapters(movie_data.path) chapters = func.get_chapters(movie_data.path)
if not user_data: if not user_data:
user_data = database.update_user_tv_movie_data(movie_data.imdb_id, None, 0, 0) user_data = database.update_user_tv_movie_data(movie_data.tmdb_id, None, 0, 0)
return render_template("tv_movies/movieViewer.html", title="Movies: " + movie_data.title, movie=movie_data, user_data=user_data, chapters=chapters) return render_template(
except Exception as e: "tv_movies/movieViewer.html", title="Movies: " + movie_data.title, movie=movie_data, user_data=user_data, chapters=chapters
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) )
return str(type(e)) + " " + str(e) except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e)) + " " + str(e)
@login_required @login_required
def episode_viewer(imdb_id): def episode_viewer(tmdb_id):
try: try:
if request.method == "POST": if request.method == "POST":
time = int(request.args.get("time", type=float)) time = int(request.args.get("time", type=float))
parent_id = request.args.get("parent", type=str) parent_id = request.args.get("parent", type=str)
length = int(request.args.get("length", type=float, default=0)) length = int(request.args.get("length", type=float, default=0))
finished = True if request.args.get("finished", default="false") == "true" else False finished = True if request.args.get("finished", default="false") == "true" else False
database.update_user_tv_movie_data(imdb_id, parent_id, time, length, finished) database.update_user_tv_movie_data(tmdb_id, parent_id, time, length, finished)
return make_response("", 201) return make_response("", 201)
else: else:
tv_show = database.get_tv_show(imdb_id) tv_show = database.get_tv_show(tmdb_id)
episodes = database.get_tv_show_episodes_by_imdb_id(imdb_id) episodes = database.get_tv_show_episodes_by_tmdb_id(tmdb_id)
season_num = request.args.get("season", type=int, default=None) season_num = request.args.get("season", type=int, default=None)
episode_num = request.args.get("episode", type=int, default=None) episode_num = request.args.get("episode", type=int, default=None)
user_tv_show_data = database.db_get_user_tv_show_episodes_data(imdb_id) user_tv_show_data = database.db_get_user_tv_show_episodes_data(tmdb_id)
if not season_num and not episode_num: if not season_num and not episode_num:
(current_episode, user_data) = database.db_get_current_tv_show_episode_and_data(imdb_id, episodes) (current_episode, user_data) = database.db_get_current_tv_show_episode_and_data(tmdb_id, episodes)
season_num = current_episode.season season_num = current_episode.season
episode_num = current_episode.episode episode_num = current_episode.episode
chapters = func.get_chapters(current_episode.path) chapters = func.get_chapters(current_episode.path)
if not user_data: if not user_data:
user_data = database.update_user_tv_movie_data(current_episode.imdb_id, imdb_id, 0, 0) user_data = database.update_user_tv_movie_data(current_episode.tmdb_id, tmdb_id, 0, 0)
else: else:
current_episode = episodes[0] current_episode = episodes[0]
user_data = database.UserTvMovieData(("", "", "", 0, 0, False, datetime.datetime.min)) user_data = database.UserTvMovieData(("", "", "", 0, 0, False, datetime.datetime.min, False, False))
for episode in episodes: for episode in episodes:
if episode.season == season_num and episode.episode == episode_num: if episode.season == season_num and episode.episode == episode_num:
current_episode = episode current_episode = episode
user_data = database.db_get_user_tv_movie_data(current_episode.imdb_id) user_data = database.db_get_user_tv_movie_data(current_episode.tmdb_id)
if not user_data: if not user_data:
user_data = database.update_user_tv_movie_data(current_episode.imdb_id, imdb_id, 0, 0) user_data = database.update_user_tv_movie_data(current_episode.tmdb_id, tmdb_id, 0, 0)
break break
else: else:
for episode in episodes: for episode in episodes:
if episode.season == season_num: if episode.season == season_num:
current_episode = episode current_episode = episode
episode_num = episode.episode episode_num = episode.episode
user_data = database.db_get_user_tv_movie_data(current_episode.imdb_id) user_data = database.db_get_user_tv_movie_data(current_episode.tmdb_id)
if not user_data: if not user_data:
user_data = database.update_user_tv_movie_data(current_episode.imdb_id, imdb_id, 0, 0) user_data = database.update_user_tv_movie_data(current_episode.tmdb_id, tmdb_id, 0, 0)
break break
chapters = func.get_chapters(current_episode.path) chapters = func.get_chapters(current_episode.path)
return render_template("tv_movies/episodeViewer.html", title="Tv: " + tv_show.title, episodes=episodes, season_num=season_num, episode_num=episode_num, episode=current_episode, user_data=user_data, user_tv_show_data=user_tv_show_data, chapters=chapters) return render_template(
except Exception as e: "tv_movies/episodeViewer.html",
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) title="Tv: " + tv_show.title,
return str(type(e)) + " " + str(e) episodes=episodes,
season_num=season_num,
episode_num=episode_num,
episode=current_episode,
user_data=user_data,
user_tv_show_data=user_tv_show_data,
chapters=chapters,
)
except Exception as e:
current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e))
return str(type(e)) + " " + str(e)
@TV_Movies.route("/tv_movies/get_movie/<imdb_id>") @TV_Movies.route("/tv_movies/get_movie/<tmdb_id>")
@login_required @login_required
def get_movie(imdb_id): def get_movie(tmdb_id):
extended = request.args.get("extended", default=False, type=bool) extended = request.args.get("extended", default=False, type=bool)
directors_cut = request.args.get("directors_cut", default=False, type=bool) directors_cut = request.args.get("directors_cut", default=False, type=bool)
movie_data = database.db_get_movie_by_imdb_id(imdb_id, extended=extended, directors_cut=directors_cut) movie_data = database.db_get_movie_by_tmdb_id(tmdb_id, extended=extended, directors_cut=directors_cut)
filename = movie_data.path.replace(func.MOVIES_DIRECTORY, "") filename = movie_data.path.replace(func.MOVIES_DIRECTORY, "")
response = make_response(send_from_directory(func.MOVIES_DIRECTORY, filename)) response = make_response(send_from_directory(func.MOVIES_DIRECTORY, filename))
response.headers["content-type"] = "video/webm" response.headers["content-type"] = "video/webm"
return response return response
@TV_Movies.route("/tv_movies/get_episode/<imdb_id>") @TV_Movies.route("/tv_movies/get_episode/<tmdb_id>")
@login_required @login_required
def get_episode(imdb_id): def get_episode(tmdb_id):
episode_data = database.db_get_episode_by_imdb_id(imdb_id) episode_data = database.db_get_episode_by_tmdb_id(tmdb_id)
filename = episode_data.path.replace(func.TV_SHOWS_DIRECTORY, "") filename = episode_data.path.replace(func.TV_SHOWS_DIRECTORY, "")
response = make_response(send_from_directory(func.TV_SHOWS_DIRECTORY, filename)) response = make_response(send_from_directory(func.TV_SHOWS_DIRECTORY, filename))
response.headers["content-type"] = "video/webm" response.headers["content-type"] = "video/webm"
return response return response