//! Data models for the Immich API use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use uuid::Uuid; /// Asset ID type alias pub type AssetId = Uuid; /// Album ID type alias pub type AlbumId = Uuid; /// User ID type alias pub type UserId = Uuid; /// Asset response from the API #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AssetResponse { /// Asset ID pub id: AssetId, /// Device asset ID pub device_asset_id: String, /// Device ID pub device_id: String, /// Asset type (IMAGE or VIDEO) #[serde(rename = "type")] pub asset_type: AssetType, /// Original file name pub original_file_name: String, /// Original mime type pub original_mime_type: String, /// File size in bytes pub exif_info: Option, /// Whether asset is a favorite pub is_favorite: bool, /// Whether asset is archived pub is_archived: bool, /// Whether asset is trashed pub is_trashed: bool, /// Created at timestamp pub created_at: DateTime, /// Updated at timestamp pub updated_at: DateTime, } /// Asset type enumeration #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "UPPERCASE")] pub enum AssetType { /// Image file Image, /// Video file Video, } /// Asset visibility enumeration #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "snake_case")] pub enum AssetVisibility { /// Archived Archive, /// Visible in timeline Timeline, /// Hidden Hidden, /// Locked Locked, } /// EXIF information for an asset #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ExifInfo { /// File size in bytes pub file_size_in_byte: Option, /// Image dimensions pub exif_image_height: Option, /// Image width pub exif_image_width: Option, /// Orientation pub orientation: Option, /// Date taken pub date_time_original: Option>, /// GPS latitude pub latitude: Option, /// GPS longitude pub longitude: Option, /// Camera make pub make: Option, /// Camera model pub model: Option, } /// Album response from the API #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AlbumResponse { /// Album ID pub id: AlbumId, /// Album name pub album_name: String, /// Album description pub description: String, /// Album cover thumbnail asset ID pub album_thumbnail_asset_id: Option, /// Number of assets in album pub asset_count: i64, /// Assets in the album pub assets: Vec, /// Created at timestamp pub created_at: DateTime, /// Updated at timestamp pub updated_at: DateTime, /// Owner ID pub owner_id: UserId, } /// User response from the API #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct UserResponse { /// User ID pub id: UserId, /// User email pub email: String, /// User name pub name: String, /// Whether user is admin pub is_admin: bool, /// Whether user has OAuth enabled pub oauth_enabled: bool, /// Storage usage in bytes pub storage_usage_in_bytes: i64, /// Created at timestamp pub created_at: DateTime, } /// Server version information #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ServerVersion { /// Major version pub major: i32, /// Minor version pub minor: i32, /// Patch version pub patch: i32, } impl std::fmt::Display for ServerVersion { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}.{}.{}", self.major, self.minor, self.patch) } } /// Server features information #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ServerFeatures { /// Whether OAuth is enabled pub oauth: bool, /// Whether OAuth auto launch is enabled pub oauth_auto_launch: bool, /// Whether password login is enabled pub password_login: bool, /// Whether config file is present pub config_file: bool, } /// Server about information #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ServerAbout { /// Version information pub version: ServerVersion, /// Version string pub version_url: String, } /// Create album request #[derive(Debug, Clone, Serialize, Deserialize, Default)] #[serde(rename_all = "camelCase")] pub struct CreateAlbumRequest { /// Album name pub album_name: String, /// Asset IDs to add to album pub asset_ids: Vec, /// User IDs to share with pub album_users: Vec, } /// Album user creation info #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AlbumUserCreate { /// User ID pub user_id: UserId, /// Role (viewer or editor) pub role: AlbumUserRole, } /// Album user role #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "snake_case")] pub enum AlbumUserRole { /// Can only view Viewer, /// Can edit Editor, } /// Update album request #[derive(Debug, Clone, Serialize, Deserialize, Default)] #[serde(rename_all = "camelCase")] pub struct UpdateAlbumRequest { /// Album name pub album_name: Option, /// Description pub description: Option, } /// Asset upload response #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AssetUploadResponse { /// Upload status pub status: AssetUploadStatus, /// Asset ID if successful pub id: Option, /// Duplicate ID if duplicate pub duplicate: Option, } /// Asset upload status #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] pub enum AssetUploadStatus { /// Upload created new asset Created, /// Asset already exists Duplicate, /// Upload rejected Rejected, } /// Delete assets request #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct DeleteAssetsRequest { /// Asset IDs to delete pub ids: Vec, /// Force delete (skip trash) pub force: bool, } /// API key response #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ApiKeyResponse { /// Key ID pub id: String, /// Key name pub name: String, /// Created at pub created_at: DateTime, /// Updated at pub updated_at: DateTime, } /// Asset order enumeration #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] pub enum AssetOrder { /// Oldest first Asc, /// Newest first Desc, } /// Time bucket response #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TimeBucketResponse { /// Number of assets in this time bucket pub count: i64, /// Time bucket identifier in YYYY-MM-DD format pub time_bucket: String, } /// Time bucket asset response - contains arrays of asset data #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TimeBucketAssetResponse { /// Array of city names extracted from EXIF GPS data pub city: Option>>, /// Array of country names extracted from EXIF GPS data pub country: Option>>, /// Array of video durations in HH:MM:SS format (null for images) pub duration: Option>>, /// Array of file creation timestamps in UTC pub file_created_at: Option>, /// Array of asset IDs in the time bucket pub id: Vec, /// Array indicating whether each asset is favorited pub is_favorite: Option>, /// Array indicating whether each asset is an image (false for videos) pub is_image: Option>, /// Array indicating whether each asset is in the trash pub is_trashed: Option>, /// Array of latitude coordinates extracted from EXIF GPS data pub latitude: Option>>, /// Array of live photo video asset IDs (null for non-live photos) pub live_photo_video_id: Option>>, /// Array of UTC offset hours at the time each photo was taken pub local_offset_hours: Option>, /// Array of longitude coordinates extracted from EXIF GPS data pub longitude: Option>>, /// Array of owner IDs for each asset pub owner_id: Option>, /// Array of projection types for 360° content pub projection_type: Option>>, /// Array of aspect ratios (width/height) for each asset pub ratio: Option>, /// Array of stack information as [stackId, assetCount] tuples pub stack: Option>>>, /// Array of BlurHash strings for generating asset previews pub thumbhash: Option>>, /// Array of visibility statuses for each asset pub visibility: Option>, } #[cfg(test)] mod tests { use super::*; #[test] fn test_asset_type_serialization() { let asset_type = AssetType::Image; let json = serde_json::to_string(&asset_type).unwrap(); assert_eq!(json, r#""IMAGE""#); } #[test] fn test_server_version_display() { let version = ServerVersion { major: 1, minor: 137, patch: 0, }; assert_eq!(version.to_string(), "1.137.0"); } }