mirror of
https://github.com/Derpy-Leggies/OnlyLegs.git
synced 2025-01-29 17:38:26 +00:00
Move prechecks to run file
Add Verbose option Cleanup run file
This commit is contained in:
parent
800ba38241
commit
2eec988815
|
@ -16,28 +16,13 @@ from flask import Flask, render_template
|
||||||
# Configuration
|
# Configuration
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
import platformdirs
|
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')
|
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
|
def create_app(test_config=None, verbose=False):
|
||||||
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):
|
|
||||||
"""
|
"""
|
||||||
Create and configure the main app
|
Create and configure the main app
|
||||||
"""
|
"""
|
||||||
|
@ -46,6 +31,17 @@ def create_app(test_config=None):
|
||||||
cache = Cache(config={'CACHE_TYPE': 'SimpleCache', 'CACHE_DEFAULT_TIMEOUT': 300})
|
cache = Cache(config={'CACHE_TYPE': 'SimpleCache', 'CACHE_DEFAULT_TIMEOUT': 300})
|
||||||
compress = Compress()
|
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 configuration
|
||||||
app.config.from_mapping(
|
app.config.from_mapping(
|
||||||
SECRET_KEY=os.environ.get('FLASK_SECRET'),
|
SECRET_KEY=os.environ.get('FLASK_SECRET'),
|
||||||
|
@ -67,7 +63,9 @@ def create_app(test_config=None):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Load theme
|
# Load theme
|
||||||
theme_manager.CompileTheme('default', app.root_path)
|
from . import theme_manager
|
||||||
|
theme_manager.CompileTheme('default', app.root_path, verbose)
|
||||||
|
|
||||||
# Bundle JS files
|
# Bundle JS files
|
||||||
js = Bundle('js/*.js', output='gen/packed.js')
|
js = Bundle('js/*.js', output='gen/packed.js')
|
||||||
assets.register('js_all', js)
|
assets.register('js_all', js)
|
||||||
|
|
|
@ -5,13 +5,16 @@ import os
|
||||||
import platformdirs
|
import platformdirs
|
||||||
|
|
||||||
from sqlalchemy import create_engine, Column, Integer, String, Boolean, DateTime, ForeignKey, PickleType
|
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('postgresql://username:password@host:port/database_name', echo=False)
|
||||||
# engine = create_engine('mysql://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()
|
base = declarative_base()
|
||||||
|
|
||||||
|
|
||||||
|
@ -130,4 +133,6 @@ class Bans (base): # pylint: disable=too-few-public-methods, C0103
|
||||||
created_at = Column(DateTime, nullable=False)
|
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)
|
|
@ -28,7 +28,7 @@
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="big-text">
|
<div class="big-text">
|
||||||
<h1>No image!</h1>
|
<h1>No images</h1>
|
||||||
{% if g.user %}
|
{% if g.user %}
|
||||||
<p>You can get started by uploading an image!</p>
|
<p>You can get started by uploading an image!</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
|
@ -12,12 +12,13 @@ class CompileTheme:
|
||||||
"""
|
"""
|
||||||
Compiles the theme into the static folder
|
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
|
Initialize the theme manager
|
||||||
Compiles the theme into the static folder and loads the fonts
|
Compiles the theme into the static folder and loads the fonts
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if verbose:
|
||||||
print(f"Loading '{theme_name}' theme...")
|
print(f"Loading '{theme_name}' theme...")
|
||||||
|
|
||||||
theme_path = os.path.join(app_path, 'themes', theme_name)
|
theme_path = os.path.join(app_path, 'themes', theme_name)
|
||||||
|
@ -30,11 +31,11 @@ class CompileTheme:
|
||||||
self.load_sass(theme_path, theme_dest)
|
self.load_sass(theme_path, theme_dest)
|
||||||
self.load_fonts(theme_path, theme_dest)
|
self.load_fonts(theme_path, theme_dest)
|
||||||
|
|
||||||
now = datetime.now()
|
if verbose:
|
||||||
print(f"{now.hour}:{now.minute}:{now.second} - Done!\n")
|
print(f"{datetime.now().hour}:{datetime.now().minute}:{datetime.now().second} - Done!\n")
|
||||||
|
|
||||||
@staticmethod
|
@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
|
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)
|
print("Failed to compile!\n", err)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
if verbose:
|
||||||
print("Compiled successfully!")
|
print("Compiled successfully!")
|
||||||
|
|
||||||
@staticmethod
|
@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
|
Copy the fonts folder to the static folder
|
||||||
"""
|
"""
|
||||||
|
@ -68,7 +70,6 @@ class CompileTheme:
|
||||||
font_dest = os.path.join(font_dest, 'fonts')
|
font_dest = os.path.join(font_dest, 'fonts')
|
||||||
|
|
||||||
if os.path.exists(font_dest):
|
if os.path.exists(font_dest):
|
||||||
print("Updating fonts...")
|
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(font_dest)
|
shutil.rmtree(font_dest)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
|
@ -77,7 +78,9 @@ class CompileTheme:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
shutil.copytree(source_path, font_dest)
|
shutil.copytree(source_path, font_dest)
|
||||||
print("Copied new fonts!")
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print("Failed to copy fonts!\n", err)
|
print("Failed to copy fonts!\n", err)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
if verbose:
|
||||||
|
print("Fonts copied successfully!")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "onlylegs"
|
name = "onlylegs"
|
||||||
version = "23.03.11"
|
version = "23.03.12"
|
||||||
description = "Gallery built for fast and simple image management"
|
description = "Gallery built for fast and simple image management"
|
||||||
authors = ["Fluffy-Bean <michal-gdula@protonmail.com>"]
|
authors = ["Fluffy-Bean <michal-gdula@protonmail.com>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
32
run.py
32
run.py
|
@ -5,28 +5,20 @@ print("""
|
||||||
| |_| | | | | | |_| | |__| __/ (_| \__ \
|
| |_| | | | | | |_| | |__| __/ (_| \__ \
|
||||||
\___/|_| |_|_|\__, |_____\___|\__, |___/
|
\___/|_| |_|_|\__, |_____\___|\__, |___/
|
||||||
|___/ |___/
|
|___/ |___/
|
||||||
Created by Fluffy Bean - Version 23.03.11
|
Created by Fluffy Bean - Version 23.03.12
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
from setup.args import PORT, ADDRESS, WORKERS, DEBUG, VERBOSE
|
||||||
import argparse
|
from setup.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='Run the OnlyLegs gallery')
|
# Run prechecks
|
||||||
parser.add_argument('-p', '--port', type=int, default=5000, help='Port to run on')
|
Configuration(verbose=VERBOSE)
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
if args.debug:
|
if DEBUG:
|
||||||
from gallery import create_app
|
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:
|
else:
|
||||||
from gunicorn.app.base import Application
|
from gunicorn.app.base import Application
|
||||||
from gunicorn import util
|
from gunicorn import util
|
||||||
|
@ -49,8 +41,12 @@ else:
|
||||||
return 'OnlyLegs'
|
return 'OnlyLegs'
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
return util.import_app('gallery:create_app()')
|
return util.import_app(f'gallery:create_app(verbose={VERBOSE})')
|
||||||
|
|
||||||
OnlyLegs({'bind': f'{ADDRESS}:{PORT}', 'workers': WORKERS}).run()
|
options = {
|
||||||
|
'bind': f'{ADDRESS}:{PORT}',
|
||||||
|
'workers': WORKERS,
|
||||||
|
}
|
||||||
|
|
||||||
|
OnlyLegs(options).run()
|
||||||
|
|
||||||
# uwu
|
|
||||||
|
|
30
setup/args.py
Normal file
30
setup/args.py
Normal file
|
@ -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
|
|
@ -7,37 +7,38 @@ import sys
|
||||||
import platformdirs
|
import platformdirs
|
||||||
import logging
|
import logging
|
||||||
import yaml
|
import yaml
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
USER_DIR = platformdirs.user_config_dir('onlylegs')
|
USER_DIR = platformdirs.user_config_dir('onlylegs')
|
||||||
|
|
||||||
|
|
||||||
class SetupApp:
|
class Configuration:
|
||||||
"""
|
"""
|
||||||
Setup the application on first run
|
Setup the application on first run
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self, verbose=False):
|
||||||
"""
|
"""
|
||||||
Main setup function
|
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):
|
if not os.path.exists(USER_DIR):
|
||||||
self.make_dir()
|
self.make_dir()
|
||||||
|
|
||||||
|
# Check if the .env file exists
|
||||||
if not os.path.exists(os.path.join(USER_DIR, '.env')):
|
if not os.path.exists(os.path.join(USER_DIR, '.env')):
|
||||||
self.make_env()
|
self.make_env()
|
||||||
|
|
||||||
|
# Check if the conf.yml file exists
|
||||||
if not os.path.exists(os.path.join(USER_DIR, 'conf.yml')):
|
if not os.path.exists(os.path.join(USER_DIR, 'conf.yml')):
|
||||||
self.make_yaml()
|
self.make_yaml()
|
||||||
|
|
||||||
|
# Load the config files
|
||||||
self.logging_config()
|
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()
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def make_dir():
|
def make_dir():
|
||||||
"""
|
"""
|
||||||
|
@ -46,67 +47,105 @@ class SetupApp:
|
||||||
try:
|
try:
|
||||||
os.makedirs(USER_DIR)
|
os.makedirs(USER_DIR)
|
||||||
os.makedirs(os.path.join(USER_DIR, 'instance'))
|
os.makedirs(os.path.join(USER_DIR, 'instance'))
|
||||||
|
|
||||||
print("Created user directory at:", USER_DIR)
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print("Error creating user directory:", err)
|
print("Error creating user directory:", err)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
print("Created user directory at:", USER_DIR)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def make_env():
|
def make_env():
|
||||||
"""
|
"""
|
||||||
Create the .env file with default values
|
Create the .env file with default values
|
||||||
"""
|
"""
|
||||||
env_conf = {
|
env_conf = {
|
||||||
'FLASK_SECRET': 'dev',
|
'FLASK_SECRET': os.urandom(32).hex(),
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(os.path.join(USER_DIR, '.env'), encoding='utf-8', mode='w+') as file:
|
with open(os.path.join(USER_DIR, '.env'), encoding='utf-8', mode='w+') as file:
|
||||||
for key, value in env_conf.items():
|
for key, value in env_conf.items():
|
||||||
file.write(f"{key}={value}\n")
|
file.write(f"{key}={value}\n")
|
||||||
print("Created environment variables")
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print("Error creating environment variables:", err)
|
print("Error creating environment variables:", err)
|
||||||
sys.exit(1)
|
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
|
@staticmethod
|
||||||
def make_yaml():
|
def make_yaml():
|
||||||
"""
|
"""
|
||||||
Create the YAML config file with default values
|
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 = {
|
yaml_conf = {
|
||||||
'admin': {
|
'admin': {
|
||||||
'name': 'Real Person',
|
'name': '%s' % name,
|
||||||
'username': 'User',
|
'username': '%s' % username,
|
||||||
'email': 'real-email@some.place'
|
'email': '%s' % email,
|
||||||
},
|
},
|
||||||
'upload': {
|
'upload': {
|
||||||
'allowed-extensions': {
|
'allowed-extensions': {
|
||||||
'jpg': 'jpeg',
|
'jpg': 'jpeg',
|
||||||
'jpeg': 'jpeg',
|
'jpeg': 'jpeg',
|
||||||
'png': 'png',
|
'png': 'png',
|
||||||
'webp': 'webp'
|
'webp': 'webp',
|
||||||
},
|
},
|
||||||
'max-size': 69,
|
'max-size': 69,
|
||||||
'rename': 'GWA_\{\{username\}\}_\{\{time\}\}'
|
'rename': 'GWA_{{username}}_{{time}}',
|
||||||
},
|
},
|
||||||
'website': {
|
'website': {
|
||||||
'name': 'OnlyLegs',
|
'name': 'OnlyLegs',
|
||||||
'motto': 'Gwa Gwa',
|
'motto': 'A gallery built for fast and simple image management. You can change this in the settings',
|
||||||
'language': 'english'
|
'language': 'en',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(os.path.join(USER_DIR, 'conf.yml'), encoding='utf-8', mode='w+') as file:
|
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)
|
yaml.dump(yaml_conf, file, default_flow_style=False)
|
||||||
print("Created default gallery config")
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
print("Error creating default gallery config:", err)
|
print("Error creating default gallery config:", err)
|
||||||
sys.exit(1)
|
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
|
@staticmethod
|
||||||
def logging_config():
|
def logging_config():
|
Loading…
Reference in a new issue