galamity/gallery.py

90 lines
2.4 KiB
Python

import os
import re
import mimetypes
from os.path import isdir, abspath, exists, split
from flask import Flask, render_template, abort, send_file, safe_join
from PIL import Image
from jinja2 import contextfilter, FileSystemLoader
app = Flask('gallery')
app.config.from_pyfile('gallery.cfg')
app.jinja_loader = FileSystemLoader(app.config['TEMPLATE_DIR'])
picmime = re.compile(app.config['MIME'])
base = app.config['DIRECTORY']
thumb = app.config['THUMB_DIR']
thsize = app.config['THUMB_SIZE']
def is_image(path):
return picmime.match(mimetypes.guess_type(path)[0] or 'NOPE')
def relurl(ctx, tgt):
return safe_join(ctx['path'], tgt)
@app.template_filter('gallery')
@contextfilter
def url_gallery(ctx, tgt):
return safe_join('/', relurl(ctx, tgt))
@app.template_filter('picture')
@contextfilter
def url_picture(ctx, tgt):
return safe_join('/pictures', relurl(ctx, tgt))
@app.template_filter('thumb')
@contextfilter
def url_thumb(ctx, tgt):
return safe_join('/thumb', relurl(ctx, tgt))
@app.route('/pictures/<path:tgt>')
def send_pic(tgt):
path = safe_join(base, tgt)
if is_image(path):
return send_file(path)
else:
abort(403)
def ensure_dir(path):
try:
os.makedirs(split(path)[0])
except OSError as e:
if e.errno == 17:
pass
else:
raise
@app.route('/thumb/<path:tgt>')
def send_thumb(tgt):
orig_path = safe_join(base, tgt)
if not is_image(orig_path):
abort(403)
thumb_path = safe_join(thumb, tgt)
if not exists(thumb_path) or \
os.stat(thumb_path).st_mtime < os.stat(orig_path).st_mtime:
ensure_dir(thumb_path)
image = Image.open(orig_path)
sz = image.size
scale = min(float(b) / a for a,b in zip(sz, thsize))
scale = min(scale, 1)
image.resize(list(map(int, (scale * sz[0], scale * sz[1]))), Image.ANTIALIAS).save(thumb_path)
return send_file(thumb_path)
@app.route('/')
@app.route('/<path:tgt>')
def view(tgt=''):
try:
path = abspath(safe_join(base, tgt))
names = [s for s in sorted(os.listdir(path))]
dirs = [f for f in names if isdir(safe_join(path,f))]
pics = list(filter(is_image, names))
return render_template('main.html', dirs=dirs, pics=pics, path=tgt,
parent = '/' + os.path.split(tgt)[0])
except OSError as e:
if e.errno == 2:
abort(404)
if __name__ == '__main__':
app.run('::', 8080, debug=True)