Files
imks/models/message_attachment.rs
T
zhenyi 821537186e refactor(tests): reformat code and update dependency management
- Reorganized import statements in adapter tests for better readability
- Replaced or_insert_with(Vec::new) with or_default() in test closures
- Updated Cargo.lock with new dependency versions and checksums
- Added TLS features to tonic dependency configuration
- Included sqlx, chrono, and uuid dependencies with specific features
- Added jsonwebtoken and arc-swap as project dependencies
- Reformatted assertion statements to comply with line length limits
- Adjusted base64 import order in engine codec module
- Updated protobuf include statement formatting
2026-06-11 12:11:05 +08:00

97 lines
2.9 KiB
Rust

//! File / image attachment on a message — new table `message_attachment`.
//!
//! Discord-style: each message can have multiple attachments. Files are
//! uploaded to S3 first, then the URL is stored here.
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// A file or image attachment on a message.
///
/// Maps to the `message_attachment` table. Files are uploaded to object
/// storage first, then the URL is stored here.
#[derive(Debug, Clone, Serialize, Deserialize, sqlx::FromRow)]
pub struct MessageAttachment {
pub id: Uuid,
pub message_id: Uuid,
/// Original filename as uploaded by the user.
pub filename: String,
/// MIME type: "image/png", "application/pdf", etc.
pub content_type: Option<String>,
/// File size in bytes.
pub size: i64,
/// Public URL (S3 presigned or CDN).
pub url: String,
/// S3 / object-store key for backend access.
pub storage_key: Option<String>,
/// Image / video width in pixels.
pub width: Option<i32>,
/// Image / video height in pixels.
pub height: Option<i32>,
/// Audio / video duration in seconds.
pub duration_secs: Option<f64>,
/// Blurred low-res preview for progressive loading (base64 data URI).
pub blurhash: Option<String>,
/// Whether this attachment should be rendered as a spoiler (hidden until click).
pub spoiler: bool,
pub created_at: DateTime<Utc>,
}
/// Lightweight attachment summary for list views.
///
/// Omits URL and storage_key to reduce payload size.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AttachmentSummary {
pub id: Uuid,
pub filename: String,
pub content_type: Option<String>,
pub size: i64,
pub width: Option<i32>,
pub height: Option<i32>,
pub spoiler: bool,
}
impl From<MessageAttachment> for AttachmentSummary {
fn from(a: MessageAttachment) -> Self {
Self {
id: a.id,
filename: a.filename,
content_type: a.content_type,
size: a.size,
width: a.width,
height: a.height,
spoiler: a.spoiler,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_attachment_conversion() {
let att = MessageAttachment {
id: Uuid::now_v7(),
message_id: Uuid::now_v7(),
filename: "photo.png".into(),
content_type: Some("image/png".into()),
size: 1024,
url: "https://cdn.example.com/photo.png".into(),
storage_key: None,
width: Some(800),
height: Some(600),
duration_secs: None,
blurhash: None,
spoiler: false,
created_at: Utc::now(),
};
let summary: AttachmentSummary = att.into();
assert_eq!(summary.filename, "photo.png");
assert_eq!(summary.size, 1024);
assert_eq!(summary.width, Some(800));
}
}