use std::{convert::Infallible, error::Error}; use elefren::{ helpers::{cli, toml}, scopes::Scopes, status_builder::Visibility, Language, Mastodon, MastodonClient, Registration, StatusBuilder, }; const FEDIVERSE_TOML_PATH: &str = "fediverse.toml"; pub trait Publisher { type Error; fn publish(&self, content: String) -> Result<(), Self::Error>; } pub struct FediversePublisher { client: Mastodon, } pub struct ConsolePublisher; impl Publisher for ConsolePublisher { type Error = Infallible; fn publish(&self, content: String) -> Result<(), Self::Error> { println!("Publishing content to stdout: {}", content); Ok(()) } } impl ConsolePublisher { pub fn new() -> ConsolePublisher { ConsolePublisher {} } } impl FediversePublisher { pub fn new(fedi_url: String) -> Result> { Ok(Self { client: toml::from_file(FEDIVERSE_TOML_PATH) .map(|data| Ok(Mastodon::from(data))) .unwrap_or_else(|_| register(fedi_url))?, }) } } impl Publisher for FediversePublisher { type Error = Box; fn publish(&self, content: String) -> Result<(), Self::Error> { let status = StatusBuilder::new() .status(&content) // .visibility(Visibility::Direct) .visibility(Visibility::Public) .sensitive(false) .language(Language::Eng) .build() .map_err(|e| Box::new(e) as Box)?; println!("Posting status [{}] to fediverse", &content); self.client .new_status(status) .map_err(|e| Box::new(e) as Box)?; Ok(()) } } fn register(fedi_url: String) -> Result> { let registration = Registration::new(fedi_url) .client_name("izzilis") .scopes(Scopes::write_all()) .build()?; let fediverse = cli::authenticate(registration)?; // Save app data for using on the next run. toml::to_file(&*fediverse, FEDIVERSE_TOML_PATH.to_string())?; Ok(fediverse) }