1use livekit_protocol as proto;
16
17use super::{ServiceBase, ServiceResult, LIVEKIT_PACKAGE};
18use crate::{access_token::VideoGrants, get_env_keys, services::twirp_client::TwirpClient};
19
20#[derive(Default, Clone, Debug)]
21pub struct CreateIngressOptions {
22 pub name: String,
23 pub room_name: String,
24 pub participant_metadata: String,
25 pub participant_identity: String,
26 pub participant_name: String,
27 pub audio: proto::IngressAudioOptions,
28 pub video: proto::IngressVideoOptions,
29 pub bypass_transcoding: bool,
30 pub enable_transcoding: Option<bool>,
31 pub url: String,
32}
33
34#[derive(Default, Clone, Debug)]
35pub struct UpdateIngressOptions {
36 pub name: String,
37 pub room_name: String,
38 pub participant_metadata: String,
39 pub participant_identity: String,
40 pub participant_name: String,
41 pub audio: proto::IngressAudioOptions,
42 pub video: proto::IngressVideoOptions,
43 pub bypass_transcoding: Option<bool>,
44 pub enable_transcoding: Option<bool>,
45}
46
47#[derive(Debug, Clone, PartialEq, Eq)]
48pub enum IngressListFilter {
49 All,
50 Room(String),
51 IngressId(String),
52}
53
54const SVC: &str = "Ingress";
55
56#[derive(Debug)]
57pub struct IngressClient {
58 base: ServiceBase,
59 client: TwirpClient,
60}
61
62impl IngressClient {
63 pub fn with_api_key(host: &str, api_key: &str, api_secret: &str) -> Self {
64 Self {
65 base: ServiceBase::with_api_key(api_key, api_secret),
66 client: TwirpClient::new(host, LIVEKIT_PACKAGE, None),
67 }
68 }
69
70 pub fn new(host: &str) -> ServiceResult<Self> {
71 let (api_key, api_secret) = get_env_keys()?;
72 Ok(Self::with_api_key(host, &api_key, &api_secret))
73 }
74
75 pub async fn create_ingress(
76 &self,
77 input_type: proto::IngressInput,
78 options: CreateIngressOptions,
79 ) -> ServiceResult<proto::IngressInfo> {
80 self.client
81 .request(
82 SVC,
83 "CreateIngress",
84 proto::CreateIngressRequest {
85 input_type: input_type as i32,
86 name: options.name,
87 room_name: options.room_name,
88 participant_metadata: options.participant_metadata,
89 participant_identity: options.participant_identity,
90 participant_name: options.participant_name,
91 audio: Some(options.audio),
92 video: Some(options.video),
93 bypass_transcoding: options.bypass_transcoding,
94 enable_transcoding: options.enable_transcoding,
95 url: options.url,
96 enabled: Default::default(), },
98 self.base
99 .auth_header(VideoGrants { ingress_admin: true, ..Default::default() }, None)?,
100 )
101 .await
102 .map_err(Into::into)
103 }
104
105 pub async fn update_ingress(
106 &self,
107 ingress_id: &str,
108 options: UpdateIngressOptions,
109 ) -> ServiceResult<proto::IngressInfo> {
110 self.client
111 .request(
112 SVC,
113 "UpdateIngress",
114 proto::UpdateIngressRequest {
115 ingress_id: ingress_id.to_owned(),
116 name: options.name,
117 room_name: options.room_name,
118 participant_metadata: options.participant_metadata,
119 participant_identity: options.participant_identity,
120 participant_name: options.participant_name,
121 audio: Some(options.audio),
122 video: Some(options.video),
123 bypass_transcoding: options.bypass_transcoding,
124 enable_transcoding: options.enable_transcoding,
125 enabled: Default::default(), },
127 self.base
128 .auth_header(VideoGrants { ingress_admin: true, ..Default::default() }, None)?,
129 )
130 .await
131 .map_err(Into::into)
132 }
133
134 pub async fn list_ingress(
135 &self,
136 filter: IngressListFilter,
137 ) -> ServiceResult<Vec<proto::IngressInfo>> {
138 let resp: proto::ListIngressResponse = self
139 .client
140 .request(
141 SVC,
142 "ListIngress",
143 proto::ListIngressRequest {
144 ingress_id: match filter.clone() {
145 IngressListFilter::IngressId(id) => id,
146 _ => Default::default(),
147 },
148 room_name: match filter {
149 IngressListFilter::Room(room) => room,
150 _ => Default::default(),
151 },
152 },
153 self.base
154 .auth_header(VideoGrants { ingress_admin: true, ..Default::default() }, None)?,
155 )
156 .await?;
157
158 Ok(resp.items)
159 }
160
161 pub async fn delete_ingress(&self, ingress_id: &str) -> ServiceResult<proto::IngressInfo> {
162 self.client
163 .request(
164 SVC,
165 "DeleteIngress",
166 proto::DeleteIngressRequest { ingress_id: ingress_id.to_owned() },
167 self.base
168 .auth_header(VideoGrants { ingress_admin: true, ..Default::default() }, None)?,
169 )
170 .await
171 .map_err(Into::into)
172 }
173}