artifacts: rewrite the entire artifact querying layer to create modular 'tools' and 'datasource's

This commit is contained in:
2026-06-17 11:09:50 +02:00
parent 33e0b1768f
commit 3a8130d785
11 changed files with 672 additions and 257 deletions
+64 -12
View File
@@ -1,9 +1,8 @@
use std::collections::HashSet;
use bandcamp::SearchResultItem;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::artifacts::{Album, Artifact, Artist, SourceID};
use crate::artifacts::{Album, Artifact, ArtifactBuilder, Artist, SourceID, Track, tools::{DataSource, ToolDescription}};
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
pub struct BandcampQueryArgs {
@@ -12,19 +11,72 @@ pub struct BandcampQueryArgs {
impl Into<Artifact> for bandcamp::Artist {
fn into(self) -> Artifact {
Artifact::Artist(Artist { name: self.name, bio: self.bio, location: self.location, sources: HashSet::from([SourceID::Bandcamp(self.id)])})
ArtifactBuilder::new(SourceID::Bandcamp).contents(Artist { name: self.name, bio: self.bio, location: self.location }).build()
}
}
impl Into<Artifact> for bandcamp::Album {
fn into(self) -> Artifact {
Artifact::Album(Album {
about: self.about,
title: self.title,
artist: self.band.name,
credits: self.credits,
release_date: Some(self.release_date),
sources: HashSet::from([SourceID::Bandcamp(self.id)])
})
ArtifactBuilder::new(SourceID::Bandcamp)
.contents(Album {
about: self.about,
title: self.title,
artist: self.band.name,
credits: self.credits,
release_date: Some(self.release_date)
}).build()
}
}
pub struct BandcampSource;
impl DataSource for BandcampSource {
type Args = BandcampQueryArgs;
type Error = ();
async fn synchronize(&mut self, _artifact: &mut Artifact) -> Result<Vec<Artifact>, Self::Error> {
todo!()
}
async fn query(&mut self, args: &Self::Args) -> Result<Vec<Artifact>, Self::Error> {
log::debug!("Fetching artifacts from Bandcamp with {:?}", args);
let mut json_results = vec![];
if let Ok(results) = bandcamp::search(args.query.as_str()).await {
for result in results {
log::debug!("Result: {:?}", result);
match result {
SearchResultItem::Artist(data) => {
let result = bandcamp::fetch_artist(data.artist_id).await.unwrap().into();
json_results.push(result);
},
SearchResultItem::Album(data) => {
let result = bandcamp::fetch_album(data.band_id, data.album_id).await.unwrap().into();
json_results.push(result);
},
SearchResultItem::Track(data) => {
let result = ArtifactBuilder::new(SourceID::Bandcamp)
.contents(Track {
title: data.name,
artist: Some(data.band_name),
album: data.album_name,
..Default::default()
}).build();
json_results.push(result);
}
_ => ()
}
}
}
Ok(json_results)
}
}
impl ToolDescription for BandcampSource {
fn description(&self) -> &str {
"Scans Bandcamp to find artifacts to use in the scene that match the given search parameters. To find an artist, provide only the artist name. To find an album, provide the artist and the album."
}
fn name(&self) -> &str {
"query_bandcamp"
}
}