teamtalk 6.0.0

TeamTalk SDK for Rust
Documentation
use crate::events::Event;
use crate::types::{Subscriptions, User, UserId};
use std::path::{Path, PathBuf};

pub(super) fn synced_audio_subscription_mask() -> Subscriptions {
    Subscriptions::all_audio()
}

pub(super) fn is_synced_bus_event(event: Event) -> bool {
    matches!(
        event,
        Event::UserJoined
            | Event::UserLeft
            | Event::AudioBlock
            | Event::ConnectSuccess
            | Event::ConnectionLost
            | Event::ConnectFailed
            | Event::ConnectCryptError
    )
}

pub(super) fn should_warn_missing_audio_subscriptions(
    subscribe_audio: bool,
    user: Option<&User>,
) -> bool {
    if subscribe_audio {
        return false;
    }
    let Some(current_user) = user else {
        return false;
    };
    !current_user.local_subscriptions.has(Subscriptions::VOICE)
        && !current_user
            .local_subscriptions
            .has(Subscriptions::MEDIAFILE)
}

pub(super) fn render_vars(template: &str, user_id: UserId, username: &str) -> String {
    template
        .replace("%user_id%", &user_id.0.to_string())
        .replace("%username%", username)
}

pub(super) fn sanitized_filename(raw: String) -> String {
    const FORBIDDEN: [char; 9] = ['<', '>', ':', '"', '/', '\\', '|', '?', '*'];
    let mut sanitized = String::with_capacity(raw.len());
    for ch in raw.chars() {
        let replacement = if ch.is_control() || FORBIDDEN.contains(&ch) {
            '_'
        } else {
            ch
        };
        sanitized.push(replacement);
    }
    let trimmed = sanitized.trim_matches([' ', '.']);
    if trimmed.is_empty() {
        "user".to_string()
    } else {
        trimmed.to_string()
    }
}

pub(super) fn unique_recording_path(path: &Path) -> PathBuf {
    if !path.exists() {
        return path.to_path_buf();
    }

    let stem = path
        .file_stem()
        .and_then(|v| v.to_str())
        .unwrap_or("recording");
    let ext = path.extension().and_then(|v| v.to_str());
    for idx in 1.. {
        let filename = match ext {
            Some(ext) if !ext.is_empty() => format!("{stem}-{idx}.{ext}"),
            _ => format!("{stem}-{idx}"),
        };
        let candidate = path.with_file_name(filename);
        if !candidate.exists() {
            return candidate;
        }
    }

    path.to_path_buf()
}