mastodon_api\methods/
media.rs1use crate::MastodonClient;
2use crate::error::Result;
3use crate::models::MediaAttachment;
4use reqwest::multipart;
5use tokio::fs::File;
6use tokio_util::codec::{BytesCodec, FramedRead};
7
8pub struct MediaHandler<'a> {
10 client: &'a MastodonClient,
11}
12
13impl<'a> MediaHandler<'a> {
14 pub fn new(client: &'a MastodonClient) -> Self {
22 Self { client }
23 }
24
25 pub async fn upload(
36 &self,
37 file_path: &str,
38 description: Option<String>,
39 ) -> Result<MediaAttachment> {
40 let path = std::path::Path::new(file_path);
41 let file_name = path
42 .file_name()
43 .and_then(|n| n.to_str())
44 .unwrap_or("file.png")
45 .to_string();
46
47 let file = File::open(file_path)
48 .await
49 .map_err(|e| crate::error::MastodonError::Custom(e.to_string()))?;
50 let stream = FramedRead::new(file, BytesCodec::new());
51 let body = reqwest::Body::wrap_stream(stream);
52
53 let part = multipart::Part::stream(body).file_name(file_name);
54 let mut form = multipart::Form::new().part("file", part);
55
56 if let Some(desc) = description {
57 form = form.text("description", desc);
58 }
59
60 let url = format!("{}/api/v1/media", self.client.base_url());
61 let req = self.client.http_client().post(&url).multipart(form);
62 self.client.send(req).await
63 }
64}