import os import tempfile from flask import Flask, request, jsonify from flask_cors import CORS import json from services.db import save_product_data, find_similar_products, get_product_by_id from services.cloudinary import upload_to_cloudinary, upload_multiple_to_cloudinary from services.feature_extraction import extract_features, analyze_product_image from services.product_service import generate_mock_product_data, create_product from werkzeug.utils import secure_filename from bson import ObjectId from flask.json.provider import DefaultJSONProvider app = Flask(__name__) CORS(app, resources={r"/api/*": {"origins": "*"}}, supports_credentials=True) # Add this to your main.py file class MongoJSONProvider(DefaultJSONProvider): def default(self, obj): if isinstance(obj, ObjectId): return str(obj) return super().default(obj) # Register the custom JSON provider with Flask app.json = MongoJSONProvider(app) @app.route("/api/search", methods=["POST"]) def search_image(): file = request.files["file"] with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp: file.save(temp.name) temp_path = temp.name query_features = extract_features(temp_path) similar_products = find_similar_products(query_features) os.remove(temp_path) return jsonify({ "similar_products": similar_products }) @app.route("/api/products", methods=["POST"]) def create_new_product(): """Create a new product with image pair and metadata""" print("Creating new product...") # Get files product_image = request.files.get("product_image") model_image = request.files.get("model_image") if not product_image or not model_image: return jsonify({"error": "Both product and model images are required"}), 400 # Get product metadata product_data = request.form.get("product_data") if product_data: try: product_data = json.loads(product_data) except json.JSONDecodeError: return jsonify({"error": "Invalid JSON format for product_data"}), 400 else: print("Generating mock product data...") product_data = generate_mock_product_data() print("Final product data:", product_data) # Debugging print try: # Create temporary files with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as product_temp: product_image.save(product_temp.name) product_path = product_temp.name with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as model_temp: model_image.save(model_temp.name) model_path = model_temp.name # Create product product_id, product = create_product( product_path, model_path, product_data, db_module, cloudinary_module, feature_extraction_module ) finally: # Ensure temp files are deleted if os.path.exists(product_path): os.remove(product_path) if os.path.exists(model_path): os.remove(model_path) return jsonify({"product_id": product_id, "product": product}) @app.route("/api/products/", methods=["GET"]) def get_product(product_id): """Get a product by ID""" product = get_product_by_id(product_id) if not product: return jsonify({"error": "Product not found"}), 404 return jsonify(product) @app.route("/api/upload", methods=["POST"]) def upload_image(): """Legacy endpoint for simple image upload""" file = request.files["file"] with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp: file.save(temp.name) temp_path = temp.name cloud_url = upload_to_cloudinary(temp_path) features = extract_features(temp_path) # Create mock product data with this image product_data = generate_mock_product_data() product_data.update({ "image_urls": [cloud_url], "features": features, "auto_description": "Sample uploaded product" }) product_id = save_product_data(product_data) os.remove(temp_path) return jsonify({ "message": "Image uploaded and product created", "url": cloud_url, "product_id": product_id }) if __name__ == "__main__": # Create module references for dependency injection import services.db as db_module import services.cloudinary as cloudinary_module import services.feature_extraction as feature_extraction_module port = int(os.environ.get("PORT", 5000)) app.run(host="0.0.0.0", port=port)