Spaces:
Running
Running
| from fastapi import FastAPI, Request | |
| from fastapi.responses import PlainTextResponse | |
| from datetime import datetime, timezone, timedelta | |
| import requests, os | |
| app = FastAPI() | |
| VERIFY_TOKEN = os.getenv("VERIFY_TOKEN") | |
| PAGE_ACCESS_TOKEN = os.getenv("PAGE_ACCESS_TOKEN") | |
| SUPABASE_URL = os.getenv("SUPABASE_URL") | |
| SUPABASE_API_KEY = os.getenv("SUPABASE_API_KEY") | |
| GAS_WEBAPP_URL = os.getenv("GAS_WEBAPP_URL") | |
| # لو لسه هتستعمل exchange_code | |
| APP_ID = os.getenv("APP_ID") | |
| APP_SECRET = os.getenv("APP_SECRET") | |
| REDIRECT_URI = os.getenv("REDIRECT_URI") | |
| async def verify_webhook(request: Request): | |
| params = request.query_params | |
| code = params.get("code") | |
| # ✅ OAuth via GAS (اختياري) | |
| if code: | |
| gas_payload = { | |
| "action": "exchange_code", | |
| "client_id": APP_ID, | |
| "redirect_uri": REDIRECT_URI, | |
| "client_secret": APP_SECRET, | |
| "code": code | |
| } | |
| resp = requests.post(GAS_WEBAPP_URL, json=gas_payload, timeout=20) | |
| print("🎟️ Token Exchange Response:", resp.json()) | |
| return PlainTextResponse("Token exchange completed") | |
| # ✅ Verification normal | |
| if params.get("hub.mode") == "subscribe" and params.get("hub.verify_token") == VERIFY_TOKEN: | |
| return PlainTextResponse(content=params.get("hub.challenge")) | |
| return PlainTextResponse(content="Verification failed", status_code=403) | |
| async def receive_webhook(request: Request): | |
| payload = await request.json() | |
| print("📥 Webhook payload received:") | |
| gmt_plus_3 = timezone(timedelta(hours=3)) | |
| print("Timestamp:", datetime.now(gmt_plus_3).strftime('%Y-%m-%d %H:%M:%S')) | |
| try: | |
| for entry in payload.get("entry", []): | |
| for change in entry.get("changes", []): | |
| if change.get("field") == "leadgen": | |
| lead_id = change["value"]["leadgen_id"] | |
| print(f"🔍 Lead ID: {lead_id}") | |
| # ✅ Fetch lead via GAS | |
| gas_payload = { | |
| "action": "fetch_lead", | |
| "lead_id": lead_id, | |
| "access_token": PAGE_ACCESS_TOKEN | |
| } | |
| response = requests.post(GAS_WEBAPP_URL, json=gas_payload, timeout=20) | |
| data = response.json() | |
| # لو Meta رجعت error | |
| if "error" in data: | |
| print("⚠️ Meta error:", data) | |
| return {"status": "error", "meta": data} | |
| print("RAW GAS RESPONSE:", data) | |
| field_map = {} | |
| for item in data.get("field_data", []): | |
| field_map[item.get("name")] = ", ".join(item.get("values", [])) | |
| headers = { | |
| "apikey": SUPABASE_API_KEY, | |
| "Authorization": f"Bearer {SUPABASE_API_KEY}", | |
| "Content-Type": "application/json" | |
| } | |
| insert_data = { | |
| "platform": "meta", | |
| "campaign_id": data.get("campaign_id"), | |
| "campaign_name": data.get("campaign_name"), | |
| "adset_id": data.get("adset_id"), | |
| "adset_name": data.get("adset_name"), | |
| "ad_id": data.get("ad_id"), | |
| "lead_id": lead_id, | |
| "full_name": field_map.get("full name"), | |
| "email": field_map.get("email"), | |
| "phone": field_map.get("phone_number"), | |
| "city": field_map.get("city"), | |
| "lead_timestamp": datetime.now(gmt_plus_3).strftime("%Y-%m-%d %H:%M:%S+03") | |
| } | |
| supa_resp = requests.post( | |
| f"{SUPABASE_URL}/rest/v1/binrushdleads", | |
| headers=headers, | |
| json=insert_data | |
| ) | |
| print("💾 Supabase insert status:", supa_resp.status_code) | |
| except Exception as e: | |
| print(f"⚠️ Error processing lead: {e}") | |
| return {"status": "ok"} | |