Deduplicates crates with different versions from the graph, drops unused features. `cargo tree -d duplicate` listing: 160 -> 112 lines. <details> <summary>Deduplicated list</summary> ``` base64 (v0.22.1, v0.21.7 -> v0.22.1) convert_case (v0.11.0, v0.10.0, v0.8.0 -> v0.11.0, v0.10.0) core-foundation (v0.10.0, v0.9.4 -> v0.10.0) cssparser (v0.36.0, v0.35.0 -> v0.37.0, v0.36.0) fancy-regex (v0.18.0, v0.16.2 -> v0.19.0) fixedbitset (v0.5.7, v0.4.2 -> v0.5.7) h2 (v0.4.12, v0.3.27 -> v0.4.12) heck (v0.5.0, v0.4.1, v0.3.3 -> v0.5.0, v0.4.1) html5ever (v0.39.0, v0.35.0 -> v0.39.0) hyper (v1.7.0, v0.14.32 -> v1.7.0) hyper-rustls (v0.27.9, v0.24.2 -> v0.27.9) mach2 (v0.6.0, v0.5.0, v0.4.3 -> v0.6.0, v0.5.0) markup5ever (v0.39.0, v0.35.0 -> v0.39.0) phf (v0.13.1, v0.12.1, v0.11.3 -> v0.13.1, v0.11.3) phf_codegen (v0.13.1, v0.11.3 -> v0.13.1) phf_generator (v0.13.1, v0.12.1, v0.11.3 -> v0.13.1, v0.11.3) phf_macros (v0.13.1, v0.12.1, v0.11.3 -> v0.13.1, v0.11.3) phf_shared (v0.13.1, v0.12.1, v0.11.3 -> v0.13.1, v0.11.3) prost (v0.12.6, v0.9.0 -> v0.14.4) prost-build (v0.12.6, v0.9.0 -> v0.14.4) prost-derive (v0.12.6, v0.9.0 -> v0.14.4) prost-types (v0.12.6, v0.9.0 -> v0.14.4) rustix (v1.1.4, v0.38.44 -> v1.1.4) rustls (v0.23.40, v0.21.12 -> v0.23.40) rustls-native-certs (v0.8.3, v0.6.3 -> v0.8.3) rustls-pemfile (v2.2.0, v1.0.4 -> v2.2.0) rustls-webpki (v0.103.13, v0.101.7 -> v0.103.13) security-framework (v3.5.1, v2.11.1 -> v3.5.1) socket2 (v0.6.3, v0.5.10 -> v0.6.3) string_cache (v0.9.0, v0.8.9 -> v0.9.0) string_cache_codegen (v0.6.1, v0.5.4 -> v0.6.1) strum (v0.28.0, v0.27.2 -> v0.28.0) strum_macros (v0.28.0, v0.27.2 -> v0.28.0) tendril (v0.5.1, v0.4.3 -> v0.5.1) tokio-rustls (v0.26.4, v0.24.1 -> v0.26.4) tungstenite (v0.28.0, v0.27.0 -> v0.28.0) web_atoms (v0.2.6, v0.1.3 -> v0.2.6) which (v6.0.3, v4.4.2 -> v8.0.5) ``` </details> Release Notes: - N/A
207 lines
5.9 KiB
Rust
207 lines
5.9 KiB
Rust
pub mod proto;
|
|
pub mod token;
|
|
|
|
use anyhow::Result;
|
|
use async_trait::async_trait;
|
|
use prost::Message;
|
|
use reqwest::header::CONTENT_TYPE;
|
|
use std::{future::Future, sync::Arc, time::Duration};
|
|
|
|
#[async_trait]
|
|
pub trait Client: Send + Sync {
|
|
fn url(&self) -> &str;
|
|
async fn create_room(&self, name: String) -> Result<()>;
|
|
async fn delete_room(&self, name: String) -> Result<()>;
|
|
async fn remove_participant(&self, room: String, identity: String) -> Result<()>;
|
|
async fn update_participant(
|
|
&self,
|
|
room: String,
|
|
identity: String,
|
|
permission: proto::ParticipantPermission,
|
|
) -> Result<()>;
|
|
fn room_token(&self, room: &str, identity: &str) -> Result<String>;
|
|
fn guest_token(&self, room: &str, identity: &str) -> Result<String>;
|
|
}
|
|
|
|
pub struct LiveKitParticipantUpdate {}
|
|
|
|
#[derive(Clone)]
|
|
pub struct LiveKitClient {
|
|
http: reqwest::Client,
|
|
url: Arc<str>,
|
|
key: Arc<str>,
|
|
secret: Arc<str>,
|
|
timestamp_source: Arc<dyn token::UnixTimestampSource>,
|
|
}
|
|
|
|
impl LiveKitClient {
|
|
pub fn new(url: String, key: String, secret: String) -> Self {
|
|
Self::new_with_timestamp_source(
|
|
url,
|
|
key,
|
|
secret,
|
|
Arc::new(token::SystemUnixTimestampSource),
|
|
)
|
|
}
|
|
|
|
pub(crate) fn new_with_timestamp_source(
|
|
mut url: String,
|
|
key: String,
|
|
secret: String,
|
|
timestamp_source: Arc<dyn token::UnixTimestampSource>,
|
|
) -> Self {
|
|
if url.ends_with('/') {
|
|
url.pop();
|
|
}
|
|
|
|
Self {
|
|
http: reqwest::ClientBuilder::new()
|
|
.timeout(Duration::from_secs(5))
|
|
.build()
|
|
.unwrap(),
|
|
url: url.into(),
|
|
key: key.into(),
|
|
secret: secret.into(),
|
|
timestamp_source,
|
|
}
|
|
}
|
|
|
|
fn request<Req, Res>(
|
|
&self,
|
|
path: &str,
|
|
grant: token::VideoGrant,
|
|
body: Req,
|
|
) -> impl Future<Output = Result<Res>>
|
|
where
|
|
Req: Message + std::fmt::Debug,
|
|
Res: Default + Message,
|
|
{
|
|
let client = self.http.clone();
|
|
let token = token::create_with_timestamp_source(
|
|
&self.key,
|
|
&self.secret,
|
|
None,
|
|
grant,
|
|
self.timestamp_source.as_ref(),
|
|
);
|
|
let url = format!("{}/{}", self.url, path);
|
|
log::info!("Request {}: {:?}", url, body);
|
|
async move {
|
|
let token = token?;
|
|
let response = client
|
|
.post(&url)
|
|
.header(CONTENT_TYPE, "application/protobuf")
|
|
.bearer_auth(token)
|
|
.body(body.encode_to_vec())
|
|
.send()
|
|
.await?;
|
|
|
|
if response.status().is_success() {
|
|
log::info!("Response {}: {:?}", url, response.status());
|
|
Ok(Res::decode(response.bytes().await?)?)
|
|
} else {
|
|
log::error!("Response {}: {:?}", url, response.status());
|
|
anyhow::bail!(
|
|
"POST {} failed with status code {:?}, {:?}",
|
|
url,
|
|
response.status(),
|
|
response.text().await
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl Client for LiveKitClient {
|
|
fn url(&self) -> &str {
|
|
&self.url
|
|
}
|
|
|
|
async fn create_room(&self, name: String) -> Result<()> {
|
|
let _: proto::Room = self
|
|
.request(
|
|
"twirp/livekit.RoomService/CreateRoom",
|
|
token::VideoGrant {
|
|
room_create: Some(true),
|
|
..Default::default()
|
|
},
|
|
proto::CreateRoomRequest {
|
|
name,
|
|
..Default::default()
|
|
},
|
|
)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
async fn delete_room(&self, name: String) -> Result<()> {
|
|
let _: proto::DeleteRoomResponse = self
|
|
.request(
|
|
"twirp/livekit.RoomService/DeleteRoom",
|
|
token::VideoGrant {
|
|
room_create: Some(true),
|
|
..Default::default()
|
|
},
|
|
proto::DeleteRoomRequest { room: name },
|
|
)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
async fn remove_participant(&self, room: String, identity: String) -> Result<()> {
|
|
let _: proto::RemoveParticipantResponse = self
|
|
.request(
|
|
"twirp/livekit.RoomService/RemoveParticipant",
|
|
token::VideoGrant::to_admin(&room),
|
|
proto::RoomParticipantIdentity {
|
|
room: room.clone(),
|
|
identity,
|
|
},
|
|
)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
async fn update_participant(
|
|
&self,
|
|
room: String,
|
|
identity: String,
|
|
permission: proto::ParticipantPermission,
|
|
) -> Result<()> {
|
|
let _: proto::ParticipantInfo = self
|
|
.request(
|
|
"twirp/livekit.RoomService/UpdateParticipant",
|
|
token::VideoGrant::to_admin(&room),
|
|
proto::UpdateParticipantRequest {
|
|
room: room.clone(),
|
|
identity,
|
|
metadata: "".to_string(),
|
|
permission: Some(permission),
|
|
},
|
|
)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
fn room_token(&self, room: &str, identity: &str) -> Result<String> {
|
|
token::create_with_timestamp_source(
|
|
&self.key,
|
|
&self.secret,
|
|
Some(identity),
|
|
token::VideoGrant::to_join(room),
|
|
self.timestamp_source.as_ref(),
|
|
)
|
|
}
|
|
|
|
fn guest_token(&self, room: &str, identity: &str) -> Result<String> {
|
|
token::create_with_timestamp_source(
|
|
&self.key,
|
|
&self.secret,
|
|
Some(identity),
|
|
token::VideoGrant::for_guest(room),
|
|
self.timestamp_source.as_ref(),
|
|
)
|
|
}
|
|
}
|