summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKlaus Purer <klaus.purer@protonmail.ch>2020-07-11 13:19:45 +0200
committerPaul Woolcock <paul@woolcock.us>2020-09-25 12:10:41 -0400
commit44da726d08ff20a67ae8f3845b0008269e1a2076 (patch)
treed70c83450d71b51f6a15d9a552cc3d5d2d6c013e
parent4afb3c3d7405c496857415920afd04d2db01c987 (diff)
feat(media): Add support for media alt text
-rw-r--r--src/lib.rs36
-rw-r--r--src/macros.rs35
-rw-r--r--src/mastodon_client.rs3
-rw-r--r--src/media_builder.rs70
4 files changed, 107 insertions, 37 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 4345abf..4504f8b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -122,6 +122,7 @@ pub use crate::data::Data;
pub use crate::errors::{ApiError, Error, Result};
pub use isolang::Language;
pub use crate::mastodon_client::{MastodonClient, MastodonUnauthenticated};
+pub use crate::media_builder::MediaBuilder;
pub use crate::registration::Registration;
pub use crate::requests::{
AddFilterRequest,
@@ -145,6 +146,8 @@ pub mod helpers;
/// Contains trait for converting `reqwest::Request`s to `reqwest::Response`s
pub mod http_send;
mod mastodon_client;
+/// Constructing media attachments for a status.
+pub mod media_builder;
/// Handling multiple pages of entities.
pub mod page;
/// Registering your app.
@@ -239,7 +242,6 @@ impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
(post (id: &str,)) reject_follow_request: "accounts/follow_requests/reject" => Empty,
(get (q: &'a str, resolve: bool,)) search: "search" => SearchResult,
(post (uri: Cow<'static, str>,)) follows: "follows" => Account,
- (post multipart (file: Cow<'static, str>,)) media: "media" => Attachment,
(post) clear_notifications: "notifications/clear" => Empty,
(post (id: &str,)) dismiss_notification: "notifications/dismiss" => Empty,
(get) get_push_subscription: "push/subscription" => Subscription,
@@ -627,6 +629,38 @@ impl<H: HttpSend> MastodonClient<H> for Mastodon<H> {
Ok(EventReader(WebSocket(client)))
}
+
+ /// Equivalent to /api/v1/media
+ fn media(&self, media_builder: MediaBuilder) -> Result<Attachment> {
+ use reqwest::multipart::Form;
+
+ let mut form_data = Form::new().file("file", media_builder.file.as_ref())?;
+
+ if let Some(description) = media_builder.description {
+ form_data = form_data.text("description", description);
+ }
+
+ if let Some(focus) = media_builder.focus {
+ let string = format!("{},{}", focus.0, focus.1);
+ form_data = form_data.text("focus", string);
+ }
+
+ let response = self.send(
+ self.client
+ .post(&self.route("/api/v1/media"))
+ .multipart(form_data),
+ )?;
+
+ let status = response.status().clone();
+
+ if status.is_client_error() {
+ return Err(Error::Client(status));
+ } else if status.is_server_error() {
+ return Err(Error::Server(status));
+ }
+
+ deserialise(response)
+ }
}
#[derive(Debug)]
diff --git a/src/macros.rs b/src/macros.rs
index 0f9f1a2..8ee6623 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -144,41 +144,6 @@ macro_rules! route_v2 {
macro_rules! route {
- ((post multipart ($($param:ident: $typ:ty,)*)) $name:ident: $url:expr => $ret:ty, $($rest:tt)*) => {
- doc_comment! {
- concat!(
- "Equivalent to `post /api/v1/",
- $url,
- "`\n# Errors\nIf `access_token` is not set."),
- fn $name(&self, $($param: $typ,)*) -> Result<$ret> {
- use reqwest::multipart::Form;
-
- let form_data = Form::new()
- $(
- .file(stringify!($param), $param.as_ref())?
- )*;
-
- let response = self.send(
- self.client
- .post(&self.route(concat!("/api/v1/", $url)))
- .multipart(form_data)
- )?;
-
- let status = response.status().clone();
-
- if status.is_client_error() {
- return Err(Error::Client(status));
- } else if status.is_server_error() {
- return Err(Error::Server(status));
- }
-
- deserialise(response)
- }
- }
-
- route!{$($rest)*}
- };
-
((get ($($param:ident: $typ:ty,)*)) $name:ident: $url:expr => $ret:ty, $($rest:tt)*) => {
doc_comment! {
concat!(
diff --git a/src/mastodon_client.rs b/src/mastodon_client.rs
index f65eda7..98d2cc3 100644
--- a/src/mastodon_client.rs
+++ b/src/mastodon_client.rs
@@ -3,6 +3,7 @@ use std::borrow::Cow;
use crate::entities::prelude::*;
use crate::errors::Result;
use crate::http_send::{HttpSend, HttpSender};
+use crate::media_builder::MediaBuilder;
use crate::page::Page;
use crate::requests::{
AddFilterRequest,
@@ -113,7 +114,7 @@ pub trait MastodonClient<H: HttpSend = HttpSender> {
unimplemented!("This method was not implemented");
}
/// POST /api/v1/media
- fn media(&self, file: Cow<'static, str>) -> Result<Attachment> {
+ fn media(&self, media_builder: MediaBuilder) -> Result<Attachment> {
unimplemented!("This method was not implemented");
}
/// POST /api/v1/notifications/clear
diff --git a/src/media_builder.rs b/src/media_builder.rs
new file mode 100644
index 0000000..5cd7639
--- /dev/null
+++ b/src/media_builder.rs
@@ -0,0 +1,70 @@
+use std::borrow::Cow;
+
+/// A builder pattern struct for constructing a media attachment.
+#[derive(Debug, Default, Clone, Serialize)]
+pub struct MediaBuilder {
+ /// The file name of the attachment to be uploaded.
+ pub file: Cow<'static, str>,
+ /// The alt text of the attachment.
+ pub description: Option<Cow<'static, str>>,
+ /// The focus point for images.
+ pub focus: Option<(f32, f32)>,
+}
+
+impl MediaBuilder {
+ /// Create a new attachment from a file name.
+ pub fn new(file: Cow<'static, str>) -> Self {
+ MediaBuilder {
+ file,
+ description: None,
+ focus: None,
+ }
+ }
+ /// Set an alt text description for the attachment.
+ pub fn description(mut self, description: Cow<'static, str>) -> Self {
+ self.description = Some(description);
+ self
+ }
+
+ /// Set a focus point for an image attachment.
+ pub fn focus(mut self, f1: f32, f2: f32) -> Self {
+ self.focus = Some((f1, f2));
+ self
+ }
+}
+
+// Convenience helper so that the mastodon.media() method can be called with a
+// file name only (owned string).
+impl From<String> for MediaBuilder {
+ fn from(file: String) -> MediaBuilder {
+ MediaBuilder {
+ file: file.into(),
+ description: None,
+ focus: None,
+ }
+ }
+}
+
+// Convenience helper so that the mastodon.media() method can be called with a
+// file name only (borrowed string).
+impl From<&'static str> for MediaBuilder {
+ fn from(file: &'static str) -> MediaBuilder {
+ MediaBuilder {
+ file: file.into(),
+ description: None,
+ focus: None,
+ }
+ }
+}
+
+// Convenience helper so that the mastodon.media() method can be called with a
+// file name only (Cow string).
+impl From<Cow<'static, str>> for MediaBuilder {
+ fn from(file: Cow<'static, str>) -> MediaBuilder {
+ MediaBuilder {
+ file,
+ description: None,
+ focus: None,
+ }
+ }
+}