Matthew Welch
2cd339f731
Pagination has been added so that the amount of items on each page is a reasonable amount.
409 lines
13 KiB
Python
409 lines
13 KiB
Python
from flask import Flask
|
|
from flask import g
|
|
from flask_login import UserMixin
|
|
|
|
from werkzeug.security import generate_password_hash, check_password_hash
|
|
from io import BytesIO
|
|
from wand.image import Image
|
|
import sqlite3
|
|
import os, time
|
|
|
|
from comicapi.issuestring import IssueString
|
|
|
|
from scripts import tmdb
|
|
|
|
RPI_DATABASE = "/var/lib/rpiWebApp/database.db"
|
|
RPI_IMDB_DATABASE = "/var/lib/rpiWebApp/imdb.db"
|
|
|
|
MC_DATABASE = "***REMOVED***"
|
|
MC_IMDB_DATABASE = "C:\\Users\\Matthew\\Documents\\MyPrograms\\Websites\\rpi_web_interface\\imdb.db"
|
|
|
|
DATABASE = RPI_DATABASE if os.path.exists(RPI_DATABASE) else MC_DATABASE
|
|
IMDB_DATABASE = RPI_IMDB_DATABASE if os.path.exists(RPI_IMDB_DATABASE) else MC_IMDB_DATABASE
|
|
|
|
|
|
def get_db():
|
|
db = getattr(g, '_database', None)
|
|
if db is None:
|
|
db = g._database = sqlite3.connect(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 initialize_db():
|
|
get_db().execute("""CREATE TABLE IF NOT EXISTS "comics" (
|
|
"path" TEXT UNIQUE,
|
|
"tagOrigin" TEXT,
|
|
"series" TEXT,
|
|
"issue" REAL,
|
|
"issueText" TEXT,
|
|
"title" TEXT,
|
|
"publisher" TEXT,
|
|
"month" INTEGER,
|
|
"year" INTEGER,
|
|
"day" INTEGER,
|
|
"seriesYear" INTEGER,
|
|
"issueCount" INTEGER,
|
|
"volume" TEXT,
|
|
"genre" TEXT,
|
|
"language" TEXT,
|
|
"comments" TEXT,
|
|
"volumeCount" INTEGER,
|
|
"criticalRating" TEXT,
|
|
"country" TEXT,
|
|
"alternateSeries" TEXT,
|
|
"alternateNumber" TEXT,
|
|
"alternateCount" INTEGER,
|
|
"imprint" TEXT,
|
|
"notes" TEXT,
|
|
"webLink" TEXT,
|
|
"format" TEXT,
|
|
"manga" TEXT,
|
|
"blackAndWhite" TEXT,
|
|
"pageCount" INTEGER,
|
|
"maturityRating" TEXT,
|
|
"storyArc" TEXT,
|
|
"seriesGroup" TEXT,
|
|
"scanInfo" TEXT,
|
|
"characters" TEXT,
|
|
"teams" TEXT,
|
|
"locations" TEXT,
|
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE
|
|
)""")
|
|
get_db().execute("""CREATE TABLE IF NOT EXISTS "credits" (
|
|
"id" INTEGER NOT NULL,
|
|
"role" TEXT,
|
|
"name" TEXT,
|
|
"primary" INTEGER NOT NULL
|
|
)""")
|
|
get_db().execute("""CREATE TABLE IF NOT EXISTS "comic_thumbnails" (
|
|
"id" INTEGER,
|
|
"pageNumber" INTEGER,
|
|
"image" BLOB,
|
|
"type" TEXT
|
|
)""")
|
|
get_db().execute("""CREATE TABLE IF NOT EXISTS "users" (
|
|
"username" TEXT UNIQUE PRIMARY KEY,
|
|
"passwordHash" VARCHAR(128),
|
|
"isAdmin" INTEGER NOT NULL DEFAULT 0
|
|
)""")
|
|
get_db().execute("""CREATE TABLE IF NOT EXISTS "movies" (
|
|
"path" TEXT,
|
|
"imdb_id" INTEGER,
|
|
"tmdb_id" INTEGER,
|
|
"title" TEXT,
|
|
"year" INTEGER,
|
|
"length" INTEGER,
|
|
"description" TEXT,
|
|
"extended" INTEGER,
|
|
"directors_cut" INTEGER,
|
|
"poster_path" TEXT,
|
|
"backdrop_path" TEXT
|
|
)""")
|
|
get_db().execute("CREATE INDEX IF NOT EXISTS path_index ON comics(path);")
|
|
get_db().execute("CREATE INDEX IF NOT EXISTS id_index ON comic_thumbnails(id);")
|
|
get_db().commit()
|
|
|
|
get_imdb().execute("CREATE INDEX IF NOT EXISTS original_title_index ON title_basics(originalTitle)")
|
|
get_imdb().execute("CREATE INDEX IF NOT EXISTS primary_title_index ON title_basics(primaryTitle)")
|
|
get_imdb().commit()
|
|
|
|
|
|
def table_exists(table_name):
|
|
cursor = get_db().execute("SELECT name FROM sqlite_master WHERE type='table' AND name='{}'".format(table_name))
|
|
get_db().commit()
|
|
if cursor.rowcount == 0:
|
|
return False
|
|
return True
|
|
|
|
|
|
def add_movies(movies):
|
|
for movie in movies:
|
|
get_db().execute("INSERT INTO movies(path, imdb_id, tmdb_id, title, year, length, description, extended, directors_cut, poster_path, backdrop_path) VALUES(?,?,?,?,?,?,?,?,?,?,?)",
|
|
(movie[0], movie[1], movie[2], movie[3], movie[4], movie[5], movie[6], movie[7], movie[8], movie[9], movie[10]))
|
|
get_db().commit()
|
|
|
|
|
|
def add_comics(meta, thumbnails):
|
|
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 in data:
|
|
for i in range(len(comic)):
|
|
if comic[i] == "":
|
|
comic[i] = None
|
|
for comic, images in zip(data, thumbnails):
|
|
get_db().execute("""INSERT INTO comics(path, tagOrigin, series, issue, issueText, title, publisher,
|
|
month, year, day, seriesYear, issueCount, volume, genre, language, comments, volumeCount,
|
|
criticalRating, country, alternateSeries, alternateNumber, alternateCount, imprint,
|
|
notes, webLink, format, manga, blackAndWhite, pageCount, maturityRating, storyArc,
|
|
seriesGroup, scanInfo, characters, teams, locations)
|
|
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""", comic)
|
|
get_db().commit()
|
|
comic_id = get_db().execute("SELECT id from comics ORDER BY id DESC LIMIT 1").fetchone()[0]
|
|
for index in range(len(images)):
|
|
get_db().execute("INSERT INTO comic_thumbnails(id, pageNumber, image, type) VALUES (?,?,?,?)", (comic_id, index, images[index][0], images[index][1]))
|
|
get_db().commit()
|
|
print("#"*18)
|
|
print("# {} comic{} added #".format(len(meta), "s" if len(meta)>1 else ""))
|
|
print("#"*18)
|
|
|
|
|
|
def add_comic_thumbnails(thumbnails):
|
|
comic_id = 1
|
|
row = get_db().execute("SELECT id from comic_thumbnails ORDER BY id DESC LIMIT 1").fetchone()
|
|
if row:
|
|
comic_id = row[0]+1
|
|
print("start comics added:", len(thumbnails))
|
|
for images in thumbnails:
|
|
print("pages in comic:", len(images))
|
|
for index in range(len(images)):
|
|
print("comic page added:", index)
|
|
get_db().execute("INSERT INTO comic_thumbnails(id, pageNumber, image) VALUES (?,?,?)", (comic_id, index, images[index]))
|
|
comic_id += 1
|
|
get_db().commit()
|
|
|
|
|
|
def db_get_all_comics():
|
|
result = get_db().execute("SELECT * FROM comics ORDER BY series, issue").fetchall()
|
|
get_db().commit()
|
|
return result
|
|
|
|
|
|
def db_get_series_by_publisher(publisher):
|
|
series = []
|
|
rows = get_db().execute("SELECT publisher, series, seriesYear, id, min(issue) FROM comics WHERE publisher=? GROUP BY publisher, series, seriesYear ORDER BY series, seriesYear", [publisher]).fetchall()
|
|
for row in rows:
|
|
series.append(row)
|
|
return series
|
|
|
|
|
|
def db_get_comics_in_series(series, publisher, series_year):
|
|
comics = []
|
|
rows = get_db().execute("SELECT * FROM comics WHERE series=? AND publisher=? AND seriesYear=? ORDER BY series, issue", [series, publisher, series_year]).fetchall()
|
|
get_db().commit()
|
|
for row in rows:
|
|
comics.append(row)
|
|
return comics
|
|
|
|
|
|
def get_publishers():
|
|
publishers = []
|
|
rows = get_db().execute("SELECT DISTINCT publisher FROM comics ORDER BY publisher").fetchall()
|
|
|
|
for row in rows:
|
|
publishers.append(row[0])
|
|
return publishers
|
|
|
|
|
|
def db_get_comic_by_id(comic_id):
|
|
row = get_db().execute("SELECT * FROM comics WHERE id=?", [comic_id]).fetchone()
|
|
return row
|
|
|
|
|
|
def db_get_thumbnail_by_id_page(comic_id, pageNumber):
|
|
row = get_db().execute("SELECT * FROM comic_thumbnails WHERE id=? AND pageNumber=?", [comic_id, pageNumber]).fetchone()
|
|
return row
|
|
|
|
|
|
def db_get_comic(publisher, series, series_year, issue):
|
|
row = get_db().execute("SELECT * FROM comics WHERE publisher=? AND series=? AND seriesYear=? AND issue=?",
|
|
[publisher, series, series_year, issue]).fetchone()
|
|
return row
|
|
|
|
|
|
def comic_path_in_db(path):
|
|
try:
|
|
result = get_db().execute("SELECT path FROM comics WHERE path=?", [path])
|
|
get_db().commit()
|
|
if result.fetchone():
|
|
return True
|
|
except Exception as e:
|
|
print(path)
|
|
print(e)
|
|
return False
|
|
|
|
|
|
def movie_path_in_db(path):
|
|
try:
|
|
result = get_db().execute("SELECT path FROM movies WHERE path=?", [path])
|
|
get_db().commit()
|
|
if result.fetchone():
|
|
return True
|
|
except Exception as e:
|
|
print(path)
|
|
print(e)
|
|
return False
|
|
|
|
|
|
def verify_paths():
|
|
rows = get_db().execute("SELECT path FROM comics").fetchall()
|
|
get_db().commit()
|
|
for row in rows:
|
|
if not os.path.exists(row["path"]):
|
|
get_db().execute("DELETE FROM comic_thumbnails WHERE id IN (SELECT id FROM comics WHERE path=?)", [row["path"]])
|
|
get_db().execute("DELETE FROM comics WHERE path=?", [row["path"]])
|
|
get_db().commit()
|
|
|
|
|
|
def verify_path(path):
|
|
if not os.path.exists(path):
|
|
row = get_db().execute("SELECT path FROM comics WHERE path=?", [path]).fetchone()
|
|
get_db().commit()
|
|
if row:
|
|
get_db().execute("DELETE FROM comic_thumbnails WHERE id IN (SELECT id FROM comics WHERE path=?)", [path])
|
|
get_db().execute("DELETE FROM comics WHERE path=?", [path])
|
|
get_db().commit()
|
|
|
|
|
|
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 tmdb_get_movie_by_imdb_id(imdb_id):
|
|
data = tmdb.get_movie_data(imdb_id)
|
|
return data
|
|
|
|
|
|
def db_get_all_movies():
|
|
rows = get_db().execute("SELECT * FROM movies ORDER BY title, year;").fetchall()
|
|
return rows
|
|
|
|
|
|
def db_get_movie_by_imdb_id(imdb_id, extended=0, directors_cut=0):
|
|
row = get_db().execute("SELECT * FROM movies WHERE imdb_id=? AND extended=? AND directors_cut=?", [imdb_id, extended, directors_cut]).fetchone()
|
|
return row
|
|
|
|
|
|
def db_search_table_columns_by_query(query, table, columns, group="", order=""):
|
|
results = {}
|
|
final_query = "%"+query.replace(" ", "%")+"%"
|
|
sqlite_base_statement = "SELECT * FROM "+table+" WHERE {condition} {group} {order}"
|
|
if not group == "":
|
|
group = "GROUP BY "+group
|
|
if not order == "":
|
|
order = "ORDER BY "+order
|
|
for column in columns:
|
|
sqlite_statement = sqlite_base_statement.format(condition=column+" LIKE '"+final_query+"'", group=group, order=order)
|
|
results[column] = get_db().execute(sqlite_statement).fetchall()
|
|
|
|
# sqlite_condition = ""
|
|
# for column in columns:
|
|
# sqlite_condition += column+" LIKE '"+final_query+"'"+(" OR " if column != columns[-1] else "")
|
|
# sqlite_statement = "SELECT * FROM {table} WHERE {condition}".format(table=table, condition=sqlite_condition)
|
|
# rows = get_db().execute(sqlite_statement).fetchall()
|
|
return results
|
|
|
|
|
|
def db_search_comics(query):
|
|
publishers = []
|
|
series = []
|
|
comics = []
|
|
|
|
results = db_search_table_columns_by_query(query, "comics", ["publisher", "title", "series", "year"])
|
|
series_results = db_search_table_columns_by_query(query, "comics", ["publisher", "title", "series", "year"],
|
|
group="series, seriesYear", order="issue")
|
|
|
|
for row in results["publisher"]:
|
|
if row["publisher"] not in publishers:
|
|
publishers.append(row["publisher"])
|
|
for row in series_results["series"]:
|
|
dict = {"publisher": row["publisher"],"series": row["series"],"seriesYear": row["seriesYear"],"id": row["id"]}
|
|
if dict not in series:
|
|
series.append(dict)
|
|
for row in results["title"]:
|
|
dict = {"publisher": row["publisher"],"series": row["series"],"seriesYear": row["seriesYear"],"issue": row["issue"],"id": row["id"],"title": row["title"]}
|
|
if dict not in comics:
|
|
comics.append(dict)
|
|
for row in results["year"]:
|
|
dict = {"publisher": row["publisher"],"series": row["series"],"seriesYear": row["seriesYear"],"issue": row["issue"],"id": row["id"],"title": row["title"]}
|
|
if dict not in comics:
|
|
comics.append(dict)
|
|
|
|
return {"publisher": publishers, "series": series, "comics": comics}
|
|
|
|
|
|
def db_search_movies(query):
|
|
results = db_search_table_columns_by_query(query, "movies", ["title", "year", "description"], order="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)
|
|
return 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
|
|
|
|
|
|
def fix_thumbnails():
|
|
new_height = 256
|
|
new_width = 256
|
|
print("Start fix thumbnail size")
|
|
rows = get_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"])
|
|
get_db().execute("UPDATE comic_thumbnails SET image=? WHERE id=? AND pageNumber=?",
|
|
[resize_image(image, new_width, new_height).make_blob(), row["id"], row["pageNumber"]])
|
|
get_db().commit()
|
|
print("Finished fix thumbnail size")
|
|
|
|
|
|
def get_user(username):
|
|
user_data = get_db().execute("SELECT * FROM users WHERE username=?", [username]).fetchone()
|
|
if user_data:
|
|
return User(user_data)
|
|
return None
|
|
|
|
|
|
class User(UserMixin):
|
|
def __init__(self, user):
|
|
self.username = user["username"]
|
|
self.password_hash = user["passwordHash"]
|
|
self.is_admin = user["isAdmin"]
|
|
|
|
def get_id(self):
|
|
return self.username
|
|
|
|
def check_password(self, password):
|
|
result = check_password_hash(self.password_hash, password)
|
|
return result
|