1use crate::{
4 activitypub::{Activity, Actor},
5 ingest::Ingest,
6 repo::{Dereference, Repo},
7 session::Session,
8};
9use std::{rc::Rc, sync::Arc};
10use url::Url;
11
12pub type Out<D> = <D as Dereference>::Output;
14
15#[async_trait::async_trait(?Send)]
17pub trait ActivityExt: Activity {
18 type ActorId: Dereference + From<Url>;
20
21 type ObjectId: Dereference + From<Url>;
23
24 fn actor(&self) -> Option<Out<Self::ActorId>>;
26
27 fn object(&self) -> Option<Out<Self::ObjectId>>;
29
30 async fn dereference_actor<I: Ingest<Out<Self::ActorId>>, R: Repo, S: Session>(
32 &self,
33 actor_id: I::ActorId,
34 ingest: I,
35 remote_repo: R,
36 session: S,
37 ) -> Result<Option<Out<Self::ActorId>>, I::Error>
38 where
39 I::Error: From<R::Error>,
40 I::ActorId: From<Url> + 'static,
41 {
42 dereference::<Self::ActorId, I, R, S>(
43 actor_id,
44 ingest,
45 remote_repo,
46 session,
47 self.actor(),
48 self.actor_id(),
49 )
50 .await
51 }
52
53 async fn dereference_object<I: Ingest<Out<Self::ObjectId>>, R: Repo, S: Session>(
55 &self,
56 actor_id: I::ActorId,
57 ingest: I,
58 remote_repo: R,
59 session: S,
60 ) -> Result<Option<Out<Self::ObjectId>>, I::Error>
61 where
62 I::Error: From<R::Error>,
63 I::ActorId: From<Url> + 'static,
64 {
65 dereference::<Self::ObjectId, I, R, S>(
66 actor_id,
67 ingest,
68 remote_repo,
69 session,
70 self.object(),
71 self.object_id(),
72 )
73 .await
74 }
75}
76
77#[async_trait::async_trait(?Send)]
79pub trait ActorExt: Actor {
80 type PublicKeyId: Dereference + From<Url>;
82
83 fn public_key(&self) -> Option<Out<Self::PublicKeyId>>;
85
86 async fn dereference_public_key<I: Ingest<Out<Self::PublicKeyId>>, R: Repo, S: Session>(
88 &self,
89 actor_id: I::ActorId,
90 ingest: I,
91 remote_repo: R,
92 session: S,
93 ) -> Result<Option<Out<Self::PublicKeyId>>, I::Error>
94 where
95 I::Error: From<R::Error>,
96 I::ActorId: From<Url> + 'static,
97 {
98 dereference::<Self::PublicKeyId, I, R, S>(
99 actor_id,
100 ingest,
101 remote_repo,
102 session,
103 self.public_key(),
104 self.public_key_id(),
105 )
106 .await
107 }
108}
109
110pub async fn dereference<D: Dereference + From<Url>, I: Ingest<Out<D>>, R: Repo, S: Session>(
112 actor_id: I::ActorId,
113 ingest: I,
114 remote_repo: R,
115 session: S,
116 output: Option<D::Output>,
117 id: &Url,
118) -> Result<Option<D::Output>, I::Error>
119where
120 I::ActorId: From<Url> + 'static,
121 I::Error: From<R::Error>,
122{
123 if let Some(item) = output {
124 return Ok(Some(item));
125 }
126
127 ingest
128 .fetch(D::from(id.clone()), actor_id, remote_repo, session)
129 .await
130}
131
132impl<'a, T> ActivityExt for &'a T
133where
134 T: ActivityExt,
135{
136 type ActorId = T::ActorId;
137 type ObjectId = T::ObjectId;
138
139 fn actor(&self) -> Option<<Self::ActorId as Dereference>::Output> {
140 T::actor(self)
141 }
142
143 fn object(&self) -> Option<<Self::ObjectId as Dereference>::Output> {
144 T::object(self)
145 }
146}
147
148impl<'a, T> ActivityExt for &'a mut T
149where
150 T: ActivityExt,
151{
152 type ActorId = T::ActorId;
153 type ObjectId = T::ObjectId;
154
155 fn actor(&self) -> Option<<Self::ActorId as Dereference>::Output> {
156 T::actor(self)
157 }
158
159 fn object(&self) -> Option<<Self::ObjectId as Dereference>::Output> {
160 T::object(self)
161 }
162}
163
164impl<T> ActivityExt for Box<T>
165where
166 T: ActivityExt,
167{
168 type ActorId = T::ActorId;
169 type ObjectId = T::ObjectId;
170
171 fn actor(&self) -> Option<<Self::ActorId as Dereference>::Output> {
172 T::actor(self)
173 }
174
175 fn object(&self) -> Option<<Self::ObjectId as Dereference>::Output> {
176 T::object(self)
177 }
178}
179
180impl<T> ActivityExt for Rc<T>
181where
182 T: ActivityExt,
183{
184 type ActorId = T::ActorId;
185 type ObjectId = T::ObjectId;
186
187 fn actor(&self) -> Option<<Self::ActorId as Dereference>::Output> {
188 T::actor(self)
189 }
190
191 fn object(&self) -> Option<<Self::ObjectId as Dereference>::Output> {
192 T::object(self)
193 }
194}
195
196impl<T> ActivityExt for Arc<T>
197where
198 T: ActivityExt,
199{
200 type ActorId = T::ActorId;
201 type ObjectId = T::ObjectId;
202
203 fn actor(&self) -> Option<<Self::ActorId as Dereference>::Output> {
204 T::actor(self)
205 }
206
207 fn object(&self) -> Option<<Self::ObjectId as Dereference>::Output> {
208 T::object(self)
209 }
210}