]> Untitled Git - lemmy.git/blob - crates/apub/src/fetcher/community.rs
Rewrite fetcher (#1792)
[lemmy.git] / crates / apub / src / fetcher / community.rs
1 use crate::{
2   activities::community::announce::AnnounceActivity,
3   fetcher::{fetch::fetch_remote_object, object_id::ObjectId},
4   objects::community::Group,
5 };
6 use activitystreams::collection::{CollectionExt, OrderedCollection};
7 use anyhow::Context;
8 use lemmy_api_common::blocking;
9 use lemmy_apub_lib::ActivityHandler;
10 use lemmy_db_queries::Joinable;
11 use lemmy_db_schema::source::{
12   community::{Community, CommunityModerator, CommunityModeratorForm},
13   person::Person,
14 };
15 use lemmy_db_views_actor::community_moderator_view::CommunityModeratorView;
16 use lemmy_utils::{location_info, LemmyError};
17 use lemmy_websocket::LemmyContext;
18 use url::Url;
19
20 pub(crate) async fn update_community_mods(
21   group: &Group,
22   community: &Community,
23   context: &LemmyContext,
24   request_counter: &mut i32,
25 ) -> Result<(), LemmyError> {
26   let new_moderators = fetch_community_mods(context, group, request_counter).await?;
27   let community_id = community.id;
28   let current_moderators = blocking(context.pool(), move |conn| {
29     CommunityModeratorView::for_community(conn, community_id)
30   })
31   .await??;
32   // Remove old mods from database which arent in the moderators collection anymore
33   for mod_user in &current_moderators {
34     if !new_moderators.contains(&mod_user.moderator.actor_id.clone().into()) {
35       let community_moderator_form = CommunityModeratorForm {
36         community_id: mod_user.community.id,
37         person_id: mod_user.moderator.id,
38       };
39       blocking(context.pool(), move |conn| {
40         CommunityModerator::leave(conn, &community_moderator_form)
41       })
42       .await??;
43     }
44   }
45
46   // Add new mods to database which have been added to moderators collection
47   for mod_id in new_moderators {
48     let mod_id = ObjectId::new(mod_id);
49     let mod_user: Person = mod_id.dereference(context, request_counter).await?;
50
51     if !current_moderators
52       .clone()
53       .iter()
54       .map(|c| c.moderator.actor_id.clone())
55       .any(|x| x == mod_user.actor_id)
56     {
57       let community_moderator_form = CommunityModeratorForm {
58         community_id: community.id,
59         person_id: mod_user.id,
60       };
61       blocking(context.pool(), move |conn| {
62         CommunityModerator::join(conn, &community_moderator_form)
63       })
64       .await??;
65     }
66   }
67
68   Ok(())
69 }
70
71 pub(crate) async fn fetch_community_outbox(
72   context: &LemmyContext,
73   outbox: &Url,
74   recursion_counter: &mut i32,
75 ) -> Result<(), LemmyError> {
76   let outbox =
77     fetch_remote_object::<OrderedCollection>(context.client(), outbox, recursion_counter).await?;
78   let outbox_activities = outbox.items().context(location_info!())?.clone();
79   let mut outbox_activities = outbox_activities.many().context(location_info!())?;
80   if outbox_activities.len() > 20 {
81     outbox_activities = outbox_activities[0..20].to_vec();
82   }
83
84   for announce in outbox_activities {
85     // TODO: instead of converting like this, we should create a struct CommunityOutbox with
86     //       AnnounceActivity as inner type, but that gives me stackoverflow
87     let ser = serde_json::to_string(&announce)?;
88     let announce: AnnounceActivity = serde_json::from_str(&ser)?;
89     announce.receive(context, recursion_counter).await?;
90   }
91
92   Ok(())
93 }
94
95 async fn fetch_community_mods(
96   context: &LemmyContext,
97   group: &Group,
98   recursion_counter: &mut i32,
99 ) -> Result<Vec<Url>, LemmyError> {
100   if let Some(mods_url) = &group.moderators {
101     let mods =
102       fetch_remote_object::<OrderedCollection>(context.client(), mods_url, recursion_counter)
103         .await?;
104     let mods = mods
105       .items()
106       .map(|i| i.as_many())
107       .flatten()
108       .context(location_info!())?
109       .iter()
110       .filter_map(|i| i.as_xsd_any_uri())
111       .map(|u| u.to_owned())
112       .collect();
113     Ok(mods)
114   } else {
115     Ok(vec![])
116   }
117 }