use crate::config::MastodonConfig; use chrono::{DateTime, Utc}; use megalodon::{ entities::{Status, StatusVisibility}, generator, mastodon::mastodon::Mastodon, megalodon::AppInputOptions, megalodon::GetHomeTimelineInputOptions, Megalodon, }; use std::error::Error; use std::io::stdin; /// Get Mastodon Object instance pub fn get_mastodon_instance(config: &MastodonConfig) -> Result> { Ok(Mastodon::new( config.base.to_string(), Some(config.token.to_string()), None, )?) } /// Get the edited_at field from the specified toot pub async fn get_status_edited_at(mastodon: &Mastodon, t: u64) -> Option> { mastodon .get_status(t.to_string()) .await .ok() .and_then(|t| t.json.edited_at) } /// Get the home timeline since the last toot pub async fn get_mastodon_timeline_since( mastodon: &Mastodon, id: Option, ) -> Result, Box> { let input_options = GetHomeTimelineInputOptions { only_media: Some(false), limit: None, max_id: None, since_id: id.map(|i| i.to_string()), min_id: None, local: Some(true), }; let mut timeline: Vec = mastodon .get_home_timeline(Some(&input_options)) .await? .json() .iter() .filter(|t| { // this excludes the reply to other users t.in_reply_to_account_id.is_none() || t.in_reply_to_account_id .clone() .is_some_and(|r| r == t.account.id) }) .filter(|t| t.visibility == StatusVisibility::Public) // excludes everything that isn’t // public .filter(|t| t.reblog.is_none()) // excludes reblogs .cloned() .collect(); timeline.reverse(); Ok(timeline) } /// Generic register function /// As this function is supposed to be run only once, it will panic for every error it encounters /// Most of this function is a direct copy/paste of the official `elefren` crate #[tokio::main] pub async fn register(host: &str) { let mastodon = generator(megalodon::SNS::Mastodon, host.to_string(), None, None) .expect("Cannot build Mastodon generator object"); let options = AppInputOptions { redirect_uris: None, scopes: Some(["read:statuses".to_string()].to_vec()), website: Some("https://framagit.org/veretcle/oolatoocs".to_string()), }; let app_data = mastodon .register_app(env!("CARGO_PKG_NAME").to_string(), &options) .await .expect("Cannot build registration object!"); let url = app_data.url.expect("Cannot generate registration URI!"); println!("Click this link to authorize on Mastodon: {url}"); println!("Paste the returned authorization code: "); let mut input = String::new(); stdin() .read_line(&mut input) .expect("Unable to read back registration code!"); let token_data = mastodon .fetch_access_token( app_data.client_id.to_owned(), app_data.client_secret.to_owned(), input.trim().to_string(), megalodon::default::NO_REDIRECT.to_string(), ) .await .expect("Unable to create access token!"); println!( r#"Please insert the following block at the end of your configuration file: [mastodon] base = "{}" client_id = "{}" client_secret = "{}" redirect = "{}" token = "{}""#, host, app_data.client_id, app_data.client_secret, app_data.redirect_uri.as_ref().unwrap(), token_data.access_token, ); }