]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/report.rs
aaa1e5108140bbe1a3df89d1a678bc9e14239241
[lemmy.git] / crates / apub / src / activities / community / report.rs
1 use crate::{
2   activities::{generate_activity_id, send_lemmy_activity, verify_person_in_community},
3   insert_activity,
4   objects::{community::ApubCommunity, person::ApubPerson},
5   protocol::{activities::community::report::Report, InCommunity},
6   PostOrComment,
7   SendActivity,
8 };
9 use activitypub_federation::{
10   config::Data,
11   fetch::object_id::ObjectId,
12   kinds::activity::FlagType,
13   traits::{ActivityHandler, Actor},
14 };
15 use lemmy_api_common::{
16   comment::{CommentReportResponse, CreateCommentReport},
17   context::LemmyContext,
18   post::{CreatePostReport, PostReportResponse},
19   utils::local_user_view_from_jwt,
20   websocket::UserOperation,
21 };
22 use lemmy_db_schema::{
23   source::{
24     comment_report::{CommentReport, CommentReportForm},
25     post_report::{PostReport, PostReportForm},
26   },
27   traits::Reportable,
28 };
29 use lemmy_db_views::structs::{CommentReportView, PostReportView};
30 use lemmy_utils::error::LemmyError;
31 use url::Url;
32
33 #[async_trait::async_trait]
34 impl SendActivity for CreatePostReport {
35   type Response = PostReportResponse;
36
37   async fn send_activity(
38     request: &Self,
39     response: &Self::Response,
40     context: &Data<LemmyContext>,
41   ) -> Result<(), LemmyError> {
42     let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
43     Report::send(
44       ObjectId::from(response.post_report_view.post.ap_id.clone()),
45       &local_user_view.person.into(),
46       ObjectId::from(response.post_report_view.community.actor_id.clone()),
47       request.reason.to_string(),
48       context,
49     )
50     .await
51   }
52 }
53
54 #[async_trait::async_trait]
55 impl SendActivity for CreateCommentReport {
56   type Response = CommentReportResponse;
57
58   async fn send_activity(
59     request: &Self,
60     response: &Self::Response,
61     context: &Data<LemmyContext>,
62   ) -> Result<(), LemmyError> {
63     let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
64     Report::send(
65       ObjectId::from(response.comment_report_view.comment.ap_id.clone()),
66       &local_user_view.person.into(),
67       ObjectId::from(response.comment_report_view.community.actor_id.clone()),
68       request.reason.to_string(),
69       context,
70     )
71     .await
72   }
73 }
74
75 impl Report {
76   #[tracing::instrument(skip_all)]
77   async fn send(
78     object_id: ObjectId<PostOrComment>,
79     actor: &ApubPerson,
80     community_id: ObjectId<ApubCommunity>,
81     reason: String,
82     context: &Data<LemmyContext>,
83   ) -> Result<(), LemmyError> {
84     let community = community_id.dereference_local(context).await?;
85     let kind = FlagType::Flag;
86     let id = generate_activity_id(
87       kind.clone(),
88       &context.settings().get_protocol_and_hostname(),
89     )?;
90     let report = Report {
91       actor: actor.id().into(),
92       to: [community.id().into()],
93       object: object_id,
94       summary: reason,
95       kind,
96       id: id.clone(),
97       audience: Some(community.id().into()),
98     };
99
100     let inbox = vec![community.shared_inbox_or_inbox()];
101     send_lemmy_activity(context, report, actor, inbox, false).await
102   }
103 }
104
105 #[async_trait::async_trait]
106 impl ActivityHandler for Report {
107   type DataType = LemmyContext;
108   type Error = LemmyError;
109
110   fn id(&self) -> &Url {
111     &self.id
112   }
113
114   fn actor(&self) -> &Url {
115     self.actor.inner()
116   }
117
118   #[tracing::instrument(skip_all)]
119   async fn verify(&self, context: &Data<Self::DataType>) -> Result<(), LemmyError> {
120     let community = self.community(context).await?;
121     verify_person_in_community(&self.actor, &community, context).await?;
122     Ok(())
123   }
124
125   #[tracing::instrument(skip_all)]
126   async fn receive(self, context: &Data<Self::DataType>) -> Result<(), LemmyError> {
127     insert_activity(&self.id, &self, false, true, context).await?;
128     let actor = self.actor.dereference(context).await?;
129     match self.object.dereference(context).await? {
130       PostOrComment::Post(post) => {
131         let report_form = PostReportForm {
132           creator_id: actor.id,
133           post_id: post.id,
134           original_post_name: post.name.clone(),
135           original_post_url: post.url.clone(),
136           reason: self.summary,
137           original_post_body: post.body.clone(),
138         };
139
140         let report = PostReport::report(context.pool(), &report_form).await?;
141
142         let post_report_view = PostReportView::read(context.pool(), report.id, actor.id).await?;
143
144         context.send_mod_ws_message(
145           &UserOperation::CreateCommentReport,
146           &PostReportResponse { post_report_view },
147           post.community_id,
148           None,
149         )?;
150       }
151       PostOrComment::Comment(comment) => {
152         let report_form = CommentReportForm {
153           creator_id: actor.id,
154           comment_id: comment.id,
155           original_comment_text: comment.content.clone(),
156           reason: self.summary,
157         };
158
159         let report = CommentReport::report(context.pool(), &report_form).await?;
160
161         let comment_report_view =
162           CommentReportView::read(context.pool(), report.id, actor.id).await?;
163         let community_id = comment_report_view.community.id;
164
165         context.send_mod_ws_message(
166           &UserOperation::CreateCommentReport,
167           &CommentReportResponse {
168             comment_report_view,
169           },
170           community_id,
171           None,
172         )?;
173       }
174     };
175     Ok(())
176   }
177 }