-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
67 lines (50 loc) · 1.92 KB
/
Copy pathmain.py
File metadata and controls
67 lines (50 loc) · 1.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
"""FastAPI entry point.
Two routes:
- GET / - liveness check
- POST /sayna/webhook - receives signed SIP webhooks from Sayna and spawns
a background voice session for the call.
"""
import logging
from fastapi import BackgroundTasks, FastAPI, HTTPException, Request
from sayna_client import SaynaValidationError, WebhookReceiver
from config import settings
from voice_agent import VoiceAgent
from voice_session import VoiceSession
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
)
logger = logging.getLogger(__name__)
app = FastAPI(title="Sayna Python Example")
agent = VoiceAgent(google_api_key=settings.google_api_key)
webhook_receiver = WebhookReceiver(secret=settings.sayna_webhook_secret)
@app.get("/")
async def health() -> dict[str, str]:
return {"status": "ok"}
@app.post("/sayna/webhook")
async def sayna_webhook(request: Request, background_tasks: BackgroundTasks) -> dict[str, str]:
body = (await request.body()).decode("utf-8")
try:
event = webhook_receiver.receive(headers=dict(request.headers), body=body)
except SaynaValidationError as exc:
logger.warning("rejected webhook: %s", exc)
raise HTTPException(status_code=401, detail=str(exc))
logger.info(
"SIP call %s -> %s (room=%s)",
event.from_phone_number,
event.to_phone_number,
event.room.name,
)
session = VoiceSession(room_name=event.room.name, agent=agent)
background_tasks.add_task(_run_session, session)
return {"status": "accepted"}
async def _run_session(session: VoiceSession) -> None:
try:
await session.run()
except Exception:
logger.exception("voice session crashed (room=%s)", session.room_name)
finally:
await session.stop()
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", host="0.0.0.0", port=settings.port, reload=False)