//! ActivityPub implementation code and related abstractions. use futures::prelude::*; use serde::Serialize; use crate::{ Id, Activity, err, Result, Error, sign, ctx::Context }; #[derive(Clone, Serialize)] pub enum Create { Note { object: Note } } impl From for Activity { fn from (a: Create) -> Activity { Activity::Create (a) } } #[derive(Clone, Serialize)] pub enum Follow { Actor { object: Actor } } impl From for Activity { fn from (a: Follow) -> Activity { Activity::Follow (a) } } #[derive(Clone, Serialize)] pub enum Accept { Follow { object: Follow } } impl From for Activity { fn from (a: Accept) -> Activity { Activity::Accept (a) } } /// An entity that publishes activities. #[derive(Clone, Serialize, sqlx::FromRow)] pub struct Actor { id: Id, } #[derive(Clone, Serialize)] pub struct Note { id: Id, } impl Activity { /// Deliver the activity to all its targets through the ActivityPub /// delivery mechanism. pub async fn deliver (self, signer: &S) -> Result<()> where S: sign::Sign + ?Sized, { // Create a shared client #efficiency let client = reqwest::Client::new(); // the function that does the delivery to a target. It creates // a request with the proper headers and signs it using the // `signer`. let do_delivery = |url| async { let req = { let mut r = client.get(url).build()?; signer.sign(&mut r)?; r }; client .execute(req) .map_err(err) .await }; // Collect only the errors, since we don't need to do anything // with a successful delivery. let errors = self .delivery_targets() .await? .into_iter() .map(do_delivery) .collect::>() .filter_map(|r: Result<_>| async { r.err().map(err) }) .collect::>() .await; for err in errors { // Failure to deliver is not a fatal error per se, // so we log and move on. println!("Failed to deliver activity: {:?}", err); } Ok (()) } /// Get all delivery targets as urls. async fn delivery_targets (&self) -> Result> { todo!() } /// Perform the activity. pub async fn perform (self, ctx: &mut Context) -> Result<()> where S: sign::Sign { todo!() } }