tests: run tests with different lang settings
fix: parsing subscriber count on channel search itms fix: add warnings for all date and numstr parsing fix: error parsing search suggestions
This commit is contained in:
parent
6a99540ef5
commit
b88faa9d05
32 changed files with 6501 additions and 214 deletions
|
|
@ -179,8 +179,11 @@ impl MapResponse<Channel<Paginator<VideoItem>>> for response::Channel {
|
||||||
lang,
|
lang,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut mapper =
|
let mut mapper = response::YouTubeListMapper::<VideoItem>::with_channel(
|
||||||
response::YouTubeListMapper::<VideoItem>::with_channel(lang, &channel_data);
|
lang,
|
||||||
|
&channel_data.c,
|
||||||
|
channel_data.warnings,
|
||||||
|
);
|
||||||
mapper.map_response(content.content);
|
mapper.map_response(content.content);
|
||||||
let p = Paginator::new_ext(
|
let p = Paginator::new_ext(
|
||||||
None,
|
None,
|
||||||
|
|
@ -191,7 +194,7 @@ impl MapResponse<Channel<Paginator<VideoItem>>> for response::Channel {
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(MapResult {
|
Ok(MapResult {
|
||||||
c: combine_channel_data(channel_data, p),
|
c: combine_channel_data(channel_data.c, p),
|
||||||
warnings: mapper.warnings,
|
warnings: mapper.warnings,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -219,13 +222,16 @@ impl MapResponse<Channel<Paginator<PlaylistItem>>> for response::Channel {
|
||||||
lang,
|
lang,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut mapper =
|
let mut mapper = response::YouTubeListMapper::<PlaylistItem>::with_channel(
|
||||||
response::YouTubeListMapper::<PlaylistItem>::with_channel(lang, &channel_data);
|
lang,
|
||||||
|
&channel_data.c,
|
||||||
|
channel_data.warnings,
|
||||||
|
);
|
||||||
mapper.map_response(content.content);
|
mapper.map_response(content.content);
|
||||||
let p = Paginator::new(None, mapper.items, mapper.ctoken);
|
let p = Paginator::new(None, mapper.items, mapper.ctoken);
|
||||||
|
|
||||||
Ok(MapResult {
|
Ok(MapResult {
|
||||||
c: combine_channel_data(channel_data, p),
|
c: combine_channel_data(channel_data.c, p),
|
||||||
warnings: mapper.warnings,
|
warnings: mapper.warnings,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -266,7 +272,7 @@ impl MapResponse<Channel<ChannelInfo>> for response::Channel {
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(MapResult {
|
Ok(MapResult {
|
||||||
c: combine_channel_data(channel_data, cinfo),
|
c: combine_channel_data(channel_data.c, cinfo),
|
||||||
warnings,
|
warnings,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -297,7 +303,7 @@ fn map_channel(
|
||||||
d: MapChannelData,
|
d: MapChannelData,
|
||||||
id: &str,
|
id: &str,
|
||||||
lang: Language,
|
lang: Language,
|
||||||
) -> Result<Channel<()>, ExtractionError> {
|
) -> Result<MapResult<Channel<()>>, ExtractionError> {
|
||||||
let header = d
|
let header = d
|
||||||
.header
|
.header
|
||||||
.ok_or(ExtractionError::ContentUnavailable(Cow::Borrowed(
|
.ok_or(ExtractionError::ContentUnavailable(Cow::Borrowed(
|
||||||
|
|
@ -326,33 +332,35 @@ fn map_channel(
|
||||||
.vanity_channel_url
|
.vanity_channel_url
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|url| map_vanity_url(url, id));
|
.and_then(|url| map_vanity_url(url, id));
|
||||||
|
let mut warnings = Vec::new();
|
||||||
|
|
||||||
Ok(match header {
|
Ok(MapResult {
|
||||||
response::channel::Header::C4TabbedHeaderRenderer(header) => Channel {
|
c: match header {
|
||||||
id: metadata.external_id,
|
response::channel::Header::C4TabbedHeaderRenderer(header) => Channel {
|
||||||
name: metadata.title,
|
id: metadata.external_id,
|
||||||
subscriber_count: header
|
name: metadata.title,
|
||||||
.subscriber_count_text
|
subscriber_count: header
|
||||||
.and_then(|txt| util::parse_large_numstr(&txt, lang)),
|
.subscriber_count_text
|
||||||
avatar: header.avatar.into(),
|
.and_then(|txt| util::parse_large_numstr_or_warn(&txt, lang, &mut warnings)),
|
||||||
verification: header.badges.into(),
|
avatar: header.avatar.into(),
|
||||||
description: metadata.description,
|
verification: header.badges.into(),
|
||||||
tags: microformat.microformat_data_renderer.tags,
|
description: metadata.description,
|
||||||
vanity_url,
|
tags: microformat.microformat_data_renderer.tags,
|
||||||
banner: header.banner.into(),
|
vanity_url,
|
||||||
mobile_banner: header.mobile_banner.into(),
|
banner: header.banner.into(),
|
||||||
tv_banner: header.tv_banner.into(),
|
mobile_banner: header.mobile_banner.into(),
|
||||||
has_shorts: d.has_shorts,
|
tv_banner: header.tv_banner.into(),
|
||||||
has_live: d.has_live,
|
has_shorts: d.has_shorts,
|
||||||
visitor_data: d.visitor_data,
|
has_live: d.has_live,
|
||||||
content: (),
|
visitor_data: d.visitor_data,
|
||||||
},
|
content: (),
|
||||||
response::channel::Header::CarouselHeaderRenderer(carousel) => {
|
},
|
||||||
let hdata = carousel
|
response::channel::Header::CarouselHeaderRenderer(carousel) => {
|
||||||
.contents
|
let hdata = carousel
|
||||||
.into_iter()
|
.contents
|
||||||
.filter_map(|item| {
|
.into_iter()
|
||||||
match item {
|
.filter_map(|item| {
|
||||||
|
match item {
|
||||||
response::channel::CarouselHeaderRendererItem::TopicChannelDetailsRenderer {
|
response::channel::CarouselHeaderRendererItem::TopicChannelDetailsRenderer {
|
||||||
subscriber_count_text,
|
subscriber_count_text,
|
||||||
subtitle,
|
subtitle,
|
||||||
|
|
@ -360,32 +368,33 @@ fn map_channel(
|
||||||
} => Some((subscriber_count_text.or(subtitle), avatar)),
|
} => Some((subscriber_count_text.or(subtitle), avatar)),
|
||||||
response::channel::CarouselHeaderRendererItem::None => None,
|
response::channel::CarouselHeaderRendererItem::None => None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.next();
|
.next();
|
||||||
|
|
||||||
Channel {
|
Channel {
|
||||||
id: metadata.external_id,
|
id: metadata.external_id,
|
||||||
name: metadata.title,
|
name: metadata.title,
|
||||||
subscriber_count: hdata.as_ref().and_then(|hdata| {
|
subscriber_count: hdata.as_ref().and_then(|hdata| {
|
||||||
hdata
|
hdata.0.as_ref().and_then(|txt| {
|
||||||
.0
|
util::parse_large_numstr_or_warn(txt, lang, &mut warnings)
|
||||||
.as_ref()
|
})
|
||||||
.and_then(|txt| util::parse_large_numstr(txt, lang))
|
}),
|
||||||
}),
|
avatar: hdata.map(|hdata| hdata.1.into()).unwrap_or_default(),
|
||||||
avatar: hdata.map(|hdata| hdata.1.into()).unwrap_or_default(),
|
verification: crate::model::Verification::Verified,
|
||||||
verification: crate::model::Verification::Verified,
|
description: metadata.description,
|
||||||
description: metadata.description,
|
tags: microformat.microformat_data_renderer.tags,
|
||||||
tags: microformat.microformat_data_renderer.tags,
|
vanity_url,
|
||||||
vanity_url,
|
banner: Vec::new(),
|
||||||
banner: Vec::new(),
|
mobile_banner: Vec::new(),
|
||||||
mobile_banner: Vec::new(),
|
tv_banner: Vec::new(),
|
||||||
tv_banner: Vec::new(),
|
has_shorts: d.has_shorts,
|
||||||
has_shorts: d.has_shorts,
|
has_live: d.has_live,
|
||||||
has_live: d.has_live,
|
visitor_data: d.visitor_data,
|
||||||
visitor_data: d.visitor_data,
|
content: (),
|
||||||
content: (),
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
warnings,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -269,7 +269,7 @@ fn map_artist_page(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mapped = mapper.group_items();
|
let mut mapped = mapper.group_items();
|
||||||
|
|
||||||
static WIKIPEDIA_REGEX: Lazy<Regex> =
|
static WIKIPEDIA_REGEX: Lazy<Regex> =
|
||||||
Lazy::new(|| Regex::new(r"\(?https://[a-z\d-]+\.wikipedia.org/wiki/[^\s]+").unwrap());
|
Lazy::new(|| Regex::new(r"\(?https://[a-z\d-]+\.wikipedia.org/wiki/[^\s]+").unwrap());
|
||||||
|
|
@ -302,9 +302,10 @@ fn map_artist_page(
|
||||||
description: header.description,
|
description: header.description,
|
||||||
wikipedia_url,
|
wikipedia_url,
|
||||||
subscriber_count: header.subscription_button.and_then(|btn| {
|
subscriber_count: header.subscription_button.and_then(|btn| {
|
||||||
util::parse_large_numstr(
|
util::parse_large_numstr_or_warn(
|
||||||
&btn.subscribe_button_renderer.subscriber_count_text,
|
&btn.subscribe_button_renderer.subscriber_count_text,
|
||||||
lang,
|
lang,
|
||||||
|
&mut mapped.warnings,
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
tracks: mapped.c.tracks,
|
tracks: mapped.c.tracks,
|
||||||
|
|
|
||||||
|
|
@ -207,22 +207,25 @@ impl MapResponse<TrackDetails> for response::MusicDetails {
|
||||||
response::music_item::PlaylistPanelVideo::None => None,
|
response::music_item::PlaylistPanelVideo::None => None,
|
||||||
})
|
})
|
||||||
.ok_or(ExtractionError::InvalidData(Cow::Borrowed("no video item")))?;
|
.ok_or(ExtractionError::InvalidData(Cow::Borrowed("no video item")))?;
|
||||||
let track = map_queue_item(track_item, lang);
|
let mut track = map_queue_item(track_item, lang);
|
||||||
|
|
||||||
if track.id != id {
|
if track.c.id != id {
|
||||||
return Err(ExtractionError::WrongResult(format!(
|
return Err(ExtractionError::WrongResult(format!(
|
||||||
"got wrong video id {}, expected {}",
|
"got wrong video id {}, expected {}",
|
||||||
track.id, id
|
track.c.id, id
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut warnings = content.contents.warnings;
|
||||||
|
warnings.append(&mut track.warnings);
|
||||||
|
|
||||||
Ok(MapResult {
|
Ok(MapResult {
|
||||||
c: TrackDetails {
|
c: TrackDetails {
|
||||||
track,
|
track: track.c,
|
||||||
lyrics_id,
|
lyrics_id,
|
||||||
related_id,
|
related_id,
|
||||||
},
|
},
|
||||||
warnings: content.contents.warnings,
|
warnings,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -251,13 +254,17 @@ impl MapResponse<Paginator<TrackItem>> for response::MusicDetails {
|
||||||
.content
|
.content
|
||||||
.playlist_panel_renderer;
|
.playlist_panel_renderer;
|
||||||
|
|
||||||
|
let mut warnings = content.contents.warnings;
|
||||||
|
|
||||||
let tracks = content
|
let tracks = content
|
||||||
.contents
|
.contents
|
||||||
.c
|
.c
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|item| match item {
|
.filter_map(|item| match item {
|
||||||
response::music_item::PlaylistPanelVideo::PlaylistPanelVideoRenderer(item) => {
|
response::music_item::PlaylistPanelVideo::PlaylistPanelVideoRenderer(item) => {
|
||||||
Some(map_queue_item(item, lang))
|
let mut track = map_queue_item(item, lang);
|
||||||
|
warnings.append(&mut track.warnings);
|
||||||
|
Some(track.c)
|
||||||
}
|
}
|
||||||
response::music_item::PlaylistPanelVideo::None => None,
|
response::music_item::PlaylistPanelVideo::None => None,
|
||||||
})
|
})
|
||||||
|
|
@ -277,7 +284,7 @@ impl MapResponse<Paginator<TrackItem>> for response::MusicDetails {
|
||||||
None,
|
None,
|
||||||
crate::model::paginator::ContinuationEndpoint::MusicNext,
|
crate::model::paginator::ContinuationEndpoint::MusicNext,
|
||||||
),
|
),
|
||||||
warnings: content.contents.warnings,
|
warnings,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,9 @@ impl MapResponse<Paginator<MusicItem>> for response::MusicContinuation {
|
||||||
mapper.add_warnings(&mut panel.contents.warnings);
|
mapper.add_warnings(&mut panel.contents.warnings);
|
||||||
panel.contents.c.into_iter().for_each(|item| {
|
panel.contents.c.into_iter().for_each(|item| {
|
||||||
if let PlaylistPanelVideo::PlaylistPanelVideoRenderer(item) = item {
|
if let PlaylistPanelVideo::PlaylistPanelVideoRenderer(item) = item {
|
||||||
mapper.add_item(MusicItem::Track(map_queue_item(item, lang)))
|
let mut track = map_queue_item(item, lang);
|
||||||
|
mapper.add_item(MusicItem::Track(track.c));
|
||||||
|
mapper.add_warnings(&mut track.warnings);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -618,7 +618,11 @@ impl MusicListMapper {
|
||||||
(FlexColumnDisplayStyle::TwoLines, true) => (
|
(FlexColumnDisplayStyle::TwoLines, true) => (
|
||||||
None,
|
None,
|
||||||
album_p.and_then(|p| {
|
album_p.and_then(|p| {
|
||||||
util::parse_large_numstr(p.first_str(), self.lang)
|
util::parse_large_numstr_or_warn(
|
||||||
|
p.first_str(),
|
||||||
|
self.lang,
|
||||||
|
&mut self.warnings,
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
(_, false) => (
|
(_, false) => (
|
||||||
|
|
@ -692,7 +696,11 @@ impl MusicListMapper {
|
||||||
match page_type {
|
match page_type {
|
||||||
MusicPageType::Artist => {
|
MusicPageType::Artist => {
|
||||||
let subscriber_count = subtitle_p2.and_then(|p| {
|
let subscriber_count = subtitle_p2.and_then(|p| {
|
||||||
util::parse_large_numstr(p.first_str(), self.lang)
|
util::parse_large_numstr_or_warn(
|
||||||
|
p.first_str(),
|
||||||
|
self.lang,
|
||||||
|
&mut self.warnings,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
self.items.push(MusicItem::Artist(ArtistItem {
|
self.items.push(MusicItem::Artist(ArtistItem {
|
||||||
|
|
@ -792,7 +800,11 @@ impl MusicListMapper {
|
||||||
artists,
|
artists,
|
||||||
album: None,
|
album: None,
|
||||||
view_count: subtitle_p2.and_then(|c| {
|
view_count: subtitle_p2.and_then(|c| {
|
||||||
util::parse_large_numstr(c.first_str(), self.lang)
|
util::parse_large_numstr_or_warn(
|
||||||
|
c.first_str(),
|
||||||
|
self.lang,
|
||||||
|
&mut self.warnings,
|
||||||
|
)
|
||||||
}),
|
}),
|
||||||
is_video,
|
is_video,
|
||||||
track_nr: None,
|
track_nr: None,
|
||||||
|
|
@ -801,8 +813,13 @@ impl MusicListMapper {
|
||||||
Ok(Some(MusicItemType::Track))
|
Ok(Some(MusicItemType::Track))
|
||||||
}
|
}
|
||||||
MusicPageType::Artist => {
|
MusicPageType::Artist => {
|
||||||
let subscriber_count = subtitle_p1
|
let subscriber_count = subtitle_p1.and_then(|p| {
|
||||||
.and_then(|p| util::parse_large_numstr(p.first_str(), self.lang));
|
util::parse_large_numstr_or_warn(
|
||||||
|
p.first_str(),
|
||||||
|
self.lang,
|
||||||
|
&mut self.warnings,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
self.items.push(MusicItem::Artist(ArtistItem {
|
self.items.push(MusicItem::Artist(ArtistItem {
|
||||||
id,
|
id,
|
||||||
|
|
@ -927,8 +944,13 @@ impl MusicListMapper {
|
||||||
let item_type = match card.on_tap.music_page() {
|
let item_type = match card.on_tap.music_page() {
|
||||||
Some((page_type, id)) => match page_type {
|
Some((page_type, id)) => match page_type {
|
||||||
MusicPageType::Artist => {
|
MusicPageType::Artist => {
|
||||||
let subscriber_count = subtitle_p2
|
let subscriber_count = subtitle_p2.and_then(|p| {
|
||||||
.and_then(|p| util::parse_large_numstr(p.first_str(), self.lang));
|
util::parse_large_numstr_or_warn(
|
||||||
|
p.first_str(),
|
||||||
|
self.lang,
|
||||||
|
&mut self.warnings,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
self.items.push(MusicItem::Artist(ArtistItem {
|
self.items.push(MusicItem::Artist(ArtistItem {
|
||||||
id,
|
id,
|
||||||
|
|
@ -963,8 +985,13 @@ impl MusicListMapper {
|
||||||
let (album, view_count) = if is_video {
|
let (album, view_count) = if is_video {
|
||||||
(
|
(
|
||||||
None,
|
None,
|
||||||
subtitle_p3
|
subtitle_p3.and_then(|p| {
|
||||||
.and_then(|p| util::parse_large_numstr(p.first_str(), self.lang)),
|
util::parse_large_numstr_or_warn(
|
||||||
|
p.first_str(),
|
||||||
|
self.lang,
|
||||||
|
&mut self.warnings,
|
||||||
|
)
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
|
|
@ -1149,7 +1176,8 @@ pub(crate) fn map_album_type(txt: &str, lang: Language) -> AlbumType {
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn map_queue_item(item: QueueMusicItem, lang: Language) -> TrackItem {
|
pub(crate) fn map_queue_item(item: QueueMusicItem, lang: Language) -> MapResult<TrackItem> {
|
||||||
|
let mut warnings = Vec::new();
|
||||||
let mut subtitle_parts = item.long_byline_text.split(util::DOT_SEPARATOR).into_iter();
|
let mut subtitle_parts = item.long_byline_text.split(util::DOT_SEPARATOR).into_iter();
|
||||||
|
|
||||||
let is_video = !item
|
let is_video = !item
|
||||||
|
|
@ -1167,7 +1195,8 @@ pub(crate) fn map_queue_item(item: QueueMusicItem, lang: Language) -> TrackItem
|
||||||
let (album, view_count) = if is_video {
|
let (album, view_count) = if is_video {
|
||||||
(
|
(
|
||||||
None,
|
None,
|
||||||
subtitle_p2.and_then(|p| util::parse_large_numstr(p.first_str(), lang)),
|
subtitle_p2
|
||||||
|
.and_then(|p| util::parse_large_numstr_or_warn(p.first_str(), lang, &mut warnings)),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
|
|
@ -1176,20 +1205,23 @@ pub(crate) fn map_queue_item(item: QueueMusicItem, lang: Language) -> TrackItem
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
TrackItem {
|
MapResult {
|
||||||
id: item.video_id,
|
c: TrackItem {
|
||||||
name: item.title,
|
id: item.video_id,
|
||||||
duration: item
|
name: item.title,
|
||||||
.length_text
|
duration: item
|
||||||
.and_then(|txt| util::parse_video_length(&txt)),
|
.length_text
|
||||||
cover: item.thumbnail.into(),
|
.and_then(|txt| util::parse_video_length(&txt)),
|
||||||
artists,
|
cover: item.thumbnail.into(),
|
||||||
artist_id,
|
artists,
|
||||||
album,
|
artist_id,
|
||||||
view_count,
|
album,
|
||||||
is_video,
|
view_count,
|
||||||
track_nr: None,
|
is_video,
|
||||||
by_va,
|
track_nr: None,
|
||||||
|
by_va,
|
||||||
|
},
|
||||||
|
warnings,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
use serde::{de::IgnoredAny, Deserialize};
|
use serde::{
|
||||||
|
de::{IgnoredAny, Visitor},
|
||||||
|
Deserialize,
|
||||||
|
};
|
||||||
use serde_with::{json::JsonString, serde_as};
|
use serde_with::{json::JsonString, serde_as};
|
||||||
|
|
||||||
use super::{video_item::YouTubeListRendererWrap, ResponseContext};
|
use super::{video_item::YouTubeListRendererWrap, ResponseContext};
|
||||||
|
|
@ -26,8 +29,40 @@ pub(crate) struct TwoColumnSearchResultsRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub(crate) struct SearchSuggestion(
|
pub(crate) struct SearchSuggestion(IgnoredAny, pub Vec<SearchSuggestionItem>, IgnoredAny);
|
||||||
IgnoredAny,
|
|
||||||
pub Vec<(String, IgnoredAny, IgnoredAny)>,
|
#[derive(Debug)]
|
||||||
IgnoredAny,
|
pub(crate) struct SearchSuggestionItem(pub String);
|
||||||
);
|
|
||||||
|
impl<'de> Deserialize<'de> for SearchSuggestionItem {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct ItemVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for ItemVisitor {
|
||||||
|
type Value = SearchSuggestionItem;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
formatter.write_str("search suggestion item")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: serde::de::SeqAccess<'de>,
|
||||||
|
{
|
||||||
|
match seq.next_element::<String>()? {
|
||||||
|
Some(s) => {
|
||||||
|
// Ignore the rest of the list
|
||||||
|
while seq.next_element::<IgnoredAny>()?.is_some() {}
|
||||||
|
Ok(SearchSuggestionItem(s))
|
||||||
|
}
|
||||||
|
None => Err(serde::de::Error::invalid_length(0, &"1")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_seq(ItemVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -536,6 +536,8 @@ pub(crate) struct CommentRenderer {
|
||||||
pub author_comment_badge: Option<AuthorCommentBadge>,
|
pub author_comment_badge: Option<AuthorCommentBadge>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub reply_count: u64,
|
pub reply_count: u64,
|
||||||
|
#[serde_as(as = "Option<Text>")]
|
||||||
|
pub vote_count: Option<String>,
|
||||||
/// Buttons for comment interaction (Like/Dislike/Reply)
|
/// Buttons for comment interaction (Like/Dislike/Reply)
|
||||||
pub action_buttons: CommentActionButtons,
|
pub action_buttons: CommentActionButtons,
|
||||||
}
|
}
|
||||||
|
|
@ -581,7 +583,6 @@ pub(crate) struct CommentActionButtons {
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub(crate) struct CommentActionButtonsRenderer {
|
pub(crate) struct CommentActionButtonsRenderer {
|
||||||
pub like_button: ToggleButtonWrap,
|
|
||||||
pub creator_heart: Option<CreatorHeart>,
|
pub creator_heart: Option<CreatorHeart>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -415,7 +415,7 @@ impl<T> YouTubeListMapper<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_channel<C>(lang: Language, channel: &Channel<C>) -> Self {
|
pub fn with_channel<C>(lang: Language, channel: &Channel<C>, warnings: Vec<String>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
lang,
|
lang,
|
||||||
channel: Some(ChannelTag {
|
channel: Some(ChannelTag {
|
||||||
|
|
@ -426,7 +426,7 @@ impl<T> YouTubeListMapper<T> {
|
||||||
subscriber_count: channel.subscriber_count,
|
subscriber_count: channel.subscriber_count,
|
||||||
}),
|
}),
|
||||||
items: Vec::new(),
|
items: Vec::new(),
|
||||||
warnings: Vec::new(),
|
warnings,
|
||||||
ctoken: None,
|
ctoken: None,
|
||||||
corrected_query: None,
|
corrected_query: None,
|
||||||
channel_info: None,
|
channel_info: None,
|
||||||
|
|
@ -572,10 +572,12 @@ impl<T> YouTubeListMapper<T> {
|
||||||
name: channel.title,
|
name: channel.title,
|
||||||
avatar: channel.thumbnail.into(),
|
avatar: channel.thumbnail.into(),
|
||||||
verification: channel.owner_badges.into(),
|
verification: channel.owner_badges.into(),
|
||||||
subscriber_count: sc_txt
|
subscriber_count: sc_txt.and_then(|txt| {
|
||||||
.and_then(|txt| util::parse_numeric_or_warn(&txt, &mut self.warnings)),
|
util::parse_large_numstr_or_warn(&txt, self.lang, &mut self.warnings)
|
||||||
video_count: vc_text
|
}),
|
||||||
.and_then(|txt| util::parse_numeric_or_warn(&txt, &mut self.warnings)),
|
video_count: vc_text.and_then(|txt| {
|
||||||
|
util::parse_large_numstr_or_warn(&txt, self.lang, &mut self.warnings)
|
||||||
|
}),
|
||||||
short_description: channel.description_snippet,
|
short_description: channel.description_snippet,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: Verified,
|
verification: Verified,
|
||||||
subscriber_count: Some(582),
|
subscriber_count: Some(582000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "Music Submissions: https://monstafluff.edmdistrict.com/",
|
short_description: "Music Submissions: https://monstafluff.edmdistrict.com/",
|
||||||
)),
|
)),
|
||||||
|
|
@ -42,7 +42,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: Artist,
|
verification: Artist,
|
||||||
subscriber_count: Some(403),
|
subscriber_count: Some(4030000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "Welcome to the official Music Travel Love YouTube channel! We travel the world making music, friends, videos and memories!",
|
short_description: "Welcome to the official Music Travel Love YouTube channel! We travel the world making music, friends, videos and memories!",
|
||||||
)),
|
)),
|
||||||
|
|
@ -62,7 +62,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: Verified,
|
verification: Verified,
|
||||||
subscriber_count: Some(167),
|
subscriber_count: Some(167000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "MUSIC IN HARMONY WITH YOUR LIFE!!! If any producer, label, artist or photographer has an issue with any of the music or\u{a0}...",
|
short_description: "MUSIC IN HARMONY WITH YOUR LIFE!!! If any producer, label, artist or photographer has an issue with any of the music or\u{a0}...",
|
||||||
)),
|
)),
|
||||||
|
|
@ -82,7 +82,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: Artist,
|
verification: Artist,
|
||||||
subscriber_count: Some(411),
|
subscriber_count: Some(411000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "The official YouTube channel of HAEVN Music. Receiving a piano from his grandfather had a great impact on Jorrit\'s life.",
|
short_description: "The official YouTube channel of HAEVN Music. Receiving a piano from his grandfather had a great impact on Jorrit\'s life.",
|
||||||
)),
|
)),
|
||||||
|
|
@ -102,7 +102,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: None,
|
verification: None,
|
||||||
subscriber_count: Some(312),
|
subscriber_count: Some(31200),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "Hello and welcome to \"Artemis Music\"! Music can play an effective role in helping us lead a better and more productive life.",
|
short_description: "Hello and welcome to \"Artemis Music\"! Music can play an effective role in helping us lead a better and more productive life.",
|
||||||
)),
|
)),
|
||||||
|
|
@ -122,7 +122,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: Verified,
|
verification: Verified,
|
||||||
subscriber_count: Some(372),
|
subscriber_count: Some(372000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "Music is the only language in which you cannot say a mean or sarcastic thing. Have fun listening to music.",
|
short_description: "Music is the only language in which you cannot say a mean or sarcastic thing. Have fun listening to music.",
|
||||||
)),
|
)),
|
||||||
|
|
@ -142,7 +142,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: Verified,
|
verification: Verified,
|
||||||
subscriber_count: Some(178),
|
subscriber_count: Some(178000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "S!X - Music is an independent Hip-Hop label. Soundcloud : https://soundcloud.com/s1xmusic Facebook\u{a0}...",
|
short_description: "S!X - Music is an independent Hip-Hop label. Soundcloud : https://soundcloud.com/s1xmusic Facebook\u{a0}...",
|
||||||
)),
|
)),
|
||||||
|
|
@ -162,7 +162,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: Verified,
|
verification: Verified,
|
||||||
subscriber_count: Some(104),
|
subscriber_count: Some(1040000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "Welcome to Shake Music, a Trap & Bass Channel / Record Label dedicated to bringing you the best tracks. All tracks on Shake\u{a0}...",
|
short_description: "Welcome to Shake Music, a Trap & Bass Channel / Record Label dedicated to bringing you the best tracks. All tracks on Shake\u{a0}...",
|
||||||
)),
|
)),
|
||||||
|
|
@ -182,7 +182,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: Verified,
|
verification: Verified,
|
||||||
subscriber_count: Some(822),
|
subscriber_count: Some(822000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "Welcome to Miracle Music! On this channel you will find a wide variety of different Deep House, Tropical House, Chill Out, EDM,.",
|
short_description: "Welcome to Miracle Music! On this channel you will find a wide variety of different Deep House, Tropical House, Chill Out, EDM,.",
|
||||||
)),
|
)),
|
||||||
|
|
@ -202,7 +202,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: Verified,
|
verification: Verified,
|
||||||
subscriber_count: Some(462),
|
subscriber_count: Some(4620000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "",
|
short_description: "",
|
||||||
)),
|
)),
|
||||||
|
|
@ -222,7 +222,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: Verified,
|
verification: Verified,
|
||||||
subscriber_count: Some(105),
|
subscriber_count: Some(1050000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "BRINGING YOU ONLY THE BEST EDM - TRAP Submit your own track for promotion here:\u{a0}...",
|
short_description: "BRINGING YOU ONLY THE BEST EDM - TRAP Submit your own track for promotion here:\u{a0}...",
|
||||||
)),
|
)),
|
||||||
|
|
@ -242,7 +242,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: Verified,
|
verification: Verified,
|
||||||
subscriber_count: Some(709),
|
subscriber_count: Some(709000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "Hey there! I am Mr MoMo My channel focus on Japan music, lofi, trap & bass type beat and Japanese instrumental. I mindfully\u{a0}...",
|
short_description: "Hey there! I am Mr MoMo My channel focus on Japan music, lofi, trap & bass type beat and Japanese instrumental. I mindfully\u{a0}...",
|
||||||
)),
|
)),
|
||||||
|
|
@ -262,7 +262,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: None,
|
verification: None,
|
||||||
subscriber_count: Some(544),
|
subscriber_count: Some(54400),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "",
|
short_description: "",
|
||||||
)),
|
)),
|
||||||
|
|
@ -282,7 +282,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: None,
|
verification: None,
|
||||||
subscriber_count: Some(359),
|
subscriber_count: Some(3590),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "Welcome to our Energy Transformation Relaxing Music . This chakra music channel will focus on developing the best chakra\u{a0}...",
|
short_description: "Welcome to our Energy Transformation Relaxing Music . This chakra music channel will focus on developing the best chakra\u{a0}...",
|
||||||
)),
|
)),
|
||||||
|
|
@ -302,7 +302,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: Verified,
|
verification: Verified,
|
||||||
subscriber_count: Some(416),
|
subscriber_count: Some(416000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "Nonstop Music - Home of 1h videos of your favourite songs and mixes. Nonstop Genres: Pop • Chillout • Tropical House • Deep\u{a0}...",
|
short_description: "Nonstop Music - Home of 1h videos of your favourite songs and mixes. Nonstop Genres: Pop • Chillout • Tropical House • Deep\u{a0}...",
|
||||||
)),
|
)),
|
||||||
|
|
@ -322,7 +322,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: Verified,
|
verification: Verified,
|
||||||
subscriber_count: Some(3),
|
subscriber_count: Some(3000000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "Vibe Music strives to bring the best lyric videos of popular Rap & Hip Hop songs. Be sure to Subscribe to see new videos we\u{a0}...",
|
short_description: "Vibe Music strives to bring the best lyric videos of popular Rap & Hip Hop songs. Be sure to Subscribe to see new videos we\u{a0}...",
|
||||||
)),
|
)),
|
||||||
|
|
@ -342,7 +342,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: None,
|
verification: None,
|
||||||
subscriber_count: Some(120),
|
subscriber_count: Some(120000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "",
|
short_description: "",
|
||||||
)),
|
)),
|
||||||
|
|
@ -362,7 +362,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: None,
|
verification: None,
|
||||||
subscriber_count: Some(817),
|
subscriber_count: Some(81700),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "",
|
short_description: "",
|
||||||
)),
|
)),
|
||||||
|
|
@ -382,7 +382,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: None,
|
verification: None,
|
||||||
subscriber_count: Some(53),
|
subscriber_count: Some(53000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "Welcome to my channel - Helios Music. I created this channel to help people have the most relaxing, refreshing and comfortable\u{a0}...",
|
short_description: "Welcome to my channel - Helios Music. I created this channel to help people have the most relaxing, refreshing and comfortable\u{a0}...",
|
||||||
)),
|
)),
|
||||||
|
|
@ -402,7 +402,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: None,
|
verification: None,
|
||||||
subscriber_count: Some(129),
|
subscriber_count: Some(129000),
|
||||||
video_count: None,
|
video_count: None,
|
||||||
short_description: "Music On (UNOFFICIAL CHANNEL)",
|
short_description: "Music On (UNOFFICIAL CHANNEL)",
|
||||||
)),
|
)),
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ SearchResult(
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
verification: Verified,
|
verification: Verified,
|
||||||
subscriber_count: Some(292),
|
subscriber_count: Some(2920000),
|
||||||
video_count: Some(219),
|
video_count: Some(219),
|
||||||
short_description: "Hi, I\'m Tina, aka Doobydobap! Food is the medium I use to tell stories and connect with people who share the same passion as I\u{a0}...",
|
short_description: "Hi, I\'m Tina, aka Doobydobap! Food is the medium I use to tell stories and connect with people who share the same passion as I\u{a0}...",
|
||||||
)),
|
)),
|
||||||
|
|
|
||||||
|
|
@ -191,9 +191,10 @@ impl MapResponse<VideoDetails> for response::VideoDetails {
|
||||||
};
|
};
|
||||||
|
|
||||||
let comment_count = comment_count_section.and_then(|s| {
|
let comment_count = comment_count_section.and_then(|s| {
|
||||||
util::parse_large_numstr::<u64>(
|
util::parse_large_numstr_or_warn::<u64>(
|
||||||
&s.comments_entry_point_header_renderer.comment_count,
|
&s.comments_entry_point_header_renderer.comment_count,
|
||||||
lang,
|
lang,
|
||||||
|
&mut warnings,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -331,9 +332,9 @@ impl MapResponse<VideoDetails> for response::VideoDetails {
|
||||||
name: channel_name,
|
name: channel_name,
|
||||||
avatar: owner.thumbnail.into(),
|
avatar: owner.thumbnail.into(),
|
||||||
verification: owner.badges.into(),
|
verification: owner.badges.into(),
|
||||||
subscriber_count: owner
|
subscriber_count: owner.subscriber_count_text.and_then(|txt| {
|
||||||
.subscriber_count_text
|
util::parse_large_numstr_or_warn(&txt, lang, &mut warnings)
|
||||||
.and_then(|txt| util::parse_large_numstr(&txt, lang)),
|
}),
|
||||||
},
|
},
|
||||||
view_count,
|
view_count,
|
||||||
like_count,
|
like_count,
|
||||||
|
|
@ -505,16 +506,16 @@ fn map_comment(
|
||||||
}),
|
}),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
publish_date: timeago::parse_timeago_to_dt(lang, &c.published_time_text),
|
publish_date: timeago::parse_timeago_dt_or_warn(
|
||||||
publish_date_txt: c.published_time_text,
|
lang,
|
||||||
like_count: util::parse_numeric_or_warn(
|
&c.published_time_text,
|
||||||
&c.action_buttons
|
|
||||||
.comment_action_buttons_renderer
|
|
||||||
.like_button
|
|
||||||
.toggle_button_renderer
|
|
||||||
.accessibility_data,
|
|
||||||
&mut warnings,
|
&mut warnings,
|
||||||
),
|
),
|
||||||
|
publish_date_txt: c.published_time_text,
|
||||||
|
like_count: match c.vote_count {
|
||||||
|
Some(txt) => util::parse_numeric_or_warn(&txt, &mut warnings),
|
||||||
|
None => Some(0),
|
||||||
|
},
|
||||||
reply_count: c.reply_count as u32,
|
reply_count: c.reply_count as u32,
|
||||||
replies: replies
|
replies: replies
|
||||||
.map(|items| Paginator::new(Some(c.reply_count), items, reply_ctoken))
|
.map(|items| Paginator::new(Some(c.reply_count), items, reply_ctoken))
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ pub fn parse_timeago(lang: Language, textual_date: &str) -> Option<TimeAgo> {
|
||||||
/// Parse a TimeAgo string (e.g. "29 minutes ago") into a Chrono DateTime object.
|
/// Parse a TimeAgo string (e.g. "29 minutes ago") into a Chrono DateTime object.
|
||||||
///
|
///
|
||||||
/// Returns None if the date could not be parsed.
|
/// Returns None if the date could not be parsed.
|
||||||
pub fn parse_timeago_to_dt(lang: Language, textual_date: &str) -> Option<OffsetDateTime> {
|
pub fn parse_timeago_dt(lang: Language, textual_date: &str) -> Option<OffsetDateTime> {
|
||||||
parse_timeago(lang, textual_date).map(|ta| ta.into())
|
parse_timeago(lang, textual_date).map(|ta| ta.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,7 +219,7 @@ pub(crate) fn parse_timeago_dt_or_warn(
|
||||||
textual_date: &str,
|
textual_date: &str,
|
||||||
warnings: &mut Vec<String>,
|
warnings: &mut Vec<String>,
|
||||||
) -> Option<OffsetDateTime> {
|
) -> Option<OffsetDateTime> {
|
||||||
let res = parse_timeago_to_dt(lang, textual_date);
|
let res = parse_timeago_dt(lang, textual_date);
|
||||||
if res.is_none() {
|
if res.is_none() {
|
||||||
warnings.push(format!("could not parse timeago `{textual_date}`"));
|
warnings.push(format!("could not parse timeago `{textual_date}`"));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5571,17 +5571,19 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
timeago_tokens: ::phf::Map {
|
timeago_tokens: ::phf::Map {
|
||||||
key: 15467950696543387533,
|
key: 15467950696543387533,
|
||||||
disps: &[
|
disps: &[
|
||||||
(3, 5),
|
(0, 1),
|
||||||
(0, 0),
|
(2, 0),
|
||||||
],
|
],
|
||||||
entries: &[
|
entries: &[
|
||||||
("ว\u{e34}นาท\u{e35}ท\u{e35}\u{e48}ผ\u{e48}านมา", TaToken { n: 1, unit: Some(TimeUnit::Second) }),
|
|
||||||
("ว\u{e31}นท\u{e35}\u{e48}ผ\u{e48}านมา", TaToken { n: 1, unit: Some(TimeUnit::Day) }),
|
|
||||||
("นาท\u{e35}ท\u{e35}\u{e48}ผ\u{e48}านมา", TaToken { n: 1, unit: Some(TimeUnit::Minute) }),
|
("นาท\u{e35}ท\u{e35}\u{e48}ผ\u{e48}านมา", TaToken { n: 1, unit: Some(TimeUnit::Minute) }),
|
||||||
("ช\u{e31}\u{e48}วโมงท\u{e35}\u{e48}ผ\u{e48}านมา", TaToken { n: 1, unit: Some(TimeUnit::Hour) }),
|
|
||||||
("ส\u{e31}ปดาห\u{e4c}ท\u{e35}\u{e48}ผ\u{e48}านมา", TaToken { n: 1, unit: Some(TimeUnit::Week) }),
|
|
||||||
("ป\u{e35}ท\u{e35}\u{e48}แล\u{e49}ว", TaToken { n: 1, unit: Some(TimeUnit::Year) }),
|
("ป\u{e35}ท\u{e35}\u{e48}แล\u{e49}ว", TaToken { n: 1, unit: Some(TimeUnit::Year) }),
|
||||||
("เด\u{e37}อนท\u{e35}\u{e48}ผ\u{e48}านมา", TaToken { n: 1, unit: Some(TimeUnit::Month) }),
|
("เด\u{e37}อนท\u{e35}\u{e48}ผ\u{e48}านมา", TaToken { n: 1, unit: Some(TimeUnit::Month) }),
|
||||||
|
("ช\u{e31}\u{e48}วโมงท\u{e35}\u{e48}ผ\u{e48}านมา", TaToken { n: 1, unit: Some(TimeUnit::Hour) }),
|
||||||
|
("นาท\u{e35}", TaToken { n: 1, unit: Some(TimeUnit::Minute) }),
|
||||||
|
("ว\u{e31}นท\u{e35}\u{e48}ผ\u{e48}านมา", TaToken { n: 1, unit: Some(TimeUnit::Day) }),
|
||||||
|
("ส\u{e31}ปดาห\u{e4c}ท\u{e35}\u{e48}ผ\u{e48}านมา", TaToken { n: 1, unit: Some(TimeUnit::Week) }),
|
||||||
|
("ว\u{e34}นาท\u{e35}", TaToken { n: 1, unit: Some(TimeUnit::Second) }),
|
||||||
|
("ว\u{e34}นาท\u{e35}ท\u{e35}\u{e48}ผ\u{e48}านมา", TaToken { n: 1, unit: Some(TimeUnit::Second) }),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
date_order: &[DateCmp::D, DateCmp::Y],
|
date_order: &[DateCmp::D, DateCmp::Y],
|
||||||
|
|
|
||||||
|
|
@ -328,6 +328,21 @@ where
|
||||||
.ok()
|
.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_large_numstr_or_warn<F>(
|
||||||
|
string: &str,
|
||||||
|
lang: Language,
|
||||||
|
warnings: &mut Vec<String>,
|
||||||
|
) -> Option<F>
|
||||||
|
where
|
||||||
|
F: TryFrom<u64>,
|
||||||
|
{
|
||||||
|
let res = parse_large_numstr::<F>(string, lang);
|
||||||
|
if res.is_none() {
|
||||||
|
warnings.push(format!("could not parse numstr `{string}`"));
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
/// Replace all html control characters to make a string safe for inserting into HTML.
|
/// Replace all html control characters to make a string safe for inserting into HTML.
|
||||||
pub fn escape_html(input: &str) -> String {
|
pub fn escape_html(input: &str) -> String {
|
||||||
let mut buf = String::with_capacity(input.len());
|
let mut buf = String::with_capacity(input.len());
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,8 @@
|
||||||
"آلاف": 3,
|
"آلاف": 3,
|
||||||
"ألف": 3,
|
"ألف": 3,
|
||||||
"مليار": 9,
|
"مليار": 9,
|
||||||
"مليون": 6
|
"مليون": 6,
|
||||||
|
"واحد": 0
|
||||||
},
|
},
|
||||||
"album_types": {
|
"album_types": {
|
||||||
"أغنية منفردة": "Single",
|
"أغنية منفردة": "Single",
|
||||||
|
|
@ -666,10 +667,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"en": {
|
"en": {
|
||||||
"equivalent": [
|
"equivalent": ["en-GB", "en-IN"],
|
||||||
"en-GB",
|
|
||||||
"en-IN"
|
|
||||||
],
|
|
||||||
"by_char": false,
|
"by_char": false,
|
||||||
"timeago_tokens": {
|
"timeago_tokens": {
|
||||||
"day": "D",
|
"day": "D",
|
||||||
|
|
@ -774,9 +772,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"es-US": {
|
"es-US": {
|
||||||
"equivalent": [
|
"equivalent": ["es-419"],
|
||||||
"es-419"
|
|
||||||
],
|
|
||||||
"by_char": false,
|
"by_char": false,
|
||||||
"timeago_tokens": {
|
"timeago_tokens": {
|
||||||
"año": "Y",
|
"año": "Y",
|
||||||
|
|
@ -1055,9 +1051,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fr": {
|
"fr": {
|
||||||
"equivalent": [
|
"equivalent": ["fr-CA"],
|
||||||
"fr-CA"
|
|
||||||
],
|
|
||||||
"by_char": false,
|
"by_char": false,
|
||||||
"timeago_tokens": {
|
"timeago_tokens": {
|
||||||
"an": "Y",
|
"an": "Y",
|
||||||
|
|
@ -3294,7 +3288,9 @@
|
||||||
"วันที่ผ่านมา": "D",
|
"วันที่ผ่านมา": "D",
|
||||||
"วินาทีที่ผ่านมา": "s",
|
"วินาทีที่ผ่านมา": "s",
|
||||||
"สัปดาห์ที่ผ่านมา": "W",
|
"สัปดาห์ที่ผ่านมา": "W",
|
||||||
"เดือนที่ผ่านมา": "M"
|
"เดือนที่ผ่านมา": "M",
|
||||||
|
"นาที": "m",
|
||||||
|
"วินาที": "s"
|
||||||
},
|
},
|
||||||
"date_order": "DY",
|
"date_order": "DY",
|
||||||
"months": {
|
"months": {
|
||||||
|
|
|
||||||
3224
tests/snapshots/youtube__music_album_audiobook_intl.snap
Normal file
3224
tests/snapshots/youtube__music_album_audiobook_intl.snap
Normal file
File diff suppressed because it is too large
Load diff
129
tests/snapshots/youtube__music_album_ep_intl.snap
Normal file
129
tests/snapshots/youtube__music_album_ep_intl.snap
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
---
|
||||||
|
source: tests/youtube.rs
|
||||||
|
expression: album
|
||||||
|
---
|
||||||
|
MusicAlbum(
|
||||||
|
id: "MPREb_u1I69lSAe5v",
|
||||||
|
playlist_id: Some("OLAK5uy_lGP_zv0vJDUlecQDzugUJmjcF7pvyVNyY"),
|
||||||
|
name: "Waldbrand",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCpJyCbFbdTrx0M90HCNBHFQ"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCpJyCbFbdTrx0M90HCNBHFQ"),
|
||||||
|
description: None,
|
||||||
|
album_type: Ep,
|
||||||
|
year: Some(2016),
|
||||||
|
by_va: false,
|
||||||
|
tracks: [
|
||||||
|
TrackItem(
|
||||||
|
id: "aGd3VKSOTxY",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(221),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCpJyCbFbdTrx0M90HCNBHFQ"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCpJyCbFbdTrx0M90HCNBHFQ"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_u1I69lSAe5v",
|
||||||
|
name: "Waldbrand",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(1),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "Jz-26iiDuYs",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(208),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCpJyCbFbdTrx0M90HCNBHFQ"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCpJyCbFbdTrx0M90HCNBHFQ"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_u1I69lSAe5v",
|
||||||
|
name: "Waldbrand",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(2),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "Bu26uFtpt58",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(223),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCpJyCbFbdTrx0M90HCNBHFQ"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCpJyCbFbdTrx0M90HCNBHFQ"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_u1I69lSAe5v",
|
||||||
|
name: "Waldbrand",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(3),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "RgwNqqiVqdY",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(221),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCpJyCbFbdTrx0M90HCNBHFQ"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCpJyCbFbdTrx0M90HCNBHFQ"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_u1I69lSAe5v",
|
||||||
|
name: "Waldbrand",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(4),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "2TuOh30XbCI",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(197),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCpJyCbFbdTrx0M90HCNBHFQ"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCpJyCbFbdTrx0M90HCNBHFQ"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_u1I69lSAe5v",
|
||||||
|
name: "Waldbrand",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(5),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
variants: [],
|
||||||
|
)
|
||||||
134
tests/snapshots/youtube__music_album_no_artist_intl.snap
Normal file
134
tests/snapshots/youtube__music_album_no_artist_intl.snap
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
---
|
||||||
|
source: tests/youtube.rs
|
||||||
|
expression: album
|
||||||
|
---
|
||||||
|
MusicAlbum(
|
||||||
|
id: "MPREb_bqWA6mAZFWS",
|
||||||
|
playlist_id: Some("OLAK5uy_mUiRbMqeQXFUH6h9KB87RcEmNtm45Qvs0"),
|
||||||
|
name: "Pedha Rasi Peddamma Katha",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [],
|
||||||
|
artist_id: None,
|
||||||
|
description: None,
|
||||||
|
album_type: Ep,
|
||||||
|
year: Some(1968),
|
||||||
|
by_va: false,
|
||||||
|
tracks: [
|
||||||
|
TrackItem(
|
||||||
|
id: "EX7-pOQHPyE",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(267),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC1C05NyYICFB2mVGn9_ttEw"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC1C05NyYICFB2mVGn9_ttEw"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_bqWA6mAZFWS",
|
||||||
|
name: "Pedha Rasi Peddamma Katha",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(1),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "0AyWB-Quj4A",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(179),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCDqpyYkgWy2h03HamIfODjw"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCDqpyYkgWy2h03HamIfODjw"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_bqWA6mAZFWS",
|
||||||
|
name: "Pedha Rasi Peddamma Katha",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(2),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "s0Sb-GZLXSM",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(155),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: None,
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: None,
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_bqWA6mAZFWS",
|
||||||
|
name: "Pedha Rasi Peddamma Katha",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(3),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "P4XAaXjlCDA",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(229),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCl4iPtukwe7m0kIxUMskkgA"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCl4iPtukwe7m0kIxUMskkgA"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_bqWA6mAZFWS",
|
||||||
|
name: "Pedha Rasi Peddamma Katha",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(4),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
variants: [
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_h8ltx5oKvyY",
|
||||||
|
name: "Pedha Rasi Peddamma Katha",
|
||||||
|
cover: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://lh3.googleusercontent.com/iZtBdPWBGNB-GAWvOp9seuYj5QqKrUYGSe-B5J026yxHqFSWv4zsxHy-LxX5LbFlnepOPRWNLrajO-_-=w226-h226-l90-rj",
|
||||||
|
width: 226,
|
||||||
|
height: 226,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://lh3.googleusercontent.com/iZtBdPWBGNB-GAWvOp9seuYj5QqKrUYGSe-B5J026yxHqFSWv4zsxHy-LxX5LbFlnepOPRWNLrajO-_-=w544-h544-l90-rj",
|
||||||
|
width: 544,
|
||||||
|
height: 544,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCl4iPtukwe7m0kIxUMskkgA"),
|
||||||
|
name: "S P Balasubramaniam",
|
||||||
|
),
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCWgAqlYG7mXTUxrFiLyDSsg"),
|
||||||
|
name: "S Janaki",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCl4iPtukwe7m0kIxUMskkgA"),
|
||||||
|
album_type: Ep,
|
||||||
|
year: None,
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
61
tests/snapshots/youtube__music_album_no_year_intl.snap
Normal file
61
tests/snapshots/youtube__music_album_no_year_intl.snap
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
---
|
||||||
|
source: tests/youtube.rs
|
||||||
|
expression: album
|
||||||
|
---
|
||||||
|
MusicAlbum(
|
||||||
|
id: "MPREb_F3Af9UZZVxX",
|
||||||
|
playlist_id: Some("OLAK5uy_nim4i4eycEtlBtS3Ci6j4SvvTmdfBcRX4"),
|
||||||
|
name: "La Ultima Vez (Remix)",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCAJwa_1l4rHzBJyWbeBtGZw"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCbBaYg2UToDaoOwo-R6xi4g"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCiY3z8HAGD6BlSNKVn2kSvQ"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCAJwa_1l4rHzBJyWbeBtGZw"),
|
||||||
|
description: None,
|
||||||
|
album_type: Single,
|
||||||
|
year: None,
|
||||||
|
by_va: false,
|
||||||
|
tracks: [
|
||||||
|
TrackItem(
|
||||||
|
id: "1Sz3lUVGBSM",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(229),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCAJwa_1l4rHzBJyWbeBtGZw"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCbBaYg2UToDaoOwo-R6xi4g"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCiY3z8HAGD6BlSNKVn2kSvQ"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCAJwa_1l4rHzBJyWbeBtGZw"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_F3Af9UZZVxX",
|
||||||
|
name: "La Ultima Vez (Remix)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(1),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
variants: [],
|
||||||
|
)
|
||||||
429
tests/snapshots/youtube__music_album_one_artist_intl.snap
Normal file
429
tests/snapshots/youtube__music_album_one_artist_intl.snap
Normal file
|
|
@ -0,0 +1,429 @@
|
||||||
|
---
|
||||||
|
source: tests/youtube.rs
|
||||||
|
expression: album
|
||||||
|
---
|
||||||
|
MusicAlbum(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
playlist_id: Some("OLAK5uy_myZkBX2d2TzcrlQhIwLy3hCj2MkAMaPR4"),
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
description: None,
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2016),
|
||||||
|
by_va: false,
|
||||||
|
tracks: [
|
||||||
|
TrackItem(
|
||||||
|
id: "g0iRiJ_ck48",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(216),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(1),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "rREEBXp0y9s",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(224),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(2),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "zvU5Y8Q19hU",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(176),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(3),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "ARKLrzzTQA0",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(215),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(4),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "tstLgN8A_Ng",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(268),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(5),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "k2DjgQOY3Ts",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(202),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(6),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "azHwhecxEsI",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(185),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(7),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "_FcsdYIQ2co",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(226),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(8),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "27bOWEbshyE",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(207),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(9),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "riD_3oZwt8w",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(211),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(10),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "8GNvjF3no9s",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(179),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(11),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "YHMFzf1uN2U",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(218),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(12),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "jvV-z5F3oAo",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(277),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(13),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "u8_9cxlrh8k",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(204),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(14),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "gSvKcvM1Wk0",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(202),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(15),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "wQHgKRJ0pDQ",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(222),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(16),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "Ckz5i6-hzf0",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(177),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(17),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "y5zuUgyFqrc",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(220),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_nlBWQROfvjo",
|
||||||
|
name: "Märchen enden gut",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(18),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
variants: [
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_jk6Msw8izou",
|
||||||
|
name: "Märchen enden gut (Nyáre Ranta (Märchenedition))",
|
||||||
|
cover: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://lh3.googleusercontent.com/BKgnW_-hapCHk599AtRfTYZGdXVIo0C4bJp1Bh7qUpGK7fNAXGW8Bhv2x-ukeFM8cuxKbGqqGaTo8fZASA=w226-h226-l90-rj",
|
||||||
|
width: 226,
|
||||||
|
height: 226,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://lh3.googleusercontent.com/BKgnW_-hapCHk599AtRfTYZGdXVIo0C4bJp1Bh7qUpGK7fNAXGW8Bhv2x-ukeFM8cuxKbGqqGaTo8fZASA=w544-h544-l90-rj",
|
||||||
|
width: 544,
|
||||||
|
height: 544,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
name: "Oonagh",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_vmjW5e1xEHhYjY2a0kK1A"),
|
||||||
|
album_type: Album,
|
||||||
|
year: None,
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
318
tests/snapshots/youtube__music_album_show_intl.snap
Normal file
318
tests/snapshots/youtube__music_album_show_intl.snap
Normal file
|
|
@ -0,0 +1,318 @@
|
||||||
|
---
|
||||||
|
source: tests/youtube.rs
|
||||||
|
expression: album
|
||||||
|
---
|
||||||
|
MusicAlbum(
|
||||||
|
id: "MPREb_cwzk8EUwypZ",
|
||||||
|
playlist_id: Some("OLAK5uy_kODvYZ5CEpYdtd4VPsmg0eRTlpazG0dvA"),
|
||||||
|
name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
description: None,
|
||||||
|
album_type: Show,
|
||||||
|
year: Some(2022),
|
||||||
|
by_va: false,
|
||||||
|
tracks: [
|
||||||
|
TrackItem(
|
||||||
|
id: "lSbKz5LWvKE",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(229),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_cwzk8EUwypZ",
|
||||||
|
name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(1),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "fdO6gu4qjRw",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(235),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_cwzk8EUwypZ",
|
||||||
|
name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(2),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "muCxstXirvY",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(197),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_cwzk8EUwypZ",
|
||||||
|
name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(3),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "aG1N0vo__Ng",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(186),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_cwzk8EUwypZ",
|
||||||
|
name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(4),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "roHhLNYS9yo",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(188),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_cwzk8EUwypZ",
|
||||||
|
name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(5),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "nJ49NuLvcAw",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(205),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_cwzk8EUwypZ",
|
||||||
|
name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(6),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "Me119D570h0",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(219),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_cwzk8EUwypZ",
|
||||||
|
name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(7),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "YXnRLK-qKG8",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(240),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_cwzk8EUwypZ",
|
||||||
|
name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(8),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "A61wz1jz9X0",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(239),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_cwzk8EUwypZ",
|
||||||
|
name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(9),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "u_S08EJOTUg",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(197),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_cwzk8EUwypZ",
|
||||||
|
name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(10),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "0qwYJihV1EU",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(201),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_cwzk8EUwypZ",
|
||||||
|
name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(11),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "zjhoyTnEzuQ",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(187),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_cwzk8EUwypZ",
|
||||||
|
name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(12),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "oDjDd0UBzAY",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(183),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_cwzk8EUwypZ",
|
||||||
|
name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(13),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "_3-WVmqgi-Q",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(193),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCNoyEM0e2A7WlsBmP2w3avg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_cwzk8EUwypZ",
|
||||||
|
name: "Folge 2: Eiszeit (Das Original-Hörspiel zur TV-Serie)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(14),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
variants: [],
|
||||||
|
)
|
||||||
53
tests/snapshots/youtube__music_album_single_intl.snap
Normal file
53
tests/snapshots/youtube__music_album_single_intl.snap
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
---
|
||||||
|
source: tests/youtube.rs
|
||||||
|
expression: album
|
||||||
|
---
|
||||||
|
MusicAlbum(
|
||||||
|
id: "MPREb_bHfHGoy7vuv",
|
||||||
|
playlist_id: Some("OLAK5uy_kdSWBZ-9AZDkYkuy0QCc3p0KO9DEHVNH0"),
|
||||||
|
name: "Der Himmel reißt auf",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCXGYZ-OhdOpPBamHX3K9YRg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCFTcSVPYRWlDoHisR-ZKwgw"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCXGYZ-OhdOpPBamHX3K9YRg"),
|
||||||
|
description: None,
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2020),
|
||||||
|
by_va: false,
|
||||||
|
tracks: [
|
||||||
|
TrackItem(
|
||||||
|
id: "VU6lEv0PKAo",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(183),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCXGYZ-OhdOpPBamHX3K9YRg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCFTcSVPYRWlDoHisR-ZKwgw"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCXGYZ-OhdOpPBamHX3K9YRg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_bHfHGoy7vuv",
|
||||||
|
name: "Der Himmel reißt auf",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(1),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
variants: [],
|
||||||
|
)
|
||||||
271
tests/snapshots/youtube__music_album_unavailable_intl.snap
Normal file
271
tests/snapshots/youtube__music_album_unavailable_intl.snap
Normal file
|
|
@ -0,0 +1,271 @@
|
||||||
|
---
|
||||||
|
source: tests/youtube.rs
|
||||||
|
expression: album
|
||||||
|
---
|
||||||
|
MusicAlbum(
|
||||||
|
id: "MPREb_AzuWg8qAVVl",
|
||||||
|
playlist_id: Some("OLAK5uy_mux5ygfN9sbiR1ma3yh1GHTmqNekZNoAI"),
|
||||||
|
name: "13 Reasons Why (Season 3)",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [],
|
||||||
|
artist_id: None,
|
||||||
|
description: None,
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2019),
|
||||||
|
by_va: true,
|
||||||
|
tracks: [
|
||||||
|
TrackItem(
|
||||||
|
id: "R3VIKRtzAdE",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(205),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCCj0RlDqqahEB5BXVtDcPqg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCCj0RlDqqahEB5BXVtDcPqg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_AzuWg8qAVVl",
|
||||||
|
name: "13 Reasons Why (Season 3)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(1),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "t0v0UOgOt18",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(174),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCMrCoizKiBxqeg5pTpBXn1A"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCMrCoizKiBxqeg5pTpBXn1A"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_AzuWg8qAVVl",
|
||||||
|
name: "13 Reasons Why (Season 3)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(2),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "HjJYAkUXrxI",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(199),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCWjoDY2SXJ5dvcdunWI6mjQ"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCWjoDY2SXJ5dvcdunWI6mjQ"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_AzuWg8qAVVl",
|
||||||
|
name: "13 Reasons Why (Season 3)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(3),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "Hg0KUOTL06I",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(187),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UChzK2t3sjnQkWzGnyKXOSSg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UChzK2t3sjnQkWzGnyKXOSSg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_AzuWg8qAVVl",
|
||||||
|
name: "13 Reasons Why (Season 3)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(5),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "c8AfY6yhdkM",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(159),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCvsgN5NKOzXnAURfaf3TOig"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCvsgN5NKOzXnAURfaf3TOig"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_AzuWg8qAVVl",
|
||||||
|
name: "13 Reasons Why (Season 3)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(6),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "_ZmdHjVvwhc",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(186),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCI4YNnmHjXFaaKvfdmpWvJQ"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCI4YNnmHjXFaaKvfdmpWvJQ"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_AzuWg8qAVVl",
|
||||||
|
name: "13 Reasons Why (Season 3)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(7),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "wBe1Zi3q1n8",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(209),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCDaFVUr2n8T7_X1f5yJ1xlw"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCDaFVUr2n8T7_X1f5yJ1xlw"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_AzuWg8qAVVl",
|
||||||
|
name: "13 Reasons Why (Season 3)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(8),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "l8Pj8s9uPGc",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(209),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCZcc-WkffIMBVGUr6j9e6aQ"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCZcc-WkffIMBVGUr6j9e6aQ"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_AzuWg8qAVVl",
|
||||||
|
name: "13 Reasons Why (Season 3)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(9),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "Kn3cruxYj0c",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(174),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCQPPz_A65SWYi2wXX8z76AQ"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCQPPz_A65SWYi2wXX8z76AQ"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_AzuWg8qAVVl",
|
||||||
|
name: "13 Reasons Why (Season 3)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(11),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "Sy1lIOl1YN0",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(185),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UChTOXkDhGJ0JftnfMWjpCCg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UChTOXkDhGJ0JftnfMWjpCCg"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_AzuWg8qAVVl",
|
||||||
|
name: "13 Reasons Why (Season 3)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(12),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "njdlNT1RRo4",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(237),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCMUB52aO4CqrUXmLwbfRWYA"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCMUB52aO4CqrUXmLwbfRWYA"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_AzuWg8qAVVl",
|
||||||
|
name: "13 Reasons Why (Season 3)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(13),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "Si-CXM8CHqQ",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(246),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC4YvDAbE1EYwZpj6gQ-lpLw"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC4YvDAbE1EYwZpj6gQ-lpLw"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_AzuWg8qAVVl",
|
||||||
|
name: "13 Reasons Why (Season 3)",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(18),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
variants: [],
|
||||||
|
)
|
||||||
145
tests/snapshots/youtube__music_album_various_artists_intl.snap
Normal file
145
tests/snapshots/youtube__music_album_various_artists_intl.snap
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
---
|
||||||
|
source: tests/youtube.rs
|
||||||
|
expression: album
|
||||||
|
---
|
||||||
|
MusicAlbum(
|
||||||
|
id: "MPREb_8QkDeEIawvX",
|
||||||
|
playlist_id: Some("OLAK5uy_mEX9ljZeeEWgTM1xLL1isyiGaWXoPyoOk"),
|
||||||
|
name: "<Queendom2> FINAL",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [],
|
||||||
|
artist_id: None,
|
||||||
|
description: None,
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2022),
|
||||||
|
by_va: true,
|
||||||
|
tracks: [
|
||||||
|
TrackItem(
|
||||||
|
id: "Tzai7JXo45w",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(274),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: None,
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: None,
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_8QkDeEIawvX",
|
||||||
|
name: "<Queendom2> FINAL",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(1),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "9WYpLYAEub0",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(216),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: None,
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: None,
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_8QkDeEIawvX",
|
||||||
|
name: "<Queendom2> FINAL",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(2),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "R48tE237bW4",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(239),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCAKvDuIX3m1AUdPpDSqV_3w"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCAKvDuIX3m1AUdPpDSqV_3w"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_8QkDeEIawvX",
|
||||||
|
name: "<Queendom2> FINAL",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(3),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "-UzsoR6z-vg",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(254),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: None,
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: None,
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_8QkDeEIawvX",
|
||||||
|
name: "<Queendom2> FINAL",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(4),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "kbNVyn8Ex28",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(187),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: None,
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: None,
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_8QkDeEIawvX",
|
||||||
|
name: "<Queendom2> FINAL",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(5),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "NJrQZUzWP5Y",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(224),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: None,
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: None,
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_8QkDeEIawvX",
|
||||||
|
name: "<Queendom2> FINAL",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(6),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
variants: [],
|
||||||
|
)
|
||||||
138
tests/snapshots/youtube__music_album_version_no_artist_intl.snap
Normal file
138
tests/snapshots/youtube__music_album_version_no_artist_intl.snap
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
---
|
||||||
|
source: tests/youtube.rs
|
||||||
|
expression: album
|
||||||
|
---
|
||||||
|
MusicAlbum(
|
||||||
|
id: "MPREb_h8ltx5oKvyY",
|
||||||
|
playlist_id: Some("OLAK5uy_lIDfTi_k8V1RJ54MeJJGK_BduAeYbm-0s"),
|
||||||
|
name: "Pedha Rasi Peddamma Katha",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCl4iPtukwe7m0kIxUMskkgA"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCWgAqlYG7mXTUxrFiLyDSsg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCl4iPtukwe7m0kIxUMskkgA"),
|
||||||
|
description: None,
|
||||||
|
album_type: Ep,
|
||||||
|
year: Some(1968),
|
||||||
|
by_va: false,
|
||||||
|
tracks: [
|
||||||
|
TrackItem(
|
||||||
|
id: "AKJ3IJZKPWc",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(228),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCl4iPtukwe7m0kIxUMskkgA"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCWgAqlYG7mXTUxrFiLyDSsg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCl4iPtukwe7m0kIxUMskkgA"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_h8ltx5oKvyY",
|
||||||
|
name: "Pedha Rasi Peddamma Katha",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(1),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "WnpZuHNB33E",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(266),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC1C05NyYICFB2mVGn9_ttEw"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC1C05NyYICFB2mVGn9_ttEw"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_h8ltx5oKvyY",
|
||||||
|
name: "Pedha Rasi Peddamma Katha",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(2),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "pRqoDGXg1-I",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(154),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC_KQPMiRQl3CFAIKTVfCHwA"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC_KQPMiRQl3CFAIKTVfCHwA"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_h8ltx5oKvyY",
|
||||||
|
name: "Pedha Rasi Peddamma Katha",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(3),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
TrackItem(
|
||||||
|
id: "20vIKLJxjBY",
|
||||||
|
name: "[name]",
|
||||||
|
duration: Some(178),
|
||||||
|
cover: [],
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: None,
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCDqpyYkgWy2h03HamIfODjw"),
|
||||||
|
album: Some(AlbumId(
|
||||||
|
id: "MPREb_h8ltx5oKvyY",
|
||||||
|
name: "Pedha Rasi Peddamma Katha",
|
||||||
|
)),
|
||||||
|
view_count: None,
|
||||||
|
is_video: false,
|
||||||
|
track_nr: Some(4),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
variants: [
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_bqWA6mAZFWS",
|
||||||
|
name: "Pedha Rasi Peddamma Katha",
|
||||||
|
cover: [
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://lh3.googleusercontent.com/cyKTDdyucqYv8xfv0t3Vs9CkhmvssXRKsGzlWN_DU6A9uapXvovV0Ys2fXc9-r7Jv7V4UB1OD48iYH5z=w226-h226-l90-rj",
|
||||||
|
width: 226,
|
||||||
|
height: 226,
|
||||||
|
),
|
||||||
|
Thumbnail(
|
||||||
|
url: "https://lh3.googleusercontent.com/cyKTDdyucqYv8xfv0t3Vs9CkhmvssXRKsGzlWN_DU6A9uapXvovV0Ys2fXc9-r7Jv7V4UB1OD48iYH5z=w544-h544-l90-rj",
|
||||||
|
width: 544,
|
||||||
|
height: 544,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artists: [],
|
||||||
|
artist_id: None,
|
||||||
|
album_type: Ep,
|
||||||
|
year: None,
|
||||||
|
by_va: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
665
tests/snapshots/youtube__music_artist_basic_all_intl.snap
Normal file
665
tests/snapshots/youtube__music_artist_basic_all_intl.snap
Normal file
|
|
@ -0,0 +1,665 @@
|
||||||
|
---
|
||||||
|
source: tests/youtube.rs
|
||||||
|
expression: artist
|
||||||
|
---
|
||||||
|
MusicArtist(
|
||||||
|
id: "UC7cl4MmM6ZZ2TcFyMk_b4pg",
|
||||||
|
name: "[name]",
|
||||||
|
header_image: "[header_image]",
|
||||||
|
description: "[description]",
|
||||||
|
wikipedia_url: "[wikipedia_url]",
|
||||||
|
subscriber_count: "[subscriber_count]",
|
||||||
|
tracks: "[tracks]",
|
||||||
|
albums: [
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_43NWLzXChnh",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2010),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_585fV7eqUP8",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2014),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_6PEkIQE7sWY",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Ep,
|
||||||
|
year: Some(2008),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_7nIPO6oeETY",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2012),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_88p7e6nBtgz",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2012),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_8rukEzdytkN",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2015),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_BJKvCuKo7nJ",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2015),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_EAiIEvINDHB",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2012),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_HrCgErOdgCv",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2004),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_Md2aZrjaqHX",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2021),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_OW1GOBZ64ap",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2018),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_Oq0WKqNwSVY",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2003),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_QEClJsuO9xM",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2012),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_QyGCcLWExXj",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2014),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_R3p5kDRIGKL",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2006),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_T4fJMmrfxXk",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2000),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_TiIBQqCFttT",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2016),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_U9HLD8nF7H5",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2017),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_U9dMPQUeR9q",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2012),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_V0FEmw2pj2u",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2017),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_WYx2c0e95TA",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2008),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_Wc8Ehka0R0T",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2021),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_Yj49s4xy7fM",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2021),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_baIxpKBcYbF",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Ep,
|
||||||
|
year: Some(2003),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_eiYjUXT1Mn3",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2010),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_f4MhYbccbPi",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2006),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_gHlGAdNjEZI",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2010),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_kW2NAMSZElX",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2015),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_m5U1xZasDSy",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2002),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_n1H3JiFyGkv",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Ep,
|
||||||
|
year: Some(2015),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_ohcGTZrqKPZ",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2004),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_pWpeXxATZYb",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2014),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_ptO8gh250LP",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Ep,
|
||||||
|
year: Some(2003),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_qbJv3f0ijrk",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2007),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_rHhaDLqalbT",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Ep,
|
||||||
|
year: Some(2010),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_rdrfznTDhSX",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2012),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_saXgTKNPaSu",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2014),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_t6zStv8YrVG",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2010),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_vM0cMpn8pHh",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2008),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_wgm3k1qxpbF",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2010),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_wmSecJVDwPB",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2008),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_xCehp2mGhCk",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2010),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_y5fUQ2toJwT",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2017),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
playlists: "[playlists]",
|
||||||
|
similar_artists: "[artists]",
|
||||||
|
tracks_playlist_id: Some("OLAK5uy_n6aX-F_lCQxgyTIv4FJhp78bXV93b9NUM"),
|
||||||
|
videos_playlist_id: Some("OLAK5uy_nrePwvOEzmO7SydszEFfCDu8gAJxKfFtw"),
|
||||||
|
radio_id: Some("RDEMdgjzN3Qrk_GD7BooQbkJ4A"),
|
||||||
|
)
|
||||||
320
tests/snapshots/youtube__music_artist_basic_intl.snap
Normal file
320
tests/snapshots/youtube__music_artist_basic_intl.snap
Normal file
|
|
@ -0,0 +1,320 @@
|
||||||
|
---
|
||||||
|
source: tests/youtube.rs
|
||||||
|
expression: artist
|
||||||
|
---
|
||||||
|
MusicArtist(
|
||||||
|
id: "UC7cl4MmM6ZZ2TcFyMk_b4pg",
|
||||||
|
name: "[name]",
|
||||||
|
header_image: "[header_image]",
|
||||||
|
description: "[description]",
|
||||||
|
wikipedia_url: "[wikipedia_url]",
|
||||||
|
subscriber_count: "[subscriber_count]",
|
||||||
|
tracks: "[tracks]",
|
||||||
|
albums: [
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_43NWLzXChnh",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2010),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_585fV7eqUP8",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2014),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_6PEkIQE7sWY",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Ep,
|
||||||
|
year: Some(2008),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_88p7e6nBtgz",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2012),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_Md2aZrjaqHX",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2021),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_OW1GOBZ64ap",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2018),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_QyGCcLWExXj",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2014),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_R3p5kDRIGKL",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2006),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_TiIBQqCFttT",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2016),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_U9HLD8nF7H5",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2017),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_V0FEmw2pj2u",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2017),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_WYx2c0e95TA",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2008),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_Yj49s4xy7fM",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2021),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_f4MhYbccbPi",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2006),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_kW2NAMSZElX",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2015),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_n1H3JiFyGkv",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Ep,
|
||||||
|
year: Some(2015),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_pWpeXxATZYb",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2014),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_rHhaDLqalbT",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Ep,
|
||||||
|
year: Some(2010),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_saXgTKNPaSu",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2014),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_wmSecJVDwPB",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UC7cl4MmM6ZZ2TcFyMk_b4pg"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2008),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
playlists: "[playlists]",
|
||||||
|
similar_artists: "[artists]",
|
||||||
|
tracks_playlist_id: Some("OLAK5uy_n6aX-F_lCQxgyTIv4FJhp78bXV93b9NUM"),
|
||||||
|
videos_playlist_id: Some("OLAK5uy_nrePwvOEzmO7SydszEFfCDu8gAJxKfFtw"),
|
||||||
|
radio_id: Some("RDEMdgjzN3Qrk_GD7BooQbkJ4A"),
|
||||||
|
)
|
||||||
19
tests/snapshots/youtube__music_artist_no_artist_intl.snap
Normal file
19
tests/snapshots/youtube__music_artist_no_artist_intl.snap
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
source: tests/youtube.rs
|
||||||
|
expression: artist
|
||||||
|
---
|
||||||
|
MusicArtist(
|
||||||
|
id: "UCh8gHdtzO2tXd593_bjErWg",
|
||||||
|
name: "[name]",
|
||||||
|
header_image: "[header_image]",
|
||||||
|
description: "[description]",
|
||||||
|
wikipedia_url: "[wikipedia_url]",
|
||||||
|
subscriber_count: "[subscriber_count]",
|
||||||
|
tracks: "[tracks]",
|
||||||
|
albums: [],
|
||||||
|
playlists: "[playlists]",
|
||||||
|
similar_artists: "[artists]",
|
||||||
|
tracks_playlist_id: None,
|
||||||
|
videos_playlist_id: None,
|
||||||
|
radio_id: None,
|
||||||
|
)
|
||||||
155
tests/snapshots/youtube__music_artist_no_more_albums_intl.snap
Normal file
155
tests/snapshots/youtube__music_artist_no_more_albums_intl.snap
Normal file
|
|
@ -0,0 +1,155 @@
|
||||||
|
---
|
||||||
|
source: tests/youtube.rs
|
||||||
|
expression: artist
|
||||||
|
---
|
||||||
|
MusicArtist(
|
||||||
|
id: "UCOR4_bSVIXPsGa4BbCSt60Q",
|
||||||
|
name: "[name]",
|
||||||
|
header_image: "[header_image]",
|
||||||
|
description: "[description]",
|
||||||
|
wikipedia_url: "[wikipedia_url]",
|
||||||
|
subscriber_count: "[subscriber_count]",
|
||||||
|
tracks: "[tracks]",
|
||||||
|
albums: [
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_8PsIyll0LFV",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2014),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_HPXN9BBzFpV",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2017),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_POeT6m0bw9q",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
album_type: Ep,
|
||||||
|
year: Some(2014),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_R6EV2L1q0oc",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2017),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_UYdRV1nnK2J",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2017),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_bi34SGT1xlc",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
album_type: Album,
|
||||||
|
year: Some(2014),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_hcK0fXETEf9",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2017),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_kLvmX2AzYBL",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2014),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_oHieBHkXn3A",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCOR4_bSVIXPsGa4BbCSt60Q"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2014),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
playlists: "[playlists]",
|
||||||
|
similar_artists: "[artists]",
|
||||||
|
tracks_playlist_id: Some("OLAK5uy_miHesZCUQY5S9EwqfoNP2tZR9nZ0NBAeU"),
|
||||||
|
videos_playlist_id: Some("OLAK5uy_mqbgE6T9uvusUWrAxJGiImf4_P4dM7IvQ"),
|
||||||
|
radio_id: Some("RDEM7AbogW0cCnElSU0WYm1GqA"),
|
||||||
|
)
|
||||||
35
tests/snapshots/youtube__music_artist_only_singles_intl.snap
Normal file
35
tests/snapshots/youtube__music_artist_only_singles_intl.snap
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
source: tests/youtube.rs
|
||||||
|
expression: artist
|
||||||
|
---
|
||||||
|
MusicArtist(
|
||||||
|
id: "UCfwCE5VhPMGxNPFxtVv7lRw",
|
||||||
|
name: "[name]",
|
||||||
|
header_image: "[header_image]",
|
||||||
|
description: "[description]",
|
||||||
|
wikipedia_url: "[wikipedia_url]",
|
||||||
|
subscriber_count: "[subscriber_count]",
|
||||||
|
tracks: "[tracks]",
|
||||||
|
albums: [
|
||||||
|
AlbumItem(
|
||||||
|
id: "MPREb_vq8dZfFBEdx",
|
||||||
|
name: "[name]",
|
||||||
|
cover: "[cover]",
|
||||||
|
artists: [
|
||||||
|
ArtistId(
|
||||||
|
id: Some("UCfwCE5VhPMGxNPFxtVv7lRw"),
|
||||||
|
name: "[name]",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
artist_id: Some("UCfwCE5VhPMGxNPFxtVv7lRw"),
|
||||||
|
album_type: Single,
|
||||||
|
year: Some(2019),
|
||||||
|
by_va: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
playlists: "[playlists]",
|
||||||
|
similar_artists: "[artists]",
|
||||||
|
tracks_playlist_id: None,
|
||||||
|
videos_playlist_id: Some("OLAK5uy_lmH3iVq6lqjsnLkBWzpvRTh0DidLzbU-I"),
|
||||||
|
radio_id: Some("RDEMYsk_DTFHAng1G7n5toi_oA"),
|
||||||
|
)
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
---
|
---
|
||||||
source: tests/youtube.rs
|
source: tests/youtube.rs
|
||||||
expression: lyrics
|
expression: lyrics.body
|
||||||
---
|
---
|
||||||
Lyrics(
|
"Eyes, in the sky, gazing far into the night\nI raise my hand to the fire, but it\'s no use\n\'Cause you can\'t stop it from shining through\nIt\'s true\nBaby let the light shine through\nIf you believe it\'s true\nBaby won\'t you let the light shine through\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nWon\'t you let the light shine through\n\nEyes, in the sky, gazing far into the night\nI raise my hand to the fire, but it\'s no use\n\'Cause you can\'t stop it from shining through\nIt\'s true\nBaby let the light shine through\nIf you believe it\'s true\nBaby won\'t you let the light shine through\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you"
|
||||||
body: "Eyes, in the sky, gazing far into the night\nI raise my hand to the fire, but it\'s no use\n\'Cause you can\'t stop it from shining through\nIt\'s true\nBaby let the light shine through\nIf you believe it\'s true\nBaby won\'t you let the light shine through\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nWon\'t you let the light shine through\n\nEyes, in the sky, gazing far into the night\nI raise my hand to the fire, but it\'s no use\n\'Cause you can\'t stop it from shining through\nIt\'s true\nBaby let the light shine through\nIf you believe it\'s true\nBaby won\'t you let the light shine through\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you\nFor you",
|
|
||||||
footer: "Source: Musixmatch",
|
|
||||||
)
|
|
||||||
|
|
|
||||||
191
tests/youtube.rs
191
tests/youtube.rs
|
|
@ -1,8 +1,10 @@
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use rstest::{fixture, rstest};
|
use rstest::{fixture, rstest};
|
||||||
use rustypipe::model::paginator::ContinuationEndpoint;
|
use rustypipe::model::paginator::ContinuationEndpoint;
|
||||||
|
use rustypipe::param::Language;
|
||||||
use rustypipe::validate;
|
use rustypipe::validate;
|
||||||
use time::macros::date;
|
use time::macros::date;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
|
|
@ -921,35 +923,46 @@ fn assert_channel_eevblog<T>(channel: &Channel<T>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
#[case::artist("UC_vmjW5e1xEHhYjY2a0kK1A", "Oonagh - Topic", false, false)]
|
#[case::artist("UC_vmjW5e1xEHhYjY2a0kK1A", "Oonagh - Topic", false, false, false)]
|
||||||
#[case::shorts("UCh8gHdtzO2tXd593_bjErWg", "Doobydobap", true, true)]
|
#[case::shorts("UCh8gHdtzO2tXd593_bjErWg", "Doobydobap", true, true, true)]
|
||||||
#[case::livestream(
|
#[case::livestream(
|
||||||
"UChs0pSaEoNLV4mevBFGaoKA",
|
"UChs0pSaEoNLV4mevBFGaoKA",
|
||||||
"The Good Life Radio x Sensual Musique",
|
"The Good Life Radio x Sensual Musique",
|
||||||
true,
|
true,
|
||||||
|
true,
|
||||||
true
|
true
|
||||||
)]
|
)]
|
||||||
#[case::music("UC-9-kyTW8ZkZNDHQJ6FgpwQ", "Music", false, false)]
|
#[case::music("UC-9-kyTW8ZkZNDHQJ6FgpwQ", "Music", false, false, false)]
|
||||||
fn channel_more(
|
fn channel_more(
|
||||||
#[case] id: &str,
|
#[case] id: &str,
|
||||||
#[case] name: &str,
|
#[case] name: &str,
|
||||||
#[case] has_videos: bool,
|
#[case] has_videos: bool,
|
||||||
#[case] has_playlists: bool,
|
#[case] has_playlists: bool,
|
||||||
|
#[case] name_unlocalized: bool,
|
||||||
rp: RustyPipe,
|
rp: RustyPipe,
|
||||||
|
unlocalized: bool,
|
||||||
) {
|
) {
|
||||||
fn assert_channel<T>(channel: &Channel<T>, id: &str, name: &str) {
|
fn assert_channel<T>(channel: &Channel<T>, id: &str, name: &str, unlocalized: bool) {
|
||||||
assert_eq!(channel.id, id);
|
assert_eq!(channel.id, id);
|
||||||
assert_eq!(channel.name, name);
|
|
||||||
|
if unlocalized {
|
||||||
|
assert_eq!(channel.name, name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let channel_videos = tokio_test::block_on(rp.query().channel_videos(&id)).unwrap();
|
let channel_videos = tokio_test::block_on(rp.query().channel_videos(&id)).unwrap();
|
||||||
assert_channel(&channel_videos, id, name);
|
assert_channel(&channel_videos, id, name, unlocalized || name_unlocalized);
|
||||||
if has_videos {
|
if has_videos {
|
||||||
assert!(!channel_videos.content.items.is_empty(), "got no videos");
|
assert!(!channel_videos.content.items.is_empty(), "got no videos");
|
||||||
}
|
}
|
||||||
|
|
||||||
let channel_playlists = tokio_test::block_on(rp.query().channel_playlists(&id)).unwrap();
|
let channel_playlists = tokio_test::block_on(rp.query().channel_playlists(&id)).unwrap();
|
||||||
assert_channel(&channel_playlists, id, name);
|
assert_channel(
|
||||||
|
&channel_playlists,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
unlocalized || name_unlocalized,
|
||||||
|
);
|
||||||
if has_playlists {
|
if has_playlists {
|
||||||
assert!(
|
assert!(
|
||||||
!channel_playlists.content.items.is_empty(),
|
!channel_playlists.content.items.is_empty(),
|
||||||
|
|
@ -958,7 +971,7 @@ fn channel_more(
|
||||||
}
|
}
|
||||||
|
|
||||||
let channel_info = tokio_test::block_on(rp.query().channel_info(&id)).unwrap();
|
let channel_info = tokio_test::block_on(rp.query().channel_info(&id)).unwrap();
|
||||||
assert_channel(&channel_info, id, name);
|
assert_channel(&channel_info, id, name, unlocalized || name_unlocalized);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
|
|
@ -968,7 +981,7 @@ fn channel_more(
|
||||||
#[case::sports("UCEgdi0XIXXZ-qJOFPf4JSKw")]
|
#[case::sports("UCEgdi0XIXXZ-qJOFPf4JSKw")]
|
||||||
#[case::learning("UCtFRv9O2AHqOZjjynzrv-xg")]
|
#[case::learning("UCtFRv9O2AHqOZjjynzrv-xg")]
|
||||||
#[case::live("UC4R8DWoMoI7CAwX8_LjQHig")]
|
#[case::live("UC4R8DWoMoI7CAwX8_LjQHig")]
|
||||||
#[case::news("UCYfdidRxbB8Qhf0Nx7ioOYw")]
|
// #[case::news("UCYfdidRxbB8Qhf0Nx7ioOYw")]
|
||||||
fn channel_not_found(#[case] id: &str, rp: RustyPipe) {
|
fn channel_not_found(#[case] id: &str, rp: RustyPipe) {
|
||||||
let err = tokio_test::block_on(rp.query().channel_videos(&id)).unwrap_err();
|
let err = tokio_test::block_on(rp.query().channel_videos(&id)).unwrap_err();
|
||||||
|
|
||||||
|
|
@ -1030,15 +1043,17 @@ mod channel_rss {
|
||||||
//#SEARCH
|
//#SEARCH
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn search(rp: RustyPipe) {
|
fn search(rp: RustyPipe, unlocalized: bool) {
|
||||||
let result = tokio_test::block_on(rp.query().search("doobydoobap")).unwrap();
|
let result = tokio_test::block_on(rp.query().search("doobydoobap")).unwrap();
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
result.items.count.unwrap() > 7000,
|
result.items.count.unwrap() > 1000,
|
||||||
"expected > 7000 total results, got {}",
|
"expected > 1000 total results, got {}",
|
||||||
result.items.count.unwrap()
|
result.items.count.unwrap()
|
||||||
);
|
);
|
||||||
assert_eq!(result.corrected_query.unwrap(), "doobydobap");
|
if unlocalized {
|
||||||
|
assert_eq!(result.corrected_query.unwrap(), "doobydobap");
|
||||||
|
}
|
||||||
|
|
||||||
assert_next(result.items, rp.query(), 10, 2);
|
assert_next(result.items, rp.query(), 10, 2);
|
||||||
}
|
}
|
||||||
|
|
@ -1094,8 +1109,12 @@ fn search_suggestion(rp: RustyPipe) {
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn search_suggestion_empty(rp: RustyPipe) {
|
fn search_suggestion_empty(rp: RustyPipe) {
|
||||||
let result =
|
let result = tokio_test::block_on(
|
||||||
tokio_test::block_on(rp.query().search_suggestion("fjew327%4ifjelwfvnewg49")).unwrap();
|
rp.query()
|
||||||
|
.lang(Language::Th)
|
||||||
|
.search_suggestion("fjew327p4ifjelwfvnewg49"),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
assert!(result.is_empty());
|
assert!(result.is_empty());
|
||||||
}
|
}
|
||||||
|
|
@ -1214,6 +1233,7 @@ fn music_playlist(
|
||||||
#[case] channel: Option<(&str, &str)>,
|
#[case] channel: Option<(&str, &str)>,
|
||||||
#[case] from_ytm: bool,
|
#[case] from_ytm: bool,
|
||||||
rp: RustyPipe,
|
rp: RustyPipe,
|
||||||
|
unlocalized: bool,
|
||||||
) {
|
) {
|
||||||
let playlist = tokio_test::block_on(rp.query().music_playlist(id)).unwrap();
|
let playlist = tokio_test::block_on(rp.query().music_playlist(id)).unwrap();
|
||||||
|
|
||||||
|
|
@ -1226,7 +1246,9 @@ fn music_playlist(
|
||||||
if is_long { 100 } else { 10 },
|
if is_long { 100 } else { 10 },
|
||||||
"track count",
|
"track count",
|
||||||
);
|
);
|
||||||
assert_eq!(playlist.description, description);
|
if unlocalized {
|
||||||
|
assert_eq!(playlist.description, description);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(expect) = channel {
|
if let Some(expect) = channel {
|
||||||
let c = playlist.channel.unwrap();
|
let c = playlist.channel.unwrap();
|
||||||
|
|
@ -1296,14 +1318,25 @@ fn music_playlist_not_found(rp: RustyPipe) {
|
||||||
#[case::no_year("no_year", "MPREb_F3Af9UZZVxX")]
|
#[case::no_year("no_year", "MPREb_F3Af9UZZVxX")]
|
||||||
#[case::version_no_artist("version_no_artist", "MPREb_h8ltx5oKvyY")]
|
#[case::version_no_artist("version_no_artist", "MPREb_h8ltx5oKvyY")]
|
||||||
#[case::no_artist("no_artist", "MPREb_bqWA6mAZFWS")]
|
#[case::no_artist("no_artist", "MPREb_bqWA6mAZFWS")]
|
||||||
fn music_album(#[case] name: &str, #[case] id: &str, rp: RustyPipe) {
|
fn music_album(#[case] name: &str, #[case] id: &str, rp: RustyPipe, unlocalized: bool) {
|
||||||
let album = tokio_test::block_on(rp.query().music_album(id)).unwrap();
|
let album = tokio_test::block_on(rp.query().music_album(id)).unwrap();
|
||||||
|
|
||||||
assert!(!album.cover.is_empty(), "got no cover");
|
assert!(!album.cover.is_empty(), "got no cover");
|
||||||
|
|
||||||
insta::assert_ron_snapshot!(format!("music_album_{name}"), album,
|
if unlocalized {
|
||||||
{".cover" => "[cover]"}
|
insta::assert_ron_snapshot!(format!("music_album_{name}"), album,
|
||||||
);
|
{".cover" => "[cover]"}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
insta::assert_ron_snapshot!(format!("music_album_{name}_intl"), album,
|
||||||
|
{
|
||||||
|
".cover" => "[cover]",
|
||||||
|
".artists[].name" => "[name]",
|
||||||
|
".tracks[].name" => "[name]",
|
||||||
|
".tracks[].artists[].name" => "[name]",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
|
|
@ -1335,6 +1368,7 @@ fn music_artist(
|
||||||
#[case] min_tracks: usize,
|
#[case] min_tracks: usize,
|
||||||
#[case] min_playlists: usize,
|
#[case] min_playlists: usize,
|
||||||
rp: RustyPipe,
|
rp: RustyPipe,
|
||||||
|
unlocalized: bool,
|
||||||
) {
|
) {
|
||||||
let mut artist = tokio_test::block_on(rp.query().music_artist(id, all_albums)).unwrap();
|
let mut artist = tokio_test::block_on(rp.query().music_artist(id, all_albums)).unwrap();
|
||||||
|
|
||||||
|
|
@ -1370,14 +1404,30 @@ fn music_artist(
|
||||||
// Sort albums to ensure consistent order
|
// Sort albums to ensure consistent order
|
||||||
artist.albums.sort_by_key(|a| a.id.to_owned());
|
artist.albums.sort_by_key(|a| a.id.to_owned());
|
||||||
|
|
||||||
insta::assert_ron_snapshot!(format!("music_artist_{name}"), artist, {
|
if unlocalized {
|
||||||
".header_image" => "[header_image]",
|
insta::assert_ron_snapshot!(format!("music_artist_{name}"), artist, {
|
||||||
".subscriber_count" => "[subscriber_count]",
|
".header_image" => "[header_image]",
|
||||||
".albums[].cover" => "[cover]",
|
".subscriber_count" => "[subscriber_count]",
|
||||||
".tracks" => "[tracks]",
|
".albums[].cover" => "[cover]",
|
||||||
".playlists" => "[playlists]",
|
".tracks" => "[tracks]",
|
||||||
".similar_artists" => "[artists]",
|
".playlists" => "[playlists]",
|
||||||
});
|
".similar_artists" => "[artists]",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
insta::assert_ron_snapshot!(format!("music_artist_{name}_intl"), artist, {
|
||||||
|
".name" => "[name]",
|
||||||
|
".header_image" => "[header_image]",
|
||||||
|
".description" => "[description]",
|
||||||
|
".wikipedia_url" => "[wikipedia_url]",
|
||||||
|
".subscriber_count" => "[subscriber_count]",
|
||||||
|
".albums[].name" => "[name]",
|
||||||
|
".albums[].cover" => "[cover]",
|
||||||
|
".albums[].artists[].name" => "[name]",
|
||||||
|
".tracks" => "[tracks]",
|
||||||
|
".playlists" => "[playlists]",
|
||||||
|
".similar_artists" => "[artists]",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
|
|
@ -1397,7 +1447,7 @@ fn music_artist_not_found(rp: RustyPipe) {
|
||||||
#[rstest]
|
#[rstest]
|
||||||
#[case::default(false)]
|
#[case::default(false)]
|
||||||
#[case::typo(true)]
|
#[case::typo(true)]
|
||||||
fn music_search(#[case] typo: bool, rp: RustyPipe) {
|
fn music_search(#[case] typo: bool, rp: RustyPipe, unlocalized: bool) {
|
||||||
let res = tokio_test::block_on(rp.query().music_search(match typo {
|
let res = tokio_test::block_on(rp.query().music_search(match typo {
|
||||||
false => "lieblingsmensch namika",
|
false => "lieblingsmensch namika",
|
||||||
true => "lieblingsmesch namika",
|
true => "lieblingsmesch namika",
|
||||||
|
|
@ -1434,7 +1484,9 @@ fn music_search(#[case] typo: bool, rp: RustyPipe) {
|
||||||
track_artist.id.as_ref().unwrap(),
|
track_artist.id.as_ref().unwrap(),
|
||||||
"UCIh4j8fXWf2U0ro0qnGU8Mg"
|
"UCIh4j8fXWf2U0ro0qnGU8Mg"
|
||||||
);
|
);
|
||||||
assert_eq!(track_artist.name, "Namika");
|
if unlocalized {
|
||||||
|
assert_eq!(track_artist.name, "Namika");
|
||||||
|
}
|
||||||
|
|
||||||
let track_album = track.album.as_ref().unwrap();
|
let track_album = track.album.as_ref().unwrap();
|
||||||
assert_eq!(track_album.id, "MPREb_RXHxrUFfrvQ");
|
assert_eq!(track_album.id, "MPREb_RXHxrUFfrvQ");
|
||||||
|
|
@ -1446,7 +1498,7 @@ fn music_search(#[case] typo: bool, rp: RustyPipe) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn music_search2(rp: RustyPipe) {
|
fn music_search2(rp: RustyPipe, unlocalized: bool) {
|
||||||
let res = tokio_test::block_on(rp.query().music_search("taylor swift")).unwrap();
|
let res = tokio_test::block_on(rp.query().music_search("taylor swift")).unwrap();
|
||||||
|
|
||||||
assert!(!res.tracks.is_empty(), "no tracks");
|
assert!(!res.tracks.is_empty(), "no tracks");
|
||||||
|
|
@ -1463,12 +1515,14 @@ fn music_search2(rp: RustyPipe) {
|
||||||
panic!("could not find artist, got {:#?}", &res.artists);
|
panic!("could not find artist, got {:#?}", &res.artists);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(artist.name, "Taylor Swift");
|
if unlocalized {
|
||||||
|
assert_eq!(artist.name, "Taylor Swift");
|
||||||
|
}
|
||||||
assert!(!artist.avatar.is_empty(), "got no avatar");
|
assert!(!artist.avatar.is_empty(), "got no avatar");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn music_search_tracks(rp: RustyPipe) {
|
fn music_search_tracks(rp: RustyPipe, unlocalized: bool) {
|
||||||
let res = tokio_test::block_on(rp.query().music_search_tracks("black mamba")).unwrap();
|
let res = tokio_test::block_on(rp.query().music_search_tracks("black mamba")).unwrap();
|
||||||
|
|
||||||
let track = &res
|
let track = &res
|
||||||
|
|
@ -1489,7 +1543,9 @@ fn music_search_tracks(rp: RustyPipe) {
|
||||||
track_artist.id.as_ref().unwrap(),
|
track_artist.id.as_ref().unwrap(),
|
||||||
"UCEdZAdnnKqbaHOlv8nM6OtA"
|
"UCEdZAdnnKqbaHOlv8nM6OtA"
|
||||||
);
|
);
|
||||||
assert_eq!(track_artist.name, "aespa");
|
if unlocalized {
|
||||||
|
assert_eq!(track_artist.name, "aespa");
|
||||||
|
}
|
||||||
|
|
||||||
assert_eq!(track.duration.unwrap(), 175);
|
assert_eq!(track.duration.unwrap(), 175);
|
||||||
|
|
||||||
|
|
@ -1501,7 +1557,7 @@ fn music_search_tracks(rp: RustyPipe) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn music_search_videos(rp: RustyPipe) {
|
fn music_search_videos(rp: RustyPipe, unlocalized: bool) {
|
||||||
let res = tokio_test::block_on(rp.query().music_search_videos("black mamba")).unwrap();
|
let res = tokio_test::block_on(rp.query().music_search_videos("black mamba")).unwrap();
|
||||||
|
|
||||||
let track = &res
|
let track = &res
|
||||||
|
|
@ -1522,7 +1578,9 @@ fn music_search_videos(rp: RustyPipe) {
|
||||||
track_artist.id.as_ref().unwrap(),
|
track_artist.id.as_ref().unwrap(),
|
||||||
"UCEdZAdnnKqbaHOlv8nM6OtA"
|
"UCEdZAdnnKqbaHOlv8nM6OtA"
|
||||||
);
|
);
|
||||||
assert_eq!(track_artist.name, "aespa");
|
if unlocalized {
|
||||||
|
assert_eq!(track_artist.name, "aespa");
|
||||||
|
}
|
||||||
|
|
||||||
assert_eq!(track.duration.unwrap(), 230);
|
assert_eq!(track.duration.unwrap(), 230);
|
||||||
assert_eq!(track.album, None);
|
assert_eq!(track.album, None);
|
||||||
|
|
@ -1621,7 +1679,7 @@ fn music_search_albums(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn music_search_artists(rp: RustyPipe) {
|
fn music_search_artists(rp: RustyPipe, unlocalized: bool) {
|
||||||
let res = tokio_test::block_on(rp.query().music_search_artists("namika")).unwrap();
|
let res = tokio_test::block_on(rp.query().music_search_artists("namika")).unwrap();
|
||||||
|
|
||||||
let artist = res
|
let artist = res
|
||||||
|
|
@ -1630,7 +1688,9 @@ fn music_search_artists(rp: RustyPipe) {
|
||||||
.iter()
|
.iter()
|
||||||
.find(|a| a.id == "UCIh4j8fXWf2U0ro0qnGU8Mg")
|
.find(|a| a.id == "UCIh4j8fXWf2U0ro0qnGU8Mg")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(artist.name, "Namika");
|
if unlocalized {
|
||||||
|
assert_eq!(artist.name, "Namika");
|
||||||
|
}
|
||||||
assert!(!artist.avatar.is_empty(), "got no avatar");
|
assert!(!artist.avatar.is_empty(), "got no avatar");
|
||||||
assert!(
|
assert!(
|
||||||
artist.subscriber_count.unwrap() > 735_000,
|
artist.subscriber_count.unwrap() > 735_000,
|
||||||
|
|
@ -1651,7 +1711,7 @@ fn music_search_artists_cont(rp: RustyPipe) {
|
||||||
#[rstest]
|
#[rstest]
|
||||||
#[case::ytm(false)]
|
#[case::ytm(false)]
|
||||||
#[case::default(true)]
|
#[case::default(true)]
|
||||||
fn music_search_playlists(#[case] with_community: bool, rp: RustyPipe) {
|
fn music_search_playlists(#[case] with_community: bool, rp: RustyPipe, unlocalized: bool) {
|
||||||
let res = if with_community {
|
let res = if with_community {
|
||||||
tokio_test::block_on(rp.query().music_search_playlists("pop biggest hits")).unwrap()
|
tokio_test::block_on(rp.query().music_search_playlists("pop biggest hits")).unwrap()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1670,7 +1730,9 @@ fn music_search_playlists(#[case] with_community: bool, rp: RustyPipe) {
|
||||||
.find(|p| p.id == "RDCLAK5uy_nmS3YoxSwVVQk9lEQJ0UX4ZCjXsW_psU8")
|
.find(|p| p.id == "RDCLAK5uy_nmS3YoxSwVVQk9lEQJ0UX4ZCjXsW_psU8")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(playlist.name, "Pop's Biggest Hits");
|
if unlocalized {
|
||||||
|
assert_eq!(playlist.name, "Pop's Biggest Hits");
|
||||||
|
}
|
||||||
assert!(!playlist.thumbnail.is_empty(), "got no thumbnail");
|
assert!(!playlist.thumbnail.is_empty(), "got no thumbnail");
|
||||||
assert_gte(playlist.track_count.unwrap(), 100, "tracks");
|
assert_gte(playlist.track_count.unwrap(), 100, "tracks");
|
||||||
assert_eq!(playlist.channel, None);
|
assert_eq!(playlist.channel, None);
|
||||||
|
|
@ -1784,7 +1846,12 @@ fn music_details(#[case] name: &str, #[case] id: &str, rp: RustyPipe) {
|
||||||
fn music_lyrics(rp: RustyPipe) {
|
fn music_lyrics(rp: RustyPipe) {
|
||||||
let track = tokio_test::block_on(rp.query().music_details("60ImQ8DS3Vs")).unwrap();
|
let track = tokio_test::block_on(rp.query().music_details("60ImQ8DS3Vs")).unwrap();
|
||||||
let lyrics = tokio_test::block_on(rp.query().music_lyrics(&track.lyrics_id.unwrap())).unwrap();
|
let lyrics = tokio_test::block_on(rp.query().music_lyrics(&track.lyrics_id.unwrap())).unwrap();
|
||||||
insta::assert_ron_snapshot!(lyrics);
|
insta::assert_ron_snapshot!(lyrics.body);
|
||||||
|
assert!(
|
||||||
|
lyrics.footer.contains("Musixmatch"),
|
||||||
|
"footer text: {}",
|
||||||
|
lyrics.footer
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
|
|
@ -2041,14 +2108,16 @@ fn music_new_videos(rp: RustyPipe) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn music_genres(rp: RustyPipe) {
|
fn music_genres(rp: RustyPipe, unlocalized: bool) {
|
||||||
let genres = tokio_test::block_on(rp.query().music_genres()).unwrap();
|
let genres = tokio_test::block_on(rp.query().music_genres()).unwrap();
|
||||||
|
|
||||||
let chill = genres
|
let chill = genres
|
||||||
.iter()
|
.iter()
|
||||||
.find(|g| g.id == "ggMPOg1uX1JOQWZFeDByc2Jm")
|
.find(|g| g.id == "ggMPOg1uX1JOQWZFeDByc2Jm")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(chill.name, "Chill");
|
if unlocalized {
|
||||||
|
assert_eq!(chill.name, "Chill");
|
||||||
|
}
|
||||||
assert!(chill.is_mood);
|
assert!(chill.is_mood);
|
||||||
|
|
||||||
let pop = genres
|
let pop = genres
|
||||||
|
|
@ -2067,12 +2136,19 @@ fn music_genres(rp: RustyPipe) {
|
||||||
#[rstest]
|
#[rstest]
|
||||||
#[case::chill("ggMPOg1uX1JOQWZFeDByc2Jm", "Chill")]
|
#[case::chill("ggMPOg1uX1JOQWZFeDByc2Jm", "Chill")]
|
||||||
#[case::pop("ggMPOg1uX1lMbVZmbzl6NlJ3", "Pop")]
|
#[case::pop("ggMPOg1uX1lMbVZmbzl6NlJ3", "Pop")]
|
||||||
fn music_genre(#[case] id: &str, #[case] name: &str, rp: RustyPipe) {
|
fn music_genre(#[case] id: &str, #[case] name: &str, rp: RustyPipe, unlocalized: bool) {
|
||||||
let genre = tokio_test::block_on(rp.query().music_genre(id)).unwrap();
|
let genre = tokio_test::block_on(rp.query().music_genre(id)).unwrap();
|
||||||
|
|
||||||
fn check_music_genre(genre: MusicGenre, id: &str, name: &str) -> Vec<(String, String)> {
|
fn check_music_genre(
|
||||||
|
genre: MusicGenre,
|
||||||
|
id: &str,
|
||||||
|
name: &str,
|
||||||
|
unlocalized: bool,
|
||||||
|
) -> Vec<(String, String)> {
|
||||||
assert_eq!(genre.id, id);
|
assert_eq!(genre.id, id);
|
||||||
assert_eq!(genre.name, name);
|
if unlocalized {
|
||||||
|
assert_eq!(genre.name, name);
|
||||||
|
}
|
||||||
assert_gte(genre.sections.len(), 2, "genre sections");
|
assert_gte(genre.sections.len(), 2, "genre sections");
|
||||||
|
|
||||||
let mut subgenres = Vec::new();
|
let mut subgenres = Vec::new();
|
||||||
|
|
@ -2105,7 +2181,7 @@ fn music_genre(#[case] id: &str, #[case] name: &str, rp: RustyPipe) {
|
||||||
subgenres
|
subgenres
|
||||||
}
|
}
|
||||||
|
|
||||||
let subgenres = check_music_genre(genre, id, name);
|
let subgenres = check_music_genre(genre, id, name, unlocalized);
|
||||||
|
|
||||||
if name == "Chill" {
|
if name == "Chill" {
|
||||||
assert_gte(subgenres.len(), 2, "subgenres");
|
assert_gte(subgenres.len(), 2, "subgenres");
|
||||||
|
|
@ -2113,7 +2189,7 @@ fn music_genre(#[case] id: &str, #[case] name: &str, rp: RustyPipe) {
|
||||||
|
|
||||||
for (id, name) in subgenres {
|
for (id, name) in subgenres {
|
||||||
let genre = tokio_test::block_on(rp.query().music_genre(&id)).unwrap();
|
let genre = tokio_test::block_on(rp.query().music_genre(&id)).unwrap();
|
||||||
check_music_genre(genre, &id, &name);
|
check_music_genre(genre, &id, &name, unlocalized);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2167,10 +2243,25 @@ fn invalid_ctoken(#[case] ep: ContinuationEndpoint, rp: RustyPipe) {
|
||||||
|
|
||||||
//#TESTUTIL
|
//#TESTUTIL
|
||||||
|
|
||||||
|
/// Get the language setting from the environment variable
|
||||||
|
#[fixture]
|
||||||
|
fn lang() -> Language {
|
||||||
|
std::env::var("YT_LANG")
|
||||||
|
.ok()
|
||||||
|
.map(|l| Language::from_str(&l).unwrap())
|
||||||
|
.unwrap_or(Language::En)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a new RustyPipe instance
|
/// Get a new RustyPipe instance
|
||||||
#[fixture]
|
#[fixture]
|
||||||
fn rp() -> RustyPipe {
|
fn rp(lang: Language) -> RustyPipe {
|
||||||
RustyPipe::builder().strict().build()
|
RustyPipe::builder().strict().lang(lang).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a flag signaling if the language is set to English
|
||||||
|
#[fixture]
|
||||||
|
fn unlocalized(lang: Language) -> bool {
|
||||||
|
lang == Language::En
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a new RustyPipe instance with pre-set visitor data
|
/// Get a new RustyPipe instance with pre-set visitor data
|
||||||
|
|
|
||||||
Reference in a new issue