]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/update.rs
964a423889d727d1faa077f945e0ad111f18dc9b
[lemmy.git] / crates / apub / src / activities / community / update.rs
1 use crate::{
2   activities::{
3     community::send_websocket_message,
4     verify_activity,
5     verify_mod_action,
6     verify_person_in_community,
7   },
8   objects::community::Group,
9 };
10 use activitystreams::activity::kind::UpdateType;
11 use lemmy_api_common::blocking;
12 use lemmy_apub_lib::{values::PublicUrl, ActivityCommonFields, ActivityHandler};
13 use lemmy_db_queries::{ApubObject, Crud};
14 use lemmy_db_schema::source::community::{Community, CommunityForm};
15 use lemmy_utils::LemmyError;
16 use lemmy_websocket::{LemmyContext, UserOperationCrud};
17 use url::Url;
18
19 /// This activity is received from a remote community mod, and updates the description or other
20 /// fields of a local community.
21 #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
22 #[serde(rename_all = "camelCase")]
23 pub struct UpdateCommunity {
24   to: PublicUrl,
25   object: Group,
26   cc: [Url; 1],
27   #[serde(rename = "type")]
28   kind: UpdateType,
29   #[serde(flatten)]
30   common: ActivityCommonFields,
31 }
32
33 #[async_trait::async_trait(?Send)]
34 impl ActivityHandler for UpdateCommunity {
35   async fn verify(
36     &self,
37     context: &LemmyContext,
38     request_counter: &mut i32,
39   ) -> Result<(), LemmyError> {
40     verify_activity(self.common())?;
41     verify_person_in_community(&self.common.actor, &self.cc[0], context, request_counter).await?;
42     verify_mod_action(&self.common.actor, self.cc[0].clone(), context).await?;
43     Ok(())
44   }
45
46   async fn receive(
47     self,
48     context: &LemmyContext,
49     _request_counter: &mut i32,
50   ) -> Result<(), LemmyError> {
51     let cc = self.cc[0].clone().into();
52     let community = blocking(context.pool(), move |conn| {
53       Community::read_from_apub_id(conn, &cc)
54     })
55     .await??;
56
57     let updated_community =
58       Group::from_apub_to_form(&self.object, &community.actor_id.clone().into()).await?;
59     let cf = CommunityForm {
60       name: updated_community.name,
61       title: updated_community.title,
62       description: updated_community.description,
63       nsfw: updated_community.nsfw,
64       // TODO: icon and banner would be hosted on the other instance, ideally we would copy it to ours
65       icon: updated_community.icon,
66       banner: updated_community.banner,
67       ..CommunityForm::default()
68     };
69     let updated_community = blocking(context.pool(), move |conn| {
70       Community::update(conn, community.id, &cf)
71     })
72     .await??;
73
74     send_websocket_message(
75       updated_community.id,
76       UserOperationCrud::EditCommunity,
77       context,
78     )
79     .await
80   }
81
82   fn common(&self) -> &ActivityCommonFields {
83     &self.common
84   }
85 }