use std::{collections::HashSet, process::{Command, Stdio}}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::artifacts::{Artifact, SourceID, Track}; #[derive(Debug, Default, Serialize, Deserialize, Clone, JsonSchema)] pub struct BeatsQueryArgs { artist: Option, album: Option, genre: Option, title: Option, year: Option } #[derive(Debug, Default, Deserialize)] struct BeetsTrack { album: String, artist: String, genres: Option>, label: Option, title: String, year: u32, mb_trackid: Option } impl Into for BeetsTrack { fn into(self) -> Artifact { let sources = if let Some(mbid) = self.mb_trackid { HashSet::from([SourceID::Beets, SourceID::Musicbrainz(mbid)]) } else { HashSet::from([SourceID::Beets]) }; Artifact::Track(Track { title: self.title, label: self.label, year: Some(self.year), genres: self.genres.unwrap_or_default(), album: Some(self.album), artist: Some(self.artist), bpm: None, sources }) } } impl BeatsQueryArgs { pub fn execute(self) -> Result, ()> { let mut beets_cmd = Command::new("beet"); beets_cmd.args(["export", "-f", "json", "-i", "title,label,year,genres,album,artist,mb_trackid"]); let mut valid = false; if let Some(artist) = self.artist { beets_cmd.arg(format!("artist:{}", artist)); valid = true; } if let Some(genre) = self.genre { beets_cmd.arg(format!("genre:{}", genre)); valid = true; } if let Some(album) = self.album { beets_cmd.arg(format!("album:{}", album)); valid = true; } if let Some(title) = self.title { beets_cmd.arg(format!("title:{}", title)); valid = true; } if let Some(year) = self.year { beets_cmd.arg(format!("year:{}", year)); valid = true; } if !valid { log::warn!("Tried to execute an empty beets query"); return Err(()) } log::debug!("Executing beets: {:?}", beets_cmd); if let Ok(output) = beets_cmd.stdout(Stdio::piped()).stderr(Stdio::null()).spawn().unwrap().wait_with_output() { match serde_json::from_str::>(str::from_utf8(&output.stdout).unwrap()) { Ok(track) => Ok(track.into_iter().map(|t| { t.into()}).collect()), Err(err) => { log::error!("Failed to decode beets json: {:?}", err); Err(()) } } } else { log::error!("Unable to execute query!"); Err(()) } } }