From 7e403c00af4956a3996e5570eb0aa578745c520d Mon Sep 17 00:00:00 2001 From: Vika Date: Tue, 20 Aug 2024 18:41:40 +0300 Subject: Send posts made in the post composer --- src/micropub.rs | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/micropub.rs (limited to 'src/micropub.rs') diff --git a/src/micropub.rs b/src/micropub.rs new file mode 100644 index 0000000..e855459 --- /dev/null +++ b/src/micropub.rs @@ -0,0 +1,81 @@ +use soup::prelude::*; +pub use kittybox_util::micropub::{Error as MicropubError, Config, QueryType}; + +#[derive(Debug)] +pub struct Client { + micropub: String, + access_token: String, + + //http: soup::Session, +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("glib error: {0}")] + Glib(#[from] glib::Error), + #[error("json serialization error: {0}")] + Json(#[from] serde_json::Error), + #[error("micropub error: {0}")] + Micropub(#[from] MicropubError), + #[error("micropub server did not return a location: header")] + NoLocationHeader +} + +impl Client { + pub fn new(uri: glib::Uri, token: String) -> Self { + Self { + micropub: uri.to_string(), + access_token: token, + + //http: soup::Session::new() + } + } + + pub async fn config(&self) -> Result { + let uri = glib::Uri::parse(&self.micropub, glib::UriFlags::NONE).unwrap(); + let uri = super::util::append_query( + &uri, [("q".to_string(), "config".to_string())] + ); + + let exch = soup::Message::from_uri("GET", &uri); + let headers = exch.request_headers().expect("SoupMessage with no headers"); + // TODO: create a SoupAuth subclass that allows pasting in a token + headers.append("Authorization", &format!("Bearer {}", self.access_token)); + + let http = soup::Session::new(); + let body = http.send_and_read_future(&exch, glib::Priority::DEFAULT).await?; + + Ok(serde_json::from_slice(&body)?) + } + + pub async fn send_post(&self, post: microformats::types::Item) -> Result { + let uri = glib::Uri::parse(&self.micropub, glib::UriFlags::NONE).unwrap(); + let exch = soup::Message::from_uri("POST", &uri); + let headers = exch.request_headers().expect("SoupMessage with no headers"); + headers.append("Authorization", &format!("Bearer {}", self.access_token)); + + exch.set_request_body_from_bytes(Some("application/json"), + Some(&glib::Bytes::from_owned(serde_json::to_vec(&post).unwrap())) + ); + + let http = soup::Session::new(); + let body = http.send_and_read_future(&exch, glib::Priority::DEFAULT).await?; + + match exch.status() { + soup::Status::Created | soup::Status::Accepted => { + let response_headers = exch.response_headers().expect("Successful SoupMessage with no response headers"); + let location = response_headers.one("Location").ok_or(Error::NoLocationHeader)?; + + Ok(glib::Uri::parse(&location, glib::UriFlags::NONE)?) + }, + soup::Status::InternalServerError | soup::Status::BadGateway | soup::Status::ServiceUnavailable => { + todo!("micropub server is down") + }, + _ => { + let error = serde_json::from_slice::(&body)?; + + Err(error.into()) + } + } + } +} -- cgit 1.4.1