]> Untitled Git - lemmy.git/blob - crates/apub/src/activities/community/report.rs
Extract Activitypub logic into separate library (#2288)
[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   local_instance,
4   objects::{community::ApubCommunity, person::ApubPerson},
5   protocol::activities::community::report::Report,
6   ActorType,
7   PostOrComment,
8 };
9 use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
10 use activitystreams_kinds::activity::FlagType;
11 use lemmy_api_common::{comment::CommentReportResponse, post::PostReportResponse, utils::blocking};
12 use lemmy_db_schema::{
13   source::{
14     comment_report::{CommentReport, CommentReportForm},
15     post_report::{PostReport, PostReportForm},
16   },
17   traits::Reportable,
18 };
19 use lemmy_db_views::structs::{CommentReportView, PostReportView};
20 use lemmy_utils::error::LemmyError;
21 use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};
22 use url::Url;
23
24 impl Report {
25   #[tracing::instrument(skip_all)]
26   pub async fn send(
27     object_id: ObjectId<PostOrComment>,
28     actor: &ApubPerson,
29     community_id: ObjectId<ApubCommunity>,
30     reason: String,
31     context: &LemmyContext,
32   ) -> Result<(), LemmyError> {
33     let community = community_id
34       .dereference_local::<LemmyError>(context)
35       .await?;
36     let kind = FlagType::Flag;
37     let id = generate_activity_id(
38       kind.clone(),
39       &context.settings().get_protocol_and_hostname(),
40     )?;
41     let report = Report {
42       actor: ObjectId::new(actor.actor_id()),
43       to: ObjectId::new(community.actor_id()),
44       object: object_id,
45       summary: reason,
46       kind,
47       id: id.clone(),
48       unparsed: Default::default(),
49     };
50     send_lemmy_activity(
51       context,
52       &report,
53       &id,
54       actor,
55       vec![community.shared_inbox_or_inbox_url()],
56       false,
57     )
58     .await
59   }
60 }
61
62 #[async_trait::async_trait(?Send)]
63 impl ActivityHandler for Report {
64   type DataType = LemmyContext;
65   type Error = LemmyError;
66
67   fn id(&self) -> &Url {
68     &self.id
69   }
70
71   fn actor(&self) -> &Url {
72     self.actor.inner()
73   }
74
75   #[tracing::instrument(skip_all)]
76   async fn verify(
77     &self,
78     context: &Data<LemmyContext>,
79     request_counter: &mut i32,
80   ) -> Result<(), LemmyError> {
81     let community = self
82       .to
83       .dereference::<LemmyError>(context, local_instance(context), request_counter)
84       .await?;
85     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
86     Ok(())
87   }
88
89   #[tracing::instrument(skip_all)]
90   async fn receive(
91     self,
92     context: &Data<LemmyContext>,
93     request_counter: &mut i32,
94   ) -> Result<(), LemmyError> {
95     let actor = self
96       .actor
97       .dereference::<LemmyError>(context, local_instance(context), request_counter)
98       .await?;
99     match self
100       .object
101       .dereference::<LemmyError>(context, local_instance(context), request_counter)
102       .await?
103     {
104       PostOrComment::Post(post) => {
105         let report_form = PostReportForm {
106           creator_id: actor.id,
107           post_id: post.id,
108           original_post_name: post.name.clone(),
109           original_post_url: post.url.clone(),
110           reason: self.summary,
111           original_post_body: post.body.clone(),
112         };
113
114         let report = blocking(context.pool(), move |conn| {
115           PostReport::report(conn, &report_form)
116         })
117         .await??;
118
119         let post_report_view = blocking(context.pool(), move |conn| {
120           PostReportView::read(conn, report.id, actor.id)
121         })
122         .await??;
123
124         context.chat_server().do_send(SendModRoomMessage {
125           op: UserOperation::CreateCommentReport,
126           response: PostReportResponse { post_report_view },
127           community_id: post.community_id,
128           websocket_id: None,
129         });
130       }
131       PostOrComment::Comment(comment) => {
132         let report_form = CommentReportForm {
133           creator_id: actor.id,
134           comment_id: comment.id,
135           original_comment_text: comment.content.clone(),
136           reason: self.summary,
137         };
138
139         let report = blocking(context.pool(), move |conn| {
140           CommentReport::report(conn, &report_form)
141         })
142         .await??;
143
144         let comment_report_view = blocking(context.pool(), move |conn| {
145           CommentReportView::read(conn, report.id, actor.id)
146         })
147         .await??;
148         let community_id = comment_report_view.community.id;
149
150         context.chat_server().do_send(SendModRoomMessage {
151           op: UserOperation::CreateCommentReport,
152           response: CommentReportResponse {
153             comment_report_view,
154           },
155           community_id,
156           websocket_id: None,
157         });
158       }
159     };
160     Ok(())
161   }
162 }