diff --git a/admin/admin.py b/admin/admin.py index f298a39..87afdfe 100644 --- a/admin/admin.py +++ b/admin/admin.py @@ -1,5 +1,5 @@ -from flask import Blueprint, flash, redirect, url_for, render_template -from flask_login import login_required, current_user +from flask import Blueprint, flash, redirect, render_template, url_for +from flask_login import current_user, login_required Admin = Blueprint("admin", __name__, template_folder="templates") @@ -7,7 +7,7 @@ Admin = Blueprint("admin", __name__, template_folder="templates") @Admin.route("/admin") @login_required def index(): - if not current_user.is_admin: - flash("you must be an admin to access this page, login with an admin account.") - return redirect(url_for("login")) - return render_template("admin/index.html", title="Admin") + if not current_user.is_admin: + flash("you must be an admin to access this page, login with an admin account.") + return redirect(url_for("login")) + return render_template("admin/index.html", title="Admin") diff --git a/comics/comics.py b/comics/comics.py index 35ab492..507e1ba 100644 --- a/comics/comics.py +++ b/comics/comics.py @@ -1,10 +1,12 @@ -from flask import Blueprint, render_template, request, make_response, current_app -from flask_login import login_required - -from urllib import parse -import filetype -import os, pytz, datetime +import datetime 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 @@ -16,145 +18,195 @@ MOBILE_DEVICES = ["android", "blackberry", "ipad", "iphone"] @Comics.route("/comics") @login_required def index(): - try: - page = request.args.get("page", 1, type=int) - max_items = request.args.get("max_items", 30, type=int) - publishers = database.get_publishers() - start = (max_items*(page-1)) - 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)) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return str(type(e)) + " " + str(e) + try: + page = request.args.get("page", 1, type=int) + max_items = request.args.get("max_items", 30, type=int) + publishers = database.get_publishers() + start = max_items * (page - 1) + 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), + ) + 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") @login_required def search(): - try: - page = request.args.get("page", 1, type=int) - max_items = request.args.get("max_items", 30, type=int) - publisher_end = 0 - series_end = 0 - comics_end = 0 - publisher_start = 0 - series_start = 0 - comics_start = 0 - item_count = 0 - query = request.args.get("q") - results = { - "publisher": [], - "series": [], - "comics": [] - } - if query: - results = database.db_search_comics(query) - item_count = len(results["publisher"]) + len(results["series"]) + len(results["comics"]) - for temp_page in range(1, page+1): - publisher_start = publisher_end - series_start = series_end - comics_start = comics_end - items = 0 - publisher_end = len(results["publisher"]) if len(results["publisher"]) < max_items*temp_page else max_items*temp_page - items += publisher_end - publisher_start - if items < max_items: - series_end = len(results["series"]) if len(results["series"]) < (max_items*temp_page)-items else (max_items*temp_page)-items - items += series_end-series_start - if items < max_items: - 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 - return render_template("comics/search.html", title="Comics: Search", publishers=results["publisher"], 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) + try: + page = request.args.get("page", 1, type=int) + max_items = request.args.get("max_items", 30, type=int) + publisher_end = 0 + series_end = 0 + comics_end = 0 + publisher_start = 0 + series_start = 0 + comics_start = 0 + item_count = 0 + query = request.args.get("q") + results = {"publisher": [], "series": [], "comics": []} + if query: + results = database.db_search_comics(query) + item_count = len(results["publisher"]) + len(results["series"]) + len(results["comics"]) + for temp_page in range(1, page + 1): + publisher_start = publisher_end + series_start = series_end + comics_start = comics_end + items = 0 + publisher_end = len(results["publisher"]) if len(results["publisher"]) < max_items * temp_page else max_items * temp_page + items += publisher_end - publisher_start + if items < max_items: + series_end = ( + len(results["series"]) if len(results["series"]) < (max_items * temp_page) - items else (max_items * temp_page) - items + ) + items += series_end - series_start + if items < max_items: + 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 + ) + return render_template( + "comics/search.html", + title="Comics: Search", + publishers=results["publisher"], + 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/") @login_required def comics_publisher(publisher): - try: - publisher = parse.unquote(publisher) - series = request.args.get("series") - series_year = request.args.get("seriesYear") - issue = request.args.get("issue") - page_number = request.args.get("pageNumber") - page = request.args.get("page", 1, type=int) - max_items = request.args.get("max_items", 30, type=int) - publisher_series = database.db_get_series_by_publisher(publisher) - start = (max_items*(page-1)) - end = len(publisher_series) if len(publisher_series) < max_items*page else max_items*page - if series: - comics = database.db_get_comics_in_series(series, publisher, series_year) - start = (max_items * (page - 1)) - end = len(comics) if len(comics) < max_items * page else max_items * page - if issue: - return comic_gallery(publisher, series, series_year, issue) - comics_dict = [] - for i in comics: - item = i.__dict__ - item.pop('_sa_instance_state', None) - item.pop('path', None) - comics_dict.append(item) - return render_template("comics/seriesView.html", title="Comics", comics=comics_dict, - start=start, end=end, page=page, max_items=max_items, item_count=len(comics)) - pub_series_dict = [] - for i in publisher_series: - 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) + try: + publisher = parse.unquote(publisher) + series = request.args.get("series") + series_year = request.args.get("seriesYear") + issue = request.args.get("issue") + page_number = request.args.get("pageNumber") + page = request.args.get("page", 1, type=int) + max_items = request.args.get("max_items", 30, type=int) + publisher_series = database.db_get_series_by_publisher(publisher) + start = max_items * (page - 1) + end = len(publisher_series) if len(publisher_series) < max_items * page else max_items * page + if series: + comics = database.db_get_comics_in_series(series, publisher, series_year) + start = max_items * (page - 1) + end = len(comics) if len(comics) < max_items * page else max_items * page + if issue: + return comic_gallery(publisher, series, series_year, issue) + comics_dict = [] + for i in comics: + item = i.__dict__ + item.pop("_sa_instance_state", None) + item.pop("path", None) + comics_dict.append(item) + return render_template( + "comics/seriesView.html", + title="Comics", + comics=comics_dict, + start=start, + end=end, + page=page, + max_items=max_items, + item_count=len(comics), + ) + pub_series_dict = [] + for i in publisher_series: + 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/") @login_required def comic_gallery(comic_id): - try: - page = request.args.get("page", 1, type=int) - max_items = request.args.get("max_items", 30, type=int) - meta = database.db_get_comic(comic_id) - start = (max_items*(page-1)) - end = meta.pagecount if meta.pagecount < max_items*page else max_items*page - comic_dict = meta.__dict__ - comic_dict.pop('_sa_instance_state', 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) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return str(type(e)) + " " + str(e) + try: + page = request.args.get("page", 1, type=int) + max_items = request.args.get("max_items", 30, type=int) + meta = database.db_get_comic(comic_id) + start = max_items * (page - 1) + end = meta.pagecount if meta.pagecount < max_items * page else max_items * page + comic_dict = meta.__dict__ + comic_dict.pop("_sa_instance_state", 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, + ) + 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//") @login_required def get_comic_page(comic_id, page_number): - meta = database.db_get_comic_by_id(comic_id) - comic = func.open_comic(meta.path) - byte_image = comic.getPage(page_number) - type = filetype.guess(byte_image).mime - response = make_response(byte_image) - response.headers["content-type"] = type - response.headers["cache-control"] = "public" - 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["Content-Disposition"] = "attachment; filename=\"{} {}_{}{}\"".format(str(meta.series), meta.issuetext, str(page_number), filetype.guess(byte_image).extension) - return response + meta = database.db_get_comic_by_id(comic_id) + comic = func.open_comic(meta.path) + byte_image = comic.getPage(page_number) + type = filetype.guess(byte_image).mime + response = make_response(byte_image) + response.headers["content-type"] = type + response.headers["cache-control"] = "public" + 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["Content-Disposition"] = 'attachment; filename="{} {}_{}{}"'.format( + str(meta.series), meta.issuetext, str(page_number), filetype.guess(byte_image).extension + ) + return response @Comics.route("/comics/get_comic///thumbnail") @login_required def get_comic_thumbnail(comic_id, page_number): - meta = database.db_get_comic_by_id(comic_id) - thumb = database.db_get_thumbnail_by_id_page(comic_id, page_number) - response = make_response(thumb.image) - response.headers["cache-control"] = "public" - 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["content-type"] = thumb.type - response.headers["Content-Disposition"] = "attachment; filename=\"{} {}_{}_thumbnail\"".format(str(meta.series), meta.issuetext, str(page_number)) - return response + meta = database.db_get_comic_by_id(comic_id) + thumb = database.db_get_thumbnail_by_id_page(comic_id, page_number) + response = make_response(thumb.image) + response.headers["cache-control"] = "public" + 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["content-type"] = thumb.type + response.headers["Content-Disposition"] = 'attachment; filename="{} {}_{}_thumbnail"'.format(str(meta.series), meta.issuetext, str(page_number)) + return response diff --git a/comics/templates/comics/comicGallery.html b/comics/templates/comics/comicGallery.html index c7916b2..24c382f 100644 --- a/comics/templates/comics/comicGallery.html +++ b/comics/templates/comics/comicGallery.html @@ -117,7 +117,7 @@ page_container.innerHTML = ""; for (i = start;i < end; i++) { var list_element = `
- +

${1+i}/${comic.pagecount}

`; page_container.innerHTML += list_element; @@ -134,15 +134,24 @@ let next_image = document.getElementById("next"); let prev_image = document.getElementById("prev"); + for (let i=0; i<{{ item_count }};i++) { + light_box_content.innerHTML += `` + } + function load_next_image(page_number) { if (document.getElementById(page_number.toString())) {return;} if (page_number >= page_count) {return;} console.log("start loading: page "+(page_number+1).toString()); - let image = '
'; + let image = ''; - 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 @@ -202,4 +211,6 @@ }); load_next_image(0); + {% endblock %} diff --git a/games/games.py b/games/games.py index 183f17c..c5cf8c0 100644 --- a/games/games.py +++ b/games/games.py @@ -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 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 @@ -14,78 +13,157 @@ Games = Blueprint("games", __name__, template_folder="templates") @Games.route("/games") @login_required def index(): - try: - page = request.args.get("page", 1, type=int) - max_items = request.args.get("max_items", 30, type=int) - games = database.get_all_games() - start = (max_items*(page-1)) - end = len(games) if len(games) < max_items*page else max_items*page - return render_template("games/index.html", title="Games", games=games) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return str(type(e)) + " " + str(e) + try: + page = request.args.get("page", 1, type=int) + max_items = request.args.get("max_items", 30, type=int) + games = database.get_all_games() + start = max_items * (page - 1) + end = len(games) if len(games) < max_items * page else max_items * page + return render_template("games/index.html", title="Games", games=games) + 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') +@Games.route("/games/get_games") @login_required def get_games(): - try: - games = database.get_all_games() - games_json = {} - for game in games: - games_json[game.game_id] = { - "id": game.game_id, - "title": game.title, - "windows": game.windows, - "mac": game.mac, - "linux": game.linux, - "description": game.description, - "poster_path": game.poster_path - } - return jsonify(games_json) - # return jsonify({game["id"]: game for game in games}) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return str(type(e)) + " " + str(e) + try: + games = database.get_all_games() + games_json = {} + for game in games: + games_json[game.game_id] = { + "id": game.game_id, + "title": game.title, + "description": game.description, + "poster_path": game.poster_path, + "windows": game.windows, + "mac": game.mac, + "linux": game.linux, + "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_game/') +@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/") @login_required def get_game(game_id): - try: - game = database.get_game(game_id) - if game: - game_json = { - "title": game.title, - "game_id": game.game_id, - "description": game.description, - "poster_path": game.poster_path, - "windows": game.windows, - "mac": game.mac, - "linux": game.linux - } - 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) + try: + game = database.get_game(game_id) + if game: + with open(os.path.join(game.path, "info.json")) as f: + info = json.load(f) + windows = None + mac = None + linux = None + if "windows" in info.keys(): + windows = info["windows"] + if "mac" in info.keys(): + mac = info["mac"] + if "linux" in info.keys(): + linux = info["linux"] + game_json = { + "title": game.title, + "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/") +@Games.route("/games/download_hash//") @login_required -def download_game(game_id): - try: - game = database.get_game(game_id) - if game: - files = game.windows["files"] - filename = sanitize_filename(files[0]) - folder = re.match(r"(.+)_setup_win.(exe|msi)", filename).group(1) - if len(files) > 1: - filename = sanitize_filename(game.title+".zip") - path = os.path.join(func.GAMES_DIRECTORY, folder, filename) - return send_file(path, as_attachment=True, attachment_filename=filename) - else: - 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) +def download_game_hash(game_id, file_hash): + try: + game = database.get_game(game_id) + if game: + folder = game.path + path = os.path.join(folder, file_hash[:2], file_hash) + return send_file(path, as_attachment=True, attachment_filename=file_hash) + else: + 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) diff --git a/games/templates/games/index.html b/games/templates/games/index.html index 5706467..5bad66d 100644 --- a/games/templates/games/index.html +++ b/games/templates/games/index.html @@ -2,7 +2,7 @@ {% block content %} {% for game in games %} - Download + Download

{{ game.title }} - {{ game.game_id }}

{% endfor %} {% endblock %} diff --git a/rpiWebApp.py b/rpiWebApp.py index 2d82692..1e71cb3 100644 --- a/rpiWebApp.py +++ b/rpiWebApp.py @@ -1,47 +1,48 @@ -from flask import Flask -from flask import render_template, request, g, redirect, url_for, flash, current_app, Response -from flask_login import LoginManager, current_user, login_user, logout_user, login_required +import base64 +import datetime +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 -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 -from scripts import database from admin import admin from comics import comics -from tv_movies import tv_movies from games import games +from scripts import database +from tv_movies import tv_movies class NullHandler(logging.Handler): - def emit(self, record=None): - pass + def emit(self, record=None): + pass + + def debug(self, *arg): + pass + - def debug(self, *arg): - pass nullLog = NullHandler() inotify.adapters._LOGGER = nullLog GOOGLE_CLIENT_ID = "***REMOVED***" GOOGLE_CLIENT_SECRET = "***REMOVED***" -GOOGLE_DISCOVERY_URL = ( - "https://accounts.google.com/.well-known/openid-configuration" -) +GOOGLE_DISCOVERY_URL = "https://accounts.google.com/.well-known/openid-configuration" client = WebApplicationClient(GOOGLE_CLIENT_ID) def get_google_provider_cfg(): - return requests.get(GOOGLE_DISCOVERY_URL).json() + return requests.get(GOOGLE_DISCOVERY_URL).json() app = Flask(__name__) @@ -54,7 +55,7 @@ app.logger.setLevel("DEBUG") # app.use_x_sendfile = True login_manager = LoginManager(app) -login_manager.login_view = "login" +# login_manager.login_view = "login" app.config["REMEMBER_COOKIE_DOMAIN"] = "narnian.us" @@ -62,101 +63,135 @@ MOBILE_DEVICES = ["android", "blackberry", "ipad", "iphone"] def get_comics(): - with app.app_context(): - i = inotify.adapters.InotifyTree(func.COMICS_DIRECTORY) - func.get_comics() - for event in i.event_gen(yield_nones=False): - (header, type_names, path, filename) = event - file_path = os.path.join(path, filename) - if "IN_CLOSE_WRITE" in type_names or "IN_MOVED_TO" in type_names: - func.get_comic(file_path) + with app.app_context(): + i = inotify.adapters.InotifyTree(func.COMICS_DIRECTORY) + new_dirs = [] + func.get_comics() + while True: + for event in i.event_gen(timeout_s=5*60, 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_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(): - with app.app_context(): - i = inotify.adapters.InotifyTree(func.MOVIES_DIRECTORY) - func.get_movies() - for event in i.event_gen(yield_nones=False): - (header, type_names, path, filename) = event - file_path = os.path.join(path, filename) - if "IN_CLOSE_WRITE" in type_names or "IN_MOVED_TO" in type_names: - func.get_movie(file_path) + with app.app_context(): + i = inotify.adapters.InotifyTree(func.MOVIES_DIRECTORY) + + func.get_movies() + + 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_movie(file_path) def get_tv_shows(): - with app.app_context(): - i = inotify.adapters.InotifyTree(func.TV_SHOWS_DIRECTORY) - func.get_tv_shows() - func.get_tv_episodes() - for event in i.event_gen(yield_nones=False): - (header, type_names, path, filename) = event - file_path = os.path.join(path, filename) - if "IN_CLOSE_WRITE" in type_names or "IN_MOVED_TO" in type_names: - func.get_tv_shows() - func.get_tv_episode(file_path) + with app.app_context(): + i = inotify.adapters.InotifyTree(func.TV_SHOWS_DIRECTORY) + func.get_tv_shows() + func.get_tv_episodes() + 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: + if file_path.is_dir(): + func.get_tv_shows() + else: + func.get_tv_episode(file_path) def get_games(): - with app.app_context(): - func.get_games() + with app.app_context(): + 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(): - current_app.logger.info("server start") - thread = threading.Thread(target=get_comics, args=()) - thread.daemon = True - thread.start() - thread2 = threading.Thread(target=get_movies, args=()) - thread2.daemon = True - thread2.start() - thread3 = threading.Thread(target=get_tv_shows, args=()) - thread3.daemon = True - thread3.start() - thread4 = threading.Thread(target=get_games, args=()) - thread4.daemon = True - thread4.start() + current_app.logger.info("server start") + thread = threading.Thread(target=get_comics, args=()) + thread.daemon = True + thread.start() + thread2 = threading.Thread(target=get_movies, args=()) + thread2.daemon = True + thread2.start() + thread3 = threading.Thread(target=get_tv_shows, args=()) + thread3.daemon = True + thread3.start() + thread4 = threading.Thread(target=get_games, args=()) + thread4.daemon = True + thread4.start() @app.teardown_appcontext def close_connection(exception): - db = getattr(g, '_database', None) - if db is not None: - db.close() + db = getattr(g, "_database", None) + if db is not None: + db.close() def update_comic_db(sender, **kw): - try: - database.add_comics(kw["meta"], kw["thumbnails"]) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + try: + database.add_comics(kw["meta"], kw["thumbnails"]) + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) def update_movie_db(sender, **kw): - try: - database.add_movies(kw["movies"]) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + try: + database.add_movies(kw["movies"]) + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) def update_tv_show_db(sender, **kw): - try: - database.add_tv_shows(kw["tv_show"]) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + try: + database.add_tv_shows(kw["tv_show"]) + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) def update_tv_episodes_db(sender, **kw): - try: - database.add_tv_episodes(kw["tv_episodes"]) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + try: + database.add_tv_episodes(kw["tv_episodes"]) + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) def update_games_db(sender, **kw): - try: - database.add_games(kw["games"]) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + try: + database.add_games(kw["games"]) + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) func.comic_loaded.connect(update_comic_db) @@ -168,177 +203,183 @@ func.games_loaded.connect(update_games_db) @login_manager.user_loader def load_user(email): - try: - return database.get_user(email) - except Exception as 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)) + try: + return database.get_user(email) + except Exception as 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)) @login_manager.request_loader def load_user_from_request(request): - try: - api_key = request.headers.get('Authorization') - if api_key: - api_key = api_key.replace('Basic ', '', 1) - try: - api_key = base64.b64decode(api_key).decode("utf-8") - except TypeError: - pass - email = api_key.split(":")[0] - password = api_key.split(":")[1] - user = load_user(email) - if user and user.check_password(password): - return user - return None - except Exception as 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)) + try: + api_key = request.headers.get("Authorization") + if api_key: + api_key = api_key.replace("Basic ", "", 1) + try: + api_key = base64.b64decode(api_key).decode("utf-8") + except TypeError: + pass + email = api_key.split(":")[0] + password = api_key.split(":")[1] + user = load_user(email) + if user and user.check_password(password): + return user + return None + except Exception as 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)) @app.route("/login", methods=["GET", "POST"]) def login(): - try: - google_provider_cfg = get_google_provider_cfg() - authorization_endpoint = google_provider_cfg["authorization_endpoint"] + try: + url = urlsplit(request.url) + 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( - authorization_endpoint, - redirect_uri=request.base_url + "/callback", - scope=["openid", "email", "profile"], - ) + google_provider_cfg = get_google_provider_cfg() + authorization_endpoint = google_provider_cfg["authorization_endpoint"] - if request.method == "POST": - email = request.form.get("email") - password = request.form.get("password") - user = database.get_user(email) - if user is None or not user.check_password(password): - flash("invalid email or password") - return redirect(url_for("login")) - login_user(user, remember=True, duration=datetime.timedelta(days=7)) - next_page = request.args.get("next") - if not next_page: - next_page = url_for("home") - 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) + request_uri = client.prepare_request_uri( + authorization_endpoint, + redirect_uri=urljoin(request.host_url, url_for("callback")), + scope=["openid", "email", "profile"], + state=next_page, + hd="narnian.us", + ) + + if request.method == "POST": + email = request.form.get("email") + password = request.form.get("password") + user = database.get_user(email) + if user is None or not user.check_password(password): + flash("invalid email or password") + return redirect(url_for("login")) + 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") def callback(): - try: - # Get authorization code Google sent back to you - code = request.args.get("code") + try: + # Get authorization code Google sent back to you + code = request.args.get("code") - google_provider_cfg = get_google_provider_cfg() - token_endpoint = google_provider_cfg["token_endpoint"] + google_provider_cfg = get_google_provider_cfg() + token_endpoint = google_provider_cfg["token_endpoint"] - token_url, headers, body = client.prepare_token_request( - token_endpoint, - authorization_response=request.url, - redirect_url=request.base_url, - code=code - ) - token_response = requests.post( - token_url, - headers=headers, - data=body, - auth=(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET) - ) + token_url, headers, body = client.prepare_token_request( + token_endpoint, authorization_response=request.url, redirect_url=request.base_url, 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"] - uri, headers, body = client.add_token(userinfo_endpoint) - userinfo_response = requests.get(uri, headers=headers, data=body) + userinfo_endpoint = google_provider_cfg["userinfo_endpoint"] + uri, headers, body = client.add_token(userinfo_endpoint) + userinfo_response = requests.get(uri, headers=headers, data=body) - if userinfo_response.json().get("email_verified"): - unique_id = userinfo_response.json()["sub"] - users_email = userinfo_response.json()["email"] - users_name = userinfo_response.json()["given_name"] - else: - return "User email not available or not verified by Google.", 400 + if userinfo_response.json().get("email_verified"): + unique_id = userinfo_response.json()["sub"] + users_email = userinfo_response.json()["email"] + users_name = userinfo_response.json()["given_name"] + else: + 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)) - user = database.get_user(users_email) + current_app.logger.info("user data from google: " + str(data)) + user = database.get_user(users_email) - if not user: - user = database.add_user(data) - current_app.logger.info("new user: {} created".format(users_email)) + if not user: + user = database.add_user(data) + current_app.logger.info("new user: {} created".format(users_email)) - current_app.logger.info("email: "+str(user.email)) - current_app.logger.info("username: "+str(user.username)) - current_app.logger.info("authenticated: "+str(user.is_authenticated)) - current_app.logger.info("active: "+str(user.is_active)) - current_app.logger.info("id: "+str(user.get_id())) - login_user(user, remember=True, duration=datetime.timedelta(days=7), force=True) + current_app.logger.info("email: " + str(user.email)) + current_app.logger.info("username: " + str(user.username)) + current_app.logger.info("authenticated: " + str(user.is_authenticated)) + current_app.logger.info("active: " + str(user.is_active)) + current_app.logger.info("id: " + str(user.get_id())) + login_user(user, remember=True, duration=datetime.timedelta(days=7), force=True) - return redirect(url_for("home")) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return str(e) + return redirect(request.args.get("state")) + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + return str(e) @app.route("/logout") def logout(): - try: - logout_user() - return redirect(url_for("login")) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return str(e) + try: + logout_user() + return redirect(url_for("login")) + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + return str(e) @app.route("/") def root(): - return redirect(url_for("home")) + return redirect(url_for("home")) @app.route("/home") @login_required def home(): - try: - return render_template("home.html", title="Home", current_user=current_user) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return str(e) + try: + return render_template("home.html", title="Home", current_user=current_user) + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + return str(e) @app.after_request def apply_headers(response: Response): - try: - user_name = "anonymous" - if current_user: - user_name = getattr(current_user, "email", "anonymous") - response.set_cookie("rpi_name", user_name) - return response - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return str(e) + try: + user_name = "anonymous" + if current_user: + user_name = getattr(current_user, "email", "anonymous") + response.set_cookie("rpi_name", user_name) + response.headers.set("email", user_name) + return response + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + return str(e) @app.route("/music") @login_required def music(): - return "No music" + return "No music" @app.errorhandler(404) def resource_not_found(e): - try: - return render_template("404.html"), 404 - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return str(e) + try: + return render_template("404.html"), 404 + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + return str(e) + + +@login_manager.unauthorized_handler +def handle_unauthorized(): + temp = login() + return temp, 401 @app.errorhandler(Exception) 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) @@ -351,5 +392,5 @@ comics.Comics.register_error_handler(Exception, handle_exception) admin.Admin.register_error_handler(Exception, handle_exception) -if __name__ == '__main__': - app.run() +if __name__ == "__main__": + app.run() diff --git a/scripts/database.py b/scripts/database.py index 280b613..1a48752 100644 --- a/scripts/database.py +++ b/scripts/database.py @@ -1,24 +1,19 @@ -from flask import g, current_app -from flask_login import UserMixin, current_user - -from werkzeug.security import check_password_hash -from io import BytesIO -from wand.image import Image -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy import create_engine -from sqlalchemy.exc import IntegrityError -from sqlalchemy import Column, Integer, String, BLOB, Boolean, DateTime, Numeric, func, over, ARRAY, TIMESTAMP, JSON -from sqlalchemy.orm import sessionmaker, scoped_session -from sqlalchemy.pool import NullPool -from sqlalchemy.sql.expression import cast -import sqlalchemy -import sqlite3 -import os +import datetime import inspect import logging -import datetime +import os +import sqlalchemy from comicapi.issuestring import IssueString +from flask import current_app +from flask_login import UserMixin, current_user +from sqlalchemy import ARRAY, BLOB, JSON, TIMESTAMP, Boolean, Column, DateTime, Integer, Numeric, String, create_engine, func, over +from sqlalchemy.exc import IntegrityError +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import scoped_session, sessionmaker +from sqlalchemy.pool import NullPool +from sqlalchemy.sql.expression import cast +from werkzeug.security import check_password_hash from scripts import tmdb @@ -33,7 +28,7 @@ USER_DATABASE = RPI_USER_DATABASE if os.path.exists(RPI_USER_DATABASE) else MC_U engine = create_engine("***REMOVED***", poolclass=NullPool) -logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO) +logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO) session_factory = sessionmaker(bind=engine) Session = scoped_session(session_factory) @@ -41,300 +36,298 @@ Base = declarative_base() class Comic(Base): - __tablename__ = "comics" + __tablename__ = "comics" - path = Column(String, unique=True) - tagorigin = Column(String) - series = Column(String) - issue = Column(Integer) - issuetext = Column(String) - title = Column(String) - publisher = Column(String) - month = Column(Integer) - year = Column(Integer) - day = Column(Integer) - seriesyear = Column(Integer) - issuecount = Column(Integer) - volume = Column(String) - genre = Column(String) - language = Column(String) - comments = Column(String) - volumecount = Column(Integer) - criticalrating = Column(String) - country = Column(String) - alternateseries = Column(String) - alternatenumber = Column(String) - alternatecount = Column(Integer) - imprint = Column(String) - notes = Column(String) - weblink = Column(String) - format = Column(String) - manga = Column(String) - blackandwhite = Column(String) - pagecount = Column(Integer) - maturityrating = Column(String) - storyarc = Column(String) - seriesgroup = Column(String) - scaninfo = Column(String) - characters = Column(String) - teams = Column(String) - locations = Column(String) - id = Column(Integer, primary_key=True, autoincrement=True) + path = Column(String, unique=True) + tagorigin = Column(String) + series = Column(String) + issue = Column(Integer) + issuetext = Column(String) + title = Column(String) + publisher = Column(String) + month = Column(Integer) + year = Column(Integer) + day = Column(Integer) + seriesyear = Column(Integer) + issuecount = Column(Integer) + volume = Column(String) + genre = Column(String) + language = Column(String) + comments = Column(String) + volumecount = Column(Integer) + criticalrating = Column(String) + country = Column(String) + alternateseries = Column(String) + alternatenumber = Column(String) + alternatecount = Column(Integer) + imprint = Column(String) + notes = Column(String) + weblink = Column(String) + format = Column(String) + manga = Column(String) + blackandwhite = Column(String) + pagecount = Column(Integer) + maturityrating = Column(String) + storyarc = Column(String) + seriesgroup = Column(String) + scaninfo = Column(String) + characters = Column(String) + teams = Column(String) + locations = Column(String) + id = Column(Integer, primary_key=True, autoincrement=True) - def __init__(self, data): - i = 0 - try: - for column in self.__table__.columns: - if column.name == "id": - continue - setattr(self, column.name, data[i]) - i += 1 - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) +" "+ str(e)) + def __init__(self, data): + i = 0 + try: + for column in self.__table__.columns: + if column.name == "id": + continue + setattr(self, column.name, data[i]) + i += 1 + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + "Comic" + " " + str(type(e)) + " " + str(e)) - def __repr__(self): - return "".format(series=self.series, issue=self.issuetext) + def __repr__(self): + return "".format(series=self.series, issue=self.issuetext) class ComicThumbnail(Base): - __tablename__ = "comic_thumbnails" + __tablename__ = "comic_thumbnails" - comic_id = Column(Integer) - pagenumber = Column(Integer) - image = Column(BLOB) - type = Column(String) - id = Column(Integer, primary_key=True, autoincrement=True) + comic_id = Column(Integer) + pagenumber = Column(Integer) + image = Column(BLOB) + type = Column(String) + id = Column(Integer, primary_key=True, autoincrement=True) - def __init__(self, data): - i = 0 - try: - for column in self.__table__.columns: - if column.name == "id": - continue - setattr(self, column.name, data[i]) - i += 1 - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) +" "+ str(e)) + def __init__(self, data): + i = 0 + try: + for column in self.__table__.columns: + if column.name == "id": + continue + setattr(self, column.name, data[i]) + i += 1 + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + "ComicThumbnail" + " " + str(type(e)) + " " + str(e)) class Movie(Base): - __tablename__ = "movies" + __tablename__ = "movies" - path = Column(String, primary_key=True) - imdb_id = Column(String) - tmdb_id = Column(Integer) - title = Column(String) - year = Column(Integer) - length = Column(Integer) - description = Column(String) - extended = Column(Boolean) - directors_cut = Column(Boolean) - poster_path = Column(String) - backdrop_path = Column(String) + path = Column(String, primary_key=True) + tmdb_id = Column(Integer) + title = Column(String) + year = Column(Integer) + description = Column(String) + extended = Column(Boolean) + directors_cut = Column(Boolean) + poster_path = Column(String) + backdrop_path = Column(String) - def __init__(self, data): - i = 0 - try: - for column in self.__table__.columns: - setattr(self, column.name, data[i]) - i += 1 - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) +" "+ str(e)) + def __init__(self, data): + i = 0 + try: + for column in self.__table__.columns: + setattr(self, column.name, data[i]) + i += 1 + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + "Movie" + " " + str(type(e)) + " " + str(e)) class TvShow(Base): - __tablename__ = "tv_shows" + __tablename__ = "tv_shows" - imdb_id = Column(String, primary_key=True) - tmdb_id = Column(Integer) - title = Column(String) - year = Column(Integer) - description = Column(String) - poster_path = Column(String) - path = Column(String) + tmdb_id = Column(Integer, primary_key=True) + title = Column(String) + year = Column(Integer) + description = Column(String) + poster_path = Column(String) + path = Column(String) - def __init__(self, data): - i = 0 - try: - for column in self.__table__.columns: - setattr(self, column.name, data[i]) - i += 1 - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + def __init__(self, data): + i = 0 + try: + for column in self.__table__.columns: + setattr(self, column.name, data[i]) + i += 1 + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + "TvShow" + " " + str(type(e)) + " " + str(e)) class TvEpisode(Base): - __tablename__ = "tv_episodes" + __tablename__ = "tv_episodes" - imdb_id = Column(String, primary_key=True) - parent_imdb_id = Column(String) - tmdb_id = Column(Integer) - title = Column(String) - season = Column(Integer) - episode = Column(Integer) - description = Column(String) - still_path = Column(String) - path = Column(String) + tmdb_id = Column(Integer, primary_key=True) + parent_tmdb_id = Column(String) + title = Column(String) + season = Column(Integer) + episode = Column(Integer) + description = Column(String) + still_path = Column(String) + path = Column(String) - def __init__(self, data): - i = 0 - try: - for column in self.__table__.columns: - setattr(self, column.name, data[i]) - i += 1 - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + def __init__(self, data): + i = 0 + try: + for column in self.__table__.columns: + setattr(self, column.name, data[i]) + i += 1 + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + "TvEpisode" + " " + str(type(e)) + " " + str(e)) class DupComic(Base): - __tablename__ = "duplicate_comics" + __tablename__ = "duplicate_comics" - path = Column(String, unique=True) - tagorigin = Column(String) - series = Column(String) - issue = Column(Integer) - issuetext = Column(String) - title = Column(String) - publisher = Column(String) - month = Column(Integer) - year = Column(Integer) - day = Column(Integer) - seriesyear = Column(Integer) - issuecount = Column(Integer) - volume = Column(String) - genre = Column(String) - language = Column(String) - comments = Column(String) - volumecount = Column(Integer) - criticalrating = Column(String) - country = Column(String) - alternateseries = Column(String) - alternatenumber = Column(String) - alternatecount = Column(Integer) - imprint = Column(String) - notes = Column(String) - weblink = Column(String) - format = Column(String) - manga = Column(String) - blackandwhite = Column(String) - pagecount = Column(Integer) - maturityrating = Column(String) - storyarc = Column(String) - seriesgroup = Column(String) - scaninfo = Column(String) - characters = Column(String) - teams = Column(String) - locations = Column(String) - id = Column(Integer, primary_key=True, autoincrement=True) + path = Column(String, unique=True) + tagorigin = Column(String) + series = Column(String) + issue = Column(Integer) + issuetext = Column(String) + title = Column(String) + publisher = Column(String) + month = Column(Integer) + year = Column(Integer) + day = Column(Integer) + seriesyear = Column(Integer) + issuecount = Column(Integer) + volume = Column(String) + genre = Column(String) + language = Column(String) + comments = Column(String) + volumecount = Column(Integer) + criticalrating = Column(String) + country = Column(String) + alternateseries = Column(String) + alternatenumber = Column(String) + alternatecount = Column(Integer) + imprint = Column(String) + notes = Column(String) + weblink = Column(String) + format = Column(String) + manga = Column(String) + blackandwhite = Column(String) + pagecount = Column(Integer) + maturityrating = Column(String) + storyarc = Column(String) + seriesgroup = Column(String) + scaninfo = Column(String) + characters = Column(String) + teams = Column(String) + locations = Column(String) + id = Column(Integer, primary_key=True, autoincrement=True) - def __init__(self, data): - i = 0 - try: - for column in self.__table__.columns: - if column.name == "id": - continue - setattr(self, column.name, data[i]) - i += 1 - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + def __init__(self, data): + i = 0 + try: + for column in self.__table__.columns: + if column.name == "id": + continue + setattr(self, column.name, data[i]) + i += 1 + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + "DupComic" + " " + str(type(e)) + " " + str(e)) class Game(Base): - __tablename__ = "games" + __tablename__ = "games" - title = Column(String) - game_id = Column(Integer, primary_key=True) - description = Column(String) - poster_path = Column(String) - windows = Column(JSON) - mac = Column(JSON) - linux = Column(JSON) + title = Column(String) + game_id = Column(Integer, primary_key=True) + description = Column(String) + poster_path = Column(String) + path = Column(String) + windows = Column(Boolean) + mac = Column(Boolean) + linux = Column(Boolean) + title_sanitized = Column(String) - def __init__(self, data): - i = 0 - try: - for column in self.__table__.columns: - setattr(self, column.name, data[i]) - i += 1 - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + def __init__(self, data): + i = 0 + try: + for column in self.__table__.columns: + setattr(self, column.name, data[i]) + i += 1 + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + "Game" + " " + str(type(e)) + " " + str(e)) class User(Base, UserMixin): - __tablename__ = "users" + __tablename__ = "users" - id = Column(Numeric, primary_key=True) - username = Column(String) - email = Column(String, unique=True) - passwordHash = Column(String(128)) - isAdmin = Column(Boolean, default=False) + id = Column(Numeric, primary_key=True) + username = Column(String) + email = Column(String, unique=True) + passwordHash = Column(String(128)) + isAdmin = Column(Boolean, default=False) - def __init__(self, data): - i = 0 - try: - for column in self.__table__.columns: - setattr(self, column.name, data[i]) - i += 1 - pass - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + def __init__(self, data): + i = 0 + try: + for column in self.__table__.columns: + setattr(self, column.name, data[i]) + i += 1 + pass + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + "User" + " " + str(type(e)) + " " + str(e)) - def get_id(self): - return self.email + def get_id(self): + return self.email - def check_password(self, password): - if not self.passwordHash: - return - result = check_password_hash(self.passwordHash, password) - return result + def check_password(self, password): + if not self.passwordHash: + return + result = check_password_hash(self.passwordHash, password) + return result class UserTvMovieData(Base): - __tablename__ = "user_tv_movie_data" + __tablename__ = "user_tv_movie_data" - id = Column(Integer, primary_key=True, autoincrement=True) - user = Column(String) - imdb_id = Column(String) - parent_imdb = Column(String) - time = Column(Integer) - length = Column(Integer) - finished = Column(Boolean, default=False) - time_stamp = Column(DateTime) - extended = Column(Boolean, default=False) - directors_cut = Column(Boolean, default=False) + id = Column(Integer, primary_key=True, autoincrement=True) + user = Column(String) + tmdb_id = Column(String) + parent_tmdb = Column(String) + time = Column(Integer) + length = Column(Integer) + finished = Column(Boolean, default=False) + time_stamp = Column(DateTime) + extended = Column(Boolean, default=False) + directors_cut = Column(Boolean, default=False) - def __init__(self, data): - i = 0 - try: - for column in self.__table__.columns: - if column.name == "id": - continue - setattr(self, column.name, data[i]) - i += 1 - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + def __init__(self, data): + i = 0 + try: + for column in self.__table__.columns: + if column.name == "id": + continue + setattr(self, column.name, data[i]) + i += 1 + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + "UserTvMovieData" + " " + str(type(e)) + " " + str(e)) class TvMovieKeywords(Base): - __tablename__ = "tv_movie_keywords" + __tablename__ = "tv_movie_keywords" - imdb_id = Column(String) - extended = Column(Boolean, default=False) - directors_cut = Column(Boolean, default=False) - key_words = Column(ARRAY(String)) - id = Column(Integer, primary_key=True) - date = Column(TIMESTAMP) + tmdb_id = Column(String) + extended = Column(Boolean, default=False) + directors_cut = Column(Boolean, default=False) + key_words = Column(ARRAY(String)) + id = Column(Integer, primary_key=True) + date = Column(TIMESTAMP) - def __init__(self, data): - i = 0 - try: - for column in self.__table__.columns: - if column.name == "id" or column.name == "date": - continue - setattr(self, column.name, data[i]) - i += 1 - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + def __init__(self, data): + i = 0 + try: + for column in self.__table__.columns: + if column.name == "id" or column.name == "date": + continue + setattr(self, column.name, data[i]) + i += 1 + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + "TvMovieKeywords" + " " + str(type(e)) + " " + str(e)) """class UserComicData(Base): @@ -364,502 +357,580 @@ class TvMovieKeywords(Base): # return db -def get_imdb(): - db = getattr(g, '_imdb_database', None) - if db is None: - db = g._imdb_database = sqlite3.connect(IMDB_DATABASE) - - db.row_factory = sqlite3.Row - return db +# def get_imdb(): +# db = getattr(g, '_imdb_database', None) +# if db is None: +# db = g._imdb_database = sqlite3.connect(IMDB_DATABASE) +# +# db.row_factory = sqlite3.Row +# return db -def update_user_tv_movie_data(imdb_id, parent_id, time, length, finished=False, extended=False, directors_cut=False): - session = Session() - email = current_user.email - user_data = session.query(UserTvMovieData).filter(UserTvMovieData.imdb_id == imdb_id, UserTvMovieData.user == email, UserTvMovieData.extended == extended, UserTvMovieData.directors_cut == directors_cut).one_or_none() - if user_data: - user_data.time = time - user_data.finished = finished - user_data.time_stamp = datetime.datetime.now() - if not user_data.length > 0 and length > 0: - user_data.length = length - session.commit() - return user_data - else: - data = UserTvMovieData((email, imdb_id, parent_id, time, length, finished, datetime.datetime.now(), extended, directors_cut)) - session.add(data) - session.commit() - return data +def update_user_tv_movie_data(tmdb_id, parent_id, time, length, finished=False, extended=False, directors_cut=False): + session = Session() + email = current_user.email + user_data = ( + session.query(UserTvMovieData) + .filter( + UserTvMovieData.tmdb_id == tmdb_id, + UserTvMovieData.user == email, + UserTvMovieData.extended == extended, + UserTvMovieData.directors_cut == directors_cut, + ) + .one_or_none() + ) + if user_data: + user_data.time = time + user_data.finished = finished + user_data.time_stamp = datetime.datetime.now() + if not user_data.length > 0 and length > 0: + user_data.length = length + session.commit() + return user_data + else: + data = UserTvMovieData((email, tmdb_id, parent_id, time, length, finished, datetime.datetime.now(), extended, directors_cut)) + session.add(data) + session.commit() + return data def add_user(data): - session = Session() - user = User(data) - session.add(user) - session.commit() - return user + session = Session() + user = User(data) + session.add(user) + session.commit() + return user def add_movies(movies): - session = Session() - for movie_data in movies: - movie = Movie(movie_data) - session.add(movie) - session.commit() + session = Session() + for movie_data in movies: + movie = Movie(movie_data) + session.add(movie) + session.commit() def add_tv_shows(tv_show_data): - try: - session = Session() - tv_show = TvShow(tv_show_data) - session.add(tv_show) - session.commit() - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + try: + session = Session() + tv_show = TvShow(tv_show_data) + session.add(tv_show) + session.commit() + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) def add_tv_episodes(episodes): - session = Session() - for episode_data in episodes: - try: - episode = TvEpisode(episode_data) - if not session.query(TvEpisode).filter(TvEpisode.tmdb_id == episode.tmdb_id).one_or_none(): - session.add(episode) - session.commit() - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + session = Session() + for episode_data in episodes: + try: + episode = TvEpisode(episode_data) + if not session.query(TvEpisode).filter(TvEpisode.tmdb_id == episode.tmdb_id).one_or_none(): + session.add(episode) + session.commit() + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) def add_comics(meta, thumbnails): - session = Session() - data = [] - for info in meta: - issue = IssueString(info[1].issue).asFloat() - data.append([info[0], info[1].tagOrigin, info[1].series, (issue or -1), info[1].issue, info[1].title, info[1].publisher, - info[1].month, info[1].year, info[1].day, info[1].seriesYear, info[1].issueCount, info[1].volume, info[1].genre, - info[1].language, info[1].comments, info[1].volumeCount, info[1].criticalRating, info[1].country, - info[1].alternateSeries, info[1].alternateNumber, info[1].alternateCount, info[1].imprint, - info[1].notes, info[1].webLink, info[1].format, info[1].manga, info[1].blackAndWhite, - info[1].pageCount, info[1].maturityRating, info[1].storyArc, info[1].seriesGroup, info[1].scanInfo, - info[1].characters, info[1].teams, info[1].locations]) - for comic_data in data: - for i in range(len(comic_data)): - if comic_data[i] == "": - comic_data[i] = None - dup_comics = [] - for comic_data, images in zip(data, thumbnails): - try: - comic = Comic(comic_data) - if comic.publisher is None: - dup_comics.append(comic_data) - continue - session.add(comic) - session.commit() - comic_id = session.query(Comic.id).order_by(Comic.id.desc()).first()[0] - for index in range(len(images)): - thumbnail = ComicThumbnail([comic_id, index, images[index][0], images[index][1]]) - session.add(thumbnail) - session.commit() - except IntegrityError as e: - session.rollback() - dup_comics.append(comic_data) - for dup in dup_comics: - try: - dup_comic = DupComic(dup) - session.add(dup_comic) - session.commit() - except IntegrityError as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - session.rollback() - current_app.logger.info("{} comic{} added".format(len(meta), "s" if len(meta)>1 or len(meta)<1 else "")) + session = Session() + data = [] + for info in meta: + issue = IssueString(info[1].issue).asFloat() + data.append( + [ + info[0], + info[1].tagOrigin, + info[1].series, + (issue or -1), + info[1].issue, + info[1].title, + info[1].publisher, + info[1].month, + info[1].year, + info[1].day, + info[1].seriesYear, + info[1].issueCount, + info[1].volume, + info[1].genre, + info[1].language, + info[1].comments, + info[1].volumeCount, + info[1].criticalRating, + info[1].country, + info[1].alternateSeries, + info[1].alternateNumber, + info[1].alternateCount, + info[1].imprint, + info[1].notes, + info[1].webLink, + info[1].format, + info[1].manga, + info[1].blackAndWhite, + info[1].pageCount, + info[1].maturityRating, + info[1].storyArc, + info[1].seriesGroup, + info[1].scanInfo, + info[1].characters, + info[1].teams, + info[1].locations, + ] + ) + for comic_data in data: + for i in range(len(comic_data)): + if comic_data[i] == "": + comic_data[i] = None + dup_comics = [] + for comic_data, images in zip(data, thumbnails): + try: + comic = Comic(comic_data) + if comic.publisher is None: + dup_comics.append(comic_data) + continue + session.add(comic) + session.commit() + comic_id = session.query(Comic.id).order_by(Comic.id.desc()).first()[0] + for index in range(len(images)): + thumbnail = ComicThumbnail([comic_id, index, images[index][0], images[index][1]]) + session.add(thumbnail) + session.commit() + except IntegrityError as e: + session.rollback() + dup_comics.append(comic_data) + for dup in dup_comics: + try: + dup_comic = DupComic(dup) + session.add(dup_comic) + session.commit() + except IntegrityError as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + session.rollback() + current_app.logger.info("{} comic{} added".format(len(meta), "s" if len(meta) > 1 or len(meta) < 1 else "")) def add_games(games): - session = Session() - for game_data in games: - game = Game(game_data) - session.add(game) - session.commit() + session = Session() + for game_data in games: + game = Game(game_data) + session.add(game) + session.commit() + + +def update_game(game_data): + session = Session() + game = session.query(Game).filter(Game.game_id == game_data[0]).one_or_none() + game.windows = game_data[1] + game.mac = game_data[2] + game.linux = game_data[3] + session.commit() def db_get_all_comics(): - session = Session() - result = session.query(Comic).all() - return result + session = Session() + result = session.query(Comic).all() + return result def db_get_series_by_publisher(publisher): - session = Session() - result = session.query(Comic).filter(Comic.publisher == publisher).order_by(Comic.series, Comic.seriesyear, Comic.issue).distinct(Comic.series).all() - series = result - return series + session = Session() + result = ( + session.query(Comic).filter(Comic.publisher == publisher).order_by(Comic.series, Comic.seriesyear, Comic.issue).distinct(Comic.series).all() + ) + series = result + return series def db_get_comics_in_series(series, publisher, series_year): - session = Session() - result = session.query(Comic).filter(Comic.publisher == publisher, Comic.series == series, Comic.seriesyear == series_year).order_by(Comic.issue).all() - comics = result - return comics + session = Session() + result = ( + session.query(Comic).filter(Comic.publisher == publisher, Comic.series == series, Comic.seriesyear == series_year).order_by(Comic.issue).all() + ) + comics = result + return comics def get_publishers(): - session = Session() - result = session.query(Comic.publisher).distinct(Comic.publisher).order_by(Comic.publisher).all() - publishers = [r for (r,) in result] - return publishers + session = Session() + result = session.query(Comic.publisher).distinct(Comic.publisher).order_by(Comic.publisher).all() + publishers = [r for (r,) in result] + return publishers def db_get_comic_by_id(comic_id): - session = Session() - comic = session.query(Comic).filter(Comic.id == comic_id).one_or_none() - return comic + session = Session() + comic = session.query(Comic).filter(Comic.id == comic_id).one_or_none() + return comic def db_get_thumbnail_by_id_page(comic_id, pageNumber): - session = Session() - thumbnail = session.query(ComicThumbnail).filter(ComicThumbnail.comic_id == comic_id, ComicThumbnail.pagenumber == pageNumber).one_or_none() - return thumbnail + session = Session() + thumbnail = session.query(ComicThumbnail).filter(ComicThumbnail.comic_id == comic_id, ComicThumbnail.pagenumber == pageNumber).one_or_none() + return thumbnail def db_get_comic(comic_id): - session = Session() - comic = session.query(Comic).filter(Comic.id == comic_id).one_or_none() - #comic = session.query(Comic).filter(Comic.publisher == publisher, Comic.series == series, Comic.seriesyear == series_year, Comic.issue == issue).one_or_none() - return comic + session = Session() + comic = session.query(Comic).filter(Comic.id == comic_id).one_or_none() + # comic = session.query(Comic).filter(Comic.publisher == publisher, Comic.series == series, Comic.seriesyear == series_year, Comic.issue == issue).one_or_none() + return comic def comic_path_in_db(path): - try: - session = Session() - result = session.query(Comic).filter(Comic.path == path).one_or_none() - result2 = session.query(DupComic).filter(DupComic.path == path).one_or_none() - if result or result2: - return True - except Exception as e: - current_app.logger.info(path) - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return False + try: + session = Session() + result = session.query(Comic).filter(Comic.path == path).one_or_none() + result2 = session.query(DupComic).filter(DupComic.path == path).one_or_none() + if result or result2: + return True + except Exception as e: + current_app.logger.info(path) + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + return False def movie_path_in_db(path): - try: - session = Session() - result = session.query(Movie).filter(Movie.path == path).one_or_none() - if result: - return True - except Exception as e: - current_app.logger.info(path) - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return False + try: + session = Session() + result = session.query(Movie).filter(Movie.path == path).one_or_none() + if result: + return True + except Exception as e: + current_app.logger.info(path) + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + return False def tv_show_path_in_db(path): - try: - session = Session() - result = session.query(TvShow).filter(TvShow.path == path).one_or_none() - if result: - return True - except Exception as e: - current_app.logger.info(path) - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return False + try: + session = Session() + result = session.query(TvShow).filter(TvShow.path == path).one_or_none() + if result: + return True + except Exception as e: + current_app.logger.info(path) + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + return False def tv_episode_path_in_db(path): - try: - session = Session() - result = session.query(TvEpisode).filter(TvEpisode.path == path).one_or_none() - if result: - return True - except Exception as e: - current_app.logger.info(path) - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return False + try: + session = Session() + result = session.query(TvEpisode).filter(TvEpisode.path == path).one_or_none() + if result: + return True + except Exception as e: + current_app.logger.info(path) + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + return False def game_in_db(game_id): - try: - session = Session() - result = session.query(Game).filter(Game.game_id == game_id).one_or_none() - if result: - return True - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return False + try: + session = Session() + result = session.query(Game).filter(Game.game_id == game_id).one_or_none() + if result: + return True + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + return False -def imdb_get_movie(title, year): - row = get_imdb().execute("SELECT tconst, runtimeMinutes FROM title_basics WHERE (originalTitle LIKE ? OR primaryTitle LIKE ?) AND (titleType LIKE '%movie' OR titleType='video') AND startYear=?", (title, title, year)).fetchone() - return row +# def imdb_get_movie(title, year): +# row = get_imdb().execute("SELECT tconst, runtimeMinutes FROM title_basics WHERE (originalTitle LIKE ? OR primaryTitle LIKE ?) AND (titleType LIKE '%movie' OR titleType='video') AND startYear=?", (title, title, year)).fetchone() +# return row +# +# +# def imdb_get_tv_show(title, year, info={}): +# if not info: +# row = get_imdb().execute( +# "SELECT tconst FROM title_basics WHERE (originalTitle LIKE ? OR primaryTitle LIKE ?) AND (titleType LIKE 'tvSeries' OR titleType LIKE 'tvMiniSeries') AND startYear=?", +# (title, title, year)).fetchone() +# else: +# row = get_imdb().execute( +# "SELECT tconst FROM title_basics WHERE originalTitle=? AND primaryTitle=? AND titleType=? AND startYear=? AND endYear=? AND runtimeMinutes=? AND genres=?", +# (info["originalTitle"], info["primaryTitle"], info["titleType"], info["startYear"], info["endYear"], info["runtimeMinutes"], info["genres"])).fetchone() +# return row +# +# +# def imdb_get_tv_episode(imdb_id, season, episode): +# row = get_imdb().execute( +# "SELECT tconst FROM title_episode WHERE parentTconst=? AND seasonNumber=? AND episodeNumber=?", +# [imdb_id, season, episode]).fetchone() +# return row -def imdb_get_tv_show(title, year, info={}): - if not info: - row = get_imdb().execute( - "SELECT tconst FROM title_basics WHERE (originalTitle LIKE ? OR primaryTitle LIKE ?) AND (titleType LIKE 'tvSeries' OR titleType LIKE 'tvMiniSeries') AND startYear=?", - (title, title, year)).fetchone() - else: - row = get_imdb().execute( - "SELECT tconst FROM title_basics WHERE originalTitle=? AND primaryTitle=? AND titleType=? AND startYear=? AND endYear=? AND runtimeMinutes=? AND genres=?", - (info["originalTitle"], info["primaryTitle"], info["titleType"], info["startYear"], info["endYear"], info["runtimeMinutes"], info["genres"])).fetchone() - return row - - -def imdb_get_tv_episode(imdb_id, season, episode): - row = get_imdb().execute( - "SELECT tconst FROM title_episode WHERE parentTconst=? AND seasonNumber=? AND episodeNumber=?", - [imdb_id, season, episode]).fetchone() - return row - - -def tmdb_get_movie_by_imdb_id(imdb_id): - data = tmdb.get_movie_data(imdb_id) - return data - - -def tmdb_get_tv_show_by_imdb_id(imdb_id): - data = tmdb.get_tv_show_data(imdb_id) - return data - - -def tmdb_get_tv_episode_by_imdb_id(imdb_id): - data = tmdb.get_tv_episode_data(imdb_id) - return data +# def tmdb_get_movie_by_imdb_id(imdb_id): +# data = tmdb.get_movie_data(imdb_id) +# return data +# +# +# def tmdb_get_tv_show_by_imdb_id(imdb_id): +# data = tmdb.get_tv_show_data(imdb_id) +# return data +# +# +# def tmdb_get_tv_episode_by_imdb_id(imdb_id): +# data = tmdb.get_tv_episode_data(imdb_id) +# return data def db_get_all_movies(): - session = Session() - movies = session.query(Movie).order_by(Movie.title, Movie.year).all() - if current_user: - email = current_user.email - movies = [(i, session.execute("SELECT rpiwebapp.is_movie_finished('{}', '{}')".format(i.imdb_id, email)).first()[0]) for i in movies] - return movies + session = Session() + movies = session.query(Movie).order_by(Movie.title, Movie.year).all() + if current_user: + email = current_user.email + movies = [(i, session.execute("SELECT rpiwebapp.is_movie_finished({}, '{}')".format(i.tmdb_id, email)).first()[0]) for i in movies] + return movies -def db_get_movie_by_imdb_id(imdb_id, extended=False, directors_cut=False): - session = Session() - result = session.query(Movie).filter(Movie.imdb_id == imdb_id, Movie.extended == extended, - Movie.directors_cut == directors_cut).one_or_none() - return result +def db_get_movie_by_tmdb_id(tmdb_id, extended=False, directors_cut=False): + session = Session() + result = session.query(Movie).filter(Movie.tmdb_id == tmdb_id, Movie.extended == extended, Movie.directors_cut == directors_cut).one_or_none() + return result def tv_movie_sort(a): - if type(a) is tuple: - return a[0].title - return a.title + if type(a) is tuple: + return a[0].title + return a.title def get_all_tv_movies(): - session = Session() - movies = session.query(Movie).order_by(Movie.title, Movie.year).all() - shows = session.query(TvShow).order_by(TvShow.title, TvShow.year).all() - tv_movies = movies + shows - if current_user: - email = current_user.email - shows = [ - (i, session.execute("SELECT rpiwebapp.is_tv_show_finished('{}', '{}')".format(i.imdb_id, email)).first()[0]) - for i in shows] - movies = [ - (i, session.execute("SELECT rpiwebapp.is_movie_finished('{}', '{}')".format(i.imdb_id, email)).first()[0]) - for i in movies] - tv_movies = movies + shows - tv_movies = sorted(tv_movies, key=tv_movie_sort) - return tv_movies + session = Session() + movies = session.query(Movie).order_by(Movie.title, Movie.year).all() + shows = session.query(TvShow).order_by(TvShow.title, TvShow.year).all() + tv_movies = movies + shows + if current_user: + email = current_user.email + shows = [(i, session.execute("SELECT rpiwebapp.is_tv_show_finished({}, '{}')".format(i.tmdb_id, email)).first()[0]) for i in shows] + movies = [(i, session.execute("SELECT rpiwebapp.is_movie_finished({}, '{}')".format(i.tmdb_id, email)).first()[0]) for i in movies] + tv_movies = movies + shows + tv_movies = sorted(tv_movies, key=tv_movie_sort) + return tv_movies -def get_tv_movie_by_imdb_id(imdb_id, extended=False, directors_cut=False): - session = Session() - result = session.query(Movie).filter(Movie.imdb_id == imdb_id, Movie.extended == extended, - Movie.directors_cut == directors_cut).one_or_none() - if not result: - result = session.query(TvShow).filter(TvShow.imdb_id == imdb_id).one_or_none() - return result +def get_tv_movie_by_tmdb_id(tmdb_id, extended=False, directors_cut=False): + session = Session() + result = session.query(Movie).filter(Movie.tmdb_id == tmdb_id, Movie.extended == extended, Movie.directors_cut == directors_cut).one_or_none() + if not result: + result = session.query(TvShow).filter(TvShow.tmdb_id == tmdb_id).one_or_none() + return result def get_currently_watching(): - pass + pass def get_all_tv_shows(): - session = Session() - result = session.query(TvShow).order_by(TvShow.title, TvShow.year).all() - if current_user: - email = current_user.email - shows = [(i, session.execute("SELECT rpiwebapp.is_tv_show_finished('{}', '{}')".format(i.imdb_id, email)).first()[0]) for i in result] - else: - shows = result - return shows + session = Session() + result = session.query(TvShow).order_by(TvShow.title, TvShow.year).all() + if current_user: + email = current_user.email + shows = [(i, session.execute("SELECT rpiwebapp.is_tv_show_finished({}, {})".format(i.tmdb_id, email)).first()[0]) for i in result] + else: + shows = result + return shows -def get_tv_show(imdb_id): - session = Session() - result = session.query(TvShow).filter(TvShow.imdb_id == imdb_id).one_or_none() - return result +def get_tv_show(tmdb_id): + session = Session() + result = session.query(TvShow).filter(TvShow.tmdb_id == tmdb_id).one_or_none() + return result -def get_tv_show_episodes_by_imdb_id(imdb_id): - session = Session() - result = session.query(TvEpisode).filter(TvEpisode.parent_imdb_id == imdb_id).order_by(TvEpisode.season, TvEpisode.episode).all() - return result +def get_tv_show_episodes_by_tmdb_id(tmdb_id): + session = Session() + result = session.query(TvEpisode).filter(TvEpisode.parent_tmdb_id == tmdb_id).order_by(TvEpisode.season, TvEpisode.episode).all() + return result -def db_get_episode_by_imdb_id(imdb_id): - session = Session() - result = session.query(TvEpisode).filter(TvEpisode.imdb_id == imdb_id).one_or_none() - return result +def db_get_episode_by_tmdb_id(tmdb_id): + session = Session() + result = session.query(TvEpisode).filter(TvEpisode.tmdb_id == tmdb_id).one_or_none() + return result -def db_get_user_tv_movie_data(imdb_id, extended=False, directors_cut=False): - session = Session() - email = current_user.email - result = session.query(UserTvMovieData).filter(UserTvMovieData.user == email, UserTvMovieData.imdb_id == imdb_id, UserTvMovieData.extended == extended, UserTvMovieData.directors_cut == directors_cut).one_or_none() - return result +def db_get_user_tv_movie_data(tmdb_id, extended=False, directors_cut=False): + session = Session() + email = current_user.email + result = ( + session.query(UserTvMovieData) + .filter( + UserTvMovieData.user == email, + UserTvMovieData.tmdb_id == tmdb_id, + UserTvMovieData.extended == extended, + UserTvMovieData.directors_cut == directors_cut, + ) + .one_or_none() + ) + return result -def db_get_user_tv_show_episodes_data(parent_imdb_id) -> list: - session = Session() - email = current_user.email - result = session.query(UserTvMovieData).filter(UserTvMovieData.user == email, - UserTvMovieData.parent_imdb == parent_imdb_id).all() - return result +def db_get_user_tv_show_episodes_data(parent_tmdb_id) -> list: + session = Session() + email = current_user.email + result = session.query(UserTvMovieData).filter(UserTvMovieData.user == email, UserTvMovieData.parent_tmdb == parent_tmdb_id).all() + return result -def db_get_current_tv_show_episode_and_data(parent_imdb_id, episodes): - session = Session() - email = current_user.email - result = session.query(UserTvMovieData).filter(UserTvMovieData.user == email, - UserTvMovieData.parent_imdb == parent_imdb_id).all() - if not result: - return episodes[0], None - most_recent_data = result[0] - most_recent_episode = episodes[0] - for episode_data in result: - if episode_data.time_stamp and most_recent_data.time_stamp: - if episode_data.time_stamp > most_recent_data.time_stamp: - most_recent_data = episode_data - for episode in episodes: - if episode.imdb_id == most_recent_data.imdb_id: - if most_recent_data.finished: - if episode == episodes[-1]: - most_recent_episode = episodes[0] - most_recent_data = None - break - most_recent_episode = episodes[episodes.index(episode)+1] - for episode_data in result: - if most_recent_episode.imdb_id == episode_data.imdb_id: - most_recent_data = episode_data - break - else: - most_recent_data = None - break - most_recent_episode = episode - break - return most_recent_episode, most_recent_data +def db_get_current_tv_show_episode_and_data(parent_tmdb_id, episodes): + session = Session() + email = current_user.email + result = session.query(UserTvMovieData).filter(UserTvMovieData.user == email, UserTvMovieData.parent_tmdb == parent_tmdb_id).all() + if not result: + return episodes[0], None + most_recent_data = result[0] + most_recent_episode = episodes[0] + for episode_data in result: + if episode_data.time_stamp and most_recent_data.time_stamp: + if episode_data.time_stamp > most_recent_data.time_stamp: + most_recent_data = episode_data + for episode in episodes: + if episode.tmdb_id == most_recent_data.tmdb_id: + if most_recent_data.finished: + if episode == episodes[-1]: + most_recent_episode = episodes[0] + most_recent_data = None + break + most_recent_episode = episodes[episodes.index(episode) + 1] + for episode_data in result: + if most_recent_episode.tmdb_id == episode_data.tmdb_id: + most_recent_data = episode_data + break + else: + most_recent_data = None + break + most_recent_episode = episode + break + return most_recent_episode, most_recent_data def get_all_games(): - session = Session() - result = session.query(Game).order_by(Game.title).all() - return result + session = Session() + result = session.query(Game).order_by(Game.title).all() + return result + + +def get_windows_games(): + session = Session() + result = session.query(Game).filter(Game.windows == True).order_by(Game.title).all() + return result + + +def get_mac_games(): + session = Session() + result = session.query(Game).filter(Game.mac == True).order_by(Game.title).all() + return result + + +def get_linux_games(): + session = Session() + result = session.query(Game).filter(Game.linux == True).order_by(Game.title).all() + return result def get_game(game_id): - session = Session() - result = session.query(Game).filter(Game.game_id == game_id).one_or_none() - return result + session = Session() + result = session.query(Game).filter(Game.game_id == game_id).one_or_none() + return result def db_search_table_columns_by_query(query, table, columns, group=[], order=[]): - session = Session() - results = {} - final_query = "%" + query.replace(" ", "%") + "%" - for column in columns: - results[column.name] = [i[0] for i in session.query(table, over(func.rank(), partition_by=group, order_by=order)).filter(cast(column, sqlalchemy.String).ilike(final_query)).all()] - return results + session = Session() + results = {} + final_query = "%" + query.replace(" ", "%") + "%" + for column in columns: + results[column.name] = [ + i[0] + for i in session.query(table, over(func.rank(), partition_by=group, order_by=order)) + .filter(cast(column, sqlalchemy.String).ilike(final_query)) + .all() + ] + return results def db_search_comics(query): - publishers = [] - series = [] - comics = [] + publishers = [] + series = [] + comics = [] - results = db_search_table_columns_by_query(query, Comic, [Comic.publisher, Comic.title, Comic.series, Comic.year]) - series_results = db_search_table_columns_by_query(query, Comic, [Comic.publisher, Comic.title, Comic.series, Comic.year], - group=[Comic.series, Comic.seriesyear], order=[Comic.issue]) - for row in results["publisher"]: - if row["publisher"] not in publishers: - publishers.append(row.publisher) - for row in series_results["series"]: - if row not in series: - series.append(row) - for row in results["title"]: - if row not in comics: - comics.append(row) - for row in results["year"]: - if row not in comics: - comics.append(row) + results = db_search_table_columns_by_query(query, Comic, [Comic.publisher, Comic.title, Comic.series, Comic.year]) + series_results = db_search_table_columns_by_query( + query, Comic, [Comic.publisher, Comic.title, Comic.series, Comic.year], group=[Comic.series, Comic.seriesyear], order=[Comic.issue] + ) + for row in results["publisher"]: + if row["publisher"] not in publishers: + publishers.append(row.publisher) + for row in series_results["series"]: + if row not in series: + series.append(row) + for row in results["title"]: + if row not in comics: + comics.append(row) + for row in results["year"]: + if row not in comics: + comics.append(row) - return {"publisher": publishers, "series": series, "comics": comics} + return {"publisher": publishers, "series": series, "comics": comics} def db_search_movies(query): - results = db_search_table_columns_by_query(query, Movie, [Movie.title, Movie.year, Movie.description], order=[Movie.title]) - movies = [] - for movie in results["title"]: - if movie not in movies: - movies.append(movie) - for movie in results["description"]: - if movie not in movies: - movies.append(movie) - for movie in results["year"]: - if movie not in movies: - movies.append(movie) - session = Session() - email = current_user.email - movies = [(i, session.execute("SELECT rpiwebapp.is_movie_finished('{}', '{}')".format(i.imdb_id, email)).first()[0]) for i in movies] + results = db_search_table_columns_by_query(query, Movie, [Movie.title, Movie.year, Movie.description], order=[Movie.title]) + movies = [] + for movie in results["title"]: + if movie not in movies: + movies.append(movie) + for movie in results["description"]: + if movie not in movies: + movies.append(movie) + for movie in results["year"]: + if movie not in movies: + movies.append(movie) + session = Session() + email = current_user.email + movies = [(i, session.execute("SELECT rpiwebapp.is_movie_finished({}, '{}')".format(i.tmdb_id, email)).first()[0]) for i in movies] - return movies + return movies def db_search_tv_shows(query): - results = db_search_table_columns_by_query(query, TvShow, [TvShow.title, TvShow.year, TvShow.description], order=[TvShow.title]) - tv_shows = [] - for show in results["title"]: - if show not in tv_shows: - tv_shows.append(show) - for show in results["description"]: - if show not in tv_shows: - tv_shows.append(show) - for show in results["year"]: - if show not in tv_shows: - tv_shows.append(show) - session = Session() - email = current_user.email - shows = [ - (i, session.execute("SELECT rpiwebapp.is_tv_show_finished('{}', '{}')".format(i.imdb_id, email)).first()[0]) for - i in tv_shows] - return shows + results = db_search_table_columns_by_query(query, TvShow, [TvShow.title, TvShow.year, TvShow.description], order=[TvShow.title]) + tv_shows = [] + for show in results["title"]: + if show not in tv_shows: + tv_shows.append(show) + for show in results["description"]: + if show not in tv_shows: + tv_shows.append(show) + for show in results["year"]: + if show not in tv_shows: + tv_shows.append(show) + session = Session() + email = current_user.email + shows = [(i, session.execute("SELECT rpiwebapp.is_tv_show_finished({}, '{}')".format(i.tmdb_id, email)).first()[0]) for i in tv_shows] + return shows def db_search_tv_movie(query): - movies = db_search_movies(query) - shows = db_search_tv_shows(query) - tv_movies = sorted(movies + shows, key=tv_movie_sort) - return tv_movies + movies = db_search_movies(query) + shows = db_search_tv_shows(query) + tv_movies = sorted(movies + shows, key=tv_movie_sort) + return tv_movies def resize_image(image, new_width=256, new_height=256): - new_image = image - orig_height = new_image.height - orig_width = new_image.width - if orig_height >= orig_width: - width = int((orig_width / orig_height) * new_height) - height = new_height - else: - height = int((orig_height / orig_width) * new_width) - width = new_width - new_image.thumbnail(width, height) - return new_image + new_image = image + orig_height = new_image.height + orig_width = new_image.width + if orig_height >= orig_width: + width = int((orig_width / orig_height) * new_height) + height = new_height + else: + height = int((orig_height / orig_width) * new_width) + width = new_width + new_image.thumbnail(width, height) + return new_image # def fix_thumbnails(): @@ -880,11 +951,11 @@ def resize_image(image, new_width=256, new_height=256): def get_user(email): - try: - session = Session() - result = session.query(User).filter(User.email == email).one_or_none() - if result: - return result - return None - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + try: + session = Session() + result = session.query(User).filter(User.email == email).one_or_none() + if result: + return result + return None + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) diff --git a/scripts/fix_thumbnail_size.py b/scripts/fix_thumbnail_size.py index 8947674..e70cc81 100644 --- a/scripts/fix_thumbnail_size.py +++ b/scripts/fix_thumbnail_size.py @@ -1,7 +1,8 @@ +import os +import sqlite3 from io import BytesIO -from wand.image import Image -import sqlite3, os +from wand.image import Image 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): - new_image = image - orig_height = new_image.height - orig_width = new_image.width - if orig_height >= orig_width: - width = int((orig_width/orig_height) * new_height) - height = new_height - else: - height = int((orig_height/orig_width) * new_width) - width = new_width - new_image.thumbnail(width, height) - return new_image + new_image = image + orig_height = new_image.height + orig_width = new_image.width + if orig_height >= orig_width: + width = int((orig_width / orig_height) * new_height) + height = new_height + else: + height = int((orig_height / orig_width) * new_width) + width = new_width + new_image.thumbnail(width, height) + return new_image def fix_thumbnails(): - new_height = 256 - new_width = 256 - print("Start fix thumbnail size") - rows = db.execute("SELECT * FROM comic_thumbnails") - print("got list of all thumbnails\n") + new_height = 256 + new_width = 256 + print("Start fix thumbnail size") + rows = db.execute("SELECT * FROM comic_thumbnails") + print("got list of all thumbnails\n") - for row in rows: - image = Image(file=BytesIO(row["image"])) - if image.width > new_width or image.height > new_height: - 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.commit() + for row in rows: + image = Image(file=BytesIO(row["image"])) + if image.width > new_width or image.height > new_height: + 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.commit() fix_thumbnails() diff --git a/scripts/func.py b/scripts/func.py index 7fa6687..3d45983 100644 --- a/scripts/func.py +++ b/scripts/func.py @@ -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 json +import os +import pathlib +import re +from datetime import timedelta +from io import BytesIO + import enzyme import requests +from blinker import Namespace +from comicapi import comicarchive +from flask import current_app +from wand.image import Image from scripts import database @@ -22,6 +24,8 @@ games_loaded = rpi_signals.signal("games_loaded") publishers_to_ignore = ["***REMOVED***"] +API_KEY = "***REMOVED***" + # Directories 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(): - total_comics = 0 - comics_in_db = 0 - comics_added = 0 - meta = [] - thumbnails = [] - i = 0 - for root, dirs, files in os.walk(COMICS_DIRECTORY): - for f in files: - if "temp" in root: - continue - if f.endswith(".cbr"): - total_comics += 1 - path = os.path.join(root, f) - if not database.comic_path_in_db(path): - try: - test_path = path.encode("utf8") - except Exception as e: - current_app.logger.info("encoding failed on: "+path) - continue - archive = open_comic(path) - md = archive.readCIX() - if md.publisher in publishers_to_ignore: - continue - current_app.logger.info(path) - try: - meta.append((path, md)) - thumbnails.append(get_comic_thumbnails(archive)) - comics_added += 1 - i += 1 - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - continue - if i >= 2: - comic_loaded.send("anonymous", meta=meta.copy(), thumbnails=thumbnails.copy()) - meta.clear() - thumbnails.clear() - i = 0 - comics_in_db += 1 - 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("number of comics added: "+str(comics_added)) - comic_loaded.send("anonymous", meta=meta, thumbnails=thumbnails) + total_comics = 0 + comics_in_db = 0 + comics_added = 0 + meta = [] + thumbnails = [] + i = 0 + for root, dirs, files in os.walk(COMICS_DIRECTORY): + for f in files: + if "temp" in root: + continue + if f.endswith(".cbr"): + total_comics += 1 + path = os.path.join(root, f) + if not database.comic_path_in_db(path): + try: + test_path = path.encode("utf8") + except Exception as e: + current_app.logger.info("encoding failed on: " + path) + continue + archive = open_comic(path) + md = archive.readCIX() + if md.publisher in publishers_to_ignore: + continue + current_app.logger.info(path) + try: + meta.append((path, md)) + thumbnails.append(get_comic_thumbnails(archive)) + comics_added += 1 + i += 1 + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + continue + if i >= 2: + comic_loaded.send("anonymous", meta=meta.copy(), thumbnails=thumbnails.copy()) + meta.clear() + thumbnails.clear() + i = 0 + comics_in_db += 1 + 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("number of comics added: " + str(comics_added)) + comic_loaded.send("anonymous", meta=meta, thumbnails=thumbnails) -def get_comic(path): - meta = [] - thumbnails = [] - if path.endswith(".cbr"): - if not database.comic_path_in_db(path): - try: - test_path = path.encode("utf8") - except Exception as e: - current_app.logger.info("encoding failed on: "+path) - return - archive = open_comic(path) - md = archive.readCIX() - if md.publisher in publishers_to_ignore: - return - current_app.logger.info(path) - meta.append((path, md)) - try: - thumbnails.append(get_comic_thumbnails(archive)) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return - comic_loaded.send("anonymous", meta=meta, thumbnails=thumbnails) +def get_comic(path: pathlib.Path): + meta = [] + thumbnails = [] + if path.suffix == ".cbr": + if not database.comic_path_in_db(str(path)): + try: + test_path = str(path).encode("utf8") + except Exception as e: + current_app.logger.info(f"encoding failed on: {path}") + return + archive = open_comic(str(path)) + md = archive.readCIX() + if md.publisher in publishers_to_ignore: + return + current_app.logger.info(path) + meta.append((str(path), md)) + try: + thumbnails.append(get_comic_thumbnails(archive)) + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + return + comic_loaded.send("anonymous", meta=meta, thumbnails=thumbnails) def get_comic_thumbnails(comic): - thumbnails = [] - size = "256x256" - new_height = 256 - new_width = 256 - for page in range(comic.getNumberOfPages()): - image_bytes = BytesIO(comic.getPage(page)) - image = Image(file=image_bytes) - orig_height = image.height - orig_width = image.width - if orig_height >= orig_width: - width = int((orig_width/orig_height) * new_height) - height = new_height - else: - height = int((orig_height/orig_width) * new_width) - width = new_width - image.thumbnail(width, height) - thumbnails.append((image.make_blob(), "image/"+image.format)) - return thumbnails + thumbnails = [] + size = "256x256" + new_height = 256 + new_width = 256 + for page in range(comic.getNumberOfPages()): + image_bytes = BytesIO(comic.getPage(page)) + image = Image(file=image_bytes) + orig_height = image.height + orig_width = image.width + if orig_height >= orig_width: + width = int((orig_width / orig_height) * new_height) + height = new_height + else: + height = int((orig_height / orig_width) * new_width) + width = new_width + image.thumbnail(width, height) + thumbnails.append((image.make_blob(), "image/" + image.format)) + return thumbnails def open_comic(path): - archive = comicarchive.ComicArchive(path, default_image_path="static/images/icon.png") - return archive + archive = comicarchive.ComicArchive(path, default_image_path="static/images/icon.png") + return archive def get_movies(): - current_app.logger.info("start load movies") - pattern = r"(?P.+) \((?P<year>\d+)\)(?P<extended>\(extended\))?(?P<directors_cut> Director's Cut)?(?P<extension>\.mkv)" - movies = [] - total_movies = 0 - movies_in_db = 0 - movies_added = 0 - for root, dirs, files in os.walk(MOVIES_DIRECTORY): - for f in files: - if f.endswith(".mkv"): - total_movies += 1 - path = os.path.join(root, f) - if not database.movie_path_in_db(path): - try: - match = re.match(pattern, f) - if not match: - current_app.logger.info(f+" did not match regex.") - continue - current_app.logger.info("movie path: "+path) - title = match.group("title") - current_app.logger.info("movie title: "+title) - year = int(match.group("year")) - extended = False - directors_cut = False - if match.group("extended"): - 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"] + 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)" + url = "https://api.themoviedb.org/3/search/movie" + movies = [] + total_movies = 0 + movies_in_db = 0 + movies_added = 0 + for root, dirs, files in os.walk(MOVIES_DIRECTORY): + for f in files: + if f.endswith(".mkv"): + total_movies += 1 + path = os.path.join(root, f) + if not database.movie_path_in_db(path): + try: + match = re.match(pattern, f) + if not match: + current_app.logger.info(f + " did not match regex.") + continue + current_app.logger.info("movie path: " + path) + title = match.group("title") + current_app.logger.info("movie title: " + title) + year = int(match.group("year")) + extended = True if match.group("extended") else False + directors_cut = True if match.group("directors_cut") else False - tmdb_data = database.tmdb_get_movie_by_imdb_id(imdb_id) - if not tmdb_data: - current_app.logger.info("could not get tmdb data") - continue - tmdb_id = tmdb_data[0] - description = tmdb_data[1] - poster_path = tmdb_data[2] - backdrop_path = tmdb_data[3] - movies_added += 1 + data = { + "api_key": API_KEY, + "query": title, + "primary_release_year": year, + "language": "en-US", + } + r = requests.get(url, params=data) + if len(r.json()["results"]) == 0: + 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)) - if len(movies) >= 20: - movie_loaded.send("anonymous", movies=movies.copy()) - movies.clear() - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) +" "+ str(e)) - # print(e) - movies_in_db += 1 - movie_loaded.send("anonymous", movies=movies) - current_app.logger.info("finish load 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)) + tmdb_id = info["id"] + description = info["overview"] + poster_path = info["poster_path"] + backdrop_path = info["backdrop_path"] + movies_added += 1 + + movies.append((path, tmdb_id, title, year, description, extended, directors_cut, poster_path, backdrop_path,)) + if len(movies) >= 20: + movie_loaded.send("anonymous", movies=movies.copy()) + movies.clear() + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + # 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): - pattern = r"(?P<title>.+) \((?P<year>\d+)\)(?P<extended>\(extended\))?(?P<directors_cut> Director's Cut)?(?P<extension>\.mkv)" - movies = [] - if not database.movie_path_in_db(path): - try: - match = re.match(pattern, path) - if not match: - current_app.logger.info(path + " did not match regex.") - return - current_app.logger.info("movie path: " + path) - title = match.group("title") - current_app.logger.info("movie title: " + title) - year = int(match.group("year")) - extended = False - directors_cut = False - if match.group("extended"): - 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"] +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)" + url = "https://api.themoviedb.org/3/search/movie" + movies = [] + if not database.movie_path_in_db(str(path)): + try: + match = re.match(pattern, path.name) + if not match: + current_app.logger.info(f"{path.name} did not match regex.") + return + current_app.logger.info(f"movie path: {path}") + title = match.group("title") + current_app.logger.info("movie title: " + title) + year = int(match.group("year")) + extended = match.group("extended") is True + directors_cut = match.group("directors_cut") is True - tmdb_data = database.tmdb_get_movie_by_imdb_id(imdb_id) - if not tmdb_data: - current_app.logger.info("could not get tmdb data") - return - tmdb_id = tmdb_data[0] - description = tmdb_data[1] - poster_path = tmdb_data[2] - backdrop_path = tmdb_data[3] + data = { + "api_key": API_KEY, + "query": title, + "primary_release_year": year, + "language": "en-US", + } + r = requests.get(url, params=data) + 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, - poster_path, backdrop_path)) - movie_loaded.send("anonymous", movies=movies.copy()) - movies.clear() - current_app.logger.info("finish load movie") - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + tmdb_id = info["id"] + description = info["overview"] + poster_path = info["poster_path"] + backdrop_path = info["backdrop_path"] + + movies.append((str(path), tmdb_id, title, year, description, extended, directors_cut, poster_path, backdrop_path,)) + 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(): - dir_pattern = r"(?P<title>.+) \((?P<year>\d+)\)" - for dir in sorted(os.listdir(TV_SHOWS_DIRECTORY)): - dir_match = re.match(dir_pattern, dir) - if dir_match: - path = TV_SHOWS_DIRECTORY+dir - if not database.tv_show_path_in_db(path): - info = {} - if os.path.exists(path+"/info.json"): - with open(path+"/info.json") as f: - info = json.load(f) - series_name = dir_match.group("title") - series_year = int(dir_match.group("year")) - imdb_data = database.imdb_get_tv_show(series_name, series_year, info) - if not imdb_data: - current_app.logger.info("could not get imdb data for:"+series_name+" "+str(series_year)) - # print("could not get imdb data for:", series_name, series_year) - continue - imdb_id = imdb_data["tconst"] - tmdb_data = database.tmdb_get_tv_show_by_imdb_id(imdb_id) - if not tmdb_data: - current_app.logger.info("could not get tmdb data for:" + series_name + " " + str(series_year)) - # print("could not get tmdb data for:", series_name, series_year) - 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") - continue - tmdb_id = tmdb_data[0] - description = tmdb_data[1] - poster_path = tmdb_data[2] - tv_show_data = (imdb_id, 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 load tv shows.") + dir_pattern = r"(?P<title>.+) \((?P<year>\d+)\)" + search_url = "https://api.themoviedb.org/3/search/tv" + tv_url = "https://api.themoviedb.org/3/tv/" + current_app.logger.info("start loading tv shows") + for dir in sorted(os.listdir(TV_SHOWS_DIRECTORY)): + dir_match = re.match(dir_pattern, dir) + if dir_match: + path = TV_SHOWS_DIRECTORY + dir + if not database.tv_show_path_in_db(path): + json_info = {} + if os.path.exists(path + "/info.json"): + with open(path + "/info.json") as f: + json_info = json.load(f) + series_name = dir_match.group("title") + series_year = int(dir_match.group("year")) + + if not json_info: + data = { + "api_key": API_KEY, + "query": series_name, + "first_air_date_year": series_year, + "language": "en-US", + } + r = requests.get(search_url, params=data) + if len(r.json()["results"]) == 0: + current_app.logger.info(f"no tv show results for {series_name} - ({series_year})") + continue + info = r.json()["results"][0] + else: + data = {"api_key": API_KEY, "language": "en-US"} + 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(): - try: - video_pattern = r"S(?P<season>\d+)E(?P<episode>\d+) - (?P<title>.+)(?P<extension>.mp4|.mkv)" - rows = database.get_all_tv_shows() - for tv_show in rows: - episodes = [] - for video in sorted(os.listdir(tv_show.path)): - video_match = re.match(video_pattern, video) - if video_match: - path = os.path.join(tv_show.path, video) - if not database.tv_episode_path_in_db(path): - season = int(video_match.group("season")) - episode = int(video_match.group("episode")) - episode_name = video_match.group("title") - episode_imdb_data = database.imdb_get_tv_episode(tv_show.imdb_id, season, episode) - if not episode_imdb_data: - current_app.logger.info("could not get imdb data for: "+tv_show.title+" "+str(tv_show.year)+" "+str(season)+" "+str(episode)) - print("could not get imdb data for:", tv_show.title, tv_show.year, season, episode) - continue - episode_imdb_id = episode_imdb_data["tconst"] - episode_tmdb_data = database.tmdb_get_tv_episode_by_imdb_id(episode_imdb_id) - if not episode_tmdb_data: - current_app.logger.info("could not get tmdb data for: "+tv_show.title+" "+str(tv_show.year)+" "+str(season)+" "+str(episode)) - 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_show.year) + " " + str(season) + " " + str(episode) + "\n") - continue - 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 episodes") - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + video_pattern = r"S(?P<season>\d+)E(?P<episode>\d+) - (?P<title>.+)(?P<extension>.mkv)" + rows = database.get_all_tv_shows() + current_app.logger.info("start loading tv episodes") + for tv_show in rows: + try: + episodes = [] + for video in sorted(os.listdir(tv_show.path)): + video_match = re.match(video_pattern, video) + if video_match: + path = os.path.join(tv_show.path, video) + if not database.tv_episode_path_in_db(path): + season = int(video_match.group("season")) + episode = int(video_match.group("episode")) + episode_name = video_match.group("title") + current_app.logger.info(f"S{season} E{episode} - {tv_show.title}: {episode_name}") + url = f"https://api.themoviedb.org/3/tv/{tv_show.tmdb_id}/season/{season}/episode/{episode}" + + data = {"api_key": API_KEY, "language": "en-US"} + r = requests.get(url, params=data) + if "status_code" in r.json().keys(): + current_app.logger.info(f"no tv episode results for S{season} E{episode} - {tv_show.title}: {episode_name}") + continue + info = r.json() + + episode_tmdb_id = info["id"] + episode_description = info["overview"] + episode_still_path = info["still_path"] + episodes.append( + (episode_tmdb_id, tv_show.tmdb_id, episode_name, season, episode, episode_description, episode_still_path, path,) + ) + if len(episodes) >= 10: + tv_episodes_loaded.send("anonymous", tv_episodes=episodes.copy()) + episodes.clear() + tv_episodes_loaded.send("anonymous", tv_episodes=episodes) + 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): - folder, name = os.path.split(path) - video_pattern = r"S(?P<season>\d+)E(?P<episode>\d+) - (?P<title>.+)(?P<extension>.mp4|.mkv)" - video_match = re.match(video_pattern, name) - if video_match: - rows = database.get_all_tv_shows() - for tv_show in rows: - if folder == tv_show.path: - if not database.tv_episode_path_in_db(path): - episodes = [] - season = int(video_match.group("season")) - episode = int(video_match.group("episode")) - episode_name = video_match.group("title") - episode_imdb_data = database.imdb_get_tv_episode(tv_show.imdb_id, season, episode) - if not episode_imdb_data: - current_app.logger.info( - "could not get imdb data for: " + tv_show.title + " " + str(tv_show.year) + " " + str( - season) + " " + str(episode)) - print("could not get imdb data for:", tv_show.title, tv_show.year, season, episode) - return - episode_imdb_id = episode_imdb_data["tconst"] - episode_tmdb_data = database.tmdb_get_tv_episode_by_imdb_id(episode_imdb_id) - if not episode_tmdb_data: - current_app.logger.info( - "could not get tmdb data for: " + tv_show.title + " " + str(tv_show.year) + " " + str( - season) + " " + str(episode)) - 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_show.year) + " " + str(season) + " " + str(episode) + "\n") - 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_tv_episode(path: pathlib.Path): + video_pattern = r"S(?P<season>\d+)E(?P<episode>\d+) - (?P<title>.+)(?P<extension>.mkv)" + video_match = re.match(video_pattern, path.name) + if video_match: + rows = database.get_all_tv_shows() + for tv_show in rows: + if path.parent == tv_show.path: + if not database.tv_episode_path_in_db(str(path)): + episodes = [] + season = int(video_match.group("season")) + episode = int(video_match.group("episode")) + episode_name = video_match.group("title") + url = f"https://api.themoviedb.org/3/tv/{tv_show.tmdb_id}/season/{season}/episode/{episode}" + + data = {"api_key": API_KEY, "language": "en-US"} + r = requests.get(url, params=data) + if "status_code" in r.json().keys(): + current_app.logger.info(f"no tv episode results for S{season} E{episode} - {tv_show.title}: {episode_name}") + continue + info = r.json() + + episode_tmdb_id = info["id"] + episode_description = info["overview"] + episode_still_path = info["still_path"] + episodes.append( + (episode_tmdb_id, tv_show.tmdb_id, episode_name, season, episode, episode_description, episode_still_path, str(path),) + ) + tv_episodes_loaded.send("anonymous", tv_episodes=episodes) + current_app.logger.info("finished loading tv episode") def get_chapters(path): - try: - with open(path, 'rb') as f: - mkv = enzyme.MKV(f) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - mkv_info = {} - for chapter in mkv.chapters: - if chapter.string == "Intro": - mkv_info["intro"] = { - "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 == "end-credit scene": - if "end-credit scene" not in mkv_info.keys(): - mkv_info["end-credit scene"] = [] - end_credit = {"start": chapter.start.seconds} - if chapter.end: - end_credit["end"] = timedelta(microseconds=chapter.end//1000).seconds - mkv_info["end-credit scene"].append(end_credit) - return mkv_info + try: + with open(path, "rb") as f: + mkv = enzyme.MKV(f) + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + return {} + mkv_info = {} + for chapter in mkv.chapters: + if chapter.string == "Intro": + mkv_info["intro"] = { + "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 == "end-credit scene": + if "end-credit scene" not in mkv_info.keys(): + mkv_info["end-credit scene"] = [] + end_credit = {"start": chapter.start.seconds} + if chapter.end: + end_credit["end"] = timedelta(microseconds=chapter.end // 1000).seconds + mkv_info["end-credit scene"].append(end_credit) + return mkv_info def get_tags(path): - try: - with open(path, 'rb') as f: - mkv = enzyme.MKV(f) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - mkv_info = {} - for tag in mkv.tags: - if tag.targets.data[0].data == 70: - mkv_info["collection"] = {} - for simple in tag.simpletags: - if simple.name == "TITLE": - mkv_info["collection"]["title"] = simple.string - if simple.name == "TOTAL_PARTS": - mkv_info["collection"]["episodes"] = int(simple.string) - if simple.name == "KEYWORDS": - mkv_info["collection"]["key_words"] = simple.string.split(",") - if simple.name == "DATE_RELEASED": - mkv_info["collection"]["year"] = int(simple.string) - if simple.name == "SUMMARY": - mkv_info["collection"]["summary"] = simple.string - if tag.targets.data[0].data == 60: - mkv_info["season"] = {} - for simple in tag.simpletags: - if simple.name == "TITLE": - mkv_info["season"]["title"] = simple.string - if simple.name == "TOTAL_PARTS": - mkv_info["season"]["episodes"] = int(simple.string) - if tag.targets.data[0].data == 50: - mkv_info["movie"] = {} - for simple in tag.simpletags: - if simple.name == "TITLE": - mkv_info["movie"]["title"] = simple.string - if simple.name == "DATE_RELEASED": - mkv_info["movie"]["year"] = int(simple.string) - if simple.name == "PART_NUMBER": - mkv_info["movie"]["episode"] = int(simple.string) - if simple.name == "KEYWORDS": - mkv_info["movie"]["key_words"] = simple.string.split(",") - if simple.name == "SUMMARY": - mkv_info["movie"]["summary"] = simple.string - return mkv_info + try: + with open(path, "rb") as f: + mkv = enzyme.MKV(f) + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + mkv_info = {} + for tag in mkv.tags: + if tag.targets.data[0].data == 70: + mkv_info["collection"] = {} + for simple in tag.simpletags: + if simple.name == "TITLE": + mkv_info["collection"]["title"] = simple.string + if simple.name == "TOTAL_PARTS": + mkv_info["collection"]["episodes"] = int(simple.string) + if simple.name == "KEYWORDS": + mkv_info["collection"]["key_words"] = simple.string.split(",") + if simple.name == "DATE_RELEASED": + mkv_info["collection"]["year"] = int(simple.string) + if simple.name == "SUMMARY": + mkv_info["collection"]["summary"] = simple.string + if tag.targets.data[0].data == 60: + mkv_info["season"] = {} + for simple in tag.simpletags: + if simple.name == "TITLE": + mkv_info["season"]["title"] = simple.string + if simple.name == "TOTAL_PARTS": + mkv_info["season"]["episodes"] = int(simple.string) + if tag.targets.data[0].data == 50: + mkv_info["movie"] = {} + for simple in tag.simpletags: + if simple.name == "TITLE": + mkv_info["movie"]["title"] = simple.string + if simple.name == "DATE_RELEASED": + mkv_info["movie"]["year"] = int(simple.string) + if simple.name == "PART_NUMBER": + mkv_info["movie"]["episode"] = int(simple.string) + if simple.name == "KEYWORDS": + mkv_info["movie"]["key_words"] = simple.string.split(",") + if simple.name == "SUMMARY": + mkv_info["movie"]["summary"] = simple.string + return mkv_info def get_games(): - games = [] - cover_url = "https://api-v3.igdb.com/covers" - games_url = "https://api-v3.igdb.com/games" - headers = { - "accept": "application/json", - "user-key": "641f7f0e3af5273dcc1105ce851ea804" - } - i = 0 - for folder in sorted(os.listdir(GAMES_DIRECTORY), key=str.casefold): - root = os.path.join(GAMES_DIRECTORY, folder) - if os.path.isdir(os.path.join(root)): - path = os.path.join(root, "info.json") - with open(path, "r") as f: - info = json.load(f) - game_id = info["id"] - if not database.game_in_db(game_id): - 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 = None - mac = None - linux = None - if "windows" in info.keys(): - windows = info["windows"] - if "mac" in info.keys(): - mac = info["mac"] - if "linux" in info.keys(): - linux = info["linux"] - game = (info["name"], game_id, description, poster_path, windows, mac, linux) - games.append(game) - i += 1 - if i >= 5: - games_loaded.send("anonymous", games=games.copy()) - games.clear() - i = 0 - games_loaded.send("anonymous", games=games) - current_app.logger.info("finished loading games") + games = [] + cover_url = "https://api-v3.igdb.com/covers" + games_url = "https://api-v3.igdb.com/games" + headers = { + "accept": "application/json", + "user-key": "641f7f0e3af5273dcc1105ce851ea804", + } + i = 0 + current_app.logger.info("start loading games") + for folder in sorted(os.listdir(GAMES_DIRECTORY), key=str.casefold): + root = os.path.join(GAMES_DIRECTORY, folder) + if os.path.isdir(os.path.join(root)): + try: + path = os.path.join(root, "info.json") + with open(path, "r") as f: + info = json.load(f) + game_id = info["id"] + if not database.game_in_db(game_id): + 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, + root, + 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)) diff --git a/scripts/imdb_import.py b/scripts/imdb_import.py index de463b3..7e98086 100644 --- a/scripts/imdb_import.py +++ b/scripts/imdb_import.py @@ -1,4 +1,6 @@ -import sqlite3, subprocess, os +import os +import sqlite3 +import subprocess RPI_IMDB_DATABASE = "/var/lib/rpiWebApp/" 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(): - 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(["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") + 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( + ["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(): - print("start import csv") - f = open("import_csv.sql").read() - sql_script = f.format(CSV_DIRECTORY) - subprocess.run(["sudo", "-u", "http", "sqlite3", IMDB_DATABASE+"imdb.db"], input=sql_script.encode("utf8")) - print("end import csv") + print("start import csv") + f = open("import_csv.sql").read() + sql_script = f.format(CSV_DIRECTORY) + subprocess.run(["sudo", "-u", "http", "sqlite3", IMDB_DATABASE + "imdb.db"], input=sql_script.encode("utf8")) + print("end import csv") create_csv_files() diff --git a/scripts/tmdb.py b/scripts/tmdb.py index e65f7ca..505006b 100644 --- a/scripts/tmdb.py +++ b/scripts/tmdb.py @@ -1,7 +1,8 @@ -from flask import current_app -import requests import inspect +import requests +from flask import current_app + API_KEY = "***REMOVED***" TMDB_FIND_URL = "https://api.themoviedb.org/3/find/" 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): - try: - data = { - "api_key": API_KEY, - "language": "en-US", - "external_source": "imdb_id" - } - r = requests.get(TMDB_FIND_URL+imdb_id, params=data) - info = dict(r.json()) - 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"])) - return None - if info["movie_results"] == []: - current_app.logger.info("no tmdb results for: " + str(imdb_id)) - return None - current_app.logger.info("tmdb movie title: " + str(info["movie_results"][0]["title"])) - 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"] + try: + data = {"api_key": API_KEY, "language": "en-US", "external_source": "imdb_id"} + r = requests.get(TMDB_FIND_URL + imdb_id, params=data) + info = dict(r.json()) + 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"])) + return None + if info["movie_results"] == []: + current_app.logger.info("no tmdb results for: " + str(imdb_id)) + return None + current_app.logger.info("tmdb movie title: " + str(info["movie_results"][0]["title"])) + 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 - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + return movie_id, overview, poster_path, backdrop_path + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) def get_tv_show_data(imdb_id): - try: - data = { - "api_key": API_KEY, - "language": "en-US", - "external_source": "imdb_id" - } - r = requests.get(TMDB_FIND_URL+imdb_id, params=data) - info = dict(r.json()) - 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"])) - return None - if info["tv_results"] == []: - current_app.logger.info("no tmdb results for: " + str(imdb_id)) - return None - 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"] + try: + data = {"api_key": API_KEY, "language": "en-US", "external_source": "imdb_id"} + r = requests.get(TMDB_FIND_URL + imdb_id, params=data) + info = dict(r.json()) + 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"])) + return None + if info["tv_results"] == []: + current_app.logger.info("no tmdb results for: " + str(imdb_id)) + return None + 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 - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + return tv_show_id, overview, poster_path + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) def get_tv_episode_data(imdb_id): - try: - data = { - "api_key": API_KEY, - "language": "en-US", - "external_source": "imdb_id" - } - r = requests.get(TMDB_FIND_URL+imdb_id, params=data) - episode_info = dict(r.json()) - if "status_code" in episode_info.keys(): - current_app.logger.info("error getting tmdb tv episode data, status code: " + str(episode_info["status_code"])+" "+str(episode_info["status_message"])) - return None - if episode_info["tv_episode_results"] == []: - current_app.logger.info("no tmdb results for: " + str(imdb_id)) - return None - data = { - "api_key": API_KEY, - "language": "en-US" - } - r = requests.get(TMDB_GET_TV_URL+str(episode_info["tv_episode_results"][0]["show_id"]), params=data) - show_name = dict(r.json())["name"] - 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"] + try: + data = {"api_key": API_KEY, "language": "en-US", "external_source": "imdb_id"} + r = requests.get(TMDB_FIND_URL + imdb_id, params=data) + episode_info = dict(r.json()) + if "status_code" in episode_info.keys(): + current_app.logger.info( + "error getting tmdb tv episode data, status code: " + str(episode_info["status_code"]) + " " + str(episode_info["status_message"]) + ) + return None + if episode_info["tv_episode_results"] == []: + current_app.logger.info("no tmdb results for: " + str(imdb_id)) + return None + data = {"api_key": API_KEY, "language": "en-US"} + r = requests.get(TMDB_GET_TV_URL + str(episode_info["tv_episode_results"][0]["show_id"]), params=data) + show_name = dict(r.json())["name"] + 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 - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) + return tv_episode_id, overview, still_path + except Exception as e: + current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) diff --git a/static/images/Seven Seas Entertainment.png b/static/images/Seven Seas Entertainment.png new file mode 100644 index 0000000..d1e010a Binary files /dev/null and b/static/images/Seven Seas Entertainment.png differ diff --git a/static/images/default.png b/static/images/default.png index 352dc8b..7a3adac 100644 Binary files a/static/images/default.png and b/static/images/default.png differ diff --git a/templates/base.html b/templates/base.html index 135f6b2..f8a9c69 100644 --- a/templates/base.html +++ b/templates/base.html @@ -61,7 +61,7 @@ </div> <script> - var page_num = {{ page }}; + var page_num = {% if page %}{{ page }}{% else %}1{% endif %}; var max_items = {{ max_items }}; var item_count = {{ item_count }}; var start = max_items*(page_num-1); @@ -74,6 +74,10 @@ var page_container = document.getElementById("page-container"); 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; start = max_items*(page_num-1); if (item_count < max_items*page_num) { @@ -126,6 +130,7 @@ } } } + window.scrollTo(0, 0) } function offset_page(i) { diff --git a/tv_movies/templates/tv_movies/episodeViewer.html b/tv_movies/templates/tv_movies/episodeViewer.html index 39d6b5b..18b8078 100644 --- a/tv_movies/templates/tv_movies/episodeViewer.html +++ b/tv_movies/templates/tv_movies/episodeViewer.html @@ -1,11 +1,13 @@ {% extends "base.html" %} {% 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="{}"> - <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'> 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> @@ -32,7 +34,7 @@ {% endif %} {% endfor %} <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 %} {% 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-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 %} - {% 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"> <img src="/static/svg/verified.svg" > </div> @@ -71,7 +73,7 @@ {% endfor %} </div> {% 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-red" style="height: 5px; width: {{ (data.time/data.length)*100 }}%"></div> </div> @@ -83,6 +85,8 @@ </form> </div> </div> + <div class="w3-col s1 w3-hide-small m1 l2"><p></p></div> + </div> {% endblock %} @@ -133,7 +137,7 @@ //length = myPlayer.duration(); let oReq = new XMLHttpRequest(); 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(); time = myPlayer.currentTime(); } @@ -143,7 +147,7 @@ //length = myPlayer.duration(); let oReq = new XMLHttpRequest(); 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(); time = myPlayer.currentTime(); }); diff --git a/tv_movies/templates/tv_movies/index.html b/tv_movies/templates/tv_movies/index.html index cf7cf67..0e6a231 100644 --- a/tv_movies/templates/tv_movies/index.html +++ b/tv_movies/templates/tv_movies/index.html @@ -16,8 +16,8 @@ <div style="text-align: center"> {% include "pagination.html" %} </div> - <div class="container col-10"> - <div id="page-container" class="row justify-content-start"></div> + <div class="w3-container"> + <div id="page-container" style="display: flow-root; text-align: center"></div> </div> <div style="text-align: center"> {% include "pagination.html" %} @@ -34,28 +34,42 @@ function populate_page() { page_container.innerHTML = ""; 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) { - 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) { - 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) { - 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 = ``; 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"> <img src="/static/svg/verified.svg" > </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} <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'"> - <div class="card-body"> - ${tv_shows[i][0].title} (${tv_shows[i][0].year}) - </div> + <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'"> + ${text} ${finished} + ${badge} </div> </a> </div>`; diff --git a/tv_movies/templates/tv_movies/movieViewer.html b/tv_movies/templates/tv_movies/movieViewer.html index b320ae9..e102fe8 100644 --- a/tv_movies/templates/tv_movies/movieViewer.html +++ b/tv_movies/templates/tv_movies/movieViewer.html @@ -1,17 +1,19 @@ {% extends "base.html" %} {% block content %} - <div class="container" 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-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 vjs-16-9" style="display: inline-block" controls preload="auto" poster="https://image.tmdb.org/t/p/original{{ movie.backdrop_path }}" data-setup="{}"> {% 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 %} - <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 %} - <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 %} - <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 %} <p class='vjs-no-js'> To view this video please enable JavaScript, and consider upgrading to a web browser that @@ -20,7 +22,9 @@ </video> <h1>{{ movie.title }}</h1> <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> {% endblock %} @@ -60,7 +64,7 @@ length = myPlayer.duration(); let oReq = new XMLHttpRequest(); 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(); time = myPlayer.currentTime(); } @@ -70,7 +74,7 @@ length = myPlayer.duration(); let oReq = new XMLHttpRequest(); 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(); time = myPlayer.currentTime(); }); diff --git a/tv_movies/templates/tv_movies/search.html b/tv_movies/templates/tv_movies/search.html index 74f1207..8ce5778 100644 --- a/tv_movies/templates/tv_movies/search.html +++ b/tv_movies/templates/tv_movies/search.html @@ -16,9 +16,9 @@ <div style="text-align: center"> {% include "pagination.html" %} </div> - <div class="container col-10"> + <div class="w3-container"> {% 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 %} <h1>No results.</h1> {% endif %} @@ -38,28 +38,42 @@ function populate_page() { page_container.innerHTML = ""; 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) { - 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) { - 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) { - 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 = ``; 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"> <img src="/static/svg/verified.svg" > </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} <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'"> - <div class="card-body"> - ${tv_shows[i][0].title} (${tv_shows[i][0].year}) - </div> + <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'"> + ${text} ${finished} + ${badge} </div> </a> </div>`; diff --git a/tv_movies/tv_movies.py b/tv_movies/tv_movies.py index e308f0a..ed3d97b 100644 --- a/tv_movies/tv_movies.py +++ b/tv_movies/tv_movies.py @@ -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 scripts import database, func -import inspect -import datetime 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") @login_required def index(): - try: - page = request.args.get("page", 1, type=int) - max_items = request.args.get("max_items", 30, type=int) - tv = database.get_all_tv_movies() - start = (max_items * (page - 1)) - end = len(tv) if len(tv) < max_items * page else max_items * page - tv_dict = [] - for tv_item in tv: - item = tv_item[0].__dict__ - item.pop('_sa_instance_state', None) - item.pop('path', None) - 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)) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return str(type(e))+" "+str(e) + try: + page = request.args.get("page", 1, type=int) + max_items = request.args.get("max_items", 30, type=int) + tv = database.get_all_tv_movies() + start = max_items * (page - 1) + end = len(tv) if len(tv) < max_items * page else max_items * page + tv_dict = [] + for tv_item in tv: + item = tv_item[0].__dict__ + item.pop("_sa_instance_state", None) + item.pop("path", None) + 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) + ) + 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") @login_required def search(): - try: - page = request.args.get("page", 1, type=int) - max_items = request.args.get("max_items", 30, type=int) - start = 0 - end = 0 - query = request.args.get("q") - tv = [] - if query: - tv = database.db_search_tv_movie(query) - start = (max_items * (page - 1)) - end = len(tv) if len(tv) < max_items * page else max_items * page - tv_dict = [] - for tv_item in tv: - item = tv_item[0].__dict__ - item.pop('_sa_instance_state', None) - item.pop('path', None) - 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, - 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)) - return str(type(e))+" "+str(e) + try: + page = request.args.get("page", 1, type=int) + max_items = request.args.get("max_items", 30, type=int) + start = 0 + end = 0 + query = request.args.get("q") + tv = [] + if query: + tv = database.db_search_tv_movie(query) + start = max_items * (page - 1) + end = len(tv) if len(tv) < max_items * page else max_items * page + tv_dict = [] + for tv_item in tv: + item = tv_item[0].__dict__ + item.pop("_sa_instance_state", None) + item.pop("path", None) + 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, 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)) + 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 -def tv_movie_viewer(imdb_id): - try: - tv_movie = database.get_tv_movie_by_imdb_id(imdb_id) - if type(tv_movie) is database.Movie: - extended = request.args.get("extended", 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) - else: - return episode_viewer(imdb_id) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return str(type(e))+" "+str(e) +def tv_movie_viewer(tmdb_id): + try: + tv_movie = database.get_tv_movie_by_tmdb_id(tmdb_id) + if type(tv_movie) is database.Movie: + extended = request.args.get("extended", default=False, type=bool) + directors_cut = request.args.get("directors_cut", default=False, type=bool) + return movie_view(tmdb_id, extended=extended, directors_cut=directors_cut) + else: + return episode_viewer(tmdb_id) + 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 -def movie_view(imdb_id, extended=False, directors_cut=False): - try: - if request.method == "POST": - time = int(request.args.get("time", type=float)) - length = int(request.args.get("length", type=float, default=0)) - 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) - return make_response("", 201) - else: - movie_data = database.db_get_movie_by_imdb_id(imdb_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) - chapters = func.get_chapters(movie_data.path) - if not user_data: - user_data = database.update_user_tv_movie_data(movie_data.imdb_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) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return str(type(e)) + " " + str(e) +def movie_view(tmdb_id, extended=False, directors_cut=False): + try: + if request.method == "POST": + time = int(request.args.get("time", type=float)) + length = int(request.args.get("length", type=float, default=0)) + finished = True if request.args.get("finished", default="false") == "true" else False + database.update_user_tv_movie_data(tmdb_id, None, time, length, finished, extended, directors_cut) + return make_response("", 201) + else: + 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.tmdb_id, extended=extended, directors_cut=directors_cut) + chapters = func.get_chapters(movie_data.path) + if not user_data: + 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 + ) + 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 -def episode_viewer(imdb_id): - try: - if request.method == "POST": - time = int(request.args.get("time", type=float)) - parent_id = request.args.get("parent", type=str) - length = int(request.args.get("length", type=float, default=0)) - 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) - return make_response("", 201) - else: - tv_show = database.get_tv_show(imdb_id) - episodes = database.get_tv_show_episodes_by_imdb_id(imdb_id) - season_num = request.args.get("season", 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) - if not season_num and not episode_num: - (current_episode, user_data) = database.db_get_current_tv_show_episode_and_data(imdb_id, episodes) - season_num = current_episode.season - episode_num = current_episode.episode - chapters = func.get_chapters(current_episode.path) - if not user_data: - user_data = database.update_user_tv_movie_data(current_episode.imdb_id, imdb_id, 0, 0) - else: - current_episode = episodes[0] - user_data = database.UserTvMovieData(("", "", "", 0, 0, False, datetime.datetime.min)) - for episode in episodes: - if episode.season == season_num and episode.episode == episode_num: - current_episode = episode - user_data = database.db_get_user_tv_movie_data(current_episode.imdb_id) - if not user_data: - user_data = database.update_user_tv_movie_data(current_episode.imdb_id, imdb_id, 0, 0) - break - else: - for episode in episodes: - if episode.season == season_num: - current_episode = episode - episode_num = episode.episode - user_data = database.db_get_user_tv_movie_data(current_episode.imdb_id) - if not user_data: - user_data = database.update_user_tv_movie_data(current_episode.imdb_id, imdb_id, 0, 0) - break - 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) - except Exception as e: - current_app.logger.info(inspect.stack()[0][3] + " " + str(type(e)) + " " + str(e)) - return str(type(e)) + " " + str(e) +def episode_viewer(tmdb_id): + try: + if request.method == "POST": + time = int(request.args.get("time", type=float)) + parent_id = request.args.get("parent", type=str) + length = int(request.args.get("length", type=float, default=0)) + finished = True if request.args.get("finished", default="false") == "true" else False + database.update_user_tv_movie_data(tmdb_id, parent_id, time, length, finished) + return make_response("", 201) + else: + tv_show = database.get_tv_show(tmdb_id) + episodes = database.get_tv_show_episodes_by_tmdb_id(tmdb_id) + season_num = request.args.get("season", 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(tmdb_id) + if not season_num and not episode_num: + (current_episode, user_data) = database.db_get_current_tv_show_episode_and_data(tmdb_id, episodes) + season_num = current_episode.season + episode_num = current_episode.episode + chapters = func.get_chapters(current_episode.path) + if not user_data: + user_data = database.update_user_tv_movie_data(current_episode.tmdb_id, tmdb_id, 0, 0) + else: + current_episode = episodes[0] + user_data = database.UserTvMovieData(("", "", "", 0, 0, False, datetime.datetime.min, False, False)) + for episode in episodes: + if episode.season == season_num and episode.episode == episode_num: + current_episode = episode + user_data = database.db_get_user_tv_movie_data(current_episode.tmdb_id) + if not user_data: + user_data = database.update_user_tv_movie_data(current_episode.tmdb_id, tmdb_id, 0, 0) + break + else: + for episode in episodes: + if episode.season == season_num: + current_episode = episode + episode_num = episode.episode + user_data = database.db_get_user_tv_movie_data(current_episode.tmdb_id) + if not user_data: + user_data = database.update_user_tv_movie_data(current_episode.tmdb_id, tmdb_id, 0, 0) + break + 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, + ) + 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 -def get_movie(imdb_id): - extended = request.args.get("extended", 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) - filename = movie_data.path.replace(func.MOVIES_DIRECTORY, "") - response = make_response(send_from_directory(func.MOVIES_DIRECTORY, filename)) - response.headers["content-type"] = "video/webm" - return response +def get_movie(tmdb_id): + extended = request.args.get("extended", default=False, type=bool) + directors_cut = request.args.get("directors_cut", default=False, type=bool) + 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, "") + response = make_response(send_from_directory(func.MOVIES_DIRECTORY, filename)) + response.headers["content-type"] = "video/webm" + return response -@TV_Movies.route("/tv_movies/get_episode/<imdb_id>") +@TV_Movies.route("/tv_movies/get_episode/<tmdb_id>") @login_required -def get_episode(imdb_id): - episode_data = database.db_get_episode_by_imdb_id(imdb_id) - filename = episode_data.path.replace(func.TV_SHOWS_DIRECTORY, "") - response = make_response(send_from_directory(func.TV_SHOWS_DIRECTORY, filename)) - response.headers["content-type"] = "video/webm" - return response +def get_episode(tmdb_id): + episode_data = database.db_get_episode_by_tmdb_id(tmdb_id) + filename = episode_data.path.replace(func.TV_SHOWS_DIRECTORY, "") + response = make_response(send_from_directory(func.TV_SHOWS_DIRECTORY, filename)) + response.headers["content-type"] = "video/webm" + return response