//! Attachment CRUD operations on `MessageRepo`. use uuid::Uuid; use crate::ImksResult; use crate::models::message_attachment::{AttachmentSummary, MessageAttachment}; use super::message_repo::MessageRepo; impl MessageRepo { /// Create a single attachment record. #[allow(clippy::too_many_arguments)] pub async fn create_attachment( &self, message_id: Uuid, filename: &str, content_type: Option<&str>, size: i64, url: &str, storage_key: Option<&str>, width: Option, height: Option, spoiler: bool, ) -> ImksResult { let id = Uuid::now_v7(); sqlx::query_as::<_, MessageAttachment>( r#" INSERT INTO message_attachment ( id, message_id, filename, content_type, size, url, storage_key, width, height, spoiler ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING * "#, ) .bind(id) .bind(message_id) .bind(filename) .bind(content_type) .bind(size) .bind(url) .bind(storage_key) .bind(width) .bind(height) .bind(spoiler) .fetch_one(self.pool()) .await .map_err(Into::into) } /// Get all attachments for a message. pub async fn get_attachments(&self, message_id: Uuid) -> ImksResult> { sqlx::query_as::<_, MessageAttachment>( "SELECT * FROM message_attachment WHERE message_id = $1 ORDER BY created_at", ) .bind(message_id) .fetch_all(self.pool()) .await .map_err(Into::into) } /// Get lightweight attachment summaries (no URLs/storage keys). pub async fn get_attachment_summaries( &self, message_id: Uuid, ) -> ImksResult> { let attachments = self.get_attachments(message_id).await?; Ok(attachments .into_iter() .map(AttachmentSummary::from) .collect()) } /// Delete a single attachment. pub async fn delete_attachment(&self, attachment_id: Uuid) -> ImksResult { let result = sqlx::query("DELETE FROM message_attachment WHERE id = $1") .bind(attachment_id) .execute(self.pool()) .await?; Ok(result.rows_affected() > 0) } }