artifacts: rewrite the artifacts model to be source agnostic for now
This commit is contained in:
+111
-43
@@ -3,46 +3,109 @@ use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlite::OpenFlags;
|
||||
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub enum Artifact {
|
||||
Bandcamp(BandcampResult),
|
||||
BeetsTrack(serde_json::Value)
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct Artist {
|
||||
pub name: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub bio: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub location: Option<String>
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub enum BandcampResult {
|
||||
Artist { name: String, bio: Option<String>, location: Option<String> },
|
||||
Album { title: String, about: Option<String>, credits: Option<String>, release_date: DateTime<Utc>, artist: String }
|
||||
}
|
||||
|
||||
impl Into<BandcampResult> for bandcamp::Artist {
|
||||
fn into(self) -> BandcampResult {
|
||||
BandcampResult::Artist { name: self.name, bio: self.bio, location: self.location }
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<BandcampResult> for bandcamp::Album {
|
||||
fn into(self) -> BandcampResult {
|
||||
BandcampResult::Album {
|
||||
about: self.about,
|
||||
title: self.title,
|
||||
artist: self.band.name,
|
||||
credits: self.credits,
|
||||
release_date: self.release_date
|
||||
impl PartialEq for Artist {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
if self.name != other.name {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn ne(&self, other: &Self) -> bool {
|
||||
!self.eq(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Artifact> for bandcamp::Album {
|
||||
fn into(self) -> Artifact {
|
||||
Artifact::Bandcamp(self.into())
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
|
||||
pub struct Album {
|
||||
pub title: String,
|
||||
pub artist: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub about: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub credits: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub release_date: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct Track {
|
||||
pub title: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub label: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub year: Option<u32>,
|
||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
#[serde(default)]
|
||||
pub genres: Vec<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub album: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub artist: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub bpm: Option<f64>
|
||||
}
|
||||
|
||||
impl PartialEq for Track {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
if self.title != other.title {
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.artist.is_some() && self.artist != other.artist {
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.album.is_some() && self.album != other.album {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn ne(&self, other: &Self) -> bool {
|
||||
!self.eq(other)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
||||
pub enum Artifact {
|
||||
Artist(Artist),
|
||||
Album(Album),
|
||||
Track(Track)
|
||||
}
|
||||
|
||||
impl Artifact {
|
||||
pub fn merge(&mut self, other: &Artifact) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Artifact> for bandcamp::Artist {
|
||||
fn into(self) -> Artifact {
|
||||
Artifact::Bandcamp(self.into())
|
||||
Artifact::Artist(Artist { name: self.name, bio: self.bio, location: self.location })
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,14 +114,6 @@ pub struct BandcampQueryArgs {
|
||||
pub query: String
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||
pub struct MixxxTrack {
|
||||
pub artist: String,
|
||||
pub album: String,
|
||||
pub title: String,
|
||||
pub bpm: f64
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MixxxError {
|
||||
Sql(sqlite::Error)
|
||||
@@ -73,9 +128,10 @@ impl From<sqlite::Error> for MixxxError {
|
||||
pub struct MixxxDB(());
|
||||
|
||||
impl MixxxDB {
|
||||
pub fn load(episode_number: u32) -> Result<Vec<MixxxTrack>, MixxxError> {
|
||||
pub fn load(episode_number: u32) -> Result<Vec<Artifact>, MixxxError> {
|
||||
let mut ret = vec![];
|
||||
let playlist_name = format!("BFF.fm - Episode {}", episode_number);
|
||||
log::info!("Loading Mixxx playlist {}", playlist_name);
|
||||
let connection = sqlite::Connection::open_thread_safe_with_flags("mixxxdb.sqlite", OpenFlags::new().with_read_only())?;
|
||||
let query = "SELECT id FROM Playlists WHERE name = ? ORDER BY id DESC LIMIT 1";
|
||||
let mut statement = connection.prepare(query)?;
|
||||
@@ -89,12 +145,24 @@ impl MixxxDB {
|
||||
let artist = track.try_read::<&str, _>("artist").unwrap_or("Unknown Artist");
|
||||
let album = track.try_read::<&str, _>("album").unwrap_or("Unknown Album");
|
||||
let bpm = track.try_read::<f64, _>("bpm").unwrap_or(0.);
|
||||
ret.push(MixxxTrack {
|
||||
artist: artist.into(),
|
||||
album: album.into(),
|
||||
ret.push(Artifact::Track(Track {
|
||||
artist: Some(artist.into()),
|
||||
album: Some(album.into()),
|
||||
title: title.into(),
|
||||
bpm
|
||||
});
|
||||
bpm: Some(bpm),
|
||||
..Default::default()
|
||||
}));
|
||||
|
||||
ret.push(Artifact::Album(Album {
|
||||
artist: artist.into(),
|
||||
title: album.into(),
|
||||
..Default::default()
|
||||
}));
|
||||
|
||||
ret.push(Artifact::Artist(Artist {
|
||||
name: artist.into(),
|
||||
..Default::default()
|
||||
}));
|
||||
}
|
||||
|
||||
Ok(ret)
|
||||
|
||||
Reference in New Issue
Block a user