rpiwebapp-public/app.py
Matthew Welch 5b78e61031 Improved comic viewer
added swipe controls for easier use on mobile devices and better buttons for use on non mobile devices.
2019-07-16 11:15:35 -07:00

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()