Implement cannot have MBID in core #220
@ -5,7 +5,7 @@ use std::{
|
|||||||
|
|
||||||
use crate::core::collection::{
|
use crate::core::collection::{
|
||||||
merge::{Merge, MergeSorted, WithId},
|
merge::{Merge, MergeSorted, WithId},
|
||||||
musicbrainz::MbAlbumRef,
|
musicbrainz::{MbAlbumRef, MbRefOption},
|
||||||
track::{Track, TrackFormat},
|
track::{Track, TrackFormat},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ pub struct AlbumMeta {
|
|||||||
pub id: AlbumId,
|
pub id: AlbumId,
|
||||||
pub date: AlbumDate,
|
pub date: AlbumDate,
|
||||||
pub seq: AlbumSeq,
|
pub seq: AlbumSeq,
|
||||||
pub musicbrainz: Option<MbAlbumRef>,
|
pub musicbrainz: MbRefOption<MbAlbumRef>,
|
||||||
pub primary_type: Option<AlbumPrimaryType>,
|
pub primary_type: Option<AlbumPrimaryType>,
|
||||||
pub secondary_types: Vec<AlbumSecondaryType>,
|
pub secondary_types: Vec<AlbumSecondaryType>,
|
||||||
}
|
}
|
||||||
@ -186,7 +186,7 @@ impl AlbumMeta {
|
|||||||
id: id.into(),
|
id: id.into(),
|
||||||
date: date.into(),
|
date: date.into(),
|
||||||
seq: AlbumSeq::default(),
|
seq: AlbumSeq::default(),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type,
|
primary_type,
|
||||||
secondary_types,
|
secondary_types,
|
||||||
}
|
}
|
||||||
@ -364,7 +364,7 @@ mod tests {
|
|||||||
|
|
||||||
let mut album = Album::new(AlbumId::new("an album"), AlbumDate::default(), None, vec![]);
|
let mut album = Album::new(AlbumId::new("an album"), AlbumDate::default(), None, vec![]);
|
||||||
|
|
||||||
let mut expected: Option<MbAlbumRef> = None;
|
let mut expected: MbRefOption<MbAlbumRef> = MbRefOption::None;
|
||||||
assert_eq!(album.meta.musicbrainz, expected);
|
assert_eq!(album.meta.musicbrainz, expected);
|
||||||
|
|
||||||
// Setting a URL on an album.
|
// Setting a URL on an album.
|
||||||
|
@ -7,7 +7,7 @@ use std::{
|
|||||||
use crate::core::collection::{
|
use crate::core::collection::{
|
||||||
album::Album,
|
album::Album,
|
||||||
merge::{Merge, MergeCollections, WithId},
|
merge::{Merge, MergeCollections, WithId},
|
||||||
musicbrainz::MbArtistRef,
|
musicbrainz::{MbArtistRef, MbRefOption},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An artist.
|
/// An artist.
|
||||||
@ -22,7 +22,7 @@ pub struct Artist {
|
|||||||
pub struct ArtistMeta {
|
pub struct ArtistMeta {
|
||||||
pub id: ArtistId,
|
pub id: ArtistId,
|
||||||
pub sort: Option<ArtistId>,
|
pub sort: Option<ArtistId>,
|
||||||
pub musicbrainz: Option<MbArtistRef>,
|
pub musicbrainz: MbRefOption<MbArtistRef>,
|
||||||
pub properties: HashMap<String, Vec<String>>,
|
pub properties: HashMap<String, Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ impl ArtistMeta {
|
|||||||
ArtistMeta {
|
ArtistMeta {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
sort: None,
|
sort: None,
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
properties: HashMap::new(),
|
properties: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -255,7 +255,7 @@ mod tests {
|
|||||||
fn set_clear_musicbrainz_url() {
|
fn set_clear_musicbrainz_url() {
|
||||||
let mut artist = Artist::new(ArtistId::new("an artist"));
|
let mut artist = Artist::new(ArtistId::new("an artist"));
|
||||||
|
|
||||||
let mut expected: Option<MbArtistRef> = None;
|
let mut expected: MbRefOption<MbArtistRef> = MbRefOption::None;
|
||||||
assert_eq!(artist.meta.musicbrainz, expected);
|
assert_eq!(artist.meta.musicbrainz, expected);
|
||||||
|
|
||||||
// Setting a URL on an artist.
|
// Setting a URL on an artist.
|
||||||
@ -417,7 +417,7 @@ mod tests {
|
|||||||
let left = FULL_COLLECTION[0].to_owned();
|
let left = FULL_COLLECTION[0].to_owned();
|
||||||
let mut right = FULL_COLLECTION[1].to_owned();
|
let mut right = FULL_COLLECTION[1].to_owned();
|
||||||
right.meta.id = left.meta.id.clone();
|
right.meta.id = left.meta.id.clone();
|
||||||
right.meta.musicbrainz = None;
|
right.meta.musicbrainz = MbRefOption::None;
|
||||||
right.meta.properties = HashMap::new();
|
right.meta.properties = HashMap::new();
|
||||||
|
|
||||||
let mut expected = left.clone();
|
let mut expected = left.clone();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::fmt::{Debug, Display};
|
use std::{fmt, mem};
|
||||||
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
@ -38,6 +38,30 @@ try_from_impl_for_mbid!(&str);
|
|||||||
try_from_impl_for_mbid!(&String);
|
try_from_impl_for_mbid!(&String);
|
||||||
try_from_impl_for_mbid!(String);
|
try_from_impl_for_mbid!(String);
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum MbRefOption<T> {
|
||||||
|
Some(T),
|
||||||
|
CannotHaveMbid,
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> MbRefOption<T> {
|
||||||
|
pub fn or(self, optb: MbRefOption<T>) -> MbRefOption<T> {
|
||||||
|
match self {
|
||||||
|
x @ MbRefOption::Some(_) => x,
|
||||||
|
MbRefOption::CannotHaveMbid | MbRefOption::None => optb,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn replace(&mut self, value: T) -> MbRefOption<T> {
|
||||||
|
mem::replace(self, MbRefOption::Some(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take(&mut self) -> MbRefOption<T> {
|
||||||
|
mem::replace(self, MbRefOption::None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
struct MusicBrainzRef {
|
struct MusicBrainzRef {
|
||||||
mbid: Mbid,
|
mbid: Mbid,
|
||||||
@ -142,7 +166,7 @@ impl MusicBrainzRef {
|
|||||||
MusicBrainzRef { mbid, url }
|
MusicBrainzRef { mbid, url }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invalid_url_error<U: Display>(url: U, entity: &'static str) -> Error {
|
fn invalid_url_error<U: fmt::Display>(url: U, entity: &'static str) -> Error {
|
||||||
Error::UrlError(format!("invalid {entity} MusicBrainz URL: {url}"))
|
Error::UrlError(format!("invalid {entity} MusicBrainz URL: {url}"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,11 +297,14 @@ impl<Database: IDatabase, Library> MusicHoard<Database, Library> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use mockall::{predicate, Sequence};
|
use mockall::{predicate, Sequence};
|
||||||
|
|
||||||
use crate::core::{
|
use crate::{
|
||||||
|
collection::musicbrainz::MbRefOption,
|
||||||
|
core::{
|
||||||
collection::{album::AlbumDate, artist::ArtistId},
|
collection::{album::AlbumDate, artist::ArtistId},
|
||||||
interface::database::{self, MockIDatabase},
|
interface::database::{self, MockIDatabase},
|
||||||
musichoard::{base::IMusicHoardBase, NoLibrary},
|
musichoard::{base::IMusicHoardBase, NoLibrary},
|
||||||
testmod::FULL_COLLECTION,
|
testmod::FULL_COLLECTION,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -441,7 +444,7 @@ mod tests {
|
|||||||
|
|
||||||
assert!(music_hoard.add_artist(artist_id.clone()).is_ok());
|
assert!(music_hoard.add_artist(artist_id.clone()).is_ok());
|
||||||
|
|
||||||
let mut expected: Option<MbArtistRef> = None;
|
let mut expected: MbRefOption<MbArtistRef> = MbRefOption::None;
|
||||||
assert_eq!(music_hoard.collection[0].meta.musicbrainz, expected);
|
assert_eq!(music_hoard.collection[0].meta.musicbrainz, expected);
|
||||||
|
|
||||||
// Setting a URL on an artist not in the collection is an error.
|
// Setting a URL on an artist not in the collection is an error.
|
||||||
|
@ -4,7 +4,7 @@ use std::collections::HashMap;
|
|||||||
use crate::core::collection::{
|
use crate::core::collection::{
|
||||||
album::{Album, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSeq},
|
album::{Album, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSeq},
|
||||||
artist::{Artist, ArtistId, ArtistMeta},
|
artist::{Artist, ArtistId, ArtistMeta},
|
||||||
musicbrainz::{MbAlbumRef, MbArtistRef},
|
musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption},
|
||||||
track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality},
|
track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality},
|
||||||
};
|
};
|
||||||
use crate::testmod::*;
|
use crate::testmod::*;
|
||||||
|
30
src/external/database/json/testmod.rs
vendored
30
src/external/database/json/testmod.rs
vendored
@ -1,10 +1,10 @@
|
|||||||
pub static DATABASE_JSON: &str = "{\
|
pub static DATABASE_JSON: &str = "{\
|
||||||
\"V20240828\":\
|
\"V20240924\":\
|
||||||
[\
|
[\
|
||||||
{\
|
{\
|
||||||
\"name\":\"Album_Artist ‘A’\",\
|
\"name\":\"Album_Artist ‘A’\",\
|
||||||
\"sort\":null,\
|
\"sort\":null,\
|
||||||
\"musicbrainz\":\"00000000-0000-0000-0000-000000000000\",\
|
\"musicbrainz\":{\"Some\":\"00000000-0000-0000-0000-000000000000\"},\
|
||||||
\"properties\":{\
|
\"properties\":{\
|
||||||
\"MusicButler\":[\"https://www.musicbutler.io/artist-page/000000000\"],\
|
\"MusicButler\":[\"https://www.musicbutler.io/artist-page/000000000\"],\
|
||||||
\"Qobuz\":[\"https://www.qobuz.com/nl-nl/interpreter/artist-a/download-streaming-albums\"]\
|
\"Qobuz\":[\"https://www.qobuz.com/nl-nl/interpreter/artist-a/download-streaming-albums\"]\
|
||||||
@ -12,11 +12,11 @@ pub static DATABASE_JSON: &str = "{\
|
|||||||
\"albums\":[\
|
\"albums\":[\
|
||||||
{\
|
{\
|
||||||
\"title\":\"album_title a.a\",\"seq\":1,\
|
\"title\":\"album_title a.a\",\"seq\":1,\
|
||||||
\"musicbrainz\":\"00000000-0000-0000-0000-000000000000\",\
|
\"musicbrainz\":{\"Some\":\"00000000-0000-0000-0000-000000000000\"},\
|
||||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||||
},\
|
},\
|
||||||
{\
|
{\
|
||||||
\"title\":\"album_title a.b\",\"seq\":1,\"musicbrainz\":null,\
|
\"title\":\"album_title a.b\",\"seq\":1,\"musicbrainz\":\"None\",\
|
||||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||||
}\
|
}\
|
||||||
]\
|
]\
|
||||||
@ -24,7 +24,7 @@ pub static DATABASE_JSON: &str = "{\
|
|||||||
{\
|
{\
|
||||||
\"name\":\"Album_Artist ‘B’\",\
|
\"name\":\"Album_Artist ‘B’\",\
|
||||||
\"sort\":null,\
|
\"sort\":null,\
|
||||||
\"musicbrainz\":\"11111111-1111-1111-1111-111111111111\",\
|
\"musicbrainz\":{\"Some\":\"11111111-1111-1111-1111-111111111111\"},\
|
||||||
\"properties\":{\
|
\"properties\":{\
|
||||||
\"Bandcamp\":[\"https://artist-b.bandcamp.com/\"],\
|
\"Bandcamp\":[\"https://artist-b.bandcamp.com/\"],\
|
||||||
\"MusicButler\":[\
|
\"MusicButler\":[\
|
||||||
@ -35,21 +35,21 @@ pub static DATABASE_JSON: &str = "{\
|
|||||||
},\
|
},\
|
||||||
\"albums\":[\
|
\"albums\":[\
|
||||||
{\
|
{\
|
||||||
\"title\":\"album_title b.a\",\"seq\":1,\"musicbrainz\":null,\
|
\"title\":\"album_title b.a\",\"seq\":1,\"musicbrainz\":\"None\",\
|
||||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||||
},\
|
},\
|
||||||
{\
|
{\
|
||||||
\"title\":\"album_title b.b\",\"seq\":3,\
|
\"title\":\"album_title b.b\",\"seq\":3,\
|
||||||
\"musicbrainz\":\"11111111-1111-1111-1111-111111111111\",\
|
\"musicbrainz\":{\"Some\":\"11111111-1111-1111-1111-111111111111\"},\
|
||||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||||
},\
|
},\
|
||||||
{\
|
{\
|
||||||
\"title\":\"album_title b.c\",\"seq\":2,\
|
\"title\":\"album_title b.c\",\"seq\":2,\
|
||||||
\"musicbrainz\":\"11111111-1111-1111-1111-111111111112\",\
|
\"musicbrainz\":{\"Some\":\"11111111-1111-1111-1111-111111111112\"},\
|
||||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||||
},\
|
},\
|
||||||
{\
|
{\
|
||||||
\"title\":\"album_title b.d\",\"seq\":4,\"musicbrainz\":null,\
|
\"title\":\"album_title b.d\",\"seq\":4,\"musicbrainz\":\"None\",\
|
||||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||||
}\
|
}\
|
||||||
]\
|
]\
|
||||||
@ -57,15 +57,15 @@ pub static DATABASE_JSON: &str = "{\
|
|||||||
{\
|
{\
|
||||||
\"name\":\"The Album_Artist ‘C’\",\
|
\"name\":\"The Album_Artist ‘C’\",\
|
||||||
\"sort\":\"Album_Artist ‘C’, The\",\
|
\"sort\":\"Album_Artist ‘C’, The\",\
|
||||||
\"musicbrainz\":\"11111111-1111-1111-1111-111111111111\",\
|
\"musicbrainz\":\"CannotHaveMbid\",\
|
||||||
\"properties\":{},\
|
\"properties\":{},\
|
||||||
\"albums\":[\
|
\"albums\":[\
|
||||||
{\
|
{\
|
||||||
\"title\":\"album_title c.a\",\"seq\":0,\"musicbrainz\":null,\
|
\"title\":\"album_title c.a\",\"seq\":0,\"musicbrainz\":\"None\",\
|
||||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||||
},\
|
},\
|
||||||
{\
|
{\
|
||||||
\"title\":\"album_title c.b\",\"seq\":0,\"musicbrainz\":null,\
|
\"title\":\"album_title c.b\",\"seq\":0,\"musicbrainz\":\"None\",\
|
||||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||||
}\
|
}\
|
||||||
]\
|
]\
|
||||||
@ -73,15 +73,15 @@ pub static DATABASE_JSON: &str = "{\
|
|||||||
{\
|
{\
|
||||||
\"name\":\"Album_Artist ‘D’\",\
|
\"name\":\"Album_Artist ‘D’\",\
|
||||||
\"sort\":null,\
|
\"sort\":null,\
|
||||||
\"musicbrainz\":null,\
|
\"musicbrainz\":\"None\",\
|
||||||
\"properties\":{},\
|
\"properties\":{},\
|
||||||
\"albums\":[\
|
\"albums\":[\
|
||||||
{\
|
{\
|
||||||
\"title\":\"album_title d.a\",\"seq\":0,\"musicbrainz\":null,\
|
\"title\":\"album_title d.a\",\"seq\":0,\"musicbrainz\":\"None\",\
|
||||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||||
},\
|
},\
|
||||||
{\
|
{\
|
||||||
\"title\":\"album_title d.b\",\"seq\":0,\"musicbrainz\":null,\
|
\"title\":\"album_title d.b\",\"seq\":0,\"musicbrainz\":\"None\",\
|
||||||
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
\"primary_type\":\"Album\",\"secondary_types\":[]\
|
||||||
}\
|
}\
|
||||||
]\
|
]\
|
||||||
|
13
src/external/database/serde/common.rs
vendored
13
src/external/database/serde/common.rs
vendored
@ -1,6 +1,17 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::core::collection::album::{AlbumPrimaryType, AlbumSecondaryType};
|
use crate::{
|
||||||
|
collection::musicbrainz::MbRefOption,
|
||||||
|
core::collection::album::{AlbumPrimaryType, AlbumSecondaryType},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(remote = "MbRefOption")]
|
||||||
|
pub enum MbRefOptionDef<T> {
|
||||||
|
Some(T),
|
||||||
|
CannotHaveMbid,
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(remote = "AlbumPrimaryType")]
|
#[serde(remote = "AlbumPrimaryType")]
|
||||||
|
40
src/external/database/serde/deserialize.rs
vendored
40
src/external/database/serde/deserialize.rs
vendored
@ -3,7 +3,11 @@ use std::{collections::HashMap, fmt};
|
|||||||
use serde::{de::Visitor, Deserialize, Deserializer};
|
use serde::{de::Visitor, Deserialize, Deserializer};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
collection::{album::AlbumMeta, artist::ArtistMeta, musicbrainz::Mbid},
|
collection::{
|
||||||
|
album::AlbumMeta,
|
||||||
|
artist::ArtistMeta,
|
||||||
|
musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption, Mbid},
|
||||||
|
},
|
||||||
core::collection::{
|
core::collection::{
|
||||||
album::{Album, AlbumDate, AlbumId, AlbumSeq},
|
album::{Album, AlbumDate, AlbumId, AlbumSeq},
|
||||||
artist::{Artist, ArtistId},
|
artist::{Artist, ArtistId},
|
||||||
@ -12,15 +16,17 @@ use crate::{
|
|||||||
external::database::serde::common::{SerdeAlbumPrimaryType, SerdeAlbumSecondaryType},
|
external::database::serde::common::{SerdeAlbumPrimaryType, SerdeAlbumSecondaryType},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::common::MbRefOptionDef;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub enum DeserializeDatabase {
|
pub enum DeserializeDatabase {
|
||||||
V20240828(Vec<DeserializeArtist>),
|
V20240924(Vec<DeserializeArtist>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<DeserializeDatabase> for Collection {
|
impl From<DeserializeDatabase> for Collection {
|
||||||
fn from(database: DeserializeDatabase) -> Self {
|
fn from(database: DeserializeDatabase) -> Self {
|
||||||
match database {
|
match database {
|
||||||
DeserializeDatabase::V20240828(collection) => {
|
DeserializeDatabase::V20240924(collection) => {
|
||||||
collection.into_iter().map(Into::into).collect()
|
collection.into_iter().map(Into::into).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -31,7 +37,7 @@ impl From<DeserializeDatabase> for Collection {
|
|||||||
pub struct DeserializeArtist {
|
pub struct DeserializeArtist {
|
||||||
name: String,
|
name: String,
|
||||||
sort: Option<String>,
|
sort: Option<String>,
|
||||||
musicbrainz: Option<DeserializeMbid>,
|
musicbrainz: DeserializeMbRefOption,
|
||||||
properties: HashMap<String, Vec<String>>,
|
properties: HashMap<String, Vec<String>>,
|
||||||
albums: Vec<DeserializeAlbum>,
|
albums: Vec<DeserializeAlbum>,
|
||||||
}
|
}
|
||||||
@ -40,14 +46,34 @@ pub struct DeserializeArtist {
|
|||||||
pub struct DeserializeAlbum {
|
pub struct DeserializeAlbum {
|
||||||
title: String,
|
title: String,
|
||||||
seq: u8,
|
seq: u8,
|
||||||
musicbrainz: Option<DeserializeMbid>,
|
musicbrainz: DeserializeMbRefOption,
|
||||||
primary_type: Option<SerdeAlbumPrimaryType>,
|
primary_type: Option<SerdeAlbumPrimaryType>,
|
||||||
secondary_types: Vec<SerdeAlbumSecondaryType>,
|
secondary_types: Vec<SerdeAlbumSecondaryType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct DeserializeMbRefOption(#[serde(with = "MbRefOptionDef")] MbRefOption<DeserializeMbid>);
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct DeserializeMbid(Mbid);
|
pub struct DeserializeMbid(Mbid);
|
||||||
|
|
||||||
|
macro_rules! impl_from_for_mb_ref_option {
|
||||||
|
($ref:ty) => {
|
||||||
|
impl From<DeserializeMbRefOption> for MbRefOption<$ref> {
|
||||||
|
fn from(value: DeserializeMbRefOption) -> Self {
|
||||||
|
match value.0 {
|
||||||
|
MbRefOption::Some(val) => MbRefOption::Some(val.0.into()),
|
||||||
|
MbRefOption::CannotHaveMbid => MbRefOption::CannotHaveMbid,
|
||||||
|
MbRefOption::None => MbRefOption::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_from_for_mb_ref_option!(MbArtistRef);
|
||||||
|
impl_from_for_mb_ref_option!(MbAlbumRef);
|
||||||
|
|
||||||
impl From<DeserializeMbid> for Mbid {
|
impl From<DeserializeMbid> for Mbid {
|
||||||
fn from(value: DeserializeMbid) -> Self {
|
fn from(value: DeserializeMbid) -> Self {
|
||||||
value.0
|
value.0
|
||||||
@ -89,7 +115,7 @@ impl From<DeserializeArtist> for Artist {
|
|||||||
meta: ArtistMeta {
|
meta: ArtistMeta {
|
||||||
id: ArtistId::new(artist.name),
|
id: ArtistId::new(artist.name),
|
||||||
sort: artist.sort.map(ArtistId::new),
|
sort: artist.sort.map(ArtistId::new),
|
||||||
musicbrainz: artist.musicbrainz.map(Into::<Mbid>::into).map(Into::into),
|
musicbrainz: artist.musicbrainz.into(),
|
||||||
properties: artist.properties,
|
properties: artist.properties,
|
||||||
},
|
},
|
||||||
albums: artist.albums.into_iter().map(Into::into).collect(),
|
albums: artist.albums.into_iter().map(Into::into).collect(),
|
||||||
@ -104,7 +130,7 @@ impl From<DeserializeAlbum> for Album {
|
|||||||
id: AlbumId { title: album.title },
|
id: AlbumId { title: album.title },
|
||||||
date: AlbumDate::default(),
|
date: AlbumDate::default(),
|
||||||
seq: AlbumSeq(album.seq),
|
seq: AlbumSeq(album.seq),
|
||||||
musicbrainz: album.musicbrainz.map(Into::<Mbid>::into).map(Into::into),
|
musicbrainz: album.musicbrainz.into(),
|
||||||
primary_type: album.primary_type.map(Into::into),
|
primary_type: album.primary_type.map(Into::into),
|
||||||
secondary_types: album.secondary_types.into_iter().map(Into::into).collect(),
|
secondary_types: album.secondary_types.into_iter().map(Into::into).collect(),
|
||||||
},
|
},
|
||||||
|
43
src/external/database/serde/serialize.rs
vendored
43
src/external/database/serde/serialize.rs
vendored
@ -3,19 +3,21 @@ use std::collections::BTreeMap;
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
collection::musicbrainz::Mbid,
|
collection::musicbrainz::{MbRefOption, Mbid},
|
||||||
core::collection::{album::Album, artist::Artist, musicbrainz::IMusicBrainzRef, Collection},
|
core::collection::{album::Album, artist::Artist, musicbrainz::IMusicBrainzRef, Collection},
|
||||||
external::database::serde::common::{SerdeAlbumPrimaryType, SerdeAlbumSecondaryType},
|
external::database::serde::common::{
|
||||||
|
MbRefOptionDef, SerdeAlbumPrimaryType, SerdeAlbumSecondaryType,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub enum SerializeDatabase<'a> {
|
pub enum SerializeDatabase<'a> {
|
||||||
V20240828(Vec<SerializeArtist<'a>>),
|
V20240924(Vec<SerializeArtist<'a>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a Collection> for SerializeDatabase<'a> {
|
impl<'a> From<&'a Collection> for SerializeDatabase<'a> {
|
||||||
fn from(collection: &'a Collection) -> Self {
|
fn from(collection: &'a Collection) -> Self {
|
||||||
SerializeDatabase::V20240828(collection.iter().map(Into::into).collect())
|
SerializeDatabase::V20240924(collection.iter().map(Into::into).collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,7 +25,7 @@ impl<'a> From<&'a Collection> for SerializeDatabase<'a> {
|
|||||||
pub struct SerializeArtist<'a> {
|
pub struct SerializeArtist<'a> {
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
sort: Option<&'a str>,
|
sort: Option<&'a str>,
|
||||||
musicbrainz: Option<SerializeMbid<'a>>,
|
musicbrainz: SerializeMbRefOption<'a>,
|
||||||
properties: BTreeMap<&'a str, &'a Vec<String>>,
|
properties: BTreeMap<&'a str, &'a Vec<String>>,
|
||||||
albums: Vec<SerializeAlbum<'a>>,
|
albums: Vec<SerializeAlbum<'a>>,
|
||||||
}
|
}
|
||||||
@ -32,14 +34,31 @@ pub struct SerializeArtist<'a> {
|
|||||||
pub struct SerializeAlbum<'a> {
|
pub struct SerializeAlbum<'a> {
|
||||||
title: &'a str,
|
title: &'a str,
|
||||||
seq: u8,
|
seq: u8,
|
||||||
musicbrainz: Option<SerializeMbid<'a>>,
|
musicbrainz: SerializeMbRefOption<'a>,
|
||||||
primary_type: Option<SerdeAlbumPrimaryType>,
|
primary_type: Option<SerdeAlbumPrimaryType>,
|
||||||
secondary_types: Vec<SerdeAlbumSecondaryType>,
|
secondary_types: Vec<SerdeAlbumSecondaryType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct SerializeMbRefOption<'a>(
|
||||||
|
#[serde(with = "MbRefOptionDef")] MbRefOption<SerializeMbid<'a>>,
|
||||||
|
);
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SerializeMbid<'a>(&'a Mbid);
|
pub struct SerializeMbid<'a>(&'a Mbid);
|
||||||
|
|
||||||
|
impl<'a, T: IMusicBrainzRef> From<&'a MbRefOption<T>> for SerializeMbRefOption<'a> {
|
||||||
|
fn from(value: &'a MbRefOption<T>) -> Self {
|
||||||
|
match value {
|
||||||
|
MbRefOption::Some(val) => {
|
||||||
|
SerializeMbRefOption(MbRefOption::Some(SerializeMbid(val.mbid())))
|
||||||
|
}
|
||||||
|
MbRefOption::CannotHaveMbid => SerializeMbRefOption(MbRefOption::CannotHaveMbid),
|
||||||
|
MbRefOption::None => SerializeMbRefOption(MbRefOption::None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Serialize for SerializeMbid<'a> {
|
impl<'a> Serialize for SerializeMbid<'a> {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
@ -54,11 +73,7 @@ impl<'a> From<&'a Artist> for SerializeArtist<'a> {
|
|||||||
SerializeArtist {
|
SerializeArtist {
|
||||||
name: &artist.meta.id.name,
|
name: &artist.meta.id.name,
|
||||||
sort: artist.meta.sort.as_ref().map(|id| id.name.as_ref()),
|
sort: artist.meta.sort.as_ref().map(|id| id.name.as_ref()),
|
||||||
musicbrainz: artist
|
musicbrainz: (&artist.meta.musicbrainz).into(),
|
||||||
.meta
|
|
||||||
.musicbrainz
|
|
||||||
.as_ref()
|
|
||||||
.map(|mbref| SerializeMbid(mbref.mbid())),
|
|
||||||
properties: artist
|
properties: artist
|
||||||
.meta
|
.meta
|
||||||
.properties
|
.properties
|
||||||
@ -75,11 +90,7 @@ impl<'a> From<&'a Album> for SerializeAlbum<'a> {
|
|||||||
SerializeAlbum {
|
SerializeAlbum {
|
||||||
title: &album.meta.id.title,
|
title: &album.meta.id.title,
|
||||||
seq: album.meta.seq.0,
|
seq: album.meta.seq.0,
|
||||||
musicbrainz: album
|
musicbrainz: (&album.meta.musicbrainz).into(),
|
||||||
.meta
|
|
||||||
.musicbrainz
|
|
||||||
.as_ref()
|
|
||||||
.map(|mbref| SerializeMbid(mbref.mbid())),
|
|
||||||
primary_type: album.meta.primary_type.map(Into::into),
|
primary_type: album.meta.primary_type.map(Into::into),
|
||||||
secondary_types: album
|
secondary_types: album
|
||||||
.meta
|
.meta
|
||||||
|
@ -7,7 +7,7 @@ macro_rules! full_collection {
|
|||||||
name: "Album_Artist ‘A’".to_string(),
|
name: "Album_Artist ‘A’".to_string(),
|
||||||
},
|
},
|
||||||
sort: None,
|
sort: None,
|
||||||
musicbrainz: Some(MbArtistRef::from_url_str(
|
musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str(
|
||||||
"https://musicbrainz.org/artist/00000000-0000-0000-0000-000000000000"
|
"https://musicbrainz.org/artist/00000000-0000-0000-0000-000000000000"
|
||||||
).unwrap()),
|
).unwrap()),
|
||||||
properties: HashMap::from([
|
properties: HashMap::from([
|
||||||
@ -29,7 +29,7 @@ macro_rules! full_collection {
|
|||||||
},
|
},
|
||||||
date: 1998.into(),
|
date: 1998.into(),
|
||||||
seq: AlbumSeq(1),
|
seq: AlbumSeq(1),
|
||||||
musicbrainz: Some(MbAlbumRef::from_url_str(
|
musicbrainz: MbRefOption::Some(MbAlbumRef::from_url_str(
|
||||||
"https://musicbrainz.org/release-group/00000000-0000-0000-0000-000000000000"
|
"https://musicbrainz.org/release-group/00000000-0000-0000-0000-000000000000"
|
||||||
).unwrap()),
|
).unwrap()),
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
@ -92,7 +92,7 @@ macro_rules! full_collection {
|
|||||||
},
|
},
|
||||||
date: (2015, 4).into(),
|
date: (2015, 4).into(),
|
||||||
seq: AlbumSeq(1),
|
seq: AlbumSeq(1),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -129,7 +129,7 @@ macro_rules! full_collection {
|
|||||||
name: "Album_Artist ‘B’".to_string(),
|
name: "Album_Artist ‘B’".to_string(),
|
||||||
},
|
},
|
||||||
sort: None,
|
sort: None,
|
||||||
musicbrainz: Some(MbArtistRef::from_url_str(
|
musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str(
|
||||||
"https://musicbrainz.org/artist/11111111-1111-1111-1111-111111111111"
|
"https://musicbrainz.org/artist/11111111-1111-1111-1111-111111111111"
|
||||||
).unwrap()),
|
).unwrap()),
|
||||||
properties: HashMap::from([
|
properties: HashMap::from([
|
||||||
@ -155,7 +155,7 @@ macro_rules! full_collection {
|
|||||||
},
|
},
|
||||||
date: (2003, 6, 6).into(),
|
date: (2003, 6, 6).into(),
|
||||||
seq: AlbumSeq(1),
|
seq: AlbumSeq(1),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -194,7 +194,7 @@ macro_rules! full_collection {
|
|||||||
},
|
},
|
||||||
date: 2008.into(),
|
date: 2008.into(),
|
||||||
seq: AlbumSeq(3),
|
seq: AlbumSeq(3),
|
||||||
musicbrainz: Some(MbAlbumRef::from_url_str(
|
musicbrainz: MbRefOption::Some(MbAlbumRef::from_url_str(
|
||||||
"https://musicbrainz.org/release-group/11111111-1111-1111-1111-111111111111"
|
"https://musicbrainz.org/release-group/11111111-1111-1111-1111-111111111111"
|
||||||
).unwrap()),
|
).unwrap()),
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
@ -235,7 +235,7 @@ macro_rules! full_collection {
|
|||||||
},
|
},
|
||||||
date: 2009.into(),
|
date: 2009.into(),
|
||||||
seq: AlbumSeq(2),
|
seq: AlbumSeq(2),
|
||||||
musicbrainz: Some(MbAlbumRef::from_url_str(
|
musicbrainz: MbRefOption::Some(MbAlbumRef::from_url_str(
|
||||||
"https://musicbrainz.org/release-group/11111111-1111-1111-1111-111111111112"
|
"https://musicbrainz.org/release-group/11111111-1111-1111-1111-111111111112"
|
||||||
).unwrap()),
|
).unwrap()),
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
@ -276,7 +276,7 @@ macro_rules! full_collection {
|
|||||||
},
|
},
|
||||||
date: 2015.into(),
|
date: 2015.into(),
|
||||||
seq: AlbumSeq(4),
|
seq: AlbumSeq(4),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -318,9 +318,7 @@ macro_rules! full_collection {
|
|||||||
sort: Some(ArtistId {
|
sort: Some(ArtistId {
|
||||||
name: "Album_Artist ‘C’, The".to_string(),
|
name: "Album_Artist ‘C’, The".to_string(),
|
||||||
}),
|
}),
|
||||||
musicbrainz: Some(MbArtistRef::from_url_str(
|
musicbrainz: MbRefOption::CannotHaveMbid,
|
||||||
"https://musicbrainz.org/artist/11111111-1111-1111-1111-111111111111"
|
|
||||||
).unwrap()),
|
|
||||||
properties: HashMap::new(),
|
properties: HashMap::new(),
|
||||||
},
|
},
|
||||||
albums: vec![
|
albums: vec![
|
||||||
@ -331,7 +329,7 @@ macro_rules! full_collection {
|
|||||||
},
|
},
|
||||||
date: 1985.into(),
|
date: 1985.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -370,7 +368,7 @@ macro_rules! full_collection {
|
|||||||
},
|
},
|
||||||
date: 2018.into(),
|
date: 2018.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -410,7 +408,7 @@ macro_rules! full_collection {
|
|||||||
name: "Album_Artist ‘D’".to_string(),
|
name: "Album_Artist ‘D’".to_string(),
|
||||||
},
|
},
|
||||||
sort: None,
|
sort: None,
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
properties: HashMap::new(),
|
properties: HashMap::new(),
|
||||||
},
|
},
|
||||||
albums: vec![
|
albums: vec![
|
||||||
@ -421,7 +419,7 @@ macro_rules! full_collection {
|
|||||||
},
|
},
|
||||||
date: 1995.into(),
|
date: 1995.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -460,7 +458,7 @@ macro_rules! full_collection {
|
|||||||
},
|
},
|
||||||
date: 2028.into(),
|
date: 2028.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,7 @@ macro_rules! library_collection {
|
|||||||
name: "Album_Artist ‘A’".to_string(),
|
name: "Album_Artist ‘A’".to_string(),
|
||||||
},
|
},
|
||||||
sort: None,
|
sort: None,
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
properties: HashMap::new(),
|
properties: HashMap::new(),
|
||||||
},
|
},
|
||||||
albums: vec![
|
albums: vec![
|
||||||
@ -19,7 +19,7 @@ macro_rules! library_collection {
|
|||||||
},
|
},
|
||||||
date: 1998.into(),
|
date: 1998.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: None,
|
primary_type: None,
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -80,7 +80,7 @@ macro_rules! library_collection {
|
|||||||
},
|
},
|
||||||
date: (2015, 4).into(),
|
date: (2015, 4).into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: None,
|
primary_type: None,
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -117,7 +117,7 @@ macro_rules! library_collection {
|
|||||||
name: "Album_Artist ‘B’".to_string(),
|
name: "Album_Artist ‘B’".to_string(),
|
||||||
},
|
},
|
||||||
sort: None,
|
sort: None,
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
properties: HashMap::new(),
|
properties: HashMap::new(),
|
||||||
},
|
},
|
||||||
albums: vec![
|
albums: vec![
|
||||||
@ -128,7 +128,7 @@ macro_rules! library_collection {
|
|||||||
},
|
},
|
||||||
date: (2003, 6, 6).into(),
|
date: (2003, 6, 6).into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: None,
|
primary_type: None,
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -167,7 +167,7 @@ macro_rules! library_collection {
|
|||||||
},
|
},
|
||||||
date: 2008.into(),
|
date: 2008.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: None,
|
primary_type: None,
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -206,7 +206,7 @@ macro_rules! library_collection {
|
|||||||
},
|
},
|
||||||
date: 2009.into(),
|
date: 2009.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: None,
|
primary_type: None,
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -245,7 +245,7 @@ macro_rules! library_collection {
|
|||||||
},
|
},
|
||||||
date: 2015.into(),
|
date: 2015.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: None,
|
primary_type: None,
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -287,7 +287,7 @@ macro_rules! library_collection {
|
|||||||
sort: Some(ArtistId {
|
sort: Some(ArtistId {
|
||||||
name: "Album_Artist ‘C’, The".to_string(),
|
name: "Album_Artist ‘C’, The".to_string(),
|
||||||
}),
|
}),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
properties: HashMap::new(),
|
properties: HashMap::new(),
|
||||||
},
|
},
|
||||||
albums: vec![
|
albums: vec![
|
||||||
@ -298,7 +298,7 @@ macro_rules! library_collection {
|
|||||||
},
|
},
|
||||||
date: 1985.into(),
|
date: 1985.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: None,
|
primary_type: None,
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -337,7 +337,7 @@ macro_rules! library_collection {
|
|||||||
},
|
},
|
||||||
date: 2018.into(),
|
date: 2018.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: None,
|
primary_type: None,
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -377,7 +377,7 @@ macro_rules! library_collection {
|
|||||||
name: "Album_Artist ‘D’".to_string(),
|
name: "Album_Artist ‘D’".to_string(),
|
||||||
},
|
},
|
||||||
sort: None,
|
sort: None,
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
properties: HashMap::new(),
|
properties: HashMap::new(),
|
||||||
},
|
},
|
||||||
albums: vec![
|
albums: vec![
|
||||||
@ -388,7 +388,7 @@ macro_rules! library_collection {
|
|||||||
},
|
},
|
||||||
date: 1995.into(),
|
date: 1995.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: None,
|
primary_type: None,
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -427,7 +427,7 @@ macro_rules! library_collection {
|
|||||||
},
|
},
|
||||||
date: 2028.into(),
|
date: 2028.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: None,
|
primary_type: None,
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
|
@ -6,7 +6,7 @@ use std::{
|
|||||||
use musichoard::collection::{
|
use musichoard::collection::{
|
||||||
album::AlbumMeta,
|
album::AlbumMeta,
|
||||||
artist::{Artist, ArtistMeta},
|
artist::{Artist, ArtistMeta},
|
||||||
musicbrainz::{IMusicBrainzRef, Mbid},
|
musicbrainz::{IMusicBrainzRef, MbRefOption, Mbid},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
@ -35,9 +35,8 @@ impl FetchState {
|
|||||||
|
|
||||||
fn try_recv(&mut self) -> Result<MbApiResult, TryRecvError> {
|
fn try_recv(&mut self) -> Result<MbApiResult, TryRecvError> {
|
||||||
if let Some(lookup_rx) = &self.lookup_rx {
|
if let Some(lookup_rx) = &self.lookup_rx {
|
||||||
let result = lookup_rx.try_recv();
|
match lookup_rx.try_recv() {
|
||||||
match result {
|
x @ Ok(_) | x @ Err(TryRecvError::Empty) => return x,
|
||||||
Ok(_) | Err(TryRecvError::Empty) => return result,
|
|
||||||
Err(TryRecvError::Disconnected) => {
|
Err(TryRecvError::Disconnected) => {
|
||||||
self.lookup_rx.take();
|
self.lookup_rx.take();
|
||||||
}
|
}
|
||||||
@ -142,15 +141,16 @@ impl AppMachine<FetchState> {
|
|||||||
artist: &Artist,
|
artist: &Artist,
|
||||||
) -> Result<(), DaemonError> {
|
) -> Result<(), DaemonError> {
|
||||||
let requests = match artist.meta.musicbrainz {
|
let requests = match artist.meta.musicbrainz {
|
||||||
Some(ref arid) => {
|
MbRefOption::Some(ref arid) => {
|
||||||
let arid = arid.mbid();
|
let arid = arid.mbid();
|
||||||
let albums = artist.albums.iter();
|
let albums = artist.albums.iter();
|
||||||
albums
|
albums
|
||||||
.filter(|album| album.meta.musicbrainz.is_none())
|
.filter(|album| matches!(album.meta.musicbrainz, MbRefOption::None))
|
||||||
.map(|album| MbParams::search_release_group(arid.clone(), album.meta.clone()))
|
.map(|album| MbParams::search_release_group(arid.clone(), album.meta.clone()))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
None => VecDeque::from([MbParams::search_artist(artist.meta.clone())]),
|
MbRefOption::CannotHaveMbid => return Ok(()),
|
||||||
|
MbRefOption::None => VecDeque::from([MbParams::search_artist(artist.meta.clone())]),
|
||||||
};
|
};
|
||||||
musicbrainz.submit_background_job(result_sender, requests)
|
musicbrainz.submit_background_job(result_sender, requests)
|
||||||
}
|
}
|
||||||
@ -379,6 +379,20 @@ mod tests {
|
|||||||
AppMachine::app_lookup_artist(inner, fetch, &artist, mbid());
|
AppMachine::app_lookup_artist(inner, fetch, &artist, mbid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fetch_artist_cannot_have_mbid() {
|
||||||
|
let music_hoard = music_hoard(COLLECTION.to_owned());
|
||||||
|
let inner = inner(music_hoard);
|
||||||
|
|
||||||
|
// Use third artist to match the expectation.
|
||||||
|
let browse = AppMachine::browse_state(inner);
|
||||||
|
let browse = browse.increment_selection(Delta::Line).unwrap_browse();
|
||||||
|
let app = browse.increment_selection(Delta::Line);
|
||||||
|
|
||||||
|
let app = app.unwrap_browse().fetch_musicbrainz();
|
||||||
|
assert!(matches!(app, AppState::Match(_)));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fetch_artist_job_sender_err() {
|
fn fetch_artist_job_sender_err() {
|
||||||
let mut mb_job_sender = MockIMbJobSender::new();
|
let mut mb_job_sender = MockIMbJobSender::new();
|
||||||
|
10
src/tui/lib/external/musicbrainz/api/mod.rs
vendored
10
src/tui/lib/external/musicbrainz/api/mod.rs
vendored
@ -6,7 +6,7 @@ use musichoard::{
|
|||||||
collection::{
|
collection::{
|
||||||
album::{AlbumDate, AlbumMeta, AlbumSeq},
|
album::{AlbumDate, AlbumMeta, AlbumSeq},
|
||||||
artist::{ArtistId, ArtistMeta},
|
artist::{ArtistId, ArtistMeta},
|
||||||
musicbrainz::Mbid,
|
musicbrainz::{MbRefOption, Mbid},
|
||||||
},
|
},
|
||||||
external::musicbrainz::{
|
external::musicbrainz::{
|
||||||
api::{
|
api::{
|
||||||
@ -100,7 +100,7 @@ fn from_lookup_artist_response(entity: LookupArtistResponse) -> Lookup<ArtistMet
|
|||||||
item: ArtistMeta {
|
item: ArtistMeta {
|
||||||
id: entity.meta.name,
|
id: entity.meta.name,
|
||||||
sort,
|
sort,
|
||||||
musicbrainz: Some(entity.meta.id.into()),
|
musicbrainz: MbRefOption::Some(entity.meta.id.into()),
|
||||||
properties: HashMap::new(),
|
properties: HashMap::new(),
|
||||||
},
|
},
|
||||||
disambiguation: entity.meta.disambiguation,
|
disambiguation: entity.meta.disambiguation,
|
||||||
@ -113,7 +113,7 @@ fn from_lookup_release_group_response(entity: LookupReleaseGroupResponse) -> Loo
|
|||||||
id: entity.meta.title,
|
id: entity.meta.title,
|
||||||
date: entity.meta.first_release_date,
|
date: entity.meta.first_release_date,
|
||||||
seq: AlbumSeq::default(),
|
seq: AlbumSeq::default(),
|
||||||
musicbrainz: Some(entity.meta.id.into()),
|
musicbrainz: MbRefOption::Some(entity.meta.id.into()),
|
||||||
primary_type: Some(entity.meta.primary_type),
|
primary_type: Some(entity.meta.primary_type),
|
||||||
secondary_types: entity.meta.secondary_types.unwrap_or_default(),
|
secondary_types: entity.meta.secondary_types.unwrap_or_default(),
|
||||||
},
|
},
|
||||||
@ -130,7 +130,7 @@ fn from_search_artist_response_artist(entity: SearchArtistResponseArtist) -> Mat
|
|||||||
item: ArtistMeta {
|
item: ArtistMeta {
|
||||||
id: entity.meta.name,
|
id: entity.meta.name,
|
||||||
sort,
|
sort,
|
||||||
musicbrainz: Some(entity.meta.id.into()),
|
musicbrainz: MbRefOption::Some(entity.meta.id.into()),
|
||||||
properties: HashMap::new(),
|
properties: HashMap::new(),
|
||||||
},
|
},
|
||||||
disambiguation: entity.meta.disambiguation,
|
disambiguation: entity.meta.disambiguation,
|
||||||
@ -146,7 +146,7 @@ fn from_search_release_group_response_release_group(
|
|||||||
id: entity.meta.title,
|
id: entity.meta.title,
|
||||||
date: entity.meta.first_release_date,
|
date: entity.meta.first_release_date,
|
||||||
seq: AlbumSeq::default(),
|
seq: AlbumSeq::default(),
|
||||||
musicbrainz: Some(entity.meta.id.into()),
|
musicbrainz: MbRefOption::Some(entity.meta.id.into()),
|
||||||
primary_type: Some(entity.meta.primary_type),
|
primary_type: Some(entity.meta.primary_type),
|
||||||
secondary_types: entity.meta.secondary_types.unwrap_or_default(),
|
secondary_types: entity.meta.secondary_types.unwrap_or_default(),
|
||||||
},
|
},
|
||||||
|
25
src/tui/lib/external/musicbrainz/daemon/mod.rs
vendored
25
src/tui/lib/external/musicbrainz/daemon/mod.rs
vendored
@ -316,7 +316,7 @@ mod tests {
|
|||||||
use musichoard::collection::{
|
use musichoard::collection::{
|
||||||
album::AlbumMeta,
|
album::AlbumMeta,
|
||||||
artist::ArtistMeta,
|
artist::ArtistMeta,
|
||||||
musicbrainz::{IMusicBrainzRef, Mbid},
|
musicbrainz::{IMusicBrainzRef, MbRefOption, Mbid},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::tui::{
|
use crate::tui::{
|
||||||
@ -327,6 +327,21 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
fn mb_ref_opt_unwrap<T>(opt: MbRefOption<T>) -> T {
|
||||||
|
match opt {
|
||||||
|
MbRefOption::Some(val) => val,
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mb_ref_opt_as_ref<T>(opt: &MbRefOption<T>) -> MbRefOption<&T> {
|
||||||
|
match *opt {
|
||||||
|
MbRefOption::Some(ref x) => MbRefOption::Some(x),
|
||||||
|
MbRefOption::CannotHaveMbid => MbRefOption::CannotHaveMbid,
|
||||||
|
MbRefOption::None => MbRefOption::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn musicbrainz() -> MockIMusicBrainz {
|
fn musicbrainz() -> MockIMusicBrainz {
|
||||||
MockIMusicBrainz::new()
|
MockIMusicBrainz::new()
|
||||||
}
|
}
|
||||||
@ -403,8 +418,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn search_albums_requests() -> VecDeque<MbParams> {
|
fn search_albums_requests() -> VecDeque<MbParams> {
|
||||||
let mbref = COLLECTION[1].meta.musicbrainz.as_ref();
|
let mbref = mb_ref_opt_as_ref(&COLLECTION[1].meta.musicbrainz);
|
||||||
let arid = mbref.unwrap().mbid().clone();
|
let arid = mb_ref_opt_unwrap(mbref).mbid().clone();
|
||||||
|
|
||||||
let album_1 = COLLECTION[1].albums[0].meta.clone();
|
let album_1 = COLLECTION[1].albums[0].meta.clone();
|
||||||
let album_4 = COLLECTION[1].albums[3].meta.clone();
|
let album_4 = COLLECTION[1].albums[3].meta.clone();
|
||||||
@ -416,8 +431,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn album_arid_expectation() -> Mbid {
|
fn album_arid_expectation() -> Mbid {
|
||||||
let mbref = COLLECTION[1].meta.musicbrainz.as_ref();
|
let mbref = mb_ref_opt_as_ref(&COLLECTION[1].meta.musicbrainz);
|
||||||
mbref.unwrap().mbid().clone()
|
mb_ref_opt_unwrap(mbref).mbid().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_album_expectations_1() -> (AlbumMeta, Vec<Match<AlbumMeta>>) {
|
fn search_album_expectations_1() -> (AlbumMeta, Vec<Match<AlbumMeta>>) {
|
||||||
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
|||||||
use musichoard::collection::{
|
use musichoard::collection::{
|
||||||
album::{Album, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSeq},
|
album::{Album, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSeq},
|
||||||
artist::{Artist, ArtistId, ArtistMeta},
|
artist::{Artist, ArtistId, ArtistMeta},
|
||||||
musicbrainz::{MbAlbumRef, MbArtistRef},
|
musicbrainz::{MbAlbumRef, MbArtistRef, MbRefOption},
|
||||||
track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality},
|
track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality},
|
||||||
};
|
};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use musichoard::collection::{
|
use musichoard::collection::{
|
||||||
album::{AlbumDate, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq, AlbumStatus},
|
album::{AlbumDate, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq, AlbumStatus},
|
||||||
artist::ArtistMeta,
|
artist::ArtistMeta,
|
||||||
|
musicbrainz::{IMusicBrainzRef, MbRefOption},
|
||||||
track::{TrackFormat, TrackQuality},
|
track::{TrackFormat, TrackQuality},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -30,6 +31,14 @@ impl UiDisplay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn display_mb_ref_option_as_url<T: IMusicBrainzRef>(option: &MbRefOption<T>) -> &str {
|
||||||
|
match option {
|
||||||
|
MbRefOption::Some(val) => val.url().as_str(),
|
||||||
|
MbRefOption::CannotHaveMbid => "cannot have a MusicBrainz identifier",
|
||||||
|
MbRefOption::None => "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn display_type(
|
pub fn display_type(
|
||||||
primary: &Option<AlbumPrimaryType>,
|
primary: &Option<AlbumPrimaryType>,
|
||||||
secondary: &Vec<AlbumSecondaryType>,
|
secondary: &Vec<AlbumSecondaryType>,
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use musichoard::collection::{album::Album, artist::Artist, musicbrainz::IMusicBrainzRef};
|
use musichoard::collection::{album::Album, artist::Artist};
|
||||||
use ratatui::widgets::{ListState, Paragraph};
|
use ratatui::widgets::{ListState, Paragraph};
|
||||||
|
|
||||||
|
use super::display::UiDisplay;
|
||||||
|
|
||||||
struct InfoOverlay;
|
struct InfoOverlay;
|
||||||
|
|
||||||
impl InfoOverlay {
|
impl InfoOverlay {
|
||||||
@ -74,7 +76,7 @@ impl<'a> ArtistOverlay<'a> {
|
|||||||
Properties: {}",
|
Properties: {}",
|
||||||
artist.map(|a| a.meta.id.name.as_str()).unwrap_or(""),
|
artist.map(|a| a.meta.id.name.as_str()).unwrap_or(""),
|
||||||
artist
|
artist
|
||||||
.and_then(|a| a.meta.musicbrainz.as_ref().map(|mb| mb.url().as_str()))
|
.and_then(|a| Some(UiDisplay::display_mb_ref_option_as_url(&a.meta.musicbrainz)))
|
||||||
.unwrap_or(""),
|
.unwrap_or(""),
|
||||||
Self::opt_hashmap_to_string(
|
Self::opt_hashmap_to_string(
|
||||||
artist.map(|a| &a.meta.properties),
|
artist.map(|a| &a.meta.properties),
|
||||||
@ -102,7 +104,7 @@ impl<'a> AlbumOverlay<'a> {
|
|||||||
MusicBrainz: {}",
|
MusicBrainz: {}",
|
||||||
album.map(|a| a.meta.id.title.as_str()).unwrap_or(""),
|
album.map(|a| a.meta.id.title.as_str()).unwrap_or(""),
|
||||||
album
|
album
|
||||||
.and_then(|a| a.meta.musicbrainz.as_ref().map(|mb| mb.url().as_str()))
|
.and_then(|a| Some(UiDisplay::display_mb_ref_option_as_url(&a.meta.musicbrainz)))
|
||||||
.unwrap_or(""),
|
.unwrap_or(""),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -305,7 +305,15 @@ mod tests {
|
|||||||
|
|
||||||
draw_test_suite(artists, &mut selection);
|
draw_test_suite(artists, &mut selection);
|
||||||
|
|
||||||
|
// Change the artist (which cannot have a MBID).
|
||||||
|
selection.increment_selection(artists, Delta::Line);
|
||||||
|
selection.increment_selection(artists, Delta::Line);
|
||||||
|
|
||||||
|
draw_test_suite(artists, &mut selection);
|
||||||
|
|
||||||
// Change the track (which has a different track format).
|
// Change the track (which has a different track format).
|
||||||
|
selection.decrement_selection(artists, Delta::Line);
|
||||||
|
selection.decrement_selection(artists, Delta::Line);
|
||||||
selection.increment_category();
|
selection.increment_category();
|
||||||
selection.increment_category();
|
selection.increment_category();
|
||||||
selection.increment_selection(artists, Delta::Line);
|
selection.increment_selection(artists, Delta::Line);
|
||||||
|
@ -1 +1 @@
|
|||||||
{"V20240828":[{"name":"Аркона","sort":"Arkona","musicbrainz":"baad262d-55ef-427a-83c7-f7530964f212","properties":{"Bandcamp":["https://arkonamoscow.bandcamp.com/"],"MusicButler":["https://www.musicbutler.io/artist-page/283448581"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/arkona/download-streaming-albums"]},"albums":[{"title":"Slovo","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":[]}]},{"name":"Eluveitie","sort":null,"musicbrainz":"8000598a-5edb-401c-8e6d-36b167feaf38","properties":{"MusicButler":["https://www.musicbutler.io/artist-page/269358403"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/eluveitie/download-streaming-albums"]},"albums":[{"title":"Vên [re‐recorded]","seq":0,"musicbrainz":null,"primary_type":"Ep","secondary_types":[]},{"title":"Slania","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":[]}]},{"name":"Frontside","sort":null,"musicbrainz":"3a901353-fccd-4afd-ad01-9c03f451b490","properties":{"MusicButler":["https://www.musicbutler.io/artist-page/826588800"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/frontside/download-streaming-albums"]},"albums":[{"title":"…nasze jest królestwo, potęga i chwała na wieki…","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":[]}]},{"name":"Heaven’s Basement","sort":"Heaven’s Basement","musicbrainz":"c2c4d56a-d599-4a18-bd2f-ae644e2198cc","properties":{"MusicButler":["https://www.musicbutler.io/artist-page/291158685"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/heaven-s-basement/download-streaming-albums"]},"albums":[{"title":"Paper Plague","seq":0,"musicbrainz":null,"primary_type":null,"secondary_types":[]},{"title":"Unbreakable","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":[]}]},{"name":"Metallica","sort":null,"musicbrainz":"65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab","properties":{"MusicButler":["https://www.musicbutler.io/artist-page/3996865"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/metallica/download-streaming-albums"]},"albums":[{"title":"Ride the Lightning","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":[]},{"title":"S&M","seq":0,"musicbrainz":null,"primary_type":"Album","secondary_types":["Live"]}]}]}
|
{"V20240924":[{"name":"Аркона","sort":"Arkona","musicbrainz":{"Some":"baad262d-55ef-427a-83c7-f7530964f212"},"properties":{"Bandcamp":["https://arkonamoscow.bandcamp.com/"],"MusicButler":["https://www.musicbutler.io/artist-page/283448581"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/arkona/download-streaming-albums"]},"albums":[{"title":"Slovo","seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Eluveitie","sort":null,"musicbrainz":{"Some":"8000598a-5edb-401c-8e6d-36b167feaf38"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/269358403"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/eluveitie/download-streaming-albums"]},"albums":[{"title":"Vên [re‐recorded]","seq":0,"musicbrainz":"None","primary_type":"Ep","secondary_types":[]},{"title":"Slania","seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Frontside","sort":null,"musicbrainz":{"Some":"3a901353-fccd-4afd-ad01-9c03f451b490"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/826588800"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/frontside/download-streaming-albums"]},"albums":[{"title":"…nasze jest królestwo, potęga i chwała na wieki…","seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Heaven’s Basement","sort":"Heaven’s Basement","musicbrainz":{"Some":"c2c4d56a-d599-4a18-bd2f-ae644e2198cc"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/291158685"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/heaven-s-basement/download-streaming-albums"]},"albums":[{"title":"Paper Plague","seq":0,"musicbrainz":"None","primary_type":null,"secondary_types":[]},{"title":"Unbreakable","seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Metallica","sort":null,"musicbrainz":{"Some":"65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/3996865"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/metallica/download-streaming-albums"]},"albums":[{"title":"Ride the Lightning","seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]},{"title":"S&M","seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":["Live"]}]}]}
|
@ -4,7 +4,7 @@ use std::collections::HashMap;
|
|||||||
use musichoard::collection::{
|
use musichoard::collection::{
|
||||||
album::{Album, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq},
|
album::{Album, AlbumId, AlbumMeta, AlbumPrimaryType, AlbumSecondaryType, AlbumSeq},
|
||||||
artist::{Artist, ArtistId, ArtistMeta},
|
artist::{Artist, ArtistId, ArtistMeta},
|
||||||
musicbrainz::MbArtistRef,
|
musicbrainz::{MbArtistRef, MbRefOption},
|
||||||
track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality},
|
track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality},
|
||||||
Collection,
|
Collection,
|
||||||
};
|
};
|
||||||
@ -19,7 +19,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
|||||||
sort: Some(ArtistId{
|
sort: Some(ArtistId{
|
||||||
name: String::from("Arkona")
|
name: String::from("Arkona")
|
||||||
}),
|
}),
|
||||||
musicbrainz: Some(MbArtistRef::from_url_str(
|
musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str(
|
||||||
"https://musicbrainz.org/artist/baad262d-55ef-427a-83c7-f7530964f212"
|
"https://musicbrainz.org/artist/baad262d-55ef-427a-83c7-f7530964f212"
|
||||||
).unwrap()),
|
).unwrap()),
|
||||||
properties: HashMap::from([
|
properties: HashMap::from([
|
||||||
@ -41,7 +41,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
|||||||
},
|
},
|
||||||
date: 2011.into(),
|
date: 2011.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -209,7 +209,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
|||||||
name: String::from("Eluveitie"),
|
name: String::from("Eluveitie"),
|
||||||
},
|
},
|
||||||
sort: None,
|
sort: None,
|
||||||
musicbrainz: Some(MbArtistRef::from_url_str(
|
musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str(
|
||||||
"https://musicbrainz.org/artist/8000598a-5edb-401c-8e6d-36b167feaf38"
|
"https://musicbrainz.org/artist/8000598a-5edb-401c-8e6d-36b167feaf38"
|
||||||
).unwrap()),
|
).unwrap()),
|
||||||
properties: HashMap::from([
|
properties: HashMap::from([
|
||||||
@ -229,7 +229,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
|||||||
},
|
},
|
||||||
date: 2004.into(),
|
date: 2004.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: Some(AlbumPrimaryType::Ep),
|
primary_type: Some(AlbumPrimaryType::Ep),
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -309,7 +309,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
|||||||
},
|
},
|
||||||
date: 2008.into(),
|
date: 2008.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -456,7 +456,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
|||||||
name: String::from("Frontside"),
|
name: String::from("Frontside"),
|
||||||
},
|
},
|
||||||
sort: None,
|
sort: None,
|
||||||
musicbrainz: Some(MbArtistRef::from_url_str(
|
musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str(
|
||||||
"https://musicbrainz.org/artist/3a901353-fccd-4afd-ad01-9c03f451b490"
|
"https://musicbrainz.org/artist/3a901353-fccd-4afd-ad01-9c03f451b490"
|
||||||
).unwrap()),
|
).unwrap()),
|
||||||
properties: HashMap::from([
|
properties: HashMap::from([
|
||||||
@ -475,7 +475,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
|||||||
},
|
},
|
||||||
date: 2001.into(),
|
date: 2001.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -612,7 +612,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
|||||||
sort: Some(ArtistId {
|
sort: Some(ArtistId {
|
||||||
name: String::from("Heaven’s Basement"),
|
name: String::from("Heaven’s Basement"),
|
||||||
}),
|
}),
|
||||||
musicbrainz: Some(MbArtistRef::from_url_str(
|
musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str(
|
||||||
"https://musicbrainz.org/artist/c2c4d56a-d599-4a18-bd2f-ae644e2198cc"
|
"https://musicbrainz.org/artist/c2c4d56a-d599-4a18-bd2f-ae644e2198cc"
|
||||||
).unwrap()),
|
).unwrap()),
|
||||||
properties: HashMap::from([
|
properties: HashMap::from([
|
||||||
@ -631,7 +631,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
|||||||
},
|
},
|
||||||
date: 2011.into(),
|
date: 2011.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: None,
|
primary_type: None,
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -655,7 +655,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
|||||||
},
|
},
|
||||||
date: 2011.into(),
|
date: 2011.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -746,7 +746,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
|||||||
name: String::from("Metallica"),
|
name: String::from("Metallica"),
|
||||||
},
|
},
|
||||||
sort: None,
|
sort: None,
|
||||||
musicbrainz: Some(MbArtistRef::from_url_str(
|
musicbrainz: MbRefOption::Some(MbArtistRef::from_url_str(
|
||||||
"https://musicbrainz.org/artist/65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab"
|
"https://musicbrainz.org/artist/65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab"
|
||||||
).unwrap()),
|
).unwrap()),
|
||||||
properties: HashMap::from([
|
properties: HashMap::from([
|
||||||
@ -766,7 +766,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
|||||||
},
|
},
|
||||||
date: 1984.into(),
|
date: 1984.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
secondary_types: vec![],
|
secondary_types: vec![],
|
||||||
},
|
},
|
||||||
@ -868,7 +868,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
|||||||
},
|
},
|
||||||
date: 1999.into(),
|
date: 1999.into(),
|
||||||
seq: AlbumSeq(0),
|
seq: AlbumSeq(0),
|
||||||
musicbrainz: None,
|
musicbrainz: MbRefOption::None,
|
||||||
primary_type: Some(AlbumPrimaryType::Album),
|
primary_type: Some(AlbumPrimaryType::Album),
|
||||||
secondary_types: vec![AlbumSecondaryType::Live],
|
secondary_types: vec![AlbumSecondaryType::Live],
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user