from flask import Flask, request, jsonify, send_file, render_template import os, io, json, argparse from pathlib import Path from werkzeug.utils import secure_filename from metadata_pipeline import read_metadata, write_metadata, strip_metadata from metadata_randomizer import process_file as randomize_file import tempfile app = Flask(__name__) app.config['MAX_CONTENT_LENGTH'] = 50 * 1024 * 1024 # 50MB ALLOWED = {'.jpg', '.jpeg', '.png', '.webp'} def allowed(filename): return Path(filename).suffix.lower() in ALLOWED @app.route('/') def index(): return render_template('index.html') @app.route('/api/read', methods=['POST']) def api_read(): f = request.files.get('image') if not f or not allowed(f.filename): return jsonify({'error': 'Invalid file'}), 400 with tempfile.NamedTemporaryFile(suffix=Path(f.filename).suffix, delete=False) as tmp: f.save(tmp.name) try: meta = read_metadata(tmp.name) finally: os.unlink(tmp.name) return jsonify(meta) @app.route('/api/write', methods=['POST']) def api_write(): f = request.files.get('image') if not f or not allowed(f.filename): return jsonify({'error': 'Invalid file'}), 400 suffix = Path(secure_filename(f.filename)).suffix.lower() with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp_in: f.save(tmp_in.name) tmp_out = tmp_in.name + '_out' + suffix try: data = request.form args = argparse.Namespace( title=data.get('title') or None, author=data.get('author') or None, description=data.get('description') or None, copyright=data.get('copyright') or None, software=data.get('software') or None, keywords=data.get('keywords') or None, date=data.get('date') or None, rating=int(data['rating']) if data.get('rating') else None, lat=float(data['lat']) if data.get('lat') else None, lon=float(data['lon']) if data.get('lon') else None, alt=float(data['alt']) if data.get('alt') else None, make=data.get('make') or None, model=data.get('model') or None, lens_make=data.get('lens_make') or None, lens_model=data.get('lens_model') or None, output=tmp_out, ) write_metadata(tmp_in.name, tmp_out, args) return send_file(tmp_out, as_attachment=True, download_name='edited_' + secure_filename(f.filename), mimetype='image/' + suffix.lstrip('.')) finally: os.unlink(tmp_in.name) if os.path.exists(tmp_out): os.unlink(tmp_out) @app.route('/api/strip', methods=['POST']) def api_strip(): f = request.files.get('image') if not f or not allowed(f.filename): return jsonify({'error': 'Invalid file'}), 400 suffix = Path(secure_filename(f.filename)).suffix.lower() with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp_in: f.save(tmp_in.name) tmp_out = tmp_in.name + '_stripped' + suffix try: strip_metadata(tmp_in.name, tmp_out) return send_file(tmp_out, as_attachment=True, download_name='stripped_' + secure_filename(f.filename), mimetype='image/' + suffix.lstrip('.')) finally: os.unlink(tmp_in.name) if os.path.exists(tmp_out): os.unlink(tmp_out) @app.route('/api/randomize', methods=['POST']) def api_randomize(): f = request.files.get('image') if not f or not allowed(f.filename): return jsonify({'error': 'Invalid file'}), 400 suffix = Path(secure_filename(f.filename)).suffix.lower() with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp_in: f.save(tmp_in.name) out_dir = tempfile.mkdtemp() try: randomize_file(tmp_in.name, out_dir) out_path = os.path.join(out_dir, os.path.basename(tmp_in.name)) return send_file(out_path, as_attachment=True, download_name='randomized_' + secure_filename(f.filename), mimetype='image/' + suffix.lstrip('.')) finally: os.unlink(tmp_in.name) import shutil shutil.rmtree(out_dir, ignore_errors=True) if __name__ == '__main__': port = int(os.environ.get('PORT', 7860)) app.run(host='0.0.0.0', port=port)