Add an assets list command
This commit is contained in:
		
							parent
							
								
									a8796b2728
								
							
						
					
					
						commit
						c026375ce1
					
				
					 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;
 | 
				
			||||||
| 
						 | 
					@ -51,6 +52,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