Merge branch 'assets-list' into 'main'
Add an assets list command See merge request kernald/immich-tools!14
This commit is contained in:
commit
af5990796e
5 changed files with 109 additions and 5 deletions
19
src/args.rs
19
src/args.rs
|
@ -27,6 +27,14 @@ pub(crate) struct Opts {
|
||||||
|
|
||||||
#[derive(Serialize, Subcommand)]
|
#[derive(Serialize, Subcommand)]
|
||||||
pub(crate) enum Commands {
|
pub(crate) enum Commands {
|
||||||
|
/// Assets related commands
|
||||||
|
#[serde(rename = "assets")]
|
||||||
|
Assets {
|
||||||
|
#[command(subcommand)]
|
||||||
|
#[serde(flatten)]
|
||||||
|
assets_command: AssetsCommands,
|
||||||
|
},
|
||||||
|
|
||||||
/// People related commands
|
/// People related commands
|
||||||
#[serde(rename = "people")]
|
#[serde(rename = "people")]
|
||||||
People {
|
People {
|
||||||
|
@ -43,6 +51,17 @@ pub(crate) enum Commands {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Subcommand)]
|
||||||
|
pub(crate) enum AssetsCommands {
|
||||||
|
/// List all assets
|
||||||
|
#[serde(rename = "list")]
|
||||||
|
List {
|
||||||
|
/// List only offline assets
|
||||||
|
#[arg(short, long, action)]
|
||||||
|
offline: bool,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Subcommand)]
|
#[derive(Serialize, Subcommand)]
|
||||||
pub(crate) enum PeopleCommands {
|
pub(crate) enum PeopleCommands {
|
||||||
/// Synchronises date of births from a vcard file
|
/// Synchronises date of births from a vcard file
|
||||||
|
|
59
src/commands/list_assets.rs
Normal file
59
src/commands/list_assets.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
use crate::{
|
||||||
|
utils::assets::{fetch_all_assets, AssetQuery},
|
||||||
|
Client,
|
||||||
|
};
|
||||||
|
use color_eyre::eyre::Result;
|
||||||
|
use tabled::{
|
||||||
|
settings::{
|
||||||
|
object::{Columns, Object, Rows},
|
||||||
|
Format, Style,
|
||||||
|
},
|
||||||
|
Table, Tabled,
|
||||||
|
};
|
||||||
|
#[derive(Tabled)]
|
||||||
|
struct Asset {
|
||||||
|
#[tabled(rename = "Path")]
|
||||||
|
original_file_path: String,
|
||||||
|
#[tabled(rename = "Is offline")]
|
||||||
|
is_offline: bool,
|
||||||
|
#[tabled(rename = "Camera")]
|
||||||
|
model: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn list_assets(offline: bool, client: &Client) -> Result<()> {
|
||||||
|
let query = AssetQuery {
|
||||||
|
is_offline: if offline { Some(true) } else { None },
|
||||||
|
with_exif: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut assets: Vec<_> = fetch_all_assets(query, client)
|
||||||
|
.await?
|
||||||
|
.into_iter()
|
||||||
|
.map(|asset| Asset {
|
||||||
|
is_offline: asset.is_offline,
|
||||||
|
model: asset
|
||||||
|
.exif_info
|
||||||
|
.clone()
|
||||||
|
.and_then(|exif| exif.model)
|
||||||
|
.unwrap_or(String::from("(Unknown)")),
|
||||||
|
original_file_path: asset.original_path,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
assets.sort_by_key(|asset| asset.original_file_path.clone());
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
Table::new(assets).with(Style::rounded()).modify(
|
||||||
|
Columns::single(1).not(Rows::first()),
|
||||||
|
Format::content(|s| {
|
||||||
|
match s {
|
||||||
|
"true" => "Yes".to_string(),
|
||||||
|
_ => "No".to_string(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod list_assets;
|
||||||
pub mod missing_date_of_birth;
|
pub mod missing_date_of_birth;
|
||||||
pub mod server_features;
|
pub mod server_features;
|
||||||
pub mod server_version;
|
pub mod server_version;
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
|
include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
|
||||||
|
|
||||||
use crate::args::Commands;
|
use crate::args::Commands;
|
||||||
use args::{PeopleCommands, ServerCommands};
|
use args::{AssetsCommands, PeopleCommands, ServerCommands};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use color_eyre::eyre::{Result, WrapErr};
|
use color_eyre::eyre::{Result, WrapErr};
|
||||||
use color_eyre::Section;
|
use color_eyre::Section;
|
||||||
|
use commands::list_assets::list_assets;
|
||||||
use commands::missing_date_of_birth::missing_date_of_birth;
|
use commands::missing_date_of_birth::missing_date_of_birth;
|
||||||
use commands::server_features::server_features;
|
use commands::server_features::server_features;
|
||||||
use commands::server_version::server_version;
|
use commands::server_version::server_version;
|
||||||
|
@ -52,6 +53,9 @@ async fn main() -> Result<()> {
|
||||||
validate_client_connection(&client).await?;
|
validate_client_connection(&client).await?;
|
||||||
|
|
||||||
match &args.command {
|
match &args.command {
|
||||||
|
Commands::Assets { assets_command } => match assets_command {
|
||||||
|
AssetsCommands::List { offline } => list_assets(*offline, &client).await,
|
||||||
|
},
|
||||||
Commands::People { people_command } => match people_command {
|
Commands::People { people_command } => match people_command {
|
||||||
PeopleCommands::MissingDateOfBirths {} => missing_date_of_birth(&client).await,
|
PeopleCommands::MissingDateOfBirths {} => missing_date_of_birth(&client).await,
|
||||||
PeopleCommands::SyncDateOfBirths { vcard: _ } => {
|
PeopleCommands::SyncDateOfBirths { vcard: _ } => {
|
||||||
|
|
|
@ -2,9 +2,26 @@ use crate::{
|
||||||
types::{AssetResponseDto, MetadataSearchDto},
|
types::{AssetResponseDto, MetadataSearchDto},
|
||||||
Client,
|
Client,
|
||||||
};
|
};
|
||||||
|
use chrono::{TimeZone, Utc};
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
|
use log::debug;
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct AssetQuery {
|
||||||
|
pub is_offline: Option<bool>,
|
||||||
|
pub with_exif: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn fetch_all_assets(query: AssetQuery, client: &Client) -> Result<Vec<AssetResponseDto>> {
|
||||||
|
debug!("Fetching assets with query {:?}", query);
|
||||||
|
|
||||||
|
// is_offline is ignored, let's fetch trashed assets instead and filter them later
|
||||||
|
let trashed_after = if query.is_offline == Some(true) {
|
||||||
|
Some(Utc.with_ymd_and_hms(1970, 1, 1, 0, 0, 0).unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
pub async fn fetch_all_assets(client: &Client) -> Result<Vec<AssetResponseDto>> {
|
|
||||||
let mut all_assets = Vec::new();
|
let mut all_assets = Vec::new();
|
||||||
let mut page_number = None;
|
let mut page_number = None;
|
||||||
let mut has_next_page = true;
|
let mut has_next_page = true;
|
||||||
|
@ -26,7 +43,7 @@ pub async fn fetch_all_assets(client: &Client) -> Result<Vec<AssetResponseDto>>
|
||||||
is_favorite: None,
|
is_favorite: None,
|
||||||
is_motion: None,
|
is_motion: None,
|
||||||
is_not_in_album: None,
|
is_not_in_album: None,
|
||||||
is_offline: None,
|
is_offline: query.is_offline,
|
||||||
is_visible: None,
|
is_visible: None,
|
||||||
lens_model: None,
|
lens_model: None,
|
||||||
library_id: None,
|
library_id: None,
|
||||||
|
@ -43,14 +60,14 @@ pub async fn fetch_all_assets(client: &Client) -> Result<Vec<AssetResponseDto>>
|
||||||
taken_after: None,
|
taken_after: None,
|
||||||
taken_before: None,
|
taken_before: None,
|
||||||
thumbnail_path: None,
|
thumbnail_path: None,
|
||||||
trashed_after: None,
|
trashed_after,
|
||||||
trashed_before: None,
|
trashed_before: None,
|
||||||
type_: None,
|
type_: None,
|
||||||
updated_after: None,
|
updated_after: None,
|
||||||
updated_before: None,
|
updated_before: None,
|
||||||
with_archived: true,
|
with_archived: true,
|
||||||
with_deleted: None,
|
with_deleted: None,
|
||||||
with_exif: None,
|
with_exif: Some(query.with_exif),
|
||||||
with_people: None,
|
with_people: None,
|
||||||
with_stacked: None,
|
with_stacked: None,
|
||||||
})
|
})
|
||||||
|
@ -64,5 +81,9 @@ pub async fn fetch_all_assets(client: &Client) -> Result<Vec<AssetResponseDto>>
|
||||||
.map(|page| page.parse::<f64>().unwrap());
|
.map(|page| page.parse::<f64>().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if query.is_offline == Some(true) {
|
||||||
|
all_assets.retain(|asset| asset.is_offline);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(all_assets)
|
Ok(all_assets)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue