]> Untitled Git - lemmy.git/blob - lemmy_structs/src/lib.rs
Merge remote-tracking branch 'origin/split-db-workspace' into move_views_to_diesel_split
[lemmy.git] / lemmy_structs / src / lib.rs
1 pub mod comment;
2 pub mod community;
3 pub mod post;
4 pub mod site;
5 pub mod user;
6
7 use diesel::PgConnection;
8 use lemmy_db::{source::user::User, Crud, DbPool};
9 use lemmy_db_schema::source::{
10   comment::Comment,
11   post::Post,
12   user::User_,
13   user_mention::{UserMention, UserMentionForm},
14 };
15 use lemmy_utils::{email::send_email, settings::Settings, utils::MentionData, LemmyError};
16 use log::error;
17 use serde::{Deserialize, Serialize};
18
19 #[derive(Serialize, Deserialize, Debug)]
20 pub struct WebFingerLink {
21   pub rel: Option<String>,
22   #[serde(rename(serialize = "type", deserialize = "type"))]
23   pub type_: Option<String>,
24   pub href: Option<String>,
25   #[serde(skip_serializing_if = "Option::is_none")]
26   pub template: Option<String>,
27 }
28
29 #[derive(Serialize, Deserialize, Debug)]
30 pub struct WebFingerResponse {
31   pub subject: String,
32   pub aliases: Vec<String>,
33   pub links: Vec<WebFingerLink>,
34 }
35
36 pub async fn blocking<F, T>(pool: &DbPool, f: F) -> Result<T, LemmyError>
37 where
38   F: FnOnce(&diesel::PgConnection) -> T + Send + 'static,
39   T: Send + 'static,
40 {
41   let pool = pool.clone();
42   let res = actix_web::web::block(move || {
43     let conn = pool.get()?;
44     let res = (f)(&conn);
45     Ok(res) as Result<_, LemmyError>
46   })
47   .await?;
48
49   Ok(res)
50 }
51
52 pub async fn send_local_notifs(
53   mentions: Vec<MentionData>,
54   comment: Comment,
55   user: &User_,
56   post: Post,
57   pool: &DbPool,
58   do_send_email: bool,
59 ) -> Result<Vec<i32>, LemmyError> {
60   let user2 = user.clone();
61   let ids = blocking(pool, move |conn| {
62     do_send_local_notifs(conn, &mentions, &comment, &user2, &post, do_send_email)
63   })
64   .await?;
65
66   Ok(ids)
67 }
68
69 fn do_send_local_notifs(
70   conn: &PgConnection,
71   mentions: &[MentionData],
72   comment: &Comment,
73   user: &User_,
74   post: &Post,
75   do_send_email: bool,
76 ) -> Vec<i32> {
77   let mut recipient_ids = Vec::new();
78
79   // Send the local mentions
80   for mention in mentions
81     .iter()
82     .filter(|m| m.is_local() && m.name.ne(&user.name))
83     .collect::<Vec<&MentionData>>()
84   {
85     if let Ok(mention_user) = User_::read_from_name(&conn, &mention.name) {
86       // TODO
87       // At some point, make it so you can't tag the parent creator either
88       // This can cause two notifications, one for reply and the other for mention
89       recipient_ids.push(mention_user.id);
90
91       let user_mention_form = UserMentionForm {
92         recipient_id: mention_user.id,
93         comment_id: comment.id,
94         read: None,
95       };
96
97       // Allow this to fail softly, since comment edits might re-update or replace it
98       // Let the uniqueness handle this fail
99       let _ = UserMention::create(&conn, &user_mention_form);
100
101       // Send an email to those users that have notifications on
102       if do_send_email && mention_user.send_notifications_to_email {
103         send_email_to_user(
104           mention_user,
105           "Mentioned by",
106           "User Mention",
107           &comment.content,
108         )
109       }
110     }
111   }
112
113   // Send notifs to the parent commenter / poster
114   match comment.parent_id {
115     Some(parent_id) => {
116       if let Ok(parent_comment) = Comment::read(&conn, parent_id) {
117         if parent_comment.creator_id != user.id {
118           if let Ok(parent_user) = User_::read(&conn, parent_comment.creator_id) {
119             recipient_ids.push(parent_user.id);
120
121             if do_send_email && parent_user.send_notifications_to_email {
122               send_email_to_user(parent_user, "Reply from", "Comment Reply", &comment.content)
123             }
124           }
125         }
126       }
127     }
128     // Its a post
129     None => {
130       if post.creator_id != user.id {
131         if let Ok(parent_user) = User_::read(&conn, post.creator_id) {
132           recipient_ids.push(parent_user.id);
133
134           if do_send_email && parent_user.send_notifications_to_email {
135             send_email_to_user(parent_user, "Reply from", "Post Reply", &comment.content)
136           }
137         }
138       }
139     }
140   };
141   recipient_ids
142 }
143
144 pub fn send_email_to_user(user: User_, subject_text: &str, body_text: &str, comment_content: &str) {
145   if user.banned {
146     return;
147   }
148
149   if let Some(user_email) = user.email {
150     let subject = &format!(
151       "{} - {} {}",
152       subject_text,
153       Settings::get().hostname,
154       user.name,
155     );
156     let html = &format!(
157       "<h1>{}</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
158       body_text,
159       user.name,
160       comment_content,
161       Settings::get().get_protocol_and_hostname()
162     );
163     match send_email(subject, &user_email, &user.name, html) {
164       Ok(_o) => _o,
165       Err(e) => error!("{}", e),
166     };
167   }
168 }