use reqwest::{Client, Url}; use thiserror::Error; use tracing::{event, instrument, Level}; #[derive(Debug, Error)] pub enum Error { #[error("invalid URL")] InvalidUrl(#[from] url::ParseError), #[error("invalid response")] InvalidResponse(reqwest::Error), #[error("network request failed")] Network(reqwest::Error), } /// Handler for the IT-Syndikat API. #[derive(Clone, Debug)] pub struct ItsApi { base_url: Url, spaceping_token: String, client: Client, } impl ItsApi { /// Constructs a new IT-Syndikat API handler. #[instrument] pub fn new(base_url: Url, spaceping_token: String) -> Self { Self { base_url, spaceping_token, client: Client::new(), } } /// Request the SpaceAPI status. /// /// # Errors /// /// This function returns an error if the network request fails, or if the /// returned data can not be parsed as a valid SpaceAPI response. #[instrument] pub async fn status(&self) -> Result { event!(Level::DEBUG, "requesting spaceapi status"); let status = self .client .get(self.base_url.join("status.php")?) .send() .await .map_err(Error::Network)? .json() .await .map_err(Error::InvalidResponse)?; event!(Level::DEBUG, ?status); Ok(status) } /// Makes the box in the space beep. /// /// # Errors /// /// This function returns an error if the network request fails. #[instrument] pub async fn ping(&self) -> Result<(), Error> { event!(Level::INFO, "sending spaceping"); self.client .post(self.base_url.join("ping.php")?) .query(&[("apikey", &self.spaceping_token)]) .send() .await .map_err(Error::Network)? .error_for_status() .map_err(Error::InvalidResponse)?; Ok(()) } }