hermit/src/ap/mod.rs

100 lines
2.4 KiB
Rust

//! 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<Create> for Activity { fn from (a: Create) -> Activity { Activity::Create (a) } }
#[derive(Clone, Serialize)]
pub enum Follow {
Actor { object: Actor }
}
impl From<Follow> for Activity { fn from (a: Follow) -> Activity { Activity::Follow (a) } }
#[derive(Clone, Serialize)]
pub enum Accept {
Follow { object: Follow }
}
impl From<Accept> 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 <S> (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::<stream::FuturesUnordered<_>>()
.filter_map(|r: Result<_>| async {
r.err().map(err)
})
.collect::<Vec<Error>>()
.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<Vec<reqwest::Url>> {
todo!()
}
/// Perform the activity.
pub async fn perform <S> (self, ctx: &mut Context<S>) -> Result<()> where S: sign::Sign {
todo!()
}
}