use megalodon::{generator, streaming::Message}; use std::env; use scraper::{Html,Selector}; use megalodon::entities::Status; use megalodon::entities::notification::NotificationType; #[tokio::main] async fn main() { env_logger::init(); let url = env::var("MASTODON_STREAMING_URL").unwrap_or_else(|_| { String::from("https://mamot.fr/") }); let Ok(token) = env::var("MASTODON_ACCESS_TOKEN") else { println!("Specify MASTODON_ACCESS_TOKEN!!"); return }; let client = megalodon::generator( megalodon::SNS::Mastodon, url.clone(), Some(token.clone()), None, ); let res = client.verify_account_credentials().await.unwrap(); println!("Creds: {:#?}", res.json()); let res = client.get_instance().await.unwrap(); //println!("Instance: {:#?}", res.json()); let mut res2 = client.get_home_timeline(None).await.unwrap().json(); res2.reverse(); for status in &res2 { print_status(status); } let url_ws = res.json().urls.unwrap().streaming_api; streaming(url_ws.as_str(), token).await; } fn print_status(status: &Status) { let now = chrono::offset::Utc::now(); let date_diff = duration_to_string(&(now - status.created_at)); if let Some(retoot) = &status.reblog { println!("From: {}, {date_diff} ago [retoot by: {}]", retoot.account.acct, status.account.acct); print_content(&retoot.content); } else { println!("From: {}, {date_diff} ago", status.account.acct); print_content(&status.content); } println!(); } fn duration_to_string(d: &chrono::Duration) -> String { match d.num_seconds() { s if s < 60 => format!("{} secs.", s), s if s < 60*60 => format!("{} mins.", s/60), s if s < 60*60*24 => format!("{} hours.", s/(60*60)), s => format!("{}days", s/(60*60*24)) } } fn print_content(content: &str) { let fragment = Html::parse_fragment(content); let sel = Selector::parse("p").unwrap(); if let Some(p) = fragment.select(&sel).next() { let text = p.text().collect::>(); let text2 = text.join(" "); println!("Content: {}", text2); } else { println!("Content: {:?}", content); } } async fn streaming(url: &str, access_token: String) { let client = generator( megalodon::SNS::Mastodon, url.to_string(), Some(access_token), None, ); let streaming = client.user_streaming(url.to_string()); streaming .listen(Box::new(|message| match message { Message::Update(status) => print_status(&status), Message::Notification(mes) => { let from = mes.account.map(| u | u.acct) .unwrap_or_else(|| String::from("(unknown)")); match mes.r#type { NotificationType::Favourite => { println!("*** {from} favorited one of your toots."); }, NotificationType::Reblog => { println!("*** {from} boosted one of your toots."); }, NotificationType::Follow => { println!("*** {from} follows you."); }, NotificationType::FollowRequest => { println!("*** {from} sent you a follow request."); }, _ => { println!("Notification: {:?}", mes.r#type); } } }, Message::Conversation(mes) => { println!("Conversation: {:#?}", mes); } Message::Delete(mes) => { println!("message is deleted: {}", mes); } Message::StatusUpdate(mes) => { println!("updated: {:#?}", mes) } Message::Heartbeat() => { //println!("heartbeat"); } })) .await; }