]> Untitled Git - lemmy.git/blob - crates/db_views/src/private_message_view.rs
Use typed-builder crate for queries (#2379)
[lemmy.git] / crates / db_views / src / private_message_view.rs
1 use crate::structs::PrivateMessageView;
2 use diesel::{pg::Pg, result::Error, *};
3 use lemmy_db_schema::{
4   newtypes::{PersonId, PrivateMessageId},
5   schema::{person, person_alias_1, private_message},
6   source::{
7     person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1},
8     private_message::PrivateMessage,
9   },
10   traits::{ToSafe, ViewToVec},
11   utils::limit_and_offset,
12 };
13 use tracing::debug;
14 use typed_builder::TypedBuilder;
15
16 type PrivateMessageViewTuple = (PrivateMessage, PersonSafe, PersonSafeAlias1);
17
18 impl PrivateMessageView {
19   pub fn read(conn: &PgConnection, private_message_id: PrivateMessageId) -> Result<Self, Error> {
20     let (private_message, creator, recipient) = private_message::table
21       .find(private_message_id)
22       .inner_join(person::table.on(private_message::creator_id.eq(person::id)))
23       .inner_join(person_alias_1::table.on(private_message::recipient_id.eq(person_alias_1::id)))
24       .order_by(private_message::published.desc())
25       .select((
26         private_message::all_columns,
27         Person::safe_columns_tuple(),
28         PersonAlias1::safe_columns_tuple(),
29       ))
30       .first::<PrivateMessageViewTuple>(conn)?;
31
32     Ok(PrivateMessageView {
33       private_message,
34       creator,
35       recipient,
36     })
37   }
38
39   /// Gets the number of unread messages
40   pub fn get_unread_messages(conn: &PgConnection, my_person_id: PersonId) -> Result<i64, Error> {
41     use diesel::dsl::*;
42     private_message::table
43       .filter(private_message::read.eq(false))
44       .filter(private_message::recipient_id.eq(my_person_id))
45       .filter(private_message::deleted.eq(false))
46       .select(count(private_message::id))
47       .first::<i64>(conn)
48   }
49 }
50
51 #[derive(TypedBuilder)]
52 #[builder(field_defaults(default))]
53 pub struct PrivateMessageQuery<'a> {
54   #[builder(!default)]
55   conn: &'a PgConnection,
56   #[builder(!default)]
57   recipient_id: PersonId,
58   unread_only: Option<bool>,
59   page: Option<i64>,
60   limit: Option<i64>,
61 }
62
63 impl<'a> PrivateMessageQuery<'a> {
64   pub fn list(self) -> Result<Vec<PrivateMessageView>, Error> {
65     let mut query = private_message::table
66       .inner_join(person::table.on(private_message::creator_id.eq(person::id)))
67       .inner_join(person_alias_1::table.on(private_message::recipient_id.eq(person_alias_1::id)))
68       .select((
69         private_message::all_columns,
70         Person::safe_columns_tuple(),
71         PersonAlias1::safe_columns_tuple(),
72       ))
73       .into_boxed();
74
75     // If its unread, I only want the ones to me
76     if self.unread_only.unwrap_or(false) {
77       query = query
78         .filter(private_message::read.eq(false))
79         .filter(private_message::recipient_id.eq(self.recipient_id));
80     }
81     // Otherwise, I want the ALL view to show both sent and received
82     else {
83       query = query.filter(
84         private_message::recipient_id
85           .eq(self.recipient_id)
86           .or(private_message::creator_id.eq(self.recipient_id)),
87       )
88     }
89
90     let (limit, offset) = limit_and_offset(self.page, self.limit)?;
91
92     query = query
93       .filter(private_message::deleted.eq(false))
94       .limit(limit)
95       .offset(offset)
96       .order_by(private_message::published.desc());
97
98     debug!(
99       "Private Message View Query: {:?}",
100       debug_query::<Pg, _>(&query)
101     );
102
103     let res = query.load::<PrivateMessageViewTuple>(self.conn)?;
104
105     Ok(PrivateMessageView::from_tuple_to_vec(res))
106   }
107 }
108
109 impl ViewToVec for PrivateMessageView {
110   type DbTuple = PrivateMessageViewTuple;
111   fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
112     items
113       .into_iter()
114       .map(|a| Self {
115         private_message: a.0,
116         creator: a.1,
117         recipient: a.2,
118       })
119       .collect::<Vec<Self>>()
120   }
121 }