mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2026-06-18 07:19:35 +00:00
153 lines
5.0 KiB
Python
153 lines
5.0 KiB
Python
"""
|
|
Public endpoints — no auth, CORS-open. Used by the landing page.
|
|
|
|
Routes:
|
|
POST /api/v1/public/demo-request — landing form submission
|
|
Body: {name, company, email, phone, sector?, size?, message?, consent, website(honeypot)}
|
|
Returns: {ok: true, calendly_url: "...", lead_id?: "..."}
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
import os
|
|
from typing import Any
|
|
|
|
from fastapi import APIRouter, HTTPException, Request
|
|
|
|
from dealix.analytics import FUNNEL_EVENTS, capture_event
|
|
|
|
log = logging.getLogger(__name__)
|
|
router = APIRouter(prefix="/api/v1/public", tags=["public"])
|
|
|
|
|
|
CALENDLY_URL = os.getenv(
|
|
"CALENDLY_URL",
|
|
"https://calendly.com/sami-assiri11/dealix-demo",
|
|
)
|
|
|
|
|
|
@router.post("/demo-request")
|
|
async def demo_request(req: Request) -> dict[str, Any]:
|
|
"""Public landing form — captures demo request and returns Calendly booking URL."""
|
|
try:
|
|
body = await req.json()
|
|
except Exception as e:
|
|
raise HTTPException(status_code=400, detail="invalid_json") from e
|
|
|
|
# Honeypot: if "website" field is filled, silently drop
|
|
if body.get("website"):
|
|
log.info("demo_request_honeypot_triggered")
|
|
return {"ok": True, "calendly_url": CALENDLY_URL}
|
|
|
|
name = str(body.get("name") or "").strip()
|
|
company = str(body.get("company") or "").strip()
|
|
email = str(body.get("email") or "").strip()
|
|
phone = str(body.get("phone") or "").strip()
|
|
sector = str(body.get("sector") or "").strip()
|
|
size = str(body.get("size") or "").strip()
|
|
message = str(body.get("message") or "").strip()
|
|
consent = bool(body.get("consent"))
|
|
|
|
if not name or not company or "@" not in email or not phone:
|
|
raise HTTPException(status_code=422, detail="missing_required_fields")
|
|
if not consent:
|
|
raise HTTPException(status_code=422, detail="consent_required")
|
|
|
|
# Fire PostHog event (fire-and-forget — never blocks response)
|
|
try:
|
|
await capture_event(
|
|
(
|
|
FUNNEL_EVENTS.DEMO_REQUESTED
|
|
if hasattr(FUNNEL_EVENTS, "DEMO_REQUESTED")
|
|
else "demo_requested"
|
|
),
|
|
distinct_id=email,
|
|
properties={
|
|
"name": name,
|
|
"company": company,
|
|
"email": email,
|
|
"phone": phone,
|
|
"sector": sector,
|
|
"size": size,
|
|
"message_len": len(message),
|
|
"source": "landing.demo_form",
|
|
},
|
|
)
|
|
except Exception:
|
|
log.exception("posthog_capture_failed")
|
|
|
|
# TODO: once AcquisitionPipeline is DI-wired here, route through pipeline.run()
|
|
# For now, minimal path: accept + return Calendly URL. Lead is still in PostHog.
|
|
log.info(
|
|
"demo_request_accepted email=%s company=%s sector=%s",
|
|
email,
|
|
company,
|
|
sector,
|
|
)
|
|
|
|
return {
|
|
"ok": True,
|
|
"calendly_url": CALENDLY_URL,
|
|
"message": "تم استلام طلبك — سنتواصل خلال 4 ساعات عمل",
|
|
}
|
|
|
|
|
|
@router.get("/health")
|
|
async def public_health() -> dict[str, Any]:
|
|
"""Unauthenticated health probe for landing page to show live status."""
|
|
return {"ok": True, "service": "dealix-api"}
|
|
|
|
|
|
@router.post("/partner-application")
|
|
async def partner_application(req: Request) -> dict[str, Any]:
|
|
"""Public partner signup — for agencies/freelancers/consultants."""
|
|
try:
|
|
body = await req.json()
|
|
except Exception:
|
|
# Also accept form-urlencoded submissions from Formspree-style forms
|
|
form = await req.form()
|
|
body = dict(form)
|
|
|
|
name = str(body.get("name") or "").strip()
|
|
company = str(body.get("company") or "").strip()
|
|
email = str(body.get("email") or "").strip()
|
|
phone = str(body.get("phone") or "").strip()
|
|
ptype = str(body.get("partnership_type") or body.get("type") or "referral").strip()
|
|
services = str(body.get("services") or "").strip()
|
|
active_clients = str(body.get("active_clients") or body.get("clients") or "0")
|
|
why = str(body.get("why") or "").strip()
|
|
|
|
if not name or not company or "@" not in email:
|
|
raise HTTPException(status_code=422, detail="missing_required_fields")
|
|
|
|
log.info(
|
|
"partner_application_received company=%s type=%s clients=%s",
|
|
company,
|
|
ptype,
|
|
active_clients,
|
|
)
|
|
|
|
try:
|
|
await capture_event(
|
|
"partner_application_submitted",
|
|
distinct_id=email or company or "anonymous",
|
|
properties={
|
|
"company": company,
|
|
"partnership_type": ptype,
|
|
"active_clients": active_clients,
|
|
"has_phone": bool(phone),
|
|
"has_services": bool(services),
|
|
"has_why": bool(why),
|
|
"source": "dealix.partners_page",
|
|
},
|
|
)
|
|
except Exception:
|
|
log.warning("posthog_capture_failed", exc_info=True)
|
|
|
|
return {
|
|
"ok": True,
|
|
"message": "وصلنا طلبك. سنتواصل خلال 48 ساعة.",
|
|
"next_step": "email_review",
|
|
}
|