All checks were successful
		
		
	
	Checking Renovate configuration / validate (pull_request) Successful in 1m37s
				
			Build and test / Tests (pull_request) Successful in 1m52s
				
			Build and test / Clippy (pull_request) Successful in 1m52s
				
			Checking yaml / Run yamllint (pull_request) Successful in 3s
				
			Build and test / Build AMD64 (pull_request) Successful in 1m53s
				
			Build and test / Generate Documentation (pull_request) Successful in 1m53s
				
			
		
			
				
	
	
		
			143 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			143 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
include!(concat!(env!("OUT_DIR"), "/client.rs"));
 | 
						|
 | 
						|
#[cfg(test)]
 | 
						|
mod tests {
 | 
						|
    #[allow(dead_code)]
 | 
						|
    pub mod apimock {
 | 
						|
        include!(concat!(env!("OUT_DIR"), "/mock.rs"));
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
use crate::args::Commands;
 | 
						|
use args::{AlbumsCommands, AssetsCommands, LibrariesCommands, PeopleCommands, ServerCommands};
 | 
						|
use clap::Parser;
 | 
						|
use color_eyre::eyre::{Result, WrapErr};
 | 
						|
use color_eyre::Section;
 | 
						|
use commands::auto_create_albums::auto_create_albums;
 | 
						|
use commands::delete_albums::delete_albums;
 | 
						|
use commands::delete_assets::delete_assets;
 | 
						|
use commands::list_albums::list_albums;
 | 
						|
use commands::list_assets::list_assets;
 | 
						|
use commands::list_libraries::list_libraries;
 | 
						|
use commands::missing_date_of_birth::missing_date_of_birth;
 | 
						|
use commands::scan_libraries::scan_libraries;
 | 
						|
use commands::server_features::server_features;
 | 
						|
use commands::server_version::server_version;
 | 
						|
use commands::sync_date_of_birth::sync_date_of_birth;
 | 
						|
use config::Config;
 | 
						|
use context::Context;
 | 
						|
use directories::ProjectDirs;
 | 
						|
use figment::providers::{Env, Format, Serialized, Toml};
 | 
						|
use figment::Figment;
 | 
						|
use figment_file_provider_adapter::FileAdapter;
 | 
						|
use log::*;
 | 
						|
use reqwest::header;
 | 
						|
 | 
						|
mod actions;
 | 
						|
mod args;
 | 
						|
mod commands;
 | 
						|
mod config;
 | 
						|
mod context;
 | 
						|
mod models;
 | 
						|
mod utils;
 | 
						|
 | 
						|
#[tokio::main]
 | 
						|
async fn main() -> Result<()> {
 | 
						|
    color_eyre::install()?;
 | 
						|
 | 
						|
    let args = args::Opts::parse();
 | 
						|
 | 
						|
    pretty_env_logger::formatted_timed_builder()
 | 
						|
        .filter_level(args.verbose.log_level_filter())
 | 
						|
        .init();
 | 
						|
 | 
						|
    let mut conf_extractor = Figment::new();
 | 
						|
    if let Some(project_dirs) = ProjectDirs::from("fr", "enoent", "Immich Tools") {
 | 
						|
        let config_file_path = project_dirs.config_dir().join("config.toml");
 | 
						|
        if config_file_path.exists() {
 | 
						|
            debug!("Reading configuration from {config_file_path:?}");
 | 
						|
            conf_extractor =
 | 
						|
                conf_extractor.merge(FileAdapter::wrap(Toml::file_exact(config_file_path)));
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        warn!("Unable to determine configuration file path");
 | 
						|
    }
 | 
						|
 | 
						|
    let conf: Config = conf_extractor
 | 
						|
        .merge(FileAdapter::wrap(Env::prefixed("IMMICH_TOOLS_")))
 | 
						|
        .merge(Serialized::defaults(&args))
 | 
						|
        .extract()
 | 
						|
        .wrap_err_with(|| "Invalid configuration or insufficient command line arguments")?;
 | 
						|
 | 
						|
    let client = get_client(&conf.server_url, &conf.api_key)?;
 | 
						|
 | 
						|
    let ctx = Context::builder()
 | 
						|
        .client(client)
 | 
						|
        .dry_run(args.dry_run)
 | 
						|
        .no_confirm(args.no_confirm)
 | 
						|
        .build();
 | 
						|
 | 
						|
    validate_client_connection(&ctx.client).await?;
 | 
						|
 | 
						|
    match &args.command {
 | 
						|
        Commands::Albums { albums_command } => match albums_command {
 | 
						|
            AlbumsCommands::AutoCreate {
 | 
						|
                album_name_separator,
 | 
						|
            } => auto_create_albums(ctx, album_name_separator.to_string()).await,
 | 
						|
            AlbumsCommands::Delete { empty } => delete_albums(ctx, *empty).await,
 | 
						|
            AlbumsCommands::List {} => list_albums(ctx).await,
 | 
						|
        },
 | 
						|
        Commands::Assets { assets_command } => match assets_command {
 | 
						|
            AssetsCommands::Delete { offline } => delete_assets(ctx, *offline).await,
 | 
						|
            AssetsCommands::List { offline } => list_assets(ctx, *offline).await,
 | 
						|
        },
 | 
						|
        Commands::Libraries { libraries_command } => match libraries_command {
 | 
						|
            LibrariesCommands::List {} => list_libraries(ctx).await,
 | 
						|
            LibrariesCommands::Scan {} => scan_libraries(ctx).await,
 | 
						|
        },
 | 
						|
        Commands::People { people_command } => match people_command {
 | 
						|
            PeopleCommands::MissingDateOfBirths {} => missing_date_of_birth(ctx).await,
 | 
						|
            PeopleCommands::SyncDateOfBirths { vcard: _ } => {
 | 
						|
                sync_date_of_birth(ctx, &conf.people.sync_date_of_births.vcard).await
 | 
						|
            }
 | 
						|
        },
 | 
						|
        Commands::Server { server_command } => match server_command {
 | 
						|
            ServerCommands::Features {} => server_features(ctx).await,
 | 
						|
            ServerCommands::Version {} => server_version(ctx).await,
 | 
						|
        },
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
fn get_client(url: &str, api_key: &str) -> Result<Client> {
 | 
						|
    let mut headers = header::HeaderMap::new();
 | 
						|
 | 
						|
    let mut auth_value = header::HeaderValue::from_str(api_key)?;
 | 
						|
    auth_value.set_sensitive(true);
 | 
						|
    headers.insert("x-api-key", auth_value);
 | 
						|
 | 
						|
    Ok(Client::new_with_client(
 | 
						|
        url,
 | 
						|
        reqwest::Client::builder()
 | 
						|
            .default_headers(headers)
 | 
						|
            .build()
 | 
						|
            .unwrap(),
 | 
						|
    ))
 | 
						|
}
 | 
						|
 | 
						|
async fn validate_client_connection(client: &Client) -> Result<()> {
 | 
						|
    client
 | 
						|
        .validate_access_token()
 | 
						|
        .await
 | 
						|
        .wrap_err_with(|| "Unable to connect to Immich")
 | 
						|
        .with_suggestion(|| "The API key might be invalid")
 | 
						|
        .with_suggestion(|| "There server URL might be invalid, it should likely end in /api")
 | 
						|
        .with_note(|| format!("The provided server URL was {}", client.baseurl()))
 | 
						|
        .with_note(|| {
 | 
						|
            format!(
 | 
						|
                "The API version for this client is {}, make sure the server version is compatible",
 | 
						|
                Client::api_version()
 | 
						|
            )
 | 
						|
        })?;
 | 
						|
 | 
						|
    Ok(())
 | 
						|
}
 |