add get-tags and set-tags commands and fix error on no extension

This commit is contained in:
Chaos 2022-12-14 14:08:46 +00:00
parent 3eb010b21c
commit e57ea88b22
No known key found for this signature in database
9 changed files with 198 additions and 17 deletions

View file

@ -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": {

View file

@ -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<String>,
#[clap(long)]
pub title: Option<String>,
#[clap(long)]
pub artist: Option<String>,
}
#[derive(Debug, Clone, Args)]
pub struct GetTagsCommandArgs {
pub files: Vec<String>,
#[clap(long)]
pub json: bool,
}

70
src/commands/get_tags.rs Normal file
View file

@ -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<dyn std::error::Error>> {
let mut files: Vec<File> = 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<String, Tags> = 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(())
}

View file

@ -1,4 +1,6 @@
pub mod copy;
pub mod genhtml;
pub mod get_tags;
pub mod process;
pub mod set_tags;
pub mod transcode;

71
src/commands/set_tags.rs Normal file
View file

@ -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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
let mut files: Vec<File> = 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(())
}

View file

@ -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<dyn std::error::Error>> {
@ -28,6 +30,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
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");
}

View file

@ -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();

View file

@ -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")
}

View file

@ -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()));
}