|
|
|
|
@ -1,16 +1,18 @@
|
|
|
|
|
import os |
|
|
|
|
import re |
|
|
|
|
import yaml |
|
|
|
|
|
|
|
|
|
from flask import Blueprint, current_app, render_template |
|
|
|
|
from flask import Blueprint, current_app, escape, flash, render_template |
|
|
|
|
from flask import jsonify |
|
|
|
|
|
|
|
|
|
from .. import util |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VIDEO_EXTENSIONS = ['.avi', '.m4v', '.mkv', '.mp4', '.mpg'] |
|
|
|
|
MAX_RECURSE_DEPTH = 5 |
|
|
|
|
bp = Blueprint('file_listing', __name__) |
|
|
|
|
bp = Blueprint('file_listing', __name__, url_prefix='/file_listing') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class path_entry: |
|
|
|
|
class path_entry(object): |
|
|
|
|
def __init__(self): |
|
|
|
|
self.base_name = '' |
|
|
|
|
self.rel_path = '' # NOTE: fs path relative to config['MOVIE_DIR'] |
|
|
|
|
@ -20,7 +22,7 @@ class path_entry:
|
|
|
|
|
self.contents = [] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/file_listing') |
|
|
|
|
@bp.route('/') |
|
|
|
|
def index(): |
|
|
|
|
# construct tree of path_entry objects |
|
|
|
|
video_path = current_app.config['MOVIE_DIR'] |
|
|
|
|
@ -34,9 +36,57 @@ def index():
|
|
|
|
|
return render_template( |
|
|
|
|
'file_listing/index.html', |
|
|
|
|
paths=paths, |
|
|
|
|
debug_str=yaml.dump(paths) |
|
|
|
|
debug_str=util.dumpObject(paths) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/folder_contents/') |
|
|
|
|
def getBaseFolderContents(): |
|
|
|
|
full_path = current_app.config['MOVIE_DIR'] |
|
|
|
|
paths = [] |
|
|
|
|
|
|
|
|
|
# validate input |
|
|
|
|
if not os.path.exists(full_path): |
|
|
|
|
flash('invalid path') |
|
|
|
|
else: |
|
|
|
|
for entry in os.scandir(full_path): |
|
|
|
|
paths.append(getPathInfo(entry, MAX_RECURSE_DEPTH)) |
|
|
|
|
|
|
|
|
|
return render_template( |
|
|
|
|
'file_listing/folder_contents.html', |
|
|
|
|
paths=paths, |
|
|
|
|
debug_str=util.dumpObject(paths) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# NOTE: return a listing of files and directories in a sub_directory as JSON |
|
|
|
|
# @param subpath a path relative to config['MOVIE_DIR'] |
|
|
|
|
@bp.route('/folder_contents/<path:subpath>') |
|
|
|
|
def getFolderJSON(subpath = ''): |
|
|
|
|
video_path = current_app.config['MOVIE_DIR'] |
|
|
|
|
full_path = os.path.join(video_path, subpath) |
|
|
|
|
paths = [] |
|
|
|
|
|
|
|
|
|
# validate input |
|
|
|
|
if re.search('\.\.', subpath) or not os.path.exists(full_path): |
|
|
|
|
flash('invalid path') |
|
|
|
|
else: |
|
|
|
|
for entry in os.scandir(full_path): |
|
|
|
|
# TODO: remove 'getPathInfo()' when finished with async file listing |
|
|
|
|
# make sure to continue to test for '.' and symlinks |
|
|
|
|
logger.info(entry) |
|
|
|
|
pe = getPathInfo(entry, MAX_RECURSE_DEPTH) |
|
|
|
|
if pe: |
|
|
|
|
paths.append({ |
|
|
|
|
'base_name': pe.base_name, |
|
|
|
|
'rel_path': pe.rel_path, |
|
|
|
|
'file_extension': pe.file_extension, |
|
|
|
|
'is_dir': pe.is_dir, |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
return jsonify(paths) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def getPathInfo(entry, depth=0): |
|
|
|
|
if not entry.name.startswith('.') and not entry.is_symlink(): |
|
|
|
|
video_path = current_app.config['MOVIE_DIR'] |
|
|
|
|
|