diff --git a/gallery/__init__.py b/gallery/__init__.py
index 10c34b9..21d4960 100644
--- a/gallery/__init__.py
+++ b/gallery/__init__.py
@@ -16,28 +16,13 @@ from flask import Flask, render_template
# Configuration
from dotenv import load_dotenv
import platformdirs
-import yaml
+from yaml import FullLoader, load
-from . import theme_manager
-from . import setup
-
-
-# Run setup checks
-setup.SetupApp()
USER_DIR = platformdirs.user_config_dir('onlylegs')
-# Get environment variables
-load_dotenv(os.path.join(USER_DIR, '.env'))
-print("Loaded environment variables")
-# Get config file
-with open(os.path.join(USER_DIR, 'conf.yml'), encoding='utf-8') as f:
- conf = yaml.load(f, Loader=yaml.FullLoader)
- print("Loaded gallery config")
-
-
-def create_app(test_config=None):
+def create_app(test_config=None, verbose=False):
"""
Create and configure the main app
"""
@@ -45,6 +30,17 @@ def create_app(test_config=None):
assets = Environment()
cache = Cache(config={'CACHE_TYPE': 'SimpleCache', 'CACHE_DEFAULT_TIMEOUT': 300})
compress = Compress()
+
+ # Get environment variables
+ load_dotenv(os.path.join(USER_DIR, '.env'))
+ if verbose:
+ print("Loaded environment variables")
+
+ # Get config file
+ with open(os.path.join(USER_DIR, 'conf.yml'), encoding='utf-8') as f:
+ conf = load(f, Loader=FullLoader)
+ if verbose:
+ print("Loaded gallery config")
# App configuration
app.config.from_mapping(
@@ -67,7 +63,9 @@ def create_app(test_config=None):
pass
# Load theme
- theme_manager.CompileTheme('default', app.root_path)
+ from . import theme_manager
+ theme_manager.CompileTheme('default', app.root_path, verbose)
+
# Bundle JS files
js = Bundle('js/*.js', output='gen/packed.js')
assets.register('js_all', js)
diff --git a/gallery/db.py b/gallery/db.py
index 0b3a543..cd5946e 100644
--- a/gallery/db.py
+++ b/gallery/db.py
@@ -5,13 +5,16 @@ import os
import platformdirs
from sqlalchemy import create_engine, Column, Integer, String, Boolean, DateTime, ForeignKey, PickleType
-from sqlalchemy.orm import declarative_base, relationship, backref, mapped_column
+from sqlalchemy.orm import declarative_base, relationship
+
+
+USER_DIR = platformdirs.user_config_dir('onlylegs')
+DB_PATH = os.path.join(USER_DIR, 'gallery.sqlite')
-path_to_db = os.path.join(platformdirs.user_config_dir('onlylegs'), 'gallery.sqlite')
-engine = create_engine(f'sqlite:///{path_to_db}', echo=False)
# engine = create_engine('postgresql://username:password@host:port/database_name', echo=False)
# engine = create_engine('mysql://username:password@host:port/database_name', echo=False)
+engine = create_engine(f'sqlite:///{DB_PATH}', echo=False)
base = declarative_base()
@@ -130,4 +133,6 @@ class Bans (base): # pylint: disable=too-few-public-methods, C0103
created_at = Column(DateTime, nullable=False)
-base.metadata.create_all(engine)
+# check if database file exists, if not create it
+if not os.path.isfile(DB_PATH):
+ base.metadata.create_all(engine)
\ No newline at end of file
diff --git a/gallery/templates/index.html b/gallery/templates/index.html
index bc1ad52..3da78d4 100644
--- a/gallery/templates/index.html
+++ b/gallery/templates/index.html
@@ -28,7 +28,7 @@
{% else %}
-
No image!
+
No images
{% if g.user %}
You can get started by uploading an image!
{% else %}
diff --git a/gallery/theme_manager.py b/gallery/theme_manager.py
index f8fb22a..36f98fd 100644
--- a/gallery/theme_manager.py
+++ b/gallery/theme_manager.py
@@ -12,13 +12,14 @@ class CompileTheme:
"""
Compiles the theme into the static folder
"""
- def __init__(self, theme_name, app_path):
+ def __init__(self, theme_name, app_path, verbose=False):
"""
Initialize the theme manager
Compiles the theme into the static folder and loads the fonts
"""
- print(f"Loading '{theme_name}' theme...")
+ if verbose:
+ print(f"Loading '{theme_name}' theme...")
theme_path = os.path.join(app_path, 'themes', theme_name)
theme_dest = os.path.join(app_path, 'static', 'theme')
@@ -30,11 +31,11 @@ class CompileTheme:
self.load_sass(theme_path, theme_dest)
self.load_fonts(theme_path, theme_dest)
- now = datetime.now()
- print(f"{now.hour}:{now.minute}:{now.second} - Done!\n")
+ if verbose:
+ print(f"{datetime.now().hour}:{datetime.now().minute}:{datetime.now().second} - Done!\n")
@staticmethod
- def load_sass(source_path, css_dest):
+ def load_sass(source_path, css_dest, verbose=False):
"""
Compile the sass (or scss) file into css and save it to the static folder
"""
@@ -56,10 +57,11 @@ class CompileTheme:
print("Failed to compile!\n", err)
sys.exit(1)
- print("Compiled successfully!")
+ if verbose:
+ print("Compiled successfully!")
@staticmethod
- def load_fonts(source_path, font_dest):
+ def load_fonts(source_path, font_dest, verbose=False):
"""
Copy the fonts folder to the static folder
"""
@@ -68,7 +70,6 @@ class CompileTheme:
font_dest = os.path.join(font_dest, 'fonts')
if os.path.exists(font_dest):
- print("Updating fonts...")
try:
shutil.rmtree(font_dest)
except Exception as err:
@@ -77,7 +78,9 @@ class CompileTheme:
try:
shutil.copytree(source_path, font_dest)
- print("Copied new fonts!")
except Exception as err:
print("Failed to copy fonts!\n", err)
sys.exit(1)
+
+ if verbose:
+ print("Fonts copied successfully!")
diff --git a/pyproject.toml b/pyproject.toml
index 47c85c7..4ce7350 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "onlylegs"
-version = "23.03.11"
+version = "23.03.12"
description = "Gallery built for fast and simple image management"
authors = ["Fluffy-Bean
"]
license = "MIT"
diff --git a/run.py b/run.py
index e62b4dd..8e73f21 100644
--- a/run.py
+++ b/run.py
@@ -5,28 +5,20 @@ print("""
| |_| | | | | | |_| | |__| __/ (_| \__ \
\___/|_| |_|_|\__, |_____\___|\__, |___/
|___/ |___/
-Created by Fluffy Bean - Version 23.03.11
+Created by Fluffy Bean - Version 23.03.12
""")
-
-import argparse
+from setup.args import PORT, ADDRESS, WORKERS, DEBUG, VERBOSE
+from setup.configuration import Configuration
-parser = argparse.ArgumentParser(description='Run the OnlyLegs gallery')
-parser.add_argument('-p', '--port', type=int, default=5000, help='Port to run on')
-parser.add_argument('-a', '--address', type=str, default='0.0.0.0', help='Address to run on')
-parser.add_argument('-w', '--workers', type=int, default=4, help='Number of workers to run')
-parser.add_argument('-d', '--debug', type=bool, default=False, help='Run as Flask app in debug mode')
-args = parser.parse_args()
-
-PORT = args.port
-ADDRESS = args.address
-WORKERS = args.workers
+# Run prechecks
+Configuration(verbose=VERBOSE)
-if args.debug:
+if DEBUG:
from gallery import create_app
- create_app().run(host=ADDRESS, port=PORT, debug=True)
+ create_app(verbose=VERBOSE).run(host=ADDRESS, port=PORT, debug=True, threaded=True)
else:
from gunicorn.app.base import Application
from gunicorn import util
@@ -49,8 +41,12 @@ else:
return 'OnlyLegs'
def load(self):
- return util.import_app('gallery:create_app()')
+ return util.import_app(f'gallery:create_app(verbose={VERBOSE})')
+
+ options = {
+ 'bind': f'{ADDRESS}:{PORT}',
+ 'workers': WORKERS,
+ }
+
+ OnlyLegs(options).run()
- OnlyLegs({'bind': f'{ADDRESS}:{PORT}', 'workers': WORKERS}).run()
-
-# uwu
diff --git a/setup/args.py b/setup/args.py
new file mode 100644
index 0000000..ae3e7ab
--- /dev/null
+++ b/setup/args.py
@@ -0,0 +1,30 @@
+"""
+Startup arguments for the OnlyLegs gallery
+
+ -p, --port: Port to run on (default: 5000)
+ -a, --address: Address to run on (default:0.0.0.0)
+ -w, --workers: Number of workers to run (default: 4)
+
+ -d, --debug: Run as Flask app in debug mode (default: False)
+ -V, --verbose: Show verbose output (default: False)
+ -h, --help: Show a help message
+"""
+
+import argparse
+
+
+parser = argparse.ArgumentParser(description='Run the OnlyLegs gallery')
+parser.add_argument('-p', '--port', type=int, default=5000, help='Port to run on')
+parser.add_argument('-a', '--address', type=str, default='0.0.0.0', help='Address to run on')
+parser.add_argument('-w', '--workers', type=int, default=4, help='Number of workers to run')
+parser.add_argument('-d', '--debug', action='store_true', help='Run as Flask app in debug mode')
+parser.add_argument('-V', '--verbose', action='store_true', help='Show verbose output')
+args = parser.parse_args()
+
+
+PORT = args.port
+ADDRESS = args.address
+WORKERS = args.workers
+
+DEBUG = args.debug
+VERBOSE = args.verbose
\ No newline at end of file
diff --git a/gallery/setup.py b/setup/configuration.py
similarity index 53%
rename from gallery/setup.py
rename to setup/configuration.py
index edf1941..c2964f3 100644
--- a/gallery/setup.py
+++ b/setup/configuration.py
@@ -7,36 +7,37 @@ import sys
import platformdirs
import logging
import yaml
+import re
USER_DIR = platformdirs.user_config_dir('onlylegs')
-class SetupApp:
+class Configuration:
"""
Setup the application on first run
"""
- def __init__(self):
+ def __init__(self, verbose=False):
"""
Main setup function
"""
- print("Running setup...")
+ if verbose:
+ print("Running startup checks...")
- self.requires_restart = False
-
+ # Check if the user directory exists
if not os.path.exists(USER_DIR):
self.make_dir()
+
+ # Check if the .env file exists
if not os.path.exists(os.path.join(USER_DIR, '.env')):
self.make_env()
+
+ # Check if the conf.yml file exists
if not os.path.exists(os.path.join(USER_DIR, 'conf.yml')):
self.make_yaml()
-
- self.logging_config()
- if self.requires_restart:
- print("WARNING: You need to restart and edit the config files before running the app again!")
- print("You can find the config files at:", USER_DIR)
- sys.exit()
+ # Load the config files
+ self.logging_config()
@staticmethod
def make_dir():
@@ -46,11 +47,11 @@ class SetupApp:
try:
os.makedirs(USER_DIR)
os.makedirs(os.path.join(USER_DIR, 'instance'))
-
- print("Created user directory at:", USER_DIR)
except Exception as err:
print("Error creating user directory:", err)
sys.exit(1)
+
+ print("Created user directory at:", USER_DIR)
@staticmethod
def make_env():
@@ -58,55 +59,93 @@ class SetupApp:
Create the .env file with default values
"""
env_conf = {
- 'FLASK_SECRET': 'dev',
+ 'FLASK_SECRET': os.urandom(32).hex(),
}
+
try:
with open(os.path.join(USER_DIR, '.env'), encoding='utf-8', mode='w+') as file:
for key, value in env_conf.items():
file.write(f"{key}={value}\n")
- print("Created environment variables")
except Exception as err:
print("Error creating environment variables:", err)
sys.exit(1)
-
- print("Generated default .env file, please edit!")
+
+ print("""
+ ####################################################
+ # PLEASE NOTE DOWN THE FLASK_SECRET KEY LOCARED IN #
+ # YOUR .config/onlylegs/.env FILE! A NEW KEY WAS #
+ # GENERATED FOR YOU! #
+ ####################################################
+ """)
@staticmethod
def make_yaml():
"""
Create the YAML config file with default values
"""
+ is_correct = False
+ email_regex = re.compile(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b')
+ username_regex = re.compile(r'\b[A-Za-z0-9._%+-]+\b')
+
+ print("No config file found, please enter the following information:")
+ while not is_correct:
+ try:
+ username = input("Admin username: ")
+ name = input("Admin name: ")
+ email = input("Admin email: ")
+ except ValueError:
+ print("Please enter valid values!")
+
+ # Check if the values are valid
+ if not username or not username_regex.match(username):
+ print("Username is invalid!")
+ continue
+
+ if not name:
+ print("Name is invalid!")
+ continue
+
+ if not email or not email_regex.match(email):
+ print("Email is invalid!")
+ continue
+
+ # Check if user is happy with the values
+ _ = input("Is this correct? (y/n): ")
+
+ if _ == 'y' or _ == 'Y':
+ is_correct = True
+
yaml_conf = {
'admin': {
- 'name': 'Real Person',
- 'username': 'User',
- 'email': 'real-email@some.place'
+ 'name': '%s' % name,
+ 'username': '%s' % username,
+ 'email': '%s' % email,
},
'upload': {
'allowed-extensions': {
'jpg': 'jpeg',
'jpeg': 'jpeg',
'png': 'png',
- 'webp': 'webp'
+ 'webp': 'webp',
},
'max-size': 69,
- 'rename': 'GWA_\{\{username\}\}_\{\{time\}\}'
+ 'rename': 'GWA_{{username}}_{{time}}',
},
'website': {
'name': 'OnlyLegs',
- 'motto': 'Gwa Gwa',
- 'language': 'english'
+ 'motto': 'A gallery built for fast and simple image management. You can change this in the settings',
+ 'language': 'en',
}
}
+
try:
with open(os.path.join(USER_DIR, 'conf.yml'), encoding='utf-8', mode='w+') as file:
yaml.dump(yaml_conf, file, default_flow_style=False)
- print("Created default gallery config")
except Exception as err:
print("Error creating default gallery config:", err)
sys.exit(1)
- print("Generated default YAML config, please edit!")
+ print("Generated config file, you can change these values in the settings of the app")
@staticmethod
def logging_config():