use crate::{
activitypub::{Activity, Actor},
ingest::Ingest,
repo::{Dereference, Repo},
session::Session,
};
use std::{rc::Rc, sync::Arc};
use url::Url;
pub type Out<D> = <D as Dereference>::Output;
#[async_trait::async_trait(?Send)]
pub trait ActivityExt: Activity {
type ActorId: Dereference + From<Url>;
type ObjectId: Dereference + From<Url>;
fn actor(&self) -> Option<Out<Self::ActorId>>;
fn object(&self) -> Option<Out<Self::ObjectId>>;
async fn dereference_actor<I: Ingest<Out<Self::ActorId>>, R: Repo, S: Session>(
&self,
actor_id: I::ActorId,
ingest: I,
remote_repo: R,
session: S,
) -> Result<Option<Out<Self::ActorId>>, I::Error>
where
I::Error: From<R::Error>,
I::ActorId: From<Url> + 'static,
{
dereference::<Self::ActorId, I, R, S>(
actor_id,
ingest,
remote_repo,
session,
self.actor(),
self.actor_id(),
)
.await
}
async fn dereference_object<I: Ingest<Out<Self::ObjectId>>, R: Repo, S: Session>(
&self,
actor_id: I::ActorId,
ingest: I,
remote_repo: R,
session: S,
) -> Result<Option<Out<Self::ObjectId>>, I::Error>
where
I::Error: From<R::Error>,
I::ActorId: From<Url> + 'static,
{
dereference::<Self::ObjectId, I, R, S>(
actor_id,
ingest,
remote_repo,
session,
self.object(),
self.object_id(),
)
.await
}
}
#[async_trait::async_trait(?Send)]
pub trait ActorExt: Actor {
type PublicKeyId: Dereference + From<Url>;
fn public_key(&self) -> Option<Out<Self::PublicKeyId>>;
async fn dereference_public_key<I: Ingest<Out<Self::PublicKeyId>>, R: Repo, S: Session>(
&self,
actor_id: I::ActorId,
ingest: I,
remote_repo: R,
session: S,
) -> Result<Option<Out<Self::PublicKeyId>>, I::Error>
where
I::Error: From<R::Error>,
I::ActorId: From<Url> + 'static,
{
dereference::<Self::PublicKeyId, I, R, S>(
actor_id,
ingest,
remote_repo,
session,
self.public_key(),
self.public_key_id(),
)
.await
}
}
pub async fn dereference<D: Dereference + From<Url>, I: Ingest<Out<D>>, R: Repo, S: Session>(
actor_id: I::ActorId,
ingest: I,
remote_repo: R,
session: S,
output: Option<D::Output>,
id: &Url,
) -> Result<Option<D::Output>, I::Error>
where
I::ActorId: From<Url> + 'static,
I::Error: From<R::Error>,
{
if let Some(item) = output {
return Ok(Some(item));
}
ingest
.fetch(D::from(id.clone()), actor_id, remote_repo, session)
.await
}
impl<'a, T> ActivityExt for &'a T
where
T: ActivityExt,
{
type ActorId = T::ActorId;
type ObjectId = T::ObjectId;
fn actor(&self) -> Option<<Self::ActorId as Dereference>::Output> {
T::actor(self)
}
fn object(&self) -> Option<<Self::ObjectId as Dereference>::Output> {
T::object(self)
}
}
impl<'a, T> ActivityExt for &'a mut T
where
T: ActivityExt,
{
type ActorId = T::ActorId;
type ObjectId = T::ObjectId;
fn actor(&self) -> Option<<Self::ActorId as Dereference>::Output> {
T::actor(self)
}
fn object(&self) -> Option<<Self::ObjectId as Dereference>::Output> {
T::object(self)
}
}
impl<T> ActivityExt for Box<T>
where
T: ActivityExt,
{
type ActorId = T::ActorId;
type ObjectId = T::ObjectId;
fn actor(&self) -> Option<<Self::ActorId as Dereference>::Output> {
T::actor(self)
}
fn object(&self) -> Option<<Self::ObjectId as Dereference>::Output> {
T::object(self)
}
}
impl<T> ActivityExt for Rc<T>
where
T: ActivityExt,
{
type ActorId = T::ActorId;
type ObjectId = T::ObjectId;
fn actor(&self) -> Option<<Self::ActorId as Dereference>::Output> {
T::actor(self)
}
fn object(&self) -> Option<<Self::ObjectId as Dereference>::Output> {
T::object(self)
}
}
impl<T> ActivityExt for Arc<T>
where
T: ActivityExt,
{
type ActorId = T::ActorId;
type ObjectId = T::ObjectId;
fn actor(&self) -> Option<<Self::ActorId as Dereference>::Output> {
T::actor(self)
}
fn object(&self) -> Option<<Self::ObjectId as Dereference>::Output> {
T::object(self)
}
}