diff --git a/gallery/__init__.py b/gallery/__init__.py index 89a75ac..ab0679f 100644 --- a/gallery/__init__.py +++ b/gallery/__init__.py @@ -5,37 +5,96 @@ print(""" | |_| | | | | | |_| | |__| __/ (_| \\__ \\ \\___/|_| |_|_|\\__, |_____\\___|\\__, |___/ |___/ |___/ -Created by Fluffy Bean - Version 23.03.01 +Created by Fluffy Bean - Version 23.03.02 """) from flask import Flask, render_template from flask_compress import Compress -from flask.helpers import get_root_path + from dotenv import load_dotenv +import platformdirs + import yaml import os -print(f"Running at {get_root_path(__name__)}\n") +# I could use something other than the config dir, but this works well enough +user_dir = platformdirs.user_config_dir('onlylegs') +if not os.path.exists(user_dir): + os.makedirs(user_dir) + print("Created user directory") +# Location of instance folder, where sqlite db is stored +instance_path = os.path.join(user_dir, 'instance') +if not os.path.exists(instance_path): + os.makedirs(instance_path) + print("Created instance directory") + +# Get environment variables +if os.path.exists(os.path.join(user_dir, '.env')): + load_dotenv(os.path.join(user_dir, '.env')) + print("Loaded environment variables") +else: + conf = { + 'FLASK_SECRETE': 'dev', + } + # Create .env file with default values + with open(os.path.join(user_dir, '.env'), 'w') as f: + for key, value in conf.items(): + f.write(f"{key}={value}\n") + print("Created default environment variables at:", + os.path.join(user_dir, '.env'), + "\nCHANGE THESE VALUES USING TEHE GALLERY!") + +# Get config file +if os.path.exists(os.path.join(user_dir, 'conf.yml')): + with open(os.path.join(user_dir, 'conf.yml'), 'r') as f: + conf = yaml.load(f, Loader=yaml.FullLoader) + print("Loaded gallery config") +else: + conf = { + 'admin': { + 'name': 'Real Person', + 'username': 'User', + 'email': 'real-email@some.place' + }, + 'upload': { + 'allowed-extensions': { + 'jpg': 'jpeg', + 'jpeg': 'jpeg', + 'png': 'png', + 'webp': 'webp' + }, + 'max-size': 69, + 'rename': 'GWA_\{\{username\}\}_\{\{time\}\}' + }, + 'website': { + 'name': 'OnlyLegs', + 'motto': 'Gwa Gwa', + 'language': 'english' + } + } + # Create yaml config file with default values + with open(os.path.join(user_dir, 'conf.yml'), 'w') as f: + yaml.dump(conf, f, default_flow_style=False) + print("Created default gallery config at:", + os.path.join(user_dir, 'conf.yml'), + "\nCHANGE THESE VALUES USING TEHE GALLERY!") + +# Load logger +from .logger import logger + +logger.innit_logger() + def create_app(test_config=None): # create and configure the app - app = Flask(__name__) + app = Flask(__name__, instance_path=instance_path) compress = Compress() - # Get environment variables - load_dotenv(os.path.join(app.root_path, 'user', '.env')) - print("Loaded environment variables") - - # Get config file - with open(os.path.join(app.root_path, 'user', 'conf.yml'), 'r') as f: - conf = yaml.load(f, Loader=yaml.FullLoader) - print("Loaded gallery config") - # App configuration app.config.from_mapping( SECRET_KEY=os.environ.get('FLASK_SECRET'), DATABASE=os.path.join(app.instance_path, 'gallery.sqlite'), - UPLOAD_FOLDER=os.path.join(app.root_path, 'user', 'uploads'), + UPLOAD_FOLDER=os.path.join(user_dir, 'uploads'), MAX_CONTENT_LENGTH=1024 * 1024 * conf['upload']['max-size'], ALLOWED_EXTENSIONS=conf['upload']['allowed-extensions'], WEBSITE=conf['website'], @@ -61,10 +120,6 @@ def create_app(test_config=None): # Load theme from . import sassy sassy.compile('default', app.root_path) - - # Load logger - from .logger import logger - logger.innit_logger(app) @app.errorhandler(405) def method_not_allowed(e): @@ -104,7 +159,7 @@ def create_app(test_config=None): from . import routing app.register_blueprint(routing.blueprint) app.add_url_rule('/', endpoint='index') - + # Load routes for settings from . import settings app.register_blueprint(settings.blueprint) diff --git a/gallery/api.py b/gallery/api.py index 9b5a462..bac571d 100644 --- a/gallery/api.py +++ b/gallery/api.py @@ -4,7 +4,7 @@ from werkzeug.utils import secure_filename from gallery.auth import login_required from gallery.db import get_db -from PIL import Image, ImageOps +from PIL import Image, ImageOps, ImageFilter from . import metadata as mt from .logger import logger @@ -12,20 +12,30 @@ from .logger import logger from uuid import uuid4 import io import os -import time blueprint = Blueprint('api', __name__, url_prefix='/api') -@blueprint.route('/uploads//', methods=['GET']) -def uploads(file, quality): - # If quality is 0, return original file - if quality == 0: +@blueprint.route('/uploads/', methods=['GET']) +def uploads(file): + # Get args + width = request.args.get('w', default=0, type=int) # Width of image + height = request.args.get('h', default=0, type=int) # Height of image + filtered = request.args.get('f', default=False, type=bool) # Whether to apply filters to image, + # such as blur for NSFW images + + # if no args are passed, return the raw file + if width == 0 and height == 0 and not filtered: return send_from_directory(current_app.config['UPLOAD_FOLDER'], secure_filename(file), as_attachment=True) - # Set variables + # Of either width or height is 0, set it to the other value to keep aspect ratio + if width > 0 and height == 0: + height = width + elif width == 0 and height > 0: + width = height + set_ext = current_app.config['ALLOWED_EXTENSIONS'] buff = io.BytesIO() @@ -33,11 +43,11 @@ def uploads(file, quality): try: img = Image.open( os.path.join(current_app.config['UPLOAD_FOLDER'], - secure_filename(file))) + secure_filename(file))) except Exception as e: logger.server(600, f"Error opening image: {e}") abort(500) - + img_ext = os.path.splitext(secure_filename(file))[-1].lower().replace( '.', '') img_ext = set_ext[img_ext] @@ -45,8 +55,15 @@ def uploads(file, quality): "icc_profile") # Get ICC profile as it alters colours # Resize image and orientate correctly - img.thumbnail((quality, quality), Image.LANCZOS) + img.thumbnail((width, height), Image.LANCZOS) img = ImageOps.exif_transpose(img) + + # TODO: Add filters + # If has NSFW tag, blur image, etc. + if filtered: + #pass + img = img.filter(ImageFilter.GaussianBlur(20)) + try: img.save(buff, img_ext, icc_profile=img_icc) except OSError: @@ -57,7 +74,7 @@ def uploads(file, quality): except: logger.server(600, f"Error resizing image: {file}") abort(500) - + img.close() # Seek to beginning of buffer and return @@ -74,13 +91,14 @@ def upload(): if not form_file: return abort(404) - img_ext = os.path.splitext(secure_filename(form_file.filename))[-1].replace('.', '').lower() + img_ext = os.path.splitext(secure_filename( + form_file.filename))[-1].replace('.', '').lower() img_name = f"GWAGWA_{uuid4().__str__()}.{img_ext}" if not img_ext in current_app.config['ALLOWED_EXTENSIONS'].keys(): logger.add(303, f"File extension not allowed: {img_ext}") abort(403) - + if os.path.isdir(current_app.config['UPLOAD_FOLDER']) == False: os.mkdir(current_app.config['UPLOAD_FOLDER']) @@ -94,7 +112,7 @@ def upload(): except Exception as e: logger.server(600, f"Error saving to database: {e}") abort(500) - + # Save file try: form_file.save( @@ -154,17 +172,18 @@ def metadata(id): return jsonify(exif) + @blueprint.route('/logfile') @login_required def logfile(): filename = logger.filename() log_dict = {} i = 0 - + with open(filename) as f: for line in f: line = line.split(' : ') - + event = line[0].strip().split(' ') event_data = { 'date': event[0], @@ -172,7 +191,7 @@ def logfile(): 'severity': event[2], 'owner': event[3] } - + message = line[1].strip() try: message_data = { @@ -180,16 +199,10 @@ def logfile(): 'message': message[5:].strip() } except: - message_data = { - 'code': 0, - 'message': message - } - - log_dict[i] = { - 'event': event_data, - 'message': message_data - } - - i += 1 # Line number, starts at 0 - + message_data = {'code': 0, 'message': message} + + log_dict[i] = {'event': event_data, 'message': message_data} + + i += 1 # Line number, starts at 0 + return jsonify(log_dict) \ No newline at end of file diff --git a/gallery/logger.py b/gallery/logger.py index 2d09ea4..188fff8 100644 --- a/gallery/logger.py +++ b/gallery/logger.py @@ -1,14 +1,15 @@ import logging import os from datetime import datetime +import platformdirs # Prevent werkzeug from logging logging.getLogger('werkzeug').disabled = True class logger: - def innit_logger(app): - filepath = os.path.join(app.root_path, 'user', 'logs') + def innit_logger(): + filepath = os.path.join(platformdirs.user_config_dir('onlylegs'), 'logs') #filename = f'onlylogs_{datetime.now().strftime("%Y%m%d")}.log' filename = 'only.log' diff --git a/gallery/sassy.py b/gallery/sassy.py index d1463c3..8dc3603 100644 --- a/gallery/sassy.py +++ b/gallery/sassy.py @@ -11,8 +11,8 @@ class compile(): def __init__(self, theme, dir): print(f"Loading '{theme}' theme...") - theme_path = os.path.join(dir, 'user', 'themes', theme) - font_path = os.path.join(dir, 'user', 'themes', theme, 'fonts') + theme_path = os.path.join(dir, 'themes', theme) + font_path = os.path.join(dir, 'themes', theme, 'fonts') dest = os.path.join(dir, 'static', 'theme') # print(f"Theme path: {theme_path}") diff --git a/gallery/static/js/login.js b/gallery/static/js/login.js index b4c71ee..d66c25a 100644 --- a/gallery/static/js/login.js +++ b/gallery/static/js/login.js @@ -2,11 +2,10 @@ function showLogin() { popUpShow( 'idk what to put here, just login please', 'Need an account? Register!', - '', - '
\ + '', + '\ \ \ - \
' ); }; @@ -14,13 +13,12 @@ function showRegister() { popUpShow( 'Who are you?', 'Already have an account? Login!', - '', - '
\ + '', + '\ \ \ \ \ - \
' ); }; diff --git a/gallery/static/js/main.js b/gallery/static/js/main.js index f8a0f99..1844d14 100644 --- a/gallery/static/js/main.js +++ b/gallery/static/js/main.js @@ -157,4 +157,12 @@ function popupDissmiss() { setTimeout(function() { popup.classList = 'pop-up'; }, 200); -} \ No newline at end of file +} + +document.addEventListener('keydown', function(event) { + if (event.key === 'Escape') { + if (document.querySelector('.pop-up').classList.contains('pop-up__active')) { + popupDissmiss(); + } + } +}); \ No newline at end of file diff --git a/gallery/static/js/upload.js b/gallery/static/js/upload.js index 67217f9..c1b9b50 100644 --- a/gallery/static/js/upload.js +++ b/gallery/static/js/upload.js @@ -2,13 +2,12 @@ function showUpload() { popUpShow( 'Upload funny stuff', 'May the world see your stuff 👀', - '', - '
\ + '', + '\ \ \ \ \ - \
' ); }; diff --git a/gallery/templates/image.html b/gallery/templates/image.html index 7e0af8d..ddee033 100644 --- a/gallery/templates/image.html +++ b/gallery/templates/image.html @@ -2,7 +2,7 @@ {% block header %}
- +
{% endblock %} @@ -15,7 +15,7 @@
Dewww eeeet!', - '' + '' ); }); $('#img-edit').click(function() { diff --git a/gallery/templates/index.html b/gallery/templates/index.html index 1900624..89bd7aa 100644 --- a/gallery/templates/index.html +++ b/gallery/templates/index.html @@ -43,7 +43,7 @@ var image = images[i]; if (image.getBoundingClientRect().top < window.innerHeight && image.getBoundingClientRect().bottom > 0) { if (!image.src) { - image.src = `/api/uploads/${image.getAttribute('data-src')}/400` + image.src = `/api/uploads/${image.getAttribute('data-src')}?w=500&h=500` } } } diff --git a/gallery/user/themes/default/animations.sass b/gallery/themes/default/animations.sass similarity index 100% rename from gallery/user/themes/default/animations.sass rename to gallery/themes/default/animations.sass diff --git a/gallery/user/themes/default/buttons/jumpUp.sass b/gallery/themes/default/buttons/jumpUp.sass similarity index 100% rename from gallery/user/themes/default/buttons/jumpUp.sass rename to gallery/themes/default/buttons/jumpUp.sass diff --git a/gallery/user/themes/default/buttons/pill.sass b/gallery/themes/default/buttons/pill.sass similarity index 100% rename from gallery/user/themes/default/buttons/pill.sass rename to gallery/themes/default/buttons/pill.sass diff --git a/gallery/user/themes/default/fonts/worksans-black.woff2 b/gallery/themes/default/fonts/worksans-black.woff2 similarity index 100% rename from gallery/user/themes/default/fonts/worksans-black.woff2 rename to gallery/themes/default/fonts/worksans-black.woff2 diff --git a/gallery/user/themes/default/fonts/worksans-bold.woff2 b/gallery/themes/default/fonts/worksans-bold.woff2 similarity index 100% rename from gallery/user/themes/default/fonts/worksans-bold.woff2 rename to gallery/themes/default/fonts/worksans-bold.woff2 diff --git a/gallery/user/themes/default/fonts/worksans-regular.woff2 b/gallery/themes/default/fonts/worksans-regular.woff2 similarity index 100% rename from gallery/user/themes/default/fonts/worksans-regular.woff2 rename to gallery/themes/default/fonts/worksans-regular.woff2 diff --git a/gallery/user/themes/default/style.sass b/gallery/themes/default/style.sass similarity index 100% rename from gallery/user/themes/default/style.sass rename to gallery/themes/default/style.sass diff --git a/gallery/user/themes/default/ui/background.sass b/gallery/themes/default/ui/background.sass similarity index 100% rename from gallery/user/themes/default/ui/background.sass rename to gallery/themes/default/ui/background.sass diff --git a/gallery/user/themes/default/ui/banner.sass b/gallery/themes/default/ui/banner.sass similarity index 100% rename from gallery/user/themes/default/ui/banner.sass rename to gallery/themes/default/ui/banner.sass diff --git a/gallery/user/themes/default/ui/content.sass b/gallery/themes/default/ui/content.sass similarity index 100% rename from gallery/user/themes/default/ui/content.sass rename to gallery/themes/default/ui/content.sass diff --git a/gallery/user/themes/default/ui/gallery.sass b/gallery/themes/default/ui/gallery.sass similarity index 100% rename from gallery/user/themes/default/ui/gallery.sass rename to gallery/themes/default/ui/gallery.sass diff --git a/gallery/user/themes/default/ui/navigation.sass b/gallery/themes/default/ui/navigation.sass similarity index 100% rename from gallery/user/themes/default/ui/navigation.sass rename to gallery/themes/default/ui/navigation.sass diff --git a/gallery/user/themes/default/ui/notification.sass b/gallery/themes/default/ui/notification.sass similarity index 100% rename from gallery/user/themes/default/ui/notification.sass rename to gallery/themes/default/ui/notification.sass diff --git a/gallery/user/themes/default/ui/pop-up.sass b/gallery/themes/default/ui/pop-up.sass similarity index 94% rename from gallery/user/themes/default/ui/pop-up.sass rename to gallery/themes/default/ui/pop-up.sass index 40b3430..6293a49 100644 --- a/gallery/user/themes/default/ui/pop-up.sass +++ b/gallery/themes/default/ui/pop-up.sass @@ -45,7 +45,7 @@ .pop-up-wrapper margin: 0 - padding: 0.5rem + padding: 0 width: 621px height: auto @@ -57,7 +57,6 @@ display: flex flex-direction: column - gap: 0.5rem background-color: $white border-radius: $rad @@ -69,7 +68,7 @@ .pop-up-content margin: 0 - padding: 0 + padding: 0.5rem 0.5rem 0 width: 100% height: auto @@ -138,22 +137,21 @@ .pop-up-controlls margin: 0 - padding: 0 + padding: 0.5rem width: 100% height: auto display: flex - flex-direction: column + flex-direction: row + justify-content: flex-end gap: 0.5rem - justify-content: center - .pop-up__btn margin: 0 - padding: 0.5rem + padding: 0.5rem 1rem - width: 100% + width: auto height: 2.5rem display: flex @@ -255,6 +253,13 @@ img max-height: 50vh + + .pop-up-controlls + flex-direction: column + justify-content: center + + .pop-up__btn + width: 100% .pop-up__active opacity: 1 diff --git a/gallery/user/themes/default/ui/wrappers/error.sass b/gallery/themes/default/ui/wrappers/error.sass similarity index 100% rename from gallery/user/themes/default/ui/wrappers/error.sass rename to gallery/themes/default/ui/wrappers/error.sass diff --git a/gallery/user/themes/default/ui/wrappers/image.sass b/gallery/themes/default/ui/wrappers/image.sass similarity index 99% rename from gallery/user/themes/default/ui/wrappers/image.sass rename to gallery/themes/default/ui/wrappers/image.sass index ef99bca..77f9fde 100644 --- a/gallery/user/themes/default/ui/wrappers/image.sass +++ b/gallery/themes/default/ui/wrappers/image.sass @@ -86,8 +86,6 @@ object-fit: contain object-position: center - border-radius: $rad - .image-info__container margin: 0 padding: 0 diff --git a/gallery/user/themes/default/ui/wrappers/index.sass b/gallery/themes/default/ui/wrappers/index.sass similarity index 100% rename from gallery/user/themes/default/ui/wrappers/index.sass rename to gallery/themes/default/ui/wrappers/index.sass diff --git a/gallery/user/themes/default/ui/wrappers/settings.sass b/gallery/themes/default/ui/wrappers/settings.sass similarity index 100% rename from gallery/user/themes/default/ui/wrappers/settings.sass rename to gallery/themes/default/ui/wrappers/settings.sass diff --git a/gallery/user/themes/default/variables.sass b/gallery/themes/default/variables.sass similarity index 100% rename from gallery/user/themes/default/variables.sass rename to gallery/themes/default/variables.sass diff --git a/gallery/user/example.env b/gallery/user/example.env deleted file mode 100644 index cb07e79..0000000 --- a/gallery/user/example.env +++ /dev/null @@ -1,9 +0,0 @@ -# EMAIL CONFIGURATION -EMAIL_HOST = #smtp.gmail.com -EMAIL_PORT = #465 -EMAIL_HOST_USER = #your email -EMAIL_HOST_PASSWORD = #your password -EMAIL_USE_TLS = #True - -# FLASK SECRETE KEY, DONT LOOSE IT!!!!!!! -FLASK_SECRET = #your secret key \ No newline at end of file diff --git a/gallery/user/example.yml b/gallery/user/example.yml deleted file mode 100644 index 09db1d1..0000000 --- a/gallery/user/example.yml +++ /dev/null @@ -1,21 +0,0 @@ -# THIS IS AN EXAMPLE CONFIG, RENAME THIS TO conf.yml TO USE - -admin: - name: Real Person - username: User - email: real-email@some.place - -upload: - allowed-extensions: - - .png - - .jpg - - .jpeg - - .webp - max-size: 69MB - rename: GWA_{{username}}_{{time}} - -website: - name: OnlyLegs - motto: Gwa Gwa - language: english # Placeholder for future language support endevours - diff --git a/setup.py b/setup.py index 8796b97..cfc23eb 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import find_packages, setup setup( name='onlylegs', - version='23.03.01', + version='23.03.02', packages=find_packages(), include_package_data=True, install_requires=[ @@ -13,5 +13,6 @@ setup( 'pillow', 'colorthief', 'pyyaml', + 'platformdirs', ], )