4 announce::{AnnouncableActivities, GetCommunity},
5 get_community_from_moderators_url,
10 verify_add_remove_moderator_target,
13 verify_person_in_community,
15 context::lemmy_context,
16 fetcher::object_id::ObjectId,
17 generate_moderators_url,
18 objects::{community::ApubCommunity, person::ApubPerson},
20 use activitystreams::{
21 activity::kind::AddType,
23 primitives::OneOrMany,
27 use lemmy_api_common::blocking;
30 traits::{ActivityFields, ActivityHandler, ActorType},
32 use lemmy_db_schema::{
33 source::community::{CommunityModerator, CommunityModeratorForm},
36 use lemmy_utils::LemmyError;
37 use lemmy_websocket::LemmyContext;
38 use serde::{Deserialize, Serialize};
41 #[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
42 #[serde(rename_all = "camelCase")]
44 actor: ObjectId<ApubPerson>,
46 object: ObjectId<ApubPerson>,
49 #[serde(rename = "type")]
52 #[serde(rename = "@context")]
53 context: OneOrMany<AnyBase>,
60 community: &ApubCommunity,
61 added_mod: &ApubPerson,
63 context: &LemmyContext,
64 ) -> Result<(), LemmyError> {
65 let id = generate_activity_id(
67 &context.settings().get_protocol_and_hostname(),
70 actor: ObjectId::new(actor.actor_id()),
72 object: ObjectId::new(added_mod.actor_id()),
73 target: generate_moderators_url(&community.actor_id)?.into(),
74 cc: vec![community.actor_id()],
77 context: lemmy_context(),
78 unparsed: Default::default(),
81 let activity = AnnouncableActivities::AddMod(add);
82 let inboxes = vec![added_mod.shared_inbox_or_inbox_url()];
83 send_to_community(activity, &id, actor, community, inboxes, context).await
87 #[async_trait::async_trait(?Send)]
88 impl ActivityHandler for AddMod {
89 type DataType = LemmyContext;
93 context: &Data<LemmyContext>,
94 request_counter: &mut i32,
95 ) -> Result<(), LemmyError> {
96 verify_is_public(&self.to)?;
97 verify_activity(self, &context.settings())?;
98 let community = self.get_community(context, request_counter).await?;
99 verify_person_in_community(&self.actor, &community, context, request_counter).await?;
100 verify_mod_action(&self.actor, &community, context, request_counter).await?;
101 verify_add_remove_moderator_target(&self.target, &community)?;
107 context: &Data<LemmyContext>,
108 request_counter: &mut i32,
109 ) -> Result<(), LemmyError> {
110 let community = self.get_community(context, request_counter).await?;
111 let new_mod = self.object.dereference(context, request_counter).await?;
113 // If we had to refetch the community while parsing the activity, then the new mod has already
114 // been added. Skip it here as it would result in a duplicate key error.
115 let new_mod_id = new_mod.id;
116 let moderated_communities = blocking(context.pool(), move |conn| {
117 CommunityModerator::get_person_moderated_communities(conn, new_mod_id)
120 if !moderated_communities.contains(&community.id) {
121 let form = CommunityModeratorForm {
122 community_id: community.id,
123 person_id: new_mod.id,
125 blocking(context.pool(), move |conn| {
126 CommunityModerator::join(conn, &form)
130 // TODO: send websocket notification about added mod
135 #[async_trait::async_trait(?Send)]
136 impl GetCommunity for AddMod {
137 async fn get_community(
139 context: &LemmyContext,
140 request_counter: &mut i32,
141 ) -> Result<ApubCommunity, LemmyError> {
142 get_community_from_moderators_url(&self.target, context, request_counter).await