2 activities::send::generate_activity_id,
3 activity_queue::{send_activity_single_dest, send_to_community, send_to_community_followers},
4 check_is_apub_id_valid,
5 extensions::context::lemmy_context,
6 fetcher::user::get_or_fetch_and_upsert_user,
7 generate_moderators_url,
10 use activitystreams::{
12 kind::{AcceptType, AddType, AnnounceType, DeleteType, LikeType, RemoveType, UndoType},
23 base::{AnyBase, BaseExt, ExtendsExt},
28 use itertools::Itertools;
29 use lemmy_api_structs::blocking;
30 use lemmy_db_queries::DbPool;
31 use lemmy_db_schema::source::{community::Community, user::User_};
32 use lemmy_db_views_actor::community_follower_view::CommunityFollowerView;
33 use lemmy_utils::{location_info, LemmyError};
34 use lemmy_websocket::LemmyContext;
37 #[async_trait::async_trait(?Send)]
38 impl ActorType for Community {
39 fn is_local(&self) -> bool {
42 fn actor_id(&self) -> Url {
43 self.actor_id.to_owned().into_inner()
45 fn public_key(&self) -> Option<String> {
46 self.public_key.to_owned()
48 fn private_key(&self) -> Option<String> {
49 self.private_key.to_owned()
52 fn get_shared_inbox_or_inbox_url(&self) -> Url {
56 .unwrap_or_else(|| self.inbox_url.to_owned())
62 _follow_actor_id: &Url,
63 _context: &LemmyContext,
64 ) -> Result<(), LemmyError> {
68 async fn send_unfollow(
70 _follow_actor_id: &Url,
71 _context: &LemmyContext,
72 ) -> Result<(), LemmyError> {
76 /// As a local community, accept the follow request from a remote user.
77 async fn send_accept_follow(
80 context: &LemmyContext,
81 ) -> Result<(), LemmyError> {
82 let actor_uri = follow
84 .as_single_xsd_any_uri()
85 .context(location_info!())?;
86 let user = get_or_fetch_and_upsert_user(actor_uri, context, &mut 0).await?;
88 let mut accept = Accept::new(
89 self.actor_id.to_owned().into_inner(),
90 follow.into_any_base()?,
93 .set_many_contexts(lemmy_context()?)
94 .set_id(generate_activity_id(AcceptType::Accept)?)
95 .set_to(user.actor_id());
97 send_activity_single_dest(accept, self, user.inbox_url.into(), context).await?;
101 /// If the creator of a community deletes the community, send this to all followers.
102 async fn send_delete(&self, context: &LemmyContext) -> Result<(), LemmyError> {
103 let mut delete = Delete::new(self.actor_id(), self.actor_id());
105 .set_many_contexts(lemmy_context()?)
106 .set_id(generate_activity_id(DeleteType::Delete)?)
108 .set_many_ccs(vec![self.followers_url.clone().into_inner()]);
110 send_to_community_followers(delete, self, context).await?;
114 /// If the creator of a community reverts the deletion of a community, send this to all followers.
115 async fn send_undo_delete(&self, context: &LemmyContext) -> Result<(), LemmyError> {
116 let mut delete = Delete::new(self.actor_id(), self.actor_id());
118 .set_many_contexts(lemmy_context()?)
119 .set_id(generate_activity_id(DeleteType::Delete)?)
121 .set_many_ccs(vec![self.followers_url.clone().into_inner()]);
123 let mut undo = Undo::new(self.actor_id(), delete.into_any_base()?);
125 .set_many_contexts(lemmy_context()?)
126 .set_id(generate_activity_id(UndoType::Undo)?)
128 .set_many_ccs(vec![self.followers_url.clone().into_inner()]);
130 send_to_community_followers(undo, self, context).await?;
134 /// If an admin removes a community, send this to all followers.
135 async fn send_remove(&self, context: &LemmyContext) -> Result<(), LemmyError> {
136 let mut remove = Remove::new(self.actor_id(), self.actor_id());
138 .set_many_contexts(lemmy_context()?)
139 .set_id(generate_activity_id(RemoveType::Remove)?)
141 .set_many_ccs(vec![self.followers_url.clone().into_inner()]);
143 send_to_community_followers(remove, self, context).await?;
147 /// If an admin reverts the removal of a community, send this to all followers.
148 async fn send_undo_remove(&self, context: &LemmyContext) -> Result<(), LemmyError> {
149 let mut remove = Remove::new(self.actor_id(), self.actor_id());
151 .set_many_contexts(lemmy_context()?)
152 .set_id(generate_activity_id(RemoveType::Remove)?)
154 .set_many_ccs(vec![self.followers_url.clone().into_inner()]);
156 // Undo that fake activity
157 let mut undo = Undo::new(self.actor_id(), remove.into_any_base()?);
159 .set_many_contexts(lemmy_context()?)
160 .set_id(generate_activity_id(LikeType::Like)?)
162 .set_many_ccs(vec![self.followers_url.clone().into_inner()]);
164 send_to_community_followers(undo, self, context).await?;
168 /// Wraps an activity sent to the community in an announce, and then sends the announce to all
169 /// community followers.
170 async fn send_announce(
173 context: &LemmyContext,
174 ) -> Result<(), LemmyError> {
175 let mut announce = Announce::new(self.actor_id.to_owned().into_inner(), activity);
177 .set_many_contexts(lemmy_context()?)
178 .set_id(generate_activity_id(AnnounceType::Announce)?)
180 .set_many_ccs(vec![self.followers_url.clone().into_inner()]);
182 send_to_community_followers(announce, self, context).await?;
187 /// For a given community, returns the inboxes of all followers.
188 async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<Url>, LemmyError> {
191 let follows = blocking(pool, move |conn| {
192 CommunityFollowerView::for_community(conn, id)
195 let inboxes = follows
197 .filter(|f| !f.follower.local)
198 .map(|f| f.follower.shared_inbox_url.unwrap_or(f.follower.inbox_url))
199 .map(|i| i.into_inner())
201 // Don't send to blocked instances
202 .filter(|inbox| check_is_apub_id_valid(inbox).is_ok())
209 pub async fn send_add_mod(
212 community: Community,
213 context: &LemmyContext,
214 ) -> Result<(), LemmyError> {
215 let mut add = Add::new(
216 actor.actor_id.clone().into_inner(),
217 added_mod.actor_id.into_inner(),
220 .set_many_contexts(lemmy_context()?)
221 .set_id(generate_activity_id(AddType::Add)?)
222 .set_many_tos(vec![community.actor_id.to_owned().into_inner(), public()])
223 .set_target(generate_moderators_url(&community.actor_id)?.into_inner());
227 .send_announce(add.into_any_base()?, context)
230 send_to_community(add, &actor, &community, context).await?;
235 pub async fn send_remove_mod(
238 community: Community,
239 context: &LemmyContext,
240 ) -> Result<(), LemmyError> {
241 let mut remove = Remove::new(
242 actor.actor_id.clone().into_inner(),
243 removed_mod.actor_id.into_inner(),
246 .set_many_contexts(lemmy_context()?)
247 .set_id(generate_activity_id(RemoveType::Remove)?)
248 .set_many_tos(vec![community.actor_id.to_owned().into_inner(), public()])
249 .set_target(generate_moderators_url(&community.actor_id)?.into_inner());
253 .send_announce(remove.into_any_base()?, context)
256 send_to_community(remove, &actor, &community, context).await?;