Voice-Agent / app.py
Shakeel401's picture
Update app.py
01a0663 verified
import os
import requests
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
app = FastAPI()
# ---- Allow frontend access ----
app.add_middleware(
CORSMiddleware,
allow_origins=["https://voice-call-agent.vercel.app/"], # βœ… Restrict in production
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# ---- Environment variables ----
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
AIRTABLE_API_KEY = os.getenv("AIRTABLE_API_KEY")
AIRTABLE_BASE_ID = os.getenv("AIRTABLE_BASE_ID")
AIRTABLE_TABLE = "Appointments"
# ---- Ephemeral Key Endpoint ----
@app.get("/get-ephemeral-key")
def get_ephemeral_key():
"""Generate an ephemeral client secret for OpenAI Realtime API"""
url = "https://api.openai.com/v1/realtime/client_secrets"
headers = {
"Authorization": f"Bearer {OPENAI_API_KEY}",
"Content-Type": "application/json",
}
body = {
"session": {
"type": "realtime",
"model": "gpt-4o-mini-realtime-preview",
"audio": {
"output": {"voice": "verse"}
},
}
}
res = requests.post(url, headers=headers, json=body)
print("πŸ”‘ Ephemeral key request status:", res.status_code)
data = res.json()
print("πŸ”‘ Ephemeral key response:", data)
return data
# ---- Add Appointment ----
class Appointment(BaseModel):
name: str
phone: str
date: str
time: str
service: str
@app.post("/add")
def add_appointment(appo: Appointment):
"""Add a new appointment to Airtable (auto-increment ID handled by Airtable)"""
url = f"https://api.airtable.com/v0/{AIRTABLE_BASE_ID}/{AIRTABLE_TABLE}"
headers = {
"Authorization": f"Bearer {AIRTABLE_API_KEY}",
"Content-Type": "application/json",
}
data = {
"fields": {
"Name": appo.name,
"Phone": appo.phone,
"Date": appo.date,
"Time": appo.time,
"Service": appo.service,
}
}
r = requests.post(url, headers=headers, json=data)
print("πŸ”Ή Airtable Add Response:", r.status_code, r.text)
return r.json()
# ---- Update Appointment ----
class UpdateAppointment(BaseModel):
appointment_id: str
name: str | None = None
phone: str | None = None
date: str | None = None
time: str | None = None
service: str | None = None
@app.post("/update")
def update_appointment(update: UpdateAppointment):
"""Update an existing appointment in Airtable using custom Appointment ID"""
headers = {
"Authorization": f"Bearer {AIRTABLE_API_KEY}",
"Content-Type": "application/json",
}
# Step 1: Find record by Appointment ID field
filter_formula = f"{{Appointment ID}} = '{update.appointment_id}'"
search_url = f"https://api.airtable.com/v0/{AIRTABLE_BASE_ID}/{AIRTABLE_TABLE}?filterByFormula={filter_formula}"
search_res = requests.get(search_url, headers=headers).json()
if not search_res.get("records"):
print("❌ No record found for Appointment ID:", update.appointment_id)
return {"status": "error", "message": "Appointment not found"}
record_id = search_res["records"][0]["id"]
# Step 2: Prepare updated fields
fields = {}
if update.name:
fields["Name"] = update.name
if update.phone:
fields["Phone"] = update.phone
if update.date:
fields["Date"] = update.date
if update.time:
fields["Time"] = update.time
if update.service:
fields["Service"] = update.service
# Step 3: Patch record by record ID
update_url = f"https://api.airtable.com/v0/{AIRTABLE_BASE_ID}/{AIRTABLE_TABLE}/{record_id}"
patch_res = requests.patch(update_url, headers=headers, json={"fields": fields})
print("πŸ”Έ Airtable Update Response:", patch_res.status_code, patch_res.text)
if patch_res.status_code == 200:
return {"status": "updated"}
else:
return {"status": "error", "message": "Update failed"}
class CancelAppointment(BaseModel):
appointment_id: str
@app.post("/cancel")
def cancel_appointment(cancel: CancelAppointment):
"""Cancel appointment by custom Appointment ID field"""
# Step 1: Search record by Appointment ID field
filter_formula = f"{{Appointment ID}} = '{cancel.appointment_id}'"
search_url = f"https://api.airtable.com/v0/{AIRTABLE_BASE_ID}/{AIRTABLE_TABLE}?filterByFormula={filter_formula}"
headers = {"Authorization": f"Bearer {AIRTABLE_API_KEY}"}
search_res = requests.get(search_url, headers=headers).json()
if not search_res.get("records"):
print("❌ No record found for Appointment ID:", cancel.appointment_id)
return {"status": "error", "message": "Appointment not found"}
record_id = search_res["records"][0]["id"]
print(f"βœ… Found Record ID: {record_id} for Appointment ID: {cancel.appointment_id}")
# Step 2: Delete record by Record ID
delete_url = f"https://api.airtable.com/v0/{AIRTABLE_BASE_ID}/{AIRTABLE_TABLE}/{record_id}"
delete_res = requests.delete(delete_url, headers=headers)
print("πŸ—‘οΈ Airtable Delete Response:", delete_res.status_code, delete_res.text)
if delete_res.status_code == 200:
return {"status": "deleted"}
else:
return {"status": "error", "message": "Delete failed"}