Sort by <field>_sort from tags if it is available #107
@ -65,26 +65,28 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::{tests::COLLECTION, Artist, ArtistId, Collection, Format, IUrl};
|
use crate::{tests::COLLECTION, Artist, ArtistId, Collection, Format};
|
||||||
|
|
||||||
fn opt_to_url<U: IUrl>(opt: &Option<U>) -> String {
|
fn opt_to_str<S: AsRef<str>>(opt: &Option<S>) -> String {
|
||||||
match opt {
|
match opt {
|
||||||
Some(mb) => format!("\"{}\"", mb.url()),
|
Some(val) => format!("\"{}\"", val.as_ref()),
|
||||||
None => String::from("null"),
|
None => String::from("null"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vec_to_urls<U: IUrl>(vec: &[U]) -> String {
|
fn vec_to_str<S: AsRef<str>>(vec: &[S]) -> String {
|
||||||
let mut urls: Vec<String> = vec![];
|
let mut urls: Vec<String> = vec![];
|
||||||
for item in vec.iter() {
|
for item in vec.iter() {
|
||||||
urls.push(format!("\"{}\"", item.url()));
|
urls.push(format!("\"{}\"", item.as_ref()));
|
||||||
}
|
}
|
||||||
format!("[{}]", urls.join(","))
|
format!("[{}]", urls.join(","))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn artist_to_json(artist: &Artist) -> String {
|
fn artist_id_to_str(id: &ArtistId) -> String {
|
||||||
let album_artist = &artist.id.name;
|
format!("{{\"name\":\"{}\"}}", id.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn artist_to_json(artist: &Artist) -> String {
|
||||||
let mut albums: Vec<String> = vec![];
|
let mut albums: Vec<String> = vec![];
|
||||||
for album in artist.albums.iter() {
|
for album in artist.albums.iter() {
|
||||||
let album_year = album.id.year;
|
let album_year = album.id.year;
|
||||||
@ -127,10 +129,10 @@ mod tests {
|
|||||||
}
|
}
|
||||||
let albums = albums.join(",");
|
let albums = albums.join(",");
|
||||||
|
|
||||||
let musicbrainz = opt_to_url(&artist.properties.musicbrainz);
|
let musicbrainz = opt_to_str(&artist.properties.musicbrainz);
|
||||||
let musicbutler = vec_to_urls(&artist.properties.musicbutler);
|
let musicbutler = vec_to_str(&artist.properties.musicbutler);
|
||||||
let bandcamp = vec_to_urls(&artist.properties.bandcamp);
|
let bandcamp = vec_to_str(&artist.properties.bandcamp);
|
||||||
let qobuz = opt_to_url(&artist.properties.qobuz);
|
let qobuz = opt_to_str(&artist.properties.qobuz);
|
||||||
|
|
||||||
let properties = format!(
|
let properties = format!(
|
||||||
"{{\
|
"{{\
|
||||||
@ -141,9 +143,17 @@ mod tests {
|
|||||||
}}"
|
}}"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let album_artist = artist_id_to_str(&artist.id);
|
||||||
|
let album_artist_sort = artist
|
||||||
|
.sort
|
||||||
|
.as_ref()
|
||||||
|
.map(artist_id_to_str)
|
||||||
|
.unwrap_or_else(|| "null".to_string());
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
"{{\
|
"{{\
|
||||||
\"id\":{{\"name\":\"{album_artist}\"}},\
|
\"id\":{album_artist},\
|
||||||
|
\"sort\":{album_artist_sort},\
|
||||||
\"properties\":{properties},\
|
\"properties\":{properties},\
|
||||||
\"albums\":[{albums}]\
|
\"albums\":[{albums}]\
|
||||||
}}"
|
}}"
|
||||||
|
56
src/lib.rs
56
src/lib.rs
@ -18,11 +18,6 @@ use serde::{Deserialize, Serialize};
|
|||||||
use url::Url;
|
use url::Url;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
/// An object with the [`IUrl`] trait contains a valid URL.
|
|
||||||
pub trait IUrl {
|
|
||||||
fn url(&self) -> &str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An object with the [`IMbid`] trait contains a [MusicBrainz
|
/// An object with the [`IMbid`] trait contains a [MusicBrainz
|
||||||
/// Identifier](https://musicbrainz.org/doc/MusicBrainz_Identifier) (MBID).
|
/// Identifier](https://musicbrainz.org/doc/MusicBrainz_Identifier) (MBID).
|
||||||
pub trait IMbid {
|
pub trait IMbid {
|
||||||
@ -83,6 +78,12 @@ impl MusicBrainz {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<str> for MusicBrainz {
|
||||||
|
fn as_ref(&self) -> &str {
|
||||||
|
self.0.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFrom<&str> for MusicBrainz {
|
impl TryFrom<&str> for MusicBrainz {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
@ -97,12 +98,6 @@ impl Display for MusicBrainz {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IUrl for MusicBrainz {
|
|
||||||
fn url(&self) -> &str {
|
|
||||||
self.0.as_str()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IMbid for MusicBrainz {
|
impl IMbid for MusicBrainz {
|
||||||
fn mbid(&self) -> &str {
|
fn mbid(&self) -> &str {
|
||||||
// The URL is assumed to have been validated.
|
// The URL is assumed to have been validated.
|
||||||
@ -142,6 +137,12 @@ impl MusicButler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<str> for MusicButler {
|
||||||
|
fn as_ref(&self) -> &str {
|
||||||
|
self.0.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFrom<&str> for MusicButler {
|
impl TryFrom<&str> for MusicButler {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
@ -150,12 +151,6 @@ impl TryFrom<&str> for MusicButler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IUrl for MusicButler {
|
|
||||||
fn url(&self) -> &str {
|
|
||||||
self.0.as_str()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Bandcamp reference.
|
/// Bandcamp reference.
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct Bandcamp(Url);
|
pub struct Bandcamp(Url);
|
||||||
@ -188,6 +183,12 @@ impl Bandcamp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<str> for Bandcamp {
|
||||||
|
fn as_ref(&self) -> &str {
|
||||||
|
self.0.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFrom<&str> for Bandcamp {
|
impl TryFrom<&str> for Bandcamp {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
@ -196,12 +197,6 @@ impl TryFrom<&str> for Bandcamp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IUrl for Bandcamp {
|
|
||||||
fn url(&self) -> &str {
|
|
||||||
self.0.as_str()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Qobuz reference.
|
/// Qobuz reference.
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct Qobuz(Url);
|
pub struct Qobuz(Url);
|
||||||
@ -230,6 +225,12 @@ impl Qobuz {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<str> for Qobuz {
|
||||||
|
fn as_ref(&self) -> &str {
|
||||||
|
self.0.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFrom<&str> for Qobuz {
|
impl TryFrom<&str> for Qobuz {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
@ -244,12 +245,6 @@ impl Display for Qobuz {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IUrl for Qobuz {
|
|
||||||
fn url(&self) -> &str {
|
|
||||||
self.0.as_str()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The track file format.
|
/// The track file format.
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)]
|
||||||
pub enum Format {
|
pub enum Format {
|
||||||
@ -582,6 +577,7 @@ impl Ord for Artist {
|
|||||||
impl Merge for Artist {
|
impl Merge for Artist {
|
||||||
fn merge(mut self, other: Self) -> Self {
|
fn merge(mut self, other: Self) -> Self {
|
||||||
assert_eq!(self.id, other.id);
|
assert_eq!(self.id, other.id);
|
||||||
|
self.sort = Self::merge_opts(self.sort, other.sort);
|
||||||
self.properties = self.properties.merge(other.properties);
|
self.properties = self.properties.merge(other.properties);
|
||||||
self.albums = MergeSorted::new(self.albums.into_iter(), other.albums.into_iter()).collect();
|
self.albums = MergeSorted::new(self.albums.into_iter(), other.albums.into_iter()).collect();
|
||||||
self
|
self
|
||||||
@ -1126,7 +1122,7 @@ mod tests {
|
|||||||
let uuid = "d368baa8-21ca-4759-9731-0b2753071ad8";
|
let uuid = "d368baa8-21ca-4759-9731-0b2753071ad8";
|
||||||
let url = format!("https://musicbrainz.org/artist/{uuid}");
|
let url = format!("https://musicbrainz.org/artist/{uuid}");
|
||||||
let mb = MusicBrainz::new(&url).unwrap();
|
let mb = MusicBrainz::new(&url).unwrap();
|
||||||
assert_eq!(url, mb.url());
|
assert_eq!(url, mb.as_ref());
|
||||||
assert_eq!(uuid, mb.mbid());
|
assert_eq!(uuid, mb.mbid());
|
||||||
|
|
||||||
let url = "not a url at all".to_string();
|
let url = "not a url at all".to_string();
|
||||||
|
@ -126,7 +126,7 @@ impl<BLE: IBeetsLibraryExecutor> ILibraryPrivate for BeetsLibrary<BLE> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let split: Vec<&str> = line.split(LIST_FORMAT_SEPARATOR).collect();
|
let split: Vec<&str> = line.split(LIST_FORMAT_SEPARATOR).collect();
|
||||||
if split.len() != 8 {
|
if split.len() != 9 {
|
||||||
return Err(Error::Invalid(line.to_string()));
|
return Err(Error::Invalid(line.to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,8 +363,8 @@ mod tests {
|
|||||||
.split(LIST_FORMAT_SEPARATOR)
|
.split(LIST_FORMAT_SEPARATOR)
|
||||||
.map(|s| s.to_owned())
|
.map(|s| s.to_owned())
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>();
|
||||||
invalid_string[6].clear();
|
invalid_string[7].clear();
|
||||||
invalid_string[6].push_str("invalid format");
|
invalid_string[7].push_str("invalid format");
|
||||||
let invalid_string = invalid_string.join(LIST_FORMAT_SEPARATOR);
|
let invalid_string = invalid_string.join(LIST_FORMAT_SEPARATOR);
|
||||||
output[2] = invalid_string.clone();
|
output[2] = invalid_string.clone();
|
||||||
let result = Ok(output);
|
let result = Ok(output);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use musichoard::{Album, Artist, Collection, Format, IUrl, Track};
|
use musichoard::{Album, Artist, Collection, Format, Track};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
layout::{Alignment, Rect},
|
layout::{Alignment, Rect},
|
||||||
@ -409,20 +409,23 @@ struct ArtistOverlay<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ArtistOverlay<'a> {
|
impl<'a> ArtistOverlay<'a> {
|
||||||
fn opt_opt_to_str<U: IUrl>(opt: Option<Option<&U>>) -> &str {
|
fn opt_opt_to_str<S: AsRef<str>>(opt: Option<Option<&S>>) -> &str {
|
||||||
opt.flatten().map(|item| item.url()).unwrap_or("")
|
opt.flatten().map(|item| item.as_ref()).unwrap_or("")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opt_vec_to_string<U: IUrl>(opt_vec: Option<&Vec<U>>, indent: &str) -> String {
|
fn opt_vec_to_string<S: AsRef<str>>(opt_vec: Option<&Vec<S>>, indent: &str) -> String {
|
||||||
opt_vec
|
opt_vec
|
||||||
.map(|vec| {
|
.map(|vec| {
|
||||||
if vec.len() < 2 {
|
if vec.len() < 2 {
|
||||||
vec.first().map(|item| item.url()).unwrap_or("").to_string()
|
vec.first()
|
||||||
|
.map(|item| item.as_ref())
|
||||||
|
.unwrap_or("")
|
||||||
|
.to_string()
|
||||||
} else {
|
} else {
|
||||||
let indent = format!("\n{indent}");
|
let indent = format!("\n{indent}");
|
||||||
let list = vec
|
let list = vec
|
||||||
.iter()
|
.iter()
|
||||||
.map(|item| item.url())
|
.map(|item| item.as_ref())
|
||||||
.collect::<Vec<&str>>()
|
.collect::<Vec<&str>>()
|
||||||
.join(&indent);
|
.join(&indent);
|
||||||
format!("{indent}{list}")
|
format!("{indent}{list}")
|
||||||
|
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -108,7 +108,7 @@ fn test_album_artist_query() {
|
|||||||
.list(Query::new().include(Field::AlbumArtist(String::from("Аркона"))))
|
.list(Query::new().include(Field::AlbumArtist(String::from("Аркона"))))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let expected: Vec<Item> = artists_to_items(&COLLECTION[4..5]);
|
let expected: Vec<Item> = artists_to_items(&COLLECTION[0..1]);
|
||||||
assert_eq!(output, expected);
|
assert_eq!(output, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ fn test_album_title_query() {
|
|||||||
.list(Query::new().include(Field::AlbumTitle(String::from("Slovo"))))
|
.list(Query::new().include(Field::AlbumTitle(String::from("Slovo"))))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let expected: Vec<Item> = artists_to_items(&COLLECTION[4..5]);
|
let expected: Vec<Item> = artists_to_items(&COLLECTION[0..1]);
|
||||||
assert_eq!(output, expected);
|
assert_eq!(output, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ fn test_exclude_query() {
|
|||||||
let output = beets
|
let output = beets
|
||||||
.list(Query::new().exclude(Field::AlbumArtist(String::from("Аркона"))))
|
.list(Query::new().exclude(Field::AlbumArtist(String::from("Аркона"))))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let expected: Vec<Item> = artists_to_items(&COLLECTION[..4]);
|
let expected: Vec<Item> = artists_to_items(&COLLECTION[1..]);
|
||||||
|
|
||||||
let output: HashSet<_> = output.iter().collect();
|
let output: HashSet<_> = output.iter().collect();
|
||||||
let expected: HashSet<_> = expected.iter().collect();
|
let expected: HashSet<_> = expected.iter().collect();
|
||||||
|
372
tests/testlib.rs
372
tests/testlib.rs
@ -6,6 +6,190 @@ use once_cell::sync::Lazy;
|
|||||||
|
|
||||||
pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
||||||
vec![
|
vec![
|
||||||
|
Artist {
|
||||||
|
id: ArtistId {
|
||||||
|
name: String::from("Аркона"),
|
||||||
|
},
|
||||||
|
sort: Some(ArtistId{
|
||||||
|
name: String::from("Arkona")
|
||||||
|
}),
|
||||||
|
properties: ArtistProperties {
|
||||||
|
musicbrainz: Some(MusicBrainz::new(
|
||||||
|
"https://musicbrainz.org/artist/baad262d-55ef-427a-83c7-f7530964f212",
|
||||||
|
).unwrap()),
|
||||||
|
musicbutler: vec![
|
||||||
|
MusicButler::new("https://www.musicbutler.io/artist-page/283448581").unwrap(),
|
||||||
|
],
|
||||||
|
bandcamp: vec![
|
||||||
|
Bandcamp::new("https://arkonamoscow.bandcamp.com/").unwrap(),
|
||||||
|
],
|
||||||
|
qobuz: Some(Qobuz::new(
|
||||||
|
"https://www.qobuz.com/nl-nl/interpreter/arkona/download-streaming-albums",
|
||||||
|
).unwrap()),
|
||||||
|
},
|
||||||
|
albums: vec![Album {
|
||||||
|
id: AlbumId {
|
||||||
|
year: 2011,
|
||||||
|
title: String::from("Slovo"),
|
||||||
|
},
|
||||||
|
tracks: vec![
|
||||||
|
Track {
|
||||||
|
id: TrackId {
|
||||||
|
number: 1,
|
||||||
|
title: String::from("Az’"),
|
||||||
|
},
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
quality: Quality {
|
||||||
|
format: Format::Flac,
|
||||||
|
bitrate: 992,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
id: TrackId {
|
||||||
|
number: 2,
|
||||||
|
title: String::from("Arkaim"),
|
||||||
|
},
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
quality: Quality {
|
||||||
|
format: Format::Flac,
|
||||||
|
bitrate: 1061,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
id: TrackId {
|
||||||
|
number: 3,
|
||||||
|
title: String::from("Bol’no mne"),
|
||||||
|
},
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
quality: Quality {
|
||||||
|
format: Format::Flac,
|
||||||
|
bitrate: 1004,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
id: TrackId {
|
||||||
|
number: 4,
|
||||||
|
title: String::from("Leshiy"),
|
||||||
|
},
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
quality: Quality {
|
||||||
|
format: Format::Flac,
|
||||||
|
bitrate: 1077,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
id: TrackId {
|
||||||
|
number: 5,
|
||||||
|
title: String::from("Zakliatie"),
|
||||||
|
},
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
quality: Quality {
|
||||||
|
format: Format::Flac,
|
||||||
|
bitrate: 1041,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
id: TrackId {
|
||||||
|
number: 6,
|
||||||
|
title: String::from("Predok"),
|
||||||
|
},
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
quality: Quality {
|
||||||
|
format: Format::Flac,
|
||||||
|
bitrate: 756,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
id: TrackId {
|
||||||
|
number: 7,
|
||||||
|
title: String::from("Nikogda"),
|
||||||
|
},
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
quality: Quality {
|
||||||
|
format: Format::Flac,
|
||||||
|
bitrate: 1059,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
id: TrackId {
|
||||||
|
number: 8,
|
||||||
|
title: String::from("Tam za tumanami"),
|
||||||
|
},
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
quality: Quality {
|
||||||
|
format: Format::Flac,
|
||||||
|
bitrate: 1023,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
id: TrackId {
|
||||||
|
number: 9,
|
||||||
|
title: String::from("Potomok"),
|
||||||
|
},
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
quality: Quality {
|
||||||
|
format: Format::Flac,
|
||||||
|
bitrate: 838,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
id: TrackId {
|
||||||
|
number: 10,
|
||||||
|
title: String::from("Slovo"),
|
||||||
|
},
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
quality: Quality {
|
||||||
|
format: Format::Flac,
|
||||||
|
bitrate: 1028,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
id: TrackId {
|
||||||
|
number: 11,
|
||||||
|
title: String::from("Odna"),
|
||||||
|
},
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
quality: Quality {
|
||||||
|
format: Format::Flac,
|
||||||
|
bitrate: 991,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
id: TrackId {
|
||||||
|
number: 12,
|
||||||
|
title: String::from("Vo moiom sadochke…"),
|
||||||
|
},
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
quality: Quality {
|
||||||
|
format: Format::Flac,
|
||||||
|
bitrate: 919,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
id: TrackId {
|
||||||
|
number: 13,
|
||||||
|
title: String::from("Stenka na stenku"),
|
||||||
|
},
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
quality: Quality {
|
||||||
|
format: Format::Flac,
|
||||||
|
bitrate: 1039,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Track {
|
||||||
|
id: TrackId {
|
||||||
|
number: 14,
|
||||||
|
title: String::from("Zimushka"),
|
||||||
|
},
|
||||||
|
artist: vec![String::from("Аркона")],
|
||||||
|
quality: Quality {
|
||||||
|
format: Format::Flac,
|
||||||
|
bitrate: 974,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
},
|
||||||
Artist {
|
Artist {
|
||||||
id: ArtistId {
|
id: ArtistId {
|
||||||
name: String::from("Eluveitie"),
|
name: String::from("Eluveitie"),
|
||||||
@ -391,7 +575,9 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
|||||||
id: ArtistId {
|
id: ArtistId {
|
||||||
name: String::from("Heaven’s Basement"),
|
name: String::from("Heaven’s Basement"),
|
||||||
},
|
},
|
||||||
sort: None,
|
sort: Some(ArtistId {
|
||||||
|
name: String::from("Heaven’s Basement"),
|
||||||
|
}),
|
||||||
properties: ArtistProperties {
|
properties: ArtistProperties {
|
||||||
musicbrainz: Some(MusicBrainz::new(
|
musicbrainz: Some(MusicBrainz::new(
|
||||||
"https://musicbrainz.org/artist/c2c4d56a-d599-4a18-bd2f-ae644e2198cc",
|
"https://musicbrainz.org/artist/c2c4d56a-d599-4a18-bd2f-ae644e2198cc",
|
||||||
@ -863,189 +1049,5 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
Artist {
|
|
||||||
id: ArtistId {
|
|
||||||
name: String::from("Аркона"),
|
|
||||||
},
|
|
||||||
sort: Some(ArtistId{
|
|
||||||
name: String::from("Arkona")
|
|
||||||
}),
|
|
||||||
properties: ArtistProperties {
|
|
||||||
musicbrainz: Some(MusicBrainz::new(
|
|
||||||
"https://musicbrainz.org/artist/baad262d-55ef-427a-83c7-f7530964f212",
|
|
||||||
).unwrap()),
|
|
||||||
musicbutler: vec![
|
|
||||||
MusicButler::new("https://www.musicbutler.io/artist-page/283448581").unwrap(),
|
|
||||||
],
|
|
||||||
bandcamp: vec![
|
|
||||||
Bandcamp::new("https://arkonamoscow.bandcamp.com/").unwrap(),
|
|
||||||
],
|
|
||||||
qobuz: Some(Qobuz::new(
|
|
||||||
"https://www.qobuz.com/nl-nl/interpreter/arkona/download-streaming-albums",
|
|
||||||
).unwrap()),
|
|
||||||
},
|
|
||||||
albums: vec![Album {
|
|
||||||
id: AlbumId {
|
|
||||||
year: 2011,
|
|
||||||
title: String::from("Slovo"),
|
|
||||||
},
|
|
||||||
tracks: vec![
|
|
||||||
Track {
|
|
||||||
id: TrackId {
|
|
||||||
number: 1,
|
|
||||||
title: String::from("Az’"),
|
|
||||||
},
|
|
||||||
artist: vec![String::from("Аркона")],
|
|
||||||
quality: Quality {
|
|
||||||
format: Format::Flac,
|
|
||||||
bitrate: 992,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
id: TrackId {
|
|
||||||
number: 2,
|
|
||||||
title: String::from("Arkaim"),
|
|
||||||
},
|
|
||||||
artist: vec![String::from("Аркона")],
|
|
||||||
quality: Quality {
|
|
||||||
format: Format::Flac,
|
|
||||||
bitrate: 1061,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
id: TrackId {
|
|
||||||
number: 3,
|
|
||||||
title: String::from("Bol’no mne"),
|
|
||||||
},
|
|
||||||
artist: vec![String::from("Аркона")],
|
|
||||||
quality: Quality {
|
|
||||||
format: Format::Flac,
|
|
||||||
bitrate: 1004,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
id: TrackId {
|
|
||||||
number: 4,
|
|
||||||
title: String::from("Leshiy"),
|
|
||||||
},
|
|
||||||
artist: vec![String::from("Аркона")],
|
|
||||||
quality: Quality {
|
|
||||||
format: Format::Flac,
|
|
||||||
bitrate: 1077,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
id: TrackId {
|
|
||||||
number: 5,
|
|
||||||
title: String::from("Zakliatie"),
|
|
||||||
},
|
|
||||||
artist: vec![String::from("Аркона")],
|
|
||||||
quality: Quality {
|
|
||||||
format: Format::Flac,
|
|
||||||
bitrate: 1041,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
id: TrackId {
|
|
||||||
number: 6,
|
|
||||||
title: String::from("Predok"),
|
|
||||||
},
|
|
||||||
artist: vec![String::from("Аркона")],
|
|
||||||
quality: Quality {
|
|
||||||
format: Format::Flac,
|
|
||||||
bitrate: 756,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
id: TrackId {
|
|
||||||
number: 7,
|
|
||||||
title: String::from("Nikogda"),
|
|
||||||
},
|
|
||||||
artist: vec![String::from("Аркона")],
|
|
||||||
quality: Quality {
|
|
||||||
format: Format::Flac,
|
|
||||||
bitrate: 1059,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
id: TrackId {
|
|
||||||
number: 8,
|
|
||||||
title: String::from("Tam za tumanami"),
|
|
||||||
},
|
|
||||||
artist: vec![String::from("Аркона")],
|
|
||||||
quality: Quality {
|
|
||||||
format: Format::Flac,
|
|
||||||
bitrate: 1023,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
id: TrackId {
|
|
||||||
number: 9,
|
|
||||||
title: String::from("Potomok"),
|
|
||||||
},
|
|
||||||
artist: vec![String::from("Аркона")],
|
|
||||||
quality: Quality {
|
|
||||||
format: Format::Flac,
|
|
||||||
bitrate: 838,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
id: TrackId {
|
|
||||||
number: 10,
|
|
||||||
title: String::from("Slovo"),
|
|
||||||
},
|
|
||||||
artist: vec![String::from("Аркона")],
|
|
||||||
quality: Quality {
|
|
||||||
format: Format::Flac,
|
|
||||||
bitrate: 1028,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
id: TrackId {
|
|
||||||
number: 11,
|
|
||||||
title: String::from("Odna"),
|
|
||||||
},
|
|
||||||
artist: vec![String::from("Аркона")],
|
|
||||||
quality: Quality {
|
|
||||||
format: Format::Flac,
|
|
||||||
bitrate: 991,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
id: TrackId {
|
|
||||||
number: 12,
|
|
||||||
title: String::from("Vo moiom sadochke…"),
|
|
||||||
},
|
|
||||||
artist: vec![String::from("Аркона")],
|
|
||||||
quality: Quality {
|
|
||||||
format: Format::Flac,
|
|
||||||
bitrate: 919,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
id: TrackId {
|
|
||||||
number: 13,
|
|
||||||
title: String::from("Stenka na stenku"),
|
|
||||||
},
|
|
||||||
artist: vec![String::from("Аркона")],
|
|
||||||
quality: Quality {
|
|
||||||
format: Format::Flac,
|
|
||||||
bitrate: 1039,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Track {
|
|
||||||
id: TrackId {
|
|
||||||
number: 14,
|
|
||||||
title: String::from("Zimushka"),
|
|
||||||
},
|
|
||||||
artist: vec![String::from("Аркона")],
|
|
||||||
quality: Quality {
|
|
||||||
format: Format::Flac,
|
|
||||||
bitrate: 974,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user