from fastapi import FastAPI, Request from fastapi.responses import JSONResponse # Import our modular components from config import supabase from database import get_or_create_user, update_user_activity, get_or_create_active_session, get_user_persona, get_or_create_user_intent from whatsapp import send_whatsapp_message, send_multiple_messages from ai_chat import process_message, handle_image_request from api_routes import router # --- FastAPI App Setup --- app = FastAPI(title="PropAgent", description="WhatsApp AI Agent with Supabase integration") # Include all API routes app.include_router(router) # --- WhatsApp Webhook Handler --- @app.post("/webhook") async def receive_message(req: Request): """Main webhook endpoint for receiving WhatsApp messages""" body = await req.json() print("Incoming webhook:", body) try: change = body["entry"][0]["changes"][0]["value"] contacts = change.get("contacts") messages = change.get("messages") if not contacts or not messages: return JSONResponse({"status": "ignored", "reason": "no contacts/messages"}) wa_id = contacts[0]["wa_id"] contact_name = contacts[0].get("profile", {}).get("name") msg = messages[0] if msg.get("type") == "text": user_message = msg.get("text", {}).get("body", "") wamid = msg.get("id") # Meta message ID # Get or create user in database user_info = await get_or_create_user(wa_id, contact_name) # Update user activity await update_user_activity(wa_id) # Get or create active session session = await get_or_create_active_session(wa_id) # Get user persona persona = await get_user_persona(wa_id) # Get or create user intent intent = await get_or_create_user_intent(session["id"], wa_id) # Process with AI including session memory ai_result = await process_message( user_message=user_message, user_info=user_info, session_id=session["id"], wa_id=wa_id, wamid=wamid, persona=persona, intent=intent ) ai_response = ai_result["response"] properties = ai_result.get("properties", []) # Check if this is an image request state = { "user_message": user_message, "properties": properties } # Check if this is an image request classification = ai_result.get("classification", "") print(f"DEBUG - main.py classification: '{classification}'") image_messages = None if classification.startswith("request_images") or "image" in user_message.lower() or "photo" in user_message.lower(): print(f"DEBUG - Calling handle_image_request with classification: '{classification}'") # Ensure classification is passed to handle_image_request state["classification"] = classification image_messages = await handle_image_request(state) if image_messages: # Send images await send_multiple_messages(wa_id, image_messages) else: # Send regular text response await send_whatsapp_message(wa_id, ai_response) return JSONResponse({ "status": "replied", "user_id": wa_id, "session_id": session["id"] }) except Exception as e: print("Error processing message:", e) return JSONResponse({"status": "error", "message": str(e)}) return JSONResponse({"status": "ignored"}) # --- Application Startup Event --- @app.on_event("startup") async def startup_event(): """Log startup information""" print("=" * 50) print("PropAgent WhatsApp AI Agent Starting...") print(f"Supabase: {'✅ Connected' if supabase else '❌ Not configured'}") print("=" * 50) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=7860)