|
|
|
@ -4,12 +4,13 @@ import re |
|
|
|
|
|
|
|
|
|
|
|
from PIL import Image |
|
|
|
from PIL import Image |
|
|
|
|
|
|
|
|
|
|
|
from flask import Blueprint, current_app, redirect, render_template, url_for |
|
|
|
from flask import (Blueprint, current_app, redirect, render_template, url_for, |
|
|
|
from flask import send_from_directory, Response |
|
|
|
send_from_directory, Response) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bp = Blueprint('default_routes', __name__) |
|
|
|
bp = Blueprint('default_routes', __name__) |
|
|
|
VALID_CHARS = re.compile(r"^[a-zA-Z0-9_\-\.]+$") |
|
|
|
VALID_CHARS = re.compile(r"^[a-zA-Z0-9_\-\.]+$") |
|
|
|
|
|
|
|
IMAGE_DIR = 'images' |
|
|
|
|
|
|
|
|
|
|
|
# |
|
|
|
# |
|
|
|
# Routes |
|
|
|
# Routes |
|
|
|
@ -17,20 +18,18 @@ VALID_CHARS = re.compile(r"^[a-zA-Z0-9_\-\.]+$") |
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/') |
|
|
|
@bp.route('/') |
|
|
|
def index() -> Response: |
|
|
|
def index() -> Response: |
|
|
|
album_dir = os.path.join(current_app.instance_path, 'images') |
|
|
|
image_dir = getImageDir() |
|
|
|
album_dirs = [] |
|
|
|
albums = [] |
|
|
|
|
|
|
|
entries = sorted(os.listdir(image_dir)) |
|
|
|
|
|
|
|
|
|
|
|
if os.path.isdir(album_dir): |
|
|
|
for e in entries: |
|
|
|
entries = os.listdir(album_dir) |
|
|
|
albums.append(getAlbumDetails(entries, e)) |
|
|
|
for e in entries: |
|
|
|
|
|
|
|
if os.path.isdir(os.path.join(album_dir, e)): |
|
|
|
|
|
|
|
album_dirs.append(e) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return render_template('index.j2', albums = sorted(album_dirs)) |
|
|
|
return render_template('index.j2', albums = albums) |
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/album/<path>') |
|
|
|
@bp.route('/album/<path>') |
|
|
|
def album(path:str = '') -> Response: |
|
|
|
def album(path:str = '') -> Response: |
|
|
|
image_dir = joinPath(current_app.instance_path, 'images') |
|
|
|
image_dir = getImageDir() |
|
|
|
album_dir = joinPath(image_dir, path) |
|
|
|
album_dir = joinPath(image_dir, path) |
|
|
|
images = [] |
|
|
|
images = [] |
|
|
|
|
|
|
|
|
|
|
|
@ -40,24 +39,23 @@ def album(path:str = '') -> Response: |
|
|
|
for entry in os.scandir(album_dir): |
|
|
|
for entry in os.scandir(album_dir): |
|
|
|
if entry.is_file(): |
|
|
|
if entry.is_file(): |
|
|
|
createThumbnail(entry, path) |
|
|
|
createThumbnail(entry, path) |
|
|
|
images.append(getImageDetails(entry)) |
|
|
|
images.append(entry.name) |
|
|
|
|
|
|
|
|
|
|
|
return render_template('album.j2', |
|
|
|
return render_template('album.j2', |
|
|
|
img_root = f'/image/{path}/', |
|
|
|
img_root = f'/image/{path}/', |
|
|
|
album = path, |
|
|
|
album = path, |
|
|
|
images = images |
|
|
|
images = sorted(images) |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/image/<path>/<img>') |
|
|
|
@bp.route('/image/<path>/<img>') |
|
|
|
def image(path:str, img:str) -> Response: |
|
|
|
def image(path:str, img:str) -> Response: |
|
|
|
base_dir = os.path.join(current_app.instance_path, 'images') |
|
|
|
album_dir = joinPath(getImageDir(), path) |
|
|
|
album_dir = os.path.join(base_dir, os.path.basename(path)) |
|
|
|
|
|
|
|
return send_from_directory(album_dir, img) |
|
|
|
return send_from_directory(album_dir, img) |
|
|
|
|
|
|
|
|
|
|
|
@bp.route('/thumbs/<path>/<img>') |
|
|
|
@bp.route('/thumbs/<path>/<img>') |
|
|
|
def thumbs(path:str, img:str) -> Response: |
|
|
|
def thumbs(path:str, img:str) -> Response: |
|
|
|
base_dir = os.path.join(current_app.instance_path, 'thumbnails') |
|
|
|
base_dir = joinPath(current_app.instance_path, 'thumbnails') |
|
|
|
album_dir = os.path.join(base_dir, os.path.basename(path)) |
|
|
|
album_dir = joinPath(base_dir, path) |
|
|
|
return send_from_directory(album_dir, img) |
|
|
|
return send_from_directory(album_dir, img) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -65,6 +63,9 @@ def thumbs(path:str, img:str) -> Response: |
|
|
|
# Helpers |
|
|
|
# Helpers |
|
|
|
# |
|
|
|
# |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def getImageDir() -> os.PathLike: |
|
|
|
|
|
|
|
return joinPath(current_app.instance_path, IMAGE_DIR) |
|
|
|
|
|
|
|
|
|
|
|
def joinPath(base:os.PathLike, path:str) -> os.PathLike: |
|
|
|
def joinPath(base:os.PathLike, path:str) -> os.PathLike: |
|
|
|
return os.path.join(base, os.path.basename(path)) |
|
|
|
return os.path.join(base, os.path.basename(path)) |
|
|
|
|
|
|
|
|
|
|
|
@ -83,6 +84,27 @@ def validateFile(base:os.PathLike, path:str) -> bool: |
|
|
|
|
|
|
|
|
|
|
|
return False |
|
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def getAlbumDetails(dir_list:list, album:str) -> dict: |
|
|
|
|
|
|
|
image_dir = getImageDir() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not validateDir(image_dir, album): |
|
|
|
|
|
|
|
return None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
album_dir = joinPath(image_dir, album) |
|
|
|
|
|
|
|
entries = os.scandir(album_dir) |
|
|
|
|
|
|
|
entries = sorted(os.scandir(album_dir), |
|
|
|
|
|
|
|
key=lambda e: e.name) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if len(entries) > 0: |
|
|
|
|
|
|
|
image = entries[0].name |
|
|
|
|
|
|
|
createThumbnail(entries[0], album) |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
image = None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return { 'name': album, 'image': image, 'count': len(entries) } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def getImageDetails(entry:os.PathLike) -> dict: |
|
|
|
def getImageDetails(entry:os.PathLike) -> dict: |
|
|
|
return { |
|
|
|
return { |
|
|
|
'name': entry.name, |
|
|
|
'name': entry.name, |
|
|
|
@ -104,7 +126,6 @@ def createThumbnail(image:os.DirEntry, album:str) -> None: |
|
|
|
except OSError: pass |
|
|
|
except OSError: pass |
|
|
|
|
|
|
|
|
|
|
|
with Image.open(image.path) as im: |
|
|
|
with Image.open(image.path) as im: |
|
|
|
im.thumbnail([160, 160]) |
|
|
|
im.thumbnail([300, 300]) |
|
|
|
im.save(joinPath(thumb_path, image.name), "JPEG") |
|
|
|
im.save(joinPath(thumb_path, image.name), "JPEG") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|