use megalodon::{ entities::{self, StatusVisibility}, error, generator, megalodon::PostStatusInputOptions, }; use std::env; #[tokio::main] async fn main() { tracing_subscriber::fmt::init(); let Ok(url) = env::var("MASTODON_URL") else { println!("Specify MASTODON_URL!!"); return; }; let Ok(token) = env::var("MASTODON_ACCESS_TOKEN") else { println!("Specify MASTODON_ACCESS_TOKEN!!"); return; }; let client = generator(megalodon::SNS::Mastodon, url, Some(token), None).unwrap(); let file_path = "./sample.jpg".to_string(); let Ok(res) = upload_media(&client, file_path.to_string()).await else { println!("failed to upload media"); return; }; let media_1: entities::Attachment; match res { entities::UploadMedia::AsyncAttachment(m) => { match wait_until_uploaded(&client, &m.id).await { Ok(res) => media_1 = res, Err(err) => { println!("{:#?}", err); return; } } } entities::UploadMedia::Attachment(m) => { media_1 = m; } } let media_id_1 = media_1.id; let file_path = "./sample2.jpg".to_string(); let Ok(res) = upload_media(&client, file_path).await else { println!("error"); return; }; let media_2: entities::Attachment; match res { entities::UploadMedia::AsyncAttachment(m) => { match wait_until_uploaded(&client, &m.id).await { Ok(res) => media_2 = res, Err(err) => { println!("{:#?}", err); return; } } } entities::UploadMedia::Attachment(m) => { media_2 = m; } } let media_id_2 = media_2.id; let media_ids = vec![media_id_1, media_id_2]; match post_status(&client, "Post with attached media", Some(media_ids)).await { Ok(res) => { println!("{:#?}", res); } Err(err) => { println!("{:#?}", err); } } } async fn wait_until_uploaded( client: &Box, id: &str, ) -> Result { loop { let res = client.get_media(id.to_string()).await; return match res { Ok(res) => Ok(res.json()), Err(err) => match err { error::Error::OwnError(ref own_err) => match own_err.kind { error::Kind::HTTPPartialContentError => continue, _ => Err(err), }, _ => Err(err), }, }; } } async fn upload_media( client: &Box, file_path: String, ) -> Result { let res = client.upload_media(file_path, None).await?; Ok(res.json()) } async fn post_status( client: &Box, status: &str, media_id: Option>, ) -> Result { let res = client .post_status( status.to_string(), Some(&PostStatusInputOptions { media_ids: media_id, sensitive: Some(true), visibility: Some(StatusVisibility::Unlisted), language: Some("en".to_string()), ..Default::default() }), ) .await?; Ok(res.json()) }