mirror of
https://github.com/Derpy-Leggies/OnlyLegs.git
synced 2025-06-29 03:26:16 +00:00
Remove Thumbnails table
Daddy PyLint not happy with me
This commit is contained in:
parent
db20ce7919
commit
3331edf24d
7 changed files with 104 additions and 144 deletions
|
@ -69,15 +69,14 @@ def create_app(test_config=None):
|
||||||
# Error handlers
|
# Error handlers
|
||||||
@app.errorhandler(Exception)
|
@app.errorhandler(Exception)
|
||||||
def error_page(err):
|
def error_page(err):
|
||||||
# If the error is a HTTP error, return the error page
|
# If the error is not an HTTPException, return a 500 error
|
||||||
if isinstance(err, HTTPException):
|
if not isinstance(err, HTTPException):
|
||||||
|
abort(500)
|
||||||
|
|
||||||
error = err.code
|
error = err.code
|
||||||
msg = err.description
|
msg = err.description
|
||||||
return render_template('error.html', error=error, msg=msg), err.code
|
return render_template('error.html', error=error, msg=msg), err.code
|
||||||
|
|
||||||
# Otherwise this an internal error
|
|
||||||
abort(500)
|
|
||||||
|
|
||||||
# Load login, registration and logout manager
|
# Load login, registration and logout manager
|
||||||
from gallery import auth
|
from gallery import auth
|
||||||
app.register_blueprint(auth.blueprint)
|
app.register_blueprint(auth.blueprint)
|
||||||
|
|
|
@ -60,20 +60,6 @@ class Posts (base): # pylint: disable=too-few-public-methods, C0103
|
||||||
post_alt = Column(String, nullable=False)
|
post_alt = Column(String, nullable=False)
|
||||||
|
|
||||||
junction = relationship('GroupJunction', backref='posts')
|
junction = relationship('GroupJunction', backref='posts')
|
||||||
thumbnail = relationship('Thumbnails', backref='posts')
|
|
||||||
|
|
||||||
|
|
||||||
class Thumbnails (base): # pylint: disable=too-few-public-methods, C0103
|
|
||||||
"""
|
|
||||||
Thumbnail table
|
|
||||||
"""
|
|
||||||
__tablename__ = 'thumbnails'
|
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True)
|
|
||||||
file_name = Column(String, unique=True, nullable=False)
|
|
||||||
file_ext = Column(String, nullable=False)
|
|
||||||
resolution = Column(PickleType, nullable=False)
|
|
||||||
post_id = Column(Integer, ForeignKey('posts.id'))
|
|
||||||
|
|
||||||
|
|
||||||
class Groups (base): # pylint: disable=too-few-public-methods, C0103
|
class Groups (base): # pylint: disable=too-few-public-methods, C0103
|
||||||
|
|
|
@ -4,9 +4,9 @@ Onlylegs - API endpoints
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
import platformdirs
|
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime as dt
|
from datetime import datetime as dt
|
||||||
|
import platformdirs
|
||||||
|
|
||||||
from flask import Blueprint, send_from_directory, abort, flash, jsonify, request, g, current_app
|
from flask import Blueprint, send_from_directory, abort, flash, jsonify, request, g, current_app
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
|
@ -18,7 +18,7 @@ from gallery.auth import login_required
|
||||||
|
|
||||||
from gallery import db
|
from gallery import db
|
||||||
from gallery.utils import metadata as mt
|
from gallery.utils import metadata as mt
|
||||||
from gallery.utils.generate_image import ImageGenerator
|
from gallery.utils.generate_image import generate_thumbnail
|
||||||
|
|
||||||
|
|
||||||
blueprint = Blueprint('api', __name__, url_prefix='/api')
|
blueprint = Blueprint('api', __name__, url_prefix='/api')
|
||||||
|
@ -42,7 +42,7 @@ def file(file_name):
|
||||||
|
|
||||||
return send_from_directory(current_app.config['UPLOAD_FOLDER'], file_name)
|
return send_from_directory(current_app.config['UPLOAD_FOLDER'], file_name)
|
||||||
|
|
||||||
thumb = ImageGenerator.thumbnail(file_name, res)
|
thumb = generate_thumbnail(file_name, res)
|
||||||
|
|
||||||
if not thumb:
|
if not thumb:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
@ -126,8 +126,8 @@ def delete_image(image_id):
|
||||||
# Delete cached files
|
# Delete cached files
|
||||||
cache_path = os.path.join(platformdirs.user_config_dir('onlylegs'), 'cache')
|
cache_path = os.path.join(platformdirs.user_config_dir('onlylegs'), 'cache')
|
||||||
cache_name = img.file_name.rsplit('.')[0]
|
cache_name = img.file_name.rsplit('.')[0]
|
||||||
for file in pathlib.Path(cache_path).glob(cache_name + '*'):
|
for cache_file in pathlib.Path(cache_path).glob(cache_name + '*'):
|
||||||
os.remove(file)
|
os.remove(cache_file)
|
||||||
|
|
||||||
# Delete from database
|
# Delete from database
|
||||||
db_session.query(db.Posts).filter_by(id=image_id).delete()
|
db_session.query(db.Posts).filter_by(id=image_id).delete()
|
||||||
|
@ -209,40 +209,3 @@ def metadata(img_id):
|
||||||
exif = mt.Metadata(img_path).yoink()
|
exif = mt.Metadata(img_path).yoink()
|
||||||
|
|
||||||
return jsonify(exif)
|
return jsonify(exif)
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route('/logfile')
|
|
||||||
@login_required
|
|
||||||
def logfile():
|
|
||||||
"""
|
|
||||||
Gets the log file and returns it as a JSON object
|
|
||||||
"""
|
|
||||||
log_dict = {}
|
|
||||||
|
|
||||||
with open('only.log', encoding='utf-8', mode='r') as file:
|
|
||||||
for i, line in enumerate(file):
|
|
||||||
line = line.split(' : ')
|
|
||||||
|
|
||||||
event = line[0].strip().split(' ')
|
|
||||||
event_data = {
|
|
||||||
'date': event[0],
|
|
||||||
'time': event[1],
|
|
||||||
'severity': event[2],
|
|
||||||
'owner': event[3]
|
|
||||||
}
|
|
||||||
|
|
||||||
message = line[1].strip()
|
|
||||||
try:
|
|
||||||
message_data = {
|
|
||||||
'code': int(message[1:4]),
|
|
||||||
'message': message[5:].strip()
|
|
||||||
}
|
|
||||||
except ValueError:
|
|
||||||
message_data = {'code': 0, 'message': message}
|
|
||||||
except Exception as err:
|
|
||||||
logging.error('Could not parse log file: %s', err)
|
|
||||||
abort(500)
|
|
||||||
|
|
||||||
log_dict[i] = {'event': event_data, 'message': message_data}
|
|
||||||
|
|
||||||
return jsonify(log_dict)
|
|
||||||
|
|
|
@ -62,11 +62,16 @@ def group(group_id):
|
||||||
images.append(image)
|
images.append(image)
|
||||||
|
|
||||||
if images:
|
if images:
|
||||||
text_colour = contrast.contrast(images[0].image_colours[0], 'rgb(var(--fg-black))', 'rgb(var(--fg-white))')
|
text_colour = contrast.contrast(images[0].image_colours[0],
|
||||||
|
'rgb(var(--fg-black))',
|
||||||
|
'rgb(var(--fg-white))')
|
||||||
else:
|
else:
|
||||||
text_colour = 'rgb(var(--fg-black))'
|
text_colour = 'rgb(var(--fg-black))'
|
||||||
|
|
||||||
return render_template('groups/group.html', group=group_item, images=images, text_colour=text_colour)
|
return render_template('groups/group.html',
|
||||||
|
group=group_item,
|
||||||
|
images=images,
|
||||||
|
text_colour=text_colour)
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route('/<int:group_id>/<int:image_id>')
|
@blueprint.route('/<int:group_id>/<int:image_id>')
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
top: 0
|
top: 0
|
||||||
left: 0
|
left: 0
|
||||||
|
|
||||||
background-color: RGB($fg-white)
|
background-color: RGB($bg-300)
|
||||||
// background-image: linear-gradient(to right, RGB($bg-200) 15%, RGB($bg-400) 35%, RGB($bg-200) 50%)
|
background-image: linear-gradient(to right, RGB($bg-400) 15%, RGB($bg-200) 35%, RGB($bg-400) 50%)
|
||||||
// background-size: 1000px 640px
|
background-size: 1000px 640px
|
||||||
// animation: imgLoading 1.8s linear infinite forwards
|
animation: imgLoading 1.8s linear infinite forwards
|
||||||
|
|
||||||
user-select: none
|
user-select: none
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
|
"""
|
||||||
|
Calculate the contrast between two colors
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def contrast(background, light, dark, threshold = 0.179):
|
def contrast(background, light, dark, threshold = 0.179):
|
||||||
"""
|
"""
|
||||||
Calculate the contrast between two colors
|
|
||||||
background: tuple of (r, g, b) values
|
background: tuple of (r, g, b) values
|
||||||
light: color to use if the background is light
|
light: color to use if the background is light
|
||||||
dark: color to use if the background is dark
|
dark: color to use if the background is dark
|
||||||
threshold: the threshold to use for determining lightness, the default is w3 recommended
|
threshold: the threshold to use for determining lightness, the default is w3 recommended
|
||||||
"""
|
"""
|
||||||
r = background[0]
|
red = background[0]
|
||||||
g = background[1]
|
green = background[1]
|
||||||
b = background[2]
|
blue = background[2]
|
||||||
|
|
||||||
# Calculate contrast
|
# Calculate contrast
|
||||||
uicolors = [r / 255, g / 255, b / 255]
|
uicolors = [red / 255, green / 255, blue / 255]
|
||||||
c = [col / 12.92 if col <= 0.03928 else ((col + 0.055) / 1.055) ** 2.4 for col in uicolors]
|
cont = [col / 12.92 if col <= 0.03928 else ((col + 0.055) / 1.055) ** 2.4 for col in uicolors]
|
||||||
l = (0.2126 * c[0]) + (0.7152 * c[1]) + (0.0722 * c[2])
|
lightness = (0.2126 * cont[0]) + (0.7152 * cont[1]) + (0.0722 * cont[2])
|
||||||
|
|
||||||
return light if l > threshold else dark
|
return light if lightness > threshold else dark
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
Tools for generating images and thumbnails
|
||||||
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import platformdirs
|
import platformdirs
|
||||||
from PIL import Image, ImageOps #, ImageFilter
|
from PIL import Image, ImageOps #, ImageFilter
|
||||||
|
@ -8,8 +12,7 @@ CACHE_PATH = platformdirs.user_config_dir('onlylegs') + '/cache'
|
||||||
UPLOAD_PATH = platformdirs.user_config_dir('onlylegs') + '/uploads'
|
UPLOAD_PATH = platformdirs.user_config_dir('onlylegs') + '/uploads'
|
||||||
|
|
||||||
|
|
||||||
class ImageGenerator:
|
def generate_thumbnail(file_name, resolution, ext=None):
|
||||||
def thumbnail(name, resolution, ext=None):
|
|
||||||
"""
|
"""
|
||||||
Image thumbnail generator
|
Image thumbnail generator
|
||||||
Uses PIL to generate a thumbnail of the image and saves it to the cache directory
|
Uses PIL to generate a thumbnail of the image and saves it to the cache directory
|
||||||
|
@ -22,9 +25,9 @@ class ImageGenerator:
|
||||||
os.makedirs(CACHE_PATH)
|
os.makedirs(CACHE_PATH)
|
||||||
|
|
||||||
# no sussy business
|
# no sussy business
|
||||||
name, name_ext = secure_filename(name).rsplit('.')
|
file_name, file_ext = secure_filename(file_name).rsplit('.')
|
||||||
if not ext:
|
if not ext:
|
||||||
ext = name_ext.strip('.')
|
ext = file_ext.strip('.')
|
||||||
|
|
||||||
# PIL doesnt like jpg so we convert it to jpeg
|
# PIL doesnt like jpg so we convert it to jpeg
|
||||||
if ext.lower() == "jpg":
|
if ext.lower() == "jpg":
|
||||||
|
@ -41,15 +44,15 @@ class ImageGenerator:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# If image has been already generated, return it from the cache
|
# If image has been already generated, return it from the cache
|
||||||
if os.path.exists(os.path.join(CACHE_PATH, f'{name}_{res_x}x{res_y}.{ext}')):
|
if os.path.exists(os.path.join(CACHE_PATH, f'{file_name}_{res_x}x{res_y}.{ext}')):
|
||||||
return os.path.join(CACHE_PATH, f'{name}_{res_x}x{res_y}.{ext}')
|
return os.path.join(CACHE_PATH, f'{file_name}_{res_x}x{res_y}.{ext}')
|
||||||
|
|
||||||
# Check if image exists in the uploads directory
|
# Check if image exists in the uploads directory
|
||||||
if not os.path.exists(os.path.join(UPLOAD_PATH, f'{name}.{name_ext}')):
|
if not os.path.exists(os.path.join(UPLOAD_PATH, f'{file_name}.{file_ext}')):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Open image and rotate it based on EXIF data and get ICC profile so colors are correct
|
# Open image and rotate it based on EXIF data and get ICC profile so colors are correct
|
||||||
image = Image.open(os.path.join(UPLOAD_PATH, f'{name}.{name_ext}'))
|
image = Image.open(os.path.join(UPLOAD_PATH, f'{file_name}.{file_ext}'))
|
||||||
image_icc = image.info.get("icc_profile")
|
image_icc = image.info.get("icc_profile")
|
||||||
img_x, img_y = image.size
|
img_x, img_y = image.size
|
||||||
|
|
||||||
|
@ -59,16 +62,16 @@ class ImageGenerator:
|
||||||
|
|
||||||
# Save image to cache directory
|
# Save image to cache directory
|
||||||
try:
|
try:
|
||||||
image.save(os.path.join(CACHE_PATH,f'{name}_{res_x}x{res_y}.{ext}'),
|
image.save(os.path.join(CACHE_PATH,f'{file_name}_{res_x}x{res_y}.{ext}'),
|
||||||
icc_profile=image_icc)
|
icc_profile=image_icc)
|
||||||
except OSError:
|
except OSError:
|
||||||
# This usually happens when saving a JPEG with an ICC profile,
|
# This usually happens when saving a JPEG with an ICC profile,
|
||||||
# so we convert to RGB and try again
|
# so we convert to RGB and try again
|
||||||
image = image.convert('RGB')
|
image = image.convert('RGB')
|
||||||
image.save(os.path.join(CACHE_PATH, f'{name}_{res_x}x{res_y}.{ext}'),
|
image.save(os.path.join(CACHE_PATH, f'{file_name}_{res_x}x{res_y}.{ext}'),
|
||||||
icc_profile=image_icc)
|
icc_profile=image_icc)
|
||||||
|
|
||||||
# No need to keep the image in memory, learned the hard way
|
# No need to keep the image in memory, learned the hard way
|
||||||
image.close()
|
image.close()
|
||||||
|
|
||||||
return os.path.join(CACHE_PATH, f'{name}_{res_x}x{res_y}.{ext}')
|
return os.path.join(CACHE_PATH, f'{file_name}_{res_x}x{res_y}.{ext}')
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue