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