artifacts: rewrite the entire artifact querying layer to create modular 'tools' and 'datasource's
This commit is contained in:
+65
-22
@@ -1,18 +1,19 @@
|
||||
use std::{collections::HashSet, process::{Command, Stdio}};
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::artifacts::{Artifact, SourceID, Track};
|
||||
use crate::artifacts::{Artifact, ArtifactBuilder, Contents, Merge, SourceID, Track, tools::{DataSource, ToolDescription}};
|
||||
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone, JsonSchema)]
|
||||
pub struct BeatsQueryArgs {
|
||||
artist: Option<String>,
|
||||
album: Option<String>,
|
||||
genre: Option<String>,
|
||||
title: Option<String>,
|
||||
year: Option<u32>
|
||||
pub artist: Option<String>,
|
||||
pub album: Option<String>,
|
||||
pub genre: Option<String>,
|
||||
pub title: Option<String>,
|
||||
pub year: Option<u32>
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
@@ -28,12 +29,7 @@ struct BeetsTrack {
|
||||
|
||||
impl Into<Artifact> 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 {
|
||||
let track_data = Track {
|
||||
title: self.title,
|
||||
label: self.label,
|
||||
year: Some(self.year),
|
||||
@@ -41,33 +37,70 @@ impl Into<Artifact> for BeetsTrack {
|
||||
album: Some(self.album),
|
||||
artist: Some(self.artist),
|
||||
bpm: None,
|
||||
sources
|
||||
})
|
||||
};
|
||||
let builder = ArtifactBuilder::new(SourceID::Beets)
|
||||
.contents(track_data);
|
||||
if let Some(mbid) = self.mb_trackid {
|
||||
builder.mbid(Uuid::parse_str(&mbid).unwrap()).build()
|
||||
} else {
|
||||
builder.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BeatsQueryArgs {
|
||||
pub fn execute(self) -> Result<Vec<Artifact>, ()> {
|
||||
pub struct BeetsDB;
|
||||
|
||||
impl DataSource for BeetsDB {
|
||||
type Args = BeatsQueryArgs;
|
||||
|
||||
type Error = ();
|
||||
|
||||
async fn synchronize(&mut self, artifact: &mut Artifact) -> Result<Vec<Artifact>, Self::Error> {
|
||||
match artifact.contents {
|
||||
Contents::Track(ref mut target_track) => {
|
||||
let args = BeatsQueryArgs {
|
||||
title: Some(target_track.title.clone()),
|
||||
artist: target_track.artist.clone(),
|
||||
album: target_track.album.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let results = self.query(&args).await.unwrap();
|
||||
|
||||
if let Some(first) = results.first() {
|
||||
artifact.merge(first.clone());
|
||||
} else {
|
||||
log::error!("Beets could not find {:?}", target_track);
|
||||
}
|
||||
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
|
||||
Ok(vec![])
|
||||
}
|
||||
|
||||
async fn query(&mut self, args: &Self::Args) -> Result<Vec<Artifact>, Self::Error> {
|
||||
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 {
|
||||
if let Some(ref artist) = args.artist {
|
||||
beets_cmd.arg(format!("artist:{}", artist));
|
||||
valid = true;
|
||||
}
|
||||
if let Some(genre) = self.genre {
|
||||
if let Some(ref genre) = args.genre {
|
||||
beets_cmd.arg(format!("genre:{}", genre));
|
||||
valid = true;
|
||||
}
|
||||
if let Some(album) = self.album {
|
||||
if let Some(ref album) = args.album {
|
||||
beets_cmd.arg(format!("album:{}", album));
|
||||
valid = true;
|
||||
}
|
||||
if let Some(title) = self.title {
|
||||
if let Some(ref title) = args.title {
|
||||
beets_cmd.arg(format!("title:{}", title));
|
||||
valid = true;
|
||||
}
|
||||
if let Some(year) = self.year {
|
||||
if let Some(year) = args.year {
|
||||
beets_cmd.arg(format!("year:{}", year));
|
||||
valid = true;
|
||||
}
|
||||
@@ -91,4 +124,14 @@ impl BeatsQueryArgs {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToolDescription for BeetsDB {
|
||||
fn description(&self) -> &str {
|
||||
"Queries the ship's musical artifact archives for tracks matching the given search parameters"
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
"query_beets"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user