# app/main.py from flask import Blueprint, render_template, flash, redirect, url_for, abort, send_from_directory, request from flask_login import login_required, current_user from sqlalchemy import desc, func from app.utils.image_importer import import_images_task from app.models import ImageRecord from app import db import os main = Blueprint('main', __name__) @main.route('/') def index(): from random import choice from app.models import ImageRecord image = ImageRecord.query.order_by(func.random()).first() background_url = None if image: path = image.thumb_path or image.filepath filename = path.replace('/images/', '') background_url = url_for('main.serve_image', filename=filename) return render_template('index.html', background_url=background_url) @main.route('/gallery') @login_required def gallery(): page = request.args.get('page', 1, type=int) per_page = request.args.get('per_page', 35, type=int) images = ImageRecord.query.order_by( desc(func.coalesce(ImageRecord.taken_at, ImageRecord.imported_at)) ).paginate(page=page, per_page=per_page) return render_template( 'gallery.html', images=images, has_next=images.has_next, next_page_url=url_for('main.gallery', page=images.next_num, per_page=per_page) if images.has_next else '', has_prev=images.has_prev, prev_page_url=url_for('main.gallery', page=images.prev_num, per_page=per_page) if images.has_prev else '' ) @main.route('/images/') def serve_image(filename): return send_from_directory('/images', filename) @main.route('/artist/') @login_required def artist_gallery(artist_name): page = request.args.get('page', 1, type=int) per_page = request.args.get('per_page', 35, type=int) images = ImageRecord.query.filter_by(artist=artist_name).order_by( desc(func.coalesce(ImageRecord.taken_at, ImageRecord.imported_at)) ).paginate(page=page, per_page=per_page) return render_template( 'artist_gallery.html', images=images, artist=artist_name, has_next=images.has_next, next_page_url=url_for('main.artist_gallery', artist_name=artist_name, page=images.next_num, per_page=per_page) if images.has_next else '', has_prev=images.has_prev, prev_page_url=url_for('main.artist_gallery', artist_name=artist_name, page=images.prev_num, per_page=per_page) if images.has_prev else '' ) @main.route('/artists') @login_required def artist_list(): from app.models import ImageRecord from sqlalchemy import func # Define how many images to show per artist card images_per_artist = 3 # Change this value to tweak # Get all unique artist names artists = db.session.query(ImageRecord.artist).distinct().all() artist_data = [] for (artist,) in artists: images = ( ImageRecord.query .filter_by(artist=artist) .order_by(ImageRecord.taken_at.desc().nullslast(), ImageRecord.imported_at.desc()) .limit(images_per_artist) .all() ) artist_data.append({'name': artist, 'images': images}) return render_template('artist_list.html', artist_data=artist_data, images_per_artist=images_per_artist) @main.route('/settings') @login_required def settings(): if not current_user.is_admin: abort(403) return render_template('settings.html') @main.route('/trigger-thumbnail-generation', methods=['POST']) @login_required def trigger_thumbnail_generation(): if not current_user.is_admin: flash("You do not have permission to perform this action.", "danger") return redirect(url_for('main.settings')) try: with open('/import/thumbnail.flag', 'w') as f: f.write("trigger") flash("Thumbnail regeneration has been triggered.", "success") except Exception as e: flash(f"Failed to trigger thumbnail regeneration: {e}", "danger") return redirect(url_for('main.settings')) @main.route('/import-images') @login_required def trigger_image_import(): with open('/import/trigger.flag', 'w') as f: f.write('start') flash("Image import triggered.", "success") return redirect(url_for('main.settings')) @main.route('/reset-db', methods=['POST']) @login_required def reset_db(): if not current_user.is_admin: abort(403) ImageRecord.query.delete() db.session.commit() flash("Database has been reset. All image records removed.", "info") return redirect(url_for('main.settings'))