use futures_util::stream::{self, BoxStream};
use futures_util::{Stream, StreamExt as _};
use reqwest::Method;
use serde::Serialize;
use crate::client::{CallOptions, Client};
use crate::error::{Error, Result};
use crate::pagination::{auto_page, paginate, static_page, ListParams, Page};
use crate::resources::escape;
use crate::resources::session_utils::resolve_active_session_id;
use crate::resources::sessions::{participants_fetcher, Participant};
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
struct RemoveWire<'a> {
room_id: &'a str,
participant_id: &'a str,
}
#[derive(Debug, Clone, Copy)]
pub struct ParticipantsResource<'a> {
client: &'a Client,
}
impl<'a> ParticipantsResource<'a> {
pub(crate) fn new(client: &'a Client) -> Self {
Self { client }
}
pub async fn list(&self, room_id: &str, params: ListParams) -> Result<Page<Participant>> {
let Some(session_id) = resolve_active_session_id(self.client, room_id).await? else {
return Ok(static_page(Vec::new()));
};
let path = format!("/v2/sessions/{}/participants/active", escape(&session_id));
paginate(
participants_fetcher(self.client, path),
¶ms,
"data",
None,
)
.await
}
pub fn list_stream(
&self,
room_id: &str,
params: ListParams,
) -> impl Stream<Item = Result<Participant>> + Send {
let client = self.client.clone();
let room_id = room_id.to_string();
stream::once(async move {
let inner: BoxStream<'static, Result<Participant>> =
match resolve_active_session_id(&client, &room_id).await {
Ok(Some(session_id)) => {
let path =
format!("/v2/sessions/{}/participants/active", escape(&session_id));
auto_page(participants_fetcher(&client, path), params, "data", None).boxed()
}
Ok(None) => stream::empty().boxed(),
Err(err) => stream::once(async move { Err(err) }).boxed(),
};
inner
})
.flatten()
}
pub async fn get(&self, room_id: &str, participant_id: &str) -> Result<Participant> {
let Some(session_id) = resolve_active_session_id(self.client, room_id).await? else {
return Err(Error::not_found(format!(
"no active session for room {room_id}"
)));
};
let path = format!(
"/v2/sessions/{}/participants/{}",
escape(&session_id),
escape(participant_id)
);
self.client
.json(Method::GET, &path, CallOptions::new())
.await
}
pub async fn remove(&self, room_id: &str, participant_id: &str) -> Result<String> {
let body = RemoveWire {
room_id,
participant_id,
};
self.client
.message(
Method::POST,
"/v2/sessions/participants/remove",
CallOptions::json(&body)?,
)
.await
}
}