1use crate::{
2 config::Config,
3 error::OpenAIError,
4 types::realtime::{
5 RealtimeCallAcceptRequest, RealtimeCallCreateRequest, RealtimeCallCreateResponse,
6 RealtimeCallReferRequest, RealtimeCallRejectRequest, RealtimeCreateClientSecretRequest,
7 RealtimeCreateClientSecretResponse,
8 },
9 Client, RequestOptions,
10};
11
12pub struct Realtime<'c, C: Config> {
15 client: &'c Client<C>,
16 pub(crate) request_options: RequestOptions,
17}
18
19impl<'c, C: Config> Realtime<'c, C> {
20 pub fn new(client: &'c Client<C>) -> Self {
21 Self {
22 client,
23 request_options: RequestOptions::new(),
24 }
25 }
26
27 pub async fn create_call(
32 &self,
33 request: RealtimeCallCreateRequest,
34 ) -> Result<RealtimeCallCreateResponse, OpenAIError> {
35 let (bytes, headers) = self
36 .client
37 .post_form_raw("/realtime/calls", request, &self.request_options)
38 .await?;
39
40 let location = headers
42 .get("location")
43 .and_then(|v| v.to_str().ok())
44 .map(|s| s.to_string());
45
46 if location.is_none() {
47 tracing::warn!("Location header not found in Realtime call creation response");
48 }
49
50 let sdp = String::from_utf8_lossy(&bytes).into_owned();
52
53 Ok(RealtimeCallCreateResponse { sdp, location })
54 }
55
56 pub async fn accept_call(
59 &self,
60 call_id: &str,
61 request: RealtimeCallAcceptRequest,
62 ) -> Result<(), OpenAIError> {
63 self.client
64 .post(
65 &format!("/realtime/calls/{}/accept", call_id),
66 request,
67 &self.request_options,
68 )
69 .await
70 }
71
72 pub async fn hangup_call(&self, call_id: &str) -> Result<(), OpenAIError> {
74 self.client
75 .post(
76 &format!("/realtime/calls/{}/hangup", call_id),
77 (),
78 &self.request_options,
79 )
80 .await
81 }
82
83 pub async fn refer_call(
85 &self,
86 call_id: &str,
87 request: RealtimeCallReferRequest,
88 ) -> Result<(), OpenAIError> {
89 self.client
90 .post(
91 &format!("/realtime/calls/{}/refer", call_id),
92 request,
93 &self.request_options,
94 )
95 .await
96 }
97
98 pub async fn reject_call(
100 &self,
101 call_id: &str,
102 request: Option<RealtimeCallRejectRequest>,
103 ) -> Result<(), OpenAIError> {
104 self.client
105 .post(
106 &format!("/realtime/calls/{}/reject", call_id),
107 request.unwrap_or_default(),
108 &self.request_options,
109 )
110 .await
111 }
112
113 pub async fn create_client_secret(
115 &self,
116 request: RealtimeCreateClientSecretRequest,
117 ) -> Result<RealtimeCreateClientSecretResponse, OpenAIError> {
118 self.client
119 .post("/realtime/client_secrets", request, &self.request_options)
120 .await
121 }
122}