feat: add music_new_albums/videos
This commit is contained in:
parent
bd936a8c42
commit
8f82694eaf
15 changed files with 103714 additions and 19 deletions
|
|
@ -14,7 +14,6 @@ members = [".", "codegen", "cli"]
|
|||
|
||||
[features]
|
||||
default = ["default-tls"]
|
||||
all = ["rss"]
|
||||
|
||||
rss = ["quick-xml"]
|
||||
|
||||
|
|
|
|||
2
Justfile
2
Justfile
|
|
@ -1,5 +1,5 @@
|
|||
test:
|
||||
cargo test -F all
|
||||
cargo test --all-features
|
||||
|
||||
testfiles:
|
||||
cargo run -p rustypipe-codegen -- -d . download-testfiles
|
||||
|
|
|
|||
|
|
@ -28,4 +28,4 @@ inspired by [NewPipe](https://github.com/TeamNewPipe/NewPipeExtractor).
|
|||
- [X] **Track details** (lyrics, recommendations)
|
||||
- [ ] **Moods**
|
||||
- [ ] **Charts**
|
||||
- [ ] **New**
|
||||
- [X] **New**
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ pub async fn download_testfiles(project_root: &Path) {
|
|||
music_related(&testfiles).await;
|
||||
music_radio(&testfiles).await;
|
||||
music_radio_cont(&testfiles).await;
|
||||
music_new_albums(&testfiles).await;
|
||||
music_new_videos(&testfiles).await;
|
||||
}
|
||||
|
||||
const CLIENT_TYPES: [ClientType; 5] = [
|
||||
|
|
@ -801,3 +803,27 @@ async fn music_radio_cont(testfiles: &Path) {
|
|||
let rp = rp_testfile(&json_path);
|
||||
res.next(&rp.query()).await.unwrap().unwrap();
|
||||
}
|
||||
|
||||
async fn music_new_albums(testfiles: &Path) {
|
||||
let mut json_path = testfiles.to_path_buf();
|
||||
json_path.push("music_new");
|
||||
json_path.push("albums_default.json");
|
||||
if json_path.exists() {
|
||||
return;
|
||||
}
|
||||
|
||||
let rp = rp_testfile(&json_path);
|
||||
rp.query().music_new_albums().await.unwrap();
|
||||
}
|
||||
|
||||
async fn music_new_videos(testfiles: &Path) {
|
||||
let mut json_path = testfiles.to_path_buf();
|
||||
json_path.push("music_new");
|
||||
json_path.push("videos_default.json");
|
||||
if json_path.exists() {
|
||||
return;
|
||||
}
|
||||
|
||||
let rp = rp_testfile(&json_path);
|
||||
rp.query().music_new_videos().await.unwrap();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ pub(crate) mod response;
|
|||
mod channel;
|
||||
mod music_artist;
|
||||
mod music_details;
|
||||
mod music_new;
|
||||
mod music_playlist;
|
||||
mod music_search;
|
||||
mod pagination;
|
||||
|
|
|
|||
126
src/client/music_new.rs
Normal file
126
src/client/music_new.rs
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use crate::{
|
||||
client::response::music_item::MusicListMapper,
|
||||
error::{Error, ExtractionError},
|
||||
model::{AlbumItem, FromYtItem, TrackItem},
|
||||
};
|
||||
|
||||
use super::{response, ClientType, MapResponse, QBrowse, RustyPipeQuery};
|
||||
|
||||
impl RustyPipeQuery {
|
||||
pub async fn music_new_albums(&self) -> Result<Vec<AlbumItem>, Error> {
|
||||
let context = self.get_context(ClientType::DesktopMusic, true, None).await;
|
||||
let request_body = QBrowse {
|
||||
context,
|
||||
browse_id: "FEmusic_new_releases_albums",
|
||||
};
|
||||
|
||||
self.execute_request::<response::MusicNew, _, _>(
|
||||
ClientType::DesktopMusic,
|
||||
"music_new_albums",
|
||||
"",
|
||||
"browse",
|
||||
&request_body,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn music_new_videos(&self) -> Result<Vec<TrackItem>, Error> {
|
||||
let context = self.get_context(ClientType::DesktopMusic, true, None).await;
|
||||
let request_body = QBrowse {
|
||||
context,
|
||||
browse_id: "FEmusic_new_releases_videos",
|
||||
};
|
||||
|
||||
self.execute_request::<response::MusicNew, _, _>(
|
||||
ClientType::DesktopMusic,
|
||||
"music_new_videos",
|
||||
"",
|
||||
"browse",
|
||||
&request_body,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: FromYtItem> MapResponse<Vec<T>> for response::MusicNew {
|
||||
fn map_response(
|
||||
self,
|
||||
_id: &str,
|
||||
lang: crate::param::Language,
|
||||
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
|
||||
) -> Result<crate::serializer::MapResult<Vec<T>>, ExtractionError> {
|
||||
let items = self
|
||||
.contents
|
||||
.single_column_browse_results_renderer
|
||||
.contents
|
||||
.into_iter()
|
||||
.next()
|
||||
.ok_or(ExtractionError::InvalidData(Cow::Borrowed("no content")))?
|
||||
.tab_renderer
|
||||
.content
|
||||
.section_list_renderer
|
||||
.contents
|
||||
.into_iter()
|
||||
.next()
|
||||
.ok_or(ExtractionError::InvalidData(Cow::Borrowed("no content")))?
|
||||
.grid_renderer
|
||||
.items;
|
||||
|
||||
let mut mapper = MusicListMapper::new(lang);
|
||||
mapper.map_response(items);
|
||||
|
||||
Ok(mapper.conv_items())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{fs::File, io::BufReader, path::Path};
|
||||
|
||||
use rstest::rstest;
|
||||
|
||||
use super::*;
|
||||
use crate::{param::Language, serializer::MapResult};
|
||||
|
||||
#[rstest]
|
||||
#[case::default("default")]
|
||||
fn map_music_new_albums(#[case] name: &str) {
|
||||
let filename = format!("testfiles/music_new/albums_{}.json", name);
|
||||
let json_path = Path::new(&filename);
|
||||
let json_file = File::open(json_path).unwrap();
|
||||
|
||||
let new_albums: response::MusicNew =
|
||||
serde_json::from_reader(BufReader::new(json_file)).unwrap();
|
||||
let map_res: MapResult<Vec<AlbumItem>> =
|
||||
new_albums.map_response("", Language::En, None).unwrap();
|
||||
|
||||
assert!(
|
||||
map_res.warnings.is_empty(),
|
||||
"deserialization/mapping warnings: {:?}",
|
||||
map_res.warnings
|
||||
);
|
||||
insta::assert_ron_snapshot!(format!("map_music_new_albums_{}", name), map_res.c);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case::default("default")]
|
||||
fn map_music_new_videos(#[case] name: &str) {
|
||||
let filename = format!("testfiles/music_new/videos_{}.json", name);
|
||||
let json_path = Path::new(&filename);
|
||||
let json_file = File::open(json_path).unwrap();
|
||||
|
||||
let new_albums: response::MusicNew =
|
||||
serde_json::from_reader(BufReader::new(json_file)).unwrap();
|
||||
let map_res: MapResult<Vec<TrackItem>> =
|
||||
new_albums.map_response("", Language::En, None).unwrap();
|
||||
|
||||
assert!(
|
||||
map_res.warnings.is_empty(),
|
||||
"deserialization/mapping warnings: {:?}",
|
||||
map_res.warnings
|
||||
);
|
||||
insta::assert_ron_snapshot!(format!("map_music_new_videos_{}", name), map_res.c);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ pub(crate) mod channel;
|
|||
pub(crate) mod music_artist;
|
||||
pub(crate) mod music_details;
|
||||
pub(crate) mod music_item;
|
||||
pub(crate) mod music_new;
|
||||
pub(crate) mod music_playlist;
|
||||
pub(crate) mod music_search;
|
||||
pub(crate) mod player;
|
||||
|
|
@ -19,6 +20,7 @@ pub(crate) use music_details::MusicDetails;
|
|||
pub(crate) use music_details::MusicLyrics;
|
||||
pub(crate) use music_details::MusicRelated;
|
||||
pub(crate) use music_item::MusicContinuation;
|
||||
pub(crate) use music_new::MusicNew;
|
||||
pub(crate) use music_playlist::MusicPlaylist;
|
||||
pub(crate) use music_search::MusicSearch;
|
||||
pub(crate) use music_search::MusicSearchSuggestion;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use serde::Deserialize;
|
||||
use serde_with::{serde_as, DefaultOnError};
|
||||
|
||||
use crate::serializer::{text::Text, MapResult, VecLogError};
|
||||
use crate::serializer::text::Text;
|
||||
|
||||
use super::{
|
||||
music_item::{ItemSection, MusicResponseItem, MusicThumbnailRenderer},
|
||||
music_item::{Grid, ItemSection, MusicThumbnailRenderer},
|
||||
ContentsRenderer, SectionList, Tab,
|
||||
};
|
||||
|
||||
|
|
@ -67,20 +67,6 @@ pub(crate) struct MusicArtistAlbums {
|
|||
pub contents: Contents<Grid>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct Grid {
|
||||
pub grid_renderer: GridRenderer,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct GridRenderer {
|
||||
#[serde_as(as = "VecLogError<_>")]
|
||||
pub items: MapResult<Vec<MusicResponseItem>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct SimpleHeader {
|
||||
|
|
|
|||
|
|
@ -340,6 +340,20 @@ pub(crate) struct MusicItemMenuEntry {
|
|||
pub menu_navigation_item_renderer: ButtonRenderer,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct Grid {
|
||||
pub grid_renderer: GridRenderer,
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct GridRenderer {
|
||||
#[serde_as(as = "VecLogError<_>")]
|
||||
pub items: MapResult<Vec<MusicResponseItem>>,
|
||||
}
|
||||
|
||||
/*
|
||||
#MAPPER
|
||||
*/
|
||||
|
|
|
|||
15
src/client/response/music_new.rs
Normal file
15
src/client/response/music_new.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
use super::{music_item::Grid, ContentsRenderer, SectionList, Tab};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct MusicNew {
|
||||
pub contents: Contents,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct Contents {
|
||||
pub single_column_browse_results_renderer: ContentsRenderer<Tab<SectionList<Grid>>>,
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,299 @@
|
|||
---
|
||||
source: src/client/music_new.rs
|
||||
assertion_line: 125
|
||||
expression: map_res.c
|
||||
---
|
||||
[
|
||||
TrackItem(
|
||||
id: "skl6N3zGv-s",
|
||||
title: "Adieu",
|
||||
duration: None,
|
||||
cover: [
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/skl6N3zGv-s/sddefault.jpg?sqp=-oaymwEWCJADEOEBIAQqCghqEJQEGHgg6AJIWg&rs=AMzJL3ktEUMuvlRUDZBMXDRt-Cx7Nz3EWg",
|
||||
width: 400,
|
||||
height: 225,
|
||||
),
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/skl6N3zGv-s/hq720.jpg?sqp=-oaymwEXCKAGEMIDIAQqCwjVARCqCBh4INgESFo&rs=AMzJL3nyQxZBIheGvsVXeL2EBknUqHPJow",
|
||||
width: 800,
|
||||
height: 450,
|
||||
),
|
||||
],
|
||||
artists: [
|
||||
ArtistId(
|
||||
id: Some("UCs6GGpd9zvsYghuYe0VDFUQ"),
|
||||
name: "Rammstein",
|
||||
),
|
||||
],
|
||||
artist_id: Some("UCs6GGpd9zvsYghuYe0VDFUQ"),
|
||||
album: None,
|
||||
view_count: Some(8600000),
|
||||
is_video: true,
|
||||
track_nr: None,
|
||||
),
|
||||
TrackItem(
|
||||
id: "gFERoNpcnFU",
|
||||
title: "Marteria - Wald (Official Video)",
|
||||
duration: None,
|
||||
cover: [
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/gFERoNpcnFU/sddefault.jpg?sqp=-oaymwEWCJADEOEBIAQqCghqEJQEGHgg6AJIWg&rs=AMzJL3mLZl-GbssOYbd_1gOgbN0VeeD1Wg",
|
||||
width: 400,
|
||||
height: 225,
|
||||
),
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/gFERoNpcnFU/hq720.jpg?sqp=-oaymwEXCKAGEMIDIAQqCwjVARCqCBh4INgESFo&rs=AMzJL3locAMTqlz38oUE3SFLrg2Z4-g1Aw",
|
||||
width: 800,
|
||||
height: 450,
|
||||
),
|
||||
],
|
||||
artists: [
|
||||
ArtistId(
|
||||
id: Some("UCicJjripVxiTXbUfociVZwQ"),
|
||||
name: "MARTERIA",
|
||||
),
|
||||
],
|
||||
artist_id: Some("UCicJjripVxiTXbUfociVZwQ"),
|
||||
album: None,
|
||||
view_count: Some(244000),
|
||||
is_video: true,
|
||||
track_nr: None,
|
||||
),
|
||||
TrackItem(
|
||||
id: "bmEzom5sfCI",
|
||||
title: "ELIF X PA SPORTS - ICH DENK AN DICH (Official Video)",
|
||||
duration: None,
|
||||
cover: [
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/bmEzom5sfCI/sddefault.jpg?sqp=-oaymwEWCJADEOEBIAQqCghqEJQEGHgg6AJIWg&rs=AMzJL3nFPXYLNpvXAYJwNc8cDZv2zbTQ_w",
|
||||
width: 400,
|
||||
height: 225,
|
||||
),
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/bmEzom5sfCI/hq720.jpg?sqp=-oaymwEXCKAGEMIDIAQqCwjVARCqCBh4INgESFo&rs=AMzJL3mkd-afVklbhPQSmdCLjpMEIj6zow",
|
||||
width: 800,
|
||||
height: 450,
|
||||
),
|
||||
],
|
||||
artists: [
|
||||
ArtistId(
|
||||
id: Some("UCuO5r4J0jTrgRYnmfEOd3UQ"),
|
||||
name: "ELIF",
|
||||
),
|
||||
],
|
||||
artist_id: Some("UCuO5r4J0jTrgRYnmfEOd3UQ"),
|
||||
album: None,
|
||||
view_count: Some(314000),
|
||||
is_video: true,
|
||||
track_nr: None,
|
||||
),
|
||||
TrackItem(
|
||||
id: "QHY2pm7uT3k",
|
||||
title: "HOME RUN",
|
||||
duration: None,
|
||||
cover: [
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/QHY2pm7uT3k/sddefault.jpg?sqp=-oaymwEWCJADEOEBIAQqCghqEJQEGHgg6AJIWg&rs=AMzJL3nYr8bEDDfJfpHsCldOvYscc_nmfQ",
|
||||
width: 400,
|
||||
height: 225,
|
||||
),
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/QHY2pm7uT3k/hq720.jpg?sqp=-oaymwEXCKAGEMIDIAQqCwjVARCqCBh4INgESFo&rs=AMzJL3lc6FFxwsEUKprtbtZT8Ug8u6ckaA",
|
||||
width: 800,
|
||||
height: 450,
|
||||
),
|
||||
],
|
||||
artists: [
|
||||
ArtistId(
|
||||
id: Some("UC4gi504gkSyoXt9vfaGUr9A"),
|
||||
name: "Farid Bang",
|
||||
),
|
||||
],
|
||||
artist_id: Some("UC4gi504gkSyoXt9vfaGUr9A"),
|
||||
album: None,
|
||||
view_count: Some(265000),
|
||||
is_video: true,
|
||||
track_nr: None,
|
||||
),
|
||||
TrackItem(
|
||||
id: "Su42LK7I4NM",
|
||||
title: "R3HAB, Timmy Trumpet, W&W - Poison [Tomorrowland Music]",
|
||||
duration: None,
|
||||
cover: [
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/Su42LK7I4NM/sddefault.jpg?sqp=-oaymwEWCJADEOEBIAQqCghqEJQEGHgg6AJIWg&rs=AMzJL3naagfviBJEDib3cquUWBcc0nYEsA",
|
||||
width: 400,
|
||||
height: 225,
|
||||
),
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/Su42LK7I4NM/hq720.jpg?sqp=-oaymwEXCKAGEMIDIAQqCwjVARCqCBh4INgESFo&rs=AMzJL3mf75m2WZU_U9AnZVC5Pry9sDodWA",
|
||||
width: 800,
|
||||
height: 450,
|
||||
),
|
||||
],
|
||||
artists: [
|
||||
ArtistId(
|
||||
id: Some("UCsN8M73DMWa8SPp5o_0IAQQ"),
|
||||
name: "Tomorrowland",
|
||||
),
|
||||
],
|
||||
artist_id: Some("UCsN8M73DMWa8SPp5o_0IAQQ"),
|
||||
album: None,
|
||||
view_count: Some(47000),
|
||||
is_video: true,
|
||||
track_nr: None,
|
||||
),
|
||||
TrackItem(
|
||||
id: "mly7ha04bEE",
|
||||
title: "SAMRA x JOEL BRANDENSTEIN - REGEN (prod. by Lukas Lulou Loules) [Official Video]",
|
||||
duration: None,
|
||||
cover: [
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/mly7ha04bEE/sddefault.jpg?sqp=-oaymwEWCJADEOEBIAQqCghqEJQEGHgg6AJIWg&rs=AMzJL3mZWz0zJVHnKmHxB8bGuGan56w_3g",
|
||||
width: 400,
|
||||
height: 225,
|
||||
),
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/mly7ha04bEE/hq720.jpg?sqp=-oaymwEXCKAGEMIDIAQqCwjVARCqCBh4INgESFo&rs=AMzJL3nWJJNvExgCsjQHgohAaNJYaP-Dtg",
|
||||
width: 800,
|
||||
height: 450,
|
||||
),
|
||||
],
|
||||
artists: [
|
||||
ArtistId(
|
||||
id: Some("UCc_iRXEpehN-dDTkPLoBjZg"),
|
||||
name: "Samra",
|
||||
),
|
||||
],
|
||||
artist_id: Some("UCc_iRXEpehN-dDTkPLoBjZg"),
|
||||
album: None,
|
||||
view_count: Some(225000),
|
||||
is_video: true,
|
||||
track_nr: None,
|
||||
),
|
||||
TrackItem(
|
||||
id: "c91bmLbGt-g",
|
||||
title: "Der Berg ruft",
|
||||
duration: None,
|
||||
cover: [
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/c91bmLbGt-g/sddefault.jpg?sqp=-oaymwEWCJADEOEBIAQqCghqEJQEGHgg6AJIWg&rs=AMzJL3kh7cuvBMYZNVVh9Qci2GKLdEUJTg",
|
||||
width: 400,
|
||||
height: 225,
|
||||
),
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/c91bmLbGt-g/hq720.jpg?sqp=-oaymwEXCKAGEMIDIAQqCwjVARCqCBh4INgESFo&rs=AMzJL3kPm3joE3rQMh_NJfvrWm4c4VaTpA",
|
||||
width: 800,
|
||||
height: 450,
|
||||
),
|
||||
],
|
||||
artists: [
|
||||
ArtistId(
|
||||
id: Some("UCsPz48w0M3QUEGAiDP1x17w"),
|
||||
name: "Bausa",
|
||||
),
|
||||
ArtistId(
|
||||
id: Some("UCqG3KFVWvCPCtKzEYifV5Ew"),
|
||||
name: "Maxwell",
|
||||
),
|
||||
ArtistId(
|
||||
id: Some("UC6EFoBjPEanrpj3ua_khs5w"),
|
||||
name: "Joshi Mizu",
|
||||
),
|
||||
],
|
||||
artist_id: Some("UCsPz48w0M3QUEGAiDP1x17w"),
|
||||
album: None,
|
||||
view_count: Some(124000),
|
||||
is_video: true,
|
||||
track_nr: None,
|
||||
),
|
||||
TrackItem(
|
||||
id: "IwzkfMmNMpM",
|
||||
title: "정국 Jung Kook (of BTS) featuring Fahad Al Kubaisi - Dreamers | FIFA World Cup 2022 Soundtrack",
|
||||
duration: None,
|
||||
cover: [
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/IwzkfMmNMpM/sddefault.jpg?sqp=-oaymwEWCJADEOEBIAQqCghqEJQEGHgg6AJIWg&rs=AMzJL3kCDSVTXecskVcEeDKgRZQTG8x4Yg",
|
||||
width: 400,
|
||||
height: 225,
|
||||
),
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/IwzkfMmNMpM/hq720.jpg?sqp=-oaymwEXCKAGEMIDIAQqCwjVARCqCBh4INgESFo&rs=AMzJL3nrwn3QHyDAiR6IPr9haIxEBUclYg",
|
||||
width: 800,
|
||||
height: 450,
|
||||
),
|
||||
],
|
||||
artists: [
|
||||
ArtistId(
|
||||
id: Some("UCpcTrCXblq78GZrTUTLWeBw"),
|
||||
name: "FIFA",
|
||||
),
|
||||
],
|
||||
artist_id: Some("UCpcTrCXblq78GZrTUTLWeBw"),
|
||||
album: None,
|
||||
view_count: Some(34000000),
|
||||
is_video: true,
|
||||
track_nr: None,
|
||||
),
|
||||
TrackItem(
|
||||
id: "_-spkuonX2k",
|
||||
title: "Blau zu Grau",
|
||||
duration: None,
|
||||
cover: [
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/_-spkuonX2k/sddefault.jpg?sqp=-oaymwEWCJADEOEBIAQqCghqEJQEGHgg6AJIWg&rs=AMzJL3kyiowlRzYlkTqpip9Wvvb0XRbHSg",
|
||||
width: 400,
|
||||
height: 225,
|
||||
),
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/_-spkuonX2k/hq720.jpg?sqp=-oaymwEXCKAGEMIDIAQqCwjVARCqCBh4INgESFo&rs=AMzJL3mKFbAX7nNg-FHcEpWwN5B23HXE-Q",
|
||||
width: 800,
|
||||
height: 450,
|
||||
),
|
||||
],
|
||||
artists: [
|
||||
ArtistId(
|
||||
id: Some("UCeCsfhcY09c-UvX7DkQDcUw"),
|
||||
name: "IMMI",
|
||||
),
|
||||
ArtistId(
|
||||
id: Some("UCqjwECZanh3FGxXSEgFNjkw"),
|
||||
name: "The Cratez",
|
||||
),
|
||||
],
|
||||
artist_id: Some("UCeCsfhcY09c-UvX7DkQDcUw"),
|
||||
album: None,
|
||||
view_count: Some(39000),
|
||||
is_video: true,
|
||||
track_nr: None,
|
||||
),
|
||||
TrackItem(
|
||||
id: "48pBUciAbRY",
|
||||
title: "CAPITAL BRA - BALLERLAIKA (prod. by LUCRY & CESA)",
|
||||
duration: None,
|
||||
cover: [
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/48pBUciAbRY/sddefault.jpg?sqp=-oaymwEWCJADEOEBIAQqCghqEJQEGHgg6AJIWg&rs=AMzJL3nNFQ7wq5X4pqoZMPDDsB0xg7BrGA",
|
||||
width: 400,
|
||||
height: 225,
|
||||
),
|
||||
Thumbnail(
|
||||
url: "https://i.ytimg.com/vi/48pBUciAbRY/hq720.jpg?sqp=-oaymwEXCKAGEMIDIAQqCwjVARCqCBh4INgESFo&rs=AMzJL3kUpn8ZUgkIR6v8n5jcJ6lxx-WJJg",
|
||||
width: 800,
|
||||
height: 450,
|
||||
),
|
||||
],
|
||||
artists: [
|
||||
ArtistId(
|
||||
id: Some("UCa7FGSUsN2wNRUclibmicMg"),
|
||||
name: "Capital Bra",
|
||||
),
|
||||
],
|
||||
artist_id: Some("UCa7FGSUsN2wNRUclibmicMg"),
|
||||
album: None,
|
||||
view_count: Some(400000),
|
||||
is_video: true,
|
||||
track_nr: None,
|
||||
),
|
||||
]
|
||||
93549
testfiles/music_new/albums_default.json
Normal file
93549
testfiles/music_new/albums_default.json
Normal file
File diff suppressed because it is too large
Load diff
4388
testfiles/music_new/videos_default.json
Normal file
4388
testfiles/music_new/videos_default.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -2054,6 +2054,34 @@ async fn music_radio_playlist_not_found() {
|
|||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn music_new_albums() {
|
||||
let rp = RustyPipe::builder().strict().build();
|
||||
let albums = rp.query().music_new_albums().await.unwrap();
|
||||
assert_gte(albums.len(), 10, "albums");
|
||||
|
||||
for album in albums {
|
||||
assert_album_id(&album.id);
|
||||
assert!(!album.name.is_empty());
|
||||
assert!(!album.cover.is_empty(), "got no cover");
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn music_new_videos() {
|
||||
let rp = RustyPipe::builder().strict().build();
|
||||
let videos = rp.query().music_new_videos().await.unwrap();
|
||||
assert_gte(videos.len(), 10, "videos");
|
||||
|
||||
for video in videos {
|
||||
assert_video_id(&video.id);
|
||||
assert!(!video.title.is_empty());
|
||||
assert!(!video.cover.is_empty(), "got no cover");
|
||||
assert_gte(video.view_count.unwrap(), 1000, "views");
|
||||
assert!(video.is_video);
|
||||
}
|
||||
}
|
||||
|
||||
//#AB TESTS
|
||||
|
||||
const VISITOR_DATA_SEARCH_CHANNEL_HANDLES: &str = "CgszYlc1Yk1WZGRCSSjrwOSbBg%3D%3D";
|
||||
|
|
|
|||
Reference in a new issue