From e57ea88b2225cb5a7ac5af474578de0b04985783 Mon Sep 17 00:00:00 2001 From: Chaos Date: Wed, 14 Dec 2022 14:08:46 +0000 Subject: [PATCH] add get-tags and set-tags commands and fix error on no extension --- flake.lock | 18 +++++----- src/args.rs | 18 ++++++++++ src/commands/get_tags.rs | 70 +++++++++++++++++++++++++++++++++++++ src/commands/mod.rs | 2 ++ src/commands/set_tags.rs | 71 ++++++++++++++++++++++++++++++++++++++ src/main.rs | 8 +++++ src/types.rs | 14 ++++---- src/utils/mod.rs | 6 +++- src/utils/music_scanner.rs | 8 ++++- 9 files changed, 198 insertions(+), 17 deletions(-) create mode 100644 src/commands/get_tags.rs create mode 100644 src/commands/set_tags.rs diff --git a/flake.lock b/flake.lock index 91bb353..79f2be0 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1650374568, - "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "lastModified": 1668681692, + "narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=", "owner": "edolstra", "repo": "flake-compat", - "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "rev": "009399224d5e398d03b22badca40a37ac85412a1", "type": "github" }, "original": { @@ -18,11 +18,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1666401273, - "narHash": "sha256-AG3MoIjcWwz1SPjJ2nymWu4NmeVj9P40OpB1lsmxFtg=", + "lastModified": 1670980281, + "narHash": "sha256-g0t/SmQca/JBEd+3Ry1qFgDfDK8ME9AM6EP4YUl8/lo=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3933d8bb9120573c0d8d49dc5e890cb211681490", + "rev": "5cb48ea3c19ce2e5746a44d6b91847396bd28c1f", "type": "github" }, "original": { @@ -41,11 +41,11 @@ }, "utils": { "locked": { - "lastModified": 1659877975, - "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", "owner": "numtide", "repo": "flake-utils", - "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "type": "github" }, "original": { diff --git a/src/args.rs b/src/args.rs index a6825df..0812430 100644 --- a/src/args.rs +++ b/src/args.rs @@ -13,6 +13,8 @@ pub enum Commands { Genhtml(GenHTMLCommandArgs), Transcode(TranscodeCommandArgs), Copy(CopyCommandArgs), + SetTags(SetTagsCommandArgs), + GetTags(GetTagsCommandArgs), } #[derive(Debug, Args)] @@ -65,3 +67,19 @@ pub struct CopyCommandArgs { #[clap(long)] pub single_directory: bool, } + +#[derive(Debug, Clone, Args)] +pub struct SetTagsCommandArgs { + pub files: Vec, + #[clap(long)] + pub title: Option, + #[clap(long)] + pub artist: Option, +} + +#[derive(Debug, Clone, Args)] +pub struct GetTagsCommandArgs { + pub files: Vec, + #[clap(long)] + pub json: bool, +} diff --git a/src/commands/get_tags.rs b/src/commands/get_tags.rs new file mode 100644 index 0000000..bd45503 --- /dev/null +++ b/src/commands/get_tags.rs @@ -0,0 +1,70 @@ +use std::collections::HashMap; +use std::path::PathBuf; + +use serde::Serialize; + +use crate::args::CLIArgs; +use crate::args::GetTagsCommandArgs; +use crate::types::File; +use crate::utils::extract_tags_from_file; + +#[derive(Debug, Clone, Serialize)] +struct Tags { + title: String, + artist: String, +} + +fn from_main_tags(tags: &crate::types::Tags) -> Tags { + Tags { + title: tags.title.clone(), + artist: tags.artist.clone(), + } +} + +pub fn get_tags_command( + _args: &CLIArgs, + get_tags_args: &GetTagsCommandArgs, +) -> Result<(), Box> { + let mut files: Vec = Vec::new(); + + for file in get_tags_args.files.iter() { + files.push(File::from_path("".to_string(), PathBuf::from(file))); + } + + for file in files.iter_mut() { + let tags = extract_tags_from_file(file.clone())?; + file.tags = tags; + } + + if files.len() == 1 { + let file = files.first().unwrap(); + + if get_tags_args.json { + println!( + "{}", + serde_json::to_string_pretty(&from_main_tags(&file.tags)).unwrap() + ); + } else { + println!("{:#?}", from_main_tags(&file.tags)); + } + } else if get_tags_args.json { + let mut result: HashMap = HashMap::new(); + for file in files.iter() { + result.insert( + file.join_path_to().to_string_lossy().to_string(), + from_main_tags(&file.tags), + ); + } + println!("{}", serde_json::to_string_pretty(&result)?); + } else { + for file in files.iter() { + println!( + "{}: {:#?}", + file.join_path_to().to_string_lossy(), + from_main_tags(&file.tags) + ); + } + } + + Ok(()) +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index c7afac4..6abb9cd 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,4 +1,6 @@ pub mod copy; pub mod genhtml; +pub mod get_tags; pub mod process; +pub mod set_tags; pub mod transcode; diff --git a/src/commands/set_tags.rs b/src/commands/set_tags.rs new file mode 100644 index 0000000..9ba2164 --- /dev/null +++ b/src/commands/set_tags.rs @@ -0,0 +1,71 @@ +use std::path::PathBuf; + +use id3::TagLike; + +use crate::args::CLIArgs; +use crate::args::SetTagsCommandArgs; +use crate::types::File; + +pub fn tag_mp3( + file: &File, + add_tags_args: &SetTagsCommandArgs, +) -> Result<(), Box> { + let mut tag = id3::Tag::read_from_path(file.join_path_to())?; + + if let Some(title) = &add_tags_args.title { + tag.set_title(title); + } + + if let Some(artist) = &add_tags_args.artist { + tag.set_artist(artist); + } + + tag.write_to_path(file.join_path_to(), id3::Version::Id3v24)?; + + Ok(()) +} + +pub fn tag_flac( + file: &File, + add_tags_args: &SetTagsCommandArgs, +) -> Result<(), Box> { + let mut tag = metaflac::Tag::read_from_path(file.join_path_to())?; + + if let Some(title) = &add_tags_args.title { + tag.remove_vorbis("TITLE"); + tag.set_vorbis("TITLE", vec![title]); + } + + if let Some(artist) = &add_tags_args.artist { + tag.remove_vorbis("ARTIST"); + tag.set_vorbis("ARTIST", vec![artist]); + } + + tag.write_to_path(file.join_path_to())?; + + Ok(()) +} + +pub fn set_tags_command( + _args: &CLIArgs, + add_tags_args: &SetTagsCommandArgs, +) -> Result<(), Box> { + let mut files: Vec = Vec::new(); + + for file in add_tags_args.files.iter() { + files.push(File::from_path("".to_string(), PathBuf::from(file))); + } + + for file in files.iter() { + match file.extension.as_str() { + "mp3" => tag_mp3(file, add_tags_args)?, + "flac" => tag_flac(file, add_tags_args)?, + _ => panic!( + "Invalid File Extension for {}", + file.join_path_to().to_string_lossy() + ), + } + } + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index a82a6ac..8657666 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,9 @@ use clap::Parser; use commands::copy::copy_command; use commands::genhtml::genhtml_command; +use commands::get_tags::get_tags_command; use commands::process::process_command; +use commands::set_tags::set_tags_command; use commands::transcode::transcode_command; fn main() -> Result<(), Box> { @@ -28,6 +30,12 @@ fn main() -> Result<(), Box> { Some(Commands::Copy(copy_args)) => { copy_command(&cli, copy_args)?; } + Some(Commands::SetTags(set_tags_args)) => { + set_tags_command(&cli, set_tags_args)?; + } + Some(Commands::GetTags(get_tags_args)) => { + get_tags_command(&cli, get_tags_args)?; + } None => { panic!("please provide a subcommand"); } diff --git a/src/types.rs b/src/types.rs index 751a800..6a1f7b9 100644 --- a/src/types.rs +++ b/src/types.rs @@ -30,12 +30,14 @@ impl File { .to_str() .unwrap() .to_string(); - let extension = full_file_path - .extension() - .unwrap() - .to_str() - .unwrap() - .to_string(); + + let extension = full_file_path.extension(); + + let extension = if let Some(extension) = extension { + extension.to_str().unwrap().to_string() + } else { + "".to_string() + }; let path_from_src = full_file_path.strip_prefix(&source_dir).unwrap(); diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 0bf548b..fb69cb4 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -10,7 +10,11 @@ pub use music_scanner::scan_for_music; pub use tag_extractor::extract_tags_from_file; pub fn is_supported_file_extension(file_path: &Path) -> bool { - let ext = file_path.extension().unwrap().to_str().unwrap(); + let ext = file_path.extension(); + if ext.is_none() { + return false; + } + let ext = ext.unwrap().to_str().unwrap(); matches!(ext, "mp3" | "flac") } diff --git a/src/utils/music_scanner.rs b/src/utils/music_scanner.rs index 4822dc3..ff826cc 100644 --- a/src/utils/music_scanner.rs +++ b/src/utils/music_scanner.rs @@ -17,8 +17,14 @@ pub fn find_extra_files( continue; } let entry_path = entry.path(); + + let extension = entry_path.extension(); + if extension.is_none() { + continue; + } + if entry_path.file_stem().unwrap().to_string_lossy() == file.filename - && entry_path.extension().unwrap().to_string_lossy() != file.extension + && extension.unwrap().to_string_lossy() != file.extension { extra_files.push(File::from_path(src_dir.clone(), entry_path.clone())); }