Merge branch 'scan-libraries' into 'main'
Add a libraries command and scan subcommand See merge request kernald/immich-tools!23
This commit is contained in:
commit
be4734e5b6
9 changed files with 182 additions and 1 deletions
31
src/actions/fetch_all_libraries.rs
Normal file
31
src/actions/fetch_all_libraries.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use color_eyre::eyre::Result;
|
||||
|
||||
use crate::{context::Context, models::library::Library};
|
||||
|
||||
use super::action::Action;
|
||||
|
||||
pub struct FetchAllLibraries {}
|
||||
|
||||
impl Action for FetchAllLibraries {
|
||||
type Input = ();
|
||||
type Output = Vec<Library>;
|
||||
|
||||
fn new(_input: Self::Input) -> Self {
|
||||
Self {}
|
||||
}
|
||||
|
||||
fn describe(&self) -> String {
|
||||
String::from("Fetching all libraries")
|
||||
}
|
||||
|
||||
async fn execute(&self, ctx: &Context) -> Result<Self::Output> {
|
||||
Ok(ctx
|
||||
.client
|
||||
.get_all_libraries()
|
||||
.await?
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
.collect())
|
||||
}
|
||||
}
|
|
@ -2,5 +2,7 @@ pub mod action;
|
|||
pub mod confirm;
|
||||
pub mod fetch_album_assets;
|
||||
pub mod fetch_all_albums;
|
||||
pub mod fetch_all_libraries;
|
||||
pub mod fetch_all_persons;
|
||||
pub mod scan_library;
|
||||
pub mod update_person_date_of_birth;
|
||||
|
|
27
src/actions/scan_library.rs
Normal file
27
src/actions/scan_library.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use color_eyre::eyre::Result;
|
||||
|
||||
use crate::{context::Context, models::library::Library};
|
||||
|
||||
use super::action::Action;
|
||||
|
||||
pub struct ScanLibrary {
|
||||
library: Library,
|
||||
}
|
||||
|
||||
impl Action for ScanLibrary {
|
||||
type Input = Library;
|
||||
type Output = ();
|
||||
|
||||
fn new(input: Self::Input) -> Self {
|
||||
Self { library: input }
|
||||
}
|
||||
|
||||
fn describe(&self) -> String {
|
||||
format!("Scanning library {}", self.library.name)
|
||||
}
|
||||
|
||||
async fn execute(&self, ctx: &Context) -> Result<Self::Output> {
|
||||
ctx.client.scan_library(&self.library.id).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
15
src/args.rs
15
src/args.rs
|
@ -44,6 +44,14 @@ pub(crate) enum Commands {
|
|||
assets_command: AssetsCommands,
|
||||
},
|
||||
|
||||
/// Libraries related commands
|
||||
#[serde(rename = "libaries")]
|
||||
Libraries {
|
||||
#[command(subcommand)]
|
||||
#[serde(flatten)]
|
||||
libraries_command: LibrariesCommands,
|
||||
},
|
||||
|
||||
/// People related commands
|
||||
#[serde(rename = "people")]
|
||||
People {
|
||||
|
@ -78,6 +86,13 @@ pub(crate) enum AssetsCommands {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Subcommand)]
|
||||
pub(crate) enum LibrariesCommands {
|
||||
/// Scan all libraries
|
||||
#[serde(rename = "scan")]
|
||||
Scan {},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Subcommand)]
|
||||
pub(crate) enum PeopleCommands {
|
||||
/// Synchronises date of births from a vcard file
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pub mod delete_assets;
|
||||
pub mod list_assets;
|
||||
pub mod missing_date_of_birth;
|
||||
pub mod scan_libraries;
|
||||
pub mod server_features;
|
||||
pub mod server_version;
|
||||
pub mod sync_date_of_birth;
|
||||
|
|
17
src/commands/scan_libraries.rs
Normal file
17
src/commands/scan_libraries.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
use color_eyre::eyre::Result;
|
||||
use log::*;
|
||||
|
||||
use crate::actions::action::Action;
|
||||
use crate::actions::scan_library::ScanLibrary;
|
||||
use crate::{actions::fetch_all_libraries::FetchAllLibraries, context::Context};
|
||||
|
||||
pub async fn scan_libraries(ctx: Context) -> Result<()> {
|
||||
let libraries = FetchAllLibraries::new(()).execute(&ctx).await?;
|
||||
|
||||
for library in libraries {
|
||||
debug!("Scanning {}", library.name);
|
||||
ScanLibrary::new(library).execute(&ctx).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -9,13 +9,14 @@ mod tests {
|
|||
}
|
||||
|
||||
use crate::args::Commands;
|
||||
use args::{AssetsCommands, PeopleCommands, ServerCommands};
|
||||
use args::{AssetsCommands, LibrariesCommands, PeopleCommands, ServerCommands};
|
||||
use clap::Parser;
|
||||
use color_eyre::eyre::{Result, WrapErr};
|
||||
use color_eyre::Section;
|
||||
use commands::delete_assets::delete_assets;
|
||||
use commands::list_assets::list_assets;
|
||||
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;
|
||||
|
@ -79,6 +80,9 @@ async fn main() -> Result<()> {
|
|||
AssetsCommands::Delete { offline } => delete_assets(ctx, *offline).await,
|
||||
AssetsCommands::List { offline } => list_assets(ctx, *offline).await,
|
||||
},
|
||||
Commands::Libraries { libraries_command } => match libraries_command {
|
||||
LibrariesCommands::Scan {} => scan_libraries(ctx).await,
|
||||
},
|
||||
Commands::People { people_command } => match people_command {
|
||||
PeopleCommands::MissingDateOfBirths {} => missing_date_of_birth(ctx).await,
|
||||
PeopleCommands::SyncDateOfBirths { vcard: _ } => {
|
||||
|
|
83
src/models/library.rs
Normal file
83
src/models/library.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::types::LibraryResponseDto;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Library {
|
||||
pub id: Uuid,
|
||||
pub name: String,
|
||||
pub asset_count: i64,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub refreshed_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
impl From<LibraryResponseDto> for Library {
|
||||
fn from(value: LibraryResponseDto) -> Self {
|
||||
Self {
|
||||
id: Uuid::parse_str(&value.id).expect("Unable to parse a library's UUID"),
|
||||
name: value.name,
|
||||
asset_count: value.asset_count,
|
||||
updated_at: value.updated_at,
|
||||
refreshed_at: value.refreshed_at,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn from_library_response_dto_success() {
|
||||
let dto = LibraryResponseDto {
|
||||
id: String::from("123e4567-e89b-12d3-a456-426655440000"),
|
||||
name: String::from("Christmas photos"),
|
||||
asset_count: 1246,
|
||||
exclusion_patterns: vec![],
|
||||
import_paths: vec![],
|
||||
owner_id: String::from("abc123"),
|
||||
updated_at: DateTime::<Utc>::from_str("2024-11-17T12:55:12Z").unwrap(),
|
||||
created_at: DateTime::<Utc>::from_str("2023-10-17T12:55:12Z").unwrap(),
|
||||
refreshed_at: Some(DateTime::<Utc>::from_str("2024-11-17T12:53:12Z").unwrap()),
|
||||
};
|
||||
|
||||
let library = Library::from(dto);
|
||||
|
||||
assert_eq!(
|
||||
library.id,
|
||||
Uuid::parse_str("123e4567-e89b-12d3-a456-426655440000").unwrap()
|
||||
);
|
||||
assert_eq!(library.name, "Christmas photos".to_string());
|
||||
assert_eq!(library.asset_count, 1246);
|
||||
assert_eq!(
|
||||
library.updated_at,
|
||||
DateTime::<Utc>::from_str("2024-11-17T12:55:12Z").unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
library.refreshed_at,
|
||||
Some(DateTime::<Utc>::from_str("2024-11-17T12:53:12Z").unwrap())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn from_library_response_dto_invalid_uuid_panics() {
|
||||
let dto = LibraryResponseDto {
|
||||
id: String::from("invalid_uuid"),
|
||||
name: String::from("Christmas photos"),
|
||||
asset_count: 1246,
|
||||
exclusion_patterns: vec![],
|
||||
import_paths: vec![],
|
||||
owner_id: String::from("abc123"),
|
||||
updated_at: DateTime::<Utc>::from_str("2024-11-17T12:55:12Z").unwrap(),
|
||||
created_at: DateTime::<Utc>::from_str("2023-10-17T12:55:12Z").unwrap(),
|
||||
refreshed_at: Some(DateTime::<Utc>::from_str("2024-11-17T12:53:12Z").unwrap()),
|
||||
};
|
||||
|
||||
let _ = Library::from(dto);
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
pub mod album;
|
||||
pub mod asset;
|
||||
pub mod library;
|
||||
pub mod person;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue