Skip to main content

mxr_store/
thread.rs

1use mxr_core::id::*;
2use mxr_core::types::*;
3
4use crate::message::record_to_envelope;
5
6impl super::Store {
7    pub async fn get_thread(&self, thread_id: &ThreadId) -> Result<Option<Thread>, sqlx::Error> {
8        let tid = thread_id.as_str();
9        let row = sqlx::query!(
10            r#"SELECT
11                thread_id as "thread_id!",
12                account_id as "account_id!",
13                MIN(subject) as "subject!: String",
14                COUNT(*) as "message_count!: i64",
15                SUM(CASE WHEN (flags & 1) = 0 THEN 1 ELSE 0 END) as "unread_count!: i64",
16                MAX(date) as "latest_date!: i64",
17                snippet as "snippet!"
18             FROM messages
19             WHERE thread_id = ?
20             GROUP BY thread_id"#,
21            tid,
22        )
23        .fetch_optional(self.reader())
24        .await?;
25
26        let row = match row {
27            Some(r) => r,
28            None => return Ok(None),
29        };
30
31        // Get participants
32        let tid2 = thread_id.as_str();
33        let participant_rows = sqlx::query!(
34            r#"SELECT DISTINCT from_name, from_email as "from_email!" FROM messages WHERE thread_id = ?"#,
35            tid2,
36        )
37        .fetch_all(self.reader())
38        .await?;
39
40        let participants: Vec<Address> = participant_rows
41            .into_iter()
42            .map(|r| Address {
43                name: r.from_name,
44                email: r.from_email,
45            })
46            .collect();
47
48        Ok(Some(Thread {
49            id: ThreadId::from_uuid(uuid::Uuid::parse_str(&row.thread_id).unwrap()),
50            account_id: AccountId::from_uuid(uuid::Uuid::parse_str(&row.account_id).unwrap()),
51            subject: row.subject,
52            participants,
53            message_count: row.message_count as u32,
54            unread_count: row.unread_count as u32,
55            latest_date: chrono::DateTime::from_timestamp(row.latest_date, 0).unwrap_or_default(),
56            snippet: row.snippet,
57        }))
58    }
59
60    pub async fn get_thread_envelopes(
61        &self,
62        thread_id: &ThreadId,
63    ) -> Result<Vec<Envelope>, sqlx::Error> {
64        let tid = thread_id.as_str();
65        let rows = sqlx::query!(
66            r#"SELECT
67                id as "id!", account_id as "account_id!", provider_id as "provider_id!",
68                thread_id as "thread_id!", message_id_header, in_reply_to,
69                reference_headers, from_name, from_email as "from_email!",
70                to_addrs as "to_addrs!", cc_addrs as "cc_addrs!", bcc_addrs as "bcc_addrs!",
71                subject as "subject!", date as "date!", flags as "flags!",
72                snippet as "snippet!", has_attachments as "has_attachments!: bool",
73                size_bytes as "size_bytes!", unsubscribe_method,
74                COALESCE((
75                    SELECT GROUP_CONCAT(labels.provider_id, char(31))
76                    FROM message_labels
77                    JOIN labels ON labels.id = message_labels.label_id
78                    WHERE message_labels.message_id = messages.id
79                ), '') as "label_provider_ids!: String"
80             FROM messages WHERE thread_id = ? ORDER BY date ASC"#,
81            tid,
82        )
83        .fetch_all(self.reader())
84        .await?;
85
86        Ok(rows
87            .into_iter()
88            .map(|r| {
89                record_to_envelope(
90                    &r.id,
91                    &r.account_id,
92                    &r.provider_id,
93                    &r.thread_id,
94                    r.message_id_header.as_deref(),
95                    r.in_reply_to.as_deref(),
96                    r.reference_headers.as_deref(),
97                    r.from_name.as_deref(),
98                    &r.from_email,
99                    &r.to_addrs,
100                    &r.cc_addrs,
101                    &r.bcc_addrs,
102                    &r.subject,
103                    r.date,
104                    r.flags,
105                    &r.snippet,
106                    r.has_attachments,
107                    r.size_bytes,
108                    r.unsubscribe_method.as_deref(),
109                    &r.label_provider_ids,
110                )
111            })
112            .collect())
113    }
114}