]> Untitled Git - lemmy.git/blob - crates/api_common/src/build_response.rs
Replace Option<bool> with bool for PostQuery and CommentQuery (#3819) (#3857)
[lemmy.git] / crates / api_common / src / build_response.rs
1 use crate::{
2   comment::CommentResponse,
3   community::CommunityResponse,
4   context::LemmyContext,
5   post::PostResponse,
6   utils::{check_person_block, get_interface_language, is_mod_or_admin, send_email_to_user},
7 };
8 use actix_web::web::Json;
9 use lemmy_db_schema::{
10   newtypes::{CommentId, CommunityId, LocalUserId, PersonId, PostId},
11   source::{
12     actor_language::CommunityLanguage,
13     comment::Comment,
14     comment_reply::{CommentReply, CommentReplyInsertForm},
15     person::Person,
16     person_mention::{PersonMention, PersonMentionInsertForm},
17     post::Post,
18   },
19   traits::Crud,
20 };
21 use lemmy_db_views::structs::{CommentView, LocalUserView, PostView};
22 use lemmy_db_views_actor::structs::CommunityView;
23 use lemmy_utils::{error::LemmyError, utils::mention::MentionData};
24
25 pub async fn build_comment_response(
26   context: &LemmyContext,
27   comment_id: CommentId,
28   local_user_view: Option<LocalUserView>,
29   recipient_ids: Vec<LocalUserId>,
30 ) -> Result<CommentResponse, LemmyError> {
31   let person_id = local_user_view.map(|l| l.person.id);
32   let comment_view = CommentView::read(&mut context.pool(), comment_id, person_id).await?;
33   Ok(CommentResponse {
34     comment_view,
35     recipient_ids,
36   })
37 }
38
39 pub async fn build_community_response(
40   context: &LemmyContext,
41   local_user_view: LocalUserView,
42   community_id: CommunityId,
43 ) -> Result<Json<CommunityResponse>, LemmyError> {
44   let is_mod_or_admin =
45     is_mod_or_admin(&mut context.pool(), local_user_view.person.id, community_id)
46       .await
47       .is_ok();
48   let person_id = local_user_view.person.id;
49   let community_view = CommunityView::read(
50     &mut context.pool(),
51     community_id,
52     Some(person_id),
53     is_mod_or_admin,
54   )
55   .await?;
56   let discussion_languages = CommunityLanguage::read(&mut context.pool(), community_id).await?;
57
58   Ok(Json(CommunityResponse {
59     community_view,
60     discussion_languages,
61   }))
62 }
63
64 pub async fn build_post_response(
65   context: &LemmyContext,
66   community_id: CommunityId,
67   person_id: PersonId,
68   post_id: PostId,
69 ) -> Result<Json<PostResponse>, LemmyError> {
70   let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), person_id, community_id)
71     .await
72     .is_ok();
73   let post_view = PostView::read(
74     &mut context.pool(),
75     post_id,
76     Some(person_id),
77     is_mod_or_admin,
78   )
79   .await?;
80   Ok(Json(PostResponse { post_view }))
81 }
82
83 // TODO: this function is a mess and should be split up to handle email seperately
84 #[tracing::instrument(skip_all)]
85 pub async fn send_local_notifs(
86   mentions: Vec<MentionData>,
87   comment: &Comment,
88   person: &Person,
89   post: &Post,
90   do_send_email: bool,
91   context: &LemmyContext,
92 ) -> Result<Vec<LocalUserId>, LemmyError> {
93   let mut recipient_ids = Vec::new();
94   let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname());
95
96   // Send the local mentions
97   for mention in mentions
98     .iter()
99     .filter(|m| m.is_local(&context.settings().hostname) && m.name.ne(&person.name))
100   {
101     let mention_name = mention.name.clone();
102     let user_view = LocalUserView::read_from_name(&mut context.pool(), &mention_name).await;
103     if let Ok(mention_user_view) = user_view {
104       // TODO
105       // At some point, make it so you can't tag the parent creator either
106       // This can cause two notifications, one for reply and the other for mention
107       recipient_ids.push(mention_user_view.local_user.id);
108
109       let user_mention_form = PersonMentionInsertForm {
110         recipient_id: mention_user_view.person.id,
111         comment_id: comment.id,
112         read: None,
113       };
114
115       // Allow this to fail softly, since comment edits might re-update or replace it
116       // Let the uniqueness handle this fail
117       PersonMention::create(&mut context.pool(), &user_mention_form)
118         .await
119         .ok();
120
121       // Send an email to those local users that have notifications on
122       if do_send_email {
123         let lang = get_interface_language(&mention_user_view);
124         send_email_to_user(
125           &mention_user_view,
126           &lang.notification_mentioned_by_subject(&person.name),
127           &lang.notification_mentioned_by_body(&comment.content, &inbox_link, &person.name),
128           context.settings(),
129         )
130         .await
131       }
132     }
133   }
134
135   // Send comment_reply to the parent commenter / poster
136   if let Some(parent_comment_id) = comment.parent_comment_id() {
137     let parent_comment = Comment::read(&mut context.pool(), parent_comment_id).await?;
138
139     // Get the parent commenter local_user
140     let parent_creator_id = parent_comment.creator_id;
141
142     // Only add to recipients if that person isn't blocked
143     let creator_blocked = check_person_block(person.id, parent_creator_id, &mut context.pool())
144       .await
145       .is_err();
146
147     // Don't send a notif to yourself
148     if parent_comment.creator_id != person.id && !creator_blocked {
149       let user_view = LocalUserView::read_person(&mut context.pool(), parent_creator_id).await;
150       if let Ok(parent_user_view) = user_view {
151         recipient_ids.push(parent_user_view.local_user.id);
152
153         let comment_reply_form = CommentReplyInsertForm {
154           recipient_id: parent_user_view.person.id,
155           comment_id: comment.id,
156           read: None,
157         };
158
159         // Allow this to fail softly, since comment edits might re-update or replace it
160         // Let the uniqueness handle this fail
161         CommentReply::create(&mut context.pool(), &comment_reply_form)
162           .await
163           .ok();
164
165         if do_send_email {
166           let lang = get_interface_language(&parent_user_view);
167           send_email_to_user(
168             &parent_user_view,
169             &lang.notification_comment_reply_subject(&person.name),
170             &lang.notification_comment_reply_body(&comment.content, &inbox_link, &person.name),
171             context.settings(),
172           )
173           .await
174         }
175       }
176     }
177   } else {
178     // If there's no parent, its the post creator
179     // Only add to recipients if that person isn't blocked
180     let creator_blocked = check_person_block(person.id, post.creator_id, &mut context.pool())
181       .await
182       .is_err();
183
184     if post.creator_id != person.id && !creator_blocked {
185       let creator_id = post.creator_id;
186       let parent_user = LocalUserView::read_person(&mut context.pool(), creator_id).await;
187       if let Ok(parent_user_view) = parent_user {
188         recipient_ids.push(parent_user_view.local_user.id);
189
190         let comment_reply_form = CommentReplyInsertForm {
191           recipient_id: parent_user_view.person.id,
192           comment_id: comment.id,
193           read: None,
194         };
195
196         // Allow this to fail softly, since comment edits might re-update or replace it
197         // Let the uniqueness handle this fail
198         CommentReply::create(&mut context.pool(), &comment_reply_form)
199           .await
200           .ok();
201
202         if do_send_email {
203           let lang = get_interface_language(&parent_user_view);
204           send_email_to_user(
205             &parent_user_view,
206             &lang.notification_post_reply_subject(&person.name),
207             &lang.notification_post_reply_body(&comment.content, &inbox_link, &person.name),
208             context.settings(),
209           )
210           .await
211         }
212       }
213     }
214   }
215
216   Ok(recipient_ids)
217 }