|
|
|
use std::fmt;
|
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use tokio::io::AsyncRead;
|
|
|
|
use std::pin::Pin;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
/// A builder pattern struct for preparing a single attachment for upload.
|
|
|
|
///
|
|
|
|
/// For more details, see [`new_media()`](struct.Mastodon.html#method.new_media).
|
|
|
|
pub struct MediaBuilder {
|
|
|
|
/// The media attachment itself
|
|
|
|
pub data: MediaBuilderData,
|
|
|
|
|
|
|
|
/// The filename to send to the server
|
|
|
|
pub filename: Option<String>,
|
|
|
|
|
|
|
|
/// Mimetype to send to the server, identifying what is in the attachment.
|
|
|
|
///
|
|
|
|
/// The string should be a valid mimetype.
|
|
|
|
pub mimetype: Option<String>,
|
|
|
|
|
|
|
|
/// Plain text description of the attached piece of media, for accessibility
|
|
|
|
pub description: Option<String>,
|
|
|
|
|
|
|
|
/// (x, y) focus point, used by clients to determine how to crop an image
|
|
|
|
pub focus: Option<(f64, f64)>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Enum representing possible sources of attachments to upload
|
|
|
|
pub enum MediaBuilderData {
|
|
|
|
/// An arbitrary reader. It is useful for reading from media already in memory.
|
|
|
|
Reader(Pin<Box<dyn AsyncRead + Send + Sync>>),
|
|
|
|
|
|
|
|
/// Variant represening a file path of the file to attach.
|
|
|
|
File(PathBuf),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for MediaBuilderData {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
MediaBuilderData::File(f) => fmt.debug_tuple("File").field(&f).finish(),
|
|
|
|
MediaBuilderData::Reader(_) => fmt.debug_tuple("Reader").field(&format_args!("...")).finish(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MediaBuilder {
|
|
|
|
/// Create a new MediaBuilder from a reader `data`
|
|
|
|
pub fn from_reader<R: AsyncRead + Send + Sync + 'static>(data: R) -> MediaBuilder {
|
|
|
|
MediaBuilder {
|
|
|
|
data: MediaBuilderData::Reader(Box::pin(data)),
|
|
|
|
filename: None,
|
|
|
|
mimetype: None,
|
|
|
|
description: None,
|
|
|
|
focus: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create a new MediaBuilder from a file under `path`
|
|
|
|
///
|
|
|
|
/// This function will not check whether the file exists or if it can be read. If the path is
|
|
|
|
/// not valid, [`add_media()`](trait.MastodonClient.html#method.add_media) will return an error when called with the `MediaBuilder`.
|
|
|
|
pub fn from_file(path: impl AsRef<Path>) -> MediaBuilder {
|
|
|
|
let pb = path.as_ref().to_owned();
|
|
|
|
let filename = pb.file_name().expect("file name").to_string_lossy().to_string();
|
|
|
|
let mimetype = match pb.extension().map(|s| s.to_str()).flatten() {
|
|
|
|
Some("jpg") | Some("jpeg") => Some("image/jpeg".to_string()),
|
|
|
|
Some("png") => Some("image/png".to_string()),
|
|
|
|
Some("gif") => Some("image/gif".to_string()),
|
|
|
|
Some("txt") => Some("text/plain".to_string()),
|
|
|
|
// ...
|
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
|
|
|
|
MediaBuilder {
|
|
|
|
data: MediaBuilderData::File(pb),
|
|
|
|
filename: Some(filename),
|
|
|
|
mimetype,
|
|
|
|
description: None,
|
|
|
|
focus: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set filename
|
|
|
|
pub fn filename(&mut self, filename: impl ToString) {
|
|
|
|
self.filename = Some(filename.to_string());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set custom mime type
|
|
|
|
pub fn mimetype(&mut self, mimetype: impl ToString) {
|
|
|
|
self.mimetype = Some(mimetype.to_string());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set an alt text description for the attachment.
|
|
|
|
pub fn description(&mut self, description: impl ToString) {
|
|
|
|
self.description = Some(description.to_string());
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set a focus point for an image attachment.
|
|
|
|
pub fn focus(&mut self, f1: f64, f2: f64) {
|
|
|
|
self.focus = Some((f1, f2));
|
|
|
|
}
|
|
|
|
}
|