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