from flask import Flask from flask import render_template, request, g, redirect, url_for, make_response, flash, session from flask_login import LoginManager, current_user, login_user, logout_user, login_required from flask_log import Logging from werkzeug.useragents import UserAgent from urllib import parse from io import BytesIO from wand.image import Image import threading, os, datetime, pytz import scripts.func as func from scripts import database app = Flask(__name__) app.config["SECRET_KEY"] = "***REMOVED***" app.config["FLASK_LOG_LEVEL"] = "DEBUG" flask_log = Logging(app) login_manager = LoginManager(app) login_manager.login_view = "login" MOBILE_DEVICES = ["android", "blackberry", "ipad", "iphone"] def get_comics(): with app.app_context(): func.get_comics() def verify_paths(): with app.app_context(): database.verify_paths() with app.app_context(): app.logger.debug("server start") database.initialize_db() thread = threading.Thread(target=get_comics, args=()) thread.daemon = True thread.start() thread2 = threading.Thread(target=verify_paths, args=()) thread2.daemon = True thread2.start() @app.teardown_appcontext def close_connection(exception): 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: print(e) func.comic_loaded.connect(update_comic_db) @login_manager.user_loader def load_user(username): return database.get_user(username) @app.route("/login", methods=["GET", "POST"]) def login(): try: if request.method == "POST": username = request.form.get("username") password = request.form.get("password") user = database.get_user(username) if user is None or not user.check_password(password): flash("invalid username or password") return redirect(url_for("login")) login_user(user) 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") except Exception as e: return str(e) @app.route("/logout") def logout(): try: logout_user() return redirect(url_for("login")) except Exception as e: return str(e) @app.route("/") def root(): return redirect(url_for("home")) @app.route("/home") @login_required def home(): try: return render_template("home.html", title="Hello World", current_user=current_user) except Exception as e: return str(e) @app.route("/movies") @login_required def movies(): return "No Movies" @app.route("/music") @login_required def music(): return "No music" @app.route("/games") @login_required def games(): return "No Games" @app.route("/comics") @login_required def comics(): polling = request.args.get("polling") if polling: try: return render_template("publisherList.html", comics=database.get_publishers()) except Exception as e: print(e) return str(e) try: return render_template("publisherView.html", title="Comics", comics=database.get_publishers()) except Exception as e: print(e) return str(e) @app.route("/comics/") def comic_reroute(): return redirect(url_for("comics")) @app.route("/comics/") @login_required def comics_publisher(publisher): 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") if series: if issue: if page_number: return comic_viewer(publisher, series, series_year, issue) return comic_gallery(publisher, series, series_year, issue) return render_template("seriesView.html", title="Comics", comics=database.db_get_comics_in_series(series, publisher, series_year)) return render_template("publisherSeriesView.html", title="Comics", comics=database.db_get_series_by_publisher(publisher)) def comic_viewer(publisher, series, series_year, issue): try: on_mobile = False if request.user_agent.platform in MOBILE_DEVICES: on_mobile = True publisher_parsed = parse.quote(publisher) series_parsed = parse.quote(series) page_number = int(request.args.get("pageNumber")) meta = database.db_get_comic(publisher, series, series_year, issue) page_count = int(meta["pageCount"]) prev_page = page_number - 1 next_page = page_number + 1 if next_page >= page_count: next_page = 0 if prev_page < 0: prev_page = page_count - 1 prev_url = "/comics/{}?series={}&seriesYear={}&issue={}&pageNumber={}".format(publisher_parsed, series_parsed, series_year, issue, prev_page) next_url = "/comics/{}?series={}&seriesYear={}&issue={}&pageNumber={}".format(publisher_parsed, series_parsed, series_year, issue, next_page) return render_template("comicView.html", title="Comics", on_mobile=on_mobile, prev_url=prev_url, next_url=next_url, comic=meta, page_number=page_number) except Exception as e: print(e) return str(e) def comic_gallery(publisher, series, series_year, issue): try: meta = database.db_get_comic(publisher, series, series_year, issue) return render_template("comicGallery.html", title="Comics", comic=meta) except Exception as e: print(e) return str(e) @app.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"]) byteImage = BytesIO(comic.getPage(page_number)) image = Image(file=byteImage) response = make_response(image.make_blob()) 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"] = "image/"+image.format return response @app.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"] return response if __name__ == '__main__': app.run()