168 lines
7.5 KiB
Python
168 lines
7.5 KiB
Python
from wtforms import SubmitField, StringField, HiddenField, validators, Form
|
|
from flask_wtf import FlaskForm
|
|
from flask import request, render_template, redirect, send_from_directory
|
|
from main import db, app, ma
|
|
from sqlalchemy import Sequence
|
|
from sqlalchemy.exc import SQLAlchemyError
|
|
from status import st, Status
|
|
import os
|
|
import glob
|
|
from PIL import Image
|
|
from pymediainfo import MediaInfo
|
|
import hashlib
|
|
import exifread
|
|
import base64
|
|
import numpy
|
|
import cv2
|
|
import time
|
|
|
|
################################################################################
|
|
# Local Class imports
|
|
################################################################################
|
|
from job import Job, Joblog, NewJob
|
|
from person import Person, PersonRefimgLink
|
|
from refimg import Refimg
|
|
from settings import Settings
|
|
|
|
################################################################################
|
|
# Class describing File in the database, and via sqlalchemy, connected to the DB as well
|
|
# This has to match one-for-one the DB table
|
|
################################################################################
|
|
class EntryDirLink(db.Model):
|
|
__tablename__ = "entry_dir_link"
|
|
entry_id = db.Column(db.Integer, db.ForeignKey("entry.id"), primary_key=True )
|
|
dir_eid = db.Column(db.Integer, db.ForeignKey("dir.eid"), primary_key=True )
|
|
|
|
def __repr__(self):
|
|
return "<entry_id: {}, dir_eid: {}>".format(self.entry_id, self.dir_eid)
|
|
|
|
class Dir(db.Model):
|
|
__tablename__ = "dir"
|
|
eid = db.Column(db.Integer, db.ForeignKey("entry.id"), primary_key=True )
|
|
path_prefix = db.Column(db.String, unique=True, nullable=False )
|
|
|
|
def __repr__(self):
|
|
return "<eid: {}, path_prefix: {}>".format(self.eid, self.path_prefix)
|
|
|
|
class Entry(db.Model):
|
|
__tablename__ = "entry"
|
|
id = db.Column(db.Integer, db.Sequence('file_id_seq'), primary_key=True )
|
|
name = db.Column(db.String, unique=False, nullable=False )
|
|
type_id = db.Column(db.Integer, db.ForeignKey("file_type.id"))
|
|
type = db.relationship("FileType")
|
|
dir_details = db.relationship( "Dir")
|
|
file_details = db.relationship( "File" )
|
|
in_dir = db.relationship ("Dir", secondary="entry_dir_link" )
|
|
|
|
def __repr__(self):
|
|
return "<id: {}, name: {}, type={}, dir_details={}, file_details={}, in_dir={}>".format(self.id, self.name, self.type, self.dir_details, self.file_details, self.in_dir)
|
|
|
|
class FileRefimgLink(db.Model):
|
|
__tablename__ = "file_refimg_link"
|
|
file_id = db.Column(db.Integer, db.ForeignKey('file.eid'), unique=True, nullable=False, primary_key=True)
|
|
refimg_id = db.Column(db.Integer, db.ForeignKey('refimg.id'), unique=True, nullable=False, primary_key=True)
|
|
when_processed = db.Column(db.Float)
|
|
matched = db.Column(db.Boolean)
|
|
def __repr__(self):
|
|
return f"<file_id: {self.file_id}, refimg_id: {self.refimg_id} when_processed={self.when_processed}, matched={self.matched}"
|
|
|
|
class File(db.Model):
|
|
__tablename__ = "file"
|
|
eid = db.Column(db.Integer, db.ForeignKey("entry.id"), primary_key=True )
|
|
size_mb = db.Column(db.Integer, unique=False, nullable=False)
|
|
thumbnail = db.Column(db.String, unique=False, nullable=True)
|
|
hash = db.Column(db.Integer)
|
|
year = db.Column(db.Integer)
|
|
month = db.Column(db.Integer)
|
|
day = db.Column(db.Integer)
|
|
woy = db.Column(db.Integer)
|
|
|
|
def __repr__(self):
|
|
return f"<eid: {self.eid}, size_mb={self.size_mb}, hash={self.hash}, year={self.year}, month={self.month}, day={self.day}, woy={self.woy}>"
|
|
|
|
class FileType(db.Model):
|
|
__tablename__ = "file_type"
|
|
id = db.Column(db.Integer, db.Sequence('file_type_id_seq'), primary_key=True )
|
|
name = db.Column(db.String, unique=True, nullable=False )
|
|
|
|
def __repr__(self):
|
|
return "<id: {}, name={}>".format(self.id, self.name )
|
|
|
|
|
|
################################################################################
|
|
# /file_list -> show detailed file list of files from import_path(s)
|
|
################################################################################
|
|
@app.route("/file_list", methods=["GET"])
|
|
def file_list():
|
|
return render_template("file_list.html", page_title='View Files (details)', entry_data=Entry.query.order_by(Entry.name).all())
|
|
|
|
################################################################################
|
|
# /files -> show thumbnail view of files from import_path(s)
|
|
################################################################################
|
|
@app.route("/files", methods=["GET", "POST"])
|
|
def files():
|
|
noo="Oldest"
|
|
grouping="Day"
|
|
how_many="50"
|
|
|
|
offset=0
|
|
|
|
if request.method=="POST":
|
|
noo=request.form['noo']
|
|
how_many=request.form['how_many']
|
|
offset=int(request.form['offset'])
|
|
grouping=request.form['grouping']
|
|
if 'prev' in request.form:
|
|
offset -= int(how_many)
|
|
if offset < 0:
|
|
offset=0
|
|
if 'next' in request.form:
|
|
offset += int(how_many)
|
|
|
|
entries=[]
|
|
if noo == "Oldest":
|
|
entries=Entry.query.join(File).order_by(File.year,File.month,File.day,Entry.name).offset(offset).limit(how_many).all()
|
|
else:
|
|
entries=Entry.query.join(File).order_by(File.year.desc(),File.month.desc(),File.day.desc(),Entry.name).offset(offset).limit(how_many).all()
|
|
return render_template("files.html", page_title='View Files', entry_data=entries, grouping=grouping, how_many=how_many, offset=offset, form=request.form )
|
|
|
|
################################################################################
|
|
# /search -> show thumbnail view of files from import_path(s)
|
|
################################################################################
|
|
@app.route("/search", methods=["GET","POST"])
|
|
def search():
|
|
|
|
file_data=Entry.query.filter(Entry.name.ilike(f"%{request.form['term']}%")).all()
|
|
ai_data=Entry.query.join(File).join(FileRefimgLink).join(Refimg).join(PersonRefimgLink).join(Person).filter(FileRefimgLink.matched==True).filter(Person.tag.ilike(f"%{request.form['term']}%")).all()
|
|
|
|
all_entries = file_data + ai_data
|
|
return render_template("files.html", page_title='View Files', entry_data=all_entries)
|
|
|
|
################################################################################
|
|
# /files/scannow -> allows us to force a check for new files
|
|
################################################################################
|
|
@app.route("/files/scannow", methods=["GET"])
|
|
def scannow():
|
|
job=NewJob("scannow" )
|
|
st.SetAlert("success")
|
|
st.SetMessage("scanning for new files in: <a href=/job/{}>Job #{}</a> (Click the link to follow progress)".format( job.id, job.id) )
|
|
return render_template("base.html")
|
|
|
|
################################################################################
|
|
# /files/forcescan -> deletes old data in DB, and does a brand new scan
|
|
################################################################################
|
|
@app.route("/files/forcescan", methods=["GET"])
|
|
def forcescan():
|
|
job=NewJob("forcescan" )
|
|
st.SetAlert("success")
|
|
st.SetMessage("force scan & rebuild data for files in: <a href=/job/{}>Job #{}</a> (Click the link to follow progress)".format( job.id, job.id) )
|
|
return render_template("base.html")
|
|
|
|
################################################################################
|
|
# /static -> returns the contents of any file referenced inside /static.
|
|
# we create/use symlinks in static/ to reference the images to show
|
|
################################################################################
|
|
@app.route("/static/<filename>")
|
|
def custom_static(filename):
|
|
return send_from_directory("static/", filename)
|