]> Untitled Git - lemmy.git/blob - crates/db_views/src/private_message_view.rs
Merge branch 'split_user_table' into strictly_type_db_ids
[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::Serialize;
14
15 #[derive(Debug, PartialEq, Serialize, 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
46 pub struct PrivateMessageQueryBuilder<'a> {
47   conn: &'a PgConnection,
48   recipient_id: PersonId,
49   unread_only: bool,
50   page: Option<i64>,
51   limit: Option<i64>,
52 }
53
54 impl<'a> PrivateMessageQueryBuilder<'a> {
55   pub fn create(conn: &'a PgConnection, recipient_id: PersonId) -> Self {
56     PrivateMessageQueryBuilder {
57       conn,
58       recipient_id,
59       unread_only: false,
60       page: None,
61       limit: None,
62     }
63   }
64
65   pub fn unread_only(mut self, unread_only: bool) -> Self {
66     self.unread_only = unread_only;
67     self
68   }
69
70   pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
71     self.page = page.get_optional();
72     self
73   }
74
75   pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
76     self.limit = limit.get_optional();
77     self
78   }
79
80   pub fn list(self) -> Result<Vec<PrivateMessageView>, Error> {
81     let mut query = private_message::table
82       .inner_join(person::table.on(private_message::creator_id.eq(person::id)))
83       .inner_join(person_alias_1::table.on(private_message::recipient_id.eq(person_alias_1::id)))
84       .select((
85         private_message::all_columns,
86         Person::safe_columns_tuple(),
87         PersonAlias1::safe_columns_tuple(),
88       ))
89       .into_boxed();
90
91     // If its unread, I only want the ones to me
92     if self.unread_only {
93       query = query
94         .filter(private_message::read.eq(false))
95         .filter(private_message::recipient_id.eq(self.recipient_id));
96     }
97     // Otherwise, I want the ALL view to show both sent and received
98     else {
99       query = query.filter(
100         private_message::recipient_id
101           .eq(self.recipient_id)
102           .or(private_message::creator_id.eq(self.recipient_id)),
103       )
104     }
105
106     let (limit, offset) = limit_and_offset(self.page, self.limit);
107
108     query = query
109       .filter(private_message::deleted.eq(false))
110       .limit(limit)
111       .offset(offset)
112       .order_by(private_message::published.desc());
113
114     debug!(
115       "Private Message View Query: {:?}",
116       debug_query::<Pg, _>(&query)
117     );
118
119     let res = query.load::<PrivateMessageViewTuple>(self.conn)?;
120
121     Ok(PrivateMessageView::from_tuple_to_vec(res))
122   }
123 }
124
125 impl ViewToVec for PrivateMessageView {
126   type DbTuple = PrivateMessageViewTuple;
127   fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
128     items
129       .iter()
130       .map(|a| Self {
131         private_message: a.0.to_owned(),
132         creator: a.1.to_owned(),
133         recipient: a.2.to_owned(),
134       })
135       .collect::<Vec<Self>>()
136   }
137 }