1use crate::{
2 config::Config,
3 error::OpenAIError,
4 types::realtime::{
5 translation::{
6 RealtimeTranslationClientSecretCreateRequest,
7 RealtimeTranslationClientSecretCreateResponse,
8 },
9 RealtimeCallAcceptRequest, RealtimeCallCreateRequest, RealtimeCallCreateResponse,
10 RealtimeCallReferRequest, RealtimeCallRejectRequest, RealtimeCreateClientSecretRequest,
11 RealtimeCreateClientSecretResponse,
12 },
13 Client, RequestOptions,
14};
15
16pub struct Realtime<'c, C: Config> {
19 client: &'c Client<C>,
20 pub(crate) request_options: RequestOptions,
21}
22
23impl<'c, C: Config> Realtime<'c, C> {
24 pub fn new(client: &'c Client<C>) -> Self {
25 Self {
26 client,
27 request_options: RequestOptions::new(),
28 }
29 }
30
31 pub fn translations(&self) -> RealtimeTranslations<'_, C> {
33 RealtimeTranslations::new(self.client)
34 }
35
36 pub async fn create_call(
41 &self,
42 request: RealtimeCallCreateRequest,
43 ) -> Result<RealtimeCallCreateResponse, OpenAIError> {
44 let (bytes, headers) = self
45 .client
46 .post_form_raw("/realtime/calls", request, &self.request_options)
47 .await?;
48
49 let location = headers
51 .get("location")
52 .and_then(|v| v.to_str().ok())
53 .map(|s| s.to_string());
54
55 if location.is_none() {
56 tracing::warn!("Location header not found in Realtime call creation response");
57 }
58
59 let sdp = String::from_utf8_lossy(&bytes).into_owned();
61
62 Ok(RealtimeCallCreateResponse { sdp, location })
63 }
64
65 #[crate::byot(T0 = std::fmt::Display, T1 = serde::Serialize, R = serde::de::DeserializeOwned)]
68 pub async fn accept_call(
69 &self,
70 call_id: &str,
71 request: RealtimeCallAcceptRequest,
72 ) -> Result<(), OpenAIError> {
73 self.client
74 .post(
75 &format!("/realtime/calls/{}/accept", call_id),
76 request,
77 &self.request_options,
78 )
79 .await
80 }
81
82 #[crate::byot(T0 = std::fmt::Display, R = serde::de::DeserializeOwned)]
84 pub async fn hangup_call(&self, call_id: &str) -> Result<(), OpenAIError> {
85 self.client
86 .post(
87 &format!("/realtime/calls/{}/hangup", call_id),
88 (),
89 &self.request_options,
90 )
91 .await
92 }
93
94 #[crate::byot(T0 = std::fmt::Display, T1 = serde::Serialize, R = serde::de::DeserializeOwned)]
96 pub async fn refer_call(
97 &self,
98 call_id: &str,
99 request: RealtimeCallReferRequest,
100 ) -> Result<(), OpenAIError> {
101 self.client
102 .post(
103 &format!("/realtime/calls/{}/refer", call_id),
104 request,
105 &self.request_options,
106 )
107 .await
108 }
109
110 #[crate::byot(T0 = std::fmt::Display, T1 = serde::Serialize, R = serde::de::DeserializeOwned)]
112 pub async fn reject_call(
113 &self,
114 call_id: &str,
115 request: RealtimeCallRejectRequest,
116 ) -> Result<(), OpenAIError> {
117 self.client
118 .post(
119 &format!("/realtime/calls/{}/reject", call_id),
120 request,
121 &self.request_options,
122 )
123 .await
124 }
125
126 #[crate::byot(T0 = serde::Serialize, R = serde::de::DeserializeOwned)]
128 pub async fn create_client_secret(
129 &self,
130 request: RealtimeCreateClientSecretRequest,
131 ) -> Result<RealtimeCreateClientSecretResponse, OpenAIError> {
132 self.client
133 .post("/realtime/client_secrets", request, &self.request_options)
134 .await
135 }
136}
137
138pub struct RealtimeTranslations<'c, C: Config> {
141 client: &'c Client<C>,
142 pub(crate) request_options: RequestOptions,
143}
144
145impl<'c, C: Config> RealtimeTranslations<'c, C> {
146 pub fn new(client: &'c Client<C>) -> Self {
147 Self {
148 client,
149 request_options: RequestOptions::new(),
150 }
151 }
152
153 #[crate::byot(T0 = serde::Serialize, R = serde::de::DeserializeOwned)]
165 pub async fn create_client_secret(
166 &self,
167 request: RealtimeTranslationClientSecretCreateRequest,
168 ) -> Result<RealtimeTranslationClientSecretCreateResponse, OpenAIError> {
169 self.client
170 .post(
171 "/realtime/translations/client_secrets",
172 request,
173 &self.request_options,
174 )
175 .await
176 }
177}