File size: 5,396 Bytes
5621acf
 
af51678
5621acf
b39b3a3
af51678
 
 
b39b3a3
5621acf
 
b39b3a3
70c561e
5621acf
 
 
 
b39b3a3
af51678
 
 
 
 
5621acf
af51678
 
b39b3a3
624426e
cc1e332
 
4b20561
cc1e332
 
624426e
 
01a0663
624426e
b39b3a3
 
624426e
cc1e332
9111a92
624426e
b39b3a3
624426e
b39b3a3
624426e
9111a92
df37c18
af51678
 
 
 
 
 
 
 
df37c18
af51678
 
b39b3a3
af51678
df37c18
 
 
 
af51678
 
 
 
 
 
 
 
 
b39b3a3
af51678
b39b3a3
af51678
 
 
 
 
 
e310b5f
af51678
 
 
 
 
df37c18
af51678
 
e310b5f
df37c18
 
 
 
b39b3a3
e310b5f
 
 
 
 
 
 
 
 
 
 
 
af51678
e310b5f
 
df37c18
 
 
 
 
 
 
 
 
e310b5f
 
 
 
af51678
e310b5f
 
 
 
df37c18
305af1d
 
 
05ceeaa
af51678
 
05ceeaa
 
 
 
 
 
af51678
05ceeaa
 
 
 
 
 
 
 
305af1d
05ceeaa
 
 
 
 
 
305af1d
 
05ceeaa
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
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"}