use bandcamp::SearchResultItem; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::artifacts::{Album, Artifact, ArtifactBuilder, Artist, Contents, SourceID, Track, tools::{DataSource, ToolDescription}}; #[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)] pub struct BandcampQueryArgs { pub query: String } impl From for Artifact { fn from(val: bandcamp::Artist) -> Self { ArtifactBuilder::new(SourceID::Bandcamp).contents(Artist { name: val.name, bio: val.bio, location: val.location }).build() } } impl From for Artifact { fn from(val: bandcamp::Album) -> Self { ArtifactBuilder::new(SourceID::Bandcamp) .contents(Album { about: val.about, title: val.title, artist: val.band.name, credits: val.credits, release_date: Some(val.release_date) }).build() } } pub struct BandcampSource; impl DataSource for BandcampSource { type Args = BandcampQueryArgs; type Error = bandcamp::Error; async fn synchronize(&self, artifact: &mut Artifact) -> Result, Self::Error> { if let Contents::Artist(artist) = &artifact.contents { Ok(self.query(&BandcampQueryArgs { query: artist.name.clone() }).await.unwrap_or_default()) } else { Ok(vec![]) } } async fn query(&self, args: &Self::Args) -> Result, 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) => { // TODO: The artist and album detailed fetchers should also be separate args let result = bandcamp::fetch_artist(data.artist_id).await?.into(); json_results.push(result); }, SearchResultItem::Album(data) => { let result = bandcamp::fetch_album(data.band_id, data.album_id).await?.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" } }