use crate::json_parsing; use audiotags::Tag; use std::fs; use std::path::Path; use std::time::Duration; use thiserror::Error; #[derive(Debug)] pub struct TrackInfo { pub track_name: String, pub artist_name: String, pub album_name: String, pub duration: Duration, } #[derive(Debug, Error)] pub enum MusicError { #[error("failed to read directory: {0}")] ReadDir(#[from] std::io::Error), #[error("failed to read audio tags from {0}")] TagRead(String), #[error("failed to get song duration for {0}")] DurationRead(String), } fn is_mp3(path: &Path) -> bool { path.extension() .and_then(|ext| ext.to_str()) .map(|ext| ext.eq_ignore_ascii_case("mp3")) .unwrap_or(false) } pub fn get_song_file(path: &Path) -> Result<(), MusicError> { if !is_mp3(path) { return Ok(()); } let info = get_song_info(path)?; println!("Track: {}", info.track_name); println!("Artist: {}", info.artist_name); println!("Album: {}", info.album_name); println!("Duration: {:?}\n", info.duration); json_parsing::get_lyrics_text( &info.artist_name, &info.track_name, &info.album_name, info.duration, ); Ok(()) } pub fn get_all_music_files(directory: &Path) -> Result<(), MusicError> { if !directory.is_dir() { return Ok(()); } for entry in fs::read_dir(directory)? { let entry = entry?; let path = entry.path(); if entry.file_type()?.is_dir() { get_all_music_files(&path)?; } else if let Err(e) = get_song_file(&path) { eprintln!("Skipping file {}: {}", path.display(), e); } } Ok(()) } pub fn get_song_info(path: &Path) -> Result { let tag = Tag::new() .read_from_path(path) .map_err(|_| MusicError::TagRead(path.display().to_string()))?; let track_name = tag.title().unwrap_or("Unknown Track").to_string(); let artist_name = tag.artist().unwrap_or("Unknown Artist").to_string(); let album_name = tag .album() .map_or("Unknown Album".to_string(), |a| a.title.to_string()); let duration = get_song_length(path)?; Ok(TrackInfo { track_name, artist_name, album_name, duration, }) } pub fn get_song_length(path: &Path) -> Result { mp3_duration::from_path(path).map_err(|_| MusicError::DurationRead(path.display().to_string())) }