feat!: remove TvHtml5Embed client as it got disabled
This commit is contained in:
parent
ed7c5fd3bb
commit
43805aca66
6 changed files with 32 additions and 62 deletions
|
|
@ -272,7 +272,6 @@ enum ClientTypeArg {
|
||||||
Desktop,
|
Desktop,
|
||||||
Mobile,
|
Mobile,
|
||||||
Tv,
|
Tv,
|
||||||
TvEmbed,
|
|
||||||
Android,
|
Android,
|
||||||
Ios,
|
Ios,
|
||||||
}
|
}
|
||||||
|
|
@ -324,7 +323,6 @@ impl From<ClientTypeArg> for ClientType {
|
||||||
match value {
|
match value {
|
||||||
ClientTypeArg::Desktop => Self::Desktop,
|
ClientTypeArg::Desktop => Self::Desktop,
|
||||||
ClientTypeArg::Mobile => Self::Mobile,
|
ClientTypeArg::Mobile => Self::Mobile,
|
||||||
ClientTypeArg::TvEmbed => Self::TvHtml5Embed,
|
|
||||||
ClientTypeArg::Tv => Self::Tv,
|
ClientTypeArg::Tv => Self::Tv,
|
||||||
ClientTypeArg::Android => Self::Android,
|
ClientTypeArg::Android => Self::Android,
|
||||||
ClientTypeArg::Ios => Self::Ios,
|
ClientTypeArg::Ios => Self::Ios,
|
||||||
|
|
|
||||||
|
|
@ -64,11 +64,10 @@ pub async fn download_testfiles() {
|
||||||
music_genre().await;
|
music_genre().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CLIENT_TYPES: [ClientType; 6] = [
|
const CLIENT_TYPES: [ClientType; 5] = [
|
||||||
ClientType::Desktop,
|
ClientType::Desktop,
|
||||||
ClientType::DesktopMusic,
|
ClientType::DesktopMusic,
|
||||||
ClientType::Tv,
|
ClientType::Tv,
|
||||||
ClientType::TvHtml5Embed,
|
|
||||||
ClientType::Android,
|
ClientType::Android,
|
||||||
ClientType::Ios,
|
ClientType::Ios,
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -65,11 +65,6 @@ pub enum ClientType {
|
||||||
/// - includes lower resolution audio streams
|
/// - includes lower resolution audio streams
|
||||||
/// - does not return audio tracks in different languages
|
/// - does not return audio tracks in different languages
|
||||||
Mobile,
|
Mobile,
|
||||||
/// Client used by the embedded player for Smart TVs
|
|
||||||
///
|
|
||||||
/// - can access age-restricted videos
|
|
||||||
/// - cannot access non-embeddable videos
|
|
||||||
TvHtml5Embed,
|
|
||||||
/// Client used by youtube.com/tv
|
/// Client used by youtube.com/tv
|
||||||
///
|
///
|
||||||
/// - Does not return video metadata when fetching the player
|
/// - Does not return video metadata when fetching the player
|
||||||
|
|
@ -92,7 +87,6 @@ impl ClientType {
|
||||||
ClientType::Desktop
|
ClientType::Desktop
|
||||||
| ClientType::DesktopMusic
|
| ClientType::DesktopMusic
|
||||||
| ClientType::Mobile
|
| ClientType::Mobile
|
||||||
| ClientType::TvHtml5Embed
|
|
||||||
| ClientType::Tv => true,
|
| ClientType::Tv => true,
|
||||||
ClientType::Android | ClientType::Ios => false,
|
ClientType::Android | ClientType::Ios => false,
|
||||||
}
|
}
|
||||||
|
|
@ -223,7 +217,6 @@ const DESKTOP_CLIENT_VERSION: &str = "2.20241010.09.00";
|
||||||
const DESKTOP_MUSIC_CLIENT_VERSION: &str = "1.20241007.00.00";
|
const DESKTOP_MUSIC_CLIENT_VERSION: &str = "1.20241007.00.00";
|
||||||
const MOBILE_CLIENT_VERSION: &str = "2.20241011.01.00";
|
const MOBILE_CLIENT_VERSION: &str = "2.20241011.01.00";
|
||||||
const TV_CLIENT_VERSION: &str = "7.20241008.14.02";
|
const TV_CLIENT_VERSION: &str = "7.20241008.14.02";
|
||||||
const TVHTML5_CLIENT_VERSION: &str = "2.0";
|
|
||||||
|
|
||||||
// Mobile app client
|
// Mobile app client
|
||||||
const APP_CLIENT_VERSION: &str = "18.03.33";
|
const APP_CLIENT_VERSION: &str = "18.03.33";
|
||||||
|
|
@ -1109,7 +1102,7 @@ impl RustyPipeQuery {
|
||||||
/// This can be used for additional HTTP requests (e.g. downloading/streaming)
|
/// This can be used for additional HTTP requests (e.g. downloading/streaming)
|
||||||
pub fn user_agent(&self, ctype: ClientType) -> Cow<'_, str> {
|
pub fn user_agent(&self, ctype: ClientType) -> Cow<'_, str> {
|
||||||
match ctype {
|
match ctype {
|
||||||
ClientType::Desktop | ClientType::DesktopMusic | ClientType::TvHtml5Embed => {
|
ClientType::Desktop | ClientType::DesktopMusic => {
|
||||||
Cow::Borrowed(&self.client.inner.user_agent)
|
Cow::Borrowed(&self.client.inner.user_agent)
|
||||||
}
|
}
|
||||||
ClientType::Mobile => MOBILE_UA.into(),
|
ClientType::Mobile => MOBILE_UA.into(),
|
||||||
|
|
@ -1192,23 +1185,6 @@ impl RustyPipeQuery {
|
||||||
user: User::default(),
|
user: User::default(),
|
||||||
third_party: None,
|
third_party: None,
|
||||||
},
|
},
|
||||||
ClientType::TvHtml5Embed => YTContext {
|
|
||||||
client: ClientInfo {
|
|
||||||
client_name: "TVHTML5_SIMPLY_EMBEDDED_PLAYER",
|
|
||||||
client_version: TVHTML5_CLIENT_VERSION.into(),
|
|
||||||
client_screen: Some("EMBED"),
|
|
||||||
platform: "TV",
|
|
||||||
visitor_data,
|
|
||||||
hl,
|
|
||||||
gl,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
request: Some(RequestYT::default()),
|
|
||||||
user: User::default(),
|
|
||||||
third_party: Some(ThirdParty {
|
|
||||||
embed_url: YOUTUBE_HOME_URL,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
ClientType::Tv => YTContext {
|
ClientType::Tv => YTContext {
|
||||||
client: ClientInfo {
|
client: ClientInfo {
|
||||||
client_name: "TVHTML5",
|
client_name: "TVHTML5",
|
||||||
|
|
@ -1319,17 +1295,6 @@ impl RustyPipeQuery {
|
||||||
"X-YouTube-Client-Version",
|
"X-YouTube-Client-Version",
|
||||||
self.client.get_client_version(ctype).await.into_owned(),
|
self.client.get_client_version(ctype).await.into_owned(),
|
||||||
),
|
),
|
||||||
ClientType::TvHtml5Embed => self
|
|
||||||
.client
|
|
||||||
.inner
|
|
||||||
.http
|
|
||||||
.post(format!(
|
|
||||||
"{YOUTUBEI_V1_URL}{endpoint}?{DISABLE_PRETTY_PRINT_PARAMETER}"
|
|
||||||
))
|
|
||||||
.header(header::ORIGIN, YOUTUBE_HOME_URL)
|
|
||||||
.header(header::REFERER, YOUTUBE_HOME_URL)
|
|
||||||
.header("X-YouTube-Client-Name", "1")
|
|
||||||
.header("X-YouTube-Client-Version", TVHTML5_CLIENT_VERSION),
|
|
||||||
ClientType::Tv => self
|
ClientType::Tv => self
|
||||||
.client
|
.client
|
||||||
.inner
|
.inner
|
||||||
|
|
|
||||||
|
|
@ -83,33 +83,30 @@ impl RustyPipeQuery {
|
||||||
clients: &[ClientType],
|
clients: &[ClientType],
|
||||||
) -> Result<VideoPlayer, Error> {
|
) -> Result<VideoPlayer, Error> {
|
||||||
let video_id = video_id.as_ref();
|
let video_id = video_id.as_ref();
|
||||||
let mut last_e = Error::Other("no clients".into());
|
let last_e = Error::Other("no clients".into());
|
||||||
|
|
||||||
for client in clients {
|
for client in clients {
|
||||||
let res = self.player_from_client(video_id, *client).await;
|
let res = self.player_from_client(video_id, *client).await;
|
||||||
match res {
|
match res {
|
||||||
Ok(res) => return Ok(res),
|
Ok(res) => return Ok(res),
|
||||||
Err(Error::Extraction(e)) => {
|
Err(Error::Extraction(e)) => {
|
||||||
if e.switch_client() {
|
// TODO: fetch age-restricted videos with login
|
||||||
if let ExtractionError::Unavailable {
|
/*
|
||||||
reason: UnavailabilityReason::AgeRestricted,
|
if e.use_login() {
|
||||||
msg,
|
tracing::info!("{e}; fetching player with login");
|
||||||
} = &e
|
|
||||||
{
|
match self.player_from_client(video_id, *client).await {
|
||||||
if let Ok(res) = self
|
Ok(res) => return Ok(res),
|
||||||
.player_from_client(video_id, ClientType::TvHtml5Embed)
|
Err(Error::Extraction(e)) => {
|
||||||
.await
|
if !e.switch_client() {
|
||||||
{
|
return Err(Error::Extraction(e));
|
||||||
return Ok(res);
|
}
|
||||||
} else {
|
|
||||||
return Err(Error::Extraction(ExtractionError::Unavailable {
|
|
||||||
reason: UnavailabilityReason::AgeRestricted,
|
|
||||||
msg: msg.to_owned(),
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
Err(e) => return Err(e),
|
||||||
}
|
}
|
||||||
last_e = Error::Extraction(e);
|
last_e = Error::Extraction(e);
|
||||||
} else {
|
} else*/
|
||||||
|
if !e.switch_client() {
|
||||||
return Err(Error::Extraction(e));
|
return Err(Error::Extraction(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -747,7 +744,6 @@ mod tests {
|
||||||
#[case::desktop(ClientType::Desktop)]
|
#[case::desktop(ClientType::Desktop)]
|
||||||
#[case::desktop_music(ClientType::DesktopMusic)]
|
#[case::desktop_music(ClientType::DesktopMusic)]
|
||||||
#[case::tv(ClientType::Tv)]
|
#[case::tv(ClientType::Tv)]
|
||||||
#[case::tv_html5_embed(ClientType::TvHtml5Embed)]
|
|
||||||
#[case::android(ClientType::Android)]
|
#[case::android(ClientType::Android)]
|
||||||
#[case::ios(ClientType::Ios)]
|
#[case::ios(ClientType::Ios)]
|
||||||
fn map_player_data(#[case] client_type: ClientType) {
|
fn map_player_data(#[case] client_type: ClientType) {
|
||||||
|
|
|
||||||
14
src/error.rs
14
src/error.rs
|
|
@ -213,10 +213,20 @@ impl ExtractionError {
|
||||||
matches!(
|
matches!(
|
||||||
self,
|
self,
|
||||||
ExtractionError::Unavailable {
|
ExtractionError::Unavailable {
|
||||||
reason: UnavailabilityReason::AgeRestricted
|
reason: UnavailabilityReason::UnsupportedClient,
|
||||||
| UnavailabilityReason::UnsupportedClient,
|
|
||||||
..
|
..
|
||||||
} | ExtractionError::WrongResult(_)
|
} | ExtractionError::WrongResult(_)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return true if the video should be fetched as a logged in user
|
||||||
|
pub(crate) fn use_login(&self) -> bool {
|
||||||
|
matches!(
|
||||||
|
self,
|
||||||
|
ExtractionError::Unavailable {
|
||||||
|
reason: UnavailabilityReason::AgeRestricted | UnavailabilityReason::IpBan,
|
||||||
|
..
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ use rustypipe::validate;
|
||||||
#[case::desktop(ClientType::Desktop)]
|
#[case::desktop(ClientType::Desktop)]
|
||||||
#[case::tv(ClientType::Tv)]
|
#[case::tv(ClientType::Tv)]
|
||||||
#[case::mobile(ClientType::Mobile)]
|
#[case::mobile(ClientType::Mobile)]
|
||||||
#[case::tv_html5_embed(ClientType::TvHtml5Embed)]
|
|
||||||
#[case::android(ClientType::Android)]
|
#[case::android(ClientType::Android)]
|
||||||
#[case::ios(ClientType::Ios)]
|
#[case::ios(ClientType::Ios)]
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -222,6 +221,8 @@ async fn check_video_stream(s: impl YtStream) {
|
||||||
false,
|
false,
|
||||||
true
|
true
|
||||||
)]
|
)]
|
||||||
|
/*
|
||||||
|
TODO: add login
|
||||||
#[case::agelimit(
|
#[case::agelimit(
|
||||||
"ZDKQmBWTRnw",
|
"ZDKQmBWTRnw",
|
||||||
"The Rinky Pink Pounder. Hitachi Magic Wand clone teardown.",
|
"The Rinky Pink Pounder. Hitachi Magic Wand clone teardown.",
|
||||||
|
|
@ -233,6 +234,7 @@ async fn check_video_stream(s: impl YtStream) {
|
||||||
false,
|
false,
|
||||||
false
|
false
|
||||||
)]
|
)]
|
||||||
|
*/
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
async fn get_player(
|
async fn get_player(
|
||||||
|
|
|
||||||
Reference in a new issue