pub mod agents;
pub mod alert_rules;
pub mod batch_calls;
pub mod connectors;
pub mod egress;
pub mod hls;
pub mod ingress;
pub mod participants;
pub mod recordings;
pub mod resource_pool;
pub mod rooms;
pub mod rtmp;
pub mod sessions;
pub mod sip;
pub mod transcodings;
pub mod transcription;
mod session_utils;
#[cfg(test)]
mod egress_tests;
#[cfg(test)]
mod phase5_tests;
#[cfg(test)]
mod resource_tests;
#[cfg(test)]
mod sip_tests;
use percent_encoding::{utf8_percent_encode, AsciiSet, NON_ALPHANUMERIC};
use crate::client::Client;
const PATH_SEGMENT: &AsciiSet = &NON_ALPHANUMERIC
.remove(b'-')
.remove(b'.')
.remove(b'_')
.remove(b'~');
pub(crate) fn escape(segment: &str) -> String {
utf8_percent_encode(segment, PATH_SEGMENT).to_string()
}
pub(crate) fn random_uuid() -> String {
uuid::Uuid::new_v4().to_string()
}
pub(crate) fn slugify_name(name: &str) -> String {
let mut slug = String::with_capacity(name.len());
let mut previous_was_dash = false;
for character in name.chars().flat_map(char::to_lowercase) {
if character.is_ascii_alphanumeric() || character == '_' || character == '-' {
slug.push(character);
previous_was_dash = false;
} else if !previous_was_dash {
slug.push('-');
previous_was_dash = true;
}
}
let slug = slug.trim_matches('-');
let slug: String = slug.chars().take(40).collect();
if slug.is_empty() {
"agent".to_string()
} else {
slug
}
}
impl Client {
pub fn rooms(&self) -> rooms::RoomsResource<'_> {
rooms::RoomsResource::new(self)
}
pub fn sessions(&self) -> sessions::SessionsResource<'_> {
sessions::SessionsResource::new(self)
}
pub fn participants(&self) -> participants::ParticipantsResource<'_> {
participants::ParticipantsResource::new(self)
}
pub fn recordings(&self) -> recordings::RecordingsResource<'_> {
recordings::RecordingsResource::new(self)
}
pub fn hls(&self) -> hls::HlsResource<'_> {
hls::HlsResource::new(self)
}
pub fn rtmp(&self) -> rtmp::RtmpResource<'_> {
rtmp::RtmpResource::new(self)
}
pub fn sip(&self) -> sip::SipResource<'_> {
sip::SipResource::new(self)
}
pub fn agents(&self) -> agents::AgentsResource<'_> {
agents::AgentsResource::new(self)
}
pub fn alert_rules(&self) -> alert_rules::AlertRulesResource<'_> {
alert_rules::AlertRulesResource::new(self)
}
pub fn batch_call(&self) -> batch_calls::BatchCallsResource<'_> {
batch_calls::BatchCallsResource::new(self)
}
pub fn connectors(&self) -> connectors::ConnectorsResource<'_> {
connectors::ConnectorsResource::new(self)
}
pub fn resource_pool(&self) -> resource_pool::ResourcePoolResource<'_> {
resource_pool::ResourcePoolResource::new(self)
}
pub fn transcodings(&self) -> transcodings::TranscodingsResource<'_> {
transcodings::TranscodingsResource::new(self)
}
pub fn transcription(&self) -> transcription::TranscriptionResource<'_> {
transcription::TranscriptionResource::new(self)
}
pub fn whip(&self) -> ingress::WhipResource<'_> {
ingress::WhipResource::new(self)
}
pub fn whep(&self) -> ingress::WhepResource<'_> {
ingress::WhepResource::new(self)
}
pub fn socket_ingress(&self) -> ingress::SocketIngressResource<'_> {
ingress::SocketIngressResource::new(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn escapes_path_segments_but_keeps_unreserved_characters() {
assert_eq!(escape("abcd-efgh-ijkl"), "abcd-efgh-ijkl");
assert_eq!(escape("a_b.c~d"), "a_b.c~d");
assert_eq!(escape("a/b"), "a%2Fb");
assert_eq!(escape("a b"), "a%20b");
assert_eq!(escape("../etc"), "..%2Fetc");
assert_eq!(escape("100%"), "100%25");
}
#[test]
fn slugify_constrains_names_to_the_secret_charset() {
assert_eq!(slugify_name("My Agent"), "my-agent");
assert_eq!(
slugify_name("keep_dashes-and_underscores"),
"keep_dashes-and_underscores"
);
assert_eq!(slugify_name("a!!!b"), "a-b", "runs collapse to one dash");
assert_eq!(slugify_name("--trim--"), "trim");
assert_eq!(slugify_name("!!!"), "agent", "an empty slug falls back");
assert_eq!(
slugify_name(&"x".repeat(60)).len(),
40,
"capped at 40 chars"
);
}
#[test]
fn random_uuids_are_distinct_and_well_formed() {
let uuid = random_uuid();
assert_eq!(uuid.len(), 36);
assert_ne!(uuid, random_uuid());
}
}