Merge branch 'actions-refactor' into 'main'

Continue actions refactoring

See merge request kernald/immich-tools!22
This commit is contained in:
Marc Plano-Lesay 2024-11-08 15:33:08 +00:00
commit 2eb4e391c2
10 changed files with 162 additions and 38 deletions

43
src/actions/confirm.rs Normal file
View file

@ -0,0 +1,43 @@
use color_eyre::eyre::Result;
use dialoguer::theme::ColorfulTheme;
use crate::context::Context;
use super::action::Action;
pub struct Confirm<'a> {
prompt: &'a str,
}
pub enum ConfirmResult {
Positive,
Negative,
}
impl<'a> Action for Confirm<'a> {
type Input = Option<&'a str>;
type Output = ConfirmResult;
fn new(input: Self::Input) -> Self {
Self {
prompt: input.unwrap_or("Do you want to continue?"),
}
}
fn describe(&self) -> String {
String::from("Requesting confirmation")
}
async fn execute(&self, ctx: &Context) -> Result<Self::Output> {
if ctx.dry_run
|| ctx.no_confirm
|| dialoguer::Confirm::with_theme(&ColorfulTheme::default())
.with_prompt(self.prompt)
.interact()?
{
Ok(ConfirmResult::Positive)
} else {
Ok(ConfirmResult::Negative)
}
}
}

View file

@ -0,0 +1,38 @@
use color_eyre::eyre::Result;
use crate::{
context::Context,
models::{album::Album, asset::Asset},
};
use super::action::Action;
pub struct FetchAlbumAssets {
album: Album,
}
impl Action for FetchAlbumAssets {
type Input = Album;
type Output = Vec<Asset>;
fn new(input: Self::Input) -> Self {
Self { album: input }
}
fn describe(&self) -> String {
// TODO: derive Display for Album and use this here
format!("Fetching all assets for album {}", self.album.name)
}
async fn execute(&self, ctx: &Context) -> Result<Self::Output> {
Ok(ctx
.client
.get_album_info(&self.album.id, None, Some(false))
.await?
.assets
.clone()
.into_iter()
.map(Into::into)
.collect())
}
}

View file

@ -0,0 +1,31 @@
use color_eyre::eyre::Result;
use crate::{context::Context, models::album::Album};
use super::action::Action;
pub struct FetchAllAlbums {}
impl Action for FetchAllAlbums {
type Input = ();
type Output = Vec<Album>;
fn new(_input: Self::Input) -> Self {
Self {}
}
fn describe(&self) -> String {
String::from("Fetching all albums")
}
async fn execute(&self, ctx: &Context) -> Result<Self::Output> {
Ok(ctx
.client
.get_all_albums(None, None)
.await?
.clone()
.into_iter()
.map(Into::into)
.collect())
}
}

View file

@ -1,3 +1,6 @@
pub mod action; pub mod action;
pub mod confirm;
pub mod fetch_album_assets;
pub mod fetch_all_albums;
pub mod fetch_all_persons; pub mod fetch_all_persons;
pub mod update_person_date_of_birth; pub mod update_person_date_of_birth;

View file

@ -1,9 +1,12 @@
use crate::{ use crate::{
actions::{
action::Action,
confirm::{Confirm, ConfirmResult},
},
context::Context, context::Context,
utils::assets::{fetch_all_assets, AssetQuery}, utils::assets::{fetch_all_assets, AssetQuery},
}; };
use color_eyre::eyre::Result; use color_eyre::eyre::Result;
use dialoguer::{theme::ColorfulTheme, Confirm};
use log::info; use log::info;
use uuid::Uuid; use uuid::Uuid;
@ -22,15 +25,7 @@ pub async fn delete_assets(ctx: Context, offline: bool) -> Result<()> {
); );
} }
if !ctx.dry_run { if let ConfirmResult::Positive = Confirm::new(None).execute(&ctx).await? {
if !(ctx.no_confirm
|| Confirm::with_theme(&ColorfulTheme::default())
.with_prompt("Do you want to continue?")
.interact()?)
{
return Ok(());
}
let asset_ids: Result<Vec<_>, uuid::Error> = assets let asset_ids: Result<Vec<_>, uuid::Error> = assets
.iter() .iter()
.map(|asset| Uuid::parse_str(&asset.id)) .map(|asset| Uuid::parse_str(&asset.id))
@ -41,13 +36,13 @@ pub async fn delete_assets(ctx: Context, offline: bool) -> Result<()> {
ids: asset_ids?, ids: asset_ids?,
}) })
.await?; .await?;
}
info!( info!(
"Deleted {} assets{}", "Deleted {} assets{}",
assets.len(), assets.len(),
if ctx.dry_run { " (dry run)" } else { "" } if ctx.dry_run { " (dry run)" } else { "" }
); );
}
Ok(()) Ok(())
} }

18
src/models/album.rs Normal file
View file

@ -0,0 +1,18 @@
use uuid::Uuid;
use crate::types::AlbumResponseDto;
#[derive(Debug, Clone)]
pub struct Album {
pub id: Uuid,
pub name: String,
}
impl From<AlbumResponseDto> for Album {
fn from(value: AlbumResponseDto) -> Self {
Self {
id: Uuid::parse_str(&value.id).expect("Unable to parse an album's UUID"),
name: value.album_name,
}
}
}

16
src/models/asset.rs Normal file
View file

@ -0,0 +1,16 @@
use uuid::Uuid;
use crate::types::AssetResponseDto;
#[derive(Debug, Clone)]
pub struct Asset {
pub id: Uuid,
}
impl From<AssetResponseDto> for Asset {
fn from(value: AssetResponseDto) -> Self {
Self {
id: Uuid::parse_str(&value.id).expect("Unable to parse an asset's UUID"),
}
}
}

View file

@ -1 +1,3 @@
pub mod album;
pub mod asset;
pub mod person; pub mod person;

View file

@ -1,21 +0,0 @@
use crate::{
types::{AlbumResponseDto, AssetResponseDto},
Client,
};
use color_eyre::eyre::Result;
use uuid::Uuid;
pub async fn fetch_all_albums(client: &Client) -> Result<Vec<AlbumResponseDto>> {
Ok(client.get_all_albums(None, None).await?.to_vec())
}
pub async fn fetch_album_assets(
album_uuid: &Uuid,
client: &Client,
) -> Result<Vec<AssetResponseDto>> {
Ok(client
.get_album_info(album_uuid, None, Some(false))
.await?
.assets
.clone())
}

View file

@ -1,2 +1 @@
pub mod albums;
pub mod assets; pub mod assets;