Fix startup and init
All checks were successful
Docker Build and Publish / build (push) Successful in 6s
All checks were successful
Docker Build and Publish / build (push) Successful in 6s
This commit is contained in:
parent
6f2ecd9775
commit
905e3c3977
63
Makefile
Normal file
63
Makefile
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
.PHONY: build run clean run-docker stop-docker logs-docker
|
||||||
|
|
||||||
|
# Docker image details
|
||||||
|
IMAGE_NAME = git.dws.rip/dubey/spectra
|
||||||
|
TAG = main
|
||||||
|
|
||||||
|
# Local development settings
|
||||||
|
PYTHON = python3
|
||||||
|
PIP = pip3
|
||||||
|
PORT = 5000
|
||||||
|
|
||||||
|
build:
|
||||||
|
docker build -t $(IMAGE_NAME):$(TAG) .
|
||||||
|
|
||||||
|
run:
|
||||||
|
$(PYTHON) app.py
|
||||||
|
|
||||||
|
install:
|
||||||
|
$(PIP) install -r requirements.txt
|
||||||
|
|
||||||
|
clean:
|
||||||
|
find . -type d -name "__pycache__" -exec rm -r {} +
|
||||||
|
find . -type f -name "*.pyc" -delete
|
||||||
|
rm -rf thumbnails/*
|
||||||
|
rm -rf uploads/*
|
||||||
|
|
||||||
|
run-docker:
|
||||||
|
docker run -d \
|
||||||
|
--name spectra \
|
||||||
|
-p $(PORT):5000 \
|
||||||
|
-v $(PWD)/uploads:/app/uploads \
|
||||||
|
-v $(PWD)/thumbnails:/app/thumbnails \
|
||||||
|
-v $(PWD)/photos.db:/app/photos.db \
|
||||||
|
$(IMAGE_NAME):$(TAG)
|
||||||
|
|
||||||
|
run-docker-attached:
|
||||||
|
docker run -it \
|
||||||
|
--name spectra \
|
||||||
|
-p $(PORT):5000 \
|
||||||
|
-v $(PWD)/uploads:/app/uploads \
|
||||||
|
-v $(PWD)/thumbnails:/app/thumbnails \
|
||||||
|
-v $(PWD)/photos.db:/app/photos.db \
|
||||||
|
$(IMAGE_NAME):$(TAG)
|
||||||
|
|
||||||
|
stop-docker:
|
||||||
|
docker stop spectra
|
||||||
|
docker rm spectra
|
||||||
|
|
||||||
|
logs-docker:
|
||||||
|
docker logs -f spectra
|
||||||
|
|
||||||
|
rebuild: clean build run-docker
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Available commands:"
|
||||||
|
@echo " make build - Build Docker image"
|
||||||
|
@echo " make run - Run locally using Python"
|
||||||
|
@echo " make install - Install Python dependencies"
|
||||||
|
@echo " make clean - Remove cache files and generated content"
|
||||||
|
@echo " make run-docker - Run in Docker container"
|
||||||
|
@echo " make stop-docker - Stop and remove Docker container"
|
||||||
|
@echo " make logs-docker - View Docker container logs"
|
||||||
|
@echo " make rebuild - Clean, rebuild and run Docker container"
|
93
app.py
93
app.py
@ -1,6 +1,6 @@
|
|||||||
from flask import Flask, request, jsonify, render_template, redirect, url_for, flash, session, send_from_directory
|
from flask import Flask, request, jsonify, render_template, redirect, url_for, flash, session, send_from_directory
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
from models import Session as DBSession, Photo
|
from models import Session as DBSession, Photo, init_db
|
||||||
from config import load_or_create_config
|
from config import load_or_create_config
|
||||||
import os
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@ -205,97 +205,9 @@ def admin():
|
|||||||
|
|
||||||
return render_template('admin.html', photos=photos, accent_color=config['appearance']['accent_color'])
|
return render_template('admin.html', photos=photos, accent_color=config['appearance']['accent_color'])
|
||||||
|
|
||||||
@app.route('/admin/login', methods=['GET', 'POST'])
|
|
||||||
def admin_login():
|
|
||||||
if request.method == 'POST':
|
|
||||||
if request.form['password'] == config['admin']['password']:
|
|
||||||
session['logged_in'] = True
|
|
||||||
return redirect(url_for('admin'))
|
|
||||||
else:
|
|
||||||
flash('Invalid password')
|
|
||||||
return render_template('admin_login.html', accent_color=config['appearance']['accent_color'])
|
|
||||||
|
|
||||||
@app.route('/admin/upload', methods=['POST'])
|
|
||||||
def admin_upload():
|
|
||||||
if 'logged_in' not in session:
|
|
||||||
return redirect(url_for('admin_login'))
|
|
||||||
|
|
||||||
if 'file' not in request.files:
|
|
||||||
flash('No file part')
|
|
||||||
return redirect(url_for('admin'))
|
|
||||||
|
|
||||||
file = request.files['file']
|
|
||||||
if file.filename == '':
|
|
||||||
flash('No selected file')
|
|
||||||
return redirect(url_for('admin'))
|
|
||||||
|
|
||||||
if file and allowed_file(file.filename):
|
|
||||||
filename = secure_filename(file.filename)
|
|
||||||
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
|
||||||
file.save(file_path)
|
|
||||||
|
|
||||||
# Extract EXIF data
|
|
||||||
exif = None
|
|
||||||
exifraw = None
|
|
||||||
with Image.open(file_path) as img:
|
|
||||||
exifraw = img.info['exif']
|
|
||||||
width, height = img.size
|
|
||||||
exif = {
|
|
||||||
ExifTags.TAGS[k]: v
|
|
||||||
for k, v in img._getexif().items()
|
|
||||||
if k in ExifTags.TAGS
|
|
||||||
}
|
|
||||||
|
|
||||||
# Generate a unique key for the image
|
|
||||||
unique_key = hashlib.sha256(f"{filename}{datetime.now().isoformat()}".encode()).hexdigest()[:16]
|
|
||||||
|
|
||||||
# Embed the unique key into the image
|
|
||||||
try:
|
|
||||||
embed_message(file_path, unique_key, exifraw)
|
|
||||||
except ValueError as e:
|
|
||||||
flash(f"Error embedding key: {str(e)}")
|
|
||||||
os.remove(file_path)
|
|
||||||
return redirect(url_for('admin'))
|
|
||||||
|
|
||||||
|
|
||||||
# Generate thumbnails
|
|
||||||
generate_thumbnails(filename)
|
|
||||||
|
|
||||||
# Get image dimensions
|
|
||||||
with Image.open(file_path) as img:
|
|
||||||
width, height = img.size
|
|
||||||
|
|
||||||
exposure_time = exif['ExposureTime']
|
|
||||||
if isinstance(exposure_time, tuple):
|
|
||||||
exposure_fraction = f"{exposure_time[0]}/{exposure_time[1]}"
|
|
||||||
else:
|
|
||||||
exposure_fraction = f"1/{int(1/float(exposure_time))}"
|
|
||||||
|
|
||||||
# Create database entry
|
|
||||||
db_session = DBSession()
|
|
||||||
new_photo = Photo(
|
|
||||||
input_filename=filename,
|
|
||||||
thumbnail_filename=f"{os.path.splitext(filename)[0]}/256_{filename}",
|
|
||||||
focal_length=str(exif.get('FocalLengthIn35mmFilm', exif.get('FocalLength', ''))),
|
|
||||||
aperture=str(exif.get('FNumber', '')),
|
|
||||||
shutter_speed=exposure_fraction,
|
|
||||||
date_taken=datetime.strptime(str(exif.get('DateTime', '1970:01:01 00:00:00')), '%Y:%m:%d %H:%M:%S'),
|
|
||||||
iso=int(exif.get('ISOSpeedRatings', 0)),
|
|
||||||
orientation=int(exif.get('Orientation', 1)),
|
|
||||||
width=width,
|
|
||||||
height=height,
|
|
||||||
highlight_color=get_highlight_color(THUMBNAIL_FOLDER + f"/{os.path.splitext(filename)[0]}/256_{filename}"),
|
|
||||||
unique_key=unique_key
|
|
||||||
)
|
|
||||||
db_session.add(new_photo)
|
|
||||||
db_session.commit()
|
|
||||||
db_session.close()
|
|
||||||
|
|
||||||
flash('File uploaded successfully')
|
|
||||||
return redirect(url_for('admin'))
|
|
||||||
|
|
||||||
flash('Invalid file type')
|
|
||||||
return redirect(url_for('admin'))
|
|
||||||
|
|
||||||
@app.route('/admin/logout')
|
@app.route('/admin/logout')
|
||||||
def admin_logout():
|
def admin_logout():
|
||||||
@ -506,6 +418,9 @@ def admin_upload():
|
|||||||
flash('Invalid file type')
|
flash('Invalid file type')
|
||||||
return redirect(url_for('admin'))
|
return redirect(url_for('admin'))
|
||||||
|
|
||||||
|
# Initialize database tables
|
||||||
|
init_db()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(
|
app.run(
|
||||||
debug=True,
|
debug=True,
|
||||||
|
10
models.py
10
models.py
@ -22,5 +22,13 @@ class Photo(Base):
|
|||||||
unique_key = Column(String(16), nullable=False) # Add this line
|
unique_key = Column(String(16), nullable=False) # Add this line
|
||||||
|
|
||||||
engine = create_engine('sqlite:///photos.db')
|
engine = create_engine('sqlite:///photos.db')
|
||||||
Base.metadata.create_all(engine)
|
|
||||||
|
def init_db():
|
||||||
|
try:
|
||||||
|
Base.metadata.create_all(engine)
|
||||||
|
except Exception as e:
|
||||||
|
# Tables already exist, skip creation
|
||||||
|
pass
|
||||||
|
|
||||||
|
init_db()
|
||||||
Session = sessionmaker(bind=engine)
|
Session = sessionmaker(bind=engine)
|
||||||
|
Loading…
Reference in New Issue
Block a user