use std::sync::Arc;
use crate::error::Error;
use crate::http::HttpClient;
use crate::types::{
sort_order_to_string, topic_sort_by_to_string, DeletionResponse, ListResponse,
ResourceResponse, Topic, TopicCreateRequest, TopicListParams, TopicUpdateRequest,
TopicVisibility,
};
#[derive(Clone, Debug)]
pub struct TopicsResource {
http: Arc<HttpClient>,
}
impl TopicsResource {
pub(crate) fn new(http: Arc<HttpClient>) -> Self {
Self { http }
}
pub async fn list(&self, params: TopicListParams) -> Result<ListResponse<Topic>, Error> {
self.http
.get("/api/topics", Some(topic_query(params)))
.await
}
pub async fn create(&self, input: TopicCreateRequest) -> Result<Topic, Error> {
let response: ResourceResponse<Topic> = self.http.post("/api/topics", &input).await?;
Ok(response.data)
}
pub async fn get(&self, id: impl AsRef<str>) -> Result<Topic, Error> {
let response: ResourceResponse<Topic> = self
.http
.get(&format!("/api/topics/{}", encode(id.as_ref())), None)
.await?;
Ok(response.data)
}
pub async fn update(
&self,
id: impl AsRef<str>,
input: TopicUpdateRequest,
) -> Result<Topic, Error> {
let response: ResourceResponse<Topic> = self
.http
.patch(&format!("/api/topics/{}", encode(id.as_ref())), &input)
.await?;
Ok(response.data)
}
pub async fn delete(&self, id: impl AsRef<str>) -> Result<DeletionResponse, Error> {
self.http
.delete(&format!("/api/topics/{}", encode(id.as_ref())))
.await
}
}
fn topic_query(params: TopicListParams) -> Vec<(&'static str, String)> {
let mut query = Vec::new();
if let Some(value) = params.page {
query.push(("page", value.to_string()));
}
if let Some(value) = params.limit {
query.push(("limit", value.to_string()));
}
if let Some(value) = params.search {
query.push(("search", value));
}
if let Some(value) = params.active {
query.push(("active", value.to_string()));
}
if let Some(value) = params.visibility {
query.push(("visibility", topic_visibility_to_string(&value).to_string()));
}
if let Some(value) = params.sort_by {
query.push(("sort_by", topic_sort_by_to_string(&value).to_string()));
}
if let Some(value) = params.sort_order {
query.push(("sort_order", sort_order_to_string(&value).to_string()));
}
query
}
fn topic_visibility_to_string(value: &TopicVisibility) -> &'static str {
match value {
TopicVisibility::Public => "public",
TopicVisibility::Private => "private",
}
}
fn encode(value: &str) -> String {
url::form_urlencoded::byte_serialize(value.as_bytes()).collect()
}