use crate::{Result, streaming}; use crate::entities::card::Card; use crate::entities::context::Context; use crate::entities::status::Status; use crate::helpers::deserialise_response; use crate::streaming::EventReader; /// Client that can make unauthenticated calls to a mastodon instance #[derive(Clone, Debug)] pub struct FediClient { http_client: reqwest::Client, base: url::Url, } impl FediClient { /// Create a new unauthenticated client pub fn new(base: &str) -> Result { let base = if base.starts_with("https://") { base.to_string() } else { format!("https://{}", base) }; Ok(FediClient { http_client: reqwest::Client::new(), base: url::Url::parse(&base)?, }) } } impl FediClient { /// # Low-level API for extending /// Create a route with the given path fragment pub fn route(&self, url: &str) -> Result { Ok(self.base.join(url)?) } /// # Low-level API for extending /// Send a request pub async fn send(&self, req: reqwest::RequestBuilder) -> Result { let req = req.build()?; Ok(self.http_client.execute(req).await?) } // TODO verify if this really works without auth /// Get a stream of the public timeline pub async fn streaming_public(&self) -> Result { let mut url: url::Url = self.route("/api/v1/streaming")?; { let mut qpm = url.query_pairs_mut(); qpm.append_pair("stream", "public"); } streaming::do_open_streaming(url.as_str()).await } /// Get a stream of the local timeline pub async fn streaming_local(&self) -> Result { let mut url: url::Url = self.route("/api/v1/streaming/public")?; { let mut qpm = url.query_pairs_mut(); qpm.append_pair("stream", "public:local"); } streaming::do_open_streaming(url.as_str()).await } /// GET /api/v1/statuses/:id pub async fn get_status(&self, id: &str) -> Result { let route = self.route("/api/v1/statuses")?; let route = route.join(id)?; let response = self.send(self.http_client.get(route)).await?; deserialise_response(response).await } /// GET /api/v1/statuses/:id/context pub async fn get_context(&self, id: &str) -> Result { let route = self.route("/api/v1/statuses")?; let route = route.join(id)?; let route = route.join("context")?; let response = self.send(self.http_client.get(route)).await?; deserialise_response(response).await } /// GET /api/v1/statuses/:id/card pub async fn get_card(&self, id: &str) -> Result { let route = self.route("/api/v1/statuses")?; let route = route.join(id)?; let route = route.join("card")?; let response = self.send(self.http_client.get(route)).await?; deserialise_response(response).await } }