1use mxr_core::id::*;
2use mxr_core::types::*;
3use sqlx::Row;
4
5impl super::Store {
6 pub async fn get_body(
7 &self,
8 message_id: &MessageId,
9 ) -> Result<Option<MessageBody>, sqlx::Error> {
10 let mid = message_id.as_str();
11 let row = sqlx::query(
12 r#"SELECT message_id, text_plain, text_html, fetched_at, metadata_json FROM bodies WHERE message_id = ?"#,
13 )
14 .bind(mid)
15 .fetch_optional(self.reader())
16 .await?;
17
18 let row = match row {
19 Some(r) => r,
20 None => return Ok(None),
21 };
22
23 let att_mid = message_id.as_str();
24 let attachments_rows = sqlx::query!(
25 r#"SELECT id as "id!", message_id as "message_id!", filename as "filename!", mime_type as "mime_type!", size_bytes as "size_bytes!", local_path, provider_id as "provider_id!" FROM attachments WHERE message_id = ?"#,
26 att_mid,
27 )
28 .fetch_all(self.reader())
29 .await?;
30
31 let attachments: Vec<AttachmentMeta> = attachments_rows
32 .into_iter()
33 .map(|r| AttachmentMeta {
34 id: AttachmentId::from_uuid(uuid::Uuid::parse_str(&r.id).unwrap()),
35 message_id: MessageId::from_uuid(uuid::Uuid::parse_str(&r.message_id).unwrap()),
36 filename: r.filename,
37 mime_type: r.mime_type,
38 size_bytes: r.size_bytes as u64,
39 local_path: r.local_path.map(std::path::PathBuf::from),
40 provider_id: r.provider_id,
41 })
42 .collect();
43
44 let metadata_json: String = row.try_get("metadata_json")?;
45 Ok(Some(MessageBody {
46 message_id: MessageId::from_uuid(
47 uuid::Uuid::parse_str(row.try_get::<&str, _>("message_id")?).unwrap(),
48 ),
49 text_plain: row.try_get("text_plain")?,
50 text_html: row.try_get("text_html")?,
51 attachments,
52 fetched_at: chrono::DateTime::from_timestamp(row.try_get("fetched_at")?, 0)
53 .unwrap_or_default(),
54 metadata: serde_json::from_str(&metadata_json).unwrap_or_default(),
55 }))
56 }
57
58 pub async fn insert_body(&self, body: &MessageBody) -> Result<(), sqlx::Error> {
59 let fetched_at = body.fetched_at.timestamp();
60 let mid = body.message_id.as_str();
61 let metadata_json = serde_json::to_string(&body.metadata).unwrap_or_else(|_| "{}".into());
62
63 sqlx::query(
64 "INSERT OR REPLACE INTO bodies (message_id, text_plain, text_html, fetched_at, metadata_json) VALUES (?, ?, ?, ?, ?)",
65 )
66 .bind(mid)
67 .bind(&body.text_plain)
68 .bind(&body.text_html)
69 .bind(fetched_at)
70 .bind(metadata_json)
71 .execute(self.writer())
72 .await?;
73
74 for att in &body.attachments {
75 let att_id = att.id.as_str();
76 let att_mid = att.message_id.as_str();
77 let local_path = att
78 .local_path
79 .as_ref()
80 .map(|p| p.to_string_lossy().to_string());
81 let size_bytes = att.size_bytes as i64;
82 sqlx::query!(
83 "INSERT OR REPLACE INTO attachments (id, message_id, filename, mime_type, size_bytes, local_path, provider_id)
84 VALUES (?, ?, ?, ?, ?, ?, ?)",
85 att_id,
86 att_mid,
87 att.filename,
88 att.mime_type,
89 size_bytes,
90 local_path,
91 att.provider_id,
92 )
93 .execute(self.writer())
94 .await?;
95 }
96
97 Ok(())
98 }
99}