]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/report.rs
Making the chat server an actor. (#2793)
[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::get_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 =
43       get_local_user_view_from_jwt(&request.auth, context.pool(), context.secret()).await?;
44     Report::send(
45       ObjectId::from(response.post_report_view.post.ap_id.clone()),
46       &local_user_view.person.into(),
47       ObjectId::from(response.post_report_view.community.actor_id.clone()),
48       request.reason.to_string(),
49       context,
50     )
51     .await
52   }
53 }
54
55 #[async_trait::async_trait]
56 impl SendActivity for CreateCommentReport {
57   type Response = CommentReportResponse;
58
59   async fn send_activity(
60     request: &Self,
61     response: &Self::Response,
62     context: &Data<LemmyContext>,
63   ) -> Result<(), LemmyError> {
64     let local_user_view =
65       get_local_user_view_from_jwt(&request.auth, context.pool(), context.secret()).await?;
66     Report::send(
67       ObjectId::from(response.comment_report_view.comment.ap_id.clone()),
68       &local_user_view.person.into(),
69       ObjectId::from(response.comment_report_view.community.actor_id.clone()),
70       request.reason.to_string(),
71       context,
72     )
73     .await
74   }
75 }
76
77 impl Report {
78   #[tracing::instrument(skip_all)]
79   async fn send(
80     object_id: ObjectId<PostOrComment>,
81     actor: &ApubPerson,
82     community_id: ObjectId<ApubCommunity>,
83     reason: String,
84     context: &Data<LemmyContext>,
85   ) -> Result<(), LemmyError> {
86     let community = community_id.dereference_local(context).await?;
87     let kind = FlagType::Flag;
88     let id = generate_activity_id(
89       kind.clone(),
90       &context.settings().get_protocol_and_hostname(),
91     )?;
92     let report = Report {
93       actor: actor.id().into(),
94       to: [community.id().into()],
95       object: object_id,
96       summary: reason,
97       kind,
98       id: id.clone(),
99       audience: Some(community.id().into()),
100     };
101
102     let inbox = vec![community.shared_inbox_or_inbox()];
103     send_lemmy_activity(context, report, actor, inbox, false).await
104   }
105 }
106
107 #[async_trait::async_trait]
108 impl ActivityHandler for Report {
109   type DataType = LemmyContext;
110   type Error = LemmyError;
111
112   fn id(&self) -> &Url {
113     &self.id
114   }
115
116   fn actor(&self) -> &Url {
117     self.actor.inner()
118   }
119
120   #[tracing::instrument(skip_all)]
121   async fn verify(&self, context: &Data<Self::DataType>) -> Result<(), LemmyError> {
122     let community = self.community(context).await?;
123     verify_person_in_community(&self.actor, &community, context).await?;
124     Ok(())
125   }
126
127   #[tracing::instrument(skip_all)]
128   async fn receive(self, context: &Data<Self::DataType>) -> Result<(), LemmyError> {
129     insert_activity(&self.id, &self, false, true, context).await?;
130     let actor = self.actor.dereference(context).await?;
131     match self.object.dereference(context).await? {
132       PostOrComment::Post(post) => {
133         let report_form = PostReportForm {
134           creator_id: actor.id,
135           post_id: post.id,
136           original_post_name: post.name.clone(),
137           original_post_url: post.url.clone(),
138           reason: self.summary,
139           original_post_body: post.body.clone(),
140         };
141
142         let report = PostReport::report(context.pool(), &report_form).await?;
143
144         let post_report_view = PostReportView::read(context.pool(), report.id, actor.id).await?;
145
146         context.send_mod_ws_message(
147           &UserOperation::CreateCommentReport,
148           &PostReportResponse { post_report_view },
149           post.community_id,
150           None,
151         )?;
152       }
153       PostOrComment::Comment(comment) => {
154         let report_form = CommentReportForm {
155           creator_id: actor.id,
156           comment_id: comment.id,
157           original_comment_text: comment.content.clone(),
158           reason: self.summary,
159         };
160
161         let report = CommentReport::report(context.pool(), &report_form).await?;
162
163         let comment_report_view =
164           CommentReportView::read(context.pool(), report.id, actor.id).await?;
165         let community_id = comment_report_view.community.id;
166
167         context.send_mod_ws_message(
168           &UserOperation::CreateCommentReport,
169           &CommentReportResponse {
170             comment_report_view,
171           },
172           community_id,
173           None,
174         )?;
175       }
176     };
177     Ok(())
178   }
179 }