]> Untitled Git - lemmy.git/blob - crates/db_views/src/private_message_view.rs
281df8ba6b358d95f54e6842648d5e6304819499
[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, private_message},
6   source::{
7     person::{Person, PersonSafe},
8     private_message::PrivateMessage,
9   },
10   traits::{ToSafe, ViewToVec},
11   utils::limit_and_offset,
12 };
13 use tracing::debug;
14 use typed_builder::TypedBuilder;
15
16 type PrivateMessageViewTuple = (PrivateMessage, PersonSafe, PersonSafe);
17
18 impl PrivateMessageView {
19   pub fn read(
20     conn: &mut PgConnection,
21     private_message_id: PrivateMessageId,
22   ) -> Result<Self, Error> {
23     let person_alias_1 = diesel::alias!(person as person1);
24
25     let (private_message, creator, recipient) = private_message::table
26       .find(private_message_id)
27       .inner_join(person::table.on(private_message::creator_id.eq(person::id)))
28       .inner_join(
29         person_alias_1.on(private_message::recipient_id.eq(person_alias_1.field(person::id))),
30       )
31       .order_by(private_message::published.desc())
32       .select((
33         private_message::all_columns,
34         Person::safe_columns_tuple(),
35         person_alias_1.fields(Person::safe_columns_tuple()),
36       ))
37       .first::<PrivateMessageViewTuple>(conn)?;
38
39     Ok(PrivateMessageView {
40       private_message,
41       creator,
42       recipient,
43     })
44   }
45
46   /// Gets the number of unread messages
47   pub fn get_unread_messages(
48     conn: &mut PgConnection,
49     my_person_id: PersonId,
50   ) -> Result<i64, Error> {
51     use diesel::dsl::*;
52     private_message::table
53       .filter(private_message::read.eq(false))
54       .filter(private_message::recipient_id.eq(my_person_id))
55       .filter(private_message::deleted.eq(false))
56       .select(count(private_message::id))
57       .first::<i64>(conn)
58   }
59 }
60
61 #[derive(TypedBuilder)]
62 #[builder(field_defaults(default))]
63 pub struct PrivateMessageQuery<'a> {
64   #[builder(!default)]
65   conn: &'a mut PgConnection,
66   #[builder(!default)]
67   recipient_id: PersonId,
68   unread_only: Option<bool>,
69   page: Option<i64>,
70   limit: Option<i64>,
71 }
72
73 impl<'a> PrivateMessageQuery<'a> {
74   pub fn list(self) -> Result<Vec<PrivateMessageView>, Error> {
75     let person_alias_1 = diesel::alias!(person as person1);
76
77     let mut query = private_message::table
78       .inner_join(person::table.on(private_message::creator_id.eq(person::id)))
79       .inner_join(
80         person_alias_1.on(private_message::recipient_id.eq(person_alias_1.field(person::id))),
81       )
82       .select((
83         private_message::all_columns,
84         Person::safe_columns_tuple(),
85         person_alias_1.fields(Person::safe_columns_tuple()),
86       ))
87       .into_boxed();
88
89     // If its unread, I only want the ones to me
90     if self.unread_only.unwrap_or(false) {
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       .into_iter()
128       .map(|a| Self {
129         private_message: a.0,
130         creator: a.1,
131         recipient: a.2,
132       })
133       .collect::<Vec<Self>>()
134   }
135 }