Spaces:
Runtime error
Runtime error
| from flask import Flask, render_template, request, jsonify | |
| import os | |
| import requests | |
| import json | |
| import http.server | |
| import socketserver | |
| import threading | |
| import subprocess | |
| import time | |
| import socket | |
| from dotenv import load_dotenv | |
| from PIL import Image | |
| import io | |
| from transformers import pipeline | |
| import base64 | |
| app = Flask(__name__) | |
| load_dotenv() | |
| # Configuration | |
| INSTAGRAM_ACCESS_TOKEN = os.getenv('INSTAGRAM_ACCESS_TOKEN') | |
| INSTAGRAM_USER_ID = os.getenv('INSTAGRAM_USER_ID') | |
| HUGGINGFACE_API_TOKEN = os.getenv('HUGGINGFACE_API_TOKEN') | |
| UPLOAD_FOLDER = 'uploads' | |
| PORT = 8000 | |
| httpd = None | |
| ngrok_process = None | |
| # Ensure upload folder exists | |
| os.makedirs(UPLOAD_FOLDER, exist_ok=True) | |
| # Check if port is available | |
| def is_port_available(port): | |
| with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: | |
| return s.connect_ex(('localhost', port)) != 0 | |
| # Start local HTTP server to serve images | |
| def start_http_server(): | |
| global httpd | |
| Handler = http.server.SimpleHTTPRequestHandler | |
| port = PORT | |
| max_attempts = 5 | |
| for i in range(max_attempts): | |
| if is_port_available(port): | |
| try: | |
| httpd = socketserver.TCPServer(("", port), Handler) | |
| server_thread = threading.Thread(target=httpd.serve_forever) | |
| server_thread.daemon = True | |
| server_thread.start() | |
| print(f"HTTP server started on port {port}") | |
| return port | |
| except Exception as e: | |
| print(f"Failed to start HTTP server on port {port}: {e}") | |
| raise | |
| else: | |
| print(f"Port {port} is in use, trying port {port + 1}") | |
| port += 1 | |
| raise OSError("No available ports found after multiple attempts") | |
| # Start ngrok to create a public URL | |
| def start_ngrok(port): | |
| global ngrok_process | |
| try: | |
| ngrok_process = subprocess.Popen(["ngrok", "http", str(port)], stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
| time.sleep(2) # Wait for ngrok to start | |
| resp = requests.get("http://localhost:4040/api/tunnels") | |
| public_url = resp.json()["tunnels"][0]["public_url"] | |
| print(f"Ngrok tunnel started at {public_url}") | |
| return public_url | |
| except Exception as e: | |
| print(f"Failed to start ngrok: {e}") | |
| raise | |
| # Hugging Face captioning pipeline | |
| try: | |
| caption_pipeline = pipeline("image-to-text", model="Salesforce/blip-image-captioning-base") | |
| except Exception as e: | |
| print(f"Failed to initialize Hugging Face pipeline: {e}") | |
| caption_pipeline = None | |
| def index(): | |
| return render_template('index.html') | |
| def upload_image(): | |
| global ngrok_process | |
| try: | |
| # Get base64 image from request | |
| image_data = request.json['image'].split(',')[1] | |
| image_bytes = base64.b64decode(image_data) | |
| # Save image to uploads folder | |
| image_path = os.path.join(UPLOAD_FOLDER, 'captured_image.jpg') | |
| with open(image_path, 'wb') as f: | |
| f.write(image_bytes) | |
| # Generate caption using Hugging Face | |
| caption = "Default caption: Uploaded image" | |
| if caption_pipeline: | |
| try: | |
| image = Image.open(io.BytesIO(image_bytes)) | |
| caption_result = caption_pipeline(image) | |
| caption = caption_result[0]['generated_text'] | |
| except Exception as e: | |
| print(f"Failed to generate caption: {e}") | |
| # Get public URL from ngrok | |
| port = start_http_server() | |
| public_url = start_ngrok(port) | |
| image_url = f"{public_url}/uploads/captured_image.jpg" | |
| # Create Instagram media container | |
| create_url = f"https://graph.facebook.com/v20.0/{INSTAGRAM_USER_ID}/media" | |
| payload = { | |
| "image_url": image_url, | |
| "caption": caption, | |
| "access_token": INSTAGRAM_ACCESS_TOKEN | |
| } | |
| response = requests.post(create_url, params=payload) | |
| result = response.json() | |
| if 'id' in result: | |
| creation_id = result['id'] | |
| # Publish the media | |
| publish_url = f"https://graph.facebook.com/v20.0/{INSTAGRAM_USER_ID}/media_publish" | |
| publish_payload = { | |
| "creation_id": creation_id, | |
| "access_token": INSTAGRAM_ACCESS_TOKEN | |
| } | |
| publish_response = requests.post(publish_url, params=publish_payload) | |
| publish_result = publish_response.json() | |
| if 'id' in publish_result: | |
| return jsonify({"status": "success", "message": "Image posted to Instagram", "caption": caption}) | |
| else: | |
| return jsonify({"status": "error", "message": publish_result.get('error', {}).get('message', 'Failed to publish')}) | |
| else: | |
| return jsonify({"status": "error", "message": result.get('error', {}).get('message', 'Failed to create media container')}) | |
| except Exception as e: | |
| return jsonify({"status": "error", "message": str(e)}) | |
| finally: | |
| # Clean up ngrok | |
| if ngrok_process: | |
| ngrok_process.terminate() | |
| ngrok_process = None | |
| def shutdown(): | |
| global httpd, ngrok_process | |
| try: | |
| if httpd: | |
| httpd.shutdown() | |
| httpd.server_close() | |
| print("HTTP server shut down") | |
| if ngrok_process: | |
| ngrok_process.terminate() | |
| ngrok_process = None | |
| print("Ngrok shut down") | |
| return jsonify({"status": "success", "message": "Server shutdown"}) | |
| except Exception as e: | |
| return jsonify({"status": "error", "message": str(e)}) | |
| if __name__ == '__main__': | |
| app.run(debug=True) |