354 lines
9.7 KiB
Rust
354 lines
9.7 KiB
Rust
//! 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<ExifInfo>,
|
|
/// 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<Utc>,
|
|
/// Updated at timestamp
|
|
pub updated_at: DateTime<Utc>,
|
|
}
|
|
|
|
/// 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<i64>,
|
|
/// Image dimensions
|
|
pub exif_image_height: Option<i32>,
|
|
/// Image width
|
|
pub exif_image_width: Option<i32>,
|
|
/// Orientation
|
|
pub orientation: Option<String>,
|
|
/// Date taken
|
|
pub date_time_original: Option<DateTime<Utc>>,
|
|
/// GPS latitude
|
|
pub latitude: Option<f64>,
|
|
/// GPS longitude
|
|
pub longitude: Option<f64>,
|
|
/// Camera make
|
|
pub make: Option<String>,
|
|
/// Camera model
|
|
pub model: Option<String>,
|
|
}
|
|
|
|
/// 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<AssetId>,
|
|
/// Number of assets in album
|
|
pub asset_count: i64,
|
|
/// Assets in the album
|
|
pub assets: Vec<AssetResponse>,
|
|
/// Created at timestamp
|
|
pub created_at: DateTime<Utc>,
|
|
/// Updated at timestamp
|
|
pub updated_at: DateTime<Utc>,
|
|
/// 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<Utc>,
|
|
}
|
|
|
|
/// 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<AssetId>,
|
|
/// User IDs to share with
|
|
pub album_users: Vec<AlbumUserCreate>,
|
|
}
|
|
|
|
/// 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<String>,
|
|
/// Description
|
|
pub description: Option<String>,
|
|
}
|
|
|
|
/// 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<AssetId>,
|
|
/// Duplicate ID if duplicate
|
|
pub duplicate: Option<AssetId>,
|
|
}
|
|
|
|
/// 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<AssetId>,
|
|
/// 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<Utc>,
|
|
/// Updated at
|
|
pub updated_at: DateTime<Utc>,
|
|
}
|
|
|
|
/// 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<Vec<Option<String>>>,
|
|
/// Array of country names extracted from EXIF GPS data
|
|
pub country: Option<Vec<Option<String>>>,
|
|
/// Array of video durations in HH:MM:SS format (null for images)
|
|
pub duration: Option<Vec<Option<String>>>,
|
|
/// Array of file creation timestamps in UTC
|
|
pub file_created_at: Option<Vec<String>>,
|
|
/// Array of asset IDs in the time bucket
|
|
pub id: Vec<String>,
|
|
/// Array indicating whether each asset is favorited
|
|
pub is_favorite: Option<Vec<bool>>,
|
|
/// Array indicating whether each asset is an image (false for videos)
|
|
pub is_image: Option<Vec<bool>>,
|
|
/// Array indicating whether each asset is in the trash
|
|
pub is_trashed: Option<Vec<bool>>,
|
|
/// Array of latitude coordinates extracted from EXIF GPS data
|
|
pub latitude: Option<Vec<Option<f64>>>,
|
|
/// Array of live photo video asset IDs (null for non-live photos)
|
|
pub live_photo_video_id: Option<Vec<Option<String>>>,
|
|
/// Array of UTC offset hours at the time each photo was taken
|
|
pub local_offset_hours: Option<Vec<f64>>,
|
|
/// Array of longitude coordinates extracted from EXIF GPS data
|
|
pub longitude: Option<Vec<Option<f64>>>,
|
|
/// Array of owner IDs for each asset
|
|
pub owner_id: Option<Vec<String>>,
|
|
/// Array of projection types for 360° content
|
|
pub projection_type: Option<Vec<Option<String>>>,
|
|
/// Array of aspect ratios (width/height) for each asset
|
|
pub ratio: Option<Vec<f64>>,
|
|
/// Array of stack information as [stackId, assetCount] tuples
|
|
pub stack: Option<Vec<Option<Vec<String>>>>,
|
|
/// Array of BlurHash strings for generating asset previews
|
|
pub thumbhash: Option<Vec<Option<String>>>,
|
|
/// Array of visibility statuses for each asset
|
|
pub visibility: Option<Vec<AssetVisibility>>,
|
|
}
|
|
|
|
#[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");
|
|
}
|
|
}
|