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