Add client method to wait for attachment processing

This commit is contained in:
D. Scott Boggs 2023-01-25 06:59:43 -05:00 committed by Scott Boggs
parent 184dd32146
commit b6fd884387
5 changed files with 91 additions and 2 deletions

View File

@ -44,6 +44,7 @@ futures-util = "0.3.25"
static_assertions = "1.1.0" static_assertions = "1.1.0"
percent-encoding = "2.2.0" percent-encoding = "2.2.0"
thiserror = "1.0.38" thiserror = "1.0.38"
derive_deref = "1.1.1"
[dependencies.parse_link_header] [dependencies.parse_link_header]
version = "0.3.3" version = "0.3.3"

View File

@ -26,6 +26,7 @@ pub struct Attachment {
/// Noop will be removed. /// Noop will be removed.
pub description: Option<String>, pub description: Option<String>,
} }
/// Wrapper type for a attachment ID string /// Wrapper type for a attachment ID string
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(transparent)] #[serde(transparent)]
@ -99,3 +100,26 @@ pub enum MediaType {
#[serde(rename = "unknown")] #[serde(rename = "unknown")]
Unknown, Unknown,
} }
/// A media attachment which has been processed and has a URL.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
pub struct ProcessedAttachment {
/// ID of the attachment.
pub id: AttachmentId,
/// The media type of an attachment.
#[serde(rename = "type")]
pub media_type: MediaType,
/// URL of the locally hosted version of the image.
pub url: String,
/// For remote images, the remote URL of the original image.
pub remote_url: Option<String>,
/// URL of the preview image.
pub preview_url: String,
/// Shorter URL for the image, for insertion into text
/// (only present on local images)
pub text_url: Option<String>,
/// Meta information about the attachment.
pub meta: Option<Meta>,
/// Noop will be removed.
pub description: Option<String>,
}

View File

@ -123,6 +123,8 @@ pub mod scopes;
pub mod status_builder; pub mod status_builder;
#[macro_use] #[macro_use]
mod macros; mod macros;
/// How much time to wait before checking an endpoint again.
pub mod polling_time;
/// Automatically import the things you need /// Automatically import the things you need
pub mod prelude { pub mod prelude {
pub use crate::{ pub use crate::{

View File

@ -11,11 +11,14 @@ use crate::{
errors::{Error, Result}, errors::{Error, Result},
event_stream::event_stream, event_stream::event_stream,
helpers::read_response::read_response, helpers::read_response::read_response,
log_serde, AddFilterRequest, AddPushRequest, Data, NewStatus, Page, StatusesRequest, log_serde,
UpdateCredsRequest, UpdatePushRequest, polling_time::PollingTime,
AddFilterRequest, AddPushRequest, Data, NewStatus, Page, StatusesRequest, UpdateCredsRequest,
UpdatePushRequest,
}; };
use futures::TryStream; use futures::TryStream;
use log::{as_debug, as_serde, debug, error, trace}; use log::{as_debug, as_serde, debug, error, trace};
use mastodon_async_entities::attachment::ProcessedAttachment;
use reqwest::{multipart::Part, Client, RequestBuilder}; use reqwest::{multipart::Part, Client, RequestBuilder};
use url::Url; use url::Url;
use uuid::Uuid; use uuid::Uuid;
@ -119,6 +122,7 @@ impl Mastodon {
(delete) delete_from_suggestions[AccountId]: "suggestions/{}" => Empty, (delete) delete_from_suggestions[AccountId]: "suggestions/{}" => Empty,
(post) endorse_user[AccountId]: "accounts/{}/pin" => Relationship, (post) endorse_user[AccountId]: "accounts/{}/pin" => Relationship,
(post) unendorse_user[AccountId]: "accounts/{}/unpin" => Relationship, (post) unendorse_user[AccountId]: "accounts/{}/unpin" => Relationship,
(get) attachment[AttachmentId]: "media/{}" => Attachment,
} }
streaming! { streaming! {
@ -326,6 +330,46 @@ impl Mastodon {
self.following(&me.id).await self.following(&me.id).await
} }
/// Wait for the media to be done processing and return it with the URL.
///
/// `Default::default()` may be passed as the polling time to select a
/// polling time of 500ms.
///
/// ## Example
/// ```rust,no_run
/// use mastodon_async::prelude::*;
/// let mastodon = Mastodon::from(Data::default());
/// tokio_test::block_on(async {
/// let attachment = mastodon.media("/path/to/some/file.jpg", None).await.expect("upload");
/// let attachment = mastodon.wait_for_processing(attachment, Default::default()).await.expect("processing");
/// println!("{}", attachment.url);
/// });
/// ```
pub async fn wait_for_processing(
&self,
mut attachment: Attachment,
polling_time: PollingTime,
) -> Result<ProcessedAttachment> {
let id = attachment.id;
loop {
if let Some(url) = attachment.url {
return Ok(ProcessedAttachment {
id,
media_type: attachment.media_type,
url,
remote_url: attachment.remote_url,
preview_url: attachment.preview_url,
text_url: attachment.text_url,
meta: attachment.meta,
description: attachment.description,
});
} else {
attachment = self.attachment(&id).await?;
tokio::time::sleep(*polling_time).await;
}
}
}
/// Set the bearer authentication token /// Set the bearer authentication token
fn authenticated(&self, request: RequestBuilder) -> RequestBuilder { fn authenticated(&self, request: RequestBuilder) -> RequestBuilder {
request.bearer_auth(&self.data.token) request.bearer_auth(&self.data.token)

18
src/polling_time.rs Normal file
View File

@ -0,0 +1,18 @@
use derive_deref::Deref;
use std::time::Duration;
/// How long to wait before checking an endpoint again.
#[derive(Debug, Deref, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct PollingTime(Duration);
impl Default for PollingTime {
fn default() -> Self {
Self(Duration::from_millis(500))
}
}
impl From<Duration> for PollingTime {
fn from(value: Duration) -> Self {
Self(value)
}
}