import logging from functools import wraps from flask import request, jsonify from models import Preset, Settings from services.generation import generate_from_preset from services.job_queue import _job_queue_lock, _job_history logger = logging.getLogger('gaze') def register_routes(app): def require_api_key(f): @wraps(f) def decorated(*args, **kwargs): api_key = request.headers.get('X-API-Key') or request.args.get('api_key') if not api_key: return jsonify({'error': 'Missing API key. Provide X-API-Key header or api_key query parameter.'}), 401 settings = Settings.query.first() if not settings or not settings.api_key or api_key != settings.api_key: return jsonify({'error': 'Invalid API key.'}), 403 return f(*args, **kwargs) return decorated @app.route('/api/v1/presets') @require_api_key def api_v1_presets(): presets = Preset.query.order_by(Preset.name).all() return jsonify({ 'presets': [ { 'preset_id': p.preset_id, 'slug': p.slug, 'name': p.name, 'has_cover': bool(p.image_path), } for p in presets ] }) @app.route('/api/v1/generate/', methods=['POST']) @require_api_key def api_v1_generate(preset_slug): preset = Preset.query.filter_by(slug=preset_slug).first() if not preset: return jsonify({'error': f'Preset not found: {preset_slug}'}), 404 body = request.get_json(silent=True) or {} count = body.get('count', 1) try: count = int(count) except (TypeError, ValueError): return jsonify({'error': 'count must be an integer'}), 400 if count < 1 or count > 20: return jsonify({'error': 'count must be between 1 and 20'}), 400 seed = body.get('seed') if seed is not None: try: seed = int(seed) except (TypeError, ValueError): return jsonify({'error': 'seed must be an integer'}), 400 width = body.get('width') height = body.get('height') if (width is None) != (height is None): return jsonify({'error': 'width and height must both be provided or both omitted'}), 400 overrides = { 'action': 'preview', 'checkpoint': body.get('checkpoint', ''), 'extra_positive': body.get('extra_positive', ''), 'extra_negative': body.get('extra_negative', ''), 'seed': seed, 'width': int(width) if width else None, 'height': int(height) if height else None, } try: jobs = [] for _ in range(count): job = generate_from_preset(preset, overrides) jobs.append({'job_id': job['id'], 'status': 'queued'}) return jsonify({'jobs': jobs}), 202 except Exception as e: logger.exception("API generation error (preset %s): %s", preset_slug, e) return jsonify({'error': str(e)}), 500 @app.route('/api/v1/job/') @require_api_key def api_v1_job_status(job_id): with _job_queue_lock: job = _job_history.get(job_id) if not job: return jsonify({'error': 'Job not found'}), 404 resp = { 'id': job['id'], 'label': job['label'], 'status': job['status'], 'error': job['error'], } if job.get('result'): resp['result'] = job['result'] return jsonify(resp)