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