Matthew Welch
5b78e61031
added swipe controls for easier use on mobile devices and better buttons for use on non mobile devices.
236 lines
6.3 KiB
Python
236 lines
6.3 KiB
Python
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/<publisher>")
|
|
@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/<int:comic_id>/<int:page_number>")
|
|
@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/<int:comic_id>/<int:page_number>/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()
|