2 activities::send::generate_activity_id,
3 activity_queue::{send_activity_single_dest, send_to_community_followers},
4 check_is_apub_id_valid,
5 fetcher::get_or_fetch_and_upsert_user,
10 kind::{AcceptType, AnnounceType, DeleteType, LikeType, RemoveType, UndoType},
19 base::{AnyBase, BaseExt, ExtendsExt},
24 use itertools::Itertools;
25 use lemmy_db::{community::Community, community_view::CommunityFollowerView, DbPool};
26 use lemmy_structs::blocking;
27 use lemmy_utils::{location_info, settings::Settings, LemmyError};
28 use lemmy_websocket::LemmyContext;
31 #[async_trait::async_trait(?Send)]
32 impl ActorType for Community {
33 fn actor_id_str(&self) -> String {
34 self.actor_id.to_owned()
37 fn public_key(&self) -> Option<String> {
38 self.public_key.to_owned()
40 fn private_key(&self) -> Option<String> {
41 self.private_key.to_owned()
44 fn user_id(&self) -> i32 {
50 _follow_actor_id: &Url,
51 _context: &LemmyContext,
52 ) -> Result<(), LemmyError> {
56 async fn send_unfollow(
58 _follow_actor_id: &Url,
59 _context: &LemmyContext,
60 ) -> Result<(), LemmyError> {
64 /// As a local community, accept the follow request from a remote user.
65 async fn send_accept_follow(
68 context: &LemmyContext,
69 ) -> Result<(), LemmyError> {
70 let actor_uri = follow
72 .as_single_xsd_any_uri()
73 .context(location_info!())?;
74 let user = get_or_fetch_and_upsert_user(actor_uri, context, &mut 0).await?;
76 let mut accept = Accept::new(self.actor_id.to_owned(), follow.into_any_base()?);
78 .set_context(activitystreams::context())
79 .set_id(generate_activity_id(AcceptType::Accept)?)
80 .set_to(user.actor_id()?);
82 send_activity_single_dest(accept, self, user.get_inbox_url()?, context).await?;
86 /// If the creator of a community deletes the community, send this to all followers.
87 async fn send_delete(&self, context: &LemmyContext) -> Result<(), LemmyError> {
88 let mut delete = Delete::new(self.actor_id()?, self.actor_id()?);
90 .set_context(activitystreams::context())
91 .set_id(generate_activity_id(DeleteType::Delete)?)
93 .set_many_ccs(vec![self.get_followers_url()?]);
95 send_to_community_followers(delete, self, context).await?;
99 /// If the creator of a community reverts the deletion of a community, send this to all followers.
100 async fn send_undo_delete(&self, context: &LemmyContext) -> Result<(), LemmyError> {
101 let mut delete = Delete::new(self.actor_id()?, self.actor_id()?);
103 .set_context(activitystreams::context())
104 .set_id(generate_activity_id(DeleteType::Delete)?)
106 .set_many_ccs(vec![self.get_followers_url()?]);
108 let mut undo = Undo::new(self.actor_id()?, delete.into_any_base()?);
110 .set_context(activitystreams::context())
111 .set_id(generate_activity_id(UndoType::Undo)?)
113 .set_many_ccs(vec![self.get_followers_url()?]);
115 send_to_community_followers(undo, self, context).await?;
119 /// If an admin removes a community, send this to all followers.
120 async fn send_remove(&self, context: &LemmyContext) -> Result<(), LemmyError> {
121 let mut remove = Remove::new(self.actor_id()?, self.actor_id()?);
123 .set_context(activitystreams::context())
124 .set_id(generate_activity_id(RemoveType::Remove)?)
126 .set_many_ccs(vec![self.get_followers_url()?]);
128 send_to_community_followers(remove, self, context).await?;
132 /// If an admin reverts the removal of a community, send this to all followers.
133 async fn send_undo_remove(&self, context: &LemmyContext) -> Result<(), LemmyError> {
134 let mut remove = Remove::new(self.actor_id()?, self.actor_id()?);
136 .set_context(activitystreams::context())
137 .set_id(generate_activity_id(RemoveType::Remove)?)
139 .set_many_ccs(vec![self.get_followers_url()?]);
141 // Undo that fake activity
142 let mut undo = Undo::new(self.actor_id()?, remove.into_any_base()?);
144 .set_context(activitystreams::context())
145 .set_id(generate_activity_id(LikeType::Like)?)
147 .set_many_ccs(vec![self.get_followers_url()?]);
149 send_to_community_followers(undo, self, context).await?;
153 /// Wraps an activity sent to the community in an announce, and then sends the announce to all
154 /// community followers.
155 async fn send_announce(
158 context: &LemmyContext,
159 ) -> Result<(), LemmyError> {
160 let mut announce = Announce::new(self.actor_id.to_owned(), activity);
162 .set_context(activitystreams::context())
163 .set_id(generate_activity_id(AnnounceType::Announce)?)
165 .set_many_ccs(vec![self.get_followers_url()?]);
167 send_to_community_followers(announce, self, context).await?;
172 /// For a given community, returns the inboxes of all followers.
174 /// TODO: this function is very badly implemented, we should just store shared_inbox_url in
175 /// CommunityFollowerView
176 async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<Url>, LemmyError> {
179 let inboxes = blocking(pool, move |conn| {
180 CommunityFollowerView::for_community(conn, id)
183 let inboxes = inboxes
185 .filter(|i| !i.user_local)
186 .map(|u| -> Result<Url, LemmyError> {
187 let url = Url::parse(&u.user_actor_id)?;
188 let domain = url.domain().context(location_info!())?;
189 let port = if let Some(port) = url.port() {
194 Ok(Url::parse(&format!(
196 Settings::get().get_protocol_string(),
201 .filter_map(Result::ok)
202 // Don't send to blocked instances
203 .filter(|inbox| check_is_apub_id_valid(inbox).is_ok())