From 15d67f56677a4c9b3a3b32ec30dd85db049e3531 Mon Sep 17 00:00:00 2001 From: Joakim Hulthe Date: Mon, 6 Apr 2026 08:17:34 +0000 Subject: [PATCH] Add thumbnail endpoint with size options --- examples/thumbnail.rs | 50 +++++++++++++++++++++++++++++++++ src/apis/assets.rs | 64 ++++++++++++++++++++++++++++++++++++++++++- src/models/mod.rs | 14 ++++++++++ 3 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 examples/thumbnail.rs diff --git a/examples/thumbnail.rs b/examples/thumbnail.rs new file mode 100644 index 0000000..caea214 --- /dev/null +++ b/examples/thumbnail.rs @@ -0,0 +1,50 @@ +//! Example: Download asset thumbnails + +use immich_sdk::Client; +use immich_sdk::models::AssetMediaSize; +use std::fs; + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Create a client + let client = Client::from_url("https://immich.example.com")?.with_api_key("your-api-key"); + + // Asset ID to download thumbnail for + let asset_id = "your-asset-id-here".parse()?; + + // Download thumbnail (small size, default) + println!("Downloading thumbnail..."); + let thumbnail = client + .assets() + .thumbnail(asset_id) + .size(AssetMediaSize::Thumbnail) + .execute() + .await?; + + fs::write("/path/to/output/thumbnail.jpg", &thumbnail)?; + println!("Saved thumbnail: {} bytes", thumbnail.len()); + + // Download preview (medium size) + let preview = client + .assets() + .thumbnail(asset_id) + .size(AssetMediaSize::Preview) + .execute() + .await?; + + fs::write("/path/to/output/preview.jpg", &preview)?; + println!("Saved preview: {} bytes", preview.len()); + + // Download fullsize + let fullsize = client + .assets() + .thumbnail(asset_id) + .size(AssetMediaSize::Fullsize) + .execute() + .await?; + + fs::write("/path/to/output/fullsize.jpg", &fullsize)?; + println!("Saved fullsize: {} bytes", fullsize.len()); + + Ok(()) +} diff --git a/src/apis/assets.rs b/src/apis/assets.rs index ca2daa3..bcfafc0 100644 --- a/src/apis/assets.rs +++ b/src/apis/assets.rs @@ -5,7 +5,7 @@ use std::path::Path; use crate::{ Client, error::{ImmichError, Result}, - models::{AssetId, AssetResponse, AssetUploadResponse, DeleteAssetsRequest}, + models::{AssetId, AssetMediaSize, AssetResponse, AssetUploadResponse, DeleteAssetsRequest}, }; /// API for managing assets (photos and videos) @@ -44,6 +44,11 @@ impl AssetsApi { pub fn download(&self, id: AssetId) -> DownloadAssetBuilder { DownloadAssetBuilder::new(self.client.clone(), id) } + + /// Get asset thumbnail + pub fn thumbnail(&self, id: AssetId) -> ThumbnailBuilder { + ThumbnailBuilder::new(self.client.clone(), id) + } } /// Builder for listing assets @@ -299,3 +304,60 @@ impl DownloadAssetBuilder { Ok(bytes) } } + +/// Builder for getting asset thumbnail +#[derive(Debug)] +pub struct ThumbnailBuilder { + client: Client, + id: AssetId, + size: Option, + edited: bool, +} + +impl ThumbnailBuilder { + /// Create a new thumbnail builder + const fn new(client: Client, id: AssetId) -> Self { + Self { + client, + id, + size: None, + edited: false, + } + } + + /// Set the thumbnail size + pub fn size(mut self, size: AssetMediaSize) -> Self { + self.size = Some(size); + self + } + + /// Get the edited version if available + pub fn edited(mut self) -> Self { + self.edited = true; + self + } + + /// Execute the request + pub async fn execute(self) -> Result { + let path = format!("/assets/{}/thumbnail", self.id); + let mut req = self.client.get(&path); + + if let Some(ref size) = self.size { + let size_str = match size { + AssetMediaSize::Original => "original", + AssetMediaSize::Fullsize => "fullsize", + AssetMediaSize::Preview => "preview", + AssetMediaSize::Thumbnail => "thumbnail", + }; + req = req.query(&[("size", size_str)]); + } + + if self.edited { + req = req.query(&[("edited", "true")]); + } + + let response = self.client.execute(req.build()?).await?; + let bytes = response.bytes().await?; + Ok(bytes) + } +} diff --git a/src/models/mod.rs b/src/models/mod.rs index 9f385ca..e90ab6c 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -68,6 +68,20 @@ pub enum AssetVisibility { Locked, } +/// Asset media size for thumbnails +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum AssetMediaSize { + /// Original size + Original, + /// Full size + Fullsize, + /// Preview size + Preview, + /// Thumbnail size + Thumbnail, +} + /// EXIF information for an asset #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")]