feat: add player_from_clients function to specify client order

This commit is contained in:
ThetaDev 2024-07-29 18:03:31 +02:00
parent 8152ce6b08
commit 72b5dfec69
No known key found for this signature in database
GPG key ID: E319D3C5148D65B6

View file

@ -64,33 +64,52 @@ struct QContentPlaybackContext<'a> {
impl RustyPipeQuery { impl RustyPipeQuery {
/// Get YouTube player data (video/audio streams + basic metadata) /// Get YouTube player data (video/audio streams + basic metadata)
#[tracing::instrument(skip(self))]
pub async fn player<S: AsRef<str> + Debug>(&self, video_id: S) -> Result<VideoPlayer, Error> { pub async fn player<S: AsRef<str> + Debug>(&self, video_id: S) -> Result<VideoPlayer, Error> {
self.player_from_clients(video_id, &[ClientType::Desktop, ClientType::TvHtml5Embed])
.await
}
/// Get YouTube player data (video/audio streams + basic metadata) using a list of clients.
///
/// The clients are used in the given order. If a client cannot fetch the requested video,
/// an attempt is made with the next one.
pub async fn player_from_clients<S: AsRef<str> + Debug>(
&self,
video_id: S,
clients: &[ClientType],
) -> Result<VideoPlayer, Error> {
let video_id = video_id.as_ref(); let video_id = video_id.as_ref();
let desktop_res = self.player_from_client(video_id, ClientType::Desktop).await; let mut last_e = Error::Other("no clients".into());
// Prefer to output age restriction error (e.g. if video cannot be played
// by Desktop because of age restriction and by TvHtml5Embed because it is non-embeddable)
let mut age_restricted_e = None;
match desktop_res { for client in clients {
Ok(res) => Ok(res), let res = self.player_from_client(video_id, *client).await;
Err(Error::Extraction(e)) => { match res {
if e.switch_client() { Ok(res) => return Ok(res),
let tv_res = self Err(Error::Extraction(e)) => {
.player_from_client(video_id, ClientType::TvHtml5Embed) if e.switch_client() {
.await; if let ExtractionError::Unavailable {
reason: UnavailabilityReason::AgeRestricted,
match tv_res { msg,
// Output desktop client error if the tv client is unsupported } = &e
Err(Error::Extraction(ExtractionError::Unavailable { {
reason: UnavailabilityReason::UnsupportedClient, age_restricted_e =
.. Some(Error::Extraction(ExtractionError::Unavailable {
})) => Err(Error::Extraction(e)), reason: UnavailabilityReason::AgeRestricted,
_ => tv_res, msg: msg.to_owned(),
}));
}
last_e = Error::Extraction(e);
} else {
return Err(Error::Extraction(e));
} }
} else {
Err(Error::Extraction(e))
} }
Err(e) => return Err(e),
} }
Err(e) => Err(e),
} }
Err(age_restricted_e.unwrap_or(last_e))
} }
/// Get YouTube player data (video/audio streams + basic metadata) using the specified client /// Get YouTube player data (video/audio streams + basic metadata) using the specified client