livekit_api/services/
ingress.rs

1// Copyright 2023 LiveKit, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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(), // TODO: support this attribute
97                },
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(), // TODO: support this attribute
126                },
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}